forked from mirrors/org-mode
org-export: Expand correctly {{{title}}} and such
* contrib/lisp/org-export.el (org-export-as): Expand correctly {{{title}}} and such when they already contain a regular macro. This is done by expanding macros in two steps: at first regular macros, then document specific macros. (org-export-expand-macro): Remove function. * testing/lisp/test-org-export.el: Add test.
This commit is contained in:
parent
a8c026cb26
commit
a2120a9d73
|
@ -2563,49 +2563,65 @@ Return code as a string."
|
|||
(goto-char (point-min))
|
||||
(forward-line)
|
||||
(narrow-to-region (point) (point-max))))
|
||||
;; 1. Get export environment from original buffer. Also install
|
||||
;; user's and developer's filters.
|
||||
(let* ((info (org-export-install-filters
|
||||
(org-export-get-environment backend subtreep ext-plist)))
|
||||
;; 2. Get parse tree. Buffer isn't parsed directly.
|
||||
;; Instead, a temporary copy is created, where include
|
||||
;; keywords and macros are expanded and code blocks
|
||||
;; are evaluated.
|
||||
(tree (org-export-with-current-buffer-copy
|
||||
(unless noexpand
|
||||
(org-export-expand-include-keyword)
|
||||
;; Update radio targets since keyword
|
||||
;; inclusion might have added some more.
|
||||
(org-update-radio-target-regexp)
|
||||
(org-export-expand-macro info)
|
||||
;; TODO: Setting `org-current-export-file' is
|
||||
;; required by Org Babel to properly resolve
|
||||
;; noweb references. Once "org-exp.el" is
|
||||
;; removed, modify
|
||||
;; `org-export-blocks-preprocess' so it
|
||||
;; accepts the value as an argument instead.
|
||||
(let ((org-current-export-file (current-buffer)))
|
||||
(org-export-blocks-preprocess)))
|
||||
(goto-char (point-min))
|
||||
;; Run hook
|
||||
;; `org-export-before-parsing-hook'. with current
|
||||
;; back-end as argument.
|
||||
(run-hook-with-args
|
||||
'org-export-before-parsing-hook backend)
|
||||
;; Eventually parse buffer.
|
||||
(org-element-parse-buffer nil visible-only))))
|
||||
;; 3. Call parse-tree filters to get the final tree.
|
||||
(setq tree
|
||||
(org-export-filter-apply-functions
|
||||
(plist-get info :filter-parse-tree) tree info))
|
||||
;; 4. Now tree is complete, compute its properties and add
|
||||
;; them to communication channel.
|
||||
;; Install user's and developer's filters in communication
|
||||
;; channel.
|
||||
(let (info tree)
|
||||
(org-export-with-current-buffer-copy
|
||||
;; Update communication channel and get parse tree. Buffer
|
||||
;; isn't parsed directly. Instead, a temporary copy is
|
||||
;; created, where include keywords, macros are expanded and
|
||||
;; code blocks are evaluated.
|
||||
(unless noexpand
|
||||
(org-export-expand-include-keyword)
|
||||
;; Update macro templates since #+INCLUDE keywords might
|
||||
;; have added some new ones.
|
||||
(org-macro-initialize-templates)
|
||||
(org-macro-replace-all org-macro-templates)
|
||||
;; TODO: Setting `org-current-export-file' is required by
|
||||
;; Org Babel to properly resolve noweb references. Once
|
||||
;; "org-exp.el" is removed, modify
|
||||
;; `org-export-blocks-preprocess' so it accepts the value
|
||||
;; as an argument instead.
|
||||
(let ((org-current-export-file (current-buffer)))
|
||||
(org-export-blocks-preprocess)))
|
||||
;; Update radio targets since keyword inclusion might have
|
||||
;; added some more.
|
||||
(org-update-radio-target-regexp)
|
||||
;; Run hook `org-export-before-parsing-hook'. with current
|
||||
;; back-end as argument.
|
||||
(goto-char (point-min))
|
||||
(run-hook-with-args 'org-export-before-parsing-hook backend)
|
||||
;; Initialize communication channel.
|
||||
(setq info
|
||||
(org-export-install-filters
|
||||
(org-export-get-environment backend subtreep ext-plist)))
|
||||
;; Expand export-specific set of macros: {{{author}}},
|
||||
;; {{{date}}}, {{{email}}} and {{{title}}}. It must be done
|
||||
;; once regular macros have been expanded, since document
|
||||
;; keywords may contain one of them.
|
||||
(unless noexpand
|
||||
(org-macro-replace-all
|
||||
(list (cons "author"
|
||||
(org-element-interpret-data (plist-get info :author)))
|
||||
(cons "date"
|
||||
(org-element-interpret-data (plist-get info :date)))
|
||||
;; EMAIL is not a parsed keyword: store it as-is.
|
||||
(cons "email" (or (plist-get info :email) ""))
|
||||
(cons "title"
|
||||
(org-element-interpret-data (plist-get info :title))))))
|
||||
;; Eventually parse buffer. Call parse-tree filters to get
|
||||
;; the final tree.
|
||||
(setq tree
|
||||
(org-export-filter-apply-functions
|
||||
(plist-get info :filter-parse-tree)
|
||||
(org-element-parse-buffer nil visible-only) info)))
|
||||
;; Now tree is complete, compute its properties and add them
|
||||
;; to communication channel.
|
||||
(setq info
|
||||
(org-combine-plists
|
||||
info (org-export-collect-tree-properties tree info)))
|
||||
;; 5. Eventually transcode TREE. Wrap the resulting string
|
||||
;; into a template, if required. Eventually call
|
||||
;; final-output filter.
|
||||
;; Eventually transcode TREE. Wrap the resulting string into
|
||||
;; a template, if required. Finally call final-output filter.
|
||||
(let* ((body (org-element-normalize-string (org-export-data tree info)))
|
||||
(template (cdr (assq 'template
|
||||
(plist-get info :translate-alist))))
|
||||
|
@ -2742,26 +2758,6 @@ Point is at buffer's beginning when BODY is applied."
|
|||
(goto-char (point-min))
|
||||
(progn ,@body))))))
|
||||
|
||||
(defun org-export-expand-macro (info)
|
||||
"Expand every macro in buffer.
|
||||
INFO is a plist containing export options and buffer properties."
|
||||
;; First update macro templates since #+INCLUDE keywords might have
|
||||
;; added some new ones.
|
||||
(org-macro-initialize-templates)
|
||||
(org-macro-replace-all
|
||||
;; Before expanding macros, install {{{author}}}, {{{date}}},
|
||||
;; {{{email}}} and {{{title}}} templates.
|
||||
(nconc
|
||||
(list (cons "author"
|
||||
(org-element-interpret-data (plist-get info :author)))
|
||||
(cons "date"
|
||||
(org-element-interpret-data (plist-get info :date)))
|
||||
;; EMAIL is not a parsed keyword: store it as-is.
|
||||
(cons "email" (or (plist-get info :email) ""))
|
||||
(cons "title"
|
||||
(org-element-interpret-data (plist-get info :title))))
|
||||
org-macro-templates)))
|
||||
|
||||
(defun org-export-expand-include-keyword (&optional included dir)
|
||||
"Expand every include keyword in buffer.
|
||||
Optional argument INCLUDED is a list of included file names along
|
||||
|
|
|
@ -439,13 +439,12 @@ body\n")))
|
|||
"Test macro expansion in an Org buffer."
|
||||
;; Standard macro expansion.
|
||||
(should
|
||||
(equal "#+MACRO: macro1 value\nvalue"
|
||||
(equal "#+MACRO: macro1 value\nvalue\n"
|
||||
(org-test-with-temp-text "#+MACRO: macro1 value\n{{{macro1}}}"
|
||||
(let (info)
|
||||
(org-export-expand-macro info) (buffer-string)))))
|
||||
;; Export specific macros.
|
||||
(org-test-with-backend test (org-export-as 'test)))))
|
||||
;; Expand specific macros.
|
||||
(should
|
||||
(equal "me 2012-03-29 me@here Title"
|
||||
(equal "me 2012-03-29 me@here Title\n"
|
||||
(org-test-with-temp-text
|
||||
"
|
||||
#+TITLE: Title
|
||||
|
@ -453,23 +452,26 @@ body\n")))
|
|||
#+AUTHOR: me
|
||||
#+EMAIL: me@here
|
||||
{{{author}}} {{{date}}} {{{email}}} {{{title}}}"
|
||||
(let ((info (org-export-get-environment)))
|
||||
(org-export-expand-macro info)
|
||||
(goto-char (point-max))
|
||||
(buffer-substring (line-beginning-position)
|
||||
(line-end-position))))))
|
||||
(let ((output (org-test-with-backend test (org-export-as 'test))))
|
||||
(substring output (string-match ".*\n\\'" output))))))
|
||||
;; Expand specific macros when property contained a regular macro
|
||||
;; already.
|
||||
(should
|
||||
(equal "value\n"
|
||||
(org-test-with-temp-text "
|
||||
#+MACRO: macro1 value
|
||||
#+TITLE: {{{macro1}}}
|
||||
{{{title}}}"
|
||||
(let ((output (org-test-with-backend test (org-export-as 'test))))
|
||||
(substring output (string-match ".*\n\\'" output))))))
|
||||
;; Expand macros with templates in included files.
|
||||
(should
|
||||
(equal "success"
|
||||
(equal "success\n"
|
||||
(org-test-with-temp-text
|
||||
(format "#+INCLUDE: \"%s/examples/macro-templates.org\"
|
||||
{{{included-macro}}}" org-test-dir)
|
||||
(let (info)
|
||||
(org-export-expand-include-keyword)
|
||||
(org-export-expand-macro info)
|
||||
(goto-char (point-max))
|
||||
(buffer-substring (line-beginning-position)
|
||||
(line-end-position)))))))
|
||||
(let ((output (org-test-with-backend test (org-export-as 'test))))
|
||||
(substring output (string-match ".*\n\\'" output)))))))
|
||||
|
||||
(ert-deftest test-org-export/user-ignore-list ()
|
||||
"Test if `:ignore-list' accepts user input."
|
||||
|
|
Loading…
Reference in New Issue