From d735714fb82ebd1f1a5ba7ccdc741177b0bc2bd1 Mon Sep 17 00:00:00 2001 From: Achim Gratz Date: Sun, 18 Mar 2012 21:30:49 +0100 Subject: [PATCH] Maint fixup --- EXPERIMENTAL/org-e-ascii.el | 1927 -------- EXPERIMENTAL/org-e-html.el | 3162 -------------- EXPERIMENTAL/org-e-odt.el | 4589 -------------------- EXPERIMENTAL/org-e-publish.el | 1211 ------ contrib/lisp/org-bibtex-extras.el | 155 - .../BasicODConverter/BasicODConverter-0.8.0.oxt | Bin 0 -> 8009 bytes contrib/odt/BasicODConverter/Filters.bas | 213 + contrib/odt/BasicODConverter/Main.bas | 201 + lisp/ob-io.el | 122 - lisp/ob-scala.el | 120 - testing/README | 45 - testing/README.org | 115 + testing/contrib/lisp/.gitignore | 1 + testing/examples/include.org | 10 - testing/examples/include2.org | 1 - testing/examples/table.org | 19 + testing/lisp/test-org-element.el | 436 -- testing/lisp/test-org-export.el | 625 --- 18 files changed, 549 insertions(+), 12403 deletions(-) delete mode 100644 EXPERIMENTAL/org-e-ascii.el delete mode 100644 EXPERIMENTAL/org-e-html.el delete mode 100644 EXPERIMENTAL/org-e-odt.el delete mode 100644 EXPERIMENTAL/org-e-publish.el delete mode 100644 contrib/lisp/org-bibtex-extras.el create mode 100644 contrib/odt/BasicODConverter/BasicODConverter-0.8.0.oxt create mode 100644 contrib/odt/BasicODConverter/Filters.bas create mode 100644 contrib/odt/BasicODConverter/Main.bas delete mode 100644 lisp/ob-io.el delete mode 100644 lisp/ob-scala.el delete mode 100644 testing/README create mode 100644 testing/README.org create mode 100644 testing/contrib/lisp/.gitignore delete mode 100644 testing/examples/include.org delete mode 100644 testing/examples/include2.org create mode 100644 testing/examples/table.org delete mode 100644 testing/lisp/test-org-element.el delete mode 100644 testing/lisp/test-org-export.el diff --git a/EXPERIMENTAL/org-e-ascii.el b/EXPERIMENTAL/org-e-ascii.el deleted file mode 100644 index a4b5cbf..0000000 --- a/EXPERIMENTAL/org-e-ascii.el +++ /dev/null @@ -1,1927 +0,0 @@ -;;; org-e-ascii.el --- ASCII Back-End For Org Export Engine - -;; Copyright (C) 2012 Free Software Foundation, Inc. - -;; Author: Nicolas Goaziou -;; Keywords: outlines, hypermedia, calendar, wp - -;; This program is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see . - -;;; Commentary: - -;; This library implements an ASCII back-end for Org generic exporter. - -;; To test it, run -;; -;; M-: (org-export-to-buffer 'e-ascii "*Test e-ASCII*") RET -;; -;; in an Org mode buffer then switch to that buffer to see the ASCII -;; export. See contrib/lisp/org-export.el for more details on how -;; this exporter works. - -;;; Code: - -(eval-when-compile (require 'cl)) - -(declare-function org-element-contents "org-element" (element)) -(declare-function org-element-property "org-element" (property element)) -(declare-function org-element-normalize-string "org-element" (s)) -(declare-function org-element-map "org-element" - (data types fun &optional info first-match)) -(declare-function org-element-time-stamp-interpreter - "org-element" (time-stamp contents)) - -(declare-function org-export-clean-table "org-export" (table specialp)) -(declare-function org-export-collect-footnote-definitions - "org-export" (data info)) -(declare-function org-export-collect-headlines "org-export" (info &optional n)) -(declare-function org-export-collect-listings "org-export" (info)) -(declare-function org-export-collect-tables "org-export" (info)) -(declare-function org-export-data "org-export" (data backend info)) -(declare-function org-export-expand-macro "org-export" (macro info)) -(declare-function org-export-format-code-default "org-export" (element info)) -(declare-function org-export-get-coderef-format "org-export" (path desc)) -(declare-function org-export-get-footnote-number "org-export" (footnote info)) -(declare-function org-export-get-headline-number "org-export" (headline info)) -(declare-function org-export-get-ordinal "org-export" - (element info &optional types predicate)) -(declare-function org-export-get-parent-headline "org-export" (blob info)) -(declare-function org-export-get-relative-level "org-export" (headline info)) -(declare-function org-export-included-file "org-export" (keyword backend info)) -(declare-function org-export-low-level-p "org-export" (headline info)) -(declare-function org-export-output-file-name "org-export" - (extension &optional subtreep pub-dir)) -(declare-function org-export-resolve-coderef "org-export" (ref info)) -(declare-function org-export-resolve-fuzzy-link "org-export" (link info)) -(declare-function org-export-resolve-id-link "org-export" (link info)) -(declare-function org-export-resolve-ref-link "org-export" (link info)) -(declare-function org-export-secondary-string - "org-export" (secondary backend info)) -(declare-function org-export-table-format-info "org-export" (table)) -(declare-function - org-export-to-file "org-export" - (backend file &optional subtreep visible-only body-only ext-plist)) - - - -;;; Internal Variables - -;; The following setting won't allow to modify preferred charset -;; through a buffer keyword or an option item, but, since the property -;; will appear in communication channel nonetheless, it allows to -;; override `org-e-ascii-charset' variable on the fly by the ext-plist -;; mechanism. - -;; We also install a filter for headlines and sections, in order to -;; control blank lines separating them in output string. - -(defconst org-e-ascii-option-alist - '((:ascii-charset nil nil org-e-ascii-charset) - ) - "Alist between ASCII export properties and ways to set them. -See `org-export-option-alist' for more information on the -structure or the values.") - -(defconst org-e-ascii-filters-alist - '((:filter-headline . org-e-ascii-filter-headline-blank-lines) - (:filter-section . org-e-ascii-filter-headline-blank-lines)) - "Alist between filters keywords and back-end specific filters. -See `org-export-filters-alist' for more information.") - -(defconst org-e-ascii-dictionary - '(("Footnotes\n" - ("en" - :ascii "Footnotes\n" - :latin1 "Footnotes\n" - :utf-8 "Footnotes\n") - ("fr" - :ascii "Notes de bas de page\n" - :latin1 "Notes de bas de page\n" - :utf-8 "Notes de bas de page\n")) - ("Listing %d: %s" - ("en" - :ascii "Listing %d: %s" - :latin1 "Listing %d: %s" - :utf-8 "Listing %d: %s") - ("fr" - :ascii "Programme %d : %s" - :latin1 "Programme %d : %s" - :utf-8 "Programme nº %d : %s")) - ("List Of Listings\n" - ("en" - :ascii "List Of Listings\n" - :latin1 "List Of Listings\n" - :utf-8 "List Of Listings\n") - ("fr" - :ascii "Liste des programmes\n" - :latin1 "Liste des programmes\n" - :utf-8 "Liste des programmes\n")) - ("List Of Tables\n" - ("en" - :ascii "List Of Tables\n" - :latin1 "List Of Tables\n" - :utf-8 "List Of Tables\n") - ("fr" - :ascii "Liste des tableaux\n" - :latin1 "Liste des tableaux\n" - :utf-8 "Liste des tableaux\n")) - ("Listing %d: " - ("en" - :ascii "Listing %d: " - :latin1 "Listing %d: " - :utf-8 "Listing %d: ") - ("fr" - :ascii "Programme %d : " - :latin1 "Programme %d : " - :utf-8 "Programme nº %d : ")) - ("Table Of Contents\n" - ("en" - :ascii "Table Of Contents\n" - :latin1 "Table Of Contents\n" - :utf-8 "Table Of Contents\n") - ("fr" - :ascii "Sommaire\n" - :latin1 "Table des matières\n" - :utf-8 "Table des matières\n")) - ("Table %d: %s" - ("en" - :ascii "Table %d: %s" - :latin1 "Table %d: %s" - :utf-8 "Table %d: %s") - ("fr" - :ascii "Tableau %d : %s" - :latin1 "Tableau %d : %s" - :utf-8 "Tableau nº %d : %s")) - ("See section %s" - ("en" - :ascii "See section %s" - :latin1 "See section %s" - :utf-8 "See section %s") - ("fr" - :ascii "cf. section %s" - :latin1 "cf. section %s" - :utf-8 "cf. section %s")) - ("Table %d: " - ("en" - :ascii "Table %d: " - :latin1 "Table %d: " - :utf-8 "Table %d: ") - ("fr" - :ascii "Tableau %d : " - :latin1 "Tableau %d : " - :utf-8 "Tableau nº %d : ")) - ("Unknown reference" - ("en" - :ascii "Unknown reference" - :latin1 "Unknown reference" - :utf-8 "Unknown reference") - ("fr" - :ascii "Destination inconnue" - :latin1 "Référence inconnue" - :utf-8 "Référence inconnue"))) - "Dictionary for ASCII back-end. - -Alist whose car is the string to translate and cdr is an alist -whose car is the language string and cdr is a plist whose -properties are possible charsets and value the translated term. - -It is used as a database for `org-e-ascii--translate'.") - - - -;;; User Configurable Variables - -(defgroup org-export-e-ascii nil - "Options for exporting Org mode files to ASCII." - :tag "Org Export ASCII" - :group 'org-export) - -(defcustom org-e-ascii-text-width 72 - "Maximum width of exported text. -This number includes margin size, as set in -`org-e-ascii-global-margin'." - :group 'org-export-e-ascii - :type 'integer) - -(defcustom org-e-ascii-global-margin 0 - "Width of the left margin, in number of characters." - :group 'org-export-e-ascii - :type 'integer) - -(defcustom org-e-ascii-inner-margin 2 - "Width of the inner margin, in number of characters. -Inner margin is applied between each headline." - :group 'org-export-e-ascii - :type 'integer) - -(defcustom org-e-ascii-quote-margin 6 - "Width of margin used for quoting text, in characters. -This margin is applied on both sides of the text." - :group 'org-export-e-ascii - :type 'integer) - -(defcustom org-e-ascii-inlinetask-width 30 - "Width of inline tasks, in number of characters. -This number ignores any margin." - :group 'org-export-e-ascii - :type 'integer) - -(defcustom org-e-ascii-headline-spacing '(1 . 2) - "Number of blank lines inserted around headlines. - -This variable can be set to a cons cell. In that case, its car -represents the number of blank lines present before headline -contents whereas its cdr reflects the number of blank lines after -contents. - -A nil value replicates the number of blank lines found in the -original Org buffer at the same place." - :group 'org-export-e-ascii - :type '(choice - (const :tag "Replicate original spacing" nil) - (cons :tag "Set an uniform spacing" - (integer :tag "Number of blank lines before contents") - (integer :tag "Number of blank lines after contents")))) - -(defcustom org-e-ascii-charset 'ascii - "The charset allowed to represent various elements and objects. -Possible values are: -`ascii' Only use plain ASCII characters -`latin1' Include Latin-1 characters -`utf-8' Use all UTF-8 characters" - :group 'org-export-e-ascii - :type '(choice - (const :tag "ASCII" ascii) - (const :tag "Latin-1" latin1) - (const :tag "UTF-8" utf-8))) - -(defcustom org-e-ascii-underline '((ascii ?= ?~ ?-) - (latin1 ?= ?~ ?-) - (utf-8 ?═ ?─ ?╌ ?┄ ?┈)) - "Characters for underlining headings in ASCII export. - -Alist whose key is a symbol among `ascii', `latin1' and `utf-8' -and whose value is a list of characters. - -For each supported charset, this variable associates a sequence -of underline characters. In a sequence, the characters will be -used in order for headlines level 1, 2, ... If no character is -available for a given level, the headline won't be underlined." - :group 'org-export-e-ascii - :type '(list - (cons :tag "Underline characters sequence" - (const :tag "ASCII charset" ascii) - (repeat character)) - (cons :tag "Underline characters sequence" - (const :tag "Latin-1 charset" latin1) - (repeat character)) - (cons :tag "Underline characters sequence" - (const :tag "UTF-8 charset" utf-8) - (repeat character)))) - -(defcustom org-e-ascii-bullets '((ascii ?* ?+ ?-) - (latin1 ?§ ?¶) - (utf-8 ?◊)) - "Bullet characters for headlines converted to lists in ASCII export. - -Alist whose key is a symbol among `ascii', `latin1' and `utf-8' -and whose value is a list of characters. - -The first character is used for the first level considered as low -level, and so on. If there are more levels than characters given -here, the list will be repeated. - -Note that this variable doesn't affect plain lists -representation." - :group 'org-export-e-ascii - :type '(list - (cons :tag "Bullet characters for low level headlines" - (const :tag "ASCII charset" ascii) - (repeat character)) - (cons :tag "Bullet characters for low level headlines" - (const :tag "Latin-1 charset" latin1) - (repeat character)) - (cons :tag "Bullet characters for low level headlines" - (const :tag "UTF-8 charset" utf-8) - (repeat character)))) - -(defcustom org-e-ascii-links-to-notes t - "Non-nil means convert links to notes before the next headline. -When nil, the link will be exported in place. If the line -becomes long in this way, it will be wrapped." - :group 'org-export-e-ascii - :type 'boolean) - -(defcustom org-e-ascii-table-keep-all-vertical-lines nil - "Non-nil means keep all vertical lines in ASCII tables. -When nil, vertical lines will be removed except for those needed -for column grouping." - :group 'org-export-e-ascii - :type 'boolean) - -(defcustom org-e-ascii-table-widen-columns t - "Non-nil means widen narrowed columns for export. -When nil, narrowed columns will look in ASCII export just like in -Org mode, i.e. with \"=>\" as ellipsis." - :group 'org-export-e-ascii - :type 'boolean) - -(defcustom org-e-ascii-caption-above nil - "When non-nil, place caption string before the element. -Otherwise, place it right after it." - :group 'org-export-e-ascii - :type 'boolean) - -(defcustom org-e-ascii-verbatim-format "`%s'" - "Format string used for verbatim text and inline code." - :group 'org-export-e-ascii - :type 'string) - -(defcustom org-e-ascii-format-drawer-function nil - "Function called to format a drawer in ASCII. - -The function must accept two parameters: - NAME the drawer name, like \"LOGBOOK\" - CONTENTS the contents of the drawer. - WIDTH the text width within the drawer. - -The function should return either the string to be exported or -nil to ignore the drawer. - -For example, the variable could be set to the following function -in order to mimic default behaviour: - -\(defun org-e-ascii-format-drawer-default \(name contents width\) - \"Format a drawer element for ASCII export.\" - contents\)" - :group 'org-export-e-ascii - :type 'function) - -(defcustom org-e-ascii-format-inlinetask-function nil - "Function called to format an inlinetask in ASCII. - -The function must accept six parameters: - TODO the todo keyword, as a string - TODO-TYPE the todo type, a symbol among `todo', `done' and nil. - PRIORITY the inlinetask priority, as a string - NAME the inlinetask name, as a string. - TAGS the inlinetask tags, as a string. - CONTENTS the contents of the inlinetask, as a string. - -The function should return either the string to be exported or -nil to ignore the inline task. - -For example, the variable could be set to the following function -in order to mimic default behaviour: - -\(defun org-e-ascii-format-inlinetask-default - \(todo type priority name tags contents\) - \"Format an inline task element for ASCII export.\" - \(let* \(\(utf8p \(eq \(plist-get info :ascii-charset\) 'utf-8\)\) - \(width org-e-ascii-inlinetask-width\) - \(org-e-ascii--indent-string - \(concat - ;; Top line, with an additional blank line if not in UTF-8. - \(make-string width \(if utf8p ?━ ?_\)\) \"\\n\" - \(unless utf8p \(concat \(make-string width ? \) \"\\n\"\)\) - ;; Add title. Fill it if wider than inlinetask. - \(let \(\(title \(org-e-ascii--build-title inlinetask info width\)\)\) - \(if \(<= \(length title\) width\) title - \(org-e-ascii--fill-string title width info\)\)\) - \"\\n\" - ;; If CONTENTS is not empty, insert it along with - ;; a separator. - \(when \(org-string-nw-p contents\) - \(concat \(make-string width \(if utf8p ?─ ?-\)\) \"\\n\" contents\)\) - ;; Bottom line. - \(make-string width \(if utf8p ?━ ?_\)\)\) - ;; Flush the inlinetask to the right. - \(- \(plist-get info :ascii-width\) - \(plist-get info :ascii-margin\) - \(plist-get info :ascii-inner-margin\) - \(org-e-ascii--current-text-width inlinetask info\)\)" - :group 'org-export-e-ascii - :type 'function) - - - -;;; Internal Functions - -;; Internal functions fall into three categories. - -;; The first one is about text formatting. The core function is -;; `org-e-ascii--current-text-width', which determines the current -;; text width allowed to a given element. In other words, it helps -;; keeping each line width within maximum text width defined in -;; `org-e-ascii-text-width'. Once this information is known, -;; `org-e-ascii--fill-string', `org-e-ascii--justify-string', -;; `org-e-ascii--box-string' and `org-e-ascii--indent-string' can -;; operate on a given output string. - -;; The second category contains functions handling elements listings, -;; triggered by "#+TOC:" keyword. As such, `org-e-ascii--build-toc' -;; returns a complete table of contents, `org-e-ascii--list-listings' -;; returns a list of referenceable src-block elements, and -;; `org-e-ascii--list-tables' does the same for table elements. - -;; The third category includes general helper functions. -;; `org-e-ascii--build-title' creates the title for a given headline -;; or inlinetask element. `org-e-ascii--build-caption' returns the -;; caption string associated to a table or a src-block. -;; `org-e-ascii--describe-links' creates notes about links for -;; insertion at the end of a section. It uses -;; `org-e-ascii--unique-links' to get the list of links to describe. -;; Eventually, `org-e-ascii--translate' reads `org-e-ascii-dictionary' -;; to internationalize output. - - -(defun org-e-ascii--fill-string (s text-width info &optional justify) - "Fill a string with specified text-width and return it. - -S is the string being filled. TEXT-WIDTH is an integer -specifying maximum length of a line. INFO is the plist used as -a communication channel. - -Optional argument JUSTIFY can specify any type of justification -among `left', `center', `right' or `full'. A nil value is -equivalent to `left'. For a justification that doesn't also fill -string, see `org-e-ascii--justify-string'. - -Return nil if S isn't a string." - ;; Don't fill paragraph when break should be preserved. - (cond ((not (stringp s)) nil) - ((plist-get info :preserve-breaks) s) - (t (with-temp-buffer - (let ((fill-column text-width) - (use-hard-newlines t)) - (insert s) - (fill-region (point-min) (point-max) justify)) - (buffer-string))))) - -(defun org-e-ascii--justify-string (s text-width how) - "Justify string S. -TEXT-WIDTH is an integer specifying maximum length of a line. -HOW determines the type of justification: it can be `left', -`right', `full' or `center'." - (with-temp-buffer - (insert s) - (goto-char (point-min)) - (let ((fill-column text-width)) - (while (< (point) (point-max)) - (justify-current-line how) - (forward-line))) - (buffer-string))) - -(defun org-e-ascii--indent-string (s width) - "Indent string S by WIDTH white spaces. -Empty lines are not indented." - (when (stringp s) - (replace-regexp-in-string - "\\(^\\)\\(?:.*\\S-\\)" (make-string width ? ) s nil nil 1))) - -(defun org-e-ascii--box-string (s info) - "Return string S with a partial box to its left. -INFO is a plist used as a communicaton channel." - (let ((utf8p (eq (plist-get info :ascii-charset) 'utf-8))) - (format (if utf8p "╭────\n%s\n╰────" ",----\n%s\n`----") - (replace-regexp-in-string - "^" (if utf8p "│ " "| ") - ;; Remove last newline character. - (replace-regexp-in-string "\n[ \t]*\\'" "" s))))) - -(defun org-e-ascii--current-text-width (element info) - "Return maximum text width for ELEMENT's contents. -INFO is a plist used as a communication channel." - (case (org-element-type element) - ;; Elements with an absolute width: `headline' and `inlinetask'. - (inlinetask org-e-ascii-inlinetask-width) - ('headline - (- org-e-ascii-text-width - (let ((low-level-rank (org-export-low-level-p element info))) - (if low-level-rank (* low-level-rank 2) org-e-ascii-global-margin)))) - ;; Elements with a relative width: store maximum text width in - ;; TOTAL-WIDTH. - (otherwise - (let* ((genealogy (cons element (org-export-get-genealogy element info))) - ;; Total width is determined by the presence, or not, of an - ;; inline task among ELEMENT parents. - (total-width - (if (loop for parent in genealogy - thereis (eq (org-element-type parent) 'inlinetask)) - org-e-ascii-inlinetask-width - ;; No inlinetask: Remove global margin from text width. - (- org-e-ascii-text-width - org-e-ascii-global-margin - (let ((parent (org-export-get-parent-headline element info))) - ;; Inner margin doesn't apply to text before first - ;; headline. - (if (not parent) 0 - (let ((low-level-rank - (org-export-low-level-p parent info))) - ;; Inner margin doesn't apply to contents of - ;; low level headlines, since they've got their - ;; own indentation mechanism. - (if low-level-rank (* low-level-rank 2) - org-e-ascii-inner-margin)))))))) - (- total-width - ;; Each `quote-block', `quote-section' and `verse-block' above - ;; narrows text width by twice the standard margin size. - (+ (* (loop for parent in genealogy - when (memq (org-element-type parent) - '(quote-block quote-section verse-block)) - count parent) - 2 org-e-ascii-quote-margin) - ;; Text width within a plain-list is restricted by - ;; indentation of current item. If that's the case, - ;; compute it with the help of `:structure' property from - ;; parent item, if any. - (let ((parent-item - (if (eq (org-element-type element) 'item) element - (loop for parent in genealogy - when (eq (org-element-type parent) 'item) - return parent)))) - (if (not parent-item) 0 - ;; Compute indentation offset of the current item, - ;; that is the sum of the difference between its - ;; indentation and the indentation of the top item in - ;; the list and current item bullet's length. Also - ;; remove tag length (for description lists) or bullet - ;; length. - (let ((struct (org-element-property :structure parent-item)) - (beg-item (org-element-property :begin parent-item))) - (+ (- (org-list-get-ind beg-item struct) - (org-list-get-ind - (org-list-get-top-point struct) struct)) - (length - (or (org-list-get-tag beg-item struct) - (org-list-get-bullet beg-item struct))))))))))))) - -(defun org-e-ascii--build-title - (element info text-width &optional underline notags) - "Format ELEMENT title and return it. - -ELEMENT is either an `headline' or `inlinetask' element. INFO is -a plist used as a communication channel. TEXT-WIDTH is an -integer representing the maximum length of a line. - -When optional argument UNDERLINE is non-nil, underline title, -without the tags, according to `org-e-ascii-underline' -specifications. - -if optional argument NOTAGS is nil, no tags will be added to the -title." - (let* ((headlinep (eq (org-element-type element) 'headline)) - (numbers - ;; Numbering is specific to headlines. - (and headlinep (org-export-numbered-headline-p element info) - ;; All tests passed: build numbering string. - (concat - (mapconcat - #'number-to-string - (org-export-get-headline-number element info) ".") - " "))) - (text (org-export-secondary-string - (org-element-property :title element) 'e-ascii info)) - (todo - (and (plist-get info :with-todo-keywords) - (let ((todo (org-element-property :todo-keyword element))) - (and todo - (concat (org-export-secondary-string todo 'e-ascii info) - " "))))) - (tags (and (not notags) - (plist-get info :with-tags) - (org-element-property :tags element))) - (priority - (and (plist-get info :with-priority) - (concat (org-element-property :priority element) " "))) - (first-part (concat numbers todo priority text))) - (concat - first-part - ;; Align tags, if any. - (when tags - (format - (format " %%%ds" - (max (- text-width (1+ (length first-part))) (length tags))) - tags)) - ;; Maybe underline text, if ELEMENT type is `headline' and an - ;; underline character has been defined. - (when (and underline headlinep) - (let ((under-char - (nth (1- (org-export-get-relative-level element info)) - (cdr (assq (plist-get info :ascii-charset) - org-e-ascii-underline))))) - (and under-char - (concat "\n" - (make-string (length first-part) under-char)))))))) - -(defun org-e-ascii--build-caption (element info) - "Return caption string for ELEMENT, if applicable. - -INFO is a plist used as a communication channel. - -The caption string contains the sequence number of ELEMENT if it -has a name affiliated keyword, along with the real caption, if -any. Return nil when ELEMENT has no affiliated caption or name -keyword." - (let ((caption (org-element-property :caption element)) - (name (org-element-property :name element))) - (when (or caption name) - ;; Get sequence number of current src-block among every - ;; src-block with either a caption or a name. - (let ((reference - (org-export-get-ordinal - element info nil - (lambda (el) (or (org-element-property :caption el) - (org-element-property :name el))))) - (title-fmt (org-e-ascii--translate - (case (org-element-type element) - (table "Table %d: %s") - (src-block "Listing %d: %s")) info))) - (org-e-ascii--fill-string - (format - title-fmt reference - (if (not caption) name - (org-export-secondary-string (car caption) 'e-ascii info))) - (org-e-ascii--current-text-width element info) info))))) - -(defun org-e-ascii--build-toc (info &optional n keyword) - "Return a table of contents. - -INFO is a plist used as a communication channel. - -Optional argument N, when non-nil, is an integer specifying the -depth of the table. - -Optional argument KEYWORD specifies the TOC keyword, if any, from -which the table of contents generation has been initiated." - (let ((title (org-e-ascii--translate "Table Of Contents\n" info))) - (concat - title - (make-string (1- (length title)) - (if (eq (plist-get info :ascii-charset) 'utf-8) ?─ ?_)) - "\n\n" - (let ((text-width - (if keyword (org-e-ascii--current-text-width keyword info) - (- org-e-ascii-text-width org-e-ascii-global-margin)))) - (mapconcat - (lambda (headline) - (let* ((level (org-export-get-relative-level headline info)) - (indent (* (1- level) 3))) - (concat - (unless (zerop indent) (concat (make-string (1- indent) ?.) " ")) - (org-e-ascii--build-title - headline info (- text-width indent) nil - (eq (plist-get info :with-tags) 'not-in-toc))))) - (org-export-collect-headlines info n) "\n"))))) - -(defun org-e-ascii--list-listings (keyword info) - "Return a list of listings. - -KEYWORD is the keyword that initiated the list of listings -generation. INFO is a plist used as a communication channel." - (let ((title (org-e-ascii--translate "List Of Listings\n" info))) - (concat - title - (make-string (1- (length title)) - (if (eq (plist-get info :ascii-charset) 'utf-8) ?─ ?_)) - "\n\n" - (let ((text-width - (if keyword (org-e-ascii--current-text-width keyword info) - (- org-e-ascii-text-width org-e-ascii-global-margin))) - ;; Use a counter instead of retreiving ordinal of each - ;; src-block. - (count 0)) - (mapconcat - (lambda (src-block) - ;; Store initial text so its length can be computed. This is - ;; used to properly align caption right to it in case of - ;; filling (like contents of a description list item). - (let ((initial-text - (format (org-e-ascii--translate "Listing %d: " info) - (incf count)))) - (concat - initial-text - (org-trim - (org-e-ascii--indent-string - (org-e-ascii--fill-string - (let ((caption (org-element-property :caption src-block))) - (if (not caption) (org-element-property :name src-block) - (org-export-secondary-string - ;; Use short name in priority, if available. - (or (cdr caption) (car caption)) 'e-ascii info))) - (- text-width (length initial-text)) info) - (length initial-text)))))) - (org-export-collect-listings info) "\n"))))) - -(defun org-e-ascii--list-tables (keyword info) - "Return a list of listings. - -KEYWORD is the keyword that initiated the list of listings -generation. INFO is a plist used as a communication channel." - (let ((title (org-e-ascii--translate "List Of Tables\n" info))) - (concat - title - (make-string (1- (length title)) - (if (eq (plist-get info :ascii-charset) 'utf-8) ?─ ?_)) - "\n\n" - (let ((text-width - (if keyword (org-e-ascii--current-text-width keyword info) - (- org-e-ascii-text-width org-e-ascii-global-margin))) - ;; Use a counter instead of retreiving ordinal of each - ;; src-block. - (count 0)) - (mapconcat - (lambda (table) - ;; Store initial text so its length can be computed. This is - ;; used to properly align caption right to it in case of - ;; filling (like contents of a description list item). - (let ((initial-text - (format (org-e-ascii--translate "Table %d: " info) - (incf count)))) - (concat - initial-text - (org-trim - (org-e-ascii--indent-string - (org-e-ascii--fill-string - (let ((caption (org-element-property :caption table))) - (if (not caption) (org-element-property :name table) - ;; Use short name in priority, if available. - (org-export-secondary-string - (or (cdr caption) (car caption)) 'e-ascii info))) - (- text-width (length initial-text)) info) - (length initial-text)))))) - (org-export-collect-tables info) "\n"))))) - -(defun org-e-ascii--unique-links (element info) - "Return a list of unique link references in ELEMENT. - -ELEMENT is either an headline element or a section element. INFO -is a plist used as a communication channel. - -It covers links that may be found current headline's title, in -the following section and in any inlinetask's title there." - (let* (seen - (unique-link-p - (function - ;; Return LINK if it wasn't referenced so far, or nil. - ;; Update SEEN links along the way. - (lambda (link) - (let ((footprint - (cons (org-element-property :raw-link link) - (org-element-contents link)))) - (unless (member footprint seen) - (push footprint seen) link))))) - (harvest-links-in-title - (function - ;; Return a list of all unique links in ELEMENT. ELEMENT - ;; may be an headline or an inlinetask element. - (lambda (element) - (let (acc) - (dolist (obj (org-element-property :title element) acc) - (when (eq (org-element-type obj) 'link) - (let ((link (funcall unique-link-p obj))) - (and link (push link acc))))))))) - ;; Retrieve HEADLINE's section, if it exists. - (section (if (eq (org-element-type element) 'section) element - (let ((sec (car (org-element-contents element)))) - (and (eq (org-element-type sec) 'section) sec)))) - (headline (if (eq (org-element-type element) 'headline) element - (org-export-get-parent-headline element info)))) - (append - ;; Links that may be in HEADLINE's title. - (funcall harvest-links-in-title headline) - ;; Get all links in SECTION. - (org-element-map - section 'link (lambda (link) (funcall unique-link-p link)) info)))) - -(defun org-e-ascii--describe-links (links width info) - "Return a string describing a list of links. - -LINKS is a list of link type objects, as returned by -`org-e-ascii--unique-links'. WIDTH is the text width allowed for -the output string. INFO is a plist used as a communication -channel." - (mapconcat - (lambda (link) - (let ((type (org-element-property :type link)) - (anchor (let ((desc (org-element-contents link))) - (if (not desc) (org-element-property :raw-link link) - (org-export-secondary-string desc 'e-ascii info))))) - (cond - ;; Coderefs, radio links and fuzzy links are ignored. - ((member type '("coderef" "radio" "fuzzy")) nil) - ;; Id and custom-id links: Headlines refer to their numbering. - ((member type '("custom-id" "id")) - (let ((dest (org-export-resolve-id-link link info))) - (concat - (org-e-ascii--fill-string - (format - "[%s] %s" - anchor - (if (not dest) (org-e-ascii--translate "Unknown reference" info) - (format - (org-e-ascii--translate "See section %s" info) - (mapconcat 'number-to-string - (org-export-get-headline-number dest info) ".")))) - width info) "\n\n"))) - ;; Do not add a link that cannot be resolved and doesn't have - ;; any description: destination is already visible in the - ;; paragraph. - ((not (org-element-contents link)) nil) - (t - (concat - (org-e-ascii--fill-string - (format "[%s] %s" anchor (org-element-property :raw-link link)) - width info) - "\n\n"))))) - links "")) - - - -;;; Template - -(defun org-e-ascii-template--document-title (info) - "Return document title, as a string. -INFO is a plist used as a communication channel." - (let ((text-width org-e-ascii-text-width) - (title (org-export-secondary-string - (plist-get info :title) 'e-ascii info)) - (author - (and (plist-get info :with-author) - (let ((auth (plist-get info :author))) - (and auth (org-export-secondary-string auth 'e-ascii info))))) - (email - (and (plist-get info :with-email) - (org-export-secondary-string - (plist-get info :email) 'e-ascii info))) - (date (plist-get info :date))) - ;; There are two types of title blocks depending on the presence - ;; of a title to display. - (if (string= title "") - ;; Title block without a title. DATE is positioned at the top - ;; right of the document, AUTHOR to the top left and EMAIL - ;; just below. - (cond - ((and (org-string-nw-p date) (org-string-nw-p author)) - (concat - author - (make-string (- text-width (length date) (length author)) ? ) - date - (when (org-string-nw-p email) (concat "\n" email)) - "\n\n\n")) - ((and (org-string-nw-p date) (org-string-nw-p email)) - (concat - email - (make-string (- text-width (length date) (length email)) ? ) - date "\n\n\n")) - ((org-string-nw-p date) - (concat - (org-e-ascii--justify-string date text-width 'right) - "\n\n\n")) - ((and (org-string-nw-p author) (org-string-nw-p email)) - (concat author "\n" email "\n\n\n")) - ((org-string-nw-p author) (concat author "\n\n\n")) - ((org-string-nw-p email) (concat email "\n\n\n"))) - ;; Title block with a title. Document's TITLE, along with the - ;; AUTHOR and its EMAIL are both overlined and an underlined, - ;; centered. Date is just below, also centered. - (let* ((utf8p (eq (plist-get info :ascii-charset) 'utf-8)) - ;; Format TITLE. It may be filled if it is too wide, - ;; that is wider than the two thirds of the total width. - (title-len (min (length title) (/ (* 2 text-width) 3))) - (formatted-title (org-e-ascii--fill-string title title-len info)) - (line - (make-string - (min (+ (max title-len (length author) (length email)) 2) - text-width) (if utf8p ?━ ?_)))) - (org-e-ascii--justify-string - (concat line "\n" - (unless utf8p "\n") - (upcase formatted-title) - (cond - ((and (org-string-nw-p author) (org-string-nw-p email)) - (concat (if utf8p "\n\n\n" "\n\n") author "\n" email)) - ((org-string-nw-p author) - (concat (if utf8p "\n\n\n" "\n\n") author)) - ((org-string-nw-p email) - (concat (if utf8p "\n\n\n" "\n\n") email))) - "\n" line - (when (org-string-nw-p date) (concat "\n\n\n" date)) - "\n\n\n") text-width 'center))))) - -(defun org-e-ascii-template (contents info) - "Return complete document string after ASCII conversion. -CONTENTS is the transcoded contents string. INFO is a plist -holding export options." - (org-element-normalize-string - (org-e-ascii--indent-string - (let ((text-width (- org-e-ascii-text-width org-e-ascii-global-margin))) - ;; 1. Build title block. - (concat - (org-e-ascii-template--document-title info) - ;; 2. Table of contents. - (let ((depth (plist-get info :with-toc))) - (when depth - (concat - (org-e-ascii--build-toc info (and (wholenump depth) depth)) - "\n\n\n"))) - ;; 3. Document's body. - contents - ;; 4. Footnote definitions. - (let ((definitions (org-export-collect-footnote-definitions - (plist-get info :parse-tree) info)) - ;; Insert full links right inside the footnote definition - ;; as they have no chance to be inserted later. - (org-e-ascii-links-to-notes nil)) - (when definitions - (concat - "\n\n\n" - (let ((title (org-e-ascii--translate "Footnotes\n" info))) - (concat - title - (make-string - (1- (length title)) - (if (eq (plist-get info :ascii-charset) 'utf-8) ?─ ?_)))) - "\n\n" - (mapconcat - (lambda (ref) - (let ((id (format "[%s] " (car ref)))) - ;; Distinguish between inline definitions and - ;; full-fledged definitions. - (org-trim - (let ((def (nth 2 ref))) - (if (eq (org-element-type def) 'org-data) - ;; Full-fledged definition: footnote ID is - ;; inserted inside the first parsed paragraph - ;; (FIRST), if any, to be sure filling will - ;; take it into consideration. - (let ((first (car (org-element-contents def)))) - (if (not (eq (org-element-type first) 'paragraph)) - (concat id "\n" (org-export-data def 'e-ascii info)) - (push id (nthcdr 2 first)) - (org-export-data def 'e-ascii info))) - ;; Fill paragraph once footnote ID is inserted in - ;; order to have a correct length for first line. - (org-e-ascii--fill-string - (concat id (org-export-secondary-string def 'e-ascii info)) - text-width info)))))) - definitions "\n\n")))) - ;; 5. Creator. Ignore `comment' value as there are no comments in - ;; ASCII. Justify it to the bottom right. - (let ((creator-info (plist-get info :with-creator))) - (unless (or (not creator-info) (eq creator-info 'comment)) - (concat - "\n\n\n" - (org-e-ascii--fill-string - (plist-get info :creator) text-width info 'right)))))) - org-e-ascii-global-margin))) - -(defun org-e-ascii--translate (s info) - "Translate string S. - -INFO is a plist used as a communication channel. - -Translation depends on `:language' property and allowed charset. -If no translation in found for a given language and a given -charset, fall-back to S." - (let* ((charset (intern (format ":%s" (plist-get info :ascii-charset)))) - (lang (plist-get info :language)) - (translations (cdr (assoc s org-e-ascii-dictionary)))) - (or (plist-get (cdr (assoc lang translations)) charset) s))) - - - -;;; Transcode Functions - -;;;; Babel Call - -;; Babel Calls are ignored. - - -;;;; Center Block - -(defun org-e-ascii-center-block (center-block contents info) - "Transcode a CENTER-BLOCK element from Org to ASCII. -CONTENTS holds the contents of the block. INFO is a plist -holding contextual information." - (org-e-ascii--justify-string - contents (org-e-ascii--current-text-width center-block info) 'center)) - - -;;;; Comment - -;; Comments are ignored. - - -;;;; Comment Block - -;; Comment Blocks are ignored. - - -;;;; Drawer - -(defun org-e-ascii-drawer (drawer contents info) - "Transcode a DRAWER element from Org to ASCII. -CONTENTS holds the contents of the block. INFO is a plist -holding contextual information." - (let ((name (org-element-property :drawer-name drawer)) - (width (org-e-ascii--current-text-width drawer info))) - (if (functionp org-e-ascii-format-drawer-function) - (funcall org-e-ascii-format-drawer-function name contents width) - ;; If there's no user defined function: simply - ;; display contents of the drawer. - contents))) - - -;;;; Dynamic Block - -(defun org-e-ascii-dynamic-block (dynamic-block contents info) - "Transcode a DYNAMIC-BLOCK element from Org to ASCII. -CONTENTS holds the contents of the block. INFO is a plist -holding contextual information. See -`org-export-data'." - contents) - - -;;;; Emphasis - -(defun org-e-ascii-emphasis (emphasis contents info) - "Transcode EMPHASIS from Org to ASCII. -CONTENTS is the contents of the emphasized text. INFO is a plist -holding contextual information.." - (let ((marker (org-element-property :marker emphasis))) - ;; Leave emphasis markers as-is. - (concat marker contents marker))) - - -;;;; Entity - -(defun org-e-ascii-entity (entity contents info) - "Transcode an ENTITY object from Org to ASCII. -CONTENTS are the definition itself. INFO is a plist holding -contextual information." - (org-element-property - (intern (concat ":" (symbol-name (plist-get info :ascii-charset)))) - entity)) - - -;;;; Example Block - -(defun org-e-ascii-example-block (example-block contents info) - "Transcode a EXAMPLE-BLOCK element from Org to ASCII. -CONTENTS is nil. INFO is a plist holding contextual information." - (org-e-ascii--box-string - (org-export-format-code-default example-block info) info)) - - -;;;; Export Snippet - -(defun org-e-ascii-export-snippet (export-snippet contents info) - "Transcode a EXPORT-SNIPPET object from Org to ASCII. -CONTENTS is nil. INFO is a plist holding contextual information." - (when (eq (org-export-snippet-backend export-snippet) 'e-ascii) - (org-element-property :value export-snippet))) - - -;;;; Export Block - -(defun org-e-ascii-export-block (export-block contents info) - "Transcode a EXPORT-BLOCK element from Org to ASCII. -CONTENTS is nil. INFO is a plist holding contextual information." - (when (string= (org-element-property :type export-block) "ascii") - (org-remove-indentation (org-element-property :value export-block)))) - - -;;;; Fixed Width - -(defun org-e-ascii-fixed-width (fixed-width contents info) - "Transcode a FIXED-WIDTH element from Org to ASCII. -CONTENTS is nil. INFO is a plist holding contextual information." - (org-e-ascii--box-string - (replace-regexp-in-string - "^[ \t]*: ?" "" (org-element-property :value fixed-width)) info)) - - -;;;; Footnote Definition - -;; Footnote Definitions are ignored. They are compiled at the end of -;; the document, by `org-e-ascii-template'. - - -;;;; Footnote Reference - -(defun org-e-ascii-footnote-reference (footnote-reference contents info) - "Transcode a FOOTNOTE-REFERENCE element from Org to ASCII. -CONTENTS is nil. INFO is a plist holding contextual information." - (format "[%s]" (org-export-get-footnote-number footnote-reference info))) - - -;;;; Headline - -(defun org-e-ascii-headline (headline contents info) - "Transcode an HEADLINE element from Org to ASCII. -CONTENTS holds the contents of the headline. INFO is a plist -holding contextual information." - ;; Don't export footnote section, which will be handled at the end - ;; of the template. - (unless (org-element-property :footnote-section-p headline) - (let* ((low-level-rank (org-export-low-level-p headline info)) - (width (org-e-ascii--current-text-width headline info)) - ;; Blank lines between headline and its contents. - ;; `org-e-ascii-headline-spacing', when set, overwrites - ;; original buffer's spacing. - (pre-blanks - (make-string - (if org-e-ascii-headline-spacing (car org-e-ascii-headline-spacing) - (org-element-property :pre-blank headline)) ?\n)) - ;; Even if HEADLINE has no section, there might be some - ;; links in its title that we shouldn't forget to describe. - (links - (unless (eq (caar (org-element-contents headline)) 'section) - (org-e-ascii--describe-links - (org-e-ascii--unique-links headline info) width info)))) - ;; Deep subtree: export it as a list item. - (if low-level-rank - (concat - ;; Bullet. - (let ((bullets (cdr (assq (plist-get info :ascii-charset) - org-e-ascii-bullets)))) - (char-to-string - (nth (mod (1- low-level-rank) (length bullets)) bullets))) - " " - ;; Title. - (org-e-ascii--build-title headline info width) "\n" - ;; Contents, indented by length of bullet. - pre-blanks - (org-e-ascii--indent-string - (concat contents - (when (org-string-nw-p links) (concat "\n\n" links))) - 2)) - ;; Else: Standard headline. - (concat - (org-e-ascii--build-title headline info width 'underline) - "\n" pre-blanks - (concat (when (org-string-nw-p links) links) contents)))))) - - -;;;; Horizontal Rule - -(defun org-e-ascii-horizontal-rule (horizontal-rule contents info) - "Transcode an HORIZONTAL-RULE object from Org to ASCII. -CONTENTS is nil. INFO is a plist holding contextual -information." - (let ((attr - (read - (format - "(%s)" - (mapconcat - #'identity - (org-element-property :attr_ascii horizontal-rule) - " "))))) - (make-string (or (and (wholenump (plist-get attr :width)) - (plist-get attr :width)) - (org-e-ascii--current-text-width horizontal-rule info)) - (if (eq (plist-get info :ascii-charset) 'utf-8) ?― ?-)))) - - -;;;; Inline Babel Call - -;; Inline Babel Calls are ignored. - - -;;;; Inline Src Block - -(defun org-e-ascii-inline-src-block (inline-src-block contents info) - "Transcode an INLINE-SRC-BLOCK element from Org to ASCII. -CONTENTS holds the contents of the item. INFO is a plist holding -contextual information." - (format org-e-ascii-verbatim-format - (org-element-property :value inline-src-block))) - - -;;;; Inlinetask - -(defun org-e-ascii-inlinetask (inlinetask contents info) - "Transcode an INLINETASK element from Org to ASCII. -CONTENTS holds the contents of the block. INFO is a plist -holding contextual information." - (let ((width (org-e-ascii--current-text-width inlinetask info)) - (title (org-export-secondary-string - (org-element-property :title inlinetask) 'e-ascii info)) - (todo (and (plist-get info :with-todo-keywords) - (let ((todo (org-element-property - :todo-keyword inlinetask))) - (and todo - (org-export-secondary-string todo 'e-ascii info))))) - (todo-type (org-element-property :todo-type inlinetask)) - (tags (and (plist-get info :with-tags) - (org-element-property :tags inlinetask))) - (priority (and (plist-get info :with-priority) - (org-element-property :priority inlinetask)))) - ;; If `org-e-ascii-format-inlinetask-function' is provided, call it - ;; with appropriate arguments. - (if (functionp org-e-ascii-format-inlinetask-function) - (funcall org-e-ascii-format-inlinetask-function - todo todo-type priority title tags contents width) - ;; Otherwise, use a default template. - (let* ((utf8p (eq (plist-get info :ascii-charset) 'utf-8))) - (org-e-ascii--indent-string - (concat - ;; Top line, with an additional blank line if not in UTF-8. - (make-string width (if utf8p ?━ ?_)) "\n" - (unless utf8p (concat (make-string width ? ) "\n")) - ;; Add title. Fill it if wider than inlinetask. - (let ((title (org-e-ascii--build-title inlinetask info width))) - (if (<= (length title) width) title - (org-e-ascii--fill-string title width info))) - "\n" - ;; If CONTENTS is not empty, insert it along with - ;; a separator. - (when (org-string-nw-p contents) - (concat (make-string width (if utf8p ?─ ?-)) "\n" contents)) - ;; Bottom line. - (make-string width (if utf8p ?━ ?_))) - ;; Flush the inlinetask to the right. - (- org-e-ascii-text-width org-e-ascii-global-margin - (if (not (org-export-get-parent-headline inlinetask info)) 0 - org-e-ascii-inner-margin) - (org-e-ascii--current-text-width inlinetask info))))))) - - -;;;; Item - -(defun org-e-ascii-item (item contents info) - "Transcode an ITEM element from Org to ASCII. -CONTENTS holds the contents of the item. INFO is a plist holding -contextual information." - (let ((bullet - ;; First parent of ITEM is always the plain-list. Get - ;; `:type' property from it. - (org-list-bullet-string - (case (org-element-property :type (org-export-get-parent item info)) - (descriptive - (concat - (org-export-secondary-string - (org-element-property :tag item) 'e-ascii info) ": ")) - (ordered - ;; Return correct number for ITEM, paying attention to - ;; counters. - (let* ((struct (org-element-property :structure item)) - (bul (org-element-property :bullet item)) - (num - (number-to-string - (car (last (org-list-get-item-number - (org-element-property :begin item) - struct - (org-list-prevs-alist struct) - (org-list-parents-alist struct))))))) - (replace-regexp-in-string "[0-9]+" num bul))) - (t (let ((bul (org-element-property :bullet item))) - ;; Change bullets into more visible form if UTF-8 is active. - (if (not (eq (plist-get info :ascii-charset) 'utf-8)) bul - (replace-regexp-in-string - "-" "•" - (replace-regexp-in-string - "+" "⁃" - (replace-regexp-in-string "*" "‣" bul)))))))))) - (concat - bullet - ;; Contents: Pay attention to indentation. Note: check-boxes are - ;; already taken care of at the paragraph level so they don't - ;; interfere with indentation. - (let ((contents (org-e-ascii--indent-string contents (length bullet)))) - (if (eq (caar (org-element-contents item)) 'paragraph) - (org-trim contents) - (concat "\n" contents)))))) - - -;;;; Keyword - -(defun org-e-ascii-keyword (keyword contents info) - "Transcode a KEYWORD element from Org to ASCII. -CONTENTS is nil. INFO is a plist holding contextual -information." - (let ((key (downcase (org-element-property :key keyword))) - (value (org-element-property :value keyword))) - (cond - ((string= key "ascii") value) - ((string= key "toc") - (let ((value (downcase value))) - (cond - ((string-match "\\" value) - (let ((depth (or (and (string-match "[0-9]+" value) - (string-to-number (match-string 0 value))) - (plist-get info :with-toc)))) - (org-e-ascii--build-toc - info (and (wholenump depth) depth) keyword))) - ((string= "tables" value) - (org-e-ascii--list-tables keyword info)) - ((string= "listings" value) - (org-e-ascii--list-listings keyword info)))))))) - - -;;;; Latex Environment - -(defun org-e-ascii-latex-environment (latex-environment contents info) - "Transcode a LATEX-ENVIRONMENT element from Org to ASCII. -CONTENTS is nil. INFO is a plist holding contextual -information." - (org-remove-indentation (org-element-property :value latex-environment))) - - -;;;; Latex Fragment - -(defun org-e-ascii-latex-fragment (latex-fragment contents info) - "Transcode a LATEX-FRAGMENT object from Org to ASCII. -CONTENTS is nil. INFO is a plist holding contextual -information." - (org-element-property :value latex-fragment)) - - -;;;; Line Break - -(defun org-e-ascii-line-break (line-break contents info) - "Transcode a LINE-BREAK object from Org to ASCII. -CONTENTS is nil. INFO is a plist holding contextual - information." hard-newline) - - -;;;; Link - -(defun org-e-ascii-link (link desc info) - "Transcode a LINK object from Org to ASCII. - -DESC is the description part of the link, or the empty string. -INFO is a plist holding contextual information." - (let ((raw-link (org-element-property :raw-link link)) - (type (org-element-property :type link))) - (cond - ((string= type "coderef") - (let ((ref (org-element-property :path link))) - (format (org-export-get-coderef-format ref desc) - (org-export-resolve-coderef ref info)))) - ;; Do not apply a special syntax on radio links. Though, parse - ;; and transcode path to have a proper display of contents. - ((string= type "radio") - (org-export-secondary-string - (org-element-parse-secondary-string - (org-element-property :path link) - (cdr (assq 'radio-target org-element-object-restrictions))) - 'e-ascii info)) - ;; Do not apply a special syntax on fuzzy links pointing to - ;; targets. - ((string= type "fuzzy") - (let ((destination (org-export-resolve-fuzzy-link link info))) - ;; Ignore invisible "#+target: path". - (unless (eq (org-element-type destination) 'keyword) - (if (org-string-nw-p desc) desc - (when destination - (let ((number (org-export-get-ordinal destination info))) - (when number - (if (atom number) (number-to-string number) - (mapconcat 'number-to-string number "."))))))))) - (t - (if (not (org-string-nw-p desc)) (format "[%s]" raw-link) - (concat - (format "[%s]" desc) - (unless org-e-ascii-links-to-notes (format " (%s)" raw-link)))))))) - - -;;;; Macro - -(defun org-e-ascii-macro (macro contents info) - "Transcode a MACRO element from Org to ASCII. -CONTENTS is nil. INFO is a plist holding contextual -information." - (org-export-expand-macro macro info)) - - -;;;; Paragraph - -(defun org-e-ascii-paragraph (paragraph contents info) - "Transcode a PARAGRAPH element from Org to ASCII. -CONTENTS is the contents of the paragraph, as a string. INFO is -the plist used as a communication channel." - (org-e-ascii--fill-string - (let ((parent (org-export-get-parent paragraph info))) - ;; If PARAGRAPH is the first one in a list element, be sure to - ;; add the check-box in front of it, before any filling. Later, - ;; it would interfere with line width. - (if (and (eq (org-element-type parent) 'item) - (equal (car (org-element-contents parent)) paragraph)) - (let ((utf8p (eq (plist-get info :ascii-charset) 'utf-8))) - (concat (case (org-element-property :checkbox parent) - (on (if utf8p "☑ " "[X] ")) - (off (if utf8p "☐ " "[ ] ")) - (trans (if utf8p "☒ " "[-] "))) - contents)) - contents)) - (org-e-ascii--current-text-width paragraph info) info)) - - -;;;; Plain List - -(defun org-e-ascii-plain-list (plain-list contents info) - "Transcode a PLAIN-LIST element from Org to ASCII. -CONTENTS is the contents of the list. INFO is a plist holding -contextual information." - contents) - - -;;;; Plain Text - -(defun org-e-ascii-plain-text (text info) - "Transcode a TEXT string from Org to ASCII. -INFO is a plist used as a communication channel." - (if (not (and (eq (plist-get info :ascii-charset) 'utf-8) - (plist-get info :with-special-strings))) - text - ;; Usual replacements in utf-8 with proper option set. - (replace-regexp-in-string - "\\.\\.\\." "…" - (replace-regexp-in-string - "--" "–" - (replace-regexp-in-string "---" "—" text))))) - - -;;;; Property Drawer - -(defun org-e-ascii-property-drawer (property-drawer contents info) - "Transcode a PROPERTY-DRAWER element from Org to ASCII. -CONTENTS is nil. INFO is a plist used as a communication -channel." - ;; The property drawer isn't exported but we want separating blank - ;; lines nonetheless. - "") - - -;;;; Quote Block - -(defun org-e-ascii-quote-block (quote-block contents info) - "Transcode a QUOTE-BLOCK element from Org to ASCII. -CONTENTS holds the contents of the block. INFO is a plist -holding contextual information." - (let ((width (org-e-ascii--current-text-width quote-block info))) - (org-e-ascii--indent-string - (org-remove-indentation - (org-e-ascii--fill-string contents width info)) - org-e-ascii-quote-margin))) - - -;;;; Quote Section - -(defun org-e-ascii-quote-section (quote-section contents info) - "Transcode a QUOTE-SECTION element from Org to ASCII. -CONTENTS is nil. INFO is a plist holding contextual information." - (let ((width (org-e-ascii--current-text-width quote-section info)) - (value - (org-export-secondary-string - (org-remove-indentation - (org-element-property :value quote-section)) 'e-ascii info))) - (org-e-ascii--indent-string - value - (+ org-e-ascii-quote-margin - ;; Don't apply inner margin if parent headline is low level. - (let ((headline (org-export-get-parent-headline quote-section info))) - (if (org-export-low-level-p headline info) 0 - org-e-ascii-inner-margin)))))) - - -;;;; Radio Target - -(defun org-e-ascii-radio-target (radio-target contents info) - "Transcode a RADIO-TARGET object from Org to ASCII. -CONTENTS is the contents of the target. INFO is a plist holding -contextual information." - contents) - -;;;; Section - -(defun org-e-ascii-section (section contents info) - "Transcode a SECTION element from Org to ASCII. -CONTENTS is the contents of the section. INFO is a plist holding -contextual information." - (org-e-ascii--indent-string - (concat - contents - (when org-e-ascii-links-to-notes - ;; Add list of links at the end of SECTION. - (let ((links (org-e-ascii--describe-links - (org-e-ascii--unique-links section info) - (org-e-ascii--current-text-width section info) info))) - ;; Separate list of links and section contents. - (when (org-string-nw-p links) (concat "\n\n" links))))) - ;; Do not apply inner margin if parent headline is low level. - (let ((headline (org-export-get-parent-headline section info))) - (if (or (not headline) (org-export-low-level-p headline info)) 0 - org-e-ascii-inner-margin)))) - - -;;;; Special Block - -(defun org-e-ascii-special-block (special-block contents info) - "Transcode a SPECIAL-BLOCK element from Org to ASCII. -CONTENTS holds the contents of the block. INFO is a plist -holding contextual information." - contents) - - -;;;; Src Block - -(defun org-e-ascii-src-block (src-block contents info) - "Transcode a SRC-BLOCK element from Org to ASCII. -CONTENTS holds the contents of the item. INFO is a plist holding -contextual information." - (let ((caption (org-e-ascii--build-caption src-block info))) - (concat - (when (and caption org-e-ascii-caption-above) (concat caption "\n")) - (org-e-ascii--box-string - (org-export-format-code-default src-block info) info) - (when (and caption (not org-e-ascii-caption-above)) - (concat "\n" caption))))) - -;;;; Statistics Cookie - -(defun org-e-ascii-statistics-cookie (statistics-cookie contents info) - "Transcode a STATISTICS-COOKIE object from Org to ASCII. -CONTENTS is nil. INFO is a plist holding contextual information." - (org-element-property :value statistics-cookie)) - - -;;;; Subscript - -(defun org-e-ascii-subscript (subscript contents info) - "Transcode a SUBSCRIPT object from Org to ASCII. -CONTENTS is the contents of the object. INFO is a plist holding -contextual information." - (if (org-element-property :use-brackets-p subscript) - (format "_{%s}" contents) - (format "_%s" contents))) - - -;;;; Superscript - -(defun org-e-ascii-superscript (superscript contents info) - "Transcode a SUPERSCRIPT object from Org to ASCII. -CONTENTS is the contents of the object. INFO is a plist holding -contextual information." - (if (org-element-property :use-brackets-p superscript) - (format "_{%s}" contents) - (format "_%s" contents))) - - -;;;; Table - -;; While `org-e-ascii-table' is the callback function expected by -;; org-export mechanism, it requires four subroutines to display -;; tables accordingly to chosen charset, alignment and width -;; specifications. - -;; Thus, `org-e-ascii-table--column-width' computes the display width -;; for each column in the table, -;; `org-e-ascii-table--vertical-separators' returns a vector -;; containing separators (or lack thereof), -;; `org-e-ascii-table--build-hline' creates various hline strings, -;; depending on charset, separators and position within the tabl and -;; `org-e-ascii-table--format-cell' properly aligns contents within -;; a given cell and width. - -(defun org-e-ascii-table (table contents info) - "Transcode a TABLE element from Org to ASCII. -CONTENTS is nil. INFO is a plist holding contextual information." - (let ((raw-table (org-element-property :raw-table table)) - (caption (org-e-ascii--build-caption table info))) - (concat - ;; Possibly add a caption string above. - (when (and caption org-e-ascii-caption-above) (concat caption "\n")) - ;; Insert table. Note: "table.el" tables are left unmodified. - (if (eq (org-element-property :type table) 'table.el) raw-table - (let* ((utf8p (eq (plist-get info :ascii-charset) 'utf-8)) - ;; Extract information out of the raw table (TABLE-INFO) - ;; and clean it (CLEAN-TABLE). - (table-info (org-export-table-format-info raw-table)) - (special-col-p (plist-get table-info :special-column-p)) - (alignment (plist-get table-info :alignment)) - (clean-table (org-export-clean-table raw-table special-col-p)) - ;; Change table into lisp, much like - ;; `org-table-to-lisp', though cells are parsed and - ;; transcoded along the way. - (lisp-table - (mapcar - (lambda (line) - (if (string-match org-table-hline-regexp line) 'hline - (mapcar - (lambda (cell) - (org-trim - (org-export-secondary-string - (org-element-parse-secondary-string - cell - (cdr (assq 'item org-element-string-restrictions))) - 'e-ascii info))) - (org-split-string (org-trim line) "\\s-?|\\s-?")))) - (org-split-string clean-table "[ \t]*\n[ \t]*"))) - ;; Compute real column widths. - (column-widths - (org-e-ascii-table--column-width lisp-table table-info)) - ;; Construct separators according to column groups. - (separators (org-e-ascii-table--vertical-separators table-info)) - ;; Build different `hline' strings, depending on - ;; separators, column widths and position. - (hline-standard - (org-e-ascii-table--build-hline - nil separators column-widths info)) - (hline-top - (and utf8p (org-e-ascii-table--build-hline - 'top separators column-widths info))) - (hline-bottom - (and utf8p (org-e-ascii-table--build-hline - 'bottom separators column-widths info)))) - ;; Now build table back, with correct alignment, considering - ;; columns widths and separators. - (mapconcat - (lambda (line) - (cond - ((eq line 'hline) hline-standard) - ((eq line 'hline-bottom) hline-bottom) - ((eq line 'hline-top) hline-top) - (t (loop for cell in line - for col from 0 to (length line) - concat - (concat - (let ((sep (aref separators col))) - (if (and utf8p (not (string= sep ""))) "│" sep)) - (org-e-ascii-table--format-cell - cell col column-widths alignment info)) into l - finally return - (concat l - (let ((sep (aref separators col))) - (if (and utf8p (not (string= sep ""))) "│" - sep))))))) - ;; If charset is `utf-8', make sure lisp-table always starts - ;; with `hline-top' and ends with `hline-bottom'. - (if (not utf8p) lisp-table - (setq lisp-table - (cons 'hline-top - (if (eq (car lisp-table) 'hline) (cdr lisp-table) - lisp-table))) - (setq lisp-table - (nconc - (if (eq (car (last lisp-table)) 'hline) (butlast lisp-table) - lisp-table) - '(hline-bottom)))) "\n"))) - ;; Possible add a caption string below. - (when (and caption (not org-e-ascii-caption-above)) - (concat "\n" caption))))) - -(defun org-e-ascii-table--column-width (table table-info) - "Return vector of TABLE columns width. - -TABLE is the Lisp representation of the Org table considered. -TABLE-INFO holds information about the table. See -`org-export-table-format-info'. - -Unlike to `:width' property from `org-export-table-format-info', -the return value is a vector containing width of every column, -not only those with an explicit width cookie. Special column, if -any, is ignored." - ;; All rows have the same length, but be sure to ignore hlines. - (let ((width (make-vector - (loop for row in table - unless (eq row 'hline) - return (length row)) - 0))) - ;; Set column width to the maximum width of the cells in that - ;; column. - (mapc - (lambda (line) - (let ((idx 0)) - (unless (eq line 'hline) - (mapc (lambda (cell) - (let ((len (length cell))) - (when (> len (aref width idx)) (aset width idx len))) - (incf idx)) - line)))) - table) - (unless org-e-ascii-table-widen-columns - ;; When colums are not widened, width cookies have precedence - ;; over string lengths. Thus, overwrite the latter with the - ;; former. - (let ((cookies (plist-get table-info :width)) - (specialp (plist-get table-info :special-column-p))) - ;; Remove special column from COOKIES vector, if any. - (loop for w across (if specialp (substring cookies 1) cookies) - for idx from 0 to width - when w do (aset width idx w)))) - ;; Return value. - width)) - -(defun org-e-ascii-table--vertical-separators (table-info) - "Return a vector of strings for vertical separators. - -TABLE-INFO holds information about considered table. See -`org-export-table-format-info'. - -Return value is a vector whose length is one more than the number -of columns in the table. Special column, if any, is ignored." - (let* ((colgroups (plist-get table-info :column-groups)) - (separators (make-vector (1+ (length colgroups)) ""))) - (if org-e-ascii-table-keep-all-vertical-lines - (make-vector (length separators) "|") - (let ((column 0)) - (mapc (lambda (group) - (when (memq group '(start start-end)) - (aset separators column "|")) - (when (memq group '(end start-end)) - (aset separators (1+ column) "|")) - (incf column)) - colgroups) - ;; Remove unneeded special column. - (if (not (plist-get table-info :special-column-p)) separators - (substring separators 1)))))) - -(defun org-e-ascii-table--format-cell (cell col width alignment info) - "Format CELL with column width and alignment constraints. - -CELL is the contents of the cell, as a string. - -COL is the column containing the cell considered. - -WIDTH is a vector holding every column width, as returned by -`org-e-ascii-table--column-width'. - -ALIGNMENT is a vector containing alignment strings for every -column. - -INFO is a plist used as a communication channel." - (let ((col-width (if org-e-ascii-table-widen-columns (aref width col) - (or (aref width col) (length cell))))) - ;; When CELL is too large, it has to be truncated. - (unless (or org-e-ascii-table-widen-columns (<= (length cell) col-width)) - (setq cell (concat (substring cell 0 (- col-width 2)) "=>"))) - (let* ((indent-tabs-mode nil) - (align (aref alignment col)) - (aligned-cell - (org-e-ascii--justify-string - (org-trim cell) col-width - (cond ((string= align "c") 'center) - ((string= align "r") 'right))))) - ;; Return aligned cell, with missing white spaces added and - ;; space separators between columns. - (format - " %s " - (concat aligned-cell - (make-string (- col-width (length aligned-cell)) ? )))))) - -(defun org-e-ascii-table--build-hline (position separators column-widths info) - "Return string used as an horizontal line in tables. - -POSITION is a symbol among `top', `bottom' and nil, which -specifies position of the horizontal line within the table. - -SEPARATORS is a vector strings specifying separators used in the -table, as returned by `org-e-ascii-table--vertical-separators'. - -COLUMN-WIDTHS is a vector of numbers specifying widths of all -columns in the table, as returned by -`org-e-ascii-table--column-width'. - -INFO is a plist used as a communication channel." - (let ((utf8p (eq (plist-get info :ascii-charset) 'utf-8))) - (loop for idx from 0 to (length separators) - for width across column-widths - concat - (concat - (cond ((string= (aref separators idx) "") nil) - ((and utf8p (zerop idx)) - (cond ((eq position 'top) "┍") - ((eq position 'bottom) "┕") - (t "├"))) - (utf8p - (cond ((eq position 'top) "┯") - ((eq position 'bottom) "┷") - (t "┼"))) - (t "+")) - ;; Hline has to cover all the cell and both white spaces - ;; between columns. - (make-string (+ width 2) - (cond ((not utf8p) ?-) - ((not position) ?─) - (t ?━)))) - into hline - finally return - ;; There is one separator more than columns, so handle it - ;; here. - (concat - hline - (cond - ((string= (aref separators idx) "") nil) - (utf8p (cond ((eq position 'top) "┑") - ((eq position 'bottom) "┙") - (t "┤"))) - (t "+")))))) - - -;;;; Target - -;; Targets are invisible. - - -;;;; Time-stamp - -(defun org-e-ascii-time-stamp (time-stamp contents info) - "Transcode a TIME-STAMP object from Org to ASCII. -CONTENTS is nil. INFO is a plist holding contextual information." - ;; Return time-stamps as-is. - (org-element-time-stamp-interpreter time-stamp contents)) - - -;;;; Verbatim - -(defun org-e-ascii-verbatim (verbatim contents info) - "Return a VERBATIM object from Org to ASCII. -CONTENTS is nil. INFO is a plist holding contextual information." - (format org-e-ascii-verbatim-format - (org-element-property :value verbatim))) - - -;;;; Verse Block - -(defun org-e-ascii-verse-block (verse-block contents info) - "Transcode a VERSE-BLOCK element from Org to ASCII. -CONTENTS is nil. INFO is a plist holding contextual information." - (let ((verse-width (org-e-ascii--current-text-width verse-block info))) - (org-e-ascii--indent-string - (org-e-ascii--justify-string - (org-export-secondary-string - (org-element-property :value verse-block) 'e-ascii info) - verse-width 'left) - org-e-ascii-quote-margin))) - - -;;; Filter - -(defun org-e-ascii-filter-headline-blank-lines (headline back-end info) - "Filter controlling number of blank lines after an headline. - -HEADLINE is a string representing a transcoded headline. -BACK-END is symbol specifying back-end used for export. INFO is -plist containing the communication channel. - -This function only applies to `e-ascii' back-end. See -`org-e-ascii-headline-spacing' for information. - -For any other back-end, HEADLINE is returned as-is." - (if (not (and (eq back-end 'e-ascii) org-e-ascii-headline-spacing)) headline - (let ((blanks (make-string (1+ (cdr org-e-ascii-headline-spacing)) ?\n))) - (replace-regexp-in-string "\n\\(?:\n[ \t]*\\)*\\'" blanks headline)))) - - - -;;; Interactive function - -(defun org-e-ascii-export-to-ascii - (&optional subtreep visible-only body-only ext-plist pub-dir) - "Export current buffer to a text file. - -If narrowing is active in the current buffer, only export its -narrowed part. - -If a region is active, export that region. - -When optional argument SUBTREEP is non-nil, export the sub-tree -at point, extracting information from the headline properties -first. - -When optional argument VISIBLE-ONLY is non-nil, don't export -contents of hidden elements. - -When optional argument BODY-ONLY is non-nil, strip title, table -of contents and footnote definitions from output. - -EXT-PLIST, when provided, is a property list with external -parameters overriding Org default settings, but still inferior to -file-local settings. - -When optional argument PUB-DIR is set, use it as the publishing -directory. - -Return output file's name." - (interactive) - (let ((outfile (org-export-output-file-name ".txt" subtreep pub-dir))) - (org-export-to-file - 'e-ascii outfile subtreep visible-only body-only ext-plist))) - - -(provide 'org-e-ascii) -;;; org-e-ascii.el ends here diff --git a/EXPERIMENTAL/org-e-html.el b/EXPERIMENTAL/org-e-html.el deleted file mode 100644 index 1e1e94a..0000000 --- a/EXPERIMENTAL/org-e-html.el +++ /dev/null @@ -1,3162 +0,0 @@ -;;; org-e-html.el --- HTML Back-End For Org Export Engine - -;; Copyright (C) 2011-2012 Free Software Foundation, Inc. - -;; Author: Jambunathan K -;; Keywords: outlines, hypermedia, calendar, wp - -;; This program is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see . - -;;; Commentary: - -;; This library implements a HTML back-end for Org generic exporter. - -;; To test it, run -;; -;; M-: (org-export-to-buffer 'e-html "*Test e-HTML*") RET -;; -;; in an org-mode buffer then switch to the buffer to see the HTML -;; export. See contrib/lisp/org-export.el for more details on how -;; this exporter works. - -;;; Code: - -;;; org-e-html.el -;;; Dependencies - -(require 'format-spec) -(eval-when-compile (require 'cl) (require 'table)) - - - -;;; Function Declarations - -(declare-function org-element-get-property "org-element" (property element)) -(declare-function org-element-normalize-string "org-element" (s)) -(declare-function org-element-parse-secondary-string - "org-element" (string restriction &optional buffer)) -(defvar org-element-string-restrictions) -(defvar org-element-object-restrictions) - -(declare-function org-export-clean-table "org-export" (table specialp)) -(declare-function org-export-data "org-export" (data backend info)) -(declare-function org-export-directory "org-export" (type plist)) -(declare-function org-export-expand-macro "org-export" (macro info)) -(declare-function org-export-first-sibling-p "org-export" (headline info)) -(declare-function org-export-footnote-first-reference-p "org-export" - (footnote-reference info)) -(declare-function org-export-get-coderef-format "org-export" (path desc)) -(declare-function org-export-get-footnote-definition "org-export" - (footnote-reference info)) -(declare-function org-export-get-footnote-number "org-export" (footnote info)) -(declare-function org-export-get-previous-element "org-export" (blob info)) -(declare-function org-export-get-relative-level "org-export" (headline info)) -(declare-function org-export-handle-code - "org-export" (element info &optional num-fmt ref-fmt delayed)) -(declare-function org-export-included-file "org-export" (keyword backend info)) -(declare-function org-export-inline-image-p "org-export" - (link &optional extensions)) -(declare-function org-export-last-sibling-p "org-export" (headline info)) -(declare-function org-export-low-level-p "org-export" (headline info)) -(declare-function org-export-output-file-name - "org-export" (extension &optional subtreep pub-dir)) -(declare-function org-export-resolve-coderef "org-export" (ref info)) -(declare-function org-export-resolve-fuzzy-link "org-export" (link info)) -(declare-function org-export-secondary-string "org-export" - (secondary backend info)) -(declare-function org-export-solidify-link-text "org-export" (s)) -(declare-function org-export-table-format-info "org-export" (table)) -(declare-function - org-export-to-buffer "org-export" - (backend buffer &optional subtreep visible-only body-only ext-plist)) -(declare-function - org-export-to-file "org-export" - (backend file &optional subtreep visible-only body-only ext-plist)) - -(declare-function org-id-find-id-file "org-id" (id)) -(declare-function htmlize-region "ext:htmlize" (beg end)) -(declare-function org-pop-to-buffer-same-window - "org-compat" (&optional buffer-or-name norecord label)) - - - - -;;; Internal Variables - -(defconst org-e-html-option-alist - '((:agenda-style nil nil org-agenda-export-html-style) - (:convert-org-links nil nil org-e-html-link-org-files-as-html) - ;; FIXME Use (org-xml-encode-org-text-skip-links s) ?? - ;; (:expand-quoted-html nil "@" org-e-html-expand) - (:inline-images nil nil org-e-html-inline-images) - ;; (:link-home nil nil org-e-html-link-home) FIXME - ;; (:link-up nil nil org-e-html-link-up) FIXME - (:style nil nil org-e-html-style) - (:style-extra nil nil org-e-html-style-extra) - (:style-include-default nil nil org-e-html-style-include-default) - (:style-include-scripts nil nil org-e-html-style-include-scripts) - ;; (:timestamp nil nil org-e-html-with-timestamp) - (:html-extension nil nil org-e-html-extension) - (:html-postamble nil nil org-e-html-postamble) - (:html-preamble nil nil org-e-html-preamble) - (:html-table-tag nil nil org-e-html-table-tag) - (:xml-declaration nil nil org-e-html-xml-declaration) - (:LaTeX-fragments nil "LaTeX" org-export-with-LaTeX-fragments) - (:mathjax "MATHJAX" nil "" space)) - "Alist between export properties and ways to set them. - -The car of the alist is the property name, and the cdr is a list -like \(KEYWORD OPTION DEFAULT BEHAVIOUR\) where: - -KEYWORD is a string representing a buffer keyword, or nil. -OPTION is a string that could be found in an #+OPTIONS: line. -DEFAULT is the default value for the property. -BEHAVIOUR determine how Org should handle multiple keywords for -the same property. It is a symbol among: - nil Keep old value and discard the new one. - t Replace old value with the new one. - `space' Concatenate the values, separating them with a space. - `newline' Concatenate the values, separating them with - a newline. - `split' Split values at white spaces, and cons them to the - previous list. - -KEYWORD and OPTION have precedence over DEFAULT. - -All these properties should be back-end agnostic. For back-end -specific properties, define a similar variable named -`org-BACKEND-option-alist', replacing BACKEND with the name of -the appropriate back-end. You can also redefine properties -there, as they have precedence over these.") - -(defvar html-table-tag nil) ; dynamically scoped into this. - -;; FIXME: it already exists in org-e-html.el -(defconst org-e-html-cvt-link-fn - nil - "Function to convert link URLs to exportable URLs. -Takes two arguments, TYPE and PATH. -Returns exportable url as (TYPE PATH), or nil to signal that it -didn't handle this case. -Intended to be locally bound around a call to `org-export-as-html'." ) - - - - -(defvar org-e-html-format-table-no-css) -(defvar htmlize-buffer-places) ; from htmlize.el -(defvar body-only) ; dynamically scoped into this. - -(defvar org-e-html-table-rowgrp-open) -(defvar org-e-html-table-rownum) -(defvar org-e-html-table-cur-rowgrp-is-hdr) -(defvar org-lparse-table-is-styled) - - - -;;; User Configuration Variables - -(defgroup org-export-e-html nil - "Options for exporting Org mode files to HTML." - :tag "Org Export HTML" - :group 'org-export) - -;;;; Debugging - -(defcustom org-e-html-pretty-output t - "Enable this to generate pretty HTML." - :group 'org-export-e-html - :type 'boolean) - - -;;;; Document - -(defcustom org-e-html-extension "html" - "The extension for exported HTML files." - :group 'org-export-e-html - :type 'string) - -(defcustom org-e-html-xml-declaration - '(("html" . "") - ("php" . "\"; ?>")) - "The extension for exported HTML files. -%s will be replaced with the charset of the exported file. -This may be a string, or an alist with export extensions -and corresponding declarations." - :group 'org-export-e-html - :type '(choice - (string :tag "Single declaration") - (repeat :tag "Dependent on extension" - (cons (string :tag "Extension") - (string :tag "Declaration"))))) - -(defcustom org-e-html-coding-system nil - "Coding system for HTML export, defaults to `buffer-file-coding-system'." - :group 'org-export-e-html - :type 'coding-system) - -(defvar org-e-html-content-div "content" - "The name of the container DIV that holds all the page contents. - -This variable is obsolete since Org version 7.7. -Please set `org-e-html-divs' instead.") - -(defcustom org-e-html-divs '("preamble" "content" "postamble") - "The name of the main divs for HTML export. -This is a list of three strings, the first one for the preamble -DIV, the second one for the content DIV and the third one for the -postamble DIV." - :group 'org-export-e-html - :type '(list - (string :tag " Div for the preamble:") - (string :tag " Div for the content:") - (string :tag "Div for the postamble:"))) - - -;;;; Document Header (Styles) - -(defconst org-e-html-style-default -"" - "The default style specification for exported HTML files. -Please use the variables `org-e-html-style' and -`org-e-html-style-extra' to add to this style. If you wish to not -have the default style included, customize the variable -`org-e-html-style-include-default'.") - -(defcustom org-e-html-style-include-default t - "Non-nil means include the default style in exported HTML files. -The actual style is defined in `org-e-html-style-default' and should -not be modified. Use the variables `org-e-html-style' to add -your own style information." - :group 'org-export-e-html - :type 'boolean) -;;;###autoload -(put 'org-e-html-style-include-default 'safe-local-variable 'booleanp) - -(defcustom org-e-html-style "" - "Org-wide style definitions for exported HTML files. - -This variable needs to contain the full HTML structure to provide a style, -including the surrounding HTML tags. If you set the value of this variable, -you should consider to include definitions for the following classes: - title, todo, done, timestamp, timestamp-kwd, tag, target. - -For example, a valid value would be: - - - -If you'd like to refer to an external style file, use something like - - - -As the value of this option simply gets inserted into the HTML header, -you can \"misuse\" it to add arbitrary text to the header. -See also the variable `org-e-html-style-extra'." - :group 'org-export-e-html - :type 'string) -;;;###autoload -(put 'org-e-html-style 'safe-local-variable 'stringp) - -(defcustom org-e-html-style-extra "" - "Additional style information for HTML export. -The value of this variable is inserted into the HTML buffer right after -the value of `org-e-html-style'. Use this variable for per-file -settings of style information, and do not forget to surround the style -settings with tags." - :group 'org-export-e-html - :type 'string) -;;;###autoload -(put 'org-e-html-style-extra 'safe-local-variable 'stringp) - -(defcustom org-e-html-mathjax-options - '((path "http://orgmode.org/mathjax/MathJax.js") - (scale "100") - (align "center") - (indent "2em") - (mathml nil)) - "Options for MathJax setup. - -path The path where to find MathJax -scale Scaling for the HTML-CSS backend, usually between 100 and 133 -align How to align display math: left, center, or right -indent If align is not center, how far from the left/right side? -mathml Should a MathML player be used if available? - This is faster and reduces bandwidth use, but currently - sometimes has lower spacing quality. Therefore, the default is - nil. When browsers get better, this switch can be flipped. - -You can also customize this for each buffer, using something like - -#+MATHJAX: scale:\"133\" align:\"right\" mathml:t path:\"/MathJax/\"" - :group 'org-export-e-html - :type '(list :greedy t - (list :tag "path (the path from where to load MathJax.js)" - (const :format " " path) (string)) - (list :tag "scale (scaling for the displayed math)" - (const :format " " scale) (string)) - (list :tag "align (alignment of displayed equations)" - (const :format " " align) (string)) - (list :tag "indent (indentation with left or right alignment)" - (const :format " " indent) (string)) - (list :tag "mathml (should MathML display be used is possible)" - (const :format " " mathml) (boolean)))) - - -;;;; Document Header (Scripts) - -(defcustom org-e-html-style-include-scripts t - "Non-nil means include the JavaScript snippets in exported HTML files. -The actual script is defined in `org-e-html-scripts' and should -not be modified." - :group 'org-export-e-html - :type 'boolean) - -(defconst org-e-html-scripts -"" -"Basic JavaScript that is needed by HTML files produced by Org-mode.") - - -;;;; Document Header (Mathjax) - -(defcustom org-e-html-mathjax-template - "" - "The MathJax setup for XHTML files." - :group 'org-export-e-html - :type 'string) - - -;;;; Preamble - -(defcustom org-e-html-preamble t - "Non-nil means insert a preamble in HTML export. - -When `t', insert a string as defined by one of the formatting -strings in `org-e-html-preamble-format'. When set to a -string, this string overrides `org-e-html-preamble-format'. -When set to a function, apply this function and insert the -returned string. The function takes the property list of export -options as its only argument. - -Setting :html-preamble in publishing projects will take -precedence over this variable." - :group 'org-export-e-html - :type '(choice (const :tag "No preamble" nil) - (const :tag "Default preamble" t) - (string :tag "Custom formatting string") - (function :tag "Function (must return a string)"))) - -(defcustom org-e-html-preamble-format '(("en" "")) - "The format for the HTML preamble. - -%t stands for the title. -%a stands for the author's name. -%e stands for the author's email. -%d stands for the date. - -If you need to use a \"%\" character, you need to escape it -like that: \"%%\"." - :group 'org-export-e-html - :type 'string) - -(defcustom org-e-html-home/up-format - "
- UP - | - HOME -
" - "Snippet used to insert the HOME and UP links. -This is a format string, the first %s will receive the UP link, -the second the HOME link. If both `org-e-html-link-up' and -`org-e-html-link-home' are empty, the entire snippet will be -ignored." - :group 'org-export-e-html - :type 'string) - -;;;; Postamble - -(defcustom org-e-html-postamble 'auto - "Non-nil means insert a postamble in HTML export. - -When `t', insert a string as defined by the formatting string in -`org-e-html-postamble-format'. When set to a string, this -string overrides `org-e-html-postamble-format'. When set to -'auto, discard `org-e-html-postamble-format' and honor -`org-export-author/email/creator-info' variables. When set to a -function, apply this function and insert the returned string. -The function takes the property list of export options as its -only argument. - -Setting :html-postamble in publishing projects will take -precedence over this variable." - :group 'org-export-e-html - :type '(choice (const :tag "No postamble" nil) - (const :tag "Auto preamble" 'auto) - (const :tag "Default formatting string" t) - (string :tag "Custom formatting string") - (function :tag "Function (must return a string)"))) - -(defcustom org-e-html-postamble-format - '(("en" "

Author: %a (%e)

-

Date: %d

-

Generated by %c

-

%v

-")) - "The format for the HTML postamble. - -%a stands for the author's name. -%e stands for the author's email. -%d stands for the date. -%c will be replaced by information about Org/Emacs versions. -%v will be replaced by `org-e-html-validation-link'. - -If you need to use a \"%\" character, you need to escape it -like that: \"%%\"." - :group 'org-export-e-html - :type 'string) - -(defcustom org-e-html-validation-link - "Validate XHTML 1.0" - "Link to HTML validation service." - :group 'org-export-e-html - :type 'string) - -;; FIXME Obsolete since Org 7.7 -;; Use the :timestamp option or `org-export-time-stamp-file' instead -;;;; Emphasis - -(defcustom org-e-html-protect-char-alist - '(("&" . "&") - ("<" . "<") - (">" . ">")) - "Alist of characters to be converted by `org-e-html-protect'." - :group 'org-export-e-html - :type '(repeat (cons (string :tag "Character") - (string :tag "HTML equivalent")))) - -(defconst org-e-html-special-string-regexps - '(("\\\\-" . "­") - ("---\\([^-]\\)" . "—\\1") - ("--\\([^-]\\)" . "–\\1") - ("\\.\\.\\." . "…")) - "Regular expressions for special string conversion.") - - -;;;; Todos - -(defcustom org-e-html-todo-kwd-class-prefix "" - "Prefix to class names for TODO keywords. -Each TODO keyword gets a class given by the keyword itself, with this prefix. -The default prefix is empty because it is nice to just use the keyword -as a class name. But if you get into conflicts with other, existing -CSS classes, then this prefix can be very useful." - :group 'org-export-e-html - :type 'string) - - -;;;; Tags - -(defcustom org-e-html-tag-class-prefix "" - "Prefix to class names for TODO keywords. -Each tag gets a class given by the tag itself, with this prefix. -The default prefix is empty because it is nice to just use the keyword -as a class name. But if you get into conflicts with other, existing -CSS classes, then this prefix can be very useful." - :group 'org-export-e-html - :type 'string) - -;;;; Time-stamps -;;;; Statistics Cookie -;;;; Subscript -;;;; Superscript - -;;;; Inline images - -(defcustom org-e-html-inline-images 'maybe - "Non-nil means inline images into exported HTML pages. -This is done using an tag. When nil, an anchor with href is used to -link to the image. If this option is `maybe', then images in links with -an empty description will be inlined, while images with a description will -be linked only." - :group 'org-export-e-html - :type '(choice (const :tag "Never" nil) - (const :tag "Always" t) - (const :tag "When there is no description" maybe))) - -(defcustom org-e-html-inline-image-extensions - '("png" "jpeg" "jpg" "gif" "svg") - "Extensions of image files that can be inlined into HTML." - :group 'org-export-e-html - :type '(repeat (string :tag "Extension"))) - - -;;;; Block -;;;; Comment -;;;; Comment Block -;;;; Drawer -;;;; Dynamic Block -;;;; Emphasis -;;;; Entity -;;;; Example Block -;;;; Export Snippet -;;;; Export Block -;;;; Fixed Width -;;;; Footnotes - -(defcustom org-e-html-footnotes-section "
-

%s:

-
-%s -
-
" - "Format for the footnotes section. -Should contain a two instances of %s. The first will be replaced with the -language-specific word for \"Footnotes\", the second one will be replaced -by the footnotes themselves." - :group 'org-export-e-html - :type 'string) - -(defcustom org-e-html-footnote-format "%s" - "The format for the footnote reference. -%s will be replaced by the footnote reference itself." - :group 'org-export-e-html - :type 'string) - -(defcustom org-e-html-footnote-separator ", " - "Text used to separate footnotes." - :group 'org-export-e-html - :type 'string) - - -;;;; Headline -;;;; Horizontal Rule -;;;; Inline Babel Call -;;;; Inline Src Block -;;;; Inlinetask -;;;; Item -;;;; Keyword -;;;; Latex Environment -;;;; Latex Fragment -;;;; Line Break -;;;; Link -;;;; Babel Call -;;;; Macro -;;;; Paragraph -;;;; Plain List -;;;; Plain Text -;;;; Property Drawer -;;;; Quote Block -;;;; Quote Section -;;;; Section -;;;; Radio Target -;;;; Special Block -;;;; Src Block - -(defgroup org-export-e-htmlize nil - "Options for processing examples with htmlize.el." - :tag "Org Export Htmlize" - :group 'org-export-e-html) - -(defcustom org-export-e-htmlize-output-type 'inline-css - "Output type to be used by htmlize when formatting code snippets. -Choices are `css', to export the CSS selectors only, or `inline-css', to -export the CSS attribute values inline in the HTML. We use as default -`inline-css', in order to make the resulting HTML self-containing. - -However, this will fail when using Emacs in batch mode for export, because -then no rich font definitions are in place. It will also not be good if -people with different Emacs setup contribute HTML files to a website, -because the fonts will represent the individual setups. In these cases, -it is much better to let Org/Htmlize assign classes only, and to use -a style file to define the look of these classes. -To get a start for your css file, start Emacs session and make sure that -all the faces you are interested in are defined, for example by loading files -in all modes you want. Then, use the command -\\[org-export-e-htmlize-generate-css] to extract class definitions." - :group 'org-export-e-htmlize - :type '(choice (const css) (const inline-css))) - -(defcustom org-export-e-htmlize-css-font-prefix "org-" - "The prefix for CSS class names for htmlize font specifications." - :group 'org-export-e-htmlize - :type 'string) - -(defcustom org-export-e-htmlized-org-css-url nil - "URL pointing to a CSS file defining text colors for htmlized Emacs buffers. -Normally when creating an htmlized version of an Org buffer, htmlize will -create CSS to define the font colors. However, this does not work when -converting in batch mode, and it also can look bad if different people -with different fontification setup work on the same website. -When this variable is non-nil, creating an htmlized version of an Org buffer -using `org-export-as-org' will remove the internal CSS section and replace it -with a link to this URL." - :group 'org-export-e-htmlize - :type '(choice - (const :tag "Keep internal css" nil) - (string :tag "URL or local href"))) - - -;;;; Table - -(defcustom org-e-html-table-tag - "" - "The HTML tag that is used to start a table. -This must be a
tag, but you may change the options like -borders and spacing." - :group 'org-export-e-html - :type 'string) - -(defcustom org-e-html-table-header-tags '("") - "The opening tag for table header fields. -This is customizable so that alignment options can be specified. -The first %s will be filled with the scope of the field, either row or col. -The second %s will be replaced by a style entry to align the field. -See also the variable `org-e-html-table-use-header-tags-for-first-column'. -See also the variable `org-e-html-table-align-individual-fields'." - :group 'org-export-tables ; FIXME: change group? - :type '(cons (string :tag "Opening tag") (string :tag "Closing tag"))) - -(defcustom org-e-html-table-data-tags '("" . "") - "The opening tag for table data fields. -This is customizable so that alignment options can be specified. -The first %s will be filled with the scope of the field, either row or col. -The second %s will be replaced by a style entry to align the field. -See also the variable `org-e-html-table-align-individual-fields'." - :group 'org-export-tables - :type '(cons (string :tag "Opening tag") (string :tag "Closing tag"))) - -(defcustom org-e-html-table-row-tags '("" . "") - "The opening tag for table data fields. -This is customizable so that alignment options can be specified. -Instead of strings, these can be Lisp forms that will be evaluated -for each row in order to construct the table row tags. During evaluation, -the variable `head' will be true when this is a header line, nil when this -is a body line. And the variable `nline' will contain the line number, -starting from 1 in the first header line. For example - - (setq org-e-html-table-row-tags - (cons '(if head - \"\" - (if (= (mod nline 2) 1) - \"\" - \"\")) - \"\")) - -will give even lines the class \"tr-even\" and odd lines the class \"tr-odd\"." - :group 'org-export-tables - :type '(cons - (choice :tag "Opening tag" - (string :tag "Specify") - (sexp)) - (choice :tag "Closing tag" - (string :tag "Specify") - (sexp)))) - -(defcustom org-e-html-table-align-individual-fields t - "Non-nil means attach style attributes for alignment to each table field. -When nil, alignment will only be specified in the column tags, but this -is ignored by some browsers (like Firefox, Safari). Opera does it right -though." - :group 'org-export-tables - :type 'boolean) - -(defcustom org-e-html-table-use-header-tags-for-first-column nil - "Non-nil means format column one in tables with header tags. -When nil, also column one will use data tags." - :group 'org-export-tables - :type 'boolean) - - -;;;; Target -;;;; Time-stamp - -;;;; Verbatim -;;;; Verse Block -;;;; Headline - -(defcustom org-e-html-toplevel-hlevel 2 - "The level for level 1 headings in HTML export. -This is also important for the classes that will be wrapped around headlines -and outline structure. If this variable is 1, the top-level headlines will -be

, and the corresponding classes will be outline-1, section-number-1, -and outline-text-1. If this is 2, all of these will get a 2 instead. -The default for this variable is 2, because we use

for formatting the -document title." - :group 'org-export-e-html - :type 'string) - - -;;;; Links -;;;; Drawers -;;;; Inlinetasks -;;;; Publishing - -(defcustom org-e-html-link-org-files-as-html t - "Non-nil means make file links to `file.org' point to `file.html'. -When org-mode is exporting an org-mode file to HTML, links to -non-html files are directly put into a href tag in HTML. -However, links to other Org-mode files (recognized by the -extension `.org.) should become links to the corresponding html -file, assuming that the linked org-mode file will also be -converted to HTML. -When nil, the links still point to the plain `.org' file." - :group 'org-export-e-html - :type 'boolean) - - -;;;; Compilation - - - -;;; User Configurable Variables (MAYBE) - -;;;; Preamble - -(defcustom org-e-html-date-format - "\\today" - "Format string for \\date{...}." - :group 'org-export-e-html - :type 'boolean) - -;;;; Headline - -(defcustom org-e-html-format-headline-function nil - "Function to format headline text. - -This function will be called with 5 arguments: -TODO the todo keyword \(string or nil\). -TODO-TYPE the type of todo \(symbol: `todo', `done', nil\) -PRIORITY the priority of the headline \(integer or nil\) -TEXT the main headline text \(string\). -TAGS the tags string, separated with colons \(string or nil\). - -The function result will be used in the section format string. - -As an example, one could set the variable to the following, in -order to reproduce the default set-up: - -\(defun org-e-html-format-headline \(todo todo-type priority text tags\) - \"Default format function for an headline.\" - \(concat \(when todo - \(format \"\\\\textbf{\\\\textsc{\\\\textsf{%s}}} \" todo\)\) - \(when priority - \(format \"\\\\framebox{\\\\#%c} \" priority\)\) - text - \(when tags \(format \"\\\\hfill{}\\\\textsc{%s}\" tags\)\)\)\)" - :group 'org-export-e-html - :type 'function) - -;;;; Emphasis - -(defcustom org-e-html-emphasis-alist - '(("*" . "%s") - ("/" . "%s") - ("_" . "%s") - ("+" . "%s") - ("=" . "%s") - ("~" . "%s")) - "Alist of HTML expressions to convert emphasis fontifiers. - -The key is the character used as a marker for fontification. The -value is a formatting string to wrap fontified text with. - -Value can also be set to the following symbols: `verb' and -`protectedtexttt'. For the former, Org will use \"\\verb\" to -create a format string and select a delimiter character that -isn't in the string. For the latter, Org will use \"\\texttt\" -to typeset and try to protect special characters." - :group 'org-export-e-html - :type 'alist) - - -;;;; Footnotes - -(defcustom org-e-html-footnote-separator ", " - "Text used to separate footnotes." - :group 'org-export-e-html - :type 'string) - - -;;;; Time-stamps - -(defcustom org-e-html-active-timestamp-format "\\textit{%s}" - "A printf format string to be applied to active time-stamps." - :group 'org-export-e-html - :type 'string) - -(defcustom org-e-html-inactive-timestamp-format "\\textit{%s}" - "A printf format string to be applied to inactive time-stamps." - :group 'org-export-e-html - :type 'string) - -(defcustom org-e-html-diary-timestamp-format "\\textit{%s}" - "A printf format string to be applied to diary time-stamps." - :group 'org-export-e-html - :type 'string) - - -;;;; Links - -(defcustom org-e-html-inline-image-rules - '(("file" . "\\.\\(jpeg\\|jpg\\|png\\|gif\\|svg\\)\\'") - ("http" . "\\.\\(jpeg\\|jpg\\|png\\|gif\\|svg\\)\\'") - ("https" . "\\.\\(jpeg\\|jpg\\|png\\|gif\\|svg\\)\\'")) - "Rules characterizing image files that can be inlined into HTML. - -A rule consists in an association whose key is the type of link -to consider, and value is a regexp that will be matched against -link's path. - -Note that, by default, the image extension *actually* allowed -depend on the way the HTML file is processed. When used with -pdflatex, pdf, jpg and png images are OK. When processing -through dvi to Postscript, only ps and eps are allowed. The -default we use here encompasses both." - :group 'org-export-e-html - :type '(alist :key-type (string :tag "Type") - :value-type (regexp :tag "Path"))) - -;;;; Tables - -(defcustom org-e-html-table-caption-above t - "When non-nil, place caption string at the beginning of the table. -Otherwise, place it near the end." - :group 'org-export-e-html - :type 'boolean) - -;;;; Drawers - -(defcustom org-e-html-format-drawer-function nil - "Function called to format a drawer in HTML code. - -The function must accept two parameters: - NAME the drawer name, like \"LOGBOOK\" - CONTENTS the contents of the drawer. - -The function should return the string to be exported. - -For example, the variable could be set to the following function -in order to mimic default behaviour: - -\(defun org-e-html-format-drawer-default \(name contents\) - \"Format a drawer element for HTML export.\" - contents\)" - :group 'org-export-e-html - :type 'function) - - -;;;; Inlinetasks - -(defcustom org-e-html-format-inlinetask-function nil - "Function called to format an inlinetask in HTML code. - -The function must accept six parameters: - TODO the todo keyword, as a string - TODO-TYPE the todo type, a symbol among `todo', `done' and nil. - PRIORITY the inlinetask priority, as a string - NAME the inlinetask name, as a string. - TAGS the inlinetask tags, as a string. - CONTENTS the contents of the inlinetask, as a string. - -The function should return the string to be exported. - -For example, the variable could be set to the following function -in order to mimic default behaviour: - -\(defun org-e-html-format-inlinetask \(todo type priority name tags contents\) -\"Format an inline task element for HTML export.\" - \(let \(\(full-title - \(concat - \(when todo - \(format \"\\\\textbf{\\\\textsf{\\\\textsc{%s}}} \" todo\)\) - \(when priority \(format \"\\\\framebox{\\\\#%c} \" priority\)\) - title - \(when tags \(format \"\\\\hfill{}\\\\textsc{%s}\" tags\)\)\)\)\) - \(format \(concat \"\\\\begin{center}\\n\" - \"\\\\fbox{\\n\" - \"\\\\begin{minipage}[c]{.6\\\\textwidth}\\n\" - \"%s\\n\\n\" - \"\\\\rule[.8em]{\\\\textwidth}{2pt}\\n\\n\" - \"%s\" - \"\\\\end{minipage}}\" - \"\\\\end{center}\"\) - full-title contents\)\)" - :group 'org-export-e-html - :type 'function) - - -;; Src blocks - -;;;; Plain text - -(defcustom org-e-html-quotes - '(("fr" - ("\\(\\s-\\|[[(]\\)\"" . "«~") - ("\\(\\S-\\)\"" . "~»") - ("\\(\\s-\\|(\\)'" . "'")) - ("en" - ("\\(\\s-\\|[[(]\\)\"" . "``") - ("\\(\\S-\\)\"" . "''") - ("\\(\\s-\\|(\\)'" . "`"))) - "Alist for quotes to use when converting english double-quotes. - -The CAR of each item in this alist is the language code. -The CDR of each item in this alist is a list of three CONS. -- the first CONS defines the opening quote -- the second CONS defines the closing quote -- the last CONS defines single quotes - -For each item in a CONS, the first string is a regexp for allowed -characters before/after the quote, the second string defines the -replacement string for this quote." - :group 'org-export-e-html - :type '(list - (cons :tag "Opening quote" - (string :tag "Regexp for char before") - (string :tag "Replacement quote ")) - (cons :tag "Closing quote" - (string :tag "Regexp for char after ") - (string :tag "Replacement quote ")) - (cons :tag "Single quote" - (string :tag "Regexp for char before") - (string :tag "Replacement quote ")))) - - -;;;; Compilation - - - -;;; Internal Functions (HTML) - -(defun org-e-html-cvt-org-as-html (opt-plist type path) - "Convert an org filename to an equivalent html filename. -If TYPE is not file, just return `nil'. -See variable `org-e-html-link-org-files-as-html'." - (save-match-data - (and - org-e-html-link-org-files-as-html - (string= type "file") - (string-match "\\.org$" path) - (progn - (list - "file" - (concat - (substring path 0 (match-beginning 0)) - "." (plist-get opt-plist :html-extension))))))) - -(defun org-e-html-format-org-link (opt-plist type-1 path fragment desc attr - descp) - "Make an HTML link. -OPT-PLIST is an options list. -TYPE is the device-type of the link (THIS://foo.html). -PATH is the path of the link (http://THIS#location). -FRAGMENT is the fragment part of the link, if any (foo.html#THIS). -DESC is the link description, if any. -ATTR is a string of other attributes of the \"a\" element." - (declare (special org-lparse-par-open)) - (save-match-data - (when (string= type-1 "coderef") - (let ((ref fragment)) - (setq desc (format (org-export-get-coderef-format ref (and descp desc)) - (cdr (assoc ref org-export-code-refs))) - fragment (concat "coderef-" ref) - attr (format "class=\"coderef\" onmouseover=\"CodeHighlightOn(this, '%s');\" onmouseout=\"CodeHighlightOff(this, '%s');\"" - fragment fragment)))) - (let* ((may-inline-p - (and (member type-1 '("http" "https" "file")) - (org-lparse-should-inline-p path descp) - (not fragment))) - (type (if (equal type-1 "id") "file" type-1)) - (filename path) - ;;First pass. Just sanity stuff. - (components-1 - (cond - ((string= type "file") - (list - type - ;;Substitute just if original path was absolute. - ;;(Otherwise path must remain relative) - (if (file-name-absolute-p path) - (concat "file://" (expand-file-name path)) - path))) - ((string= type "") - (list nil path)) - (t (list type path)))) - - ;;Second pass. Components converted so they can refer - ;;to a remote site. - (components-2 - (or - (and org-e-html-cvt-link-fn - (apply org-e-html-cvt-link-fn - opt-plist components-1)) - (apply #'org-e-html-cvt-org-as-html - opt-plist components-1) - components-1)) - (type (first components-2)) - (thefile (second components-2))) - - - ;;Third pass. Build final link except for leading type - ;;spec. - (cond - ((or - (not type) - (string= type "http") - (string= type "https") - (string= type "file") - (string= type "coderef")) - (if fragment - (setq thefile (concat thefile "#" fragment)))) - - (t)) - - ;;Final URL-build, for all types. - (setq thefile - (let - ((str (org-xml-format-href thefile))) - (if (and type (not (or (string= "file" type) - (string= "coderef" type)))) - (concat type ":" str) - str))) - - (if may-inline-p - (ignore) ;; (org-e-html-format-image thefile) - (org-lparse-format - 'LINK (org-xml-format-desc desc) thefile attr))))) - -;; (caption (and caption (org-xml-encode-org-text caption))) -;; alt = (file-name-nondirectory path) - -(defun org-e-html-format-inline-image (src &optional - caption label attr standalone-p) - (let* ((id (if (not label) "" - (format " id=\"%s\"" (org-export-solidify-link-text label)))) - (attr (concat attr - (cond - ((string-match "\\" src attr))) - (format "\n%s%s\n" - id (format "\n

%s

" img) - (when caption (format "\n

%s

" caption))))) - (t (format "" src (concat attr id)))))) - -;;;; Bibliography - -(defun org-e-html-bibliography () - "Find bibliography, cut it out and return it." - (catch 'exit - (let (beg end (cnt 1) bib) - (save-excursion - (goto-char (point-min)) - (when (re-search-forward - "^[ \t]*
" nil t) - (setq cnt (+ cnt (if (string= (match-string 0) "") (forward-char 1)) - (setq bib (buffer-substring beg (point))) - (delete-region beg (point)) - (throw 'exit bib)))) - nil)))) - -;;;; Table - -(defun org-e-html-format-table (lines olines) - (let ((org-e-html-format-table-no-css nil)) - (org-lparse-format-table lines olines))) - -(defun org-e-html-splice-attributes (tag attributes) - "Read attributes in string ATTRIBUTES, add and replace in HTML tag TAG." - (if (not attributes) - tag - (let (oldatt newatt) - (setq oldatt (org-extract-attributes-from-string tag) - tag (pop oldatt) - newatt (cdr (org-extract-attributes-from-string attributes))) - (while newatt - (setq oldatt (plist-put oldatt (pop newatt) (pop newatt)))) - (if (string-match ">" tag) - (setq tag - (replace-match (concat (org-attributes-to-string oldatt) ">") - t t tag))) - tag))) - -(defun org-export-splice-style (style extra) - "Splice EXTRA into STYLE, just before \"\"." - (if (and (stringp extra) - (string-match "\\S-" extra) - (string-match "" style)) - (concat (substring style 0 (match-beginning 0)) - "\n" extra "\n" - (substring style (match-beginning 0))) - style)) - -(defun org-export-e-htmlize-region-for-paste (beg end) - "Convert the region to HTML, using htmlize.el. -This is much like `htmlize-region-for-paste', only that it uses -the settings define in the org-... variables." - (let* ((htmlize-output-type org-export-e-htmlize-output-type) - (htmlize-css-name-prefix org-export-e-htmlize-css-font-prefix) - (htmlbuf (htmlize-region beg end))) - (unwind-protect - (with-current-buffer htmlbuf - (buffer-substring (plist-get htmlize-buffer-places 'content-start) - (plist-get htmlize-buffer-places 'content-end))) - (kill-buffer htmlbuf)))) - -;;;###autoload -(defun org-export-e-htmlize-generate-css () - "Create the CSS for all font definitions in the current Emacs session. -Use this to create face definitions in your CSS style file that can then -be used by code snippets transformed by htmlize. -This command just produces a buffer that contains class definitions for all -faces used in the current Emacs session. You can copy and paste the ones you -need into your CSS file. - -If you then set `org-export-e-htmlize-output-type' to `css', calls to -the function `org-export-e-htmlize-region-for-paste' will produce code -that uses these same face definitions." - (interactive) - (require 'htmlize) - (and (get-buffer "*html*") (kill-buffer "*html*")) - (with-temp-buffer - (let ((fl (face-list)) - (htmlize-css-name-prefix "org-") - (htmlize-output-type 'css) - f i) - (while (setq f (pop fl) - i (and f (face-attribute f :inherit))) - (when (and (symbolp f) (or (not i) (not (listp i)))) - (insert (org-add-props (copy-sequence "1") nil 'face f)))) - (htmlize-region (point-min) (point-max)))) - (org-pop-to-buffer-same-window "*html*") - (goto-char (point-min)) - (if (re-search-forward "" nil t) - (delete-region (1+ (match-end 0)) (point-max))) - (beginning-of-line 1) - (if (looking-at " +") (replace-match "")) - (goto-char (point-min))) - -(defun org-e-html-make-string (n string) - (let (out) (dotimes (i n out) (setq out (concat string out))))) - -(defun org-e-html-toc-text (toc-entries) - (let* ((prev-level (1- (nth 1 (car toc-entries)))) - (start-level prev-level)) - (concat - (mapconcat - (lambda (entry) - (let ((headline (nth 0 entry)) - (level (nth 1 entry))) - (concat - (let* ((cnt (- level prev-level)) - (times (if (> cnt 0) (1- cnt) (- cnt))) - rtn) - (setq prev-level level) - (concat - (org-e-html-make-string - times (cond ((> cnt 0) "\n
    \n
  • ") - ((< cnt 0) "
  • \n
\n"))) - (if (> cnt 0) "\n
    \n
  • " "
  • \n
  • "))) - headline))) - toc-entries "") - (org-e-html-make-string - (- prev-level start-level) "
  • \n
\n")))) - -(defun* org-e-html-format-toc-headline - (todo todo-type priority text tags - &key level section-number headline-label &allow-other-keys) - (let ((headline (concat - section-number (and section-number ". ") - text - (and tags "   ") (org-e-html--tags tags)))) - (format "%s" - headline-label - (if (not nil) headline - (format "%s" todo-type headline))))) - -(defun org-e-html-toc (depth info) - (assert (wholenump depth)) - (let* ((headlines (org-export-collect-headlines info depth)) - (toc-entries - (loop for headline in headlines collect - (list (org-e-html-format-headline--wrap - headline info 'org-e-html-format-toc-headline) - (org-export-get-relative-level headline info))))) - (when toc-entries - (let* ((lang-specific-heading - (nth 3 (or (assoc (plist-get info :language) - org-export-language-setup) - (assoc "en" org-export-language-setup))))) - (concat - "
\n" - (format "%s\n" - org-e-html-toplevel-hlevel - lang-specific-heading - org-e-html-toplevel-hlevel) - "
" - (org-e-html-toc-text toc-entries) - "
\n" - "
\n"))))) - -;; (defun org-e-html-format-line (line) -;; (case org-lparse-dyn-current-environment -;; ((quote fixedwidth) (concat (org-e-html-encode-plain-text line) "\n")) -;; (t (concat line "\n")))) - -(defun org-e-html-fix-class-name (kwd) ; audit callers of this function - "Turn todo keyword into a valid class name. -Replaces invalid characters with \"_\"." - (save-match-data - (while (string-match "[^a-zA-Z0-9_]" kwd) - (setq kwd (replace-match "_" t t kwd)))) - kwd) - -(defun org-e-html-format-footnote-reference (n def refcnt) - (let ((extra (if (= refcnt 1) "" (format ".%d" refcnt)))) - (format org-e-html-footnote-format - (format - "%s" - n extra n n)))) - -(defun org-e-html-format-footnotes-section (section-name definitions) - (if (not definitions) "" - (format org-e-html-footnotes-section section-name definitions))) - -(defun org-e-html-format-footnote-definition (fn) - (let ((n (car fn)) (def (cdr fn))) - (format - "

\n\n\n\n" - (format - (format org-e-html-footnote-format - "%s") - n n n) def))) - -(defun org-e-html-footnote-section (info) - (let* ((fn-alist (org-export-collect-footnote-definitions - (plist-get info :parse-tree) info)) - - (fn-alist - (loop for (n type raw) in fn-alist collect - (cons n (if (equal (org-element-type raw) 'org-data) - (org-trim (org-export-data raw 'e-html info)) - (format "

%s

" - (org-trim (org-export-secondary-string - raw 'e-html info)))))))) - (when fn-alist - (org-e-html-format-footnotes-section - (nth 4 (or (assoc (plist-get info :language) - org-export-language-setup) - (assoc "en" org-export-language-setup))) - (format - "
" . "
%s%s
\n%s\n
\n" - (mapconcat 'org-e-html-format-footnote-definition fn-alist "\n")))))) - -(defun org-e-html-get-coding-system-for-write () - (or org-e-html-coding-system - (and (boundp 'buffer-file-coding-system) buffer-file-coding-system))) - -(defun org-e-html-get-coding-system-for-save () - (or org-e-html-coding-system - (and (boundp 'buffer-file-coding-system) buffer-file-coding-system))) - -(defun org-e-html-format-date (info) - (let ((date (plist-get info :date))) - (cond - ((and date (string-match "%" date)) - (format-time-string date)) - (date date) - (t (format-time-string "%Y-%m-%d %T %Z"))))) - - - -;;; Internal Functions (Ngz) - -(defun org-e-html--caption/label-string (caption label info) - "Return caption and label HTML string for floats. - -CAPTION is a cons cell of secondary strings, the car being the -standard caption and the cdr its short form. LABEL is a string -representing the label. INFO is a plist holding contextual -information. - -If there's no caption nor label, return the empty string. - -For non-floats, see `org-e-html--wrap-label'." - (setq label nil) ;; FIXME - - (let ((label-str (if label (format "\\label{%s}" label) ""))) - (cond - ((and (not caption) (not label)) "") - ((not caption) (format "\\label{%s}\n" label)) - ;; Option caption format with short name. - ((cdr caption) - (format "\\caption[%s]{%s%s}\n" - (org-export-secondary-string (cdr caption) 'e-html info) - label-str - (org-export-secondary-string (car caption) 'e-html info))) - ;; Standard caption format. - ;; (t (format "\\caption{%s%s}\n" - ;; label-str - ;; (org-export-secondary-string (car caption) 'e-html info))) - - (t (org-export-secondary-string (car caption) 'e-html info))))) - -(defun org-e-html--find-verb-separator (s) - "Return a character not used in string S. -This is used to choose a separator for constructs like \\verb." - (let ((ll "~,./?;':\"|!@#%^&-_=+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ<>()[]{}")) - (loop for c across ll - when (not (string-match (regexp-quote (char-to-string c)) s)) - return (char-to-string c)))) - -(defun org-e-html--quotation-marks (text info) - "Export quotation marks depending on language conventions. -TEXT is a string containing quotation marks to be replaced. INFO -is a plist used as a communication channel." - (mapc (lambda(l) - (let ((start 0)) - (while (setq start (string-match (car l) text start)) - (let ((new-quote (concat (match-string 1 text) (cdr l)))) - (setq text (replace-match new-quote t t text)))))) - (cdr (or (assoc (plist-get info :language) org-e-html-quotes) - ;; Falls back on English. - (assoc "en" org-e-html-quotes)))) - text) - -(defun org-e-html--wrap-label (element output) - "Wrap label associated to ELEMENT around OUTPUT, if appropriate. -This function shouldn't be used for floats. See -`org-e-html--caption/label-string'." - ;; (let ((label (org-element-property :name element))) - ;; (if (or (not output) (not label) (string= output "") (string= label "")) - ;; output - ;; (concat (format "\\label{%s}\n" label) output))) - output) - - - -;;; Template - -(defun org-e-html-meta-info (info) - (let* ((title (org-export-secondary-string - (plist-get info :title) 'e-html info)) - (author (and (plist-get info :with-author) - (let ((auth (plist-get info :author))) - (and auth (org-export-secondary-string - auth 'e-html info))))) - (description (plist-get info :description)) - (keywords (plist-get info :keywords))) - (concat - (format "\n%s\n" title) - (format - "\n" - (and coding-system-for-write - (fboundp 'coding-system-get) - (coding-system-get coding-system-for-write - 'mime-charset))) - (format "\n" title) - (format "\n") - (format "\n" - (org-e-html-format-date info)) - (format "\n" author) - (format "\n" description) - (format "\n" keywords)))) - -(defun org-e-html-style (info) - (concat - "\n" (when (plist-get info :style-include-default) org-e-html-style-default) - (plist-get info :style) - (plist-get info :style-extra) - "\n" - (when (plist-get info :style-include-scripts) - org-e-html-scripts))) - -(defun org-e-html-mathjax-config (info) - "Insert the user setup into the matchjax template." - (when (member (plist-get info :LaTeX-fragments) '(mathjax t)) - (let ((template org-e-html-mathjax-template) - (options org-e-html-mathjax-options) - (in-buffer (or (plist-get info :mathjax) "")) - name val (yes " ") (no "// ") x) - (mapc - (lambda (e) - (setq name (car e) val (nth 1 e)) - (if (string-match (concat "\\<" (symbol-name name) ":") in-buffer) - (setq val (car (read-from-string - (substring in-buffer (match-end 0)))))) - (if (not (stringp val)) (setq val (format "%s" val))) - (if (string-match (concat "%" (upcase (symbol-name name))) template) - (setq template (replace-match val t t template)))) - options) - (setq val (nth 1 (assq 'mathml options))) - (if (string-match (concat "\\ " (nth 0 org-e-html-divs)) - " -" - html-pre-real-contents - " -"))))) - -(defun org-e-html-postamble (info) - (concat - (when (and (not body-only) - (plist-get info :html-postamble)) - (let* ((html-post (plist-get info :html-postamble)) - (date (org-e-html-format-date info)) - (author (plist-get info :author)) - (email (plist-get info :email)) - (lang-words (or (assoc (plist-get info :language) - org-export-language-setup) - (assoc "en" org-export-language-setup))) - (email - (mapconcat (lambda(e) - (format "%s" e e)) - (split-string email ",+ *") - ", ")) - (html-validation-link (or org-e-html-validation-link "")) - (creator-info - (concat "Org version " org-version " with Emacs version " - (number-to-string emacs-major-version)))) - (concat - ;; begin postamble - " -
" - (cond - ;; auto postamble - ((eq (plist-get info :html-postamble) 'auto) - (concat - (when (plist-get info :time-stamp-file) - (format " -

%s: %s

" (nth 2 lang-words) date)) - (when (and (plist-get info :with-author) author) - (format " -

%s : %s

" (nth 1 lang-words) author)) - (when (and (plist-get info :with-email) email) - (format " -

%s

" email)) - (when (plist-get info :with-creator) - (format " -

%s

" creator-info)) - html-validation-link "\n")) - ;; postamble from a string - ((stringp (plist-get info :html-postamble)) - (format-spec (plist-get info :html-postamble) - `((?a . ,author) (?e . ,email) - (?d . ,date) (?c . ,creator-info) - (?v . ,html-validation-link)))) - - ;; postamble from a function - ((functionp (plist-get info :html-postamble)) - (with-temp-buffer - (funcall (plist-get info :html-postamble)) - (buffer-string))) - ;; default postamble - (t - (format-spec - (or (cadr (assoc (nth 0 lang-words) - org-e-html-postamble-format)) - (cadr (assoc "en" org-e-html-postamble-format))) - `((?a . ,author) (?e . ,email) - (?d . ,date) (?c . ,creator-info) - (?v . ,html-validation-link))))) - " -
"))) - ;; org-e-html-html-helper-timestamp - )) - -(defun org-e-html-template (contents info) - "Return complete document string after HTML conversion. -CONTENTS is the transcoded contents string. RAW-DATA is the -original parsed data. INFO is a plist holding export options." - (concat - (format - (or (and (stringp org-e-html-xml-declaration) - org-e-html-xml-declaration) - (cdr (assoc (plist-get info :html-extension) - org-e-html-xml-declaration)) - (cdr (assoc "html" org-e-html-xml-declaration)) - - "") - (or (and coding-system-for-write - (fboundp 'coding-system-get) - (coding-system-get coding-system-for-write - 'mime-charset)) - "iso-8859-1")) - " -" - (format " - " - (plist-get info :language) (plist-get info :language)) - " -" - (org-e-html-meta-info info) ; meta - (org-e-html-style info) ; style - (org-e-html-mathjax-config info) ; mathjax - " -" - - " -" - (let ((link-up (and (plist-get info :link-up) - (string-match "\\S-" (plist-get info :link-up)) - (plist-get info :link-up))) - (link-home (and (plist-get info :link-home) - (string-match "\\S-" (plist-get info :link-home)) - (plist-get info :link-home)))) - (when (or link-up link-home) - (format org-e-html-home/up-format - (or link-up link-home) - (or link-home link-up)))) - ;; preamble - (org-e-html-preamble info) - ;; begin content - (format " -
" (or org-e-html-content-div - (nth 1 org-e-html-divs))) - ;; document title - (format " -

%s

\n" (plist-get info :title)) - ;; table of contents - (let ((depth (plist-get info :with-toc))) - (when (wholenump depth) (org-e-html-toc depth info))) - ;; document contents - contents - ;; footnotes section - (org-e-html-footnote-section info) - ;; bibliography - (org-e-html-bibliography) - ;; end content - (unless body-only - " -
") - - ;; postamble - (org-e-html-postamble info) - - (unless body-only - " -") - " -")) - - - -;;; Transcode Helpers - -;;;; Todo - -(defun org-e-html--todo (todo) - (when todo - (format "%s" - (if (member todo org-done-keywords) "done" "todo") - org-e-html-todo-kwd-class-prefix (org-e-html-fix-class-name todo) - todo))) - -;;;; Tags - -(defun org-e-html--tags (tags) - (when tags - (format "%s" - (mapconcat - (lambda (tag) - (format "%s" - (concat org-e-html-tag-class-prefix - (org-e-html-fix-class-name tag)) - tag)) - (org-split-string tags ":") " ")))) - -;;;; Headline - -(defun* org-e-html-format-headline - (todo todo-type priority text tags - &key level section-number headline-label &allow-other-keys) - (let ((section-number - (when section-number - (format "%s " - level section-number))) - (todo (org-e-html--todo todo)) - (tags (org-e-html--tags tags))) - (concat section-number todo (and todo " ") text - (and tags "   ") tags))) - -;;;; Src Code - -(defun org-e-html-fontify-code (code lang) - (when code - (cond - ;; Case 1: No lang. Possibly an example block. - ((not lang) - ;; Simple transcoding. - (org-e-html-encode-plain-text code)) - ;; Case 2: No htmlize or an inferior version of htmlize - ((not (and (require 'htmlize nil t) (fboundp 'htmlize-region-for-paste))) - ;; Emit a warning. - (message "Cannot fontify src block (htmlize.el >= 1.34 required)") - ;; Simple transcoding. - (org-e-html-encode-plain-text code)) - (t - ;; Map language - (setq lang (or (assoc-default lang org-src-lang-modes) lang)) - (let* ((lang-mode (and lang (intern (format "%s-mode" lang))))) - (cond - ;; Case 1: Language is not associated with any Emacs mode - ((not (functionp lang-mode)) - ;; Simple transcoding. - (org-e-html-encode-plain-text code)) - ;; Case 2: Default. Fotify code. - (t - ;; htmlize - (setq code (with-temp-buffer - (insert code) - (funcall lang-mode) - (font-lock-fontify-buffer) - ;; markup each line separately - (org-remove-formatting-on-newlines-in-region - (point-min) (point-max)) - (org-src-mode) - (set-buffer-modified-p nil) - (org-export-e-htmlize-region-for-paste - (point-min) (point-max)))) - ;; Strip any encolosing
 tags
-	  (if (string-match "]*>\n*\\([^\000]*\\)" code)
-	      (match-string 1 code)
-	    code))))))))
-
-(defun org-e-html-do-format-code
-  (code &optional lang refs retain-labels num-start textarea-p)
-  (when textarea-p
-    (setq num-start nil refs nil lang nil))
-  (let* ((code-lines (org-split-string code "\n"))
-	 (code-length (length code-lines))
-	 (num-fmt
-	  (and num-start
-	       (format "%%%ds: "
-		       (length (number-to-string (+ code-length num-start))))))
-	 (code (org-e-html-fontify-code code lang)))
-    (assert (= code-length (length (org-split-string code "\n"))))
-    (org-export-format-code
-     code
-     (lambda (loc line-num ref)
-       (setq loc
-	     (concat
-	      ;; Add line number, if needed.
-	      (when num-start
-		(format "%s"
-			(format num-fmt line-num)))
-	      ;; Transcoded src line.
-	      loc
-	      ;; Add label, if needed.
-	      (when (and ref retain-labels) (format " (%s)" ref))))
-       ;; Mark transcoded line as an anchor, if needed.
-       (if (not ref) loc
-	 (format "%s"
-		 ref loc)))
-     num-start refs)))
-
-(defun org-e-html-format-code (element info)
-  (let* ((lang (org-element-property :language element))
-	 ;; (switches (org-element-property :switches element))
-	 (switches nil)			; FIXME
-	 (textarea-p (and switches (string-match "-t\\>" switches)))
-	 ;; Extract code and references.
-	 (code-info (org-export-unravel-code element))
-	 (code (car code-info))
-	 (refs (cdr code-info))
-	 ;; Does the src block contain labels?
-	 (retain-labels (org-element-property :retain-labels element))
-	 ;; Does it have line numbers?
-	 (num-start (case (org-element-property :number-lines element)
-		      (continued (org-export-get-loc element info))
-		      (new 0))))
-    (org-e-html-do-format-code
-     code lang refs retain-labels num-start textarea-p)))
-
-
-
-;;; Transcode Functions
-
-;;;; Block
-
-(defun org-e-html-center-block (center-block contents info)
-  "Transcode a CENTER-BLOCK element from Org to HTML.
-CONTENTS holds the contents of the block.  INFO is a plist
-holding contextual information."
-  (org-e-html--wrap-label
-   center-block
-   (format "
\n%s
" contents))) - - -;;;; Comment - -;; Comments are ignored. - - -;;;; Comment Block - -;; Comment Blocks are ignored. - - -;;;; Drawer - -(defun org-e-html-drawer (drawer contents info) - "Transcode a DRAWER element from Org to HTML. -CONTENTS holds the contents of the block. INFO is a plist -holding contextual information." - (let* ((name (org-element-property :drawer-name drawer)) - (output (if (functionp org-e-html-format-drawer-function) - (funcall org-e-html-format-drawer-function - name contents) - ;; If there's no user defined function: simply - ;; display contents of the drawer. - contents))) - (org-e-html--wrap-label drawer output))) - - -;;;; Dynamic Block - -(defun org-e-html-dynamic-block (dynamic-block contents info) - "Transcode a DYNAMIC-BLOCK element from Org to HTML. -CONTENTS holds the contents of the block. INFO is a plist -holding contextual information. See -`org-export-data'." - (org-e-html--wrap-label dynamic-block contents)) - - -;;;; Emphasis - -(defun org-e-html-emphasis (emphasis contents info) - "Transcode EMPHASIS from Org to HTML. -CONTENTS is the contents of the emphasized text. INFO is a plist -holding contextual information.." - (let* ((marker (org-element-property :marker emphasis))) - (format (cdr (assoc marker org-e-html-emphasis-alist)) contents))) - - -;;;; Entity - -(defun org-e-html-entity (entity contents info) - "Transcode an ENTITY object from Org to HTML. -CONTENTS are the definition itself. INFO is a plist holding -contextual information." - (org-element-property :html entity)) - - -;;;; Example Block - -(defun org-e-html-example-block (example-block contents info) - "Transcode a EXAMPLE-BLOCK element from Org to HTML. -CONTENTS is nil. INFO is a plist holding contextual information." - (let* ((options (or (org-element-property :options example-block) "")) - (lang (org-element-property :language example-block)) - (caption (org-element-property :caption example-block)) - (label (org-element-property :name example-block)) - (caption-str (org-e-html--caption/label-string caption label info)) - (attr (mapconcat #'identity - (org-element-property :attr_html example-block) - " ")) - ;; (switches (org-element-property :switches example-block)) - (switches nil) ; FIXME - (textarea-p (and switches (string-match "-t\\>" switches))) - (code (org-e-html-format-code example-block info))) - (cond - (textarea-p - (let ((cols (if (not (string-match "-w[ \t]+\\([0-9]+\\)" switches)) - 80 (string-to-number (match-string 1 switches)))) - (rows (if (string-match "-h[ \t]+\\([0-9]+\\)" switches) - (string-to-number (match-string 1 switches)) - (org-count-lines code)))) - (format - "\n

\n\n

" - cols rows code))) - (t (format "\n
\n%s\n
" code))))) - - -;;;; Export Snippet - -(defun org-e-html-export-snippet (export-snippet contents info) - "Transcode a EXPORT-SNIPPET object from Org to HTML. -CONTENTS is nil. INFO is a plist holding contextual information." - (when (eq (org-export-snippet-backend export-snippet) 'e-html) - (org-element-property :value export-snippet))) - - -;;;; Export Block - -(defun org-e-html-export-block (export-block contents info) - "Transcode a EXPORT-BLOCK element from Org to HTML. -CONTENTS is nil. INFO is a plist holding contextual information." - (when (string= (org-element-property :type export-block) "latex") - (org-remove-indentation (org-element-property :value export-block)))) - - -;;;; Fixed Width - -(defun org-e-html-fixed-width (fixed-width contents info) - "Transcode a FIXED-WIDTH element from Org to HTML. -CONTENTS is nil. INFO is a plist holding contextual information." - (let* ((value (org-element-normalize-string - (replace-regexp-in-string - "^[ \t]*: ?" "" - (org-element-property :value fixed-width))))) - (org-e-html--wrap-label - fixed-width (format "\n
\n%s\n
" - (org-e-html-do-format-code value))))) - - -;;;; Footnote Definition - -;; Footnote Definitions are ignored. - - -;;;; Footnote Reference - -(defun org-e-html-footnote-reference (footnote-reference contents info) - "Transcode a FOOTNOTE-REFERENCE element from Org to HTML. -CONTENTS is nil. INFO is a plist holding contextual information." - (concat - ;; Insert separator between two footnotes in a row. - (let ((prev (org-export-get-previous-element footnote-reference info))) - (when (eq (org-element-type prev) 'footnote-reference) - org-e-html-footnote-separator)) - (cond - ((not (org-export-footnote-first-reference-p footnote-reference info)) - (org-e-html-format-footnote-reference - (org-export-get-footnote-number footnote-reference info) - "IGNORED" 100)) - ;; Inline definitions are secondary strings. - ((eq (org-element-property :type footnote-reference) 'inline) - (org-e-html-format-footnote-reference - (org-export-get-footnote-number footnote-reference info) - "IGNORED" 1)) - ;; Non-inline footnotes definitions are full Org data. - (t (org-e-html-format-footnote-reference - (org-export-get-footnote-number footnote-reference info) - "IGNORED" 1))))) - - -;;;; Headline - -(defun org-e-html-format-headline--wrap (headline info - &optional format-function - &rest extra-keys) - "Transcode an HEADLINE element from Org to HTML. -CONTENTS holds the contents of the headline. INFO is a plist -holding contextual information." - (let* ((level (+ (org-export-get-relative-level headline info) - (1- org-e-html-toplevel-hlevel))) - (headline-number (org-export-get-headline-number headline info)) - (section-number (and (org-export-numbered-headline-p headline info) - (mapconcat 'number-to-string - headline-number "."))) - (todo (and (plist-get info :with-todo-keywords) - (let ((todo (org-element-property - :todo-keyword headline))) - (and todo - (org-export-secondary-string todo 'e-html info))))) - (todo-type (and todo (org-element-property :todo-type headline))) - (priority (and (plist-get info :with-priority) - (org-element-property :priority headline))) - (text (org-export-secondary-string - (org-element-property :title headline) 'e-html info)) - (tags (and (plist-get info :with-tags) - (org-element-property :tags headline))) - (headline-label (concat "sec-" (mapconcat 'number-to-string - headline-number "-"))) - (format-function (cond - ((functionp format-function) format-function) - ((functionp org-e-html-format-headline-function) - (function* - (lambda (todo todo-type priority text tags - &allow-other-keys) - (funcall org-e-html-format-headline-function - todo todo-type priority text tags)))) - (t 'org-e-html-format-headline)))) - (apply format-function - todo todo-type priority text tags - :headline-label headline-label :level level - :section-number section-number extra-keys))) - -(defun org-e-html-headline (headline contents info) - "Transcode an HEADLINE element from Org to HTML. -CONTENTS holds the contents of the headline. INFO is a plist -holding contextual information." - (let* ((numberedp (org-export-numbered-headline-p headline info)) - (level (org-export-get-relative-level headline info)) - (text (org-export-secondary-string - (org-element-property :title headline) 'e-html info)) - (todo (and (plist-get info :with-todo-keywords) - (let ((todo (org-element-property - :todo-keyword headline))) - (and todo - (org-export-secondary-string todo 'e-html info))))) - (todo-type (and todo (org-element-property :todo-type headline))) - (tags (and (plist-get info :with-tags) - (org-element-property :tags headline))) - (priority (and (plist-get info :with-priority) - (org-element-property :priority headline))) - (section-number (and (org-export-numbered-headline-p headline info) - (mapconcat 'number-to-string - (org-export-get-headline-number - headline info) "."))) - ;; Create the headline text. - (full-text (org-e-html-format-headline--wrap headline info))) - (cond - ;; Case 1: This is a footnote section: ignore it. - ((org-element-property :footnote-section-p headline) nil) - ;; Case 2. This is a deep sub-tree: export it as a list item. - ;; Also export as items headlines for which no section - ;; format has been found. - ((org-export-low-level-p headline info) ; FIXME (or (not section-fmt)) - ;; Build the real contents of the sub-tree. - (let* ((type (if numberedp 'unordered 'unordered)) ; FIXME - (itemized-body (org-e-html-format-list-item - contents type nil nil full-text))) - (concat - (and (org-export-first-sibling-p headline info) - (org-e-html-begin-plain-list type)) - itemized-body - (and (org-export-last-sibling-p headline info) - (org-e-html-end-plain-list type))))) - ;; Case 3. Standard headline. Export it as a section. - (t - (let* ((extra-class (org-element-property :html-container-class headline)) - (extra-ids (list (org-element-property :custom-id headline) - (org-element-property :id headline))) - (extra-ids - (mapconcat - (lambda (x) - (when x - (let ((id (org-solidify-link-text - (if (org-uuidgen-p x) (concat "ID-" x) x)))) - (format "" id id)))) - extra-ids "")) - (level1 (+ level (1- org-e-html-toplevel-hlevel))) - (id (mapconcat 'number-to-string - (org-export-get-headline-number headline info) "-"))) - (format "
%s%s
\n" - (format "outline-container-%s" id) - (concat (format "outline-%d" level1) (and extra-class " ") - extra-class) - (format "\n%s%s\n" - level1 id extra-ids full-text level1) - contents)))))) - - -;;;; Horizontal Rule - -(defun org-e-html-horizontal-rule (horizontal-rule contents info) - "Transcode an HORIZONTAL-RULE object from Org to HTML. -CONTENTS is nil. INFO is a plist holding contextual information." - (let ((attr (mapconcat #'identity - (org-element-property :attr_html horizontal-rule) - " "))) - (org-e-html--wrap-label horizontal-rule "
\n"))) - - -;;;; Inline Babel Call - -;; Inline Babel Calls are ignored. - - -;;;; Inline Src Block - -(defun org-e-html-inline-src-block (inline-src-block contents info) - "Transcode an INLINE-SRC-BLOCK element from Org to HTML. -CONTENTS holds the contents of the item. INFO is a plist holding -contextual information." - (let* ((org-lang (org-element-property :language inline-src-block)) - (code (org-element-property :value inline-src-block)) - (separator (org-e-html--find-verb-separator code))) - (error "FIXME"))) - - -;;;; Inlinetask - -(defun org-e-html-format-section (text class &optional id) - (let ((extra (concat (when id (format " id=\"%s\"" id))))) - (concat (format "
\n" class extra) text "
\n"))) - -(defun org-e-html-inlinetask (inlinetask contents info) - "Transcode an INLINETASK element from Org to HTML. -CONTENTS holds the contents of the block. INFO is a plist -holding contextual information." - (cond - ;; If `org-e-html-format-inlinetask-function' is provided, call it - ;; with appropriate arguments. - ((functionp org-e-html-format-inlinetask-function) - (let ((format-function - (function* - (lambda (todo todo-type priority text tags - &key contents &allow-other-keys) - (funcall org-e-html-format-inlinetask-function - todo todo-type priority text tags contents))))) - (org-e-html-format-headline--wrap - inlinetask info format-function :contents contents))) - ;; Otherwise, use a default template. - (t (org-e-html--wrap-label - inlinetask - (format - "\n
\n%s
\n%s\n
" - (org-e-html-format-headline--wrap inlinetask info) - contents))))) - - -;;;; Item - -(defun org-e-html-checkbox (checkbox) - (case checkbox (on "[X]") - (off "[ ]") - (trans "[-]") - (t ""))) - -(defun org-e-html-format-list-item (contents type checkbox - &optional term-counter-id - headline) - (concat - (case type - (ordered - (let* ((counter term-counter-id) - (extra (if counter (format " value=\"%s\"" counter) ""))) - (format "" extra))) - (unordered - (let* ((id term-counter-id) - (extra (if id (format " id=\"%s\"" id) ""))) - (concat - (format "" extra) - (when headline (concat headline "
"))))) - (descriptive - (let* ((term term-counter-id)) - (setq term (or term "(no term)")) - (concat (format "
%s
" term) "
")))) - (org-e-html-checkbox checkbox) (and checkbox " ") - contents - (case type - (ordered "") - (unordered "") - (descriptive "
")))) - -(defun org-e-html-item (item contents info) - "Transcode an ITEM element from Org to HTML. -CONTENTS holds the contents of the item. INFO is a plist holding -contextual information." - ;; Grab `:level' from plain-list properties, which is always the - ;; first element above current item. - (let* ((plain-list (org-export-get-parent item info)) - (type (org-element-property :type plain-list)) - (level (org-element-property :level plain-list)) - (counter (org-element-property :counter item)) - (checkbox (org-element-property :checkbox item)) - (tag (let ((tag (org-element-property :tag item))) - (and tag (org-export-secondary-string tag 'e-html info))))) - (org-e-html-format-list-item - contents type checkbox (or tag counter)))) - - -;;;; Keyword - -(defun org-e-html-keyword (keyword contents info) - "Transcode a KEYWORD element from Org to HTML. -CONTENTS is nil. INFO is a plist holding contextual information." - (let ((key (downcase (org-element-property :key keyword))) - (value (org-element-property :value keyword))) - (cond - ((string= key "latex") value) - ((string= key "index") (format "\\index{%s}" value)) - ;; Invisible targets. - ((string= key "target") nil) ; FIXME - ((string= key "toc") - (let ((value (downcase value))) - (cond - ((string-match "\\" value) - (let ((depth (or (and (string-match "[0-9]+" value) - (string-to-number (match-string 0 value))) - (plist-get info :with-toc)))) - (when (wholenump depth) (org-e-html-toc depth info)))) - ((string= "tables" value) "\\listoftables") - ((string= "figures" value) "\\listoffigures") - ((string= "listings" value) - (cond - ;; At the moment, src blocks with a caption are wrapped - ;; into a figure environment. - (t "\\listoffigures"))))))))) - - -;;;; Latex Environment - -(defun org-e-html-format-latex (latex-frag processing-type) - (let* ((cache-relpath - (concat "ltxpng/" (file-name-sans-extension - (file-name-nondirectory (buffer-file-name))))) - (cache-dir (file-name-directory (buffer-file-name ))) - (display-msg "Creating LaTeX Image...")) - - (with-temp-buffer - (insert latex-frag) - (org-format-latex cache-relpath cache-dir nil display-msg - nil nil processing-type) - (buffer-string)))) - -(defun org-e-html-latex-environment (latex-environment contents info) - "Transcode a LATEX-ENVIRONMENT element from Org to HTML. -CONTENTS is nil. INFO is a plist holding contextual information." - (org-e-html--wrap-label - latex-environment - (let ((processing-type (plist-get info :LaTeX-fragments)) - (latex-frag (org-remove-indentation - (org-element-property :value latex-environment))) - (caption (org-e-html--caption/label-string - (org-element-property :caption latex-environment) - (org-element-property :name latex-environment) - info)) - (attr nil) ; FIXME - (label (org-element-property :name latex-environment))) - (cond - ((member processing-type '(t mathjax)) - (org-e-html-format-latex latex-frag 'mathjax)) - ((equal processing-type 'dvipng) - (let* ((formula-link (org-e-html-format-latex - latex-frag processing-type))) - (when (and formula-link - (string-match "file:\\([^]]*\\)" formula-link)) - (org-e-html-format-inline-image - (match-string 1 formula-link) caption label attr t)))) - (t latex-frag))))) - - -;;;; Latex Fragment - -(defun org-e-html-latex-fragment (latex-fragment contents info) - "Transcode a LATEX-FRAGMENT object from Org to HTML. -CONTENTS is nil. INFO is a plist holding contextual information." - (let ((latex-frag (org-element-property :value latex-fragment)) - (processing-type (plist-get info :LaTeX-fragments))) - (case processing-type - ((t mathjax) - (org-e-html-format-latex latex-frag 'mathjax)) - (dvipng - (let* ((formula-link (org-e-html-format-latex - latex-frag processing-type))) - (when (and formula-link - (string-match "file:\\([^]]*\\)" formula-link)) - (org-e-html-format-inline-image - (match-string 1 formula-link))))) - (t latex-frag)))) - -;;;; Line Break - -(defun org-e-html-line-break (line-break contents info) - "Transcode a LINE-BREAK object from Org to HTML. -CONTENTS is nil. INFO is a plist holding contextual information." - "
") - - -;;;; Link - -(defun org-e-html-link--inline-image (link desc info) - "Return HTML code for an inline image. -LINK is the link pointing to the inline image. INFO is a plist -used as a communication channel." - (let* ((type (org-element-property :type link)) - (raw-path (org-element-property :path link)) - (path (cond ((member type '("http" "https")) - (concat type ":" raw-path)) - ((file-name-absolute-p raw-path) - (expand-file-name raw-path)) - (t raw-path))) - (parent (org-export-get-parent-paragraph link info)) - (caption (org-e-html--caption/label-string - (org-element-property :caption parent) - (org-element-property :name parent) - info)) - (label (org-element-property :name parent)) - ;; Retrieve latex attributes from the element around. - (attr (let ((raw-attr - (mapconcat #'identity - (org-element-property :attr_html parent) - " "))) - (unless (string= raw-attr "") raw-attr)))) - ;; Now clear ATTR from any special keyword and set a default - ;; value if nothing is left. - (setq attr (if (not attr) "" (org-trim attr))) - ;; Return proper string, depending on DISPOSITION. - (org-e-html-format-inline-image - path caption label attr (org-e-html-standalone-image-p link info)))) - -(defvar org-e-html-standalone-image-predicate) -(defun org-e-html-standalone-image-p (element info &optional predicate) - "Test if ELEMENT is a standalone image for the purpose HTML export. -INFO is a plist holding contextual information. - -Return non-nil, if ELEMENT is of type paragraph and it's sole -content, save for whitespaces, is a link that qualifies as an -inline image. - -Return non-nil, if ELEMENT is of type link and it's containing -paragraph has no other content save for leading and trailing -whitespaces. - -Return nil, otherwise. - -Bind `org-e-html-standalone-image-predicate' to constrain -paragraph further. For example, to check for only captioned -standalone images, do the following. - - \(setq org-e-html-standalone-image-predicate - \(lambda \(paragraph\) - \(org-element-property :caption paragraph\)\)\) -" - (let ((paragraph (case (org-element-type element) - (paragraph element) - (link (and (org-export-inline-image-p - element org-e-html-inline-image-rules) - (org-export-get-parent element info))) - (t nil)))) - (when paragraph - (assert (eq (org-element-type paragraph) 'paragraph)) - (when (or (not (and (boundp 'org-e-html-standalone-image-predicate) - (functionp org-e-html-standalone-image-predicate))) - (funcall org-e-html-standalone-image-predicate paragraph)) - (let ((contents (org-element-contents paragraph))) - (loop for x in contents - with inline-image-count = 0 - always (cond - ((eq (org-element-type x) 'plain-text) - (not (org-string-nw-p x))) - ((eq (org-element-type x) 'link) - (when (org-export-inline-image-p - x org-e-html-inline-image-rules) - (= (incf inline-image-count) 1))) - (t nil)))))))) - -(defun org-e-html-link (link desc info) - "Transcode a LINK object from Org to HTML. - -DESC is the description part of the link, or the empty string. -INFO is a plist holding contextual information. See -`org-export-data'." - (let* ((type (org-element-property :type link)) - (raw-path (org-element-property :path link)) - ;; Ensure DESC really exists, or set it to nil. - (desc (and (not (string= desc "")) desc)) - (path (cond - ((member type '("http" "https" "ftp" "mailto")) - (concat type ":" raw-path)) - ((string= type "file") - (when (string-match "\\(.+\\)::.+" raw-path) - (setq raw-path (match-string 1 raw-path))) - (if (file-name-absolute-p raw-path) - (concat "file://" (expand-file-name raw-path)) - ;; TODO: Not implemented yet. Concat also: - ;; (org-export-directory :HTML info) - (concat "file://" raw-path))) - (t raw-path))) - protocol) - (cond - ;; Image file. - ((and (or (eq t org-e-html-inline-images) - (and org-e-html-inline-images (not desc))) - (org-export-inline-image-p link org-e-html-inline-image-rules)) - (org-e-html-link--inline-image link desc info)) - ;; Radioed target: Target's name is obtained from original raw - ;; link. Path is parsed and transcoded in order to have a proper - ;; display of the contents. - ((string= type "radio") - (format "
%s" - (org-export-solidify-link-text path) - (org-export-secondary-string - (org-element-parse-secondary-string - path (cdr (assq 'radio-target org-element-object-restrictions))) - 'e-html info))) - ;; Links pointing to an headline: Find destination and build - ;; appropriate referencing command. - ((member type '("custom-id" "fuzzy" "id")) - (let ((destination (if (string= type "fuzzy") - (org-export-resolve-fuzzy-link link info) - (org-export-resolve-id-link link info)))) - (case (org-element-type destination) - ;; Fuzzy link points nowhere. - ('nil - (format "%s" - (or desc (org-export-secondary-string - (org-element-property :raw-link link) - 'e-html info)))) - ;; Fuzzy link points to an invisible target. - (keyword nil) - ;; LINK points to an headline. If headlines are numbered - ;; and the link has no description, display headline's - ;; number. Otherwise, display description or headline's - ;; title. - (headline - (let* ((headline-no (org-export-get-headline-number destination info)) - (label (format "sec-%s" (mapconcat 'number-to-string - headline-no "-"))) - (section-no (mapconcat 'number-to-string headline-no "."))) - (setq desc - (cond - (desc desc) - ((plist-get info :section-numbers) section-no) - (t (org-export-secondary-string - (org-element-property :title destination) - 'e-html info)))) - (format "%s" label desc))) - ;; Fuzzy link points to a target. Do as above. - (otherwise - (let ((path (org-export-solidify-link-text path)) number) - (unless desc - (setq number (cond - ((org-e-html-standalone-image-p destination info) - (org-export-get-ordinal - (assoc 'link (org-element-contents destination)) - info 'link 'org-e-html-standalone-image-p)) - (t (org-export-get-ordinal destination info)))) - (setq desc (when number - (if (atom number) (number-to-string number) - (mapconcat 'number-to-string number "."))))) - (format "%s" path (or desc "FIXME"))))))) - ;; Coderef: replace link with the reference name or the - ;; equivalent line number. - ((string= type "coderef") - (let ((fragment (concat "coderef-" path))) - (format "%s" fragment - (format (concat "class=\"coderef\"" - " onmouseover=\"CodeHighlightOn(this, '%s');\"" - " onmouseout=\"CodeHighlightOff(this, '%s');\"") - fragment fragment) - (format (org-export-get-coderef-format path (or desc "%s")) - (org-export-resolve-coderef path info))))) - ;; Link type is handled by a special function. - ((functionp (setq protocol (nth 2 (assoc type org-link-protocols)))) - (funcall protocol (org-link-unescape path) desc 'html)) - ;; External link with a description part. - ((and path desc) (format "%s" path desc)) - ;; External link without a description part. - (path (format "%s" path path)) - ;; No path, only description. Try to do something useful. - (t (format "%s" desc))))) - - -;;;; Babel Call - -;; Babel Calls are ignored. - - -;;;; Macro - -(defun org-e-html-macro (macro contents info) - "Transcode a MACRO element from Org to HTML. -CONTENTS is nil. INFO is a plist holding contextual information." - ;; Use available tools. - (org-export-expand-macro macro info)) - - -;;;; Paragraph - -(defun org-e-html-paragraph (paragraph contents info) - "Transcode a PARAGRAPH element from Org to HTML. -CONTENTS is the contents of the paragraph, as a string. INFO is -the plist used as a communication channel." - (let* ((style nil) ; FIXME - (class (cdr (assoc style '((footnote . "footnote") - (verse . nil))))) - (extra (if class (format " class=\"%s\"" class) "")) - (parent (org-export-get-parent paragraph info))) - (cond - ((and (equal (car parent) 'item) - (= (org-element-property :begin paragraph) - (org-element-property :contents-begin parent))) - ;; leading paragraph in a list item have no tags - contents) - ((org-e-html-standalone-image-p paragraph info) - ;; standalone image - contents) - (t (format "\n\n%s\n

" extra contents))))) - - -;;;; Plain List - -(defun org-e-html-begin-plain-list (type &optional arg1) - (case type - (ordered - (format "" (if arg1 ; FIXME - (format " start=\"%d\"" arg1) - ""))) - (unordered "
    ") - (descriptive "
    "))) - -(defun org-e-html-end-plain-list (type) - (case type - (ordered "") - (unordered "
") - (descriptive ""))) - -(defun org-e-html-plain-list (plain-list contents info) - "Transcode a PLAIN-LIST element from Org to HTML. -CONTENTS is the contents of the list. INFO is a plist holding -contextual information." - (let* (arg1 ;; FIXME - (type (org-element-property :type plain-list)) - (attr (mapconcat #'identity - (org-element-property :attr_html plain-list) - " "))) - (org-e-html--wrap-label - plain-list (format "%s\n%s%s" - (org-e-html-begin-plain-list type) - contents (org-e-html-end-plain-list type))))) - -;;;; Plain Text - -(defun org-e-html-convert-special-strings (string) - "Convert special characters in STRING to HTML." - (let ((all org-e-html-special-string-regexps) - e a re rpl start) - (while (setq a (pop all)) - (setq re (car a) rpl (cdr a) start 0) - (while (string-match re string start) - (setq string (replace-match rpl t nil string)))) - string)) - -(defun org-e-html-encode-plain-text (s) - "Convert plain text characters to HTML equivalent. -Possible conversions are set in `org-export-html-protect-char-alist'." - (let ((cl org-e-html-protect-char-alist) c) - (while (setq c (pop cl)) - (let ((start 0)) - (while (string-match (car c) s start) - (setq s (replace-match (cdr c) t t s) - start (1+ (match-beginning 0)))))) - s)) - -(defun org-e-html-plain-text (text info) - "Transcode a TEXT string from Org to HTML. -TEXT is the string to transcode. INFO is a plist holding -contextual information." - (setq text (org-e-html-encode-plain-text text)) - ;; Protect %, #, &, $, ~, ^, _, { and }. - ;; (while (string-match "\\([^\\]\\|^\\)\\([%$#&{}~^_]\\)" text) - ;; (setq text - ;; (replace-match (format "\\%s" (match-string 2 text)) nil t text 2))) - ;; Protect \ - ;; (setq text (replace-regexp-in-string - ;; "\\(?:[^\\]\\|^\\)\\(\\\\\\)\\(?:[^%$#&{}~^_\\]\\|$\\)" - ;; "$\\backslash$" text nil t 1)) - ;; HTML into \HTML{} and TeX into \TeX{}. - ;; (let ((case-fold-search nil) - ;; (start 0)) - ;; (while (string-match "\\<\\(\\(?:La\\)?TeX\\)\\>" text start) - ;; (setq text (replace-match - ;; (format "\\%s{}" (match-string 1 text)) nil t text) - ;; start (match-end 0)))) - ;; Handle quotation marks - ;; (setq text (org-e-html--quotation-marks text info)) - ;; Convert special strings. - ;; (when (plist-get info :with-special-strings) - ;; (while (string-match (regexp-quote "...") text) - ;; (setq text (replace-match "\\ldots{}" nil t text)))) - (when (plist-get info :with-special-strings) - (setq text (org-e-html-convert-special-strings text))) - ;; Handle break preservation if required. - (when (plist-get info :preserve-breaks) - (setq text (replace-regexp-in-string "\\(\\\\\\\\\\)?[ \t]*\n" " \\\\\\\\\n" - text))) - ;; Return value. - text) - - -;;;; Property Drawer - -(defun org-e-html-property-drawer (property-drawer contents info) - "Transcode a PROPERTY-DRAWER element from Org to HTML. -CONTENTS is nil. INFO is a plist holding contextual -information." - ;; The property drawer isn't exported but we want separating blank - ;; lines nonetheless. - "") - - -;;;; Quote Block - -(defun org-e-html-quote-block (quote-block contents info) - "Transcode a QUOTE-BLOCK element from Org to HTML. -CONTENTS holds the contents of the block. INFO is a plist -holding contextual information." - (org-e-html--wrap-label - quote-block (format "
\n%s
" contents))) - - -;;;; Quote Section - -(defun org-e-html-quote-section (quote-section contents info) - "Transcode a QUOTE-SECTION element from Org to HTML. -CONTENTS is nil. INFO is a plist holding contextual information." - (let ((value (org-remove-indentation - (org-element-property :value quote-section)))) - (when value (format "
\n%s
" value)))) - - -;;;; Section - -(defun org-e-html-section (section contents info) ; FIXME - "Transcode a SECTION element from Org to HTML. -CONTENTS holds the contents of the section. INFO is a plist -holding contextual information." - (let ((parent (org-export-get-parent-headline section info))) - ;; Before first headline: no container, just return CONTENTS. - (if (not parent) contents - ;; Get div's class and id references. - (let ((class-num (+ (org-export-get-relative-level parent info) - (1- org-e-html-toplevel-hlevel))) - (id-num - (mapconcat - 'number-to-string - (org-export-get-headline-number parent info) "-"))) - ;; Build return value. - (format "
\n%s
" - class-num id-num contents))))) - -;;;; Radio Target - -(defun org-e-html-radio-target (radio-target text info) - "Transcode a RADIO-TARGET object from Org to HTML. -TEXT is the text of the target. INFO is a plist holding -contextual information." - (let ((id (org-export-solidify-link-text - (org-element-property :raw-value radio-target)))) - (format "%s" id id text))) - - -;;;; Special Block - -(defun org-e-html-special-block (special-block contents info) - "Transcode a SPECIAL-BLOCK element from Org to HTML. -CONTENTS holds the contents of the block. INFO is a plist -holding contextual information." - (let ((type (downcase (org-element-property :type special-block)))) - (org-e-html--wrap-label - special-block - (format "\\begin{%s}\n%s\\end{%s}" type contents type)))) - - -;;;; Src Block - -(defun org-e-html-src-block (src-block contents info) - "Transcode a SRC-BLOCK element from Org to HTML. -CONTENTS holds the contents of the item. INFO is a plist holding -contextual information." - (let* ((lang (org-element-property :language src-block)) - (caption (org-element-property :caption src-block)) - (label (org-element-property :name src-block)) - (caption-str (org-e-html--caption/label-string caption label info)) - (attr (mapconcat #'identity - (org-element-property :attr_html src-block) - " ")) - ;; (switches (org-element-property :switches src-block)) - (switches nil) ; FIXME - (textarea-p (and switches (string-match "-t\\>" switches))) - (code (org-e-html-format-code src-block info))) - (cond - (lang (format - "\n
\n%s%s\n
" - (if (not caption) "" - (format "" caption-str)) - (format "\n
%s\n
" lang code))) - (textarea-p - (let ((cols (if (not (string-match "-w[ \t]+\\([0-9]+\\)" switches)) - 80 (string-to-number (match-string 1 switches)))) - (rows (if (string-match "-h[ \t]+\\([0-9]+\\)" switches) - (string-to-number (match-string 1 switches)) - (org-count-lines code)))) - (format - "\n

\n\n

" - cols rows code))) - (t (format "\n
\n%s\n
" code))))) - -;;;; Statistics Cookie - -(defun org-e-html-statistics-cookie (statistics-cookie contents info) - "Transcode a STATISTICS-COOKIE object from Org to HTML. -CONTENTS is nil. INFO is a plist holding contextual information." - (let ((cookie-value (org-element-property :value statistics-cookie))) - (format "%s" cookie-value))) - - -;;;; Subscript - -(defun org-e-html-subscript (subscript contents info) - "Transcode a SUBSCRIPT object from Org to HTML. -CONTENTS is the contents of the object. INFO is a plist holding -contextual information." - (format "%s" contents)) - - -;;;; Superscript - -(defun org-e-html-superscript (superscript contents info) - "Transcode a SUPERSCRIPT object from Org to HTML. -CONTENTS is the contents of the object. INFO is a plist holding -contextual information." - (format "%s" contents)) - - -;;;; Table - -(defun org-e-html-begin-table (caption label attributes) - (let* ((html-table-tag (or (plist-get info :html-table-tag) ; FIXME - org-e-html-table-tag)) - (html-table-tag - (org-e-html-splice-attributes html-table-tag attributes))) - (when label - (setq html-table-tag - (org-e-html-splice-attributes - html-table-tag - (format "id=\"%s\"" (org-solidify-link-text label))))) - (concat "\n" html-table-tag - (format "\n%s" (or caption ""))))) - -(defun org-e-html-end-table () - "\n") - -(defun org-e-html-format-table-cell (text r c horiz-span) - (let ((cell-style-cookie - (if org-e-html-table-align-individual-fields - (format (if (and (boundp 'org-e-html-format-table-no-css) - org-e-html-format-table-no-css) - " align=\"%s\"" " class=\"%s\"") - (or (aref (plist-get table-info :alignment) c) "left")) ""))) ;; FIXME - (cond - (org-e-html-table-cur-rowgrp-is-hdr - (concat - (format (car org-e-html-table-header-tags) "col" cell-style-cookie) - text (cdr org-e-html-table-header-tags))) - ((and (= c 0) org-e-html-table-use-header-tags-for-first-column) - (concat - (format (car org-e-html-table-header-tags) "row" cell-style-cookie) - text (cdr org-e-html-table-header-tags))) - (t - (concat - (format (car org-e-html-table-data-tags) cell-style-cookie) - text (cdr org-e-html-table-data-tags)))))) - -(defun org-e-html-format-table-row (row) - (concat (eval (car org-e-html-table-row-tags)) row - (eval (cdr org-e-html-table-row-tags)))) - -(defun org-e-html-table-row (fields &optional text-for-empty-fields) - (incf org-e-html-table-rownum) - (let ((i -1)) - (org-e-html-format-table-row - (mapconcat - (lambda (x) - (when (and (string= x "") text-for-empty-fields) - (setq x text-for-empty-fields)) - (incf i) - (let (horiz-span) - (org-e-html-format-table-cell - x org-e-html-table-rownum i (or horiz-span 0)))) - fields "\n")))) - -(defun org-e-html-end-table-rowgroup () - (when org-e-html-table-rowgrp-open - (setq org-e-html-table-rowgrp-open nil) - (if org-e-html-table-cur-rowgrp-is-hdr "" ""))) - -(defun org-e-html-begin-table-rowgroup (&optional is-header-row) - (concat - (when org-e-html-table-rowgrp-open - (org-e-html-end-table-rowgroup)) - (progn - (setq org-e-html-table-rowgrp-open t) - (setq org-e-html-table-cur-rowgrp-is-hdr is-header-row) - (if is-header-row "" "")))) - -(defun org-e-html-table-preamble () - (let ((colgroup-vector (plist-get table-info :column-groups)) ;; FIXME - c gr colgropen preamble) - (unless (aref colgroup-vector 0) - (setf (aref colgroup-vector 0) 'start)) - (dotimes (c columns-number preamble) - (setq gr (aref colgroup-vector c)) - (setq preamble - (concat - preamble - (when (memq gr '(start start-end)) - (prog1 (if colgropen "\n" "\n") - (setq colgropen t))) - (let* ((colalign-vector (plist-get table-info :alignment)) ;; FIXME - (align (cdr (assoc (aref colalign-vector c) - '(("l" . "left") - ("r" . "right") - ("c" . "center"))))) - (alignspec (if (and (boundp 'org-e-html-format-table-no-css) - org-e-html-format-table-no-css) - " align=\"%s\"" " class=\"%s\"")) - (extra (format alignspec align))) - (format "" extra)) - (when (memq gr '(end start-end)) - (setq colgropen nil) - "")))) - (concat preamble (if colgropen "")))) - -(defun org-e-html-list-table (lines caption label attributes) - (setq lines (org-e-html-org-table-to-list-table lines)) - (let* ((splice nil) head - (org-e-html-table-rownum -1) - i (cnt 0) - fields line - org-e-html-table-cur-rowgrp-is-hdr - org-e-html-table-rowgrp-open - n - (org-lparse-table-style 'org-table) - org-lparse-table-is-styled) - (cond - (splice - (setq org-lparse-table-is-styled nil) - (mapconcat 'org-e-html-table-row lines "\n")) - (t - (setq org-lparse-table-is-styled t) - - (concat - (org-e-html-begin-table caption label attributes) - (org-e-html-table-preamble) - (org-e-html-begin-table-rowgroup head) - - (mapconcat - (lambda (line) - (cond - ((equal line 'hline) (org-e-html-begin-table-rowgroup)) - (t (org-e-html-table-row line)))) - lines "\n") - - (org-e-html-end-table-rowgroup) - (org-e-html-end-table)))))) - -(defun org-e-html-transcode-table-row (row) - (if (string-match org-table-hline-regexp row) 'hline - (mapcar - (lambda (cell) - (org-export-secondary-string - (let ((cell (org-element-parse-secondary-string - cell - (cdr (assq 'table org-element-string-restrictions))))) - cell) - 'e-html info)) - (org-split-string row "[ \t]*|[ \t]*")))) - -(defun org-e-html-org-table-to-list-table (lines &optional splice) - "Convert org-table to list-table. -LINES is a list of the form (ROW1 ROW2 ROW3 ...) where each -element is a `string' representing a single row of org-table. -Thus each ROW has vertical separators \"|\" separating the table -fields. A ROW could also be a row-group separator of the form -\"|---...|\". Return a list of the form (ROW1 ROW2 ROW3 -...). ROW could either be symbol `'hline' or a list of the -form (FIELD1 FIELD2 FIELD3 ...) as appropriate." - (let (line lines-1) - (cond - (splice - (while (setq line (pop lines)) - (unless (string-match "^[ \t]*|-" line) - (push (org-e-html-transcode-table-row line) lines-1)))) - (t (while (setq line (pop lines)) - (cond - ((string-match "^[ \t]*|-" line) - (when lines (push 'hline lines-1))) - (t (push (org-e-html-transcode-table-row line) lines-1)))))) - (nreverse lines-1))) - -(defun org-e-html-table-table (raw-table) - (require 'table) - (with-current-buffer (get-buffer-create "*org-export-table*") - (erase-buffer)) - (let ((output (with-temp-buffer - (insert raw-table) - (goto-char 1) - (re-search-forward "^[ \t]*|[^|]" nil t) - (table-generate-source 'html "*org-export-table*") - (with-current-buffer "*org-export-table*" - (org-trim (buffer-string)))))) - (kill-buffer (get-buffer "*org-export-table*")) - output)) - -(defun org-e-html-table (table contents info) - "Transcode a TABLE element from Org to HTML. -CONTENTS is nil. INFO is a plist holding contextual information." - (let* ((label (org-element-property :name table)) - (caption (org-e-html--caption/label-string - (org-element-property :caption table) label info)) - (attr (mapconcat #'identity - (org-element-property :attr_html table) - " ")) - (raw-table (org-element-property :raw-table table)) - (table-type (org-element-property :type table))) - (case table-type - (table.el - (org-e-html-table-table raw-table)) - (t - (let* ((table-info (org-export-table-format-info raw-table)) - (columns-number (length (plist-get table-info :alignment))) - (lines (org-split-string - (org-export-clean-table - raw-table (plist-get table-info :special-column-p)) "\n"))) - (org-e-html-list-table lines caption label attr)))))) - - -;;;; Target - -(defun org-e-html-target (target contents info) - "Transcode a TARGET object from Org to HTML. -CONTENTS is nil. INFO is a plist holding contextual -information." - (let ((id (org-export-solidify-link-text - (org-element-property :value target)))) - (format "" id id))) - - -;;;; Time-stamp - -(defun org-e-html-time-stamp (time-stamp contents info) - "Transcode a TIME-STAMP object from Org to HTML. -CONTENTS is nil. INFO is a plist holding contextual -information." - (let ((value (org-element-property :value time-stamp)) - (type (org-element-property :type time-stamp)) - (appt-type (org-element-property :appt-type time-stamp))) - (setq value (org-translate-time - (org-export-secondary-string value 'e-html info))) - (setq appt-type (case appt-type - (scheduled org-scheduled-string) - (deadline org-deadline-string) - (closed org-closed-string))) - (format "%s%s" - (if (not appt-type) "" - (format "%s " appt-type)) - (format "%s" value)))) - - -;;;; Verbatim - -(defun org-e-html-verbatim (verbatim contents info) - "Transcode a VERBATIM object from Org to HTML. -CONTENTS is nil. INFO is a plist used as a communication -channel." - (org-e-html-emphasis - verbatim (org-element-property :value verbatim) info)) - - -;;;; Verse Block - -(defun org-e-html-verse-block (verse-block contents info) - "Transcode a VERSE-BLOCK element from Org to HTML. -CONTENTS is nil. INFO is a plist holding contextual information." - ;; Replace each newline character with line break. Also replace - ;; each blank line with a line break. - (setq contents (replace-regexp-in-string - "^ *\\\\\\\\$" "
\n" - (replace-regexp-in-string - "\\(\\\\\\\\\\)?[ \t]*\n" "
\n" - (org-remove-indentation - (org-export-secondary-string - (org-element-property :value verse-block) - 'e-html info))))) - ;; Replace each white space at beginning of a line with a - ;; non-breaking space. - (while (string-match "^[ \t]+" contents) - (let* ((num-ws (length (match-string 0 contents))) - (ws (let (out) (dotimes (i num-ws out) - (setq out (concat out " ")))))) - (setq contents (replace-match ws nil t contents)))) - (org-e-html--wrap-label - verse-block (format "

\n%s

" contents))) - - - - -;;; Filter Functions - -;;;; Filter Settings - -(defconst org-e-html-filters-alist - '((:filter-final-output . org-e-html-final-function)) - "Alist between filters keywords and back-end specific filters. -See `org-export-filters-alist' for more information.") - - -;;;; Filters - -(defun org-e-html-final-function (contents backend info) - (if (not org-e-html-pretty-output) contents - (with-temp-buffer - (nxml-mode) - (insert contents) - (indent-region (point-min) (point-max)) - (buffer-substring-no-properties (point-min) (point-max))))) - - -;;; Interactive functions - -(defun org-e-html-export-to-html - (&optional subtreep visible-only body-only ext-plist pub-dir) - "Export current buffer to a HTML file. - -If narrowing is active in the current buffer, only export its -narrowed part. - -If a region is active, export that region. - -When optional argument SUBTREEP is non-nil, export the sub-tree -at point, extracting information from the headline properties -first. - -When optional argument VISIBLE-ONLY is non-nil, don't export -contents of hidden elements. - -When optional argument BODY-ONLY is non-nil, only write code -between \"\\begin{document}\" and \"\\end{document}\". - -EXT-PLIST, when provided, is a property list with external -parameters overriding Org default settings, but still inferior to -file-local settings. - -When optional argument PUB-DIR is set, use it as the publishing -directory. - -Return output file's name." - (interactive) - - ;; FIXME - (with-current-buffer (get-buffer-create "*debug*") - (erase-buffer)) - (let* ((extension (concat "." org-e-html-extension)) - (file (org-export-output-file-name extension subtreep pub-dir))) - (org-export-to-file - 'e-html file subtreep visible-only body-only ext-plist))) - - - -;;; FIXMES, TODOS, FOR REVIEW etc - -;;;; org-format-table-html -;;;; org-format-org-table-html -;;;; org-format-table-table-html -;;;; org-table-number-fraction -;;;; org-table-number-regexp -;;;; org-e-html-table-caption-above - -;;;; org-whitespace -;;;; "%s" -;;;; Remove display properties - -;;;; org-e-html-with-timestamp -;;;; org-e-html-html-helper-timestamp - -;;;; org-export-as-html-and-open -;;;; org-export-as-html-batch -;;;; org-export-as-html-to-buffer -;;;; org-replace-region-by-html -;;;; org-export-region-as-html -;;;; org-export-as-html - -;;;; (org-export-directory :html opt-plist) -;;;; (plist-get opt-plist :html-extension) -;;;; org-e-html-toplevel-hlevel -;;;; org-e-html-special-string-regexps -;;;; org-e-html-coding-system -;;;; org-e-html-coding-system -;;;; org-e-html-inline-images -;;;; org-e-html-inline-image-extensions -;;;; org-e-html-protect-char-alist -;;;; org-e-html-table-use-header-tags-for-first-column -;;;; org-e-html-todo-kwd-class-prefix -;;;; org-e-html-tag-class-prefix -;;;; org-e-html-footnote-separator - -;;;; org-export-preferred-target-alist -;;;; org-solidify-link-text -;;;; class for anchors -;;;; org-export-with-section-numbers, body-only -;;;; org-export-mark-todo-in-toc - -(provide 'org-e-html) -;;; org-e-html.el ends here diff --git a/EXPERIMENTAL/org-e-odt.el b/EXPERIMENTAL/org-e-odt.el deleted file mode 100644 index 9b59954..0000000 --- a/EXPERIMENTAL/org-e-odt.el +++ /dev/null @@ -1,4589 +0,0 @@ -;;; org-e-odt.el --- OpenDocument Text exporter for Org-mode - -;; Copyright (C) 2010-2012 Free Software Foundation, Inc. - -;; Author: Jambunathan K -;; Keywords: outlines, hypermedia, calendar, wp -;; Homepage: http://orgmode.org - -;; This file is part of GNU Emacs. - -;; GNU Emacs is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;;; Code: -(eval-when-compile - (require 'cl)) - -(defgroup org-export-e-odt nil - "Options specific for ODT export of Org-mode files." - :tag "Org Export ODT" - :group 'org-export - :version "24.1") - -;; FIXMES -;; org-export-preprocess-after-blockquote-hook -;; org-export-e-odt-preprocess-latex-fragments -;; org-export-as-e-odt-and-open -;; org-export-as-e-odt-batch -;; org-export-as-e-odt - -(defun org-e-odt-get-style-name-for-entity (category &optional entity) - (let ((entity (or entity 'default))) - (or - (cdr (assoc entity (cdr (assoc category - org-export-e-odt-org-styles-alist)))) - (cdr (assoc entity (cdr (assoc category - org-export-e-odt-default-org-styles-alist)))) - (error "Cannot determine style name for entity %s of type %s" - entity category)))) - - -;; Following variable is let bound when `org-do-lparse' is in -;; progress. See org-html.el. - -(defun org-e-odt-format-preamble (info) - (let* ((title (plist-get info :title)) - (author (plist-get info :author)) - (date (plist-get info :date)) - (iso-date (org-e-odt-format-date date)) - (date (org-e-odt-format-date date "%d %b %Y")) - (email (plist-get info :email)) - ;; switch on or off above vars based on user settings - (author (and (plist-get info :with-author) (or author email))) - (email (and (plist-get info :with-email) email)) - ;; (date (and (plist-get info :time-stamp-file) date)) - ) - (concat - ;; title - (when title - (concat - (org-e-odt-format-stylized-paragraph - 'title (format "\n%s" title)) - ;; separator - "\n")) - (cond - ((and author (not email)) - ;; author only - (concat - (org-e-odt-format-stylized-paragraph - 'subtitle - (format "%s" author)) - ;; separator - "\n")) - ((and author email) - ;; author and email - (concat - (org-e-odt-format-stylized-paragraph - 'subtitle - (org-e-odt-format-link - (format "%s" author) - (concat "mailto:" email))) - ;; separator - "\n"))) - ;; date - (when date - (concat - (org-e-odt-format-stylized-paragraph - 'subtitle - (org-odt-format-tags - '("" - . "") - date "N75" iso-date)) - ;; separator - ""))))) - -(defun org-e-odt-begin-section (style &optional name) - (let ((default-name (car (org-e-odt-add-automatic-style "Section")))) - (format "" - style (or name default-name)))) - -(defun org-e-odt-end-section () - "") - -(defun org-e-odt-begin-paragraph (&optional style) - (format "" (org-e-odt-get-extra-attrs-for-paragraph-style style))) - -(defun org-e-odt-end-paragraph () - "") - -(defun org-e-odt-get-extra-attrs-for-paragraph-style (style) - (let (style-name) - (setq style-name - (cond - ((stringp style) style) - ((symbolp style) (org-e-odt-get-style-name-for-entity - 'paragraph style)))) - (unless style-name - (error "Don't know how to handle paragraph style %s" style)) - (format " text:style-name=\"%s\"" style-name))) - -(defun org-e-odt-format-stylized-paragraph (style text) - (format "\n%s" - (org-e-odt-get-extra-attrs-for-paragraph-style style) - text)) - -(defun org-e-odt-format-author (&optional author ) - (when (setq author (or author (plist-get org-lparse-opt-plist :author))) - (format "%s" author))) - -(defun org-e-odt-format-date (&optional org-ts fmt) - (save-match-data - (let* ((time - (and (stringp org-ts) - (string-match org-ts-regexp0 org-ts) - (apply 'encode-time - (org-fix-decoded-time - (org-parse-time-string (match-string 0 org-ts) t))))) - date) - (cond - (fmt (format-time-string fmt time)) - (t (setq date (format-time-string "%Y-%m-%dT%H:%M:%S%z" time)) - (format "%s:%s" (substring date 0 -2) (substring date -2))))))) - -(defun org-e-odt-begin-annotation (&optional author date) - (concat - "\n" - (and author (org-e-odt-format-author author)) - (org-e-odt-format-tags - '("" . "") - (org-e-odt-format-date - (or date (plist-get org-lparse-opt-plist :date)))) - (org-e-odt-begin-paragraph))) - -(defun org-e-odt-end-annotation () - "") - -(defun org-e-odt-begin-plain-list (ltype) - (let* ((style-name (org-e-odt-get-style-name-for-entity 'list ltype)) - (extra (concat - ;; (if (or org-lparse-list-table-p - ;; (and (= 1 (length org-lparse-list-stack)) - ;; (null org-e-odt-list-stack-stashed))) - ;; " text:continue-numbering=\"false\"" - ;; " text:continue-numbering=\"true\"") - - " text:continue-numbering=\"true\"" - - (when style-name - (format " text:style-name=\"%s\"" style-name))))) - (case ltype - ((ordered unordered descriptive) - (concat - ;; (org-e-odt-end-paragraph) - (format "" extra))) - (t (error "Unknown list type: %s" ltype))))) - -(defun org-e-odt-end-plain-list (ltype) - (if ltype "" - (error "Unknown list type: %s" ltype))) - -(defun org-e-odt-begin-list-item (ltype &optional arg headline) - (case ltype - (ordered - (assert (not headline) t) - (let* ((counter arg) (extra "")) - (concat "" ;; (org-e-odt-begin-paragraph) - ) - ;; (if (= (length org-lparse-list-stack) - ;; (length org-e-odt-list-stack-stashed)) - ;; "" "") - )) - (unordered - (let* ((id arg) (extra "")) - (concat - "" - ;; (org-e-odt-begin-paragraph) - (if headline (org-e-odt-format-target headline id) - (org-e-odt-format-bookmark "" id))) - ;; (if (= (length org-lparse-list-stack) - ;; (length org-e-odt-list-stack-stashed)) - ;; "" "") - )) - (descriptive - (assert (not headline) t) - (let ((term (or arg "(no term)"))) - (concat - (org-e-odt-format-tags - '("" . "") - (org-e-odt-format-stylized-paragraph 'definition-term term)) - (org-e-odt-begin-list-item 'unordered) - (org-e-odt-begin-plain-list 'descriptive) - (org-e-odt-begin-list-item 'unordered)))) - (t (error "Unknown list type")))) - -(defun org-e-odt-end-list-item (ltype) - (case ltype - ((ordered unordered) - ;; (org-lparse-insert-tag - ;; (if (= (length org-lparse-list-stack) - ;; (length org-e-odt-list-stack-stashed)) - ;; (prog1 "" - ;; (setq org-e-odt-list-stack-stashed nil)) - ;; "") - "" - ;; ) - ) - (descriptive - (concat - (org-e-odt-end-list-item 'unordered) - (org-e-odt-end-plain-list 'descriptive) - (org-e-odt-end-list-item 'unordered) - )) - (t (error "Unknown list type")))) - -(defun org-e-odt-discontinue-list () - (let ((stashed-stack org-lparse-list-stack)) - (loop for list-type in stashed-stack - do (org-lparse-end-list-item-1 list-type) - (org-lparse-end-list list-type)) - (setq org-e-odt-list-stack-stashed stashed-stack))) - -(defun org-e-odt-continue-list () - (setq org-e-odt-list-stack-stashed (nreverse org-e-odt-list-stack-stashed)) - (loop for list-type in org-e-odt-list-stack-stashed - do (org-lparse-begin-list list-type) - (org-lparse-begin-list-item list-type))) - -(defun org-e-odt-write-automatic-styles () - "Write automatic styles to \"content.xml\"." - (with-current-buffer - (find-file-noselect (expand-file-name "content.xml") t) - ;; position the cursor - (goto-char (point-min)) - (re-search-forward " " nil t) - (goto-char (match-beginning 0)) - ;; write automatic table styles - (loop for (style-name props) in - (plist-get org-e-odt-automatic-styles 'Table) do - (when (setq props (or (plist-get props :rel-width) 96)) - (insert (format org-e-odt-table-style-format style-name props)))))) - -(defun org-e-odt-add-automatic-style (object-type &optional object-props) - "Create an automatic style of type OBJECT-TYPE with param OBJECT-PROPS. -OBJECT-PROPS is (typically) a plist created by passing -\"#+ATTR_ODT: \" option of the object in question to -`org-lparse-get-block-params'. - -Use `org-e-odt-object-counters' to generate an automatic -OBJECT-NAME and STYLE-NAME. If OBJECT-PROPS is non-nil, add a -new entry in `org-e-odt-automatic-styles'. Return (OBJECT-NAME -. STYLE-NAME)." - (assert (stringp object-type)) - (let* ((object (intern object-type)) - (seqvar object) - (seqno (1+ (or (plist-get org-e-odt-object-counters seqvar) 0))) - (object-name (format "%s%d" object-type seqno)) style-name) - (setq org-e-odt-object-counters - (plist-put org-e-odt-object-counters seqvar seqno)) - (when object-props - (setq style-name (format "Org%s" object-name)) - (setq org-e-odt-automatic-styles - (plist-put org-e-odt-automatic-styles object - (append (list (list style-name object-props)) - (plist-get org-e-odt-automatic-styles object))))) - (cons object-name style-name))) - -(defun org-e-odt-format-table-columns () - (let* ((num-cols (length (plist-get table-info :alignment))) - (col-nos (loop for i from 0 below num-cols collect i)) - (levels ) - (col-widths (plist-get table-info :width)) - (style (or (nth 1 org-e-odt-table-style-spec) "OrgTable"))) - (mapconcat - (lambda (c) - (let* ((width (or (and org-lparse-table-is-styled (aref col-widths c)) - 0))) - (org-e-odt-make-string - (1+ width) - (org-e-odt-format-tags - "" "" style)))) - col-nos "\n"))) - - -(defun org-e-odt-begin-table (caption label attributes) - ;; (setq org-e-odt-table-indentedp (not (null org-lparse-list-stack))) - (setq org-e-odt-table-indentedp nil) ; FIXME - (when org-e-odt-table-indentedp - ;; Within the Org file, the table is appearing within a list item. - ;; OpenDocument doesn't allow table to appear within list items. - ;; Temporarily terminate the list, emit the table and then - ;; re-continue the list. - (org-e-odt-discontinue-list) - ;; Put the Table in an indented section. - (let ((level (length org-e-odt-list-stack-stashed))) - (org-e-odt-begin-section (format "OrgIndentedSection-Level-%d" level)))) - (setq attributes (org-lparse-get-block-params attributes)) - (setq org-e-odt-table-style (plist-get attributes :style)) - (setq org-e-odt-table-style-spec - (assoc org-e-odt-table-style org-export-e-odt-table-styles)) - (concat - (org-e-odt-format-stylized-paragraph - 'table (org-e-odt-format-entity-caption label caption "__Table__")) - (let ((name-and-style (org-e-odt-add-automatic-style "Table" attributes))) - (format - "\n\n" - (car name-and-style) (or (nth 1 org-e-odt-table-style-spec) - (cdr name-and-style) "OrgTable"))) - (org-e-odt-format-table-columns) "\n") - - ;; (org-e-html-pp table-info) - - ) - -(defun org-e-odt-end-table () - (concat - "" - ;; (when org-e-odt-table-indentedp - ;; (org-e-odt-end-section) - ;; (org-e-odt-continue-list)) - )) - -(defun org-e-odt-begin-table-rowgroup (&optional is-header-row) - (prog1 - (concat (when org-e-odt-table-rowgrp-open - (org-e-odt-end-table-rowgroup)) - (if is-header-row "" - "")) - (setq org-e-odt-table-rowgrp-open t) - (setq org-e-odt-table-cur-rowgrp-is-hdr is-header-row))) - -(defun org-e-odt-end-table-rowgroup () - (when org-e-odt-table-rowgrp-open - (setq org-e-odt-table-rowgrp-open nil) - (if org-e-odt-table-cur-rowgrp-is-hdr - "" ""))) - -(defun org-e-odt-format-table-row (row) - (org-e-odt-format-tags - '("" . "") row)) - -(defun org-e-odt-get-column-alignment (c) - (let ((colalign-vector (plist-get table-info :alignment))) - ;; FIXME - (assoc-default (aref colalign-vector c) - '(("l" . "left") - ("r" . "right") - ("c" . "center"))))) - -(defun org-e-odt-get-table-cell-styles (r c &optional style-spec) - "Retrieve styles applicable to a table cell. -R and C are (zero-based) row and column numbers of the table -cell. STYLE-SPEC is an entry in `org-export-e-odt-table-styles' -applicable to the current table. It is `nil' if the table is not -associated with any style attributes. - -Return a cons of (TABLE-CELL-STYLE-NAME . PARAGRAPH-STYLE-NAME). - -When STYLE-SPEC is nil, style the table cell the conventional way -- choose cell borders based on row and column groupings and -choose paragraph alignment based on `org-col-cookies' text -property. See also -`org-e-odt-get-paragraph-style-cookie-for-table-cell'. - -When STYLE-SPEC is non-nil, ignore the above cookie and return -styles congruent with the ODF-1.2 specification." - (cond - (style-spec - - ;; LibreOffice - particularly the Writer - honors neither table - ;; templates nor custom table-cell styles. Inorder to retain - ;; inter-operability with LibreOffice, only automatic styles are - ;; used for styling of table-cells. The current implementation is - ;; congruent with ODF-1.2 specification and hence is - ;; future-compatible. - - ;; Additional Note: LibreOffice's AutoFormat facility for tables - - ;; which recognizes as many as 16 different cell types - is much - ;; richer. Unfortunately it is NOT amenable to easy configuration - ;; by hand. - - (let* ((template-name (nth 1 style-spec)) - (cell-style-selectors (nth 2 style-spec)) - (cell-type - (cond - ((and (cdr (assoc 'use-first-column-styles cell-style-selectors)) - (= c 0)) "FirstColumn") - ((and (cdr (assoc 'use-last-column-styles cell-style-selectors)) - (= c (1- org-lparse-table-ncols))) "LastColumn") - ((and (cdr (assoc 'use-first-row-styles cell-style-selectors)) - (= r 0)) "FirstRow") - ((and (cdr (assoc 'use-last-row-styles cell-style-selectors)) - (= r org-e-odt-table-rownum)) - "LastRow") - ((and (cdr (assoc 'use-banding-rows-styles cell-style-selectors)) - (= (% r 2) 1)) "EvenRow") - ((and (cdr (assoc 'use-banding-rows-styles cell-style-selectors)) - (= (% r 2) 0)) "OddRow") - ((and (cdr (assoc 'use-banding-columns-styles cell-style-selectors)) - (= (% c 2) 1)) "EvenColumn") - ((and (cdr (assoc 'use-banding-columns-styles cell-style-selectors)) - (= (% c 2) 0)) "OddColumn") - (t "")))) - (cons - (concat template-name cell-type "TableCell") - (concat template-name cell-type "TableParagraph")))) - (t - (cons - (concat - "OrgTblCell" - (cond - ((= r 0) "T") - ((eq (cdr (assoc r nil ;; org-lparse-table-rowgrp-info FIXME - )) :start) "T") - (t "")) - (when (= r org-e-odt-table-rownum) "B") - (cond - ((= c 0) "") - ((or (memq (nth c org-table-colgroup-info) '(:start :startend)) - (memq (nth (1- c) org-table-colgroup-info) '(:end :startend))) "L") - (t ""))) - (capitalize (org-e-odt-get-column-alignment c)))))) - -(defun org-e-odt-get-paragraph-style-cookie-for-table-cell (r c) - (concat - (and (not org-e-odt-table-style-spec) - (cond - (org-e-odt-table-cur-rowgrp-is-hdr "OrgTableHeading") - ((and (= c 0) nil - ;; (org-lparse-get 'TABLE-FIRST-COLUMN-AS-LABELS) - ) - "OrgTableHeading") - (t "OrgTableContents"))) - (and org-lparse-table-is-styled - (cdr (org-e-odt-get-table-cell-styles - r c org-e-odt-table-style-spec))))) - -(defun org-e-odt-get-style-name-cookie-for-table-cell (r c) - (when org-lparse-table-is-styled - (let* ((cell-styles (org-e-odt-get-table-cell-styles - r c org-e-odt-table-style-spec)) - (table-cell-style (car cell-styles))) - table-cell-style))) - -(defun org-e-odt-format-table-cell (data r c horiz-span) - (concat - (let* ((paragraph-style-cookie - (org-e-odt-get-paragraph-style-cookie-for-table-cell r c)) - (style-name-cookie - (org-e-odt-get-style-name-cookie-for-table-cell r c)) - (extra (and style-name-cookie - (format " table:style-name=\"%s\"" style-name-cookie))) - (extra (concat extra - (and (> horiz-span 0) - (format " table:number-columns-spanned=\"%d\"" - (1+ horiz-span)))))) - (org-e-odt-format-tags - '("" . "") - (if org-lparse-list-table-p data - (org-e-odt-format-stylized-paragraph paragraph-style-cookie data)) extra)) - (let (s) - (dotimes (i horiz-span) - (setq s (concat s "\n"))) s) - "\n")) - -(defun org-e-odt-begin-toc (lang-specific-heading max-level) - (concat - (format " - - - %s -" max-level lang-specific-heading) - - (let ((entry-templates "")) - (loop for level from 1 upto 10 - do (setq entry-templates - (concat entry-templates - (format - " - - - - - - -" level level)))) - entry-templates) - - (format " - - - - - %s - - " lang-specific-heading))) - -(defun org-e-odt-end-toc () - (format " - - -")) - -(defun org-e-odt-format-toc-entry (snumber todo headline tags href) - - ;; FIXME - (setq headline (concat - (and org-export-with-section-numbers - (concat snumber ". ")) - headline - (and tags - (concat - (org-e-odt-format-spaces 3) - (org-e-odt-format-fontify tags "tag"))))) - (when todo - (setq headline (org-e-odt-format-fontify headline "todo"))) - - (let ((org-e-odt-suppress-xref t)) - (org-e-odt-format-link headline (concat "#" href)))) - -(defun org-e-odt-format-toc-item (toc-entry level org-last-level) - (let ((style (format "Contents_20_%d" - (+ level (or ;; (org-lparse-get 'TOPLEVEL-HLEVEL) - 1 - 1) -1)))) - (concat "\n" (org-e-odt-format-stylized-paragraph style toc-entry) "\n"))) - -;; Following variable is let bound during 'ORG-LINK callback. See -;; org-html.el - -(defun org-e-odt-format-link (desc href &optional attr) - (cond - ((and (= (string-to-char href) ?#) (not org-e-odt-suppress-xref)) - (setq href (concat org-export-e-odt-bookmark-prefix (substring href 1))) - (let ((xref-format "text")) - (when (numberp desc) - (setq desc (format "%d" desc) xref-format "number")) - (org-e-odt-format-tags-simple - '("" . - "") - desc xref-format href))) - (org-lparse-link-description-is-image - (org-e-odt-format-tags - '("" . "") - desc href (or attr ""))) - (t - (org-e-odt-format-tags-simple - '("" . "") - desc href (or attr ""))))) - -(defun org-e-odt-format-spaces (n) - (cond - ((= n 1) " ") - ((> n 1) (concat - " " (org-e-odt-format-tags "" "" (1- n)))) - (t ""))) - -(defun org-e-odt-format-tabs (&optional n) - (let ((tab "") - (n (or n 1))) - (insert tab))) - -(defun org-e-odt-format-line-break () - (org-e-odt-format-tags "" "")) - -(defun org-e-odt-format-horizontal-line () - (org-e-odt-format-stylized-paragraph 'horizontal-line "")) - -(defun org-e-odt-encode-plain-text (line &optional no-whitespace-filling) - (setq line (org-e-html-encode-plain-text line)) - (if no-whitespace-filling line - (org-e-odt-fill-tabs-and-spaces line))) - -(defun org-e-odt-format-line (line) - (case org-lparse-dyn-current-environment - (fixedwidth (concat - (org-e-odt-format-stylized-paragraph - 'fixedwidth (org-e-odt-encode-plain-text line)) "\n")) - (t (concat line "\n")))) - -(defun org-e-odt-format-comment (fmt &rest args) - (let ((comment (apply 'format fmt args))) - (format "\n\n" comment))) - -(defun org-e-odt-format-org-entity (wd) - (org-entity-get-representation wd 'utf8)) - -(defun org-e-odt-fill-tabs-and-spaces (line) - (replace-regexp-in-string - "\\([\t]\\|\\([ ]+\\)\\)" (lambda (s) - (cond - ((string= s "\t") (org-e-odt-format-tabs)) - (t (org-e-odt-format-spaces (length s))))) line)) - -(defun org-e-odt-hfy-face-to-css (fn) - "Create custom style for face FN. -When FN is the default face, use it's foreground and background -properties to create \"OrgSrcBlock\" paragraph style. Otherwise -use it's color attribute to create a character style whose name -is obtained from FN. Currently all attributes of FN other than -color are ignored. - -The style name for a face FN is derived using the following -operations on the face name in that order - de-dash, CamelCase -and prefix with \"OrgSrc\". For example, -`font-lock-function-name-face' is associated with -\"OrgSrcFontLockFunctionNameFace\"." - (let* ((css-list (hfy-face-to-style fn)) - (style-name ((lambda (fn) - (concat "OrgSrc" - (mapconcat - 'capitalize (split-string - (hfy-face-or-def-to-name fn) "-") - ""))) fn)) - (color-val (cdr (assoc "color" css-list))) - (background-color-val (cdr (assoc "background" css-list))) - (style (and org-export-e-odt-create-custom-styles-for-srcblocks - (cond - ((eq fn 'default) - (format org-src-block-paragraph-format - background-color-val color-val)) - (t - (format - " - - - " style-name color-val)))))) - (cons style-name style))) - -(defun org-e-odt-insert-custom-styles-for-srcblocks (styles) - "Save STYLES used for colorizing of source blocks. -Update styles.xml with styles that were collected as part of -`org-e-odt-hfy-face-to-css' callbacks." - (when styles - (with-current-buffer - (find-file-noselect (expand-file-name "styles.xml") t) - (goto-char (point-min)) - (when (re-search-forward "" nil t) - (goto-char (match-beginning 0)) - (insert "\n\n" styles "\n"))))) - -(defun org-e-odt-remap-stylenames (style-name) - (or - (cdr (assoc style-name '(("timestamp-wrapper" . "OrgTimestampWrapper") - ("timestamp" . "OrgTimestamp") - ("timestamp-kwd" . "OrgTimestampKeyword") - ("tag" . "OrgTag") - ("todo" . "OrgTodo") - ("done" . "OrgDone") - ("target" . "OrgTarget")))) - style-name)) - -(defun org-e-odt-format-fontify (text style &optional id) - (let* ((style-name - (cond - ((stringp style) - (org-e-odt-remap-stylenames style)) - ((symbolp style) - (org-e-odt-get-style-name-for-entity 'character style)) - ((listp style) - (assert (< 1 (length style))) - (let ((parent-style (pop style))) - (mapconcat (lambda (s) - ;; (assert (stringp s) t) - (org-e-odt-remap-stylenames s)) style "") - (org-e-odt-remap-stylenames parent-style))) - (t (error "Don't how to handle style %s" style))))) - (org-e-odt-format-tags - '("" . "") - text style-name))) - -(defun org-e-odt-relocate-relative-path (path dir) - (if (file-name-absolute-p path) path - (file-relative-name (expand-file-name path dir) - (expand-file-name "eyecandy" dir)))) - -(defun org-e-odt-format-inline-image (thefile - &optional caption label attrs ; FIXME - CLA - ) - (let* ((thelink (if (file-name-absolute-p thefile) thefile - (org-xml-format-href - (org-e-odt-relocate-relative-path - thefile org-current-export-file)))) - (href - (org-e-odt-format-tags - "" "" - (if org-export-e-odt-embed-images - (org-e-odt-copy-image-file thefile) thelink)))) - (org-export-e-odt-format-image thefile href))) - -(defun org-export-e-odt-format-formula (src href) - (save-match-data - (let* ((caption (org-find-text-property-in-string 'org-caption src)) - (caption (and caption (org-xml-format-desc caption))) - (label (org-find-text-property-in-string 'org-label src)) - (latex-frag (org-find-text-property-in-string 'org-latex-src src)) - (embed-as (or (and latex-frag - (org-find-text-property-in-string - 'org-latex-src-embed-type src)) - (if (or caption label) 'paragraph 'character))) - width height) - (when latex-frag - (setq href (org-propertize href :title "LaTeX Fragment" - :description latex-frag))) - (cond - ((eq embed-as 'character) - (org-e-odt-format-entity "InlineFormula" href width height)) - (t - (org-lparse-end-paragraph) - (org-lparse-insert-list-table - `((,(org-e-odt-format-entity - (if caption "CaptionedDisplayFormula" "DisplayFormula") - href width height :caption caption :label nil) - ,(if (not label) "" - (org-e-odt-format-entity-caption label nil "__MathFormula__")))) - nil nil nil ":style \"OrgEquation\"" nil '((1 "c" 8) (2 "c" 1))) - (throw 'nextline nil)))))) - -(defun org-e-odt-copy-formula-file (path) - "Returns the internal name of the file" - (let* ((src-file (expand-file-name - path (file-name-directory org-current-export-file))) - (target-dir (format "Formula-%04d/" - (incf org-e-odt-embedded-formulas-count))) - (target-file (concat target-dir "content.xml"))) - (message "Embedding %s as %s ..." - (substring-no-properties path) target-file) - - (make-directory target-dir) - (org-e-odt-create-manifest-file-entry - "application/vnd.oasis.opendocument.formula" target-dir "1.2") - - (case (org-e-odt-is-formula-link-p src-file) - (mathml - (copy-file src-file target-file 'overwrite)) - (odf - (org-e-odt-zip-extract-one src-file "content.xml" target-dir)) - (t - (error "%s is not a formula file" src-file))) - - (org-e-odt-create-manifest-file-entry "text/xml" target-file) - target-file)) - -(defun org-e-odt-format-inline-formula (thefile) - (let* ((thelink (if (file-name-absolute-p thefile) thefile - (org-xml-format-href - (org-e-odt-relocate-relative-path - thefile org-current-export-file)))) - (href - (org-e-odt-format-tags - "" "" - (file-name-directory (org-e-odt-copy-formula-file thefile))))) - (org-export-e-odt-format-formula thefile href))) - -(defun org-e-odt-is-formula-link-p (file) - (let ((case-fold-search nil)) - (cond - ((string-match "\\.\\(mathml\\|mml\\)\\'" file) - 'mathml) - ((string-match "\\.odf\\'" file) - 'odf)))) - -(defun org-e-odt-format-org-link (opt-plist type-1 path fragment desc attr - descp) - "Make a OpenDocument link. -OPT-PLIST is an options list. -TYPE-1 is the device-type of the link (THIS://foo.html). -PATH is the path of the link (http://THIS#location). -FRAGMENT is the fragment part of the link, if any (foo.html#THIS). -DESC is the link description, if any. -ATTR is a string of other attributes of the a element." - (declare (special org-lparse-par-open)) - (save-match-data - (let* ((may-inline-p - (and (member type-1 '("http" "https" "file")) - (org-lparse-should-inline-p path descp) - (not fragment))) - (type (if (equal type-1 "id") "file" type-1)) - (filename path) - (thefile path)) - (cond - ;; check for inlined images - ((and (member type '("file")) - (not fragment) - (org-file-image-p - filename org-export-e-odt-inline-image-extensions) - (or (eq t org-export-e-odt-inline-images) - (and org-export-e-odt-inline-images (not descp)))) - (org-e-odt-format-inline-image thefile)) - ;; check for embedded formulas - ((and (member type '("file")) - (not fragment) - (org-e-odt-is-formula-link-p filename) - (or (not descp))) - (org-e-odt-format-inline-formula thefile)) - ((string= type "coderef") - (let* ((ref fragment) - (lineno-or-ref (cdr (assoc ref org-export-code-refs))) - (desc (and descp desc)) - (org-e-odt-suppress-xref nil) - (href (org-xml-format-href (concat "#coderef-" ref)))) - (cond - ((and (numberp lineno-or-ref) (not desc)) - (org-e-odt-format-link lineno-or-ref href)) - ((and (numberp lineno-or-ref) desc - (string-match (regexp-quote (concat "(" ref ")")) desc)) - (format (replace-match "%s" t t desc) - (org-e-odt-format-link lineno-or-ref href))) - (t - (setq desc (format - (if (and desc (string-match - (regexp-quote (concat "(" ref ")")) - desc)) - (replace-match "%s" t t desc) - (or desc "%s")) - lineno-or-ref)) - (org-e-odt-format-link (org-xml-format-desc desc) href))))) - (t - (when (string= type "file") - (setq thefile - (cond - ((file-name-absolute-p path) - (concat "file://" (expand-file-name path))) - (t (org-e-odt-relocate-relative-path - thefile org-current-export-file))))) - - (when (and (member type '("" "http" "https" "file")) fragment) - (setq thefile (concat thefile "#" fragment))) - - (setq thefile (org-xml-format-href thefile)) - - (when (not (member type '("" "file"))) - (setq thefile (concat type ":" thefile))) - - (let ((org-e-odt-suppress-xref nil)) - (org-e-odt-format-link - (org-xml-format-desc desc) thefile attr))))))) - -(defun org-e-odt-format-heading (text level &optional id) - (let* ((text (if id (org-e-odt-format-target text id) text))) - (org-e-odt-format-tags - '("" . - "") text level level))) - -(defun org-e-odt-format-headline (title extra-targets tags - &optional snumber level) - (concat - (org-e-odt-format-extra-targets extra-targets) - - ;; No need to generate section numbers. They are auto-generated by - ;; the application - - ;; (concat (org-lparse-format 'SECTION-NUMBER snumber level) " ") - title - (and tags (concat (org-e-odt-format-spaces 3) - (org-e-odt-format-org-tags tags))))) - -(defun org-e-odt-format-anchor (text name &optional class) - (org-e-odt-format-target text name)) - -(defun org-e-odt-format-bookmark (text id) - (if id - (org-e-odt-format-tags "" text id) - text)) - -(defun org-e-odt-format-target (text id) - (let ((name (concat org-export-e-odt-bookmark-prefix id))) - (concat - (and id (org-e-odt-format-tags - "" "" name)) - (org-e-odt-format-bookmark text id) - (and id (org-e-odt-format-tags - "" "" name))))) - -(defun org-e-odt-format-footnote (n def) - (setq n (format "%d" n)) - (let ((id (concat "fn" n)) - (note-class "footnote") - (par-style "Footnote")) - (org-e-odt-format-tags - '("" . - "") - (concat - (org-e-odt-format-tags - '("" . "") - n) - (org-e-odt-format-tags - '("" . "") - def)) - id note-class))) - -(defun org-e-odt-format-footnote-reference (n def refcnt) - (if (= refcnt 1) - (org-e-odt-format-footnote n def) - (org-e-odt-format-footnote-ref n))) - -(defun org-e-odt-format-footnote-ref (n) - (setq n (format "%d" n)) - (let ((note-class "footnote") - (ref-format "text") - (ref-name (concat "fn" n))) - (org-e-odt-format-tags - '("" . "") - (org-e-odt-format-tags - '("" . "") - n note-class ref-format ref-name) - "OrgSuperscript"))) - -(defun org-e-odt-get-image-name (file-name) - (require 'sha1) - (file-relative-name - (expand-file-name - (concat (sha1 file-name) "." (file-name-extension file-name)) "Pictures"))) - -(defun org-export-e-odt-format-image (src href) - "Create image tag with source and attributes." - (save-match-data - (let* ((caption (org-find-text-property-in-string 'org-caption src)) - (caption (and caption (org-xml-format-desc caption))) - (attr (org-find-text-property-in-string 'org-attributes src)) - (label (org-find-text-property-in-string 'org-label src)) - (latex-frag (org-find-text-property-in-string - 'org-latex-src src)) - (category (and latex-frag "__DvipngImage__")) - (attr-plist (org-lparse-get-block-params attr)) - (user-frame-anchor - (car (assoc-string (plist-get attr-plist :anchor) - '(("as-char") ("paragraph") ("page")) t))) - (user-frame-style - (and user-frame-anchor (plist-get attr-plist :style))) - (user-frame-attrs - (and user-frame-anchor (plist-get attr-plist :attributes))) - (user-frame-params - (list user-frame-style user-frame-attrs user-frame-anchor)) - (embed-as (cond - (latex-frag - (symbol-name - (case (org-find-text-property-in-string - 'org-latex-src-embed-type src) - (paragraph 'paragraph) - (t 'as-char)))) - (user-frame-anchor) - (t "paragraph"))) - (size (org-e-odt-image-size-from-file - src (plist-get attr-plist :width) - (plist-get attr-plist :height) - (plist-get attr-plist :scale) nil embed-as)) - (width (car size)) (height (cdr size))) - (when latex-frag - (setq href (org-propertize href :title "LaTeX Fragment" - :description latex-frag))) - (let ((frame-style-handle (concat (and (or caption label) "Captioned") - embed-as "Image"))) - (org-e-odt-format-entity - frame-style-handle href width height - :caption caption :label label :category category - :user-frame-params user-frame-params))))) - -(defun org-e-odt-format-object-description (title description) - (concat (and title (org-e-odt-format-tags - '("" . "") - (org-e-odt-encode-plain-text title t))) - (and description (org-e-odt-format-tags - '("" . "") - (org-e-odt-encode-plain-text description t))))) - -(defun org-e-odt-format-frame (text width height style &optional - extra anchor-type) - (let ((frame-attrs - (concat - (if width (format " svg:width=\"%0.2fcm\"" width) "") - (if height (format " svg:height=\"%0.2fcm\"" height) "") - extra - (format " text:anchor-type=\"%s\"" (or anchor-type "paragraph"))))) - (org-e-odt-format-tags - '("" . "") - (concat text (org-e-odt-format-object-description - (get-text-property 0 :title text) - (get-text-property 0 :description text))) - style frame-attrs))) - -(defun org-e-odt-format-textbox (text width height style &optional - extra anchor-type) - (org-e-odt-format-frame - (org-e-odt-format-tags - '("" . "") - text (concat (format " fo:min-height=\"%0.2fcm\"" (or height .2)) - (unless width - (format " fo:min-width=\"%0.2fcm\"" (or width .2))))) - width nil style extra anchor-type)) - -(defun org-e-odt-format-inlinetask (heading content - &optional todo priority tags) - (org-e-odt-format-stylized-paragraph - nil (org-e-odt-format-textbox - (concat (org-e-odt-format-stylized-paragraph - "OrgInlineTaskHeading" - (org-lparse-format - 'HEADLINE (concat (org-lparse-format-todo todo) " " heading) - nil tags)) - content) nil nil "OrgInlineTaskFrame" " style:rel-width=\"100%\""))) - - -(defun org-e-odt-merge-frame-params(default-frame-params user-frame-params) - (if (not user-frame-params) default-frame-params - (assert (= (length default-frame-params) 3)) - (assert (= (length user-frame-params) 3)) - (loop for user-frame-param in user-frame-params - for default-frame-param in default-frame-params - collect (or user-frame-param default-frame-param)))) - -(defun* org-e-odt-format-entity (entity href width height - &key caption label category - user-frame-params) - (let* ((entity-style (assoc-string entity org-e-odt-entity-frame-styles t)) - default-frame-params frame-params) - (cond - ((not (or caption label)) - (setq default-frame-params (nth 2 entity-style)) - (setq frame-params (org-e-odt-merge-frame-params - default-frame-params user-frame-params)) - (apply 'org-e-odt-format-frame href width height frame-params)) - (t - (setq default-frame-params (nth 3 entity-style)) - (setq frame-params (org-e-odt-merge-frame-params - default-frame-params user-frame-params)) - (apply 'org-e-odt-format-textbox - (org-e-odt-format-stylized-paragraph - 'illustration - (concat - (apply 'org-e-odt-format-frame href width height - (nth 2 entity-style)) - (org-e-odt-format-entity-caption - label caption (or category (nth 1 entity-style))))) - width height frame-params))))) - -(defun org-e-odt-copy-image-file (path) - "Returns the internal name of the file" - (let* ((image-type (file-name-extension path)) - (media-type (format "image/%s" image-type)) - (src-file (expand-file-name - path (file-name-directory org-current-export-file))) - (target-dir "Images/") - (target-file - (format "%s%04d.%s" target-dir - (incf org-e-odt-embedded-images-count) image-type))) - (message "Embedding %s as %s ..." - (substring-no-properties path) target-file) - - (when (= 1 org-e-odt-embedded-images-count) - (make-directory target-dir) - (org-e-odt-create-manifest-file-entry "" target-dir)) - - (copy-file src-file target-file 'overwrite) - (org-e-odt-create-manifest-file-entry media-type target-file) - target-file)) - -(defun org-e-odt-do-image-size (probe-method file &optional dpi anchor-type) - (setq dpi (or dpi org-export-e-odt-pixels-per-inch)) - (setq anchor-type (or anchor-type "paragraph")) - (flet ((size-in-cms (size-in-pixels) - (flet ((pixels-to-cms (pixels) - (let* ((cms-per-inch 2.54) - (inches (/ pixels dpi))) - (* cms-per-inch inches)))) - (and size-in-pixels - (cons (pixels-to-cms (car size-in-pixels)) - (pixels-to-cms (cdr size-in-pixels))))))) - (case probe-method - (emacs - (size-in-cms (ignore-errors ; Emacs could be in batch mode - (clear-image-cache) - (image-size (create-image file) 'pixels)))) - (imagemagick - (size-in-cms - (let ((dim (shell-command-to-string - (format "identify -format \"%%w:%%h\" \"%s\"" file)))) - (when (string-match "\\([0-9]+\\):\\([0-9]+\\)" dim) - (cons (string-to-number (match-string 1 dim)) - (string-to-number (match-string 2 dim))))))) - (t - (cdr (assoc-string anchor-type - org-export-e-odt-default-image-sizes-alist)))))) - -(defun org-e-odt-image-size-from-file (file &optional user-width - user-height scale dpi embed-as) - (unless (file-name-absolute-p file) - (setq file (expand-file-name - file (file-name-directory org-current-export-file)))) - (let* (size width height) - (unless (and user-height user-width) - (loop for probe-method in org-export-e-odt-image-size-probe-method - until size - do (setq size (org-e-odt-do-image-size - probe-method file dpi embed-as))) - (or size (error "Cannot determine Image size. Aborting ...")) - (setq width (car size) height (cdr size))) - (cond - (scale - (setq width (* width scale) height (* height scale))) - ((and user-height user-width) - (setq width user-width height user-height)) - (user-height - (setq width (* user-height (/ width height)) height user-height)) - (user-width - (setq height (* user-width (/ height width)) width user-width)) - (t (ignore))) - ;; ensure that an embedded image fits comfortably within a page - (let ((max-width (car org-export-e-odt-max-image-size)) - (max-height (cdr org-export-e-odt-max-image-size))) - (when (or (> width max-width) (> height max-height)) - (let* ((scale1 (/ max-width width)) - (scale2 (/ max-height height)) - (scale (min scale1 scale2))) - (setq width (* scale width) height (* scale height))))) - (cons width height))) - -(defun org-e-odt-get-label-category-and-style (label default-category) - "See `org-export-e-odt-get-category-from-label'." - (let ((default-category-map - (assoc default-category org-e-odt-category-map-alist)) - user-category user-category-map category) - (cond - ((not org-export-e-odt-get-category-from-label) - default-category-map) - ((not (setq user-category - (save-match-data - (and (string-match "\\`\\(.*\\):.+" label) - (match-string 1 label))))) - default-category-map) - (t - (setq user-category-map - (or (assoc user-category org-e-odt-category-map-alist) - (list nil user-category "category-and-value")) - category (nth 1 user-category-map)) - (if (member category org-export-e-odt-user-categories) - user-category-map - default-category-map))))) - -(defun org-e-odt-add-label-definition (label default-category) - "Create an entry in `org-e-odt-entity-labels-alist' and return it." - (setq label (substring-no-properties label)) - (let* ((label-props (org-e-odt-get-label-category-and-style - label default-category)) - (category (nth 1 label-props)) - (counter category) - (label-style (nth 2 label-props)) - (sequence-var (intern (mapconcat - 'downcase - (org-split-string counter) "-"))) - (seqno (1+ (or (plist-get org-e-odt-entity-counts-plist sequence-var) - 0))) - (label-props (list label category seqno label-style))) - (setq org-e-odt-entity-counts-plist - (plist-put org-e-odt-entity-counts-plist sequence-var seqno)) - (push label-props org-e-odt-entity-labels-alist) - label-props)) - -(defun org-e-odt-format-label-definition (caption label category seqno label-style) - (assert label) - (format-spec - (cadr (assoc-string label-style org-e-odt-label-styles t)) - `((?e . ,category) - (?n . ,(org-e-odt-format-tags - '("" . "") - (format "%d" seqno) label category category)) - (?c . ,(or (and caption (concat ": " caption)) ""))))) - -(defun org-e-odt-format-label-reference (label category seqno label-style) - (assert label) - (save-match-data - (let* ((fmt (cddr (assoc-string label-style org-e-odt-label-styles t))) - (fmt1 (car fmt)) - (fmt2 (cadr fmt))) - (org-e-odt-format-tags - '("" - . "") - (format-spec fmt2 `((?e . ,category) - (?n . ,(format "%d" seqno)))) fmt1 label)))) - -(defun org-e-odt-fixup-label-references () - (goto-char (point-min)) - (while (re-search-forward - "[ \t\n]*" - nil t) - (let* ((label (match-string 1)) - (label-def (assoc label org-e-odt-entity-labels-alist)) - (rpl (and label-def - (apply 'org-e-odt-format-label-reference label-def)))) - (if rpl (replace-match rpl t t) - (org-lparse-warn - (format "Unable to resolve reference to label \"%s\"" label)))))) - -(defun org-e-odt-format-entity-caption (label caption category) - (or (and label - (apply 'org-e-odt-format-label-definition - caption (org-e-odt-add-label-definition label category))) - caption "")) - -(defun org-e-odt-format-tags-1 (tag text prefix suffix &rest args) - (cond - ((consp tag) - (concat prefix (apply 'format (car tag) args) text suffix - (format (cdr tag)))) - ((stringp tag) ; singleton tag - (concat prefix (apply 'format tag args) text)))) - -(defun org-e-odt-format-tags (tag text &rest args) - (apply 'org-e-odt-format-tags-1 tag text "\n" "\n" args)) - -(defun org-e-odt-format-tags-simple (tag text &rest args) - (apply 'org-e-odt-format-tags-1 tag text nil nil args)) - -(defun org-e-odt-init-outfile () - (unless (executable-find "zip") - ;; Not at all OSes ship with zip by default - (error "Executable \"zip\" needed for creating OpenDocument files")) - - (let* ((outdir (make-temp-file - (format org-export-e-odt-tmpdir-prefix org-lparse-backend) t)) - (content-file (expand-file-name "content.xml" outdir))) - - ;; reset variables - (setq org-e-odt-manifest-file-entries nil - org-e-odt-embedded-images-count 0 - org-e-odt-embedded-formulas-count 0 - org-e-odt-section-count 0 - org-e-odt-entity-labels-alist nil - org-e-odt-list-stack-stashed nil - org-e-odt-automatic-styles nil - org-e-odt-object-counters nil - org-e-odt-entity-counts-plist nil) - - ;; let `htmlfontify' know that we are interested in collecting - ;; styles - FIXME - - (setq hfy-user-sheet-assoc nil) - - ;; init conten.xml - (with-current-buffer - (find-file-noselect content-file t) - (current-buffer)))) - - - -(defun org-e-odt-save-as-outfile (target opt-plist) - ;; write automatic styles - (org-e-odt-write-automatic-styles) - - ;; write styles file - ;; (when (equal org-lparse-backend 'odt) FIXME - ;; ) - - (org-e-odt-update-styles-file opt-plist) - - ;; create mimetype file - (let ((mimetype (org-e-odt-write-mimetype-file ;; org-lparse-backend FIXME - 'odt))) - (org-e-odt-create-manifest-file-entry mimetype "/" "1.2")) - - ;; create a manifest entry for content.xml - (org-e-odt-create-manifest-file-entry "text/xml" "content.xml") - - ;; write out the manifest entries before zipping - (org-e-odt-write-manifest-file) - - (let ((xml-files '("mimetype" "META-INF/manifest.xml" "content.xml" - "meta.xml")) - (zipdir default-directory)) - (when (or t (equal org-lparse-backend 'odt)) ; FIXME - (push "styles.xml" xml-files)) - (message "Switching to directory %s" (expand-file-name zipdir)) - - ;; save all xml files - (mapc (lambda (file) - (with-current-buffer - (find-file-noselect (expand-file-name file) t) - ;; prettify output if needed - (when org-export-e-odt-prettify-xml - (indent-region (point-min) (point-max))) - (save-buffer 0))) - xml-files) - - (let* ((target-name (file-name-nondirectory target)) - (target-dir (file-name-directory target)) - (cmds `(("zip" "-mX0" ,target-name "mimetype") - ("zip" "-rmTq" ,target-name ".")))) - (when (file-exists-p target) - ;; FIXME: If the file is locked this throws a cryptic error - (delete-file target)) - - (let ((coding-system-for-write 'no-conversion) exitcode err-string) - (message "Creating odt file...") - (mapc - (lambda (cmd) - (message "Running %s" (mapconcat 'identity cmd " ")) - (setq err-string - (with-output-to-string - (setq exitcode - (apply 'call-process (car cmd) - nil standard-output nil (cdr cmd))))) - (or (zerop exitcode) - (ignore (message "%s" err-string)) - (error "Unable to create odt file (%S)" exitcode))) - cmds)) - - ;; move the file from outdir to target-dir - (rename-file target-name target-dir) - - ;; kill all xml buffers - (mapc (lambda (file) - (kill-buffer - (find-file-noselect (expand-file-name file zipdir) t))) - xml-files) - - (delete-directory zipdir))) - (message "Created %s" target) - (set-buffer (find-file-noselect target t))) - - -(defun org-e-odt-create-manifest-file-entry (&rest args) - (push args org-e-odt-manifest-file-entries)) - -(defun org-e-odt-write-manifest-file () - (make-directory "META-INF") - (let ((manifest-file (expand-file-name "META-INF/manifest.xml"))) - (with-current-buffer - (find-file-noselect manifest-file t) - (insert - " - \n") - (mapc - (lambda (file-entry) - (let* ((version (nth 2 file-entry)) - (extra (if version - (format " manifest:version=\"%s\"" version) - ""))) - (insert - (format org-e-odt-manifest-file-entry-tag - (nth 0 file-entry) (nth 1 file-entry) extra)))) - org-e-odt-manifest-file-entries) - (insert "\n")))) - -(defun org-e-odt-update-meta-file (info) ; FIXME opt-plist - (let ((date (org-e-odt-format-date (plist-get info :date))) - (author (or (plist-get info :author) "")) - (email (plist-get info :email)) - (keywords (plist-get info :keywords)) - (description (plist-get info :description)) - (title (plist-get info :title))) - (write-region - (concat - " - - \n" - (org-e-odt-format-author author) "\n" - (format "%s\n" author) - (format "%s\n" date) - (format "%s\n" date) - (format "%s\n" - (when org-export-creator-info - (format "Org-%s/Emacs-%s" - org-version emacs-version))) - (format "%s\n" keywords) - (format "%s\n" description) - (format "%s\n" title) - "\n" - " \n" "") - nil (expand-file-name "meta.xml"))) - - ;; create a manifest entry for meta.xml - (org-e-odt-create-manifest-file-entry "text/xml" "meta.xml")) - -(defun org-e-odt-update-styles-file (opt-plist) - ;; write styles file - (let ((styles-file (plist-get opt-plist :odt-styles-file))) - (org-e-odt-copy-styles-file (and styles-file - (read (org-trim styles-file))))) - - ;; Update styles.xml - take care of outline numbering - (with-current-buffer - (find-file-noselect (expand-file-name "styles.xml") t) - ;; Don't make automatic backup of styles.xml file. This setting - ;; prevents the backed-up styles.xml file from being zipped in to - ;; odt file. This is more of a hackish fix. Better alternative - ;; would be to fix the zip command so that the output odt file - ;; includes only the needed files and excludes any auto-generated - ;; extra files like backups and auto-saves etc etc. Note that - ;; currently the zip command zips up the entire temp directory so - ;; that any auto-generated files created under the hood ends up in - ;; the resulting odt file. - (set (make-local-variable 'backup-inhibited) t) - - ;; Import local setting of `org-export-with-section-numbers' - (org-e-odt-configure-outline-numbering - (if org-export-with-section-numbers org-export-headline-levels 0))) - - ;; Write custom styles for source blocks - (org-e-odt-insert-custom-styles-for-srcblocks - (mapconcat - (lambda (style) - (format " %s\n" (cddr style))) - hfy-user-sheet-assoc ""))) - -(defun org-e-odt-write-mimetype-file (format) - ;; create mimetype file - (let ((mimetype - (case format - (odt "application/vnd.oasis.opendocument.text") - (odf "application/vnd.oasis.opendocument.formula") - (t (error "Unknown OpenDocument backend %S" org-lparse-backend))))) - (write-region mimetype nil (expand-file-name "mimetype")) - mimetype)) - -(defun org-e-odt-finalize-outfile () - (org-e-odt-delete-empty-paragraphs)) - -(defun org-e-odt-delete-empty-paragraphs () - (goto-char (point-min)) - (let ((open "]*>") - (close "")) - (while (re-search-forward (format "%s[ \r\n\t]*%s" open close) nil t) - (replace-match "")))) - -(declare-function org-create-math-formula "org" - (latex-frag &optional mathml-file)) - -;;;###autoload -(defun org-export-e-odt-convert (&optional in-file out-fmt prefix-arg) - "Convert IN-FILE to format OUT-FMT using a command line converter. -IN-FILE is the file to be converted. If unspecified, it defaults -to variable `buffer-file-name'. OUT-FMT is the desired output -format. Use `org-export-e-odt-convert-process' as the converter. -If PREFIX-ARG is non-nil then the newly converted file is opened -using `org-open-file'." - (interactive - (append (org-lparse-convert-read-params) current-prefix-arg)) - (org-lparse-do-convert in-file out-fmt prefix-arg)) - -(defun org-e-odt-get (what &optional opt-plist) - (case what - (BACKEND 'odt) - (EXPORT-DIR (org-export-directory :html opt-plist)) - (FILE-NAME-EXTENSION "odt") - (EXPORT-BUFFER-NAME "*Org ODT Export*") - (ENTITY-CONTROL org-e-odt-entity-control-callbacks-alist) - (ENTITY-FORMAT org-e-odt-entity-format-callbacks-alist) - (INIT-METHOD 'org-e-odt-init-outfile) - (FINAL-METHOD 'org-e-odt-finalize-outfile) - (SAVE-METHOD 'org-e-odt-save-as-outfile) - (CONVERT-METHOD - (and org-export-e-odt-convert-process - (cadr (assoc-string org-export-e-odt-convert-process - org-export-e-odt-convert-processes t)))) - (CONVERT-CAPABILITIES - (and org-export-e-odt-convert-process - (cadr (assoc-string org-export-e-odt-convert-process - org-export-e-odt-convert-processes t)) - org-export-e-odt-convert-capabilities)) - (TOPLEVEL-HLEVEL 1) - (SPECIAL-STRING-REGEXPS org-export-e-odt-special-string-regexps) - (INLINE-IMAGES 'maybe) - (INLINE-IMAGE-EXTENSIONS '("png" "jpeg" "jpg" "gif" "svg")) - (PLAIN-TEXT-MAP '(("&" . "&") ("<" . "<") (">" . ">"))) - (TABLE-FIRST-COLUMN-AS-LABELS nil) - (FOOTNOTE-SEPARATOR ) - (CODING-SYSTEM-FOR-WRITE 'utf-8) - (CODING-SYSTEM-FOR-SAVE 'utf-8) - (t (error "Unknown property: %s" what)))) - -(defun org-export-e-odt-do-preprocess-latex-fragments () - "Convert LaTeX fragments to images." - (let* ((latex-frag-opt (plist-get org-lparse-opt-plist :LaTeX-fragments)) - (latex-frag-opt ; massage the options - (or (and (member latex-frag-opt '(mathjax t)) - (not (and (fboundp 'org-format-latex-mathml-available-p) - (org-format-latex-mathml-available-p))) - (prog1 org-lparse-latex-fragment-fallback - (org-lparse-warn - (concat - "LaTeX to MathML converter not available. " - (format "Using %S instead." - org-lparse-latex-fragment-fallback))))) - latex-frag-opt)) - cache-dir display-msg) - (cond - ((eq latex-frag-opt 'dvipng) - (setq cache-dir "ltxpng/") - (setq display-msg "Creating LaTeX image %s")) - ((member latex-frag-opt '(mathjax t)) - (setq latex-frag-opt 'mathml) - (setq cache-dir "ltxmathml/") - (setq display-msg "Creating MathML formula %s"))) - (when (and org-current-export-file) - (org-format-latex - (concat cache-dir (file-name-sans-extension - (file-name-nondirectory org-current-export-file))) - org-current-export-dir nil display-msg - nil nil latex-frag-opt)))) - -(defadvice org-format-latex-as-mathml - (after org-e-odt-protect-latex-fragment activate) - "Encode LaTeX fragment as XML. -Do this when translation to MathML fails." - (when (or (not (> (length ad-return-value) 0)) - (get-text-property 0 'org-protected ad-return-value)) - (setq ad-return-value - (org-propertize (org-e-odt-encode-plain-text (ad-get-arg 0)) - 'org-protected t)))) - -(defun org-export-e-odt-preprocess-latex-fragments () - (when (equal org-export-current-backend 'odt) - (org-export-e-odt-do-preprocess-latex-fragments))) - -(defun org-export-e-odt-preprocess-label-references () - (goto-char (point-min)) - (let (label label-components category value pretty-label) - (while (re-search-forward "\\\\ref{\\([^{}\n]+\\)}" nil t) - (org-if-unprotected-at (match-beginning 1) - (replace-match - (let ((org-lparse-encode-pending t) - (label (match-string 1))) - ;; markup generated below is mostly an eye-candy. At - ;; pre-processing stage, there is no information on which - ;; entity a label reference points to. The actual markup - ;; is generated as part of `org-e-odt-fixup-label-references' - ;; which gets called at the fag end of export. By this - ;; time we would have seen and collected all the label - ;; definitions in `org-e-odt-entity-labels-alist'. - (org-e-odt-format-tags - '("" . - "") - "" (org-add-props label '(org-protected t)))) t t))))) - -;; process latex fragments as part of -;; `org-export-preprocess-after-blockquote-hook'. Note that this hook -;; is the one that is closest and well before the call to -;; `org-export-attach-captions-and-attributes' in -;; `org-export-preprocess-string'. The above arrangement permits -;; captions, labels and attributes to be attached to png images -;; generated out of latex equations. -(add-hook 'org-export-preprocess-after-blockquote-hook - 'org-export-e-odt-preprocess-latex-fragments) - -(defun org-export-e-odt-preprocess (parameters) - (org-export-e-odt-preprocess-label-references)) - - -(defun org-e-odt-zip-extract-one (archive member &optional target) - (require 'arc-mode) - (let* ((target (or target default-directory)) - (archive (expand-file-name archive)) - (archive-zip-extract - (list "unzip" "-qq" "-o" "-d" target)) - exit-code command-output) - (setq command-output - (with-temp-buffer - (setq exit-code (archive-zip-extract archive member)) - (buffer-string))) - (unless (zerop exit-code) - (message command-output) - (error "Extraction failed")))) - -(defun org-e-odt-zip-extract (archive members &optional target) - (when (atom members) (setq members (list members))) - (mapc (lambda (member) - (org-e-odt-zip-extract-one archive member target)) - members)) - -(defun org-e-odt-copy-styles-file (&optional styles-file) - ;; Non-availability of styles.xml is not a critical error. For now - ;; throw an error purely for aesthetic reasons. - (setq styles-file (or styles-file - org-export-e-odt-styles-file - (expand-file-name "OrgOdtStyles.xml" - org-e-odt-styles-dir) - (error "org-e-odt: Missing styles file?"))) - (cond - ((listp styles-file) - (let ((archive (nth 0 styles-file)) - (members (nth 1 styles-file))) - (org-e-odt-zip-extract archive members) - (mapc - (lambda (member) - (when (org-file-image-p member) - (let* ((image-type (file-name-extension member)) - (media-type (format "image/%s" image-type))) - (org-e-odt-create-manifest-file-entry media-type member)))) - members))) - ((and (stringp styles-file) (file-exists-p styles-file)) - (let ((styles-file-type (file-name-extension styles-file))) - (cond - ((string= styles-file-type "xml") - (copy-file styles-file "styles.xml" t)) - ((member styles-file-type '("odt" "ott")) - (org-e-odt-zip-extract styles-file "styles.xml"))))) - (t - (error (format "Invalid specification of styles.xml file: %S" - org-export-e-odt-styles-file)))) - - ;; create a manifest entry for styles.xml - (org-e-odt-create-manifest-file-entry "text/xml" "styles.xml")) - -(defun org-e-odt-configure-outline-numbering (level) - "Outline numbering is retained only upto LEVEL. -To disable outline numbering pass a LEVEL of 0." - (goto-char (point-min)) - (let ((regex - "]*\\)text:level=\"\\([^\"]*\\)\"\\([^>]*\\)>") - (replacement - "")) - (while (re-search-forward regex nil t) - (when (> (string-to-number (match-string 2)) level) - (replace-match replacement t nil)))) - (save-buffer 0)) - -;;;###autoload -(defun org-export-as-odf (latex-frag &optional odf-file) - "Export LATEX-FRAG as OpenDocument formula file ODF-FILE. -Use `org-create-math-formula' to convert LATEX-FRAG first to -MathML. When invoked as an interactive command, use -`org-latex-regexps' to infer LATEX-FRAG from currently active -region. If no LaTeX fragments are found, prompt for it. Push -MathML source to kill ring, if `org-export-copy-to-kill-ring' is -non-nil." - (interactive - `(,(let (frag) - (setq frag (and (setq frag (and (region-active-p) - (buffer-substring (region-beginning) - (region-end)))) - (loop for e in org-latex-regexps - thereis (when (string-match (nth 1 e) frag) - (match-string (nth 2 e) frag))))) - (read-string "LaTeX Fragment: " frag nil frag)) - ,(let ((odf-filename (expand-file-name - (concat - (file-name-sans-extension - (or (file-name-nondirectory buffer-file-name))) - "." "odf") - (file-name-directory buffer-file-name)))) - (read-file-name "ODF filename: " nil odf-filename nil - (file-name-nondirectory odf-filename))))) - (let* ((org-lparse-backend 'odf) - org-lparse-opt-plist - (filename (or odf-file - (expand-file-name - (concat - (file-name-sans-extension - (or (file-name-nondirectory buffer-file-name))) - "." "odf") - (file-name-directory buffer-file-name)))) - (buffer (find-file-noselect (org-e-odt-init-outfile filename))) - (coding-system-for-write 'utf-8) - (save-buffer-coding-system 'utf-8)) - (set-buffer buffer) - (set-buffer-file-coding-system coding-system-for-write) - (let ((mathml (org-create-math-formula latex-frag))) - (unless mathml (error "No Math formula created")) - (insert mathml) - (or (org-export-push-to-kill-ring - (upcase (symbol-name org-lparse-backend))) - (message "Exporting... done"))) - (org-e-odt-save-as-outfile filename nil ; FIXME - ))) - -;;;###autoload -(defun org-export-as-odf-and-open () - "Export LaTeX fragment as OpenDocument formula and immediately open it. -Use `org-export-as-odf' to read LaTeX fragment and OpenDocument -formula file." - (interactive) - (org-lparse-and-open - nil nil nil (call-interactively 'org-export-as-odf))) - - - - -;;; Driver Starts here -;;; Dependencies - -(require 'format-spec) -(eval-when-compile (require 'cl) (require 'table)) - - - -;;; Hooks - -(defvar org-e-odt-after-blockquotes-hook nil - "Hook run during HTML export, after blockquote, verse, center are done.") - -(defvar org-e-odt-final-hook nil - "Hook run at the end of HTML export, in the new buffer.") - -;; FIXME: it already exists in org-e-odt.el -;;; Function Declarations - -(declare-function org-element-property "org-element" (property element)) -(declare-function org-element-normalize-string "org-element" (s)) -(declare-function org-element-parse-secondary-string - "org-element" (string restriction &optional buffer)) -(defvar org-element-string-restrictions) -(defvar org-element-object-restrictions) - -(declare-function org-export-clean-table "org-export" (table specialp)) -(declare-function org-export-data "org-export" (data backend info)) -(declare-function org-export-directory "org-export" (type plist)) -(declare-function org-export-expand-macro "org-export" (macro info)) -(declare-function org-export-first-sibling-p "org-export" (headline info)) -(declare-function org-export-footnote-first-reference-p "org-export" - (footnote-reference info)) -(declare-function org-export-get-coderef-format "org-export" (path desc)) -(declare-function org-export-get-footnote-definition "org-export" - (footnote-reference info)) -(declare-function org-export-get-footnote-number "org-export" (footnote info)) -(declare-function org-export-get-previous-element "org-export" (blob info)) -(declare-function org-export-get-relative-level "org-export" (headline info)) -(declare-function org-export-handle-code - "org-export" (element info &optional num-fmt ref-fmt delayed)) -(declare-function org-export-included-file "org-export" (keyword backend info)) -(declare-function org-export-inline-image-p "org-export" - (link &optional extensions)) -(declare-function org-export-last-sibling-p "org-export" (headline info)) -(declare-function org-export-low-level-p "org-export" (headline info)) -(declare-function org-export-output-file-name - "org-export" (extension &optional subtreep pub-dir)) -(declare-function org-export-resolve-coderef "org-export" (ref info)) -(declare-function org-export-resolve-fuzzy-link "org-export" (link info)) -(declare-function org-export-secondary-string "org-export" - (secondary backend info)) -(declare-function org-export-solidify-link-text "org-export" (s)) -(declare-function org-export-table-format-info "org-export" (table)) -(declare-function - org-export-to-buffer "org-export" - (backend buffer &optional subtreep visible-only body-only ext-plist)) -(declare-function - org-export-to-file "org-export" - (backend file &optional subtreep visible-only body-only ext-plist)) - -(declare-function org-id-find-id-file "org-id" (id)) -(declare-function htmlize-region "ext:htmlize" (beg end)) -(declare-function org-pop-to-buffer-same-window - "org-compat" (&optional buffer-or-name norecord label)) - - - - - -(declare-function hfy-face-to-style "htmlfontify" (fn)) -(declare-function hfy-face-or-def-to-name "htmlfontify" (fn)) -(declare-function archive-zip-extract "arc-mode.el" (archive name)) - -;;; Internal Variables - -;;;; ODT Internal Variables - -(defconst org-e-odt-lib-dir - (file-name-directory load-file-name) - "Location of ODT exporter. -Use this to infer values of `org-e-odt-styles-dir' and -`org-export-e-odt-schema-dir'.") - -(defvar org-e-odt-data-dir - (expand-file-name "../etc/" org-e-odt-lib-dir) - "Data directory for ODT exporter. -Use this to infer values of `org-e-odt-styles-dir' and -`org-export-e-odt-schema-dir'.") - - - - -(defconst org-export-e-odt-special-string-regexps - '(("\\\\-" . "­\\1") ; shy - ("---\\([^-]\\)" . "—\\1") ; mdash - ("--\\([^-]\\)" . "–\\1") ; ndash - ("\\.\\.\\." . "…")) ; hellip - "Regular expressions for special string conversion.") - -(defconst org-e-odt-schema-dir-list - (list - (and org-e-odt-data-dir - (expand-file-name "./schema/" org-e-odt-data-dir)) ; bail out - (eval-when-compile - (and (boundp 'org-e-odt-data-dir) org-e-odt-data-dir ; see make install - (expand-file-name "./schema/" org-e-odt-data-dir))) - (expand-file-name "../contrib/odt/etc/schema/" org-e-odt-lib-dir) ; git - ) - "List of directories to search for OpenDocument schema files. -Use this list to set the default value of -`org-export-e-odt-schema-dir'. The entries in this list are -populated heuristically based on the values of `org-e-odt-lib-dir' -and `org-e-odt-data-dir'.") - - -(defconst org-e-odt-styles-dir-list - (list - (and org-e-odt-data-dir - (expand-file-name "./styles/" org-e-odt-data-dir)) ; bail out - (eval-when-compile - (and (boundp 'org-e-odt-data-dir) org-e-odt-data-dir ; see make install - (expand-file-name "./styles/" org-e-odt-data-dir))) - (expand-file-name "../etc/styles/" org-e-odt-lib-dir) ; git - (expand-file-name "./etc/styles/" org-e-odt-lib-dir) ; elpa - (expand-file-name "./org/" data-directory) ; system - ) - "List of directories to search for OpenDocument styles files. -See `org-e-odt-styles-dir'. The entries in this list are populated -heuristically based on the values of `org-e-odt-lib-dir' and -`org-e-odt-data-dir'.") - -(defconst org-e-odt-styles-dir - (let* ((styles-dir - (catch 'styles-dir - (message "Debug (org-e-odt): Searching for OpenDocument styles files...") - (mapc (lambda (styles-dir) - (when styles-dir - (message "Debug (org-e-odt): Trying %s..." styles-dir) - (when (and (file-readable-p - (expand-file-name - "OrgOdtContentTemplate.xml" styles-dir)) - (file-readable-p - (expand-file-name - "OrgOdtStyles.xml" styles-dir))) - (message "Debug (org-e-odt): Using styles under %s" - styles-dir) - (throw 'styles-dir styles-dir)))) - org-e-odt-styles-dir-list) - nil))) - (unless styles-dir - (error "Error (org-e-odt): Cannot find factory styles files. Aborting.")) - styles-dir) - "Directory that holds auxiliary XML files used by the ODT exporter. - -This directory contains the following XML files - - \"OrgOdtStyles.xml\" and \"OrgOdtContentTemplate.xml\". These - XML files are used as the default values of - `org-export-e-odt-styles-file' and - `org-export-e-odt-content-template-file'. - -The default value of this variable varies depending on the -version of org in use and is initialized from -`org-e-odt-styles-dir-list'. Note that the user could be using org -from one of: org's own private git repository, GNU ELPA tar or -standard Emacs.") - -(defconst org-export-e-odt-tmpdir-prefix "%s-") -(defconst org-export-e-odt-bookmark-prefix "OrgXref.") - -(defconst org-e-odt-manifest-file-entry-tag - " -") - - - -(defvar org-lparse-dyn-first-heading-pos) ; let bound during org-do-lparse - -(defvar org-e-odt-suppress-xref nil) -(defvar org-e-odt-file-extensions - '(("odt" . "OpenDocument Text") - ("ott" . "OpenDocument Text Template") - ("odm" . "OpenDocument Master Document") - ("ods" . "OpenDocument Spreadsheet") - ("ots" . "OpenDocument Spreadsheet Template") - ("odg" . "OpenDocument Drawing (Graphics)") - ("otg" . "OpenDocument Drawing Template") - ("odp" . "OpenDocument Presentation") - ("otp" . "OpenDocument Presentation Template") - ("odi" . "OpenDocument Image") - ("odf" . "OpenDocument Formula") - ("odc" . "OpenDocument Chart"))) - -(defvar org-export-e-odt-embed-images t - "Should the images be copied in to the odt file or just linked?") - -(defvar org-export-e-odt-inline-images 'maybe) -(defvar org-export-e-odt-default-org-styles-alist - '((paragraph . ((default . "Text_20_body") - (fixedwidth . "OrgFixedWidthBlock") - (verse . "OrgVerse") - (quote . "Quotations") - (blockquote . "Quotations") - (center . "OrgCenter") - (left . "OrgLeft") - (right . "OrgRight") - (title . "OrgTitle") - (subtitle . "OrgSubtitle") - (footnote . "Footnote") - (src . "OrgSrcBlock") - (illustration . "Illustration") - (table . "Table") - (definition-term . "Text_20_body_20_bold") - (horizontal-line . "Horizontal_20_Line"))) - (character . ((bold . "Bold") - (emphasis . "Emphasis") - (code . "OrgCode") - (verbatim . "OrgCode") - (strike . "Strikethrough") - (underline . "Underline") - (subscript . "OrgSubscript") - (superscript . "OrgSuperscript"))) - (list . ((ordered . "OrgNumberedList") - (unordered . "OrgBulletedList") - (descriptive . "OrgDescriptionList")))) - "Default styles for various entities.") - -(defvar org-export-e-odt-org-styles-alist org-export-e-odt-default-org-styles-alist) - -;;;_. callbacks -;;;_. control callbacks -;;;_ , document body - -(defvar org-lparse-body-only) ; let bound during org-do-lparse -(defvar org-lparse-opt-plist) ; bound during org-do-lparse -(defvar org-lparse-list-stack) ; dynamically bound in org-do-lparse -(defvar org-e-odt-list-stack-stashed) -(defvar org-lparse-table-ncols) -(defvar org-e-odt-table-rowgrp-open) -(defvar org-e-odt-table-rownum) -(defvar org-e-odt-table-cur-rowgrp-is-hdr) -(defvar org-lparse-table-is-styled) -(defvar org-lparse-table-rowgrp-info) -(defvar org-lparse-table-colalign-vector) - -(defvar org-e-odt-table-style nil - "Table style specified by \"#+ATTR_ODT: \" line. -This is set during `org-e-odt-begin-table'.") - -(defvar org-e-odt-table-style-spec nil - "Entry for `org-e-odt-table-style' in `org-export-e-odt-table-styles'.") - - -(defvar org-e-odt-table-style-format - " - - - -" - "Template for auto-generated Table styles.") - -(defvar org-e-odt-automatic-styles '() - "Registry of automatic styles for various OBJECT-TYPEs. -The variable has the following form: -\(\(OBJECT-TYPE-A - \(\(OBJECT-NAME-A.1 OBJECT-PROPS-A.1\) - \(OBJECT-NAME-A.2 OBJECT-PROPS-A.2\) ...\)\) - \(OBJECT-TYPE-B - \(\(OBJECT-NAME-B.1 OBJECT-PROPS-B.1\) - \(OBJECT-NAME-B.2 OBJECT-PROPS-B.2\) ...\)\) - ...\). - -OBJECT-TYPEs could be \"Section\", \"Table\", \"Figure\" etc. -OBJECT-PROPS is (typically) a plist created by passing -\"#+ATTR_ODT: \" option to `org-lparse-get-block-params'. - -Use `org-e-odt-add-automatic-style' to add update this variable.'") - -(defvar org-e-odt-object-counters nil - "Running counters for various OBJECT-TYPEs. -Use this to generate automatic names and style-names. See -`org-e-odt-add-automatic-style'.") - -(defvar org-e-odt-table-indentedp nil) -(defvar org-lparse-table-colalign-info) -(defvar org-lparse-link-description-is-image nil) - - -(defvar org-src-block-paragraph-format - " - - - - - " - "Custom paragraph style for colorized source and example blocks. -This style is much the same as that of \"OrgFixedWidthBlock\" -except that the foreground and background colors are set -according to the default face identified by the `htmlfontify'.") - -(defvar hfy-optimisations) -(defvar org-e-odt-embedded-formulas-count 0) -(defvar org-e-odt-entity-frame-styles - '(("As-CharImage" "__Figure__" ("OrgInlineImage" nil "as-char")) - ("ParagraphImage" "__Figure__" ("OrgDisplayImage" nil "paragraph")) - ("PageImage" "__Figure__" ("OrgPageImage" nil "page")) - ("CaptionedAs-CharImage" "__Figure__" - ("OrgCaptionedImage" - " style:rel-width=\"100%\" style:rel-height=\"scale\"" "paragraph") - ("OrgInlineImage" nil "as-char")) - ("CaptionedParagraphImage" "__Figure__" - ("OrgCaptionedImage" - " style:rel-width=\"100%\" style:rel-height=\"scale\"" "paragraph") - ("OrgImageCaptionFrame" nil "paragraph")) - ("CaptionedPageImage" "__Figure__" - ("OrgCaptionedImage" - " style:rel-width=\"100%\" style:rel-height=\"scale\"" "paragraph") - ("OrgPageImageCaptionFrame" nil "page")) - ("InlineFormula" "__MathFormula__" ("OrgInlineFormula" nil "as-char")) - ("DisplayFormula" "__MathFormula__" ("OrgDisplayFormula" nil "as-char")) - ("CaptionedDisplayFormula" "__MathFormula__" - ("OrgCaptionedFormula" nil "paragraph") - ("OrgFormulaCaptionFrame" nil "as-char")))) - -(defvar org-e-odt-embedded-images-count 0) - -(defvar org-export-e-odt-image-size-probe-method - (append (and (executable-find "identify") '(imagemagick)) ; See Bug#10675 - '(emacs fixed)) - "Ordered list of methods for determining image sizes.") - -(defvar org-export-e-odt-default-image-sizes-alist - '(("as-char" . (5 . 0.4)) - ("paragraph" . (5 . 5))) - "Hardcoded image dimensions one for each of the anchor - methods.") - -;; A4 page size is 21.0 by 29.7 cms -;; The default page settings has 2cm margin on each of the sides. So -;; the effective text area is 17.0 by 25.7 cm -(defvar org-export-e-odt-max-image-size '(17.0 . 20.0) - "Limiting dimensions for an embedded image.") - -(defvar org-e-odt-entity-labels-alist nil - "Associate Labels with the Labeled entities. -Each element of the alist is of the form (LABEL-NAME -CATEGORY-NAME SEQNO LABEL-STYLE-NAME). LABEL-NAME is same as -that specified by \"#+LABEL: ...\" line. CATEGORY-NAME is the -type of the entity that LABEL-NAME is attached to. CATEGORY-NAME -can be one of \"Table\", \"Figure\" or \"Equation\". SEQNO is -the unique number assigned to the referenced entity on a -per-CATEGORY basis. It is generated sequentially and is 1-based. -LABEL-STYLE-NAME is a key `org-e-odt-label-styles'. - -See `org-e-odt-add-label-definition' and -`org-e-odt-fixup-label-references'.") - -(defvar org-e-odt-entity-counts-plist nil - "Plist of running counters of SEQNOs for each of the CATEGORY-NAMEs. -See `org-e-odt-entity-labels-alist' for known CATEGORY-NAMEs.") - -(defvar org-e-odt-label-styles - '(("text" "(%n)" "text" "(%n)") - ("category-and-value" "%e %n%c" "category-and-value" "%e %n") - ("value" "%e %n%c" "value" "%n")) - "Specify how labels are applied and referenced. -This is an alist where each element is of the -form (LABEL-STYLE-NAME LABEL-ATTACH-FMT LABEL-REF-MODE -LABEL-REF-FMT). - -LABEL-ATTACH-FMT controls how labels and captions are attached to -an entity. It may contain following specifiers - %e, %n and %c. -%e is replaced with the CATEGORY-NAME. %n is replaced with -\" SEQNO \". %c is replaced -with CAPTION. See `org-e-odt-format-label-definition'. - -LABEL-REF-MODE and LABEL-REF-FMT controls how label references -are generated. The following XML is generated for a label -reference - \" LABEL-REF-FMT -\". LABEL-REF-FMT may contain following -specifiers - %e and %n. %e is replaced with the CATEGORY-NAME. -%n is replaced with SEQNO. See -`org-e-odt-format-label-reference'.") - -(defvar org-e-odt-category-map-alist - '(("__Table__" "Table" "value") - ("__Figure__" "Figure" "value") - ("__MathFormula__" "Equation" "text") - ("__DvipngImage__" "Equation" "value") - ;; ("__Table__" "Table" "category-and-value") - ;; ("__Figure__" "Figure" "category-and-value") - ;; ("__DvipngImage__" "Equation" "category-and-value") - ) - "Map a CATEGORY-HANDLE to CATEGORY-NAME and LABEL-STYLE. -This is an alist where each element is of the form -\\(CATEGORY-HANDLE CATEGORY-NAME LABEL-STYLE\\). CATEGORY_HANDLE -could either be one of the internal handles (as seen above) or be -derived from the \"#+LABEL:\" specification. See -`org-export-e-odt-get-category-from-label'. CATEGORY-NAME and -LABEL-STYLE are used for generating ODT labels. See -`org-e-odt-label-styles'.") - -(defvar org-export-e-odt-user-categories - '("Illustration" "Table" "Text" "Drawing" "Equation" "Figure")) - -(defvar org-export-e-odt-get-category-from-label nil - "Should category of label be inferred from label itself. -When this option is non-nil, a label is parsed in to two -component parts delimited by a \":\" (colon) as shown here - -#+LABEL:[CATEGORY-HANDLE:]EXTRA. The CATEGORY-HANDLE is mapped -to a CATEGORY-NAME and LABEL-STYLE using -`org-e-odt-category-map-alist'. (If no such map is provided and -CATEGORY-NAME is set to CATEGORY-HANDLE and LABEL-STYLE is set to -\"category-and-value\"). If CATEGORY-NAME so obtained is listed -under `org-export-e-odt-user-categories' then the user specified -styles are used. Otherwise styles as determined by the internal -CATEGORY-HANDLE is used. See -`org-e-odt-get-label-category-and-style' for details.") - -(defvar org-e-odt-manifest-file-entries nil) -(defvar hfy-user-sheet-assoc) ; bound during org-do-lparse -(defvar org-lparse-latex-fragment-fallback) ; set by org-do-lparse - - -;;;; HTML Internal Variables - -(defvar org-e-odt-option-alist - '( - ;; (:agenda-style nil nil org-agenda-export-html-style) - ;; (:convert-org-links nil nil org-e-odt-link-org-files-as-html) - ;; ;; FIXME Use (org-xml-encode-org-text-skip-links s) ?? - ;; ;; (:expand-quoted-html nil "@" org-e-odt-expand) - ;; (:inline-images nil nil org-e-odt-inline-images) - ;; ;; (:link-home nil nil org-e-odt-link-home) FIXME - ;; ;; (:link-up nil nil org-e-odt-link-up) FIXME - ;; (:style nil nil org-e-odt-style) - ;; (:style-extra nil nil org-e-odt-style-extra) - ;; (:style-include-default nil nil org-e-odt-style-include-default) - ;; (:style-include-scripts nil nil org-e-odt-style-include-scripts) - ;; ;; (:timestamp nil nil org-e-odt-with-timestamp) - ;; (:html-extension nil nil org-e-odt-extension) - ;; (:html-postamble nil nil org-e-odt-postamble) - ;; (:html-preamble nil nil org-e-odt-preamble) - ;; (:html-table-tag nil nil org-e-odt-table-tag) - ;; (:xml-declaration nil nil org-e-odt-xml-declaration) - (:LaTeX-fragments nil "LaTeX" org-export-with-LaTeX-fragments)) - "Alist between export properties and ways to set them. - -The car of the alist is the property name, and the cdr is a list -like \(KEYWORD OPTION DEFAULT BEHAVIOUR\) where: - -KEYWORD is a string representing a buffer keyword, or nil. -OPTION is a string that could be found in an #+OPTIONS: line. -DEFAULT is the default value for the property. -BEHAVIOUR determine how Org should handle multiple keywords for -the same property. It is a symbol among: - nil Keep old value and discard the new one. - t Replace old value with the new one. - `space' Concatenate the values, separating them with a space. - `newline' Concatenate the values, separating them with - a newline. - `split' Split values at white spaces, and cons them to the - previous list. - -KEYWORD and OPTION have precedence over DEFAULT. - -All these properties should be back-end agnostic. For back-end -specific properties, define a similar variable named -`org-BACKEND-option-alist', replacing BACKEND with the name of -the appropriate back-end. You can also redefine properties -there, as they have precedence over these.") - -(defvar html-table-tag nil) ; dynamically scoped into this. - -;; FIXME: it already exists in org-e-odt.el -(defconst org-e-odt-cvt-link-fn - nil - "Function to convert link URLs to exportable URLs. -Takes two arguments, TYPE and PATH. -Returns exportable url as (TYPE PATH), or nil to signal that it -didn't handle this case. -Intended to be locally bound around a call to `org-export-as-html'." ) - - - - -(defvar org-e-odt-format-table-no-css) -(defvar htmlize-buffer-places) ; from htmlize.el -(defvar body-only) ; dynamically scoped into this. - -(defvar org-e-odt-table-rowgrp-open) -(defvar org-e-odt-table-rownum) -(defvar org-e-odt-table-cur-rowgrp-is-hdr) -(defvar org-lparse-table-is-styled) - - -(defvar org-e-odt-headline-formatter - (lambda (level snumber todo todo-type priority - title tags target extra-targets extra-class) - (concat snumber " " title))) - - - -;;; User Configuration Variables - -(defgroup org-export-e-odt nil - "Options for exporting Org mode files to HTML." - :tag "Org Export HTML" - :group 'org-export) - -(defcustom org-e-odt-protect-char-alist - '(("&" . "&") - ("<" . "<") - (">" . ">")) - "Alist of characters to be converted by `org-e-html-protect'." - :group 'org-export-e-html - :type '(repeat (cons (string :tag "Character") - (string :tag "ODT equivalent")))) -(defcustom org-export-e-odt-schema-dir - (let* ((schema-dir - (catch 'schema-dir - (message "Debug (org-e-odt): Searching for OpenDocument schema files...") - (mapc - (lambda (schema-dir) - (when schema-dir - (message "Debug (org-e-odt): Trying %s..." schema-dir) - (when (and (file-readable-p - (expand-file-name "od-manifest-schema-v1.2-cs01.rnc" - schema-dir)) - (file-readable-p - (expand-file-name "od-schema-v1.2-cs01.rnc" - schema-dir)) - (file-readable-p - (expand-file-name "schemas.xml" schema-dir))) - (message "Debug (org-e-odt): Using schema files under %s" - schema-dir) - (throw 'schema-dir schema-dir)))) - org-e-odt-schema-dir-list) - (message "Debug (org-e-odt): No OpenDocument schema files installed") - nil))) - schema-dir) - "Directory that contains OpenDocument schema files. - -This directory contains: -1. rnc files for OpenDocument schema -2. a \"schemas.xml\" file that specifies locating rules needed - for auto validation of OpenDocument XML files. - -Use the customize interface to set this variable. This ensures -that `rng-schema-locating-files' is updated and auto-validation -of OpenDocument XML takes place based on the value -`rng-nxml-auto-validate-flag'. - -The default value of this variable varies depending on the -version of org in use and is initialized from -`org-e-odt-schema-dir-list'. The OASIS schema files are available -only in the org's private git repository. It is *not* bundled -with GNU ELPA tar or standard Emacs distribution." - :type '(choice - (const :tag "Not set" nil) - (directory :tag "Schema directory")) - :group 'org-export-e-odt - :version "24.1" - :set - (lambda (var value) - "Set `org-export-e-odt-schema-dir'. -Also add it to `rng-schema-locating-files'." - (let ((schema-dir value)) - (set var - (if (and - (file-readable-p - (expand-file-name "od-manifest-schema-v1.2-cs01.rnc" schema-dir)) - (file-readable-p - (expand-file-name "od-schema-v1.2-cs01.rnc" schema-dir)) - (file-readable-p - (expand-file-name "schemas.xml" schema-dir))) - schema-dir - (when value - (message "Error (org-e-odt): %s has no OpenDocument schema files" - value)) - nil))) - (when org-export-e-odt-schema-dir - (eval-after-load 'rng-loc - '(add-to-list 'rng-schema-locating-files - (expand-file-name "schemas.xml" - org-export-e-odt-schema-dir)))))) - -(defcustom org-export-e-odt-content-template-file nil - "Template file for \"content.xml\". -The exporter embeds the exported content just before -\"\" element. - -If unspecified, the file named \"OrgOdtContentTemplate.xml\" -under `org-e-odt-styles-dir' is used." - :type 'file - :group 'org-export-e-odt - :version "24.1") - -(defcustom org-export-e-odt-styles-file nil - "Default styles file for use with ODT export. -Valid values are one of: -1. nil -2. path to a styles.xml file -3. path to a *.odt or a *.ott file -4. list of the form (ODT-OR-OTT-FILE (FILE-MEMBER-1 FILE-MEMBER-2 -...)) - -In case of option 1, an in-built styles.xml is used. See -`org-e-odt-styles-dir' for more information. - -In case of option 3, the specified file is unzipped and the -styles.xml embedded therein is used. - -In case of option 4, the specified ODT-OR-OTT-FILE is unzipped -and FILE-MEMBER-1, FILE-MEMBER-2 etc are copied in to the -generated odt file. Use relative path for specifying the -FILE-MEMBERS. styles.xml must be specified as one of the -FILE-MEMBERS. - -Use options 1, 2 or 3 only if styles.xml alone suffices for -achieving the desired formatting. Use option 4, if the styles.xml -references additional files like header and footer images for -achieving the desired formatting. - -Use \"#+ODT_STYLES_FILE: ...\" directive to set this variable on -a per-file basis. For example, - -#+ODT_STYLES_FILE: \"/path/to/styles.xml\" or -#+ODT_STYLES_FILE: (\"/path/to/file.ott\" (\"styles.xml\" \"image/hdr.png\"))." - :group 'org-export-e-odt - :version "24.1" - :type - '(choice - (const :tag "Factory settings" nil) - (file :must-match t :tag "styles.xml") - (file :must-match t :tag "ODT or OTT file") - (list :tag "ODT or OTT file + Members" - (file :must-match t :tag "ODF Text or Text Template file") - (cons :tag "Members" - (file :tag " Member" "styles.xml") - (repeat (file :tag "Member")))))) - - -(defcustom org-export-e-odt-inline-image-extensions - '("png" "jpeg" "jpg" "gif") - "Extensions of image files that can be inlined into HTML." - :type '(repeat (string :tag "Extension")) - :group 'org-export-e-odt - :version "24.1") - -(defcustom org-export-e-odt-pixels-per-inch display-pixels-per-inch - "Scaling factor for converting images pixels to inches. -Use this for sizing of embedded images. See Info node `(org) -Images in ODT export' for more information." - :type 'float - :group 'org-export-e-odt - :version "24.1") - -(defcustom org-export-e-odt-create-custom-styles-for-srcblocks t - "Whether custom styles for colorized source blocks be automatically created. -When this option is turned on, the exporter creates custom styles -for source blocks based on the advice of `htmlfontify'. Creation -of custom styles happen as part of `org-e-odt-hfy-face-to-css'. - -When this option is turned off exporter does not create such -styles. - -Use the latter option if you do not want the custom styles to be -based on your current display settings. It is necessary that the -styles.xml already contains needed styles for colorizing to work. - -This variable is effective only if -`org-export-e-odt-fontify-srcblocks' is turned on." - :group 'org-export-e-odt - :version "24.1" - :type 'boolean) - -(defcustom org-export-e-odt-preferred-output-format nil - "Automatically post-process to this format after exporting to \"odt\". -Interactive commands `org-export-as-e-odt' and -`org-export-as-e-odt-and-open' export first to \"odt\" format and -then use `org-export-e-odt-convert-process' to convert the -resulting document to this format. During customization of this -variable, the list of valid values are populated based on -`org-export-e-odt-convert-capabilities'." - :group 'org-export-e-odt - :version "24.1" - :type '(choice :convert-widget - (lambda (w) - (apply 'widget-convert (widget-type w) - (eval (car (widget-get w :args))))) - `((const :tag "None" nil) - ,@(mapcar (lambda (c) - `(const :tag ,c ,c)) - (org-lparse-reachable-formats "odt"))))) - -(defcustom org-export-e-odt-table-styles - '(("OrgEquation" "OrgEquation" - ((use-first-column-styles . t) - (use-last-column-styles . t)))) - "Specify how Table Styles should be derived from a Table Template. -This is a list where each element is of the -form (TABLE-STYLE-NAME TABLE-TEMPLATE-NAME TABLE-CELL-OPTIONS). - -TABLE-STYLE-NAME is the style associated with the table through -`org-e-odt-table-style'. - -TABLE-TEMPLATE-NAME is a set of - upto 9 - automatic -TABLE-CELL-STYLE-NAMEs and PARAGRAPH-STYLE-NAMEs (as defined -below) that is included in -`org-export-e-odt-content-template-file'. - -TABLE-CELL-STYLE-NAME := TABLE-TEMPLATE-NAME + TABLE-CELL-TYPE + - \"TableCell\" -PARAGRAPH-STYLE-NAME := TABLE-TEMPLATE-NAME + TABLE-CELL-TYPE + - \"TableParagraph\" -TABLE-CELL-TYPE := \"FirstRow\" | \"LastColumn\" | - \"FirstRow\" | \"LastRow\" | - \"EvenRow\" | \"OddRow\" | - \"EvenColumn\" | \"OddColumn\" | \"\" -where \"+\" above denotes string concatenation. - -TABLE-CELL-OPTIONS is an alist where each element is of the -form (TABLE-CELL-STYLE-SELECTOR . ON-OR-OFF). -TABLE-CELL-STYLE-SELECTOR := `use-first-row-styles' | - `use-last-row-styles' | - `use-first-column-styles' | - `use-last-column-styles' | - `use-banding-rows-styles' | - `use-banding-columns-styles' | - `use-first-row-styles' -ON-OR-OFF := `t' | `nil' - -For example, with the following configuration - -\(setq org-export-e-odt-table-styles - '\(\(\"TableWithHeaderRowsAndColumns\" \"Custom\" - \(\(use-first-row-styles . t\) - \(use-first-column-styles . t\)\)\) - \(\"TableWithHeaderColumns\" \"Custom\" - \(\(use-first-column-styles . t\)\)\)\)\) - -1. A table associated with \"TableWithHeaderRowsAndColumns\" - style will use the following table-cell styles - - \"CustomFirstRowTableCell\", \"CustomFirstColumnTableCell\", - \"CustomTableCell\" and the following paragraph styles - \"CustomFirstRowTableParagraph\", - \"CustomFirstColumnTableParagraph\", \"CustomTableParagraph\" - as appropriate. - -2. A table associated with \"TableWithHeaderColumns\" style will - use the following table-cell styles - - \"CustomFirstColumnTableCell\", \"CustomTableCell\" and the - following paragraph styles - \"CustomFirstColumnTableParagraph\", \"CustomTableParagraph\" - as appropriate.. - -Note that TABLE-TEMPLATE-NAME corresponds to the -\"\" elements contained within -\"\". The entries (TABLE-STYLE-NAME -TABLE-TEMPLATE-NAME TABLE-CELL-OPTIONS) correspond to -\"table:template-name\" and \"table:use-first-row-styles\" etc -attributes of \"\" element. Refer ODF-1.2 -specification for more information. Also consult the -implementation filed under `org-e-odt-get-table-cell-styles'. - -The TABLE-STYLE-NAME \"OrgEquation\" is used internally for -formatting of numbered display equations. Do not delete this -style from the list." - :group 'org-export-e-odt - :version "24.1" - :type '(choice - (const :tag "None" nil) - (repeat :tag "Table Styles" - (list :tag "Table Style Specification" - (string :tag "Table Style Name") - (string :tag "Table Template Name") - (alist :options (use-first-row-styles - use-last-row-styles - use-first-column-styles - use-last-column-styles - use-banding-rows-styles - use-banding-columns-styles) - :key-type symbol - :value-type (const :tag "True" t)))))) -(defcustom org-export-e-odt-fontify-srcblocks t - "Specify whether or not source blocks need to be fontified. -Turn this option on if you want to colorize the source code -blocks in the exported file. For colorization to work, you need -to make available an enhanced version of `htmlfontify' library." - :type 'boolean - :group 'org-export-e-odt - :version "24.1") - -(defcustom org-export-e-odt-prettify-xml t ; FIXME - "Specify whether or not the xml output should be prettified. -When this option is turned on, `indent-region' is run on all -component xml buffers before they are saved. Turn this off for -regular use. Turn this on if you need to examine the xml -visually." - :group 'org-export-e-odt - :version "24.1" - :type 'boolean) - -(defcustom org-export-e-odt-convert-processes - '(("LibreOffice" - "soffice --headless --convert-to %f%x --outdir %d %i") - ("unoconv" - "unoconv -f %f -o %d %i")) - "Specify a list of document converters and their usage. -The converters in this list are offered as choices while -customizing `org-export-e-odt-convert-process'. - -This variable is a list where each element is of the -form (CONVERTER-NAME CONVERTER-CMD). CONVERTER-NAME is the name -of the converter. CONVERTER-CMD is the shell command for the -converter and can contain format specifiers. These format -specifiers are interpreted as below: - -%i input file name in full -%I input file name as a URL -%f format of the output file -%o output file name in full -%O output file name as a URL -%d output dir in full -%D output dir as a URL. -%x extra options as set in `org-export-e-odt-convert-capabilities'." - :group 'org-export-e-odt - :version "24.1" - :type - '(choice - (const :tag "None" nil) - (alist :tag "Converters" - :key-type (string :tag "Converter Name") - :value-type (group (string :tag "Command line"))))) - -(defcustom org-export-e-odt-convert-process "LibreOffice" - "Use this converter to convert from \"odt\" format to other formats. -During customization, the list of converter names are populated -from `org-export-e-odt-convert-processes'." - :group 'org-export-e-odt - :version "24.1" - :type '(choice :convert-widget - (lambda (w) - (apply 'widget-convert (widget-type w) - (eval (car (widget-get w :args))))) - `((const :tag "None" nil) - ,@(mapcar (lambda (c) - `(const :tag ,(car c) ,(car c))) - org-export-e-odt-convert-processes)))) - -(defcustom org-export-e-odt-convert-capabilities - '(("Text" - ("odt" "ott" "doc" "rtf" "docx") - (("pdf" "pdf") ("odt" "odt") ("rtf" "rtf") ("ott" "ott") - ("doc" "doc" ":\"MS Word 97\"") ("docx" "docx") ("html" "html"))) - ("Web" - ("html") - (("pdf" "pdf") ("odt" "odt") ("html" "html"))) - ("Spreadsheet" - ("ods" "ots" "xls" "csv" "xlsx") - (("pdf" "pdf") ("ots" "ots") ("html" "html") ("csv" "csv") ("ods" "ods") - ("xls" "xls") ("xlsx" "xlsx"))) - ("Presentation" - ("odp" "otp" "ppt" "pptx") - (("pdf" "pdf") ("swf" "swf") ("odp" "odp") ("otp" "otp") ("ppt" "ppt") - ("pptx" "pptx") ("odg" "odg")))) - "Specify input and output formats of `org-export-e-odt-convert-process'. -More correctly, specify the set of input and output formats that -the user is actually interested in. - -This variable is an alist where each element is of the -form (DOCUMENT-CLASS INPUT-FMT-LIST OUTPUT-FMT-ALIST). -INPUT-FMT-LIST is a list of INPUT-FMTs. OUTPUT-FMT-ALIST is an -alist where each element is of the form (OUTPUT-FMT -OUTPUT-FILE-EXTENSION EXTRA-OPTIONS). - -The variable is interpreted as follows: -`org-export-e-odt-convert-process' can take any document that is in -INPUT-FMT-LIST and produce any document that is in the -OUTPUT-FMT-LIST. A document converted to OUTPUT-FMT will have -OUTPUT-FILE-EXTENSION as the file name extension. OUTPUT-FMT -serves dual purposes: -- It is used for populating completion candidates during - `org-export-e-odt-convert' commands. -- It is used as the value of \"%f\" specifier in - `org-export-e-odt-convert-process'. - -EXTRA-OPTIONS is used as the value of \"%x\" specifier in -`org-export-e-odt-convert-process'. - -DOCUMENT-CLASS is used to group a set of file formats in -INPUT-FMT-LIST in to a single class. - -Note that this variable inherently captures how LibreOffice based -converters work. LibreOffice maps documents of various formats -to classes like Text, Web, Spreadsheet, Presentation etc and -allow document of a given class (irrespective of it's source -format) to be converted to any of the export formats associated -with that class. - -See default setting of this variable for an typical -configuration." - :group 'org-export-e-odt - :version "24.1" - :type - '(choice - (const :tag "None" nil) - (alist :tag "Capabilities" - :key-type (string :tag "Document Class") - :value-type - (group (repeat :tag "Input formats" (string :tag "Input format")) - (alist :tag "Output formats" - :key-type (string :tag "Output format") - :value-type - (group (string :tag "Output file extension") - (choice - (const :tag "None" nil) - (string :tag "Extra options")))))))) - -;;;; Debugging - - -;;;; Document - -;;;; Document Header (Styles) - -;;;; Document Header (Scripts) - -;;;; Document Header (Mathjax) - -;;;; Preamble - -;;;; Postamble - -;;;; Emphasis - -;;;; Todos - -;;;; Tags - -;;;; Time-stamps -;;;; Statistics Cookie -;;;; Subscript -;;;; Superscript - -;;;; Inline images - -;;;; Block -;;;; Comment -;;;; Comment Block -;;;; Drawer -;;;; Dynamic Block -;;;; Emphasis -;;;; Entity -;;;; Example Block -;;;; Export Snippet -;;;; Export Block -;;;; Fixed Width -;;;; Footnotes - -;;;; Headline -;;;; Horizontal Rule -;;;; Inline Babel Call -;;;; Inline Src Block -;;;; Inlinetask -;;;; Item -;;;; Keyword -;;;; Latex Environment -;;;; Latex Fragment -;;;; Line Break -;;;; Link -;;;; Babel Call -;;;; Macro -;;;; Paragraph -;;;; Plain List -;;;; Plain Text -;;;; Property Drawer -;;;; Quote Block -;;;; Quote Section -;;;; Section -;;;; Radio Target -;;;; Special Block -;;;; Src Block - -;;;; Table - -;;;; Target -;;;; Time-stamp - -;;;; Verbatim -;;;; Verse Block -;;;; Headline - -;;;; Links -;;;; Drawers -;;;; Inlinetasks -;;;; Publishing - -;;;; Compilation - - - -;;; User Configurable Variables (MAYBE) - -;;;; Preamble - -;;;; Headline - -;;;; Emphasis - -(defcustom org-e-odt-format-headline-function nil - "Function to format headline text. - -This function will be called with 5 arguments: -TODO the todo keyword \(string or nil\). -TODO-TYPE the type of todo \(symbol: `todo', `done', nil\) -PRIORITY the priority of the headline \(integer or nil\) -TEXT the main headline text \(string\). -TAGS the tags string, separated with colons \(string or nil\). - -The function result will be used in the section format string. - -As an example, one could set the variable to the following, in -order to reproduce the default set-up: - -\(defun org-e-odt-format-headline \(todo todo-type priority text tags\) - \"Default format function for an headline.\" - \(concat \(when todo - \(format \"\\\\textbf{\\\\textsc{\\\\textsf{%s}}} \" todo\)\) - \(when priority - \(format \"\\\\framebox{\\\\#%c} \" priority\)\) - text - \(when tags \(format \"\\\\hfill{}\\\\textsc{%s}\" tags\)\)\)\)" - :group 'org-export-e-odt - :type 'function) - -;;;; Footnotes - -;;;; Time-stamps - -(defcustom org-e-odt-active-timestamp-format "\\textit{%s}" - "A printf format string to be applied to active time-stamps." - :group 'org-export-e-odt - :type 'string) - -(defcustom org-e-odt-inactive-timestamp-format "\\textit{%s}" - "A printf format string to be applied to inactive time-stamps." - :group 'org-export-e-odt - :type 'string) - -(defcustom org-e-odt-diary-timestamp-format "\\textit{%s}" - "A printf format string to be applied to diary time-stamps." - :group 'org-export-e-odt - :type 'string) - - -;;;; Links - -(defcustom org-e-odt-image-default-option "width=.9\\linewidth" - "Default option for images." - :group 'org-export-e-odt - :type 'string) - -(defcustom org-e-odt-default-figure-position "htb" - "Default position for latex figures." - :group 'org-export-e-odt - :type 'string) - -(defcustom org-e-odt-inline-image-rules - '(("file" . "\\.\\(pdf\\|jpeg\\|jpg\\|png\\|ps\\|eps\\)\\'")) - "Rules characterizing image files that can be inlined into HTML. - -A rule consists in an association whose key is the type of link -to consider, and value is a regexp that will be matched against -link's path. - -Note that, by default, the image extension *actually* allowed -depend on the way the HTML file is processed. When used with -pdflatex, pdf, jpg and png images are OK. When processing -through dvi to Postscript, only ps and eps are allowed. The -default we use here encompasses both." - :group 'org-export-e-odt - :type '(alist :key-type (string :tag "Type") - :value-type (regexp :tag "Path"))) - -;;;; Tables - -(defcustom org-e-odt-table-caption-above t - "When non-nil, place caption string at the beginning of the table. -Otherwise, place it near the end." - :group 'org-export-e-odt - :type 'boolean) - -;;;; Drawers - -(defcustom org-e-odt-format-drawer-function nil - "Function called to format a drawer in HTML code. - -The function must accept two parameters: - NAME the drawer name, like \"LOGBOOK\" - CONTENTS the contents of the drawer. - -The function should return the string to be exported. - -For example, the variable could be set to the following function -in order to mimic default behaviour: - -\(defun org-e-odt-format-drawer-default \(name contents\) - \"Format a drawer element for HTML export.\" - contents\)" - :group 'org-export-e-odt - :type 'function) - - -;;;; Inlinetasks - -(defcustom org-e-odt-format-inlinetask-function nil - "Function called to format an inlinetask in HTML code. - -The function must accept six parameters: - TODO the todo keyword, as a string - TODO-TYPE the todo type, a symbol among `todo', `done' and nil. - PRIORITY the inlinetask priority, as a string - NAME the inlinetask name, as a string. - TAGS the inlinetask tags, as a string. - CONTENTS the contents of the inlinetask, as a string. - -The function should return the string to be exported. - -For example, the variable could be set to the following function -in order to mimic default behaviour: - -\(defun org-e-odt-format-inlinetask \(todo type priority name tags contents\) -\"Format an inline task element for HTML export.\" - \(let \(\(full-title - \(concat - \(when todo - \(format \"\\\\textbf{\\\\textsf{\\\\textsc{%s}}} \" todo\)\) - \(when priority \(format \"\\\\framebox{\\\\#%c} \" priority\)\) - title - \(when tags \(format \"\\\\hfill{}\\\\textsc{%s}\" tags\)\)\)\)\) - \(format \(concat \"\\\\begin{center}\\n\" - \"\\\\fbox{\\n\" - \"\\\\begin{minipage}[c]{.6\\\\textwidth}\\n\" - \"%s\\n\\n\" - \"\\\\rule[.8em]{\\\\textwidth}{2pt}\\n\\n\" - \"%s\" - \"\\\\end{minipage}}\" - \"\\\\end{center}\"\) - full-title contents\)\)" - :group 'org-export-e-odt - :type 'function) - - -;; Src blocks - -;;;; Plain text - -(defcustom org-e-odt-quotes - '(("fr" ("\\(\\s-\\|[[(]\\)\"" . "«~") ("\\(\\S-\\)\"" . "~»") ("\\(\\s-\\|(\\)'" . "'")) - ("en" ("\\(\\s-\\|[[(]\\)\"" . "``") ("\\(\\S-\\)\"" . "''") ("\\(\\s-\\|(\\)'" . "`"))) - "Alist for quotes to use when converting english double-quotes. - -The CAR of each item in this alist is the language code. -The CDR of each item in this alist is a list of three CONS: -- the first CONS defines the opening quote; -- the second CONS defines the closing quote; -- the last CONS defines single quotes. - -For each item in a CONS, the first string is a regexp -for allowed characters before/after the quote, the second -string defines the replacement string for this quote." - :group 'org-export-e-odt - :type '(list - (cons :tag "Opening quote" - (string :tag "Regexp for char before") - (string :tag "Replacement quote ")) - (cons :tag "Closing quote" - (string :tag "Regexp for char after ") - (string :tag "Replacement quote ")) - (cons :tag "Single quote" - (string :tag "Regexp for char before") - (string :tag "Replacement quote ")))) - - -;;;; Compilation - - - -;;; Internal Functions (HTML) - -;; (defun org-e-odt-format-inline-image (path &optional caption label attr) -;; ;; FIXME: alt text missing here? -;; (let ((inline-image (format "\"%s\"/" -;; path (file-name-nondirectory path)))) -;; (if (not label) inline-image -;; (org-e-odt-format-section inline-image "figure" label)))) - -(defun org-e-odt-format-image (src) - "Create image tag with source and attributes." - (save-match-data - (let* ((caption (org-find-text-property-in-string 'org-caption src)) - (attr (org-find-text-property-in-string 'org-attributes src)) - (label (org-find-text-property-in-string 'org-label src)) - (caption (and caption (org-xml-encode-org-text caption))) - (img-extras (if (string-match "^ltxpng/" src) - (format " alt=\"%s\"" - (org-find-text-property-in-string - 'org-latex-src src)) - (if (string-match "\\" src img-extras)) - (extra (concat - (and label - (format "id=\"%s\" " (org-solidify-link-text label))) - "class=\"figure\""))) - (if caption - (with-temp-buffer - (with-org-lparse-preserve-paragraph-state - (insert - (org-lparse-format - '("
" . "\n
") - (concat - (org-lparse-format '("\n

" . "

") img) - (org-lparse-format '("\n

" . "

") caption)) - extra))) - (buffer-string)) - img)))) - -;;;; Bibliography - -(defun org-e-odt-bibliography () - "Find bibliography, cut it out and return it." - (catch 'exit - (let (beg end (cnt 1) bib) - (save-excursion - (goto-char (point-min)) - (when (re-search-forward - "^[ \t]*
" nil t) - (setq cnt (+ cnt (if (string= (match-string 0) "") (forward-char 1)) - (setq bib (buffer-substring beg (point))) - (delete-region beg (point)) - (throw 'exit bib)))) - nil)))) - -;;;; Table - -(defun org-e-odt-format-table (lines olines) - (let ((org-e-odt-format-table-no-css nil)) - (org-lparse-format-table lines olines))) - -(defun org-e-odt-splice-attributes (tag attributes) - "Read attributes in string ATTRIBUTES, add and replace in HTML tag TAG." - (if (not attributes) - tag - (let (oldatt newatt) - (setq oldatt (org-extract-attributes-from-string tag) - tag (pop oldatt) - newatt (cdr (org-extract-attributes-from-string attributes))) - (while newatt - (setq oldatt (plist-put oldatt (pop newatt) (pop newatt)))) - (if (string-match ">" tag) - (setq tag - (replace-match (concat (org-attributes-to-string oldatt) ">") - t t tag))) - tag))) - -(defun org-export-splice-style (style extra) - "Splice EXTRA into STYLE, just before \"\"." - (if (and (stringp extra) - (string-match "\\S-" extra) - (string-match "" style)) - (concat (substring style 0 (match-beginning 0)) - "\n" extra "\n" - (substring style (match-beginning 0))) - style)) - -;; (defun org-e-odt-format-toc-entry (snumber todo headline tags href) -;; (setq headline (concat -;; ;; section number -;; (and org-export-with-section-numbers (concat snumber " ")) -;; ;; headline -;; headline -;; ;; tags -;; (and tags (concat -;; (org-e-odt-format-spaces 3) -;; (org-e-odt-format-fontify tags "tag"))))) -;; ;; fontify headline based on TODO keyword -;; (when todo (setq headline (org-e-odt-format-fontify headline "todo"))) -;; (org-e-odt-format-link headline (concat "#" href))) - -(defun org-e-odt-toc-entry-formatter - (level snumber todo todo-type priority - headline tags target extra-targets extra-class) - (org-e-odt-format-toc-entry snumber todo headline tags target)) - -(defun org-e-odt-make-string (n string) - (let (out) (dotimes (i n out) (setq out (concat string out))))) - -(defun org-e-odt-toc-text (toc-entries) - (let* ((prev-level (1- (nth 1 (car toc-entries)))) - (start-level prev-level)) - (mapconcat - (lambda (entry) - (let ((headline (nth 0 entry)) - (level (nth 1 entry))) - (prog1 (org-e-odt-format-toc-item headline level prev-level) - (setq prev-level level)))) - toc-entries ""))) - -(defun org-e-odt-toc (depth info) - (assert (wholenump depth)) - (let* ((headlines (org-export-collect-headlines info depth)) - (toc-entries - (loop for headline in headlines collect - (list (org-e-odt-headline-text - headline info 'org-e-odt-toc-entry-formatter) - (org-export-get-relative-level headline info))))) - (when toc-entries - (let* ((lang-specific-heading "Table of Contents")) ; FIXME - (concat - (org-e-odt-begin-toc lang-specific-heading depth) - (org-e-odt-toc-text toc-entries) - (org-e-odt-end-toc)))))) - -(defun org-e-odt-begin-outline (level1 snumber title tags - target extra-targets extra-class) - (let* ((class (format "outline-%d" level1)) - (class (if extra-class (concat class " " extra-class) class)) - (id (format "outline-container-%s" - (org-lparse-suffix-from-snumber snumber))) - (extra (concat (when id (format " id=\"%s\"" id)) - (when class (format " class=\"%s\"" class))))) - (org-lparse-insert-tag "" extra) - (insert - (org-lparse-format 'HEADING - (org-lparse-format - 'HEADLINE title extra-targets tags snumber level1) - level1 target)))) - -(defun org-e-odt-end-outline () - (org-lparse-insert-tag "
")) - -(defun org-e-odt-suffix-from-snumber (snumber) - (let* ((snu (replace-regexp-in-string "\\." "-" snumber)) - (href (cdr (assoc (concat "sec-" snu) - org-export-preferred-target-alist)))) - (org-solidify-link-text (or href snu)))) - -(defun org-e-odt-format-outline (contents level1 snumber title - tags target extra-targets extra-class) - (concat - (org-e-odt-format-heading - (org-e-odt-format-headline title extra-targets tags snumber level1) - level1 target) - contents)) - -;; (defun org-e-odt-format-line (line) -;; (case org-lparse-dyn-current-environment -;; ((quote fixedwidth) (concat (org-e-odt-encode-plain-text line) "\n")) -;; (t (concat line "\n")))) - -(defun org-e-odt-fix-class-name (kwd) ; audit callers of this function - "Turn todo keyword into a valid class name. -Replaces invalid characters with \"_\"." - (save-match-data - (while (string-match "[^a-zA-Z0-9_]" kwd) - (setq kwd (replace-match "_" t t kwd)))) - kwd) - -(defun org-e-odt-format-internal-link (text href &optional extra) - (org-e-odt-format-link text (concat "#" href) extra)) - -(defun org-e-odt-format-extra-targets (extra-targets) - (if (not extra-targets) "" - (mapconcat (lambda (x) - (when x - (setq x (org-solidify-link-text - (if (org-uuidgen-p x) (concat "ID-" x) x))) - (org-e-odt-format-anchor "" x))) extra-targets ""))) - -(defun org-e-odt-format-org-tags (tags) - (if (not tags) "" - (org-e-odt-format-fontify - (mapconcat - (lambda (x) - (org-e-odt-format-fontify - x (concat "" ;; org-e-odt-tag-class-prefix - (org-e-odt-fix-class-name x)))) - (org-split-string tags ":") - (org-e-odt-format-spaces 1)) "tag"))) - -(defun org-e-odt-format-section-number (&optional snumber level) - ;; FIXME - (and nil org-export-with-section-numbers - ;; (not org-lparse-body-only) - snumber level - (org-e-odt-format-fontify snumber (format "section-number-%d" level)))) - -;; (defun org-e-odt-format-headline (title extra-targets tags -;; &optional snumber level) -;; (concat -;; (org-e-odt-format-extra-targets extra-targets) -;; (concat (org-e-odt-format-section-number snumber level) " ") -;; title -;; (and tags (concat (org-e-odt-format-spaces 3) -;; (org-e-odt-format-org-tags tags))))) - -(defun org-e-odt-get-coding-system-for-write () - (or org-e-odt-coding-system - (and (boundp 'buffer-file-coding-system) buffer-file-coding-system))) - -(defun org-e-odt-get-coding-system-for-save () - (or org-e-odt-coding-system - (and (boundp 'buffer-file-coding-system) buffer-file-coding-system))) - -;; (defun org-e-odt-format-date (info) -;; (let ((date (plist-get info :date))) -;; (cond -;; ((and date (string-match "%" date)) -;; (format-time-string date)) -;; (date date) -;; (t (format-time-string "%Y-%m-%d %T %Z"))))) - - - -;;; Internal Functions (Ngz) - -(defun org-e-odt--caption/label-string (caption label info) - "Return caption and label HTML string for floats. - -CAPTION is a cons cell of secondary strings, the car being the -standard caption and the cdr its short form. LABEL is a string -representing the label. INFO is a plist holding contextual -information. - -If there's no caption nor label, return the empty string. - -For non-floats, see `org-e-odt--wrap-label'." - (setq label nil) ;; FIXME - - (let ((label-str (if label (format "\\label{%s}" label) ""))) - (cond - ((and (not caption) (not label)) "") - ((not caption) (format "\\label{%s}\n" label)) - ;; Option caption format with short name. - ((cdr caption) - (format "\\caption[%s]{%s%s}\n" - (org-export-secondary-string (cdr caption) 'e-odt info) - label-str - (org-export-secondary-string (car caption) 'e-odt info))) - ;; Standard caption format. - ;; (t (format "\\caption{%s%s}\n" - ;; label-str - ;; (org-export-secondary-string (car caption) 'e-odt info))) - - (t (org-export-secondary-string (car caption) 'e-odt info))))) - -(defun org-e-odt--find-verb-separator (s) - "Return a character not used in string S. -This is used to choose a separator for constructs like \\verb." - (let ((ll "~,./?;':\"|!@#%^&-_=+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ<>()[]{}")) - (loop for c across ll - when (not (string-match (regexp-quote (char-to-string c)) s)) - return (char-to-string c)))) - -(defun org-e-odt--make-option-string (options) - "Return a comma separated string of keywords and values. -OPTIONS is an alist where the key is the options keyword as -a string, and the value a list containing the keyword value, or -nil." - (mapconcat (lambda (pair) - (concat (first pair) - (when (> (length (second pair)) 0) - (concat "=" (second pair))))) - options - ",")) - -(defun org-e-odt--quotation-marks (text info) - "Export quotation marks depending on language conventions. -TEXT is a string containing quotation marks to be replaced. INFO -is a plist used as a communication channel." - (mapc (lambda(l) - (let ((start 0)) - (while (setq start (string-match (car l) text start)) - (let ((new-quote (concat (match-string 1 text) (cdr l)))) - (setq text (replace-match new-quote t t text)))))) - (cdr (or (assoc (plist-get info :language) org-e-odt-quotes) - ;; Falls back on English. - (assoc "en" org-e-odt-quotes)))) - text) - -(defun org-e-odt--wrap-label (element output) - "Wrap label associated to ELEMENT around OUTPUT, if appropriate. -This function shouldn't be used for floats. See -`org-e-odt--caption/label-string'." - ;; (let ((label (org-element-property :name element))) - ;; (if (or (not output) (not label) (string= output "") (string= label "")) - ;; output - ;; (concat (format "\\label{%s}\n" label) output))) - output) - - - -;;; Transcode Helpers - -;;;; Src Code - -(defun org-e-odt-htmlfontify-string (line) - (let* ((hfy-html-quote-regex "\\([<\"&> ]\\)") - (hfy-html-quote-map '(("\"" """) - ("<" "<") - ("&" "&") - (">" ">") - (" " "") - (" " ""))) - (hfy-face-to-css 'org-e-odt-hfy-face-to-css) - (hfy-optimisations-1 (copy-seq hfy-optimisations)) - (hfy-optimisations (add-to-list 'hfy-optimisations-1 - 'body-text-only)) - (hfy-begin-span-handler - (lambda (style text-block text-id text-begins-block-p) - (insert (format "" style)))) - (hfy-end-span-handler (lambda nil (insert "")))) - (htmlfontify-string line))) - -(defun org-e-odt-do-format-code - (code &optional lang refs retain-labels num-start) - (let* ((lang (or (assoc-default lang org-src-lang-modes) lang)) - (lang-mode (and lang (intern (format "%s-mode" lang)))) - (code-lines (org-split-string code "\n")) - (code-length (length code-lines)) - (use-htmlfontify-p (and (functionp lang-mode) - org-export-e-odt-fontify-srcblocks - (require 'htmlfontify nil t) - (fboundp 'htmlfontify-string))) - (code (if (not use-htmlfontify-p) code - (with-temp-buffer - (insert code) - (funcall lang-mode) - (font-lock-fontify-buffer) - (buffer-string)))) - (fontifier (if use-htmlfontify-p 'org-e-odt-htmlfontify-string - 'org-e-odt-encode-plain-text)) - (par-style (if use-htmlfontify-p "OrgSrcBlock" - "OrgFixedWidthBlock")) - (i 0)) - (assert (= code-length (length (org-split-string code "\n")))) - (setq code - (org-export-format-code - code - (lambda (loc line-num ref) - (setq par-style - (concat par-style (and (= (incf i) code-length) "LastLine"))) - - (setq loc (concat loc (and ref retain-labels (format " (%s)" ref)))) - (setq loc (funcall fontifier loc)) - (when ref - (setq loc (org-e-odt-format-target loc (concat "coderef-" ref)))) - (setq loc (org-e-odt-format-stylized-paragraph par-style loc)) - (if (not line-num) loc - (org-e-odt-format-tags - '("" . "") loc))) - num-start refs)) - (cond - ((not num-start) code) - ((equal num-start 0) - (org-e-odt-format-tags - '("" - . "") code " text:continue-numbering=\"false\"")) - (t (org-e-odt-format-tags - '("" - . "") code " text:continue-numbering=\"true\""))))) - -(defun org-e-odt-format-code (element info) - (let* ((lang (org-element-property :language element)) - ;; Extract code and references. - (code-info (org-export-unravel-code element)) - (code (car code-info)) - (refs (cdr code-info)) - ;; Does the src block contain labels? - (retain-labels (org-element-property :retain-labels element)) - ;; Does it have line numbers? - (num-start (case (org-element-property :number-lines element) - (continued (org-export-get-loc element info)) - (new 0)))) - (org-e-odt-do-format-code code lang refs retain-labels num-start))) - - - -;;; Template - -(defun org-e-odt-template (contents info) - "Return complete document string after HTML conversion. -CONTENTS is the transcoded contents string. RAW-DATA is the -original parsed data. INFO is a plist holding export options." - - - ;; write meta file - (org-e-odt-update-meta-file info) - - - (with-temp-buffer - (insert-file-contents - (or org-export-e-odt-content-template-file - (expand-file-name "OrgOdtContentTemplate.xml" - org-e-odt-styles-dir))) - (goto-char (point-min)) - (re-search-forward "" nil nil) - (goto-char (match-beginning 0)) - - ;; Title - (insert (org-e-odt-format-preamble info)) - ;; Table of Contents - (let ((depth (plist-get info :with-toc))) - (when (wholenump depth) (org-e-odt-toc depth info))) - - ;; Contents - (insert contents) - (buffer-substring-no-properties (point-min) (point-max)))) - - - -;;; Transcode Functions - -;;;; Block - -(defun org-e-odt-center-block (center-block contents info) - "Transcode a CENTER-BLOCK element from Org to HTML. -CONTENTS holds the contents of the block. INFO is a plist -holding contextual information." - (org-e-odt--wrap-label center-block contents)) - - -;;;; Comment - -;; Comments are ignored. - - -;;;; Comment Block - -;; Comment Blocks are ignored. - - -;;;; Drawer - -(defun org-e-odt-drawer (drawer contents info) - "Transcode a DRAWER element from Org to HTML. -CONTENTS holds the contents of the block. INFO is a plist -holding contextual information." - (let* ((name (org-element-property :drawer-name drawer)) - (output (if (functionp org-e-odt-format-drawer-function) - (funcall org-e-odt-format-drawer-function - name contents) - ;; If there's no user defined function: simply - ;; display contents of the drawer. - contents))) - (org-e-odt--wrap-label drawer output))) - - -;;;; Dynamic Block - -(defun org-e-odt-dynamic-block (dynamic-block contents info) - "Transcode a DYNAMIC-BLOCK element from Org to HTML. -CONTENTS holds the contents of the block. INFO is a plist -holding contextual information. See -`org-export-data'." - (org-e-odt--wrap-label dynamic-block contents)) - - -;;;; Emphasis - -(defun org-e-odt-emphasis (emphasis contents info) - "Transcode EMPHASIS from Org to HTML. -CONTENTS is the contents of the emphasized text. INFO is a plist -holding contextual information.." - ;; (format (cdr (assoc (org-element-property :marker emphasis) - ;; org-e-odt-emphasis-alist)) - ;; contents) - (org-e-odt-format-fontify - contents (cadr (assoc - (org-element-property :marker emphasis) - '(("*" bold) - ("/" emphasis) - ("_" underline) - ("=" code) - ("~" verbatim) - ("+" strike)))))) - - -;;;; Entity - -(defun org-e-odt-entity (entity contents info) - "Transcode an ENTITY object from Org to HTML. -CONTENTS are the definition itself. INFO is a plist holding -contextual information." - ;; (let ((ent (org-element-property :latex entity))) - ;; (if (org-element-property :latex-math-p entity) - ;; (format "$%s$" ent) - ;; ent)) - (org-element-property :utf-8 entity)) - - -;;;; Example Block - -(defun org-e-odt-example-block (example-block contents info) - "Transcode a EXAMPLE-BLOCK element from Org to HTML. -CONTENTS is nil. INFO is a plist holding contextual information." - (let* ((options (or (org-element-property :options example-block) "")) - (value (org-export-handle-code example-block info nil nil t))) - (org-e-odt--wrap-label - example-block (org-e-odt-format-source-code-or-example value nil)))) - - -;;;; Export Snippet - -(defun org-e-odt-export-snippet (export-snippet contents info) - "Transcode a EXPORT-SNIPPET object from Org to HTML. -CONTENTS is nil. INFO is a plist holding contextual information." - (when (eq (org-export-snippet-backend export-snippet) 'e-odt) - (org-element-property :value export-snippet))) - - -;;;; Export Block - -(defun org-e-odt-export-block (export-block contents info) - "Transcode a EXPORT-BLOCK element from Org to HTML. -CONTENTS is nil. INFO is a plist holding contextual information." - (when (string= (org-element-property :type export-block) "latex") - (org-remove-indentation (org-element-property :value export-block)))) - - -;;;; Fixed Width - -(defun org-e-odt-fixed-width (fixed-width contents info) - "Transcode a FIXED-WIDTH element from Org to HTML. -CONTENTS is nil. INFO is a plist holding contextual information." - (let* ((value (org-element-normalize-string - (replace-regexp-in-string - "^[ \t]*: ?" "" - (org-element-property :value fixed-width))))) - (org-e-odt--wrap-label - fixed-width (org-e-odt-format-source-code-or-example value nil)))) - - -;;;; Footnote Definition - -;; Footnote Definitions are ignored. - - -;;;; Footnote Reference - -(defun org-e-odt-footnote-def (raw info) ; FIXME - (if (equal (org-element-type raw) 'org-data) - (org-trim (org-export-data raw 'e-odt info)) ; fix paragraph - ; style - (org-odt-format-stylized-paragraph - 'footnote (org-trim (org-export-secondary-string raw 'e-odt info))))) - -(defvar org-e-odt-footnote-separator - (org-e-odt-format-fontify "," 'superscript)) - -(defun org-e-odt-footnote-reference (footnote-reference contents info) - "Transcode a FOOTNOTE-REFERENCE element from Org to HTML. -CONTENTS is nil. INFO is a plist holding contextual information." - (concat - ;; Insert separator between two footnotes in a row. - (let ((prev (org-export-get-previous-element footnote-reference info))) - (when (eq (org-element-type prev) 'footnote-reference) - org-e-odt-footnote-separator)) - (cond - ((not (org-export-footnote-first-reference-p footnote-reference info)) - (let* ((n (org-export-get-footnote-number footnote-reference info))) - (org-e-odt-format-footnote-reference n "IGNORED" 100))) - ;; Inline definitions are secondary strings. - ((eq (org-element-property :type footnote-reference) 'inline) - (let* ((raw (org-export-get-footnote-definition footnote-reference info)) - (n (org-export-get-footnote-number footnote-reference info)) - (def (org-e-odt-footnote-def raw info))) - (org-e-odt-format-footnote-reference n def 1))) - ;; Non-inline footnotes definitions are full Org data. - (t - (let* ((raw (org-export-get-footnote-definition footnote-reference info)) - (n (org-export-get-footnote-number footnote-reference info)) - (def (org-e-odt-footnote-def raw info))) - (org-e-odt-format-footnote-reference n def 1)))))) - - -;;;; Headline - -(defun org-e-odt-todo (todo) - (when todo - (org-e-odt-format-fontify - (concat - "" ; org-e-odt-todo-kwd-class-prefix - (org-e-odt-fix-class-name todo)) - (list (if (member todo org-done-keywords) "done" "todo") - todo)))) - -(defun org-e-odt-headline-text (headline info &optional formatter) - "Transcode an HEADLINE element from Org to HTML. -CONTENTS holds the contents of the headline. INFO is a plist -holding contextual information." - (let* ((numberedp (org-export-numbered-headline-p headline info)) - (level (org-export-get-relative-level headline info)) - (todo (and (plist-get info :with-todo-keywords) - (let ((todo (org-element-property - :todo-keyword headline))) - (and todo - (org-export-secondary-string todo 'e-odt info))))) - (todo-type (and todo (org-element-property :todo-type headline))) - (priority (and (plist-get info :with-priority) - (org-element-property :priority headline))) - (text (org-export-secondary-string - (org-element-property :title headline) 'e-odt info)) - (tags (and (plist-get info :with-tags) - (org-element-property :tags headline))) - - (headline-no (org-export-get-headline-number headline info)) - (headline-label - (format "sec-%s" (mapconcat 'number-to-string headline-no "-"))) - (headline-labels (list headline-label)) - (headline-no (org-export-get-headline-number headline info)) - (section-no (mapconcat 'number-to-string headline-no ".")) - (primary-target (car (last headline-labels))) - (secondary-targets (butlast headline-labels)) - (extra-class nil) - (formatter (or (and (functionp formatter) formatter) - org-e-odt-headline-formatter))) - (funcall formatter level section-no todo todo-type priority - text tags primary-target secondary-targets extra-class))) - -(defun org-e-odt-headline (headline contents info) - "Transcode an HEADLINE element from Org to HTML. -CONTENTS holds the contents of the headline. INFO is a plist -holding contextual information." - (let* ((class (plist-get info :latex-class)) - (numberedp (org-export-numbered-headline-p headline info)) - ;; Get level relative to current parsed data. - (level (org-export-get-relative-level headline info)) - ;; (class-sectionning (assoc class org-e-odt-classes)) - ;; Section formatting will set two placeholders: one for the - ;; title and the other for the contents. - ;; (section-fmt - ;; (let ((sec (if (and (symbolp (nth 2 class-sectionning)) - ;; (fboundp (nth 2 class-sectionning))) - ;; (funcall (nth 2 class-sectionning) level numberedp) - ;; (nth (1+ level) class-sectionning)))) - ;; (cond - ;; ;; No section available for that LEVEL. - ;; ((not sec) nil) - ;; ;; Section format directly returned by a function. - ;; ((stringp sec) sec) - ;; ;; (numbered-section . unnumbered-section) - ;; ((not (consp (cdr sec))) - ;; (concat (funcall (if numberedp #'car #'cdr) sec) "\n%s")) - ;; ;; (numbered-open numbered-close) - ;; ((= (length sec) 2) - ;; (when numberedp (concat (car sec) "\n%s" (nth 1 sec)))) - ;; ;; (num-in num-out no-num-in no-num-out) - ;; ((= (length sec) 4) - ;; (if numberedp - ;; (concat (car sec) "\n%s" (nth 1 sec)) - ;; (concat (nth 2 sec) "\n%s" (nth 3 sec))))))) - (text (org-export-secondary-string - (org-element-property :title headline) 'e-odt info)) - (todo (and (plist-get info :with-todo-keywords) - (let ((todo (org-element-property - :todo-keyword headline))) - (and todo - (org-export-secondary-string todo 'e-odt info))))) - (todo-type (and todo (org-element-property :todo-type headline))) - (tags (and (plist-get info :with-tags) - (org-element-property :tags headline))) - (priority (and (plist-get info :with-priority) - (org-element-property :priority headline))) - ;; Create the headline text. - (full-text (if (functionp org-e-odt-format-headline-function) - ;; User-defined formatting function. - (funcall org-e-odt-format-headline-function - todo todo-type priority text tags) - ;; Default formatting. - (concat - ;; (when todo - ;; (format "\\textbf{\\textsf{\\textsc{%s}}} " todo)) - (org-e-odt-todo todo) " " - (when priority (format "\\framebox{\\#%c} " priority)) - text - ;; (when tags (format "\\hfill{}\\textsc{%s}" tags)) - ))) - ;; Associate some \label to the headline for internal links. - ;; (headline-label - ;; (format "\\label{sec-%s}\n" - ;; (mapconcat 'number-to-string - ;; (org-export-get-headline-number headline info) - ;; "-"))) - - ;; FIXME - begin - (headline-no (org-export-get-headline-number headline info)) - (headline-label - (format "sec-%s" (mapconcat 'number-to-string headline-no "-"))) - (headline-labels (list headline-label)) - (headline-no (org-export-get-headline-number headline info)) - (section-no (mapconcat 'number-to-string headline-no ".")) - ;; FIXME - end - - (pre-blanks (make-string - (org-element-property :pre-blank headline) 10))) - (cond - ;; Case 1: This is a footnote section: ignore it. - ((org-element-property :footnote-section-p headline) nil) - ;; Case 2. This is a deep sub-tree: export it as a list item. - ;; Also export as items headlines for which no section - ;; format has been found. - ((org-export-low-level-p headline info) ; FIXME (or (not section-fmt)) - ;; Build the real contents of the sub-tree. - (let* ((type (if numberedp 'unordered 'unordered)) ; FIXME - (itemized-body (org-e-odt-format-list-item - contents type nil nil full-text))) - (concat - (and (org-export-first-sibling-p headline info) - (org-e-odt-begin-plain-list type)) - itemized-body - (and (org-export-last-sibling-p headline info) - (org-e-odt-end-plain-list type))))) - ;; Case 3. Standard headline. Export it as a section. - (t - ;; (format section-fmt full-text - ;; (concat headline-label pre-blanks contents)) - - (org-e-odt-format-outline contents level section-no full-text tags - (car (last headline-labels)) - (butlast headline-labels) nil))))) - - -;;;; Horizontal Rule - -(defun org-e-odt-horizontal-rule (horizontal-rule contents info) - "Transcode an HORIZONTAL-RULE object from Org to HTML. -CONTENTS is nil. INFO is a plist holding contextual information." - (let ((attr (mapconcat #'identity - (org-element-property :attr_odt horizontal-rule) - " "))) - (org-e-odt--wrap-label horizontal-rule - (org-e-odt-format-horizontal-line)))) - - -;;;; Inline Babel Call - -;; Inline Babel Calls are ignored. - - -;;;; Inline Src Block - -(defun org-e-odt-inline-src-block (inline-src-block contents info) - "Transcode an INLINE-SRC-BLOCK element from Org to HTML. -CONTENTS holds the contents of the item. INFO is a plist holding -contextual information." - (let* ((org-lang (org-element-property :language inline-src-block)) - (code (org-element-property :value inline-src-block)) - (separator (org-e-odt--find-verb-separator code))) - (error "FIXME"))) - - -;;;; Inlinetask - -(defun org-e-odt-format-section (text class &optional id) - (let ((extra (concat (when id (format " id=\"%s\"" id))))) - (concat (format "
\n" class extra) text "
\n"))) - -(defun org-e-odt-inlinetask (inlinetask contents info) - "Transcode an INLINETASK element from Org to HTML. -CONTENTS holds the contents of the block. INFO is a plist -holding contextual information." - (let ((title (org-export-secondary-string - (org-element-property :title inlinetask) 'e-odt info)) - (todo (and (plist-get info :with-todo-keywords) - (let ((todo (org-element-property - :todo-keyword inlinetask))) - (and todo - (org-export-secondary-string todo 'e-odt info))))) - (todo-type (org-element-property :todo-type inlinetask)) - (tags (and (plist-get info :with-tags) - (org-element-property :tags inlinetask))) - (priority (and (plist-get info :with-priority) - (org-element-property :priority inlinetask)))) - ;; If `org-e-odt-format-inlinetask-function' is provided, call it - ;; with appropriate arguments. - (if (functionp org-e-odt-format-inlinetask-function) - (funcall org-e-odt-format-inlinetask-function - todo todo-type priority title tags contents) - ;; Otherwise, use a default template. - (org-e-odt--wrap-label - inlinetask - (let ((full-title - (concat - (when todo (format "\\textbf{\\textsf{\\textsc{%s}}} " todo)) - (when priority (format "\\framebox{\\#%c} " priority)) - title - (when tags (format "\\hfill{}\\textsc{%s}" tags))))) - (format (concat "\\begin{center}\n" - "\\fbox{\n" - "\\begin{minipage}[c]{.6\\textwidth}\n" - "%s\n\n" - "\\rule[.8em]{\\textwidth}{2pt}\n\n" - "%s" - "\\end{minipage}\n" - "}\n" - "\\end{center}") - full-title contents)))))) - - -;;;; Item - -(defun org-e-odt-format-list-item (contents type checkbox - &optional term-counter-id - headline) - (when checkbox - (setq checkbox - (org-e-odt-format-fontify (case checkbox - (on "[X]") - (off "[ ]") - (trans "[-]")) 'code))) - (concat - (org-e-odt-begin-list-item type term-counter-id headline) - ;; FIXME checkbox (and checkbox " ") - contents - (org-e-odt-end-list-item type))) - -(defun org-e-odt-item (item contents info) - "Transcode an ITEM element from Org to HTML. -CONTENTS holds the contents of the item. INFO is a plist holding -contextual information." - ;; Grab `:level' from plain-list properties, which is always the - ;; first element above current item. - (let* ((plain-list (org-export-get-parent item info)) - (type (org-element-property :type plain-list)) - (level (org-element-property :level plain-list)) - (counter (org-element-property :counter item)) - (checkbox (org-element-property :checkbox item)) - (tag (let ((tag (org-element-property :tag item))) - (and tag (org-export-secondary-string tag 'e-odt info))))) - (org-e-odt-format-list-item - contents type checkbox (or tag counter)))) - - -;;;; Keyword - -(defun org-e-odt-keyword (keyword contents info) - "Transcode a KEYWORD element from Org to HTML. -CONTENTS is nil. INFO is a plist holding contextual information." - (let ((key (downcase (org-element-property :key keyword))) - (value (org-element-property :value keyword))) - (cond - ((string= key "latex") value) - ((string= key "index") (format "\\index{%s}" value)) - ((string= key "target") nil ; FIXME - ;; (format "\\label{%s}" (org-export-solidify-link-text value)) - ) - ((string= key "toc") - (let ((value (downcase value))) - (cond - ((string-match "\\" value) - (let ((depth (or (and (string-match "[0-9]+" value) - (string-to-number (match-string 0 value))) - (plist-get info :with-toc)))) - (when (wholenump depth) (org-e-odt-toc depth info)))) - ((string= "tables" value) "FIXME") - ((string= "figures" value) "FIXME") - ((string= "listings" value) - (cond - ;; At the moment, src blocks with a caption are wrapped - ;; into a figure environment. - (t "FIXME"))))))))) - - -;;;; Latex Environment - -(defun org-e-odt-format-latex (latex-frag processing-type) - (let* ((prefix (case processing-type - (dvipng "ltxpng/") - (mathml "ltxmathml/"))) - (cache-relpath - (concat prefix (file-name-sans-extension - (file-name-nondirectory (buffer-file-name))))) - (cache-dir (file-name-directory (buffer-file-name ))) - (display-msg (case processing-type - (dvipng "Creating LaTeX Image...") - (mathml "Creating MathML snippet...")))) - (with-temp-buffer - (insert latex-frag) - (org-format-latex cache-relpath cache-dir nil display-msg - nil nil processing-type) - (buffer-string)))) - -(defun org-e-odt-latex-environment (latex-environment contents info) - "Transcode a LATEX-ENVIRONMENT element from Org to HTML. -CONTENTS is nil. INFO is a plist holding contextual information." - (org-e-odt--wrap-label - latex-environment - (let ((latex-frag - (org-remove-indentation - (org-element-property :value latex-environment))) - (processing-type (plist-get info :LaTeX-fragments))) - (cond - ((member processing-type '(t mathjax)) - (org-e-odt-format-latex latex-frag 'mathml)) - ((equal processing-type 'dvipng) - (let* ((formula-link (org-e-odt-format-latex - latex-frag processing-type))) - (when (and formula-link - (string-match "file:\\([^]]*\\)" formula-link)) - (org-e-odt-format-inline-image (match-string 1 formula-link))))) - (t - latex-frag))))) - - -;;;; Latex Fragment - -(defun org-e-odt-latex-fragment (latex-fragment contents info) - "Transcode a LATEX-FRAGMENT object from Org to HTML. -CONTENTS is nil. INFO is a plist holding contextual information." - ;; (org-element-property :value latex-fragment) - (let* ((latex-frag (org-element-property :value latex-fragment))) - (cond - ((string-match "\\\\ref{\\([^{}\n]+\\)}" latex-frag) - (let* ((label (match-string 1 latex-frag)) - (href (and label (org-export-solidify-link-text label))) - (text (if (string-match "\\`[a-z]\\{1,10\\}:\\(.+\\)" label) - (substring label (match-beginning 1)) - label))) - (org-e-odt-format-internal-link text href))) - (t (let ((processing-type (plist-get info :LaTeX-fragments))) - (cond - ((member processing-type '(t mathjax)) - (org-e-odt-format-latex latex-frag 'mathjax)) - ((equal processing-type 'dvipng) - (let* ((formula-link (org-e-odt-format-latex - latex-frag processing-type))) - (when (and formula-link - (string-match "file:\\([^]]*\\)" formula-link)) - (org-e-odt-format-inline-image - (match-string 1 formula-link))))) - (t latex-frag))))))) - - -;;;; Line Break - -(defun org-e-odt-line-break (line-break contents info) - "Transcode a LINE-BREAK object from Org to HTML. -CONTENTS is nil. INFO is a plist holding contextual information." - "\n") - - -;;;; Link - -(defun org-e-odt-link--inline-image (link info) - "Return HTML code for an inline image. -LINK is the link pointing to the inline image. INFO is a plist -used as a communication channel." - (let* ((parent (org-export-get-parent-paragraph link info)) - (path (let ((raw-path (org-element-property :path link))) - (if (not (file-name-absolute-p raw-path)) raw-path - (expand-file-name raw-path)))) - (caption (org-e-odt--caption/label-string - (org-element-property :caption parent) - (org-element-property :name parent) - info)) - (label (org-element-property :name parent)) - ;; Retrieve latex attributes from the element around. - (attr (let ((raw-attr - (mapconcat #'identity - (org-element-property :attr_odt parent) - " "))) - (unless (string= raw-attr "") raw-attr)))) - ;; Now clear ATTR from any special keyword and set a default - ;; value if nothing is left. - (setq attr (if (not attr) "" (org-trim attr))) - ;; Return proper string, depending on DISPOSITION. - (let ((href (and label (org-export-solidify-link-text label)))) - (org-e-odt-format-inline-image path caption href attr)))) - -(defun org-e-odt-link (link desc info) - "Transcode a LINK object from Org to HTML. - -DESC is the description part of the link, or the empty string. -INFO is a plist holding contextual information. See -`org-export-data'." - (let* ((type (org-element-property :type link)) - (raw-path (org-element-property :path link)) - ;; Ensure DESC really exists, or set it to nil. - (desc (and (not (string= desc "")) desc)) - (imagep (org-export-inline-image-p - link org-e-odt-inline-image-rules)) - (path (cond - ((member type '("http" "https" "ftp" "mailto")) - (concat type ":" raw-path)) - ((string= type "file") - (when (string-match "\\(.+\\)::.+" raw-path) - (setq raw-path (match-string 1 raw-path))) - (if (file-name-absolute-p raw-path) - (concat "file://" (expand-file-name raw-path)) - ;; TODO: Not implemented yet. Concat also: - ;; (org-export-directory :HTML info) - (concat "file://" raw-path))) - (t raw-path))) - protocol) - (cond - ;; Image file. - (imagep (org-e-odt-link--inline-image link info)) - ;; Radioed target: Target's name is obtained from original raw - ;; link. Path is parsed and transcoded in order to have a proper - ;; display of the contents. - ((string= type "radio") - (org-e-odt-format-internal-link - (org-export-secondary-string - (org-element-parse-secondary-string - path (cdr (assq 'radio-target org-element-object-restrictions))) - 'e-odt info) - (org-export-solidify-link-text path))) - ;; Links pointing to an headline: Find destination and build - ;; appropriate referencing command. - ((member type '("custom-id" "fuzzy" "id")) - (let ((destination (if (string= type "fuzzy") - (org-export-resolve-fuzzy-link link info) - (org-export-resolve-id-link link info)))) - (case (org-element-type destination) - ;; Fuzzy link points nowhere. - ('nil - (org-e-odt-format-fontify - (or desc (org-export-secondary-string - (org-element-property :raw-link link) - 'e-odt info)) 'emphasis)) - ;; Fuzzy link points to an invisible target. - (keyword nil) - ;; LINK points to an headline. If headlines are numbered - ;; and the link has no description, display headline's - ;; number. Otherwise, display description or headline's - ;; title. - (headline - (let* ((headline-no (org-export-get-headline-number destination info)) - (label (format "sec-%s" (mapconcat 'number-to-string - headline-no "-"))) - (section-no (mapconcat 'number-to-string headline-no "."))) - (setq desc - (cond - (desc desc) - ((plist-get info :section-numbers) section-no) - (t (org-export-secondary-string - (org-element-property :title destination) - 'e-odt info)))) - (org-e-odt-format-internal-link desc label))) - ;; Fuzzy link points to a target. Do as above. - (otherwise - (let ((path (org-export-solidify-link-text path))) - (unless desc - (setq desc (let ((number (org-export-get-ordinal - destination info))) - (when number - (if (atom number) (number-to-string number) - (mapconcat 'number-to-string number ".")))))) - (org-e-odt-format-internal-link (or desc "FIXME") path)))))) - ;; Coderef: replace link with the reference name or the - ;; equivalent line number. - ((string= type "coderef") - (let* ((fmt (org-export-get-coderef-format path (or desc "%s"))) - (res (org-export-resolve-coderef path info)) - (org-e-odt-suppress-xref nil) - (href (org-xml-format-href (concat "#coderef-" path)))) - (format fmt (org-e-odt-format-link res href)))) - ;; Link type is handled by a special function. - ((functionp (setq protocol (nth 2 (assoc type org-link-protocols)))) - (funcall protocol (org-link-unescape path) desc 'html)) - ;; External link with a description part. - ((and path desc) (org-e-odt-format-link desc path)) - ;; External link without a description part. - (path (org-e-odt-format-link path path)) - ;; No path, only description. Try to do something useful. - (t (org-e-odt-format-fontify desc 'emphasis))))) - - -;;;; Babel Call - -;; Babel Calls are ignored. - - -;;;; Macro - -(defun org-e-odt-macro (macro contents info) - "Transcode a MACRO element from Org to HTML. -CONTENTS is nil. INFO is a plist holding contextual information." - ;; Use available tools. - (org-export-expand-macro macro info)) - - -;;;; Paragraph - -(defun org-e-odt-paragraph (paragraph contents info) - "Transcode a PARAGRAPH element from Org to HTML. -CONTENTS is the contents of the paragraph, as a string. INFO is -the plist used as a communication channel." - (let* ((style nil) ; FIXME - (class (cdr (assoc style '((footnote . "footnote") - (verse . nil))))) - (extra (if class (format " class=\"%s\"" class) "")) - (parent (org-export-get-parent paragraph info)) - (parent-type (org-element-type parent)) - (style (case parent-type - (quote-block 'quote) - (center-block 'center) - (t nil)))) - (org-e-odt-format-stylized-paragraph style contents))) - - -;;;; Plain List - -(defun org-e-odt-plain-list (plain-list contents info) - "Transcode a PLAIN-LIST element from Org to HTML. -CONTENTS is the contents of the list. INFO is a plist holding -contextual information." - (let* (arg1 ;; FIXME - (type (org-element-property :type plain-list)) - (attr (mapconcat #'identity - (org-element-property :attr_odt plain-list) - " "))) - (org-e-odt--wrap-label - plain-list (format "%s\n%s%s" - (org-e-odt-begin-plain-list type) - contents (org-e-odt-end-plain-list type))))) - -;;;; Plain Text - -(defun org-e-odt-convert-special-strings (string) - "Convert special characters in STRING to ODT." - (let ((all org-export-e-odt-special-string-regexps) - e a re rpl start) - (while (setq a (pop all)) - (setq re (car a) rpl (cdr a) start 0) - (while (string-match re string start) - (setq string (replace-match rpl t nil string)))) - string)) - -;; (defun org-e-odt-encode-plain-text (s) -;; "Convert plain text characters to HTML equivalent. -;; Possible conversions are set in `org-export-html-protect-char-alist'." -;; (let ((cl org-e-odt-protect-char-alist) c) -;; (while (setq c (pop cl)) -;; (let ((start 0)) -;; (while (string-match (car c) s start) -;; (setq s (replace-match (cdr c) t t s) -;; start (1+ (match-beginning 0)))))) -;; s)) - -(defun org-e-odt-plain-text (text info) - "Transcode a TEXT string from Org to HTML. -TEXT is the string to transcode. INFO is a plist holding -contextual information." - (setq text (org-e-odt-encode-plain-text text t)) - ;; Protect %, #, &, $, ~, ^, _, { and }. - ;; (while (string-match "\\([^\\]\\|^\\)\\([%$#&{}~^_]\\)" text) - ;; (setq text - ;; (replace-match (format "\\%s" (match-string 2 text)) nil t text 2))) - ;; Protect \ - ;; (setq text (replace-regexp-in-string - ;; "\\(?:[^\\]\\|^\\)\\(\\\\\\)\\(?:[^%$#&{}~^_\\]\\|$\\)" - ;; "$\\backslash$" text nil t 1)) - ;; HTML into \HTML{} and TeX into \TeX{}. - ;; (let ((case-fold-search nil) - ;; (start 0)) - ;; (while (string-match "\\<\\(\\(?:La\\)?TeX\\)\\>" text start) - ;; (setq text (replace-match - ;; (format "\\%s{}" (match-string 1 text)) nil t text) - ;; start (match-end 0)))) - ;; Handle quotation marks - ;; (setq text (org-e-odt--quotation-marks text info)) - ;; Convert special strings. - ;; (when (plist-get info :with-special-strings) - ;; (while (string-match (regexp-quote "...") text) - ;; (setq text (replace-match "\\ldots{}" nil t text)))) - (when (plist-get info :with-special-strings) - (setq text (org-e-odt-convert-special-strings text))) - ;; Handle break preservation if required. - (when (plist-get info :preserve-breaks) - (setq text (replace-regexp-in-string "\\(\\\\\\\\\\)?[ \t]*\n" " \\\\\\\\\n" - text))) - ;; Return value. - text) - - -;;;; Property Drawer - -(defun org-e-odt-property-drawer (property-drawer contents info) - "Transcode a PROPERTY-DRAWER element from Org to HTML. -CONTENTS is nil. INFO is a plist holding contextual -information." - ;; The property drawer isn't exported but we want separating blank - ;; lines nonetheless. - "") - - -;;;; Quote Block - -(defun org-e-odt-quote-block (quote-block contents info) - "Transcode a QUOTE-BLOCK element from Org to HTML. -CONTENTS holds the contents of the block. INFO is a plist -holding contextual information." - (org-e-odt--wrap-label quote-block contents)) - - -;;;; Quote Section - -(defun org-e-odt-quote-section (quote-section contents info) - "Transcode a QUOTE-SECTION element from Org to HTML. -CONTENTS is nil. INFO is a plist holding contextual information." - (let ((value (org-remove-indentation - (org-element-property :value quote-section)))) - (when value (org-e-odt-format-source-code-or-example value nil)))) - - -;;;; Section - -(defun org-e-odt-section (section contents info) ; FIXME - "Transcode a SECTION element from Org to HTML. -CONTENTS holds the contents of the section. INFO is a plist -holding contextual information." - contents) - -;;;; Radio Target - -(defun org-e-odt-radio-target (radio-target text info) - "Transcode a RADIO-TARGET object from Org to HTML. -TEXT is the text of the target. INFO is a plist holding -contextual information." - (org-e-odt-format-anchor - text (org-export-solidify-link-text - (org-element-property :raw-value radio-target)))) - - -;;;; Special Block - -(defun org-e-odt-special-block (special-block contents info) - "Transcode a SPECIAL-BLOCK element from Org to HTML. -CONTENTS holds the contents of the block. INFO is a plist -holding contextual information." - (let ((type (downcase (org-element-property :type special-block)))) - (org-e-odt--wrap-label - special-block - (format "\\begin{%s}\n%s\\end{%s}" type contents type)))) - - -;;;; Src Block - -(defun org-e-odt-src-block (src-block contents info) - "Transcode a SRC-BLOCK element from Org to HTML. -CONTENTS holds the contents of the item. INFO is a plist holding -contextual information." - (let* ((lang (org-element-property :language src-block)) - (caption (org-element-property :caption src-block)) - (label (org-element-property :name src-block))) - ;; FIXME: Handle caption - - ;; caption-str (when caption) - ;; (main (org-export-secondary-string (car caption) 'e-odt info)) - ;; (secondary (org-export-secondary-string (cdr caption) 'e-odt info)) - ;; (caption-str (org-e-odt--caption/label-string caption label info)) - (org-e-odt-format-code src-block info))) - - -;;;; Statistics Cookie - -(defun org-e-odt-statistics-cookie (statistics-cookie contents info) - "Transcode a STATISTICS-COOKIE object from Org to HTML. -CONTENTS is nil. INFO is a plist holding contextual information." - (let ((cookie-value (org-element-property :value statistics-cookie))) - (org-e-odt-format-fontify cookie-value 'code))) - - -;;;; Subscript - -(defun org-e-odt-subscript (subscript contents info) - "Transcode a SUBSCRIPT object from Org to HTML. -CONTENTS is the contents of the object. INFO is a plist holding -contextual information." - ;; (format (if (= (length contents) 1) "$_%s$" "$_{\\mathrm{%s}}$") contents) - (org-e-odt-format-fontify contents 'subscript)) - - -;;;; Superscript - -(defun org-e-odt-superscript (superscript contents info) - "Transcode a SUPERSCRIPT object from Org to HTML. -CONTENTS is the contents of the object. INFO is a plist holding -contextual information." - ;; (format (if (= (length contents) 1) "$^%s$" "$^{\\mathrm{%s}}$") contents) - (org-e-odt-format-fontify contents 'superscript)) - - -;;;; Table - -(defun org-e-odt-get-colwidth (c) - (let ((col-widths (plist-get table-info :width))) - (or (and org-lparse-table-is-styled (aref col-widths c)) 0))) - -(defun org-e-odt-table-row (fields &optional text-for-empty-fields) - (incf org-e-odt-table-rownum) - (let ((i -1)) - (org-e-odt-format-table-row - (mapconcat - (lambda (x) - (when (and (string= x "") text-for-empty-fields) - (setq x text-for-empty-fields)) - (incf i) - (let ((horiz-span (org-e-odt-get-colwidth i))) - (org-e-odt-format-table-cell - x org-e-odt-table-rownum i horiz-span))) - fields "\n")))) - -(defun org-e-odt-table-preamble () - (let ((colgroup-vector (plist-get table-info :column-groups)) ;; FIXME - c gr colgropen preamble) - (unless (aref colgroup-vector 0) - (setf (aref colgroup-vector 0) 'start)) - (dotimes (c columns-number preamble) - (setq gr (aref colgroup-vector c)) - (setq preamble - (concat - preamble - (when (memq gr '(start start-end)) - (prog1 (if colgropen "\n" "\n") - (setq colgropen t))) - (let* ((colalign-vector (plist-get table-info :alignment)) ;; FIXME - (align (cdr (assoc (aref colalign-vector c) - '(("l" . "left") - ("r" . "right") - ("c" . "center"))))) - (alignspec (if (and (boundp 'org-e-odt-format-table-no-css) - org-e-odt-format-table-no-css) - " align=\"%s\"" " class=\"%s\"")) - (extra (format alignspec align))) - (format "" extra)) - (when (memq gr '(end start-end)) - (setq colgropen nil) - "")))) - (concat preamble (if colgropen "")))) - -(defun org-e-odt-list-table (lines caption label attributes) - (setq lines (org-e-odt-org-table-to-list-table lines)) - (let* ((splice nil) head - (org-e-odt-table-rownum -1) - i (cnt 0) - fields line - org-e-odt-table-cur-rowgrp-is-hdr - org-e-odt-table-rowgrp-open - n - (org-lparse-table-style 'org-table) - org-lparse-table-is-styled) - (cond - (splice - (setq org-lparse-table-is-styled nil) - (mapconcat 'org-e-odt-table-row lines "\n")) - (t - (setq org-lparse-table-is-styled t) - - (concat - (org-e-odt-begin-table caption label attributes) - ;; FIXME (org-e-odt-table-preamble) - (org-e-odt-begin-table-rowgroup head) - - (mapconcat - (lambda (line) - (cond - ((equal line 'hline) (org-e-odt-begin-table-rowgroup)) - (t (org-e-odt-table-row line)))) - lines "\n") - - (org-e-odt-end-table-rowgroup) - (org-e-odt-end-table)))))) - -(defun org-e-odt-transcode-table-row (row) - (if (string-match org-table-hline-regexp row) 'hline - (mapcar - (lambda (cell) - (org-export-secondary-string - (let ((cell (org-element-parse-secondary-string - cell - (cdr (assq 'table org-element-string-restrictions))))) - cell) - 'e-odt info)) - (org-split-string row "[ \t]*|[ \t]*")))) - -(defun org-e-odt-org-table-to-list-table (lines &optional splice) - "Convert org-table to list-table. -LINES is a list of the form (ROW1 ROW2 ROW3 ...) where each -element is a `string' representing a single row of org-table. -Thus each ROW has vertical separators \"|\" separating the table -fields. A ROW could also be a row-group separator of the form -\"|---...|\". Return a list of the form (ROW1 ROW2 ROW3 -...). ROW could either be symbol `'hline' or a list of the -form (FIELD1 FIELD2 FIELD3 ...) as appropriate." - (let (line lines-1) - (cond - (splice - (while (setq line (pop lines)) - (unless (string-match "^[ \t]*|-" line) - (push (org-e-odt-transcode-table-row line) lines-1)))) - (t (while (setq line (pop lines)) - (cond - ((string-match "^[ \t]*|-" line) - (when lines (push 'hline lines-1))) - (t (push (org-e-odt-transcode-table-row line) lines-1)))))) - (nreverse lines-1))) - -(defun org-e-odt-table-table (raw-table) - (require 'table) - (with-current-buffer (get-buffer-create "*org-export-table*") - (erase-buffer)) - (let ((output (with-temp-buffer - (insert raw-table) - (goto-char 1) - (re-search-forward "^[ \t]*|[^|]" nil t) - (table-generate-source 'html "*org-export-table*") - (with-current-buffer "*org-export-table*" - (org-trim (buffer-string)))))) - (kill-buffer (get-buffer "*org-export-table*")) - output)) - -(defun org-e-odt-table (table contents info) - "Transcode a TABLE element from Org to HTML. -CONTENTS is nil. INFO is a plist holding contextual information." - (let* ((label (org-element-property :name table)) - (caption (org-e-odt--caption/label-string - (org-element-property :caption table) label info)) - (attr (mapconcat #'identity - (org-element-property :attr_odt table) - " ")) - (raw-table (org-element-property :raw-table table)) - (table-type (org-element-property :type table))) - (case table-type - (table.el - ;; (org-e-odt-table-table raw-table) - ) - (t - (let* ((table-info (org-export-table-format-info raw-table)) - (columns-number (length (plist-get table-info :alignment))) - (lines (org-split-string - (org-export-clean-table - raw-table (plist-get table-info :special-column-p)) "\n")) - - (genealogy (org-export-get-genealogy table info)) - (parent (car genealogy)) - (parent-type (org-element-type parent))) - (org-e-odt-list-table lines caption label attr)))))) - - -;;;; Target - -(defun org-e-odt-target (target contents info) - "Transcode a TARGET object from Org to HTML. -CONTENTS is nil. INFO is a plist holding contextual -information." - (org-e-odt-format-anchor - "" (org-export-solidify-link-text (org-element-property :value target)))) - - -;;;; Time-stamp - -(defun org-e-odt-time-stamp (time-stamp contents info) - "Transcode a TIME-STAMP object from Org to HTML. -CONTENTS is nil. INFO is a plist holding contextual -information." - ;; (let ((value (org-element-property :value time-stamp)) - ;; (type (org-element-property :type time-stamp)) - ;; (appt-type (org-element-property :appt-type time-stamp))) - ;; (concat (cond ((eq appt-type 'scheduled) - ;; (format "\\textbf{\\textsc{%s}} " org-scheduled-string)) - ;; ((eq appt-type 'deadline) - ;; (format "\\textbf{\\textsc{%s}} " org-deadline-string)) - ;; ((eq appt-type 'closed) - ;; (format "\\textbf{\\textsc{%s}} " org-closed-string))) - ;; (cond ((memq type '(active active-range)) - ;; (format org-e-odt-active-timestamp-format value)) - ;; ((memq type '(inactive inactive-range)) - ;; (format org-e-odt-inactive-timestamp-format value)) - ;; (t - ;; (format org-e-odt-diary-timestamp-format value))))) - (let ((value (org-element-property :value time-stamp)) - (type (org-element-property :type time-stamp)) - (appt-type (org-element-property :appt-type time-stamp))) - (setq value (org-export-secondary-string value 'e-odt info)) - (org-e-odt-format-fontify - (concat - (org-e-odt-format-fontify - (cond ((eq appt-type 'scheduled) org-scheduled-string) - ((eq appt-type 'deadline) org-deadline-string) - ((eq appt-type 'closed) org-closed-string)) "timestamp-kwd") - ;; FIXME: (org-translate-time value) - (org-e-odt-format-fontify value "timestamp")) - "timestamp-wrapper"))) - - -;;;; Verbatim - -(defun org-e-odt-verbatim (verbatim contents info) - "Transcode a VERBATIM object from Org to HTML. -CONTENTS is nil. INFO is a plist used as a communication -channel." - (org-e-odt-emphasis - verbatim (org-element-property :value verbatim) info)) - - -;;;; Verse Block - -(defun org-e-odt-verse-block (verse-block contents info) - "Transcode a VERSE-BLOCK element from Org to HTML. -CONTENTS is nil. INFO is a plist holding contextual information." - ;; Replace each newline character with line break. Also replace - ;; each blank line with a line break. - (setq contents (replace-regexp-in-string - "^ *\\\\\\\\$" "
\n" - (replace-regexp-in-string - "\\(\\\\\\\\\\)?[ \t]*\n" "
\n" - (org-remove-indentation - (org-export-secondary-string - (org-element-property :value verse-block) - 'e-odt info))))) - - ;; Replace each white space at beginning of a line with a - ;; non-breaking space. - (while (string-match "^[ \t]+" contents) - (let ((new-str (org-e-odt-format-spaces - (length (match-string 0 contents))))) - (setq contents (replace-match new-str nil t contents)))) - - (org-e-odt--wrap-label - verse-block (format "

\n%s

" contents))) - - - - -;;; Filter Functions - -;;;; Filter Settings -;;;; Filters - -;;; Interactive functions - -(defun org-e-odt-export-to-odt - (&optional subtreep visible-only body-only ext-plist pub-dir) - "Export current buffer to a HTML file. - -If narrowing is active in the current buffer, only export its -narrowed part. - -If a region is active, export that region. - -When optional argument SUBTREEP is non-nil, export the sub-tree -at point, extracting information from the headline properties -first. - -When optional argument VISIBLE-ONLY is non-nil, don't export -contents of hidden elements. - -When optional argument BODY-ONLY is non-nil, only write code -between \"\\begin{document}\" and \"\\end{document}\". - -EXT-PLIST, when provided, is a property list with external -parameters overriding Org default settings, but still inferior to -file-local settings. - -When optional argument PUB-DIR is set, use it as the publishing -directory. - -Return output file's name." - (interactive) - - ;; FIXME - (with-current-buffer (get-buffer-create "*debug*") - (erase-buffer)) - - ;; (let* ((outfile (org-export-output-file-name ".html" subtreep pub-dir)) - ;; (outfile "content.xml")) - ;; (org-export-to-file - ;; 'e-odt outfile subtreep visible-only body-only ext-plist)) - - (let* ((outbuf (org-e-odt-init-outfile)) - (target (org-export-output-file-name ".odt" subtreep pub-dir)) - (outdir (file-name-directory (buffer-file-name outbuf))) - (default-directory outdir)) - - ;; FIXME: for copying embedded images - (setq org-current-export-file - (file-name-directory - (org-export-output-file-name ".odt" subtreep nil))) - - (org-export-to-buffer - 'e-odt outbuf - (memq 'subtree optns) (memq 'visible optns) (memq 'body optns)) - - (setq org-lparse-opt-plist nil) ; FIXME - (org-e-odt-save-as-outfile target ;; info - nil - ) - - ;; return outfile - target)) - - - - -;;; FIXMES, TODOS, FOR REVIEW etc - -;;;; org-format-table-html -;;;; org-format-org-table-html -;;;; org-format-table-table-html -;;;; org-table-number-fraction -;;;; org-table-number-regexp -;;;; org-e-odt-table-caption-above - -;;;; org-whitespace -;;;; "%s" -;;;; Remove display properties -;;;; org-e-odt-final-hook - -;;;; org-e-odt-with-timestamp -;;;; org-e-odt-html-helper-timestamp - -;;;; org-export-as-html-and-open -;;;; org-export-as-html-batch -;;;; org-export-as-html-to-buffer -;;;; org-replace-region-by-html -;;;; org-export-region-as-html -;;;; org-export-as-html - -;;;; (org-export-directory :html opt-plist) -;;;; (plist-get opt-plist :html-extension) -;;;; org-e-odt-toplevel-hlevel -;;;; org-e-odt-special-string-regexps -;;;; org-e-odt-coding-system -;;;; org-e-odt-coding-system -;;;; org-e-odt-inline-images -;;;; org-e-odt-inline-image-extensions -;;;; org-e-odt-protect-char-alist -;;;; org-e-odt-table-use-header-tags-for-first-column -;;;; org-e-odt-todo-kwd-class-prefix -;;;; org-e-odt-tag-class-prefix -;;;; org-e-odt-footnote-separator - - -;;; Library Initializations - -(mapc - (lambda (desc) - ;; Let Org open all OpenDocument files using system-registered app - (add-to-list 'org-file-apps - (cons (concat "\\." (car desc) "\\'") 'system)) - ;; Let Emacs open all OpenDocument files in archive mode - (add-to-list 'auto-mode-alist - (cons (concat "\\." (car desc) "\\'") 'archive-mode))) - org-e-odt-file-extensions) - -;; FIXME -;; (eval-after-load 'org-exp -;; '(add-to-list 'org-export-inbuffer-options-extra -;; '("ODT_STYLES_FILE" :odt-styles-file))) - -(provide 'org-e-odt) - -;;; org-e-odt.el ends here diff --git a/EXPERIMENTAL/org-e-publish.el b/EXPERIMENTAL/org-e-publish.el deleted file mode 100644 index 92e58f9..0000000 --- a/EXPERIMENTAL/org-e-publish.el +++ /dev/null @@ -1,1211 +0,0 @@ -;;; org-e-publish.el --- publish related org-mode files as a website -;; Copyright (C) 2006-2012 Free Software Foundation, Inc. - -;; Author: David O'Toole -;; Maintainer: Carsten Dominik -;; Keywords: hypermedia, outlines, wp - -;; This file is part of GNU Emacs. -;; -;; GNU Emacs is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;; This program allow configurable publishing of related sets of -;; Org mode files as a complete website. -;; -;; org-e-publish.el can do the following: -;; -;; + Publish all one's Org files to HTML or PDF -;; + Upload HTML, images, attachments and other files to a web server -;; + Exclude selected private pages from publishing -;; + Publish a clickable sitemap of pages -;; + Manage local timestamps for publishing only changed files -;; + Accept plugin functions to extend range of publishable content -;; -;; Documentation for publishing is in the manual. - -;;; Code: - -(eval-when-compile (require 'cl)) -(require 'format-spec) - -(declare-function org-element-property "org-element" (property element)) -(declare-function org-element-map "org-element" - (data types fun &optional info first-match)) - -(declare-function org-export-output-file-name "org-export" - (extension &optional subtreep pub-dir)) -(declare-function - org-export-to-file "org-export" - (backend file &optional subtreep visible-only body-only ext-plist)) -(declare-function org-export-get-parent-headline "org-export" (blob info)) -(declare-function org-export-get-environment "org-export" - (&optional backend subtreep ext-plist)) -(declare-function org-export-get-inbuffer-options "org-export" - (&optional backend files)) - - - -;;; Variables -(defvar org-e-publish-initial-buffer nil - "The buffer `org-e-publish' has been called from.") - -(defvar org-e-publish-temp-files nil - "Temporary list of files to be published.") - -;; Here, so you find the variable right before it's used the first time: -(defvar org-e-publish-cache nil - "This will cache timestamps and titles for files in publishing projects. -Blocks could hash sha1 values here.") - -(defgroup org-e-publish nil - "Options for publishing a set of Org-mode and related files." - :tag "Org Publishing" - :group 'org) - -(defcustom org-e-publish-project-alist nil - "Association list to control publishing behavior. -Each element of the alist is a publishing 'project.' The CAR of -each element is a string, uniquely identifying the project. The -CDR of each element is in one of the following forms: - -1. A well-formed property list with an even number of elements, - alternating keys and values, specifying parameters for the - publishing process. - - \(:property value :property value ... ) - -2. A meta-project definition, specifying of a list of - sub-projects: - - \(:components \(\"project-1\" \"project-2\" ...)) - -When the CDR of an element of org-e-publish-project-alist is in -this second form, the elements of the list after `:components' -are taken to be components of the project, which group together -files requiring different publishing options. When you publish -such a project with \\[org-e-publish], the components all -publish. - -When a property is given a value in -`org-e-publish-project-alist', its setting overrides the value of -the corresponding user variable \(if any) during publishing. -However, options set within a file override everything. - -Most properties are optional, but some should always be set: - - `:base-directory' - - Directory containing publishing source files. - - `:base-extension' - - Extension \(without the dot!) of source files. This can be - a regular expression. If not given, \"org\" will be used as - default extension. - - `:publishing-directory' - - Directory \(possibly remote) where output files will be - published. - -The `:exclude' property may be used to prevent certain files from -being published. Its value may be a string or regexp matching -file names you don't want to be published. - -The `:include' property may be used to include extra files. Its -value may be a list of filenames to include. The filenames are -considered relative to the base directory. - -When both `:include' and `:exclude' properties are given values, -the exclusion step happens first. - -One special property controls which back-end function to use for -publishing files in the project. This can be used to extend the -set of file types publishable by `org-e-publish', as well as the -set of output formats. - - `:publishing-function' - - Function to publish file. The default is - `org-e-publish-org-to-ascii', but other values are possible. - May also be a list of functions, in which case each function - in the list is invoked in turn. - -Another property allows you to insert code that prepares -a project for publishing. For example, you could call GNU Make -on a certain makefile, to ensure published files are built up to -date. - - `:preparation-function' - - Function to be called before publishing this project. This - may also be a list of functions. - - `:completion-function' - - Function to be called after publishing this project. This - may also be a list of functions. - -Some properties control details of the Org publishing process, -and are equivalent to the corresponding user variables listed in -the right column. Back-end specific properties may also be -included. See the back-end documentation for more information. - - :author `user-full-name' - :creator `org-export-creator-string' - :email `user-mail-address' - :exclude-tags `org-export-exclude-tags' - :headline-levels `org-export-headline-levels' - :language `org-export-default-language' - :preserve-breaks `org-export-preserve-breaks' - :section-numbers `org-export-with-section-numbers' - :select-tags `org-export-select-tags' - :time-stamp-file `org-export-time-stamp-file' - :with-archived-trees `org-export-with-archived-trees' - :with-author `org-export-with-author' - :with-creator `org-export-with-creator' - :with-drawers `org-export-with-drawers' - :with-email `org-export-with-email' - :with-emphasize `org-export-with-emphasize' - :with-entities `org-export-with-entities' - :with-fixed-width `org-export-with-fixed-width' - :with-footnotes `org-export-with-footnotes' - :with-priority `org-export-with-priority' - :with-special-strings `org-export-with-special-strings' - :with-sub-superscript `org-export-with-sub-superscripts' - :with-toc `org-export-with-toc' - :with-tables `org-export-with-tables' - :with-tags `org-export-with-tags' - :with-tasks `org-export-with-tasks' - :with-timestamps `org-export-with-timestamps' - :with-todo-keywords `org-export-with-todo-keywords' - -The following properties may be used to control publishing of -a site-map of files or summary page for a given project. - - `:auto-sitemap' - - Whether to publish a site-map during - `org-e-publish-current-project' or `org-e-publish-all'. - - `:sitemap-filename' - - Filename for output of sitemap. Defaults to \"sitemap.org\". - - `:sitemap-title' - - Title of site-map page. Defaults to name of file. - - `:sitemap-function' - - Plugin function to use for generation of site-map. Defaults to - `org-e-publish-org-sitemap', which generates a plain list of - links to all files in the project. - - `:sitemap-style' - - Can be `list' \(site-map is just an itemized list of the - titles of the files involved) or `tree' \(the directory - structure of the source files is reflected in the site-map). - Defaults to `tree'. - - `:sitemap-sans-extension' - - Remove extension from site-map's file-names. Useful to have - cool URIs \(see http://www.w3.org/Provider/Style/URI). - Defaults to nil. - -If you create a site-map file, adjust the sorting like this: - - `:sitemap-sort-folders' - - Where folders should appear in the site-map. Set this to - `first' \(default) or `last' to display folders first or - last, respectively. Any other value will mix files and - folders. - - `:sitemap-sort-files' - - The site map is normally sorted alphabetically. You can - change this behaviour setting this to `anti-chronologically', - `chronologically', or nil. - - `:sitemap-ignore-case' - - Should sorting be case-sensitive? Default nil. - -The following properties control the creation of a concept index. - - `:makeindex' - - Create a concept index. - -Other properties affecting publication. - - `:body-only' - - Set this to t to publish only the body of the documents." - :group 'org-e-publish - :type 'alist) - -(defcustom org-e-publish-use-timestamps-flag t - "Non-nil means use timestamp checking to publish only changed files. -When nil, do no timestamp checking and always publish all files." - :group 'org-e-publish - :type 'boolean) - -(defcustom org-e-publish-timestamp-directory - (convert-standard-filename "~/.org-timestamps/") - "Name of directory in which to store publishing timestamps." - :group 'org-e-publish - :type 'directory) - -(defcustom org-e-publish-list-skipped-files t - "Non-nil means show message about files *not* published." - :group 'org-e-publish - :type 'boolean) - -(defcustom org-e-publish-sitemap-sort-files 'alphabetically - "Method to sort files in site-maps. -Possible values are `alphabetically', `chronologically', -`anti-chronologically' and nil. - -If `alphabetically', files will be sorted alphabetically. If -`chronologically', files will be sorted with older modification -time first. If `anti-chronologically', files will be sorted with -newer modification time first. nil won't sort files. - -You can overwrite this default per project in your -`org-e-publish-project-alist', using `:sitemap-sort-files'." - :group 'org-e-publish - :type 'symbol) - -(defcustom org-e-publish-sitemap-sort-folders 'first - "A symbol, denoting if folders are sorted first in sitemaps. -Possible values are `first', `last', and nil. -If `first', folders will be sorted before files. -If `last', folders are sorted to the end after the files. -Any other value will not mix files and folders. - -You can overwrite this default per project in your -`org-e-publish-project-alist', using `:sitemap-sort-folders'." - :group 'org-e-publish - :type 'symbol) - -(defcustom org-e-publish-sitemap-sort-ignore-case nil - "Non-nil when site-map sorting should ignore case. - -You can overwrite this default per project in your -`org-e-publish-project-alist', using `:sitemap-ignore-case'." - :group 'org-e-publish - :type 'boolean) - -(defcustom org-e-publish-sitemap-date-format "%Y-%m-%d" - "Format for `format-time-string' which is used to print a date -in the sitemap." - :group 'org-e-publish - :type 'string) - -(defcustom org-e-publish-sitemap-file-entry-format "%t" - "Format string for site-map file entry. -You could use brackets to delimit on what part the link will be. - -%t is the title. -%a is the author. -%d is the date formatted using `org-e-publish-sitemap-date-format'." - :group 'org-e-publish - :type 'string) - - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; Timestamp-related functions - -(defun org-e-publish-timestamp-filename (filename &optional pub-dir pub-func) - "Return path to timestamp file for filename FILENAME." - (setq filename (concat filename "::" (or pub-dir "") "::" - (format "%s" (or pub-func "")))) - (concat "X" (if (fboundp 'sha1) (sha1 filename) (md5 filename)))) - -(defun org-e-publish-needed-p (filename &optional pub-dir pub-func true-pub-dir) - "Return t if FILENAME should be published in PUB-DIR using PUB-FUNC. -TRUE-PUB-DIR is where the file will truly end up. Currently we -are not using this - maybe it can eventually be used to check if -the file is present at the target location, and how old it is. -Right now we cannot do this, because we do not know under what -file name the file will be stored - the publishing function can -still decide about that independently." - (let ((rtn (if (not org-e-publish-use-timestamps-flag) t - (org-e-publish-cache-file-needs-publishing - filename pub-dir pub-func)))) - (if rtn (message "Publishing file %s using `%s'" filename pub-func) - (when org-e-publish-list-skipped-files - (message "Skipping unmodified file %s" filename))) - rtn)) - -(defun org-e-publish-update-timestamp (filename &optional pub-dir pub-func) - "Update publishing timestamp for file FILENAME. -If there is no timestamp, create one." - (let ((key (org-e-publish-timestamp-filename filename pub-dir pub-func)) - (stamp (org-e-publish-cache-ctime-of-src filename))) - (org-e-publish-cache-set key stamp))) - -(defun org-e-publish-remove-all-timestamps () - "Remove all files in the timestamp directory." - (let ((dir org-e-publish-timestamp-directory) - files) - (when (and (file-exists-p dir) (file-directory-p dir)) - (mapc 'delete-file (directory-files dir 'full "[^.]\\'")) - (org-e-publish-reset-cache)))) - - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; Getting project information out of `org-e-publish-project-alist' - -(defun org-e-publish-expand-projects (projects-alist) - "Expand projects in PROJECTS-ALIST. -This splices all the components into the list." - (let ((rest projects-alist) rtn p components) - (while (setq p (pop rest)) - (if (setq components (plist-get (cdr p) :components)) - (setq rest (append - (mapcar (lambda (x) (assoc x org-e-publish-project-alist)) - components) - rest)) - (push p rtn))) - (nreverse (delete-dups (delq nil rtn))))) - -(defvar org-sitemap-sort-files) -(defvar org-sitemap-sort-folders) -(defvar org-sitemap-ignore-case) -(defvar org-sitemap-requested) -(defvar org-sitemap-date-format) -(defvar org-sitemap-file-entry-format) -(defun org-e-publish-compare-directory-files (a b) - "Predicate for `sort', that sorts folders and files for sitemap." - (let ((retval t)) - (when (or org-sitemap-sort-files org-sitemap-sort-folders) - ;; First we sort files: - (when org-sitemap-sort-files - (case org-sitemap-sort-files - (alphabetically - (let* ((adir (file-directory-p a)) - (aorg (and (string-match "\\.org$" a) (not adir))) - (bdir (file-directory-p b)) - (borg (and (string-match "\\.org$" b) (not bdir))) - (A (if aorg (concat (file-name-directory a) - (org-e-publish-find-title a)) a)) - (B (if borg (concat (file-name-directory b) - (org-e-publish-find-title b)) b))) - (setq retval (if org-sitemap-ignore-case - (not (string-lessp (upcase B) (upcase A))) - (not (string-lessp B A)))))) - ((anti-chronologically chronologically) - (let* ((adate (org-e-publish-find-date a)) - (bdate (org-e-publish-find-date b)) - (A (+ (lsh (car adate) 16) (cadr adate))) - (B (+ (lsh (car bdate) 16) (cadr bdate)))) - (setq retval - (if (eq org-sitemap-sort-files 'chronologically) (<= A B) - (>= A B))))))) - ;; Directory-wise wins: - (when org-sitemap-sort-folders - ;; a is directory, b not: - (cond - ((and (file-directory-p a) (not (file-directory-p b))) - (setq retval (equal org-sitemap-sort-folders 'first))) - ;; a is not a directory, but b is: - ((and (not (file-directory-p a)) (file-directory-p b)) - (setq retval (equal org-sitemap-sort-folders 'last)))))) - retval)) - -(defun org-e-publish-get-base-files-1 - (base-dir &optional recurse match skip-file skip-dir) - "Set `org-e-publish-temp-files' with files from BASE-DIR directory. -If RECURSE is non-nil, check BASE-DIR recursively. If MATCH is -non-nil, restrict this list to the files matching the regexp -MATCH. If SKIP-FILE is non-nil, skip file matching the regexp -SKIP-FILE. If SKIP-DIR is non-nil, don't check directories -matching the regexp SKIP-DIR when recursing through BASE-DIR." - (mapc (lambda (f) - (let ((fd-p (file-directory-p f)) - (fnd (file-name-nondirectory f))) - (if (and fd-p recurse - (not (string-match "^\\.+$" fnd)) - (if skip-dir (not (string-match skip-dir fnd)) t)) - (org-e-publish-get-base-files-1 - f recurse match skip-file skip-dir) - (unless (or fd-p ;; this is a directory - (and skip-file (string-match skip-file fnd)) - (not (file-exists-p (file-truename f))) - (not (string-match match fnd))) - - (pushnew f org-e-publish-temp-files))))) - (if org-sitemap-requested - (sort (directory-files base-dir t (unless recurse match)) - 'org-e-publish-compare-directory-files) - (directory-files base-dir t (unless recurse match))))) - -(defun org-e-publish-get-base-files (project &optional exclude-regexp) - "Return a list of all files in PROJECT. -If EXCLUDE-REGEXP is set, this will be used to filter out -matching filenames." - (let* ((project-plist (cdr project)) - (base-dir (file-name-as-directory - (plist-get project-plist :base-directory))) - (include-list (plist-get project-plist :include)) - (recurse (plist-get project-plist :recursive)) - (extension (or (plist-get project-plist :base-extension) "org")) - ;; sitemap-... variables are dynamically scoped for - ;; org-e-publish-compare-directory-files: - (org-sitemap-requested - (plist-get project-plist :auto-sitemap)) - (sitemap-filename - (or (plist-get project-plist :sitemap-filename) "sitemap.org")) - (org-sitemap-sort-folders - (if (plist-member project-plist :sitemap-sort-folders) - (plist-get project-plist :sitemap-sort-folders) - org-e-publish-sitemap-sort-folders)) - (org-sitemap-sort-files - (cond ((plist-member project-plist :sitemap-sort-files) - (plist-get project-plist :sitemap-sort-files)) - ;; For backward compatibility: - ((plist-member project-plist :sitemap-alphabetically) - (if (plist-get project-plist :sitemap-alphabetically) - 'alphabetically nil)) - (t org-e-publish-sitemap-sort-files))) - (org-sitemap-ignore-case - (if (plist-member project-plist :sitemap-ignore-case) - (plist-get project-plist :sitemap-ignore-case) - org-e-publish-sitemap-sort-ignore-case)) - (match (if (eq extension 'any) "^[^\\.]" - (concat "^[^\\.].*\\.\\(" extension "\\)$")))) - ;; Make sure `org-sitemap-sort-folders' has an accepted value - (unless (memq org-sitemap-sort-folders '(first last)) - (setq org-sitemap-sort-folders nil)) - - (setq org-e-publish-temp-files nil) - (if org-sitemap-requested - (pushnew (expand-file-name (concat base-dir sitemap-filename)) - org-e-publish-temp-files)) - (org-e-publish-get-base-files-1 base-dir recurse match - ;; FIXME distinguish exclude regexp - ;; for skip-file and skip-dir? - exclude-regexp exclude-regexp) - (mapc (lambda (f) - (pushnew - (expand-file-name (concat base-dir f)) - org-e-publish-temp-files)) - include-list) - org-e-publish-temp-files)) - -(defun org-e-publish-get-project-from-filename (filename &optional up) - "Return the project that FILENAME belongs to." - (let* ((filename (expand-file-name filename)) - project-name) - - (catch 'p-found - (dolist (prj org-e-publish-project-alist) - (unless (plist-get (cdr prj) :components) - ;; [[info:org:Selecting%20files]] shows how this is supposed to work: - (let* ((r (plist-get (cdr prj) :recursive)) - (b (expand-file-name (file-name-as-directory - (plist-get (cdr prj) :base-directory)))) - (x (or (plist-get (cdr prj) :base-extension) "org")) - (e (plist-get (cdr prj) :exclude)) - (i (plist-get (cdr prj) :include)) - (xm (concat "^" b (if r ".+" "[^/]+") "\\.\\(" x "\\)$"))) - (when - (or (and i - (member filename - (mapcar (lambda (file) - (expand-file-name file b)) - i))) - (and (not (and e (string-match e filename))) - (string-match xm filename))) - (setq project-name (car prj)) - (throw 'p-found project-name)))))) - (when up - (dolist (prj org-e-publish-project-alist) - (if (member project-name (plist-get (cdr prj) :components)) - (setq project-name (car prj))))) - (assoc project-name org-e-publish-project-alist))) - - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; Pluggable publishing back-end functions - -(defun org-e-publish-org-to (backend filename extension plist pub-dir) - "Publish an Org file to a specified back-end. - -BACKEND is a symbol representing the back-end used for -transcoding. FILENAME is the filename of the Org file to be -published. EXTENSION is the extension used for the output -string, with the leading dot. PLIST is the property list for the -given project. PUB-DIR is the publishing directory. - -Return output file name." - (unless (file-exists-p pub-dir) (make-directory pub-dir t)) - ;; Check if a buffer visiting FILENAME is already open. - (let* ((visitingp (find-buffer-visiting filename)) - (work-buffer (or visitingp (find-file-noselect filename)))) - (prog1 (with-current-buffer work-buffer - (let ((output-file - (org-export-output-file-name extension nil pub-dir)) - (body-p (plist-get plist :body-only))) - (org-export-to-file - backend output-file nil nil body-p - ;; Install `org-e-publish-collect-index' in parse tree - ;; filters. It isn't dependent on `:makeindex', since - ;; we want to keep it up-to-date in cache anyway. - (org-combine-plists - plist `(:filter-parse-tree - (org-e-publish-collect-index - ,@(plist-get plist :filter-parse-tree))))))) - ;; Remove opened buffer in the process. - (unless visitingp (kill-buffer work-buffer))))) - -(defvar project-plist) -(defun org-e-publish-org-to-latex (plist filename pub-dir) - "Publish an Org file to LaTeX. - -FILENAME is the filename of the Org file to be published. PLIST -is the property list for the given project. PUB-DIR is the -publishing directory. - -Return output file name." - (org-e-publish-org-to 'e-latex filename ".tex" plist pub-dir)) - -(defun org-e-publish-org-to-pdf (plist filename pub-dir) - "Publish an Org file to PDF \(via LaTeX). - -FILENAME is the filename of the Org file to be published. PLIST -is the property list for the given project. PUB-DIR is the -publishing directory. - -Return output file name." - (org-e-latex-compile - (org-e-publish-org-to 'e-latex filename ".tex" plist pub-dir))) - -(defun org-e-publish-org-to-html (plist filename pub-dir) - "Publish an org file to HTML. - -FILENAME is the filename of the Org file to be published. PLIST -is the property list for the given project. PUB-DIR is the -publishing directory. - -Return output file name." - (org-e-publish-org-to 'e-html filename "html" plist pub-dir)) - -;; TODO: Not implemented yet. -;; (defun org-e-publish-org-to-org (plist filename pub-dir) -;; "Publish an org file to HTML. -;; -;; FILENAME is the filename of the Org file to be published. PLIST -;; is the property list for the given project. PUB-DIR is the -;; publishing directory. -;; -;; Return output file name." -;; (org-e-publish-org-to "org" plist filename pub-dir)) - -(defun org-e-publish-org-to-ascii (plist filename pub-dir) - "Publish an Org file to ASCII. - -FILENAME is the filename of the Org file to be published. PLIST -is the property list for the given project. PUB-DIR is the -publishing directory. - -Return output file name." - (org-e-publish-org-to - 'e-ascii filename ".txt" `(:ascii-charset ascii ,@plist) pub-dir)) - -(defun org-e-publish-org-to-latin1 (plist filename pub-dir) - "Publish an Org file to Latin-1. - -FILENAME is the filename of the Org file to be published. PLIST -is the property list for the given project. PUB-DIR is the -publishing directory. - -Return output file name." - (org-e-publish-org-to - 'e-ascii filename ".txt" `(:ascii-charset latin1 ,@plist) pub-dir)) - -(defun org-e-publish-org-to-utf8 (plist filename pub-dir) - "Publish an org file to UTF-8. - -FILENAME is the filename of the Org file to be published. PLIST -is the property list for the given project. PUB-DIR is the -publishing directory. - -Return output file name." - (org-e-publish-org-to - 'e-ascii filename ".txt" `(:ascii-charset utf-8 ,@plist) pub-dir)) - -(defun org-e-publish-attachment (plist filename pub-dir) - "Publish a file with no transformation of any kind. - -FILENAME is the filename of the Org file to be published. PLIST -is the property list for the given project. PUB-DIR is the -publishing directory. - -Return output file name." - (unless (file-directory-p pub-dir) - (make-directory pub-dir t)) - (or (equal (expand-file-name (file-name-directory filename)) - (file-name-as-directory (expand-file-name pub-dir))) - (copy-file filename - (expand-file-name (file-name-nondirectory filename) pub-dir) - t))) - - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; Publishing files, sets of files, and indices - -(defun org-e-publish-file (filename &optional project no-cache) - "Publish file FILENAME from PROJECT. -If NO-CACHE is not nil, do not initialize org-e-publish-cache and -write it to disk. This is needed, since this function is used to -publish single files, when entire projects are published. -See `org-e-publish-projects'." - (let* ((project - (or project - (or (org-e-publish-get-project-from-filename filename) - (error "File %s not part of any known project" - (abbreviate-file-name filename))))) - (project-plist (cdr project)) - (ftname (expand-file-name filename)) - (publishing-function - (or (plist-get project-plist :publishing-function) - 'org-e-publish-org-to-ascii)) - (base-dir - (file-name-as-directory - (expand-file-name - (or (plist-get project-plist :base-directory) - (error "Project %s does not have :base-directory defined" - (car project)))))) - (pub-dir - (file-name-as-directory - (file-truename - (or (eval (plist-get project-plist :publishing-directory)) - (error "Project %s does not have :publishing-directory defined" - (car project)))))) - tmp-pub-dir) - - (unless no-cache (org-e-publish-initialize-cache (car project))) - - (setq tmp-pub-dir - (file-name-directory - (concat pub-dir - (and (string-match (regexp-quote base-dir) ftname) - (substring ftname (match-end 0)))))) - (if (listp publishing-function) - ;; allow chain of publishing functions - (mapc (lambda (f) - (when (org-e-publish-needed-p filename pub-dir f tmp-pub-dir) - (funcall f project-plist filename tmp-pub-dir) - (org-e-publish-update-timestamp filename pub-dir f))) - publishing-function) - (when (org-e-publish-needed-p filename pub-dir publishing-function - tmp-pub-dir) - (funcall publishing-function project-plist filename tmp-pub-dir) - (org-e-publish-update-timestamp - filename pub-dir publishing-function))) - (unless no-cache (org-e-publish-write-cache-file)))) - -(defun org-e-publish-projects (projects) - "Publish all files belonging to the PROJECTS alist. -If `:auto-sitemap' is set, publish the sitemap too. If -`:makeindex' is set, also produce a file theindex.org." - (mapc - (lambda (project) - ;; Each project uses its own cache file: - (org-e-publish-initialize-cache (car project)) - (let* ((project-plist (cdr project)) - (exclude-regexp (plist-get project-plist :exclude)) - (sitemap-p (plist-get project-plist :auto-sitemap)) - (sitemap-filename (or (plist-get project-plist :sitemap-filename) - "sitemap.org")) - (sitemap-function (or (plist-get project-plist :sitemap-function) - 'org-e-publish-org-sitemap)) - (org-sitemap-date-format - (or (plist-get project-plist :sitemap-date-format) - org-e-publish-sitemap-date-format)) - (org-sitemap-file-entry-format - (or (plist-get project-plist :sitemap-file-entry-format) - org-e-publish-sitemap-file-entry-format)) - (preparation-function - (plist-get project-plist :preparation-function)) - (completion-function (plist-get project-plist :completion-function)) - (files (org-e-publish-get-base-files project exclude-regexp)) file) - (when preparation-function (run-hooks 'preparation-function)) - (if sitemap-p (funcall sitemap-function project sitemap-filename)) - (dolist (file files) (org-e-publish-file file project t)) - (when (plist-get project-plist :makeindex) - (org-e-publish-index-generate-theindex - project (plist-get project-plist :base-directory)) - (org-e-publish-file - (expand-file-name - "theindex.org" (plist-get project-plist :base-directory)) - project t)) - (when completion-function (run-hooks 'completion-function)) - (org-e-publish-write-cache-file))) - (org-e-publish-expand-projects projects))) - -(defun org-e-publish-org-sitemap (project &optional sitemap-filename) - "Create a sitemap of pages in set defined by PROJECT. -Optionally set the filename of the sitemap with SITEMAP-FILENAME. -Default for SITEMAP-FILENAME is 'sitemap.org'." - (let* ((project-plist (cdr project)) - (dir (file-name-as-directory - (plist-get project-plist :base-directory))) - (localdir (file-name-directory dir)) - (indent-str (make-string 2 ?\ )) - (exclude-regexp (plist-get project-plist :exclude)) - (files (nreverse - (org-e-publish-get-base-files project exclude-regexp))) - (sitemap-filename (concat dir (or sitemap-filename "sitemap.org"))) - (sitemap-title (or (plist-get project-plist :sitemap-title) - (concat "Sitemap for project " (car project)))) - (sitemap-style (or (plist-get project-plist :sitemap-style) - 'tree)) - (sitemap-sans-extension - (plist-get project-plist :sitemap-sans-extension)) - (visiting (find-buffer-visiting sitemap-filename)) - (ifn (file-name-nondirectory sitemap-filename)) - file sitemap-buffer) - (with-current-buffer (setq sitemap-buffer - (or visiting (find-file sitemap-filename))) - (erase-buffer) - (insert (concat "#+TITLE: " sitemap-title "\n\n")) - (while (setq file (pop files)) - (let ((fn (file-name-nondirectory file)) - (link (file-relative-name file dir)) - (oldlocal localdir)) - (when sitemap-sans-extension - (setq link (file-name-sans-extension link))) - ;; sitemap shouldn't list itself - (unless (equal (file-truename sitemap-filename) - (file-truename file)) - (if (eq sitemap-style 'list) - (message "Generating list-style sitemap for %s" sitemap-title) - (message "Generating tree-style sitemap for %s" sitemap-title) - (setq localdir (concat (file-name-as-directory dir) - (file-name-directory link))) - (unless (string= localdir oldlocal) - (if (string= localdir dir) - (setq indent-str (make-string 2 ?\ )) - (let ((subdirs - (split-string - (directory-file-name - (file-name-directory - (file-relative-name localdir dir))) "/")) - (subdir "") - (old-subdirs (split-string - (file-relative-name oldlocal dir) "/"))) - (setq indent-str (make-string 2 ?\ )) - (while (string= (car old-subdirs) (car subdirs)) - (setq indent-str (concat indent-str (make-string 2 ?\ ))) - (pop old-subdirs) - (pop subdirs)) - (dolist (d subdirs) - (setq subdir (concat subdir d "/")) - (insert (concat indent-str " + " d "\n")) - (setq indent-str (make-string - (+ (length indent-str) 2) ?\ ))))))) - ;; This is common to 'flat and 'tree - (let ((entry - (org-e-publish-format-file-entry - org-sitemap-file-entry-format file project-plist)) - (regexp "\\(.*\\)\\[\\([^][]+\\)\\]\\(.*\\)")) - (cond ((string-match-p regexp entry) - (string-match regexp entry) - (insert (concat indent-str " + " (match-string 1 entry) - "[[file:" link "][" - (match-string 2 entry) - "]]" (match-string 3 entry) "\n"))) - (t - (insert (concat indent-str " + [[file:" link "][" - entry - "]]\n")))))))) - (save-buffer)) - (or visiting (kill-buffer sitemap-buffer)))) - -(defun org-e-publish-format-file-entry (fmt file project-plist) - (format-spec fmt - `((?t . ,(org-e-publish-find-title file t)) - (?d . ,(format-time-string org-sitemap-date-format - (org-e-publish-find-date file))) - (?a . ,(or (plist-get project-plist :author) user-full-name))))) - -(defun org-e-publish-find-title (file &optional reset) - "Find the title of FILE in project." - (or - (and (not reset) (org-e-publish-cache-get-file-property file :title nil t)) - (let* ((visiting (find-buffer-visiting file)) - (buffer (or visiting (find-file-noselect file))) - title) - (with-current-buffer buffer - (org-mode) - (setq title - (or (plist-get (org-export-get-environment) :title) - (file-name-nondirectory (file-name-sans-extension file))))) - (unless visiting (kill-buffer buffer)) - (org-e-publish-cache-set-file-property file :title title) - title))) - -(defun org-e-publish-find-date (file) - "Find the date of FILE in project. -If FILE provides a #+date keyword use it else use the file -system's modification time. - -It returns time in `current-time' format." - (let* ((visiting (find-buffer-visiting file)) - (file-buf (or visiting (find-file-noselect file nil))) - (date (plist-get - (with-current-buffer file-buf - (org-mode) - (org-export-get-inbuffer-options)) - :date))) - (unless visiting (kill-buffer file-buf)) - (if date (org-time-string-to-time date) - (when (file-exists-p file) - (nth 5 (file-attributes file)))))) - - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; Interactive publishing functions - -;;;###autoload -(defalias 'org-e-publish-project 'org-e-publish) - -;;;###autoload -(defun org-e-publish (project &optional force) - "Publish PROJECT." - (interactive - (list - (assoc (org-icompleting-read - "Publish project: " - org-e-publish-project-alist nil t) - org-e-publish-project-alist) - current-prefix-arg)) - (setq org-e-publish-initial-buffer (current-buffer)) - (save-window-excursion - (let* ((org-e-publish-use-timestamps-flag - (if force nil org-e-publish-use-timestamps-flag))) - (org-e-publish-projects - (if (stringp project) - ;; If this function is called in batch mode, project is - ;; still a string here. - (list (assoc project org-e-publish-project-alist)) - (list project)))))) - -;;;###autoload -(defun org-e-publish-all (&optional force) - "Publish all projects. -With prefix argument, remove all files in the timestamp -directory and force publishing all files." - (interactive "P") - (when force (org-e-publish-remove-all-timestamps)) - (save-window-excursion - (let ((org-e-publish-use-timestamps-flag - (if force nil org-e-publish-use-timestamps-flag))) - (org-e-publish-projects org-e-publish-project-alist)))) - - -;;;###autoload -(defun org-e-publish-current-file (&optional force) - "Publish the current file. -With prefix argument, force publish the file." - (interactive "P") - (save-window-excursion - (let ((org-e-publish-use-timestamps-flag - (if force nil org-e-publish-use-timestamps-flag))) - (org-e-publish-file (buffer-file-name (buffer-base-buffer)))))) - -;;;###autoload -(defun org-e-publish-current-project (&optional force) - "Publish the project associated with the current file. -With a prefix argument, force publishing of all files in -the project." - (interactive "P") - (save-window-excursion - (let ((project (org-e-publish-get-project-from-filename - (buffer-file-name (buffer-base-buffer)) 'up)) - (org-e-publish-use-timestamps-flag - (if force nil org-e-publish-use-timestamps-flag))) - (if project (org-e-publish project) - (error "File %s is not part of any known project" - (buffer-file-name (buffer-base-buffer))))))) - - - -;;; Index generation - -(defun org-e-publish-collect-index (tree backend info) - "Update index for a file with TREE in cache. - -BACKEND is the back-end being used for transcoding. INFO is -a plist containing publishing options. - -The index relative to current file is stored as an alist. An -association has the following shape: \(TERM FILE-NAME PARENT), -where TERM is the indexed term, as a string, FILE-NAME is the -original full path of the file where the term in encountered, and -PARENT is the headline element containing the original index -keyword." - (org-e-publish-cache-set-file-property - (plist-get info :input-file) :index - (delete-dups - (org-element-map - tree 'keyword - (lambda (k) - (when (string= (downcase (org-element-property :key k)) - "index") - (let ((index (org-element-property :value k)) - (parent (org-export-get-parent-headline k info))) - (list index (plist-get info :input-file) parent)))) - info))) - ;; Return parse-tree to avoid altering output. - tree) - -(defun org-e-publish-index-generate-theindex (project directory) - "Retrieve full index from cache and build \"theindex.org\". -PROJECT is the project the index relates to. DIRECTORY is the -publishing directory." - (let ((all-files (org-e-publish-get-base-files - project (plist-get (cdr project) :exclude))) - full-index) - ;; Compile full index. - (mapc - (lambda (file) - (let ((index (org-e-publish-cache-get-file-property file :index))) - (dolist (term index) - (unless (member term full-index) (push term full-index))))) - all-files) - ;; Sort it alphabetically. - (setq full-index - (sort full-index (lambda (a b) (string< (downcase (car a)) - (downcase (car b)))))) - ;; Fill "theindex.org". - (with-temp-buffer - (insert "#+TITLE: Index\n#+OPTIONS: num:nil author:nil\n") - (let ((current-letter nil) (last-entry nil)) - (dolist (idx full-index) - (let* ((entry (org-split-string (car idx) "!")) - (letter (upcase (substring (car entry) 0 1))) - ;; Transform file into a path relative to publishing - ;; directory. - (file (file-relative-name - (nth 1 idx) - (plist-get (cdr project) :base-directory)))) - ;; Check if another letter has to be inserted. - (unless (string= letter current-letter) - (insert (format "* %s\n" letter))) - ;; Compute the first difference between last entry and - ;; current one: it tells the level at which new items - ;; should be added. - (let* ((rank (loop for n from 0 to (length entry) - unless (equal (nth n entry) (nth n last-entry)) - return n)) - (len (length (nthcdr rank entry)))) - ;; For each term after the first difference, create - ;; a new sub-list with the term as body. Moreover, - ;; linkify the last term. - (dotimes (n len) - (insert - (concat - (make-string (* (+ rank n) 2) ? ) " - " - (if (not (= (1- len) n)) (nth (+ rank n) entry) - ;; Last term: Link it to TARGET, if possible. - (let ((target (nth 2 idx))) - (format - "[[%s][%s]]" - ;; Destination. - (cond - ((not target) (format "file:%s" file)) - ((let ((id (org-element-property :id target))) - (and id (format "id:%s" id)))) - ((let ((id (org-element-property :custom-id target))) - (and id (format "file:%s::#%s" file id)))) - (t (format "file:%s::*%s" file - (org-element-property :raw-value target)))) - ;; Description. - (car (last entry))))) - "\n")))) - (setq current-letter letter last-entry entry)))) - ;; Write index. - (write-file (expand-file-name "theindex.org" directory))))) - - - -;;; Caching functions - -(defun org-e-publish-write-cache-file (&optional free-cache) - "Write `org-e-publish-cache' to file. -If FREE-CACHE, empty the cache." - (unless org-e-publish-cache - (error "`org-e-publish-write-cache-file' called, but no cache present")) - - (let ((cache-file (org-e-publish-cache-get ":cache-file:"))) - (unless cache-file - (error "Cannot find cache-file name in `org-e-publish-write-cache-file'")) - (with-temp-file cache-file - (let (print-level print-length) - (insert "(setq org-e-publish-cache (make-hash-table :test 'equal :weakness nil :size 100))\n") - (maphash (lambda (k v) - (insert - (format (concat "(puthash %S " - (if (or (listp v) (symbolp v)) - "'" "") - "%S org-e-publish-cache)\n") k v))) - org-e-publish-cache))) - (when free-cache (org-e-publish-reset-cache)))) - -(defun org-e-publish-initialize-cache (project-name) - "Initialize the projects cache if not initialized yet and return it." - - (unless project-name - (error "%s%s" "Cannot initialize `org-e-publish-cache' without projects name" - " in `org-e-publish-initialize-cache'")) - - (unless (file-exists-p org-e-publish-timestamp-directory) - (make-directory org-e-publish-timestamp-directory t)) - (unless (file-directory-p org-e-publish-timestamp-directory) - (error "Org publish timestamp: %s is not a directory" - org-e-publish-timestamp-directory)) - - (unless (and org-e-publish-cache - (string= (org-e-publish-cache-get ":project:") project-name)) - (let* ((cache-file - (concat - (expand-file-name org-e-publish-timestamp-directory) - project-name ".cache")) - (cexists (file-exists-p cache-file))) - - (when org-e-publish-cache (org-e-publish-reset-cache)) - - (if cexists (load-file cache-file) - (setq org-e-publish-cache - (make-hash-table :test 'equal :weakness nil :size 100)) - (org-e-publish-cache-set ":project:" project-name) - (org-e-publish-cache-set ":cache-file:" cache-file)) - (unless cexists (org-e-publish-write-cache-file nil)))) - org-e-publish-cache) - -(defun org-e-publish-reset-cache () - "Empty org-e-publish-cache and reset it nil." - (message "%s" "Resetting org-e-publish-cache") - (when (hash-table-p org-e-publish-cache) - (clrhash org-e-publish-cache)) - (setq org-e-publish-cache nil)) - -(defun org-e-publish-cache-file-needs-publishing - (filename &optional pub-dir pub-func) - "Check the timestamp of the last publishing of FILENAME. -Return `t', if the file needs publishing. The function also -checks if any included files have been more recently published, -so that the file including them will be republished as well." - (unless org-e-publish-cache - (error - "`org-e-publish-cache-file-needs-publishing' called, but no cache present")) - (let* ((key (org-e-publish-timestamp-filename filename pub-dir pub-func)) - (pstamp (org-e-publish-cache-get key)) - (visiting (find-buffer-visiting filename)) - included-files-ctime buf) - - (when (equal (file-name-extension filename) "org") - (setq buf (find-file (expand-file-name filename))) - (with-current-buffer buf - (goto-char (point-min)) - (while (re-search-forward - "^#\\+INCLUDE:[ \t]+\"?\\([^ \t\n\r\"]*\\)\"?[ \t]*.*$" nil t) - (let* ((included-file (expand-file-name (match-string 1)))) - (add-to-list 'included-files-ctime - (org-e-publish-cache-ctime-of-src included-file) t)))) - ;; FIXME: don't kill current buffer. - (unless visiting (kill-buffer buf))) - (if (null pstamp) - t - (let ((ctime (org-e-publish-cache-ctime-of-src filename))) - (or (< pstamp ctime) - (when included-files-ctime - (not (null (delq nil (mapcar (lambda(ct) (< ctime ct)) - included-files-ctime)))))))))) - -(defun org-e-publish-cache-set-file-property - (filename property value &optional project-name) - "Set the VALUE for a PROPERTY of file FILENAME in publishing cache to VALUE. -Use cache file of PROJECT-NAME. If the entry does not exist, it -will be created. Return VALUE." - ;; Evtl. load the requested cache file: - (if project-name (org-e-publish-initialize-cache project-name)) - (let ((pl (org-e-publish-cache-get filename))) - (if pl (progn (plist-put pl property value) value) - (org-e-publish-cache-get-file-property - filename property value nil project-name)))) - -(defun org-e-publish-cache-get-file-property - (filename property &optional default no-create project-name) - "Return the value for a PROPERTY of file FILENAME in publishing cache. -Use cache file of PROJECT-NAME. Return the value of that PROPERTY -or DEFAULT, if the value does not yet exist. If the entry will -be created, unless NO-CREATE is not nil." - ;; Evtl. load the requested cache file: - (if project-name (org-e-publish-initialize-cache project-name)) - (let ((pl (org-e-publish-cache-get filename)) retval) - (if pl - (if (plist-member pl property) - (setq retval (plist-get pl property)) - (setq retval default)) - ;; no pl yet: - (unless no-create - (org-e-publish-cache-set filename (list property default))) - (setq retval default)) - retval)) - -(defun org-e-publish-cache-get (key) - "Return the value stored in `org-e-publish-cache' for key KEY. -Returns nil, if no value or nil is found, or the cache does not -exist." - (unless org-e-publish-cache - (error "`org-e-publish-cache-get' called, but no cache present")) - (gethash key org-e-publish-cache)) - -(defun org-e-publish-cache-set (key value) - "Store KEY VALUE pair in `org-e-publish-cache'. -Returns value on success, else nil." - (unless org-e-publish-cache - (error "`org-e-publish-cache-set' called, but no cache present")) - (puthash key value org-e-publish-cache)) - -(defun org-e-publish-cache-ctime-of-src (filename) - "Get the FILENAME ctime as an integer." - (let* ((symlink-maybe (or (file-symlink-p filename) filename)) - (src-attr - (file-attributes - (if (file-name-absolute-p symlink-maybe) symlink-maybe - (expand-file-name symlink-maybe (file-name-directory filename)))))) - (+ (lsh (car (nth 5 src-attr)) 16) - (cadr (nth 5 src-attr))))) - - -(provide 'org-e-publish) - -;;; org-e-publish.el ends here diff --git a/contrib/lisp/org-bibtex-extras.el b/contrib/lisp/org-bibtex-extras.el deleted file mode 100644 index 8424e62..0000000 --- a/contrib/lisp/org-bibtex-extras.el +++ /dev/null @@ -1,155 +0,0 @@ -;;; org-bibtex-extras --- extras for working with org-bibtex entries - -;; Copyright (C) 2008-2012 Free Software Foundation, Inc. - -;; Author: Eric Schulte -;; Keywords: outlines, hypermedia, bibtex, d3 -;; Homepage: http://orgmode.org -;; Version: 0.01 - -;; This file is not yet part of GNU Emacs. - -;; GNU Emacs is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 3, or (at your option) -;; any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;; Warning: This should certainly be considered EXPERIMENTAL and still -;; in development, feedback is welcome, but don't expect it -;; to work. - -;; This file add some extra functionality to your bibtex entries which -;; are stored as Org-mode headlines using org-bibtex.el. Most -;; features expect that you keep all of your reading notes in a single -;; file, set the `obe-bibtex-file' variable to the path to this file. -;; -;; - d3 view :: d3 is a Javascript library which supports interactive -;; display of graphs. To view your citations as a d3 -;; graph, execute the following which will create a .json -;; export of your references file, then grab a copy of -;; d3, edit examples/force/force.js to replace -;; -;; var source`"miserables.json"; -;; -;; with -;; -;; var source`"your-references.json"; -;; -;; then view examples/force/force.html in your browser. -;; -;; - HTML export :: Customize the `obe-html-link-base' variable so -;; that it points to an html export of your -;; references, then add the following to your html -;; export hook, and citations will be resolved during -;; html export. -;; -;; (add-hook 'org-export-first-hook -;; (lambda () -;; (when (equal org-export-current-backend 'html) -;; (obe-html-export-citations)))) - -;;; Code: -(require 'org-bibtex) - -(defcustom obe-bibtex-file nil "File holding bibtex entries.") - -(defcustom obe-html-link-base nil - "Base of citation links. -For example, to point to your `obe-bibtex-file' use the following. - - (setq obe-html-link-base (format \"file:%s\" obe-bibtex-file)) -") - -(defvar obe-citations nil) -(defun obe-citations () - "Return all citations from `obe-bibtex-file'." - (or obe-citations - (save-window-excursion - (find-file obe-bibtex-file) - (goto-char (point-min)) - (while (re-search-forward " :CUSTOM_ID: \\(.+\\)$" nil t) - (push (org-babel-clean-text-properties (match-string 1)) - obe-citations)) - obe-citations))) - -(defun obe-goto-citation (&optional citation) - "Visit a citation given its ID." - (interactive) - (let ((citation (or citation - (org-icompleting-read "Citation: " - (obe-citations))))) - (find-file obe-bibtex-file) - (goto-char (point-min)) - (when (re-search-forward (format " :CUSTOM_ID: %s" citation) nil t) - (outline-previous-visible-heading 1) - t))) - -(defun obe-html-export-citations () - "Convert all \\cite{...} citations in the current file into HTML links." - (save-excursion - (goto-char (point-min)) - (while (re-search-forward "\\\\cite{\\([^\000}]+\\)}" nil t) - (replace-match - (save-match-data - (mapconcat (lambda (c) (format "[[%s#%s][%s]]" obe-html-link-base c c)) - (mapcar #'org-babel-trim - (split-string (match-string 1) ",")) ", ")))))) - -(defun obe-get-meta-data (citation) - "Collect meta-data for CITATION." - (save-excursion - (when (obe-goto-citation citation) - (let ((pt (point))) - `((:authors . ,(split-string (org-entry-get pt "AUTHOR") " and " t)) - (:title . ,(org-babel-clean-text-properties (org-get-heading 1 1))) - (:journal . ,(org-entry-get pt "JOURNAL"))))))) - -(defun obe-meta-to-json (meta &optional fields) - "Turn a list of META data from citations into a string of json." - (let ((counter 1) nodes links) - (flet ((id (it) (position it nodes :test #'string= :key #'car)) - (col (k) (mapcar (lambda (r) (cdr (assoc k r))) meta)) - (add (lst) - (dolist (el lst) (push (cons el counter) nodes)) - (incf counter))) - ;; build the nodes of the graph - (add (col :title)) - (add (remove-if (lambda (author) (string-match "others" author)) - (remove-duplicates (apply #'append (col :authors)) - :test #'string=))) - (dolist (field fields) - (add (remove-duplicates (col field) :test #'string=))) - ;; build the links in the graph - (dolist (citation meta) - (let ((dest (id (cdr (assoc :title citation))))) - (dolist (author (mapcar #'id (cdr (assoc :authors citation)))) - (when author (push (cons author dest) links))) - (let ((jid (id (cdr (assoc :journal citation))))) - (when jid (push (cons jid dest) links))) - (let ((cid (id (cdr (assoc :category citation))))) - (when cid (push (cons cid dest) links))))) - ;; build the json string - (format "{\"nodes\":[%s],\"links\":[%s]}" - (mapconcat - (lambda (pair) - (format "{\"name\":%S,\"group\":%d}" - (car pair) (cdr pair))) - nodes ",") - (mapconcat - (lambda (link) - (format "{\"source\":%d,\"target\":%d,\"value\":1}" - (car link) (cdr link))) - (meta-to-links meta nodes) ","))))) - -(provide 'org-bibtex-extras) -;;; org-bibtex-extras ends here diff --git a/contrib/odt/BasicODConverter/BasicODConverter-0.8.0.oxt b/contrib/odt/BasicODConverter/BasicODConverter-0.8.0.oxt new file mode 100644 index 0000000000000000000000000000000000000000..511187a32f53bfdd27e17d84bd96809e5b16f483 GIT binary patch literal 8009 zcmaJ`by(ET_Fftm7m$<&X^>vJL%O6xkcJhOT98f&NpUHq8|elSX~9KYVL`gPQxKK< zt@l3P>%HFZ{muR{^XzlZJD)i-?|J6TtEY*DO%4Fy;{)c+hGcUx6DR#J001#e0Dukv z0C>1K@!C7U?D+p0ctJe8A?|K`-hSSe543gZ1aEbyuE?3KyEjrMo*@pSKv;*0?wC2GfN+Hxm%!39dBBOe#EpNIJ+RU}hWu zJ8RwCmdXylAy5zUb8v1_$=o)d|1 zo_)j@nwTKjS{egL+u|>As${(dK3H*34c-&JpRXg2FX?5jAVbyN#H5(Q$)eeoe+)UC zZjDkEF5Jfy>ho{n8=JWUJHOu?(jdD%eA+NtYv~3pUfOOrdArwsZO-3Z2`jly4nn+) zr`uUR`ys~v#U-@iwi(ZvP(bw3tm{_-jVb^1z1g;(w$$tvuJ;6EQzFmaG4ap$9w!Dhx% z_4R9pcP~ZtE_{Lg_+Q^#)thAvzV(%2%G!j>LeDq_U$1AE-{}3vj$Jx2CJmu?Y8t(3 z6zE?2zM%rIx{eAz)W!|s=m7KP^Mkskz36$|CvYqJFgR|hJ!fB3WwfE@^zG0$KwPzb zVUnwB8>@Sly`In%m)No9t}*=#N(9T)*i5EW>)g@EbQW+%vT88H!xQhU|t=JWyfY6{-BK|jAteu)Vi~P`;ZxS66RN`5K z=^ePD9=b~ET|E2p)@)*DH|Ljt|6F|vWvu26dey7w)f1!pUuX5NBZ^*kNwT)rQ-NDi zlY?3ZO96c!Mb(`o!^0gXp`!a3bR^0kM8ZDcLoKshiv4U!?x~DA|7;?(FQASHw2m?# zxQ)fF6>GSO8a~gMQfVI^7vkxmpp;@9FxI4G@{*7XSS-t~5yFNulr7F;gql50{m$&T$XMKEd;&Fbrj}&1SWo=fQCA{{oO#gc4n+N;; z^GuzSeER4NLM3K=;`GW_?@GP;Y}?X~o6p#>3139EKMf3DV)uEm|Fo`4?yfnjs}GA+ zf~XhLEX-gO%9+P3>cg-3Wek)3eUE4qX6`Ptfx=a|7}#Yw~RN*;xeD``w?6l=K-J7$X; zc(OXYv-?nih!xi5%Z#+wVU5sKr2KkFwZwLWnF+A0G%_L@O2m~FO;Qmf=)91bsY0<3 zDQ5UNJ$iN*!NA!DuaNrNeql=5{_E4=FxrIxSyuuNphk3bf&l)Z5z&8OQ z{>QgLR!JWwWxv&AXig5WkX8+>4kEGHrzwwr4*OHoc3BB4Guk^etgveYoqYV;$+2-=m`NVxPy>-T%=UWy|a|DdX zd%x#`e~c&cdQc8OC)89RVy!GBbj6LtnDQ>k4vKe(C6C zj~_6_i7DHN_B<_n)P<5%VN zNwH5U4PQ61omOj$7J2L@DmpIQ?!QexU)R+jn}K*IpUBpWm$2>J!R%bkLO6VG)p=1-Rt+(%N0#(&FrU)U-YLrmN|vZYM5jEbPmcPu zEsQjkSj_3g-YxBS=3{8r01Y)%l<3Tzb$AmwQ$>~ogp`78RQru|V;re0)5 zGD#_sU;o>5N#~P+YE_E4D)iIzN9edrba9Xme8H*%;18wX5A!HG+EG0<-6Eq*KOM55 zSC34kfV;#OT(1gg)HNFcF&g9x^$^K3(1F`WvYb@*h!JHP@MBnPi#io==gh73h0KKL zbV^{I6IpA}$0EZil(!qOB3c~9<||zG0#{3nGdOrKl`S6|Gf3@~F~8Rkcq1G3=6GC5ll-H( z|84-$bkx>d3GI*==7#4NDPz3%gXvks?f|!zU*Xx2G0jD8bns|Zv$b#RhXcV?Nkq<< zB=Riy`w-V5;?{SEQqDSxZ=a=bNhsRbk(PB;k)d6 z(a!gxFtJ`2-c@qQC6OzcDWKMX{G+dp1#xh_Vy8>nRNYkuMAy#eZ&;J*|)RRE&4pnlLZ)iaplgp z;L~hj=i@Ekh*c$4m|Pct%c?_GG(7`k9P#j!GH}Dpgrq-=h4gYKFs-sb7Iy1a)-Krb zgB5FHsU3eAIbuJ0+)O5YR`I2T9L(VeemmG2VB`q?V#$|=rVaydt1-_WtBW=%hw#@i zXDUyOB0ZlF1)qolP{pYAYth7z*OG^O^eDPlqkBxK9!qU+fp{O9NL-){bn?D833&x& z6!6#qx%{Y5y=Y-hGOT^77)-(_S#ey@1>5|gA&hBR91A6DJ}bBw9|@d?&f?Jq`=$(F zVjT(5GAN$P6oum~m4NX`f`=jU7=F}9X5~d;8dHFk%2#F7x%b@1;6owMJpg}^MC4YW z3Kn7akTVhU&sCA|;&sCR9vgsBaw*|>EJ&lK+_eosgU z$4f~AtH9L+~g`Q}m-lZ;-gh;5L;5jR~H^O)Rmv_Qi z3kGy=4NNloy&8&Tq8z+6<0F(d@s2)cKlyJ(s; zY?2G;p#3^jV9?zz_u=?im7ZP*$R4aRZH1yosl5;_hnJ~Qfax6rXWPU_UEPafitn;u&$p;Gu&D`;ZUaL|tniDADY zJlhRFrq&j@{Yb*4I(>?War}LuUT5z~nS~r*r;j{cWk9U+rC22owaL3HAHJubLO#n_ zyT&U1*eBj(q#Sb#D1x~~g$XAzfs@}g8>F=6ntl;Nn8kxr;?3e+n2P)h-}%gG8`|R- zjV|DnFcUFtumfX%h%F;zb7V8hZKW*Ri#Sp~5o2Ylh+1uO{BZtGXc7-63Z?XDca4_Ef5DDUaQ4%2@$6%5y3ALraeD>0%ee z&WwgtO^}zs1F?lNc`<%bUAl&>1%q@|QcUjA=nWg3VMm7T)@s~zKXpWM+}neF;gf?YEy6q&ou)< zV}i!HfmQhr7?*A}XkUeZU*${mS$rcf|GMgOHrmzG6OQR z)fBL{A%NNJrrfgK0Gc_`aeUjWUHToyJ6t*NG9L!pKIS>Q2~4xdvi!%P422#HzEuSn z7u$+P0fdGM6yF=m{2hO=23^=Mi}5Zp8>D5kzwJABKNx*_-vNU(Eh^+TC8dBi68A2y zYmZTJo1Hjlv#7zUb&+P!nP?~5d%@L#i#jo+`>~J`|BDAx6$7GSb!iEuMPGB9H(J<@ zehOQtZp!%HhuLe5_4^N7qUf?vFLSu6TA!ptNR7O3#S^`vYl_NW6~xDwRH_#UgR^l@ z5AXnqN#!&qy5;vB!1UQ%pDZdVwqCr3f3E=2j2ZZ?vTsGIuvP%TB6yR=ixb9qEqEOg z_d1A{#2z;XwwspH`xS*xTznXn?2Z98`Kg*MgiP7=giXFo54;SH>2tW8$L2T$vSQH4I`tK)2pR9XapOeSnqpX) z7;BgG%H10_Ta`CA;vO>{+}+TST}}<%V(qxbxoffG4p}*@=l)I$%Ghq+J+F}ggD^uh z#R{-3+iVaCna*41`hpWlnart1-G)~1af)5_%Y$lf$LE#GL#*EpqPHivUNs*tQqp`m zT<3KhFQy=h*FMmF7NdJHSP3})6g7|=SFKi7HjKTD0C9Esi!0e^+devR>+RwN^Q^0f zYJ~RlY1qx?QPJM`w_BYDKJq{W@ULj|O>fP=IkFl$zrp#>+R)o`_V^eN09d310I1Qm z;eXXT+BOikU&T(fsfGKjBxy)X2+rh`!4zK2Ua`1*)&wtH+zo3jdTM%47N<#hR@q)Z zrg-%G;^EQVxYYe7Vh-YZ<EJwGH9y!mK0cPQ%s$BLE%452a zT{dfG)?!YUrL&szelXck*7mWTNjjYXDCloHIWXU>zdq=JP>^&lW_+$vRKT`9!7ccX zdG$b~^bJU8Z zoEPe$MVPqga8NsWk9*B;|7yITbui%jsSfU1BB+AGHxDN4^;mXMr+1 z{pvW+TN2amz<_>Fx5btY-%yi>!MRTfOM>?T6}r}b)^=MU&4i`-vi`rvHn165;gis)0?ZdJT>g66TxZY`l}uC3$sKz=4=uXdCH-3eQ0Gkh0D~=|w{hE1@hWZTVSxs&$PDF~ruc@R*WT zMB7HDW)$$JR@^?ITts0~oQ&>4ta3jfVPV5It8h$h=y6p1joy$O- z!jo)wjnCFHSK;dv!?&CRt>SgCv^PZ`@p$R5HsWzL4J`R206FqKoj0Xo>U0EoxfN)J zd&qnao;3;Vex|5%avnWY7RkiuXK-itS<7ChsTl}ze^Le;8i^uF7UWIK1mk*^VOr0( z4-BvAbVuvW-YgYXB;F{%)OaqW!{kkh<;0Z(bv;6c;-Fg9sHN07n48>DJl`|2yLlA+ zW0;?gWix@D80V)E`i{eX=JFE3HN&*qw#IoQyNBXByD8w~XG?d;yJ!fIq(_R%OUo}R zMD9I$$KC7g3)G_{Y$-QpDcj_Rm_9kDb1no|Hr!gGdNzw;&$6Lb7Gh!bKmF%$5XkOqILWgzr7eiLa(C zz+lEVX3ZoGdZmF%H3@4Wae2$!xh}q#u!pKwly$c~S~RZ6|8$2;QgD0CFx}L_g^Zwb z8*5egu9bDeELAdFDivIZZkAYIp80gW>qR=;1a1`fC6e;>cH6#=Kq*&GJmyxZxs@eq zH10Ts`je2(qQs=pu~$(r$FAD!V*Xy6IZbg;F!x=4$+4pdrFKm572YAHL+V=l$EB*P zE(z&t9B^zQu?)xiPR$MtnB7o4^4AY%1*=SkZ9{wSiPGTUtY31yAD>$4=6}P zf-ri=9lt9M>fT{@PEX%Gne_^i7K*Msj?vAN4f*b*%pmdN1LO5ik1wJZ9Koe{4m(Jj zM1`l>1#K5H!L`mh(URa3g2qdTBF-TBWGlQ(E=g{|L<UUp<8SxJ{&T z=+rC|DSID@<@vqen2&Y3 z={ZwrJmHfwY+K-rDCkQ5!j`(mS{qnjZTnMti(cF2r%(0eJQ-B`tokNbtqzes@`h4$ z+JA|L*@qG{#M;Vh(F%|@f_ejP^&>#Qq4LyU%z(sIS1aL)qJ5*xaGnOkpX9tJGLn*p zlS&4KsT)sNCzX0|qI+0;2X&E#wTvb7njp3WgOVpLRd~Fr3#ZdMy8t~DY6~g;8mZ=2 znUs^3_|np3o92TBcPpulF>i!>sLXkP zZ64kC>=O4;%o9wd(Ds6fn}=X&$+$rQ)X%UD1_vE;74p`BN^G^wW4r5DBy)pz$NM=FVd zC_=@TG%ch2)^Aq$kPmsYHwVyuWcsuZx~yr*5i=EpMo?wSD$!V<9D zM1$OujywBc-B0_&dMeE$XPpVbH8DW1Dem3A&RbP^-*ddl=e%hV=#txUnpe3UcVz<$ zH6b*;+rrY;a+p|{aCN(Wo8~y4*0>g{jT0`n^6fUZ*3GLV8u(2K^znKxLD~`N>Knzi z)NWX>cJ8J)WNGfxV7SHwIENvj!oVZo0i3)8zO7%PQ(9{IRp zHX*zuk1ceJq1ZF*X7|ZJDc`b%`BMMJ4&h%%0{~b;%VFrC{Hx)jM-V%AHyHo_wgIAT zbR8Wbb`JbT>i>@&2yN%(-~@qrd)fSw)Ba`pPZbVIr(oBHHlajs$S+6*dwcY}e13L5 z4$qOmUICKGVPJ5~sHP6I!m79_j!HpK`t_0stINI2c{p~ZyL-j=r@54l8?*CVWhSsB zerro@(|U#U#yfiOiU%gHtvO|OqB+V}a0De>O9_9=fbHG0q7XW3@B2p;Yg@qv9y%Z< zdZOmYgsP1`X+{siw@(%p;9{OW?)lK!D*E8wi*YZO=hn&@2Q`HPdThca`16`BkQtjgGVglwD*s#=1h;T+;l_)p(%%fNe=kmLL+*W|JMFe8~;vr{1fR< z0qi$S13G+vD~J6F@u!OP8=?-agZ`l@{ptLttn%A=4(o4c7gV-&x`}(BISOHxMy8;r>OczYfTM z`~2d-?S^NqN(KNz^zRe;fH?h9 H$^rie=t~1D literal 0 HcmV?d00001 diff --git a/contrib/odt/BasicODConverter/Filters.bas b/contrib/odt/BasicODConverter/Filters.bas new file mode 100644 index 0000000..5912f65 --- /dev/null +++ b/contrib/odt/BasicODConverter/Filters.bas @@ -0,0 +1,213 @@ +REM ***** BASIC ***** + +Dim DocTypes + +Private DocTypeToFiltersMap As New Collection +Private WriterExportFilters As New Collection +Private WriterWebExportFilters As New Collection +Private CalcExportFilters As New Collection +Private ImpressExportFilters As New Collection +Private DrawExportFilters As New Collection + + +Private ExportFiltersInited As Boolean + +Sub InitExportFilters + If ExportFiltersInited Then + Exit Sub + End If + + DocTypes = Array(_ + "com.sun.star.text.TextDocument", _ + "com.sun.star.sheet.SpreadsheetDocument", _ + "com.sun.star.presentation.PresentationDocument", _ + "com.sun.star.drawing.DrawingDocument",_ + "com.sun.star.text.WebDocument"_ + ) + With WriterExportFilters + .Add Key := "bib" , Item :=Array("bib" , "BibTeX" , "BibTeX_Writer ") + .Add Key := "doc" , Item :=Array("doc" , "Microsoft Word 97/2000/XP" , "MS Word 97 ") + .Add Key := "doc6" , Item :=Array("doc" , "Microsoft Word 6.0" , "MS WinWord 6.0 ") + .Add Key := "doc95" , Item :=Array("doc" , "Microsoft Word 95" , "MS Word 95 ") + .Add Key := "docbook" , Item :=Array("xml" , "DocBook" , "DocBook File ") + .Add Key := "html" , Item :=Array("html" , "HTML Document (OpenOffice.org Writer)" , "HTML (StarWriter) ") + .Add Key := "latex" , Item :=Array("ltx" , "LaTeX 2e" , "LaTeX_Writer ") + .Add Key := "mediawiki" , Item :=Array("txt" , "MediaWiki" , "MediaWiki ") + .Add Key := "odt" , Item :=Array("odt" , "ODF Text Document" , "writer8 ") + .Add Key := "ooxml" , Item :=Array("xml" , "Microsoft Office Open XML" , "MS Word 2003 XML ") + .Add Key := "ott" , Item :=Array("ott" , "Open Document Text" , "writer8_template ") + .Add Key := "pdf" , Item :=Array("pdf" , "Portable Document Format" , "writer_pdf_Export ") + .Add Key := "rtf" , Item :=Array("rtf" , "Rich Text Format" , "Rich Text Format ") + .Add Key := "sdw" , Item :=Array("sdw" , "StarWriter 5.0" , "StarWriter 5.0 ") + .Add Key := "sdw3" , Item :=Array("sdw" , "StarWriter 3.0" , "StarWriter 3.0 ") + .Add Key := "sdw4" , Item :=Array("sdw" , "StarWriter 4.0" , "StarWriter 4.0 ") + .Add Key := "stw" , Item :=Array("stw" , "Open Office.org 1.0 Text Document Template" , "writer_StarOffice_XML_Writer_Template ") + .Add Key := "sxw" , Item :=Array("sxw" , "Open Office.org 1.0 Text Document" , "StarOffice XML (Writer) ") + .Add Key := "text" , Item :=Array("txt" , "Text Encoded" , "Text (encoded) ") + .Add Key := "txt" , Item :=Array("txt" , "Text" , "Text ") + .Add Key := "uot" , Item :=Array("uot" , "Unified Office Format text" , "UOF text ") + .Add Key := "vor" , Item :=Array("vor" , "StarWriter 5.0 Template" , "StarWriter 5.0 Vorlage/Template ") + .Add Key := "vor3" , Item :=Array("vor" , "StarWriter 3.0 Template" , "StarWriter 3.0 Vorlage/Template ") + .Add Key := "vor4" , Item :=Array("vor" , "StarWriter 4.0 Template" , "StarWriter 4.0 Vorlage/Template ") + .Add Key := "xhtml" , Item :=Array("html" , "XHTML Document" , "XHTML Writer File ") + End With + + With DrawExportFilters + .Add Key := "bmp" , Item :=Array("bmp" , "Windows Bitmap" , "draw_bmp_Export ") + .Add Key := "emf" , Item :=Array("emf" , "Enhanced Metafile" , "draw_emf_Export ") + .Add Key := "eps" , Item :=Array("eps" , "Encapsulated PostScript" , "draw_eps_Export ") + .Add Key := "gif" , Item :=Array("gif" , "Graphics Interchange Format" , "draw_gif_Export ") + .Add Key := "html" , Item :=Array("html" , "HTML Document (OpenOffice.org Draw)" , "draw_html_Export ") + .Add Key := "jpg" , Item :=Array("jpg" , "Joint Photographic Experts Group" , "draw_jpg_Export ") + .Add Key := "met" , Item :=Array("met" , "OS/2 Metafile" , "draw_met_Export ") + .Add Key := "odd" , Item :=Array("odd" , "OpenDocument Drawing" , "draw8 ") + .Add Key := "otg" , Item :=Array("otg" , "OpenDocument Drawing Template" , "draw8_template ") + .Add Key := "pbm" , Item :=Array("pbm" , "Portable Bitmap" , "draw_pbm_Export ") + .Add Key := "pct" , Item :=Array("pct" , "Mac Pict" , "draw_pct_Export ") + .Add Key := "pdf" , Item :=Array("pdf" , "Portable Document Format" , "draw_pdf_Export ") + .Add Key := "pgm" , Item :=Array("pgm" , "Portable Graymap" , "draw_pgm_Export ") + .Add Key := "png" , Item :=Array("png" , "Portable Network Graphic" , "draw_png_Export ") + .Add Key := "ppm" , Item :=Array("ppm" , "Portable Pixelmap" , "draw_ppm_Export ") + .Add Key := "ras" , Item :=Array("ras" , "Sun Raster Image" , "draw_ras_Export ") + .Add Key := "std" , Item :=Array("std" , "OpenOffice.org 1.0 Drawing Template" , "draw_StarOffice_XML_Draw_Template ") + .Add Key := "svg" , Item :=Array("svg" , "Scalable Vector Graphics" , "draw_svg_Export ") + .Add Key := "svm" , Item :=Array("svm" , "StarView Metafile" , "draw_svm_Export ") + .Add Key := "swf" , Item :=Array("swf" , "Macromedia Flash (SWF)" , "draw_flash_Export ") + .Add Key := "sxd" , Item :=Array("sxd" , "OpenOffice.org 1.0 Drawing" , "StarOffice XML (Draw) ") + .Add Key := "sxd3" , Item :=Array("sxd" , "StarDraw 3.0" , "StarDraw 3.0 ") + .Add Key := "sxd5" , Item :=Array("sxd" , "StarDraw 5.0" , "StarDraw 5.0 ") + .Add Key := "tiff" , Item :=Array("tiff" , "Tagged Image File Format" , "draw_tif_Export ") + .Add Key := "vor" , Item :=Array("vor" , "StarDraw 5.0 Template" , "StarDraw 5.0 Vorlage ") + .Add Key := "vor3" , Item :=Array("vor" , "StarDraw 3.0 Template" , "StarDraw 3.0 Vorlage ") + .Add Key := "wmf" , Item :=Array("wmf" , "Windows Metafile" , "draw_wmf_Export ") + .Add Key := "xhtml" , Item :=Array("xhtml" , "XHTML" , "XHTML Draw File ") + .Add Key := "xpm" , Item :=Array("xpm" , "X PixMap" , "draw_xpm_Export ") + + + End With + + With ImpressExportFilters + .Add Key := "bmp" , Item :=Array("bmp" , "Windows Bitmap" , "impress_bmp_Export ") + .Add Key := "emf" , Item :=Array("emf" , "Enhanced Metafile" , "impress_emf_Export ") + .Add Key := "eps" , Item :=Array("eps" , "Encapsulated PostScript" , "impress_eps_Export ") + .Add Key := "gif" , Item :=Array("gif" , "Graphics Interchange Format" , "impress_gif_Export ") + .Add Key := "html" , Item :=Array("html" , "HTML Document (OpenOffice.org Impress)" , "impress_html_Export ") + .Add Key := "jpg" , Item :=Array("jpg" , "Joint Photographic Experts Group" , "impress_jpg_Export ") + .Add Key := "met" , Item :=Array("met" , "OS/2 Metafile" , "impress_met_Export ") + .Add Key := "odg" , Item :=Array("odg" , "ODF Drawing (Impress)" , "impress8_draw ") + .Add Key := "odp" , Item :=Array("odp" , "ODF Presentation" , "impress8 ") + .Add Key := "otp" , Item :=Array("otp" , "ODF Presentation Template" , "impress8_template ") + .Add Key := "pbm" , Item :=Array("pbm" , "Portable Bitmap" , "impress_pbm_Export ") + .Add Key := "pct" , Item :=Array("pct" , "Mac Pict" , "impress_pct_Export ") + .Add Key := "pdf" , Item :=Array("pdf" , "Portable Document Format" , "impress_pdf_Export ") + .Add Key := "pgm" , Item :=Array("pgm" , "Portable Graymap" , "impress_pgm_Export ") + .Add Key := "png" , Item :=Array("png" , "Portable Network Graphic" , "impress_png_Export ") + .Add Key := "pot" , Item :=Array("pot" , "Microsoft PowerPoint 97/2000/XP Template" , "MS PowerPoint 97 Vorlage ") + .Add Key := "ppm" , Item :=Array("ppm" , "Portable Pixelmap" , "impress_ppm_Export ") + .Add Key := "ppt" , Item :=Array("ppt" , "Microsoft PowerPoint 97/2000/XP" , "MS PowerPoint 97 ") + .Add Key := "pwp" , Item :=Array("pwp" , "PlaceWare" , "placeware_Export ") + .Add Key := "ras" , Item :=Array("ras" , "Sun Raster Image" , "impress_ras_Export ") + .Add Key := "sda" , Item :=Array("sda" , "StarDraw 5.0 (OpenOffice.org Impress)" , "StarDraw 5.0 (StarImpress) ") + .Add Key := "sdd" , Item :=Array("sdd" , "StarImpress 5.0" , "StarImpress 5.0 ") + .Add Key := "sdd3" , Item :=Array("sdd" , "StarDraw 3.0 (OpenOffice.org Impress)" , "StarDraw 3.0 (StarImpress) ") + .Add Key := "sdd4" , Item :=Array("sdd" , "StarImpress 4.0" , "StarImpress 4.0 ") + .Add Key := "sti" , Item :=Array("sti" , "OpenOffice.org 1.0 Presentation Template" , "impress_StarOffice_XML_Impress_Template ") + .Add Key := "svg" , Item :=Array("svg" , "Scalable Vector Graphics" , "impress_svg_Export ") + .Add Key := "svm" , Item :=Array("svm" , "StarView Metafile" , "impress_svm_Export ") + .Add Key := "swf" , Item :=Array("swf" , "Macromedia Flash (SWF)" , "impress_flash_Export ") + .Add Key := "sxd" , Item :=Array("sxd" , "OpenOffice.org 1.0 Drawing (OpenOffice.org Impress)" , "impress_StarOffice_XML_Draw ") + .Add Key := "sxi" , Item :=Array("sxi" , "OpenOffice.org 1.0 Presentation" , "StarOffice XML (Impress) ") + .Add Key := "tiff" , Item :=Array("tiff" , "Tagged Image File Format" , "impress_tif_Export ") + .Add Key := "uop" , Item :=Array("uop" , "Unified Office Format presentation" , "UOF presentation ") + .Add Key := "vor" , Item :=Array("vor" , "StarImpress 5.0 Template" , "StarImpress 5.0 Vorlage ") + .Add Key := "vor3" , Item :=Array("vor" , "StarDraw 3.0 Template (OpenOffice.org Impress)" , "StarDraw 3.0 Vorlage (StarImpress) ") + .Add Key := "vor4" , Item :=Array("vor" , "StarImpress 4.0 Template" , "StarImpress 4.0 Vorlage ") + .Add Key := "vor5" , Item :=Array("vor" , "StarDraw 5.0 Template (OpenOffice.org Impress)" , "StarDraw 5.0 Vorlage (StarImpress) ") + .Add Key := "wmf" , Item :=Array("wmf" , "Windows Metafile" , "impress_wmf_Export ") + .Add Key := "xhtml" , Item :=Array("xml" , "XHTML" , "XHTML Impress File ") + .Add Key := "xpm" , Item :=Array("xpm" , "X PixMap" , "impress_xpm_Export ") + + End With + + With CalcExportFilters + .Add Key := "csv" , Item :=Array("csv" , "Text CSV" , "Text - txt - csv (StarCalc) ") + .Add Key := "dbf" , Item :=Array("dbf" , "dBASE" , "dBase ") + .Add Key := "dif" , Item :=Array("dif" , "Data Interchange Format" , "DIF ") + .Add Key := "html" , Item :=Array("html" , "HTML Document (OpenOffice.org Calc)" , "HTML (StarCalc) ") + .Add Key := "ods" , Item :=Array("ods" , "ODF Spreadsheet" , "calc8 ") + .Add Key := "ooxml" , Item :=Array("xml" , "Microsoft Excel 2003 XML" , "MS Excel 2003 XML ") + .Add Key := "ots" , Item :=Array("ots" , "ODF Spreadsheet Template" , "calc8_template ") + .Add Key := "pdf" , Item :=Array("pdf" , "Portable Document Format" , "calc_pdf_Export ") + .Add Key := "sdc" , Item :=Array("sdc" , "StarCalc 5.0" , "StarCalc 5.0 ") + .Add Key := "sdc3" , Item :=Array("sdc" , "StarCalc 3.0" , "StarCalc 3.0 ") + .Add Key := "sdc4" , Item :=Array("sdc" , "StarCalc 4.0" , "StarCalc 4.0 ") + .Add Key := "slk" , Item :=Array("slk" , "SYLK" , "SYLK ") + .Add Key := "stc" , Item :=Array("stc" , "OpenOffice.org 1.0 Spreadsheet Template" , "calc_StarOffice_XML_Calc_Template ") + .Add Key := "sxc" , Item :=Array("sxc" , "OpenOffice.org 1.0 Spreadsheet" , "StarOffice XML (Calc) ") + .Add Key := "uos" , Item :=Array("uos" , "Unified Office Format spreadsheet" , "UOF spreadsheet ") + .Add Key := "vor" , Item :=Array("vor" , "StarCalc 5.0 Template" , "StarCalc 5.0 Vorlage/Template ") + .Add Key := "vor3" , Item :=Array("vor" , "StarCalc 3.0 Template" , "StarCalc 3.0 Vorlage/Template ") + .Add Key := "vor4" , Item :=Array("vor" , "StarCalc 4.0 Template" , "StarCalc 4.0 Vorlage/Template ") + .Add Key := "xhtml" , Item :=Array("xhtml" , "XHTML" , "XHTML Calc File ") + .Add Key := "xls" , Item :=Array("xls" , "Microsoft Excel 97/2000/XP" , "MS Excel 97 ") + .Add Key := "xls5" , Item :=Array("xls" , "Microsoft Excel 5.0" , "MS Excel 5.0/95 ") + .Add Key := "xls95" , Item :=Array("xls" , "Microsoft Excel 95" , "MS Excel 95 ") + .Add Key := "xlt" , Item :=Array("xlt" , "Microsoft Excel 97/2000/XP Template" , "MS Excel 97 Vorlage/Template ") + .Add Key := "xlt5" , Item :=Array("xlt" , "Microsoft Excel 5.0 Template" , "MS Excel 5.0/95 Vorlage/Template ") + .Add Key := "xlt95" , Item :=Array("xlt" , "Microsoft Excel 95 Template" , "MS Excel 95 Vorlage/Template ") + + End With + + With WriterWebExportFilters + .Add Key := "etext" , Item :=Array("txt" , "Text Encoded (OpenOffice.org Writer/Web)" , "Text (encoded) (StarWriter/Web) ") + .Add Key := "html" , Item :=Array("html" , "HTML Document" , "HTML ") + '.Add Key := "html" , Item :=Array("html" , "HTML Document Template" , "writerweb8_writer_template ") + .Add Key := "html10" , Item :=Array("html" , "OpenOffice.org 1.0 HTML Template" , "writer_web_StarOffice_XML_Writer_Web_Template ") + .Add Key := "mediawiki" , Item :=Array("txt" , "MediaWiki" , "MediaWiki_Web ") + .Add Key := "pdf" , Item :=Array("pdf" , "PDF - Portable Document Format" , "writer_web_pdf_Export ") + .Add Key := "sdw" , Item :=Array("sdw" , "StarWriter 5.0 (OpenOffice.org Writer/Web)" , "StarWriter 5.0 (StarWriter/Web) ") + .Add Key := "sdw3" , Item :=Array("sdw" , "StarWriter 3.0 (OpenOffice.org Writer/Web)" , "StarWriter 3.0 (StarWriter/Web) ") + .Add Key := "sdw4" , Item :=Array("sdw" , "StarWriter 4.0 (OpenOffice.org Writer/Web)" , "StarWriter 4.0 (StarWriter/Web) ") + .Add Key := "text" , Item :=Array("txt" , "Text (OpenOffice.org Writer/Web)" , "Text (StarWriter/Web) ") + .Add Key := "text10" , Item :=Array("txt" , "OpenOffice.org 1.0 Text Document (OpenOffice.org Writer/Web)" , "writer_web_StarOffice_XML_Writer ") + .Add Key := "odt" , Item :=Array("txt" , "OpenOffice.org Text (OpenOffice.org Writer/Web)" , "writerweb8_writer ") + .Add Key := "vor" , Item :=Array("vor" , "StarWriter/Web 5.0 Template" , "StarWriter/Web 5.0 Vorlage/Template ") + .Add Key := "vor4" , Item :=Array("vor" , "StarWriter/Web 4.0 Template" , "StarWriter/Web 4.0 Vorlage/Template ") + + End With + + With DocTypeToFiltersMap + .Add Key := "com.sun.star.text.TextDocument", Item := WriterExportFilters + .Add Key := "com.sun.star.sheet.SpreadsheetDocument", Item := CalcExportFilters + .Add Key := "com.sun.star.presentation.PresentationDocument", Item :=ImpressExportFilters + .Add Key := "com.sun.star.drawing.DrawingDocument", Item := DrawExportFilters + .Add Key := "com.sun.star.text.WebDocument", Item := WriterWebExportFilters + End With + ExportFiltersInited = True +End Sub + +Function FilterSaveExtension(filterDescriptor ()) + FilterSaveExtension = Trim(filterDescriptor(0)) +End Function + +Function FilterHandler(filterDescriptor ()) + FilterHandler = Trim(filterDescriptor(2)) +End Function + +Function GetFilter(docType, outputFormat) + Dim filters + + On Error Goto MissingFilter + filters = DocTypeToFiltersMap(docType) + LogMessage "output format is " & outputFormat + GetFilter = filters(outputFormat) + +Done: + Exit Function + +MissingFilter: + LogMessage("No existing filters for exporting " & docType & " to " & outputFormat) + GetFilter = Null + Resume Done +End Function + diff --git a/contrib/odt/BasicODConverter/Main.bas b/contrib/odt/BasicODConverter/Main.bas new file mode 100644 index 0000000..44838d3 --- /dev/null +++ b/contrib/odt/BasicODConverter/Main.bas @@ -0,0 +1,201 @@ +REM ***** BASIC ***** + +Dim Interactive As Boolean +Dim WaitFor + +Function Convert(Optional inFileURL, Optional filterSpec, Optional outFileURL) + Dim inDoc, inDocType, openParams, closeInDoc, presentationDoc + + ' Set Interactivity i.e., LogMessage pops up a message. + Interactive = False + + WaitFor = 10 + + ' Init dependencies + BasicLibraries.LoadLibrary("Tools") + ' BasicLibraries.LoadLibrary("XrayTool") + + ' Setup Export filters + InitExportFilters + + ' Export to doc format by default + If IsMissing(filterSpec) Then + If Interactive Then + filterSpec = InputBox("Export to: ") + Else + filterSpec = "doc" + End If + End If + filterSpec = Trim(filterSpec) + + closeInDoc = False + If IsMissing(inFileURL) Then + ' Most likely, the Macro is run interactively. Act on + ' the current document + If Not ThisComponent.HasLocation() Then + LogMessage("Document doesn't have a location") + Goto Failure + End If + + inDoc = ThisComponent + inFileURL = inDoc.GetLocation() + closeInDoc = False + + Else + ' Load the document + On Error Goto Failure + openParams = Array(MakePropertyValue("Hidden", True),MakePropertyValue("ReadOnly", True),) + + 'openParams = Array() + inDoc = StarDesktop.loadComponentFromURL(inFileURL, "_blank", 0, OpenParams()) + closeInDoc = True + End If + + If IsMissing(outFileURL) Then + outFileURL = GetURLWithoutExtension(inFileURL) + End If + + If ExportDocument(inDoc, filterSpec, outFileURL) Then + Goto Success + End If + + LogMessage("filterSpec1 is " & filterSpec) + + ' Export didn't go through. Maybe didn't find a valid filter. + + ' Check whether the request is to convert a Text or a Web + ' Document to a Presentation Document + + inDocType = GetDocumentType(inDoc) + If (inDocType = "com.sun.star.text.TextDocument" Or _ + inDocType = "com.sun.star.text.WebDocument") Then + LogMessage("Filterspec2 is " & filterSpec) + filter = GetFilter("com.sun.star.presentation.PresentationDocument", filterSpec) + If IsNull(filter) Then + LogMessage("We tried our best. Nothing more to do" + Goto Failure + Else + LogMessage("Trying to create presentation document. Found valid filter for " & filterSpec) + End If + Else + Goto Failure + End If + + ' Export Outline to Presentation + dispatcher = createUnoService("com.sun.star.frame.DispatchHelper") + dispatcher.executeDispatch(inDoc.CurrentController.Frame, ".uno:SendOutlineToStarImpress", "", 0, Array()) + + ' Dispatch event above is aynchronous. Wait for a few seconds for the above event to finish + Wait(WaitFor * 1000) + + ' After the dispatch, the current component is a presentation + ' document. Note that it doesn't have a location + + presentationDoc = ThisComponent + If IsNull(ExportDocument(presentationDoc, filter, outFileURL)) Then + Goto Failure + Else + presentationDoc.Close(True) + End If + +Success: + LogMessage("Successfully exported to " & outFileURL ) + Goto Done + +Failure: + LogMessage("Export failed " & outFileURL ) + Goto Done + +Done: + If closeInDoc Then + inDoc.Close(True) + End If +End Function + +' http://codesnippets.services.openoffice.org/Writer/Writer.MergeDocs.snip +' http://user.services.openoffice.org/en/forum/viewtopic.php?f=20&t=39983 +' http://user.services.openoffice.org/en/forum/viewtopic.php?f=21&t=23531 + +' http://wiki.services.openoffice.org/wiki/Documentation/BASIC_Guide/Files_and_Directories_%28Runtime_Library%29 + + +Function ExportDocument(inputDoc, filterSpec, outFileURL) As Boolean + Dim inputDocType, filter + ExportDocument = False + + On Error Goto Failure + inputDocType = GetDocumentType(inputDoc) + + If IsArray(filterSpec) Then + ' Filter is fully specified + filter = filterSpec + Else + ' Filter is specified by it's name + filter = GetFilter(inputDocType, filterSpec) + End If + + If InStr(outFileURL, ".") = 0 Then + outFileURL = outFileURL & "." & FilterSaveExtension(filter) + End If + + LogMessage("outFileURL is " & outFileURL) + + inputDoc.storeToUrl(outFileURL, Array(MakePropertyValue("FilterName", FilterHandler(filter)))) + + ExportDocument = True + LogMessage("Export to " & outFileURL & " succeeded") +Done: + Exit Function + +Failure: + LogMessage("Export to " & outFileURL & " failed") + Resume Done +End Function + + +Function GetURLWithoutExtension(s As String) + Dim pos + pos = Instr(s, ".") + If pos = 0 Then + GetURLWithoutExtension = s + Else + GetURLWithoutExtension = Left(s, pos - 1) + End If +End Function + +Function GetDocumentType(oDoc) + For Each docType in DocTypes + If (oDoc.supportsService(docType)) Then + GetDocumentType = docType + Exit Function + End If + Next docType + GetDocumentType = Nothing +End Function + +Function MakePropertyValue(Optional sName As String, Optional sValue) As com.sun.star.beans.PropertyValue + Dim oPropertyValue As New com.sun.star.beans.PropertyValue + + If Not IsMissing(sName) Then + oPropertyValue.Name = sName + EndIf + + If Not IsMissing(sValue) Then + oPropertyValue.Value = sValue + EndIf + + MakePropertyValue() = oPropertyValue + +End Function + + +Sub LogMessage(message) + If Interactive Then + If Err <> 0 Then + Print "Error " & Err & ": " & Error$ & " (line : " & Erl & ")" + End If + Print message + End If +End Sub + + diff --git a/lisp/ob-io.el b/lisp/ob-io.el deleted file mode 100644 index 7742fc6..0000000 --- a/lisp/ob-io.el +++ /dev/null @@ -1,122 +0,0 @@ -;;; ob-io.el --- org-babel functions for Io evaluation - -;; Copyright (C) 2012 Free Software Foundation, Inc. - -;; Author: Andrzej Lichnerowicz -;; Keywords: literate programming, reproducible research -;; Homepage: http://orgmode.org - -;; This file is part of GNU Emacs. - -;; GNU Emacs is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: -;; Currently only supports the external execution. No session support yet. -;; :results output -- runs in scripting mode -;; :results output repl -- runs in repl mode - -;;; Requirements: -;; - Io language :: http://iolanguage.org/ -;; - Io major mode :: Can be installed from Io sources -;; https://github.com/stevedekorte/io/blob/master/extras/SyntaxHighlighters/Emacs/io-mode.el - -;;; Code: -(require 'ob) -(require 'ob-ref) -(require 'ob-comint) -(require 'ob-eval) -(eval-when-compile (require 'cl)) - -(add-to-list 'org-babel-tangle-lang-exts '("io" . "io")) -(defvar org-babel-default-header-args:io '()) -(defvar org-babel-io-command "io" - "Name of the command to use for executing Io code.") - - -(defun org-babel-execute:io (body params) - "Execute a block of Io code with org-babel. This function is -called by `org-babel-execute-src-block'" - (message "executing Io source code block") - (let* ((processed-params (org-babel-process-params params)) - (session (org-babel-io-initiate-session (nth 0 processed-params))) - (vars (nth 1 processed-params)) - (result-params (nth 2 processed-params)) - (result-type (cdr (assoc :result-type params))) - (full-body (org-babel-expand-body:generic - body params)) - (result (org-babel-io-evaluate - session full-body result-type result-params))) - - (org-babel-reassemble-table - result - (org-babel-pick-name - (cdr (assoc :colname-names params)) (cdr (assoc :colnames params))) - (org-babel-pick-name - (cdr (assoc :rowname-names params)) (cdr (assoc :rownames params)))))) - - -(defun org-babel-io-table-or-string (results) - "Convert RESULTS into an appropriate elisp value. -If RESULTS look like a table, then convert them into an -Emacs-lisp table, otherwise return the results as a string." - (org-babel-script-escape results)) - - -(defvar org-babel-io-wrapper-method - "( -%s -) asString print -") - - -(defun org-babel-io-evaluate (session body &optional result-type result-params) - "Evaluate BODY in external Io process. -If RESULT-TYPE equals 'output then return standard output as a string. -If RESULT-TYPE equals 'value then return the value of the last statement -in BODY as elisp." - (when session (error "Sessions are not supported for Io. Yet.")) - (case result-type - (output - (if (member "repl" result-params) - (org-babel-eval org-babel-io-command body) - (let ((src-file (org-babel-temp-file "io-"))) - (progn (with-temp-file src-file (insert body)) - (org-babel-eval - (concat org-babel-io-command " " src-file) ""))))) - (value (let* ((src-file (org-babel-temp-file "io-")) - (wrapper (format org-babel-io-wrapper-method body))) - (with-temp-file src-file (insert wrapper)) - ((lambda (raw) - (if (member "code" result-params) - raw - (org-babel-io-table-or-string raw))) - (org-babel-eval - (concat org-babel-io-command " " src-file) "")))))) - - -(defun org-babel-prep-session:io (session params) - "Prepare SESSION according to the header arguments specified in PARAMS." - (error "Sessions are not supported for Io. Yet.")) - -(defun org-babel-io-initiate-session (&optional session) - "If there is not a current inferior-process-buffer in SESSION -then create. Return the initialized session. Sessions are not -supported in Io." - nil) - -(provide 'ob-io) - - - -;;; ob-io.el ends here diff --git a/lisp/ob-scala.el b/lisp/ob-scala.el deleted file mode 100644 index 8af4886..0000000 --- a/lisp/ob-scala.el +++ /dev/null @@ -1,120 +0,0 @@ -;;; ob-scala.el --- org-babel functions for Scala evaluation - -;; Copyright (C) 2012 Free Software Foundation, Inc. - -;; Author: Andrzej Lichnerowicz -;; Keywords: literate programming, reproducible research -;; Homepage: http://orgmode.org - -;; This file is part of GNU Emacs. - -;; GNU Emacs is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: -;; Currently only supports the external execution. No session support yet. - -;;; Requirements: -;; - Scala language :: http://www.scala-lang.org/ -;; - Scala major mode :: Can be installed from Scala sources -;; https://github.com/scala/scala-dist/blob/master/tool-support/src/emacs/scala-mode.el - -;;; Code: -(require 'ob) -(require 'ob-ref) -(require 'ob-comint) -(require 'ob-eval) -(eval-when-compile (require 'cl)) - -(add-to-list 'org-babel-tangle-lang-exts '("scala" . "scala")) -(defvar org-babel-default-header-args:scala '()) -(defvar org-babel-scala-command "scala" - "Name of the command to use for executing Scala code.") - - -(defun org-babel-execute:scala (body params) - "Execute a block of Scala code with org-babel. This function is -called by `org-babel-execute-src-block'" - (message "executing Scala source code block") - (let* ((processed-params (org-babel-process-params params)) - (session (org-babel-scala-initiate-session (nth 0 processed-params))) - (vars (nth 1 processed-params)) - (result-params (nth 2 processed-params)) - (result-type (cdr (assoc :result-type params))) - (full-body (org-babel-expand-body:generic - body params)) - (result (org-babel-scala-evaluate - session full-body result-type result-params))) - - (org-babel-reassemble-table - result - (org-babel-pick-name - (cdr (assoc :colname-names params)) (cdr (assoc :colnames params))) - (org-babel-pick-name - (cdr (assoc :rowname-names params)) (cdr (assoc :rownames params)))))) - - -(defun org-babel-scala-table-or-string (results) - "Convert RESULTS into an appropriate elisp value. -If RESULTS look like a table, then convert them into an -Emacs-lisp table, otherwise return the results as a string." - (org-babel-script-escape results)) - - -(defvar org-babel-scala-wrapper-method - "( -%s -) asString print -") - - -(defun org-babel-scala-evaluate - (session body &optional result-type result-params) - "Evaluate BODY in external Scala process. -If RESULT-TYPE equals 'output then return standard output as a string. -If RESULT-TYPE equals 'value then return the value of the last statement -in BODY as elisp." - (when session (error "Sessions are not supported for Scala. Yet.")) - (case result-type - (output - (let ((src-file (org-babel-temp-file "scala-"))) - (progn (with-temp-file src-file (insert body)) - (org-babel-eval - (concat org-babel-scala-command " " src-file) "")))) - (value - (let* ((src-file (org-babel-temp-file "scala-")) - (wrapper (format org-babel-scala-wrapper-method body))) - (with-temp-file src-file (insert wrapper)) - ((lambda (raw) - (if (member "code" result-params) - raw - (org-babel-scala-table-or-string raw))) - (org-babel-eval - (concat org-babel-scala-command " " src-file) "")))))) - - -(defun org-babel-prep-session:scala (session params) - "Prepare SESSION according to the header arguments specified in PARAMS." - (error "Sessions are not supported for Scala. Yet.")) - -(defun org-babel-scala-initiate-session (&optional session) - "If there is not a current inferior-process-buffer in SESSION -then create. Return the initialized session. Sessions are not -supported in Scala." - nil) - -(provide 'ob-scala) - - - -;;; ob-scala.el ends here diff --git a/testing/README b/testing/README deleted file mode 100644 index 4a68174..0000000 --- a/testing/README +++ /dev/null @@ -1,45 +0,0 @@ -# -*- mode:org -*- -#+Title: Org-mode Testing -#+Property: results silent - -* dependencies -The only dependency is [[http://www.emacswiki.org/emacs/ErtTestLibrary][ERT]] the Emacs testing library which ships with -Emacs24. If you are running an older version of Emacs and don't -already have ERT installed it can be installed from its old [[https://github.com/ohler/ert][git -repository]]. - -* non-interactive batch testing from the command line -The simplest way to run the Org-mode test suite is from the command -line with the following invocation. Note that the paths below are -relative to the base of the Org-mode directory. -#+BEGIN_SRC sh - emacs -Q --batch -l lisp/org.el -l testing/org-test.el \ - --eval "(progn (org-reload) (setq org-confirm-babel-evaluate nil))" \ - -f org-test-run-batch-tests -#+END_SRC - -The options in the above command are explained below. -| -Q | ignores any personal configuration ensuring a vanilla Emacs instance is used | -| --batch | runs Emacs in "batch" mode with no gui and termination after execution | -| -l | loads Org-mode and the org mode test suite defined in testing/org-test.el | -| --eval | reloads Org-mode and allows evaluation of code blocks by the tests | -| -f | actually runs the tests using the `org-test-run-batch-tests' function | - -* interactive testing from within Emacs -To run the Org-mode test suite from a current Emacs instance simply -load and run the test suite with the following commands. - -1) First load the test suite. - #+BEGIN_SRC emacs-lisp :var here=(buffer-file-name) - (add-to-list 'load-path (file-name-directory here)) - (require 'org-test) - #+END_SRC - -2) Then run the test suite. - #+BEGIN_SRC emacs-lisp - (org-test-run-all-tests) - #+END_SRC -* troubleshooting -- If the value of the =org-babel-no-eval-on-ctrl-c-ctrl-c= is non-nil - then it will result in some test failure, as there are tests which - rely on this behavior. diff --git a/testing/README.org b/testing/README.org new file mode 100644 index 0000000..faa0dd5 --- /dev/null +++ b/testing/README.org @@ -0,0 +1,115 @@ +#+Title: Org-mode Testing +#+Babel: results silent + +The following instructions describe how to get started using the +Org-mode test framework. + +* To run the tests interactively + :PROPERTIES: + :tangle: no + :END: +1) Install the jump.el testing dependency which is included as a git + submodule in the org-mode repository. To do so run the following + git submodule commands from inside the base of the Org-mode + directory (or just execute the following code block). + + #+begin_src sh + cd .. + git submodule init + git submodule update + #+end_src + +2) Load the [[file:org-test.el][org-test.el]] file + #+begin_src emacs-lisp + (load-file "org-test.el") + #+end_src + +3) The =org-test-jump= command is now bound to =M-C-j= in all + emacs-lisp files. Call this command from any file in the =lisp/= + directory of the org-mode repository to jump to the related test + file in the =testing/= directory. Call this functions with a + prefix argument, and the corresponding test file will be stubbed + out if it doesn't already exist. + +4) Ingest the library-of-babel.org file since some tests require this. + #+begin_src emacs-lisp + (org-babel-lob-ingest "../contrib/babel/library-of-babel.org") + #+end_src + +5) [[info:ert#Top][Review the ERT documentation]] + +6) A number of org-mode-specific functions and macros are provided in + =org-test.el= see the [[file:org-test.el::%3B%3B%3B%20Functions%20for%20writing%20tests][;;; Functions for Writing Tests]] subsection of + that file. Some of these functions make use of example org-mode + files located in the [[file:examples][examples/]] directory. + +7) Functions for loading and running the Org-mode tests are provided + in the [[file:org-test.el::%3B%3B%3B%20Load%20and%20Run%20tests][;;; Load and Run Tests]] subsection, the most important of + which are + - =org-test-load= which loads the entire Org-mode test suite + - =org-test-current-defun= which runs all tests for the current + function around point (should be called from inside of an + Org-mode elisp file) + - =org-test-run-all-tests= which runs the entire Org-mode test suite + - also note that the =ert= command can also be used to run tests + +8) Load and run all tests + #+begin_src emacs-lisp + (load-file "org-test.el") + (org-babel-lob-ingest "../contrib/babel/library-of-babel.org") + (org-test-load) + (org-test-run-all-tests) + #+end_src + +* To run the tests in batch mode +First tangle this file out to your desktop. +#+headers: :tangle ~/Desktop/run-org-tests.el +#+begin_src emacs-lisp :var org-dir=(expand-file-name ".." (file-name-directory (or load-file-name (buffer-file-name)))) + ;; add to the load path + (add-to-list 'load-path (concat org-dir "/lisp/")) + (add-to-list 'load-path (concat org-dir "/lisp/testing/")) + (add-to-list 'load-path (concat org-dir "/lisp/testing/ert/")) + + ;; load Org-mode + (require 'org) + + ;; setup the ID locations used in tests + (require 'org-id) + (org-id-update-id-locations + (list (concat org-dir "/testing/examples/babel.org") + (concat org-dir "/testing/examples/ob-C-test.org") + (concat org-dir "/testing/examples/normal.org") + (concat org-dir "/testing/examples/ob-awk-test.org") + (concat org-dir "/testing/examples/ob-octave.org") + (concat org-dir "/testing/examples/ob-fortran-test.org") + (concat org-dir "/testing/examples/ob-maxima-test.org") + (concat org-dir "/testing/examples/link-in-heading.org") + (concat org-dir "/testing/examples/links.org"))) + + ;; ensure that the latest Org-mode is loaded + (org-reload) + + ;; load the test suite + (load-file (concat org-dir "/testing/org-test.el")) + + ;; configure Babel + (org-babel-lob-ingest (concat org-dir "/contrib/babel/library-of-babel.org")) + (org-babel-do-load-languages + 'org-babel-load-languages + '((emacs-lisp . t) + (sh . t))) + (setq org-confirm-babel-evaluate nil) + + ;; run the test suite + (org-test-run-all-tests) + + ;; print the results + (with-current-buffer "*ert*" + (print (buffer-string))) +#+end_src + +Then run the test suite with the following command which could use any +version of Emacs. +#+begin_src sh :results output silent + emacs --batch -Q -l ~/Desktop/run-org-tests.el +#+end_src diff --git a/testing/contrib/lisp/.gitignore b/testing/contrib/lisp/.gitignore new file mode 100644 index 0000000..6e7ef91 --- /dev/null +++ b/testing/contrib/lisp/.gitignore @@ -0,0 +1 @@ +# this file ensures that the testing/contrib/lisp directory is created by git \ No newline at end of file diff --git a/testing/examples/include.org b/testing/examples/include.org deleted file mode 100644 index 186facb..0000000 --- a/testing/examples/include.org +++ /dev/null @@ -1,10 +0,0 @@ -Small Org file with an include keyword. - -#+BEGIN_SRC emacs-lisp :exports results -(+ 2 1) -#+END_SRC - -#+INCLUDE: "include2.org" - -* Heading -body diff --git a/testing/examples/include2.org b/testing/examples/include2.org deleted file mode 100644 index f985b46..0000000 --- a/testing/examples/include2.org +++ /dev/null @@ -1 +0,0 @@ -Success! diff --git a/testing/examples/table.org b/testing/examples/table.org new file mode 100644 index 0000000..3c6caed --- /dev/null +++ b/testing/examples/table.org @@ -0,0 +1,19 @@ +#+TITLE: example file with tables +#+OPTIONS: num:nil ^:nil + +This is an example file for use by the Org-mode tests defined in +file:../lisp/test-org-table.el. + +* simple formula + :PROPERTIES: + :ID: 563523f7-3f3e-49c9-9622-9216cc9a5d95 + :END: + +#+tblname: simple-formula +| 1 | +| 2 | +| 3 | +| 4 | +|----| +| 10 | + #+TBLFM: $1=vsum(@1..@-1) diff --git a/testing/lisp/test-org-element.el b/testing/lisp/test-org-element.el deleted file mode 100644 index db46f81..0000000 --- a/testing/lisp/test-org-element.el +++ /dev/null @@ -1,436 +0,0 @@ -;;; test-org-element.el --- Tests for org-element.el - -;; Copyright (C) 2012 Nicolas Goaziou - -;; Author: Nicolas Goaziou - -;; This program is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see . - -;;; Commentary: - -;;; Code: - -(unless (featurep 'org-element) - (signal 'missing-test-dependency "org-element")) - - - -;;; Tests: - - - -;;;; Headlines - -(ert-deftest test-org-element/headline-quote-keyword () - "Test QUOTE keyword recognition." - ;; Reference test. - (org-test-with-temp-text "* Headline" - (let ((org-quote-string "QUOTE")) - (should-not (org-element-property :quotedp (org-element-at-point))))) - ;; Standard position. - (org-test-with-temp-text "* QUOTE Headline" - (let ((org-quote-string "QUOTE")) - (let ((headline (org-element-at-point))) - (should (org-element-property :quotedp headline)) - ;; Test removal from raw value. - (should (equal (org-element-property :raw-value headline) "Headline")))) - ;; Case sensitivity. - (let ((org-quote-string "Quote")) - (should-not (org-element-property :quotedp (org-element-at-point))))) - ;; With another keyword. - (org-test-with-temp-text "* TODO QUOTE Headline" - (let ((org-quote-string "QUOTE") - (org-todo-keywords '((sequence "TODO" "DONE")))) - (should (org-element-property :quotedp (org-element-at-point)))))) - -(ert-deftest test-org-element/headline-comment-keyword () - "Test COMMENT keyword recognition." - ;; Reference test. - (org-test-with-temp-text "* Headline" - (let ((org-comment-string "COMMENT")) - (should-not (org-element-property :commentedp (org-element-at-point))))) - ;; Standard position. - (org-test-with-temp-text "* COMMENT Headline" - (let ((org-comment-string "COMMENT")) - (let ((headline (org-element-at-point))) - (should (org-element-property :commentedp headline)) - ;; Test removal from raw value. - (should (equal (org-element-property :raw-value headline) "Headline")))) - ;; Case sensitivity. - (let ((org-comment-string "Comment")) - (should-not (org-element-property :commentedp (org-element-at-point))))) - ;; With another keyword. - (org-test-with-temp-text "* TODO COMMENT Headline" - (let ((org-comment-string "COMMENT") - (org-todo-keywords '((sequence "TODO" "DONE")))) - (should (org-element-property :commentedp (org-element-at-point)))))) - -(ert-deftest test-org-element/headline-archive-tag () - "Test ARCHIVE tag recognition." - ;; Reference test. - (org-test-with-temp-text "* Headline" - (let ((org-archive-tag "ARCHIVE")) - (should-not (org-element-property :archivedp (org-element-at-point))))) - ;; Single tag. - (org-test-with-temp-text "* Headline :ARCHIVE:" - (let ((org-archive-tag "ARCHIVE")) - (let ((headline (org-element-at-point))) - (should (org-element-property :archivedp headline)) - ;; Test tag removal. - (should-not (org-element-property :tags headline)))) - (let ((org-archive-tag "Archive")) - (should-not (org-element-property :archivedp (org-element-at-point))))) - ;; Multiple tags. - (org-test-with-temp-text "* Headline :test:ARCHIVE:" - (let ((org-archive-tag "ARCHIVE")) - (let ((headline (org-element-at-point))) - (should (org-element-property :archivedp headline)) - ;; Test tag removal. - (should (equal (org-element-property :tags headline) ":test:")))))) - - - -;;;; Example-blocks and Src-blocks - -(ert-deftest test-org-element/block-switches () - "Test `example-block' and `src-block' switches parsing." - (let ((org-coderef-label-format "(ref:%s)")) - ;; 1. Test "-i" switch. - (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp\n(+ 1 1)\n#+END_SRC" - (let ((element (org-element-current-element))) - (should-not (org-element-property :preserve-indent element)))) - (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp -i\n(+ 1 1)\n#+END_SRC" - (let ((element (org-element-current-element))) - (should (org-element-property :preserve-indent element)))) - (org-test-with-temp-text "#+BEGIN_EXAMPLE\nText.\n#+END_EXAMPLE" - (let ((element (org-element-current-element))) - (should-not (org-element-property :preserve-indent element)))) - (org-test-with-temp-text "#+BEGIN_EXAMPLE -i\nText.\n#+END_EXAMPLE" - (let ((element (org-element-current-element))) - (should (org-element-property :preserve-indent element)))) - ;; 2. "-n -r -k" combination should number lines, retain labels but - ;; not use them in coderefs. - (org-test-with-temp-text "#+BEGIN_EXAMPLE -n -r -k\nText.\N#+END_EXAMPLE" - (let ((element (org-element-current-element))) - (should (and (org-element-property :number-lines element) - (org-element-property :retain-labels element) - (not (org-element-property :use-labels element)))))) - (org-test-with-temp-text - "#+BEGIN_SRC emacs-lisp -n -r -k\n(+ 1 1)\n#+END_SRC" - (let ((element (org-element-current-element))) - (should (and (org-element-property :number-lines element) - (org-element-property :retain-labels element) - (not (org-element-property :use-labels element)))))) - ;; 3. "-n -r" combination should number-lines remove labels and not - ;; use them in coderefs. - (org-test-with-temp-text "#+BEGIN_EXAMPLE -n -r\nText.\n#+END_EXAMPLE" - (let ((element (org-element-current-element))) - (should (and (org-element-property :number-lines element) - (not (org-element-property :retain-labels element)) - (not (org-element-property :use-labels element)))))) - (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp -n -r\n(+ 1 1)\n#+END_SRC" - (let ((element (org-element-current-element))) - (should (and (org-element-property :number-lines element) - (not (org-element-property :retain-labels element)) - (not (org-element-property :use-labels element)))))) - ;; 4. "-n" or "+n" should number lines, retain labels and use them - ;; in coderefs. - (org-test-with-temp-text "#+BEGIN_EXAMPLE -n\nText.\n#+END_EXAMPLE" - (let ((element (org-element-current-element))) - (should (and (org-element-property :number-lines element) - (org-element-property :retain-labels element) - (org-element-property :use-labels element))))) - (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp -n\n(+ 1 1)\n#+END_SRC" - (let ((element (org-element-current-element))) - (should (and (org-element-property :number-lines element) - (org-element-property :retain-labels element) - (org-element-property :use-labels element))))) - (org-test-with-temp-text "#+BEGIN_EXAMPLE +n\nText.\n#+END_EXAMPLE" - (let ((element (org-element-current-element))) - (should (and (org-element-property :number-lines element) - (org-element-property :retain-labels element) - (org-element-property :use-labels element))))) - (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp +n\n(+ 1 1)\n#+END_SRC" - (let ((element (org-element-current-element))) - (should (and (org-element-property :number-lines element) - (org-element-property :retain-labels element) - (org-element-property :use-labels element))))) - ;; 5. No switch should not number lines, but retain labels and use - ;; them in coderefs. - (org-test-with-temp-text "#+BEGIN_EXAMPLE\nText.\n#+END_EXAMPLE" - (let ((element (org-element-current-element))) - (should (and (not (org-element-property :number-lines element)) - (org-element-property :retain-labels element) - (org-element-property :use-labels element))))) - (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp\n(+ 1 1)\n#+END_SRC" - (let ((element (org-element-current-element))) - (should (and (not (org-element-property :number-lines element)) - (org-element-property :retain-labels element) - (org-element-property :use-labels element))))) - ;; 6. "-r" switch only: do not number lines, remove labels, and - ;; don't use labels in coderefs. - (org-test-with-temp-text "#+BEGIN_EXAMPLE -r\nText.\n#+END_EXAMPLE" - (let ((element (org-element-current-element))) - (should (and (not (org-element-property :number-lines element)) - (not (org-element-property :retain-labels element)) - (not (org-element-property :use-labels element)))))) - (org-test-with-temp-text "#+BEGIN_SRC emacs-lisp -r\n(+ 1 1)\n#+END_SRC" - (let ((element (org-element-current-element))) - (should (and (not (org-element-property :number-lines element)) - (not (org-element-property :retain-labels element)) - (not (org-element-property :use-labels element)))))) - ;; 7. Recognize coderefs with user-defined syntax. - (org-test-with-temp-text - "#+BEGIN_EXAMPLE -l \"[ref:%s]\"\nText [ref:text]\n#+END_EXAMPLE" - (let ((element (org-element-current-element))) - (should - (equal (org-element-property :label-fmt element) "[ref:%s]")))) - (org-test-with-temp-text - "#+BEGIN_SRC emacs-lisp -l \"[ref:%s]\"\n(+ 1 1) [ref:text]\n#+END_SRC" - (let ((element (org-element-current-element))) - (should - (equal (org-element-property :label-fmt element) "[ref:%s]")))))) - - - -;;; Navigation tools. - -(ert-deftest test-org-element/forward-element () - "Test `org-element-forward' specifications." - ;; 1. At EOB: should error. - (org-test-with-temp-text "Some text\n" - (goto-char (point-max)) - (should-error (org-element-forward))) - ;; 2. Standard move: expected to ignore blank lines. - (org-test-with-temp-text "First paragraph.\n\n\nSecond paragraph." - (org-element-forward) - (should (looking-at "Second paragraph."))) - ;; 3. Headline tests. - (org-test-with-temp-text " -* Head 1 -** Head 1.1 -*** Head 1.1.1 -** Head 1.2" - ;; 3.1. At an headline beginning: move to next headline at the - ;; same level. - (goto-line 3) - (org-element-forward) - (should (looking-at "** Head 1.2")) - ;; 3.2. At an headline beginning: move to parent headline if no - ;; headline at the same level. - (goto-line 3) - (org-element-forward) - (should (looking-at "** Head 1.2"))) - ;; 4. Greater element tests. - (org-test-with-temp-text - "#+BEGIN_CENTER\nInside.\n#+END_CENTER\n\nOutside." - ;; 4.1. At a greater element: expected to skip contents. - (org-element-forward) - (should (looking-at "Outside.")) - ;; 4.2. At the end of greater element contents: expected to skip - ;; to the end of the greater element. - (goto-line 2) - (org-element-forward) - (should (looking-at "Outside."))) - ;; 5. List tests. - (org-test-with-temp-text " -- item1 - - - sub1 - - - sub2 - - - sub3 - - Inner paragraph. - -- item2 - -Outside." - ;; 5.1. At list top point: expected to move to the element after - ;; the list. - (goto-line 2) - (org-element-forward) - (should (looking-at "Outside.")) - ;; 5.2. Special case: at the first line of a sub-list, but not at - ;; beginning of line, move to next item. - (goto-line 2) - (forward-char) - (org-element-forward) - (should (looking-at "- item2")) - (goto-line 4) - (forward-char) - (org-element-forward) - (should (looking-at " - sub2")) - ;; 5.3 At sub-list beginning: expected to move after the sub-list. - (goto-line 4) - (org-element-forward) - (should (looking-at " Inner paragraph.")) - ;; 5.4. At sub-list end: expected to move outside the sub-list. - (goto-line 8) - (org-element-forward) - (should (looking-at " Inner paragraph.")) - ;; 5.5. At an item: expected to move to next item, if any. - (goto-line 6) - (org-element-forward) - (should (looking-at " - sub3")))) - -(ert-deftest test-org-element/backward-element () - "Test `org-element-backward' specifications." - ;; 1. At BOB (modulo some white spaces): should error. - (org-test-with-temp-text " \nParagraph." - (org-skip-whitespace) - (should-error (org-element-backward))) - ;; 2. Not at the beginning of an element: move at its beginning. - (org-test-with-temp-text "Paragraph1.\n\nParagraph2." - (goto-line 3) - (end-of-line) - (org-element-backward) - (should (looking-at "Paragraph2."))) - ;; 3. Headline tests. - (org-test-with-temp-text " -* Head 1 -** Head 1.1 -*** Head 1.1.1 -** Head 1.2" - ;; 3.1. At an headline beginning: move to previous headline at the - ;; same level. - (goto-line 5) - (org-element-backward) - (should (looking-at "** Head 1.1")) - ;; 3.2. At an headline beginning: move to parent headline if no - ;; headline at the same level. - (goto-line 3) - (org-element-backward) - (should (looking-at "* Head 1")) - ;; 3.3. At the first top-level headline: should error. - (goto-line 2) - (should-error (org-element-backward))) - ;; 4. At beginning of first element inside a greater element: - ;; expected to move to greater element's beginning. - (org-test-with-temp-text "Before.\n#+BEGIN_CENTER\nInside.\n#+END_CENTER." - (goto-line 3) - (org-element-backward) - (should (looking-at "#\\+BEGIN_CENTER"))) - ;; 5. List tests. - (org-test-with-temp-text " -- item1 - - - sub1 - - - sub2 - - - sub3 - - Inner paragraph. - -- item2 - - -Outside." - ;; 5.1. At beginning of sub-list: expected to move to the - ;; paragraph before it. - (goto-line 4) - (org-element-backward) - (should (looking-at "item1")) - ;; 5.2. At an item in a list: expected to move at previous item. - (goto-line 8) - (org-element-backward) - (should (looking-at " - sub2")) - (goto-line 12) - (org-element-backward) - (should (looking-at "- item1")) - ;; 5.3. At end of list/sub-list: expected to move to list/sub-list - ;; beginning. - (goto-line 10) - (org-element-backward) - (should (looking-at " - sub1")) - (goto-line 15) - (org-element-backward) - (should (looking-at "- item1")) - ;; 5.4. At blank-lines before list end: expected to move to top - ;; item. - (goto-line 14) - (org-element-backward) - (should (looking-at "- item1")))) - -(ert-deftest test-org-element/up-element () - "Test `org-element-up' specifications." - ;; 1. At BOB or with no surrounding element: should error. - (org-test-with-temp-text "Paragraph." - (should-error (org-element-up))) - (org-test-with-temp-text "* Head1\n* Head2" - (goto-line 2) - (should-error (org-element-up))) - (org-test-with-temp-text "Paragraph1.\n\nParagraph2." - (goto-line 3) - (should-error (org-element-up))) - ;; 2. At an headline: move to parent headline. - (org-test-with-temp-text "* Head1\n** Sub-Head1\n** Sub-Head2" - (goto-line 3) - (org-element-up) - (should (looking-at "\\* Head1"))) - ;; 3. Inside a greater element: move to greater element beginning. - (org-test-with-temp-text - "Before.\n#+BEGIN_CENTER\nParagraph1\nParagraph2\n#+END_CENTER\n" - (goto-line 3) - (org-element-up) - (should (looking-at "#\\+BEGIN_CENTER"))) - ;; 4. List tests. - (org-test-with-temp-text "* Top -- item1 - - - sub1 - - - sub2 - - Paragraph within sub2. - -- item2" - ;; 4.1. Within an item: move to the item beginning. - (goto-line 8) - (org-element-up) - (should (looking-at " - sub2")) - ;; 4.2. At an item in a sub-list: move to parent item. - (goto-line 4) - (org-element-up) - (should (looking-at "- item1")) - ;; 4.3. At an item in top list: move to beginning of whole list. - (goto-line 10) - (org-element-up) - (should (looking-at "- item1")) - ;; 4.4. Special case. At very top point: should move to parent of - ;; list. - (goto-line 2) - (org-element-up) - (should (looking-at "\\* Top")))) - -(ert-deftest test-org-element/down-element () - "Test `org-element-down' specifications." - ;; 1. Error when the element hasn't got a recursive type. - (org-test-with-temp-text "Paragraph." - (should-error (org-element-down))) - ;; 2. When at a plain-list, move to first item. - (org-test-with-temp-text "- Item 1\n - Item 1.1\n - Item 2.2" - (goto-line 2) - (org-element-down) - (should (looking-at " - Item 1.1"))) - ;; 3. Otherwise, move inside the greater element. - (org-test-with-temp-text "#+BEGIN_CENTER\nParagraph.\n#+END_CENTER" - (org-element-down) - (should (looking-at "Paragraph")))) - - -(provide 'test-org-element) -;;; test-org-element.el ends here diff --git a/testing/lisp/test-org-export.el b/testing/lisp/test-org-export.el deleted file mode 100644 index f34cc7b..0000000 --- a/testing/lisp/test-org-export.el +++ /dev/null @@ -1,625 +0,0 @@ -;;; test-org-export.el --- Tests for org-export.el - -;; Copyright (C) 2012 Nicolas Goaziou - -;; Author: Nicolas Goaziou - -;; Released under the GNU General Public License version 3 -;; see: http://www.gnu.org/licenses/gpl-3.0.html - -;;;; Comments - - - -;;; Code: - -(unless (featurep 'org-export) - (signal 'missing-test-dependency "org-export")) - - - -;;; Tests - -(defmacro org-test-with-backend (backend &rest body) - "Execute body with an export back-end defined. - -BACKEND is the name, as a string, of the back-end. BODY is the -body to execute. The defined back-end simply returns parsed data -as Org syntax." - (declare (debug (form body)) (indent 1)) - `(flet ,(let (transcoders) - (dolist (type (append org-element-all-elements - org-element-all-objects) - transcoders) - (push `(,(intern (format "org-%s-%s" backend type)) - (obj contents info) - (,(intern (format "org-element-%s-interpreter" type)) - obj contents)) - transcoders))) - ,@body)) - -(ert-deftest test-org-export/parse-option-keyword () - "Test reading all standard #+OPTIONS: items." - (should - (equal - (org-export-parse-option-keyword - "H:1 num:t \\n:t timestamp:t arch:t author:t creator:t d:t email:t - *:t e:t ::t f:t pri:t -:t ^:t toc:t |:t tags:t tasks:t <:t todo:t") - '(:headline-levels - 1 :preserve-breaks t :section-numbers t :time-stamp-file t - :with-archived-trees t :with-author t :with-creator t :with-drawers t - :with-email t :with-emphasize t :with-entities t :with-fixed-width t - :with-footnotes t :with-priority t :with-special-strings t - :with-sub-superscript t :with-toc t :with-tables t :with-tags t - :with-tasks t :with-timestamps t :with-todo-keywords t))) - ;; Test some special values. - (should - (equal - (org-export-parse-option-keyword - "arch:headline creator:comment d:(\"TEST\") - ^:{} toc:1 tags:not-in-toc tasks:todo num:2") - '( :section-numbers - 2 - :with-archived-trees headline :with-creator comment - :with-drawers ("TEST") :with-sub-superscript {} :with-toc 1 - :with-tags not-in-toc :with-tasks todo)))) - -(ert-deftest test-org-export/get-inbuffer-options () - "Test reading all standard export keywords." - (should - (equal - (org-test-with-temp-text "#+AUTHOR: Me, Myself and I -#+CREATOR: Idem -#+DATE: Today -#+DESCRIPTION: Testing -#+DESCRIPTION: with two lines -#+EMAIL: some@email.org -#+EXPORT_EXCLUDE_TAGS: noexport invisible -#+KEYWORDS: test -#+LANGUAGE: en -#+EXPORT_SELECT_TAGS: export -#+TITLE: Some title -#+TITLE: with spaces" - (org-export-get-inbuffer-options)) - '(:author - "Me, Myself and I" :creator "Idem" :date "Today" - :description "Testing\nwith two lines" :email "some@email.org" - :exclude-tags ("noexport" "invisible") :keywords "test" :language "en" - :select-tags ("export") :title "Some title with spaces")))) - -(ert-deftest test-org-export/define-macro () - "Try defining various Org macro using in-buffer #+MACRO: keyword." - ;; Parsed macro. - (should (equal (org-test-with-temp-text "#+MACRO: one 1" - (org-export-get-inbuffer-options)) - '(:macro-one ("1")))) - ;; Evaled macro. - (should (equal (org-test-with-temp-text "#+MACRO: two (eval (+ 1 1))" - (org-export-get-inbuffer-options)) - '(:macro-two "(eval (+ 1 1))"))) - ;; Incomplete macro. - (should-not (org-test-with-temp-text "#+MACRO: three" - (org-export-get-inbuffer-options))) - ;; Macro with newline character. - (should (equal (org-test-with-temp-text "#+MACRO: four a\\nb" - (org-export-get-inbuffer-options)) - '(:macro-four ("a\nb")))) - ;; Macro with protected newline character. - (should (equal (org-test-with-temp-text "#+MACRO: five a\\\\nb" - (org-export-get-inbuffer-options)) - '(:macro-five ("a\\nb")))) - ;; Recursive macro. - (org-test-with-temp-text "#+MACRO: six 6\n#+MACRO: seven 1 + {{{six}}}" - (should - (equal - (org-export-get-inbuffer-options) - '(:macro-six - ("6") - :macro-seven - ("1 + " (macro (:key "six" :value "{{{six}}}" :args nil :begin 5 :end 14 - :post-blank 0)))))))) - -(ert-deftest test-org-export/handle-options () - "Test if export options have an impact on output." - ;; Test exclude tags. - (org-test-with-temp-text "* Head1 :noexport:" - (org-test-with-backend "test" - (should - (equal (org-export-as 'test nil nil nil '(:exclude-tags ("noexport"))) - "")))) - ;; Test include tags. - (org-test-with-temp-text " -* Head1 -** Sub-Head1.1 :export: -*** Sub-Head1.1.1 -* Head2" - (org-test-with-backend "test" - (should - (string-match - "\\* Head1\n\\*\\* Sub-Head1.1[ \t]+:export:\n\\*\\*\\* Sub-Head1.1.1\n" - (org-export-as 'test nil nil nil '(:select-tags ("export"))))))) - ;; Test mixing include tags and exclude tags. - (org-test-with-temp-text " -* Head1 :export: -** Sub-Head1 :noexport: -** Sub-Head2 -* Head2 :noexport: -** Sub-Head1 :export:" - (org-test-with-backend "test" - (should - (string-match - "\\* Head1[ \t]+:export:\n\\*\\* Sub-Head2\n" - (org-export-as - 'test nil nil nil - '(:select-tags ("export") :exclude-tags ("noexport"))))))) - ;; Ignore tasks. - (let ((org-todo-keywords '((sequence "TODO" "DONE")))) - (org-test-with-temp-text "* TODO Head1" - (org-test-with-backend "test" - (should (equal (org-export-as 'test nil nil nil '(:with-tasks nil)) - ""))))) - (let ((org-todo-keywords '((sequence "TODO" "DONE")))) - (org-test-with-temp-text "* TODO Head1" - (org-test-with-backend "test" - (should (equal (org-export-as 'test nil nil nil '(:with-tasks t)) - "* TODO Head1\n"))))) - ;; Archived tree. - (org-test-with-temp-text "* Head1 :archive:" - (let ((org-archive-tag "archive")) - (org-test-with-backend "test" - (should - (equal (org-export-as 'test nil nil nil '(:with-archived-trees nil)) - ""))))) - (org-test-with-temp-text "* Head1 :archive:\nbody\n** Sub-head 2" - (let ((org-archive-tag "archive")) - (org-test-with-backend "test" - (should - (string-match - "\\* Head1[ \t]+:archive:" - (org-export-as 'test nil nil nil - '(:with-archived-trees headline))))))) - (org-test-with-temp-text "* Head1 :archive:" - (let ((org-archive-tag "archive")) - (org-test-with-backend "test" - (should - (string-match - "\\`\\* Head1[ \t]+:archive:\n\\'" - (org-export-as 'test nil nil nil '(:with-archived-trees t))))))) - ;; Drawers. - (let ((org-drawers '("TEST"))) - (org-test-with-temp-text ":TEST:\ncontents\n:END:" - (org-test-with-backend "test" - (should (equal (org-export-as 'test nil nil nil '(:with-drawers nil)) - ""))))) - (let ((org-drawers '("TEST"))) - (org-test-with-temp-text ":TEST:\ncontents\n:END:" - (org-test-with-backend "test" - (should (equal (org-export-as 'test nil nil nil '(:with-drawers t)) - ":TEST:\ncontents\n:END:\n")))))) - -(ert-deftest test-org-export/comment-tree () - "Test if export process ignores commented trees." - (let ((org-comment-string "COMMENT")) - (org-test-with-temp-text "* COMMENT Head1" - (org-test-with-backend "test" - (should (equal (org-export-as 'test) "")))))) - -(ert-deftest test-org-export/export-scope () - "Test all export scopes." - (org-test-with-temp-text " -* Head1 -** Head2 -text -*** Head3" - (org-test-with-backend "test" - ;; Subtree. - (forward-line 3) - (should (equal (org-export-as 'test 'subtree) "text\n*** Head3\n")) - ;; Visible. - (goto-char (point-min)) - (forward-line) - (org-cycle) - (should (equal (org-export-as 'test nil 'visible) "* Head1\n")) - ;; Body only. - (flet ((org-test-template (body info) (format "BEGIN\n%sEND" body))) - (should (equal (org-export-as 'test nil nil 'body-only) - "* Head1\n** Head2\ntext\n*** Head3\n")) - (should (equal (org-export-as 'test) - "BEGIN\n* Head1\n** Head2\ntext\n*** Head3\nEND"))) - ;; Region. - (goto-char (point-min)) - (forward-line 3) - (transient-mark-mode 1) - (push-mark (point) t t) - (goto-char (point-at-eol)) - (should (equal (org-export-as 'test) "text\n"))))) - -(ert-deftest test-org-export/export-snippet () - "Test export snippets transcoding." - (org-test-with-temp-text "@test{A}@t{B}" - (org-test-with-backend "test" - (flet ((org-test-export-snippet - (snippet contents info) - (when (eq (org-export-snippet-backend snippet) 'test) - (org-element-property :value snippet)))) - (let ((org-export-snippet-translation-alist nil)) - (should (equal (org-export-as 'test) "A\n"))) - (let ((org-export-snippet-translation-alist '(("t" . "test")))) - (should (equal (org-export-as 'test) "AB\n"))))))) - -(ert-deftest test-org-export/expand-include () - "Test file inclusion in an Org buffer." - ;; Full insertion with recursive inclusion. - (org-test-with-temp-text - (format "#+INCLUDE: \"%s/examples/include.org\"" org-test-dir) - (org-export-expand-include-keyword) - (should (equal (buffer-string) - "Small Org file with an include keyword. - -#+BEGIN_SRC emacs-lisp :exports results\n(+ 2 1)\n#+END_SRC - -Success! - -* Heading -body\n"))) - ;; Localized insertion. - (org-test-with-temp-text - (format "#+INCLUDE: \"%s/examples/include.org\" :lines \"1-2\"" - org-test-dir) - (org-export-expand-include-keyword) - (should (equal (buffer-string) - "Small Org file with an include keyword.\n"))) - ;; Insertion with constraints on headlines level. - (org-test-with-temp-text - (format - "* Top heading\n#+INCLUDE: \"%s/examples/include.org\" :lines \"9-\"" - org-test-dir) - (org-export-expand-include-keyword) - (should (equal (buffer-string) "* Top heading\n** Heading\nbody\n"))) - ;; Inclusion within an example block. - (org-test-with-temp-text - (format "#+INCLUDE: \"%s/examples/include.org\" :lines \"1-2\" example" - org-test-dir) - (org-export-expand-include-keyword) - (should - (equal - (buffer-string) - "#+BEGIN_EXAMPLE\nSmall Org file with an include keyword.\n#+END_EXAMPLE\n"))) - ;; Inclusion within a src-block. - (org-test-with-temp-text - (format - "#+INCLUDE: \"%s/examples/include.org\" :lines \"4-5\" src emacs-lisp" - org-test-dir) - (org-export-expand-include-keyword) - (should (equal (buffer-string) - "#+BEGIN_SRC emacs-lisp\n(+ 2 1)\n#+END_SRC\n")))) - -(ert-deftest test-org-export/user-ignore-list () - "Test if `:ignore-list' accepts user input." - (org-test-with-backend "test" - (flet ((skip-note-head - (data backend info) - ;; Ignore headlines with the word "note" in their title. - (org-element-map - data 'headline - (lambda (headline) - (when (string-match "\\" - (org-element-property :raw-value headline)) - (org-export-ignore-element headline info))) - info) - data)) - ;; Install function in parse tree filters. - (let ((org-export-filter-parse-tree-functions '(skip-note-head))) - (org-test-with-temp-text "* Head1\n* Head2 (note)\n" - (should (equal (org-export-as 'test) "* Head1\n"))))))) - - - -;; Footnotes - -(ert-deftest test-org-export/footnotes () - "Test footnotes specifications." - (let ((org-footnote-section nil)) - ;; 1. Read every type of footnote. - (org-test-with-temp-text - "Text[fn:1] [1] [fn:label:C] [fn::D]\n\n[fn:1] A\n\n[1] B" - (let* ((tree (org-element-parse-buffer)) - (info (org-combine-plists - (org-export-initial-options) '(:with-footnotes t)))) - (setq info (org-combine-plists - info (org-export-collect-tree-properties tree info 'test))) - (should - (equal - '((1 . "A") (2 . "B") (3 . "C") (4 . "D")) - (org-element-map - tree 'footnote-reference - (lambda (ref) - (let ((def (org-export-get-footnote-definition ref info))) - (cons (org-export-get-footnote-number ref info) - (if (eq (org-element-property :type ref) 'inline) (car def) - (car (org-element-contents - (car (org-element-contents def)))))))) - info))))) - ;; 2. Test nested footnotes order. - (org-test-with-temp-text - "Text[fn:1:A[fn:2]] [fn:3].\n\n[fn:2] B [fn:3] [fn::D].\n\n[fn:3] C." - (let* ((tree (org-element-parse-buffer)) - (info (org-combine-plists - (org-export-initial-options) '(:with-footnotes t)))) - (setq info (org-combine-plists - info (org-export-collect-tree-properties tree info 'test))) - (should - (equal - '((1 . "fn:1") (2 . "fn:2") (3 . "fn:3") (4)) - (org-element-map - tree 'footnote-reference - (lambda (ref) - (when (org-export-footnote-first-reference-p ref info) - (cons (org-export-get-footnote-number ref info) - (org-element-property :label ref)))) - info))))) - ;; 3. Test nested footnote in invisible definitions. - (org-test-with-temp-text "Text[1]\n\n[1] B [2]\n\n[2] C." - ;; Hide definitions. - (narrow-to-region (point) (point-at-eol)) - (let* ((tree (org-element-parse-buffer)) - (info (org-combine-plists - (org-export-initial-options) '(:with-footnotes t)))) - (setq info (org-combine-plists - info (org-export-collect-tree-properties tree info 'test))) - ;; Both footnotes should be seen. - (should - (= (length (org-export-collect-footnote-definitions tree info)) 2)))) - ;; 4. Test footnotes definitions collection. - (org-test-with-temp-text "Text[fn:1:A[fn:2]] [fn:3]. - -\[fn:2] B [fn:3] [fn::D]. - -\[fn:3] C." - (let ((tree (org-element-parse-buffer)) - (info (org-combine-plists - (org-export-initial-options) '(:with-footnotes t)))) - (setq info (org-combine-plists - info (org-export-collect-tree-properties tree info 'test))) - (should (= (length (org-export-collect-footnote-definitions tree info)) - 4)))))) - - - -;;; Links - -(ert-deftest test-org-export/fuzzy-links () - "Test fuzz link export specifications." - ;; 1. Links to invisible (keyword) targets should be ignored. - (org-test-with-temp-text - "Paragraph.\n#+TARGET: Test\n[[Test]]" - (let* ((tree (org-element-parse-buffer)) - (info (org-combine-plists (org-export-initial-options)))) - (setq info (org-combine-plists - info (org-export-collect-tree-properties tree info 'test))) - (should-not - (org-element-map - tree 'link - (lambda (link) - (org-export-get-ordinal - (org-export-resolve-fuzzy-link link info) info)) info)))) - ;; 2. Link to an headline should return headline's number. - (org-test-with-temp-text - "Paragraph.\n* Head1\n* Head2\n* Head3\n[[Head2]]" - (let* ((tree (org-element-parse-buffer)) - (info (org-combine-plists (org-export-initial-options)))) - (setq info (org-combine-plists - info (org-export-collect-tree-properties tree info 'test))) - (should - ;; Note: Headline's number is in fact a list of numbers. - (equal '(2) - (org-element-map - tree 'link - (lambda (link) - (org-export-get-ordinal - (org-export-resolve-fuzzy-link link info) info)) info t))))) - ;; 3. Link to a target in an item should return item's number. - (org-test-with-temp-text - "- Item1\n - Item11\n - <>Item12\n- Item2\n\n\n[[test]]" - (let* ((tree (org-element-parse-buffer)) - (info (org-combine-plists (org-export-initial-options)))) - (setq info (org-combine-plists - info (org-export-collect-tree-properties tree info 'test))) - (should - ;; Note: Item's number is in fact a list of numbers. - (equal '(1 2) - (org-element-map - tree 'link - (lambda (link) - (org-export-get-ordinal - (org-export-resolve-fuzzy-link link info) info)) info t))))) - ;; 4. Link to a target in a footnote should return footnote's - ;; number. - (org-test-with-temp-text - "Paragraph[1][2][fn:lbl3:C<>][[test]][[target]]\n[1] A\n\n[2] <>B" - (let* ((tree (org-element-parse-buffer)) - (info (org-combine-plists (org-export-initial-options)))) - (setq info (org-combine-plists - info (org-export-collect-tree-properties tree info 'test))) - (should - (equal '(2 3) - (org-element-map - tree 'link - (lambda (link) - (org-export-get-ordinal - (org-export-resolve-fuzzy-link link info) info)) info))))) - ;; 5. Link to a named element should return sequence number of that - ;; element. - (org-test-with-temp-text - "#+NAME: tbl1\n|1|2|\n#+NAME: tbl2\n|3|4|\n#+NAME: tbl3\n|5|6|\n[[tbl2]]" - (let* ((tree (org-element-parse-buffer)) - (info (org-combine-plists (org-export-initial-options)))) - (setq info (org-combine-plists - info (org-export-collect-tree-properties tree info 'test))) - (should - (= 2 - (org-element-map - tree 'link - (lambda (link) - (org-export-get-ordinal - (org-export-resolve-fuzzy-link link info) info)) info t))))) - ;; 6. Link to a target not within an item, a table, a footnote - ;; reference or definition should return section number. - (org-test-with-temp-text - "* Head1\n* Head2\nParagraph<>\n* Head3\n[[target]]" - (let* ((tree (org-element-parse-buffer)) - (info (org-combine-plists (org-export-initial-options)))) - (setq info (org-combine-plists - info (org-export-collect-tree-properties tree info 'test))) - (should - (equal '(2) - (org-element-map - tree 'link - (lambda (link) - (org-export-get-ordinal - (org-export-resolve-fuzzy-link link info) info)) info t)))))) - -(defun test-org-export/resolve-coderef () - "Test `org-export-resolve-coderef' specifications." - (let ((org-coderef-label-format "(ref:%s)")) - ;; 1. A link to a "-n -k -r" block returns line number. - (org-test-with-temp-text - "#+BEGIN_EXAMPLE -n -k -r\nText (ref:coderef)\n#+END_EXAMPLE" - (let ((tree (org-element-parse-buffer))) - (should - (= (org-export-resolve-coderef "coderef" `(:parse-tree ,tree)) 1)))) - (org-test-with-temp-text - "#+BEGIN_SRC emacs-lisp -n -k -r\n(+ 1 1) (ref:coderef)\n#+END_SRC" - (let ((tree (org-element-parse-buffer))) - (should - (= (org-export-resolve-coderef "coderef" `(:parse-tree ,tree)) 1)))) - ;; 2. A link to a "-n -r" block returns line number. - (org-test-with-temp-text - "#+BEGIN_EXAMPLE -n -r\nText (ref:coderef)\n#+END_EXAMPLE" - (let ((tree (org-element-parse-buffer))) - (should - (= (org-export-resolve-coderef "coderef" `(:parse-tree ,tree)) 1)))) - (org-test-with-temp-text - "#+BEGIN_SRC emacs-lisp -n -r\n(+ 1 1) (ref:coderef)\n#+END_SRC" - (let ((tree (org-element-parse-buffer))) - (should - (= (org-export-resolve-coderef "coderef" `(:parse-tree ,tree)) 1)))) - ;; 3. A link to a "-n" block returns coderef. - (org-test-with-temp-text - "#+BEGIN_SRC emacs-lisp -n\n(+ 1 1) (ref:coderef)\n#+END_SRC" - (let ((tree (org-element-parse-buffer))) - (should - (equal (org-export-resolve-coderef "coderef" `(:parse-tree ,tree)) - "coderef")))) - (org-test-with-temp-text - "#+BEGIN_EXAMPLE -n\nText (ref:coderef)\n#+END_EXAMPLE" - (let ((tree (org-element-parse-buffer))) - (should - (equal (org-export-resolve-coderef "coderef" `(:parse-tree ,tree)) - "coderef")))) - ;; 4. A link to a "-r" block returns line number. - (org-test-with-temp-text - "#+BEGIN_SRC emacs-lisp -r\n(+ 1 1) (ref:coderef)\n#+END_SRC" - (let ((tree (org-element-parse-buffer))) - (should - (= (org-export-resolve-coderef "coderef" `(:parse-tree ,tree)) 1)))) - (org-test-with-temp-text - "#+BEGIN_EXAMPLE -r\nText (ref:coderef)\n#+END_EXAMPLE" - (let ((tree (org-element-parse-buffer))) - (should - (= (org-export-resolve-coderef "coderef" `(:parse-tree ,tree)) 1)))) - ;; 5. A link to a block without a switch returns coderef. - (org-test-with-temp-text - "#+BEGIN_SRC emacs-lisp\n(+ 1 1) (ref:coderef)\n#+END_SRC" - (let ((tree (org-element-parse-buffer))) - (should - (equal (org-export-resolve-coderef "coderef" `(:parse-tree ,tree)) - "coderef")))) - (org-test-with-temp-text - "#+BEGIN_EXAMPLE\nText (ref:coderef)\n#+END_EXAMPLE" - (let ((tree (org-element-parse-buffer))) - (should - (equal (org-export-resolve-coderef "coderef" `(:parse-tree ,tree)) - "coderef")))) - ;; 6. Correctly handle continued line numbers. A "+n" switch - ;; should resume numbering from previous block with numbered - ;; lines, ignoring blocks not numbering lines in the process. - ;; A "-n" switch resets count. - (org-test-with-temp-text " -#+BEGIN_EXAMPLE -n -Text. -#+END_EXAMPLE - -#+BEGIN_SRC emacs-lisp -\(- 1 1) -#+END_SRC - -#+BEGIN_SRC emacs-lisp +n -r -\(+ 1 1) (ref:addition) -#+END_SRC - -#+BEGIN_EXAMPLE -n -r -Another text. (ref:text) -#+END_EXAMPLE" - (let* ((tree (org-element-parse-buffer)) - (info `(:parse-tree ,tree))) - (should (= (org-export-resolve-coderef "addition" info) 2)) - (should (= (org-export-resolve-coderef "text" info) 1)))) - ;; 7. Recognize coderef with user-specified syntax. - (org-test-with-temp-text - "#+BEGIN_EXAMPLE -l \"[ref:%s]\"\nText. [ref:text]\n#+END_EXAMPLE" - (let ((tree (org-element-parse-buffer))) - (should (equal (org-export-resolve-coderef "text" `(:parse-tree ,tree)) - "text")))))) - - - -;;; Src-block and example-block - -(ert-deftest test-org-export/unravel-code () - "Test `org-export-unravel-code' function." - (let ((org-coderef-label-format "(ref:%s)")) - ;; 1. Code without reference. - (org-test-with-temp-text "#+BEGIN_EXAMPLE\n(+ 1 1)\n#+END_EXAMPLE" - (should (equal (org-export-unravel-code (org-element-current-element)) - '("(+ 1 1)\n")))) - ;; 2. Code with reference. - (org-test-with-temp-text - "#+BEGIN_EXAMPLE\n(+ 1 1) (ref:test)\n#+END_EXAMPLE" - (should (equal (org-export-unravel-code (org-element-current-element)) - '("(+ 1 1)\n" (1 . "test"))))) - ;; 3. Code with user-defined reference. - (org-test-with-temp-text - "#+BEGIN_EXAMPLE -l \"[ref:%s]\"\n(+ 1 1) [ref:test]\n#+END_EXAMPLE" - (should (equal (org-export-unravel-code (org-element-current-element)) - '("(+ 1 1)\n" (1 . "test"))))) - ;; 4. Code references keys are relative to the current block. - (org-test-with-temp-text " -#+BEGIN_EXAMPLE -n -\(+ 1 1) -#+END_EXAMPLE -#+BEGIN_EXAMPLE +n -\(+ 2 2) -\(+ 3 3) (ref:one) -#+END_EXAMPLE" - (goto-line 5) - (should (equal (org-export-unravel-code (org-element-current-element)) - '("(+ 2 2)\n(+ 3 3)\n" (2 . "one"))))) - ;; 5. Free up comma-protected lines. - ;; - ;; 5.1. In an Org source block, every line is protected. - (org-test-with-temp-text - "#+BEGIN_SRC org\n,* Test\n,# comment\n,Text\n#+END_SRC" - (should (equal (org-export-unravel-code (org-element-current-element)) - '("* Test\n# comment\nText\n")))) - ;; 5.2. In other blocks, only headlines, comments and keywords are - ;; protected. - (org-test-with-temp-text - "#+BEGIN_EXAMPLE\n,* Headline\n, * Not headline\n,Keep\n#+END_EXAMPLE" - (should (equal (org-export-unravel-code (org-element-current-element)) - '("* Headline\n, * Not headline\n,Keep\n")))))) - - - -(provide 'test-org-export) -;;; test-org-export.el end here -- 1.7.9.2