Backport commit 5b3d4e7bf from Emacs

* lisp/ox.el (org-export-get-footnote-definition): Pre-process parse
tree once to filter out all non-footnote elements.  This speeds up
subsequent footnote definition searches.

org-export-get-footnote-definition: Pre-cache references in parse tree
5b3d4e7bf0b6a1eb576e1c6e6592028e3589f792
Ihor Radchenko
Thu Jun 16 10:52:17 2022 +0300

[ km: This ported commit comes from main's f51c28671.  I'm applying it
  here too for bookkeeping/traceability purposes.  ]
This commit is contained in:
Ihor Radchenko 2022-06-12 13:05:16 +08:00 committed by Kyle Meyer
parent 5a81ec0018
commit 303c89350e

View file

@ -3750,28 +3750,33 @@ definition can be found, raise an error."
(if (not label) (org-element-contents footnote-reference) (if (not label) (org-element-contents footnote-reference)
(let ((cache (or (plist-get info :footnote-definition-cache) (let ((cache (or (plist-get info :footnote-definition-cache)
(let ((hash (make-hash-table :test #'equal))) (let ((hash (make-hash-table :test #'equal)))
;; Cache all the footnotes in document for
;; later search.
(org-element-map (plist-get info :parse-tree)
'(footnote-definition footnote-reference)
(lambda (f)
;; Skip any standard footnote reference
;; since those cannot contain a
;; definition.
(unless (eq (org-element-property :type f) 'standard)
(puthash
(cons :element (org-element-property :label f))
f
hash)))
info)
(plist-put info :footnote-definition-cache hash) (plist-put info :footnote-definition-cache hash)
hash)))) hash))))
(or (or
(gethash label cache) (gethash label cache)
(puthash label (puthash label
(org-element-map (plist-get info :parse-tree) (let ((hashed (gethash (cons :element label) cache)))
'(footnote-definition footnote-reference) (when hashed
(lambda (f) (or (org-element-contents hashed)
(cond ;; Even if the contents are empty, we can not
;; Skip any footnote with a different label. ;; return nil since that would eventually raise
;; Also skip any standard footnote reference ;; the error. Instead, return the equivalent
;; with the same label since those cannot ;; empty string.
;; 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) cache)
(error "Definition not found for footnote %s" label)))))) (error "Definition not found for footnote %s" label))))))