From 014de0a532cbc60987d09d6040ed46195cffdf12 Mon Sep 17 00:00:00 2001 From: Nicolas Goaziou Date: Fri, 20 Feb 2015 18:06:23 +0100 Subject: [PATCH] ox: Change `org-export-collect-footnote-definitions' signature * lisp/ox.el (org-export-collect-footnote-definitions): Refactor code. Change signature. * testing/lisp/test-ox.el (test-org-export/collect-footnote-definitions): New test. (test-org-export/footnotes): Update test. * lisp/ox-ascii.el (org-ascii-inner-template): * lisp/ox-html.el (org-html-footnote-section): Apply signature change. * etc/ORG-NEWS: Document signature change. This change makes `org-export-collect-footnote-definitions' compatible with `org-export-get-footnote-number' and `org-export-footnote-first-reference-p'. --- etc/ORG-NEWS | 1 + lisp/ox-ascii.el | 3 +-- lisp/ox-html.el | 3 +-- lisp/ox.el | 59 ++++++++++++++++++----------------------- testing/lisp/test-ox.el | 42 ++++++++++++++++++++++------- 5 files changed, 61 insertions(+), 47 deletions(-) diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS index 4743d7520..c1c5c1107 100644 --- a/etc/ORG-NEWS +++ b/etc/ORG-NEWS @@ -60,6 +60,7 @@ buffer name, as the title. Instead, simply ignore the title. *** Signature changes The following functions require an additional argument. See their docstring for more information. +- ~org-export-collect-footnote-definitions~ - ~org-html-format-headline-function~ - ~org-html-format-inlinetask-function~ - ~org-latex-format-headline-function~ diff --git a/lisp/ox-ascii.el b/lisp/ox-ascii.el index 3d1343e02..ddd7e3e8e 100644 --- a/lisp/ox-ascii.el +++ b/lisp/ox-ascii.el @@ -1049,8 +1049,7 @@ holding export options." ;; 1. Document's body. contents ;; 2. Footnote definitions. - (let ((definitions (org-export-collect-footnote-definitions - (plist-get info :parse-tree) info)) + (let ((definitions (org-export-collect-footnote-definitions info)) ;; Insert full links right inside the footnote definition ;; as they have no chance to be inserted later. (info (org-combine-plists info '(:ascii-links-to-notes nil)))) diff --git a/lisp/ox-html.el b/lisp/ox-html.el index 61619e014..2c191f5c0 100644 --- a/lisp/ox-html.el +++ b/lisp/ox-html.el @@ -1559,8 +1559,7 @@ Replaces invalid characters with \"_\"." (defun org-html-footnote-section (info) "Format the footnote section. INFO is a plist used as a communication channel." - (let* ((fn-alist (org-export-collect-footnote-definitions - (plist-get info :parse-tree) info)) + (let* ((fn-alist (org-export-collect-footnote-definitions info)) (fn-alist (loop for (n type raw) in fn-alist collect (cons n (if (eq (org-element-type raw) 'org-data) diff --git a/lisp/ox.el b/lisp/ox.el index 6a169974b..b79db226b 100644 --- a/lisp/ox.el +++ b/lisp/ox.el @@ -3538,39 +3538,6 @@ applied." ;; `org-export-get-footnote-number' provide easier access to ;; additional information relative to a footnote reference. -(defun org-export-collect-footnote-definitions (data info) - "Return an alist between footnote numbers, labels and definitions. - -DATA is the parse tree from which definitions are collected. -INFO is the plist used as a communication channel. - -Definitions are sorted by order of references. They either -appear as Org data or as a secondary string for inlined -footnotes. Unreferenced definitions are ignored." - (let* (num-alist - collect-fn ; for byte-compiler. - (collect-fn - (function - (lambda (data) - ;; Collect footnote number, label and definition in DATA. - (org-element-map data 'footnote-reference - (lambda (fn) - (when (org-export-footnote-first-reference-p fn info) - (let ((def (org-export-get-footnote-definition fn info))) - (push - (list (org-export-get-footnote-number fn info) - (org-element-property :label fn) - def) - num-alist) - ;; Also search in definition for nested footnotes. - (when (eq (org-element-property :type fn) 'standard) - (funcall collect-fn def))))) - ;; Don't enter footnote definitions since it will happen - ;; when their first reference is found. - info nil 'footnote-definition))))) - (funcall collect-fn (plist-get info :parse-tree)) - (reverse num-alist))) - (defun org-export-get-footnote-definition (footnote-reference info) "Return definition of FOOTNOTE-REFERENCE as parsed data. INFO is the plist used as a communication channel. If no such @@ -3625,6 +3592,32 @@ delayed until the end of the process." (funcall search-ref (plist-get info :parse-tree) body-first) (funcall search-ref (nreverse definitions) nil))) +(defun org-export-collect-footnote-definitions (info &optional body-first) + "Return an alist between footnote numbers, labels and definitions. + +INFO is the current export state, as a plist. + +Definitions are sorted by order of references. As soon as a new +reference is encountered, other references are searched within +its definition. However, if BODY-FIRST is non-nil, this step is +delayed after the whole tree is checked. This alters results +when references are found in footnote definitions. + +Definitions either appear as Org data or as a secondary string +for inlined footnotes. Unreferenced definitions are ignored." + (let ((n 0) labels alist) + (org-export--footnote-reference-map + (lambda (f) + ;; Collect footnote number, label and definition. + (let ((l (org-element-property :label f)) + (d (org-export-get-footnote-definition f info))) + (unless (and l (member l labels)) + (incf n) + (push (list n l d) alist)) + (when l (push l labels)))) + info body-first) + (nreverse alist))) + (defun org-export-footnote-first-reference-p (footnote-reference info &optional body-first) "Non-nil when a footnote reference is the first one for its label. diff --git a/testing/lisp/test-ox.el b/testing/lisp/test-ox.el index 529e20f17..5afe11d32 100644 --- a/testing/lisp/test-ox.el +++ b/testing/lisp/test-ox.el @@ -1654,6 +1654,37 @@ Footnotes[fn:2], foot[fn:test], digit only[3], and [fn:inline:anonymous footnote (org-export-get-footnote-number ref info nil))) info))))) +(ert-deftest test-org-export/collect-footnote-definitions () + "Test `org-export-collect-footnote-definitions' specifications." + (should + (= 4 + (org-test-with-parsed-data "Text[fn:1:A[fn:2]] [fn:3]. + +\[fn:2] B [fn:3] [fn::D]. + +\[fn:3] C." + (length (org-export-collect-footnote-definitions info))))) + ;; With optional argument, first check body, then footnote + ;; definitions. + (should + (equal '("fn:1" "fn:3" "fn:2" nil) + (org-test-with-parsed-data "Text[fn:1:A[fn:2]] [fn:3]. + +\[fn:2] B [fn:3] [fn::D]. + +\[fn:3] C." + (mapcar (lambda (e) (nth 1 e)) + (org-export-collect-footnote-definitions info t))))) + (should-not + (equal '("fn:1" "fn:3" "fn:2" nil) + (org-test-with-parsed-data "Text[fn:1:A[fn:2]] [fn:3]. + +\[fn:2] B [fn:3] [fn::D]. + +\[fn:3] C." + (mapcar (lambda (e) (nth 1 e)) + (org-export-collect-footnote-definitions info)))))) + (ert-deftest test-org-export/footnotes () "Miscellaneous tests on footnotes." (let ((org-footnote-section nil) @@ -1683,16 +1714,7 @@ Footnotes[fn:2], foot[fn:test], digit only[3], and [fn:inline:anonymous footnote tree (org-export-get-environment))))) ;; Both footnotes should be seen. (should - (= (length (org-export-collect-footnote-definitions tree info)) 2)))) - ;; Test footnotes definitions collection. - (should - (= 4 - (org-test-with-parsed-data "Text[fn:1:A[fn:2]] [fn:3]. - -\[fn:2] B [fn:3] [fn::D]. - -\[fn:3] C." - (length (org-export-collect-footnote-definitions tree info))))) + (= (length (org-export-collect-footnote-definitions info)) 2)))) ;; Test export of footnotes defined outside parsing scope. (should (equal