diff --git a/lisp/ox.el b/lisp/ox.el index 1778004ec..f60ff125b 100644 --- a/lisp/ox.el +++ b/lisp/ox.el @@ -1364,52 +1364,45 @@ for export. Return options as a plist." ;; same property in communication channel. The name for the ;; property is the keyword with "EXPORT_" appended to it. (org-with-wide-buffer - (let (plist + ;; Make sure point is at a heading. + (if (org-at-heading-p) (org-up-heading-safe) (org-back-to-heading t)) + (let ((plist + ;; EXPORT_OPTIONS are parsed in a non-standard way. Take + ;; care of them right from the start. + (let ((o (org-entry-get (point) "EXPORT_OPTIONS"))) + (and o (org-export--parse-option-keyword o backend)))) + ;; Take care of EXPORT_TITLE. If it isn't defined, use + ;; headline's title (with no todo keyword, priority cookie or + ;; tag) as its fallback value. + (cache (list + (cons "TITLE" + (or (org-entry-get (point) "EXPORT_TITLE") + (progn (looking-at org-complex-heading-regexp) + (org-match-string-no-properties 4)))))) ;; Look for both general keywords and back-end specific ;; options, with priority given to the latter. (options (append (and backend (org-export-get-all-options backend)) org-export-options-alist))) - ;; Make sure point is at a heading. - (if (org-at-heading-p) (org-up-heading-safe) (org-back-to-heading t)) - ;; Take care of EXPORT_TITLE. If it isn't defined, use - ;; headline's title (with no todo keyword, priority cookie or - ;; tag) as its fallback value. - (let ((title (or (org-entry-get (point) "EXPORT_TITLE") - (progn (looking-at org-complex-heading-regexp) - (org-match-string-no-properties 4))))) - (setq plist - (plist-put - plist :title - (if (eq (nth 4 (assq :title options)) 'parse) - (org-element-parse-secondary-string - title (org-element-restriction 'keyword)) - title)))) - ;; EXPORT_OPTIONS are parsed in a non-standard way. - (let ((o (org-entry-get (point) "EXPORT_OPTIONS"))) - (when o - (setq plist - (nconc plist (org-export--parse-option-keyword o backend))))) - ;; Handle other keywords. TITLE keyword is excluded as it has - ;; been handled already. Then return PLIST. - (let ((seen '("TITLE"))) - (dolist (option options plist) - (let ((property (car option)) - (keyword (nth 1 option))) - (when (and keyword (not (member keyword seen))) - (let* ((subtree-prop (concat "EXPORT_" keyword)) - (value (org-entry-get (point) subtree-prop))) - (push keyword seen) - (when (and value (not (plist-member plist property))) - (setq plist - (plist-put - plist - property - (case (nth 4 option) - (parse - (org-element-parse-secondary-string - value (org-element-restriction 'keyword))) - (split (org-split-string value)) - (t value))))))))))))) + ;; Handle other keywords. Then return PLIST. + (dolist (option options plist) + (let ((property (car option)) + (keyword (nth 1 option))) + (when keyword + (let ((value + (or (cdr (assoc keyword cache)) + (let ((v (org-entry-get (point) + (concat "EXPORT_" keyword)))) + (push (cons keyword v) cache) v)))) + (when value + (setq plist + (plist-put plist + property + (case (nth 4 option) + (parse + (org-element-parse-secondary-string + value (org-element-restriction 'keyword))) + (split (org-split-string value)) + (t value)))))))))))) (defun org-export--get-inbuffer-options (&optional backend) "Return current buffer export options, as a plist. diff --git a/testing/lisp/test-ox.el b/testing/lisp/test-ox.el index 0510c035b..9bf4b0cad 100644 --- a/testing/lisp/test-ox.el +++ b/testing/lisp/test-ox.el @@ -225,77 +225,81 @@ variable, and communication channel under `info'." (ert-deftest test-org-export/get-subtree-options () "Test setting options from headline's properties." ;; EXPORT_TITLE. - (org-test-with-temp-text "#+TITLE: Title -* Headline + (should + (equal '("Subtree Title") + (org-test-with-temp-text "#+TITLE: Title +* Headline :PROPERTIES: :EXPORT_TITLE: Subtree Title :END: Paragraph" - (forward-line) - (should (equal (plist-get (org-export-get-environment nil t) :title) - '("Subtree Title")))) - :title - '("subtree-title") + (plist-get (org-export-get-environment nil t) :title)))) ;; EXPORT_OPTIONS. - (org-test-with-temp-text "#+OPTIONS: H:1 -* Headline + (should + (= 2 + (org-test-with-temp-text "#+OPTIONS: H:1 +* Headline :PROPERTIES: :EXPORT_OPTIONS: H:2 :END: Paragraph" - (forward-line) - (should - (= 2 (plist-get (org-export-get-environment nil t) :headline-levels)))) + (plist-get (org-export-get-environment nil t) :headline-levels)))) ;; EXPORT_DATE. - (org-test-with-temp-text "#+DATE: today -* Headline + (should + (equal '("29-03-2012") + (org-test-with-temp-text "#+DATE: today +* Headline :PROPERTIES: :EXPORT_DATE: 29-03-2012 :END: Paragraph" - (forward-line) - (should (equal (plist-get (org-export-get-environment nil t) :date) - '("29-03-2012")))) + (plist-get (org-export-get-environment nil t) :date)))) ;; Properties with `split' behaviour are stored as a list of ;; strings. (should (equal '("a" "b") (org-test-with-temp-text "#+EXCLUDE_TAGS: noexport -* Headline +* Headline :PROPERTIES: :EXPORT_EXCLUDE_TAGS: a b :END: Paragraph" - (progn - (forward-line) - (plist-get (org-export-get-environment nil t) :exclude-tags))))) + (plist-get (org-export-get-environment nil t) :exclude-tags)))) ;; Handle :PROPERTY+: syntax. (should (equal '("a" "b") (org-test-with-temp-text "#+EXCLUDE_TAGS: noexport -* Headline +* Headline :PROPERTIES: :EXPORT_EXCLUDE_TAGS: a :EXPORT_EXCLUDE_TAGS+: b :END: Paragraph" - (progn - (forward-line) - (plist-get (org-export-get-environment nil t) :exclude-tags))))) + (plist-get (org-export-get-environment nil t) :exclude-tags)))) ;; Export properties are case-insensitive. - (org-test-with-temp-text "* Headline + (should + (equal '("29-03-2012") + (org-test-with-temp-text "* Headline :PROPERTIES: :EXPORT_Date: 29-03-2012 :END: Paragraph" - (should (equal (plist-get (org-export-get-environment nil t) :date) - '("29-03-2012")))) + (plist-get (org-export-get-environment nil t) :date)))) ;; Still grab correct options when section above is empty. (should (equal '("H1") - (org-test-with-temp-text "* H1\n** H11\n** H12" - (progn (forward-line 2) - (plist-get (org-export-get-environment nil t) :title)))))) + (org-test-with-temp-text "* H1\n** H11\n** H12" + (plist-get (org-export-get-environment nil t) :title)))) + ;; More than one property can refer to the same node property. + (should + (equal '("1" "1") + (org-test-with-temp-text + "* H\n:PROPERTIES:\n:EXPORT_A: 1\n:END:\n" + (let* ((backend (org-export-create-backend + :options '((:k1 "A") + (:k2 "A")))) + (options (org-export-get-environment backend t))) + (list (plist-get options :k1) (plist-get options :k2))))))) (ert-deftest test-org-export/set-title () "Test title setting."