Browse Source

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'.
Nicolas Goaziou 3 years ago
parent
commit
014de0a532
5 changed files with 61 additions and 47 deletions
  1. 1 0
      etc/ORG-NEWS
  2. 1 2
      lisp/ox-ascii.el
  3. 1 2
      lisp/ox-html.el
  4. 26 33
      lisp/ox.el
  5. 32 10
      testing/lisp/test-ox.el

+ 1 - 0
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~

+ 1 - 2
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))))

+ 1 - 2
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)

+ 26 - 33
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.

+ 32 - 10
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