ox: Implement `inner-template' transcoder
authorNicolas Goaziou <n.goaziou@gmail.com>
Mon, 11 Feb 2013 21:19:23 +0000 (11 22:19 +0100)
committerNicolas Goaziou <n.goaziou@gmail.com>
Mon, 11 Feb 2013 21:26:52 +0000 (11 22:26 +0100)
* lisp/ox.el (org-export-as): Call `inner-template' function, if
  available.
* lisp/ox-html.el (org-html-inner-template): New function.
(org-html-template): Move all parts that should be inserted even in
a body-only export into `org-html-inner-template'.
* testing/lisp/test-ox.el: Add tests.

lisp/ox-html.el
lisp/ox.el
testing/lisp/test-ox.el

index e1b9cf0..3f67c5c 100644 (file)
@@ -68,6 +68,7 @@
    (horizontal-rule . org-html-horizontal-rule)
    (inline-src-block . org-html-inline-src-block)
    (inlinetask . org-html-inlinetask)
+   (inner-template . org-html-inner-template)
    (italic . org-html-italic)
    (item . org-html-item)
    (keyword . org-html-keyword)
@@ -1369,6 +1370,26 @@ INFO is a plist used as a communication channel."
           (org-element-normalize-string postamble-contents)
           "</div>\n"))))))
 
+(defun org-html-inner-template (contents info)
+  "Return body of document string after HTML conversion.
+CONTENTS is the transcoded contents string.  INFO is a plist
+holding export options."
+  (concat
+   (format "<div id=\"%s\">\n" (nth 1 org-html-divs))
+   ;; Document title.
+   (format "<h1 class=\"title\">%s</h1>\n"
+          (org-export-data (plist-get info :title) info))
+   ;; Table of contents.
+   (let ((depth (plist-get info :with-toc)))
+     (when depth (org-html-toc depth info)))
+   ;; Document contents.
+   contents
+   ;; Footnotes section.
+   (org-html-footnote-section info)
+   ;; Bibliography.
+   (org-html-bibliography)
+   "\n</div>"))
+
 (defun org-html-template (contents info)
   "Return complete document string after HTML conversion.
 CONTENTS is the transcoded contents string.  INFO is a plist
@@ -1405,22 +1426,8 @@ holding export options."
               (or link-home link-up))))
    ;; Preamble.
    (org-html--build-preamble info)
-   ;; Begin content.
-   (format "<div id=\"%s\">\n" (nth 1 org-html-divs))
-   ;; Document title.
-   (format "<h1 class=\"title\">%s</h1>\n"
-          (org-export-data (plist-get info :title) info))
-   ;; Table of contents.
-   (let ((depth (plist-get info :with-toc)))
-     (when depth (org-html-toc depth info)))
    ;; Document contents.
    contents
-   ;; Footnotes section.
-   (org-html-footnote-section info)
-   ;; Bibliography.
-   (org-html-bibliography)
-   ;; End content.
-   "\n</div>"
    ;; Postamble.
    (org-html--build-postamble info)
    ;; Closing document.
index d83c11b..0b32842 100644 (file)
@@ -830,13 +830,15 @@ string, the type will be ignored, but the blank lines or white
 spaces will be kept.
 
 In addition to element and object types, one function can be
-associated to the `template' symbol and another one to the
-`plain-text' symbol.
+associated to the `template' (or `inner-template') symbol and
+another one to the `plain-text' symbol.
 
 The former returns the final transcoded string, and can be used
 to add a preamble and a postamble to document's body.  It must
 accept two arguments: the transcoded string and the property list
-containing export options.
+containing export options.  A function associated to `template'
+will not be applied if export has option \"body-only\".
+A function associated to `inner-template' is always applied.
 
 The latter, when defined, is to be called on every text not
 recognized as an element or an object.  It must accept two
@@ -1227,7 +1229,8 @@ The back-end could then be called with, for example:
 ;;
 ;; + `:translate-alist' :: Alist between element and object types and
 ;;      transcoding functions relative to the current back-end.
