From a7394224aa640f1ab2d9ca213b2fc3a582bdc3ed Mon Sep 17 00:00:00 2001 From: Nicolas Goaziou Date: Sun, 6 Sep 2015 21:54:57 +0200 Subject: [PATCH] ox: Fix footnotes in included files * lisp/ox.el (org-export--prepare-file-contents): Do not error when including multiple footnotes with the same label. * testing/lisp/test-ox.el (test-org-export/expand-include): Update test. Reported-by: Leonard Randall --- lisp/ox.el | 25 +++++++++++++++---------- testing/lisp/test-ox.el | 5 ++--- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/lisp/ox.el b/lisp/ox.el index d3179cc9a..6dfed8d1a 100644 --- a/lisp/ox.el +++ b/lisp/ox.el @@ -3371,20 +3371,20 @@ lines, include only those lines. Optional argument IND, when non-nil, is an integer specifying the global indentation of returned contents. Since its purpose is to allow an included file to stay in the same environment it was -created \(i.e. a list item), it doesn't apply past the first +created (e.g., a list item), it doesn't apply past the first headline encountered. Optional argument MINLEVEL, when non-nil, is an integer specifying the level that any top-level headline in the included file should have. + Optional argument ID is an integer that will be inserted before each footnote definition and reference if FILE is an Org file. This is useful to avoid conflicts when more than one Org file with footnotes is included in a document. Optional argument FOOTNOTES is a hash-table to store footnotes in -the included document. -" +the included document." (with-temp-buffer (insert-file-contents file) (when lines @@ -3413,7 +3413,7 @@ the included document. (delete-region (point) (point-max)) ;; If IND is set, preserve indentation of include keyword until ;; the first headline encountered. - (when ind + (when (and ind (> ind 0)) (unless (eq major-mode 'org-mode) (let ((org-inhibit-startup t)) (org-mode))) (goto-char (point-min)) @@ -3435,21 +3435,23 @@ the included document. (let ((levels (org-map-entries (lambda () (org-reduced-level (org-current-level)))))) (when levels - (let ((offset (- minlevel (apply 'min levels)))) + (let ((offset (- minlevel (apply #'min levels)))) (unless (zerop offset) (when org-odd-levels-only (setq offset (* offset 2))) ;; Only change stars, don't bother moving whole ;; sections. (org-map-entries - (lambda () (if (< offset 0) (delete-char (abs offset)) - (insert (make-string offset ?*))))))))))) + (lambda () + (if (< offset 0) (delete-char (abs offset)) + (insert (make-string offset ?*))))))))))) ;; Append ID to all footnote references and definitions, so they ;; become file specific and cannot collide with footnotes in other ;; included files. Further, collect relevant footnotes outside of ;; LINES. (when id (let ((marker-min (point-min-marker)) - (marker-max (point-max-marker))) + (marker-max (point-max-marker)) + seen) (goto-char (point-min)) (while (re-search-forward org-footnote-re nil t) (let ((reference (org-element-context))) @@ -3466,7 +3468,10 @@ the included document. (let ((new-label (org-export--update-footnote-label (org-element-property :begin reference) digit-label id))) - (unless (eq (org-element-property :type reference) 'inline) + (unless (or (eq (org-element-property :type reference) + 'inline) + (member label seen)) + (push label seen) (org-with-wide-buffer (let* ((definition (org-footnote-get-definition label)) (beginning (nth 1 definition))) @@ -3475,7 +3480,7 @@ the included document. "Definition not found for footnote %s in file %s" label file)) (if (or (< beginning marker-min) - (> beginning marker-max)) + (>= beginning marker-max)) ;; Store since footnote-definition is ;; outside of LINES. (puthash new-label diff --git a/testing/lisp/test-ox.el b/testing/lisp/test-ox.el index 2c97cef78..378c86c09 100644 --- a/testing/lisp/test-ox.el +++ b/testing/lisp/test-ox.el @@ -974,7 +974,7 @@ text (length (delete-dups (let ((contents " -Footnotes[fn:1], [fn:test] and [fn:inline:anonymous footnote]. +Footnotes[fn:1], [fn:test], [fn:test] and [fn:inline:anonymous footnote]. \[fn:1] Footnote 1 \[fn:test] Footnote \"test\"")) (org-test-with-temp-text-in-file contents @@ -987,8 +987,7 @@ Footnotes[fn:1], [fn:test] and [fn:inline:anonymous footnote]. (org-export-expand-include-keyword) (org-element-map (org-element-parse-buffer) 'footnote-reference - (lambda (ref) - (org-element-property :label ref))))))))))))) + (lambda (r) (org-element-property :label r))))))))))))) ;; Footnotes labels are not local to each include keyword. (should (= 4