diff --git a/lisp/ox.el b/lisp/ox.el index 6f5ebf474..bf19b4b98 100644 --- a/lisp/ox.el +++ b/lisp/ox.el @@ -3666,16 +3666,28 @@ definition can be found, raise an error." (let ((hash (make-hash-table :test #'equal))) (plist-put info :footnote-definition-cache hash) hash)))) - (or (gethash label cache) - (puthash label - (org-element-map (plist-get info :parse-tree) - '(footnote-definition footnote-reference) - (lambda (f) - (and (equal (org-element-property :label f) label) - (org-element-contents f))) - info t) - cache) - (error "Definition not found for footnote %s" label)))))) + (or + (gethash label cache) + (puthash label + (org-element-map (plist-get info :parse-tree) + '(footnote-definition footnote-reference) + (lambda (f) + (cond + ;; Skip any footnote with a different + ;; label. Also skip any standard footnote + ;; reference with the same label since those + ;; cannot contain a definition. + ((not (equal (org-element-property :label f) label)) nil) + ((eq (org-element-property :type f) 'standard) nil) + ((org-element-contents f)) + ;; Even if the contents are empty, we can not + ;; return nil since that would eventually raise + ;; the error. Instead, return the equivalent + ;; empty string. + (t ""))) + info t) + cache) + (error "Definition not found for footnote %s" label)))))) (defun org-export--footnote-reference-map (function data info &optional body-first) diff --git a/testing/lisp/test-ox.el b/testing/lisp/test-ox.el index 565bf48f5..a85f1046d 100644 --- a/testing/lisp/test-ox.el +++ b/testing/lisp/test-ox.el @@ -1887,6 +1887,61 @@ Para2" (org-export-get-footnote-number ref info nil))) info))))) +(ert-deftest test-org-export/get-footnote-definition () + "Test `org-export-get-footnote-definition' specifications." + ;; Standard test. + (should + (equal "A\n" + (org-element-interpret-data + (org-test-with-parsed-data "Text[fn:1]\n\n[fn:1] A" + (org-export-get-footnote-definition + (org-element-map tree 'footnote-reference #'identity nil t) + info))))) + ;; Raise an error if no definition is found. + (should-error + (org-test-with-parsed-data "Text[fn:1]" + (org-export-get-footnote-definition + (org-element-map tree 'footnote-reference #'identity nil t) + info))) + ;; Find inline definitions. + (should + (equal "A" + (org-element-interpret-data + (org-test-with-parsed-data "Text[fn:1:A]" + (org-export-get-footnote-definition + (org-element-map tree 'footnote-reference #'identity nil t) + info))))) + ;; Find anonymous definitions. + (should + (equal "A" + (org-element-interpret-data + (org-test-with-parsed-data "Text[fn::A]" + (org-export-get-footnote-definition + (org-element-map tree 'footnote-reference #'identity nil t) + info))))) + ;; Find empty definitions. + (should + (equal "" + (org-element-interpret-data + (org-test-with-parsed-data "Text[fn:1]\n\n[fn:1]" + (org-export-get-footnote-definition + (org-element-map tree 'footnote-reference #'identity nil t) + info))))) + (should + (equal "" + (org-element-interpret-data + (org-test-with-parsed-data "Text[fn:1:]" + (org-export-get-footnote-definition + (org-element-map tree 'footnote-reference #'identity nil t) + info))))) + (should + (equal "" + (org-element-interpret-data + (org-test-with-parsed-data "Text[fn::]" + (org-export-get-footnote-definition + (org-element-map tree 'footnote-reference #'identity nil t) + info)))))) + (ert-deftest test-org-export/collect-footnote-definitions () "Test `org-export-collect-footnote-definitions' specifications." (should