-;;      Special keys `template' and `plain-text' are also possible.
+;;      Special keys `inner-template', `template' and `plain-text' are
+;;      also possible.
 ;;   - category :: option
 ;;   - type :: alist (SYMBOL . FUNCTION)
 ;;
@@ -1286,8 +1289,8 @@ The back-end could then be called with, for example:
 ;; + `:with-latex' :: Non-nil means `latex-environment' elements and
 ;;    `latex-fragment' objects should appear in export output.  When
 ;;    this property is set to `verbatim', they will be left as-is.
-;;    - category :: option
-;;    - symbol (`verbatim', nil, t)
+;;   - category :: option
+;;   - type :: symbol (`verbatim', nil, t)
 ;;
 ;; + `:with-plannings' :: Non-nil means transcoding should include
 ;;      planning info.
@@ -2848,18 +2851,23 @@ Return code as a string."
               (org-combine-plists
                info (org-export-collect-tree-properties tree info)))
         ;; Eventually transcode TREE.  Wrap the resulting string into
-        ;; a template, if needed.  Finally call final-output filter.
-        (let ((body (org-element-normalize-string
-                     (or (org-export-data tree info) "")))
-              (template (cdr (assq 'template
-                                   (plist-get info :translate-alist)))))
+        ;; a template.
+        (let* ((body (org-element-normalize-string
+                      (or (org-export-data tree info) "")))
+               (inner-template (cdr (assq 'inner-template
+                                          (plist-get info :translate-alist))))
+               (full-body (if (not (functionp inner-template)) body
+                            (funcall inner-template body info)))
+               (template (cdr (assq 'template
+                                    (plist-get info :translate-alist)))))
           ;; Remove all text properties since they cannot be
-          ;; retrieved from an external process, and return result.
+          ;; retrieved from an external process.  Finally call
+          ;; final-output filter and return result.
           (org-no-properties
            (org-export-filter-apply-functions
             (plist-get info :filter-final-output)
-            (if (or (not (functionp template)) body-only) body
-              (funcall template body info))
+            (if (or (not (functionp template)) body-only) full-body
+              (funcall template full-body info))
             info))))))))
 
 ;;;###autoload
index b27ded0..c67db4f 100644 (file)
@@ -2093,6 +2093,50 @@ Another text. (ref:text)
 
 
 \f
+;;; Templates
+
+(ert-deftest test-org-export/inner-template ()
+  "Test `inner-template' translator specifications."
+  (should
+   (equal "Success!"
+         (let (org-export-registered-backends)
+           (org-export-define-backend test
+             ((inner-template . (lambda (contents info) "Success!"))
+              (headline . (lambda (h c i) "Headline"))))
+           (org-test-with-temp-text "* Headline"
+             (org-export-as 'test)))))
+  ;; Inner template is applied even in a "body-only" export.
+  (should
+   (equal "Success!"
+         (let (org-export-registered-backends)
+           (org-export-define-backend test
+             ((inner-template . (lambda (contents info) "Success!"))
+              (headline . (lambda (h c i) "Headline"))))
+           (org-test-with-temp-text "* Headline"
+             (org-export-as 'test nil nil 'body-only))))))
+
+(ert-deftest test-org-export/template ()
+  "Test `template' translator specifications."
+  (should
+   (equal "Success!"
+         (let (org-export-registered-backends)
+           (org-export-define-backend test
+             ((template . (lambda (contents info) "Success!"))
+              (headline . (lambda (h c i) "Headline"))))
+           (org-test-with-temp-text "* Headline"
+             (org-export-as 'test)))))
+  ;; Template is not applied in a "body-only" export.
+  (should-not
+   (equal "Success!"
+         (let (org-export-registered-backends)
+           (org-export-define-backend test
+             ((template . (lambda (contents info) "Success!"))
+              (headline . (lambda (h c i) "Headline"))))
+           (org-test-with-temp-text "* Headline"
+             (org-export-as 'test nil nil 'body-only))))))
+
+
+\f
 ;;; Topology
 
 (ert-deftest test-org-export/get-next-element ()