org-e-latex: Allow nested footnotes
* EXPERIMENTAL/org-e-latex.el (org-e-latex-footnote-reference): Allow nested footnotes. * contrib/lisp/org-element.el (org-element-string-restrictions): Allow footnote references within a footnote reference. * testing/contrib/lisp/test-org-export.el: Add a test for nested footnotes.
This commit is contained in:
parent
5313dc9d09
commit
81cc6dff19
|
@ -1013,26 +1013,46 @@ CONTENTS is nil. INFO is a plist holding contextual information."
|
||||||
(let ((prev (org-export-get-previous-element footnote-reference info)))
|
(let ((prev (org-export-get-previous-element footnote-reference info)))
|
||||||
(when (eq (org-element-type prev) 'footnote-reference)
|
(when (eq (org-element-type prev) 'footnote-reference)
|
||||||
org-e-latex-footnote-separator))
|
org-e-latex-footnote-separator))
|
||||||
;; Use \footnotemark if the footnote has already been defined.
|
|
||||||
;; Otherwise, define it with \footnote command.
|
|
||||||
(cond
|
(cond
|
||||||
|
;; Use \footnotemark if the footnote has already been defined.
|
||||||
((not (org-export-footnote-first-reference-p footnote-reference info))
|
((not (org-export-footnote-first-reference-p footnote-reference info))
|
||||||
(format "\\footnotemark[%s]"
|
(format "\\footnotemark[%s]{}"
|
||||||
(org-export-get-footnote-number footnote-reference info)))
|
(org-export-get-footnote-number footnote-reference info)))
|
||||||
;; Inline definitions are secondary strings.
|
;; Use also \footnotemark if reference is within another footnote
|
||||||
((eq (org-element-property :type footnote-reference) 'inline)
|
;; reference or footnote definition.
|
||||||
(format "\\footnote{%s}"
|
((loop for parent in (org-export-get-genealogy footnote-reference info)
|
||||||
(org-trim
|
thereis (memq (org-element-type parent)
|
||||||
(org-export-secondary-string
|
'(footnote-reference footnote-definition)))
|
||||||
(org-export-get-footnote-definition footnote-reference info)
|
(format "\\footnotemark[%s]{}"
|
||||||
'e-latex info))))
|
(org-export-get-footnote-number footnote-reference info)))
|
||||||
;; Non-inline footnotes definitions are full Org data.
|
;; Otherwise, define it with \footnote command.
|
||||||
(t
|
(t
|
||||||
(format "\\footnote{%s}"
|
(let ((def (org-export-get-footnote-definition footnote-reference info)))
|
||||||
(org-trim
|
(unless (eq (org-element-type def) 'org-data)
|
||||||
(org-export-data
|
(setq def (cons 'org-data (cons nil def))))
|
||||||
(org-export-get-footnote-definition footnote-reference info)
|
(concat
|
||||||
'e-latex info)))))))
|
(format "\\footnote{%s}" (org-trim (org-export-data def 'e-latex info)))
|
||||||
|
;; Retrieve all footnote references within the footnote to add
|
||||||
|
;; their definition after it, since LaTeX doesn't support them
|
||||||
|
;; inside.
|
||||||
|
(let ((all-refs
|
||||||
|
(org-element-map
|
||||||
|
def 'footnote-reference
|
||||||
|
(lambda (ref)
|
||||||
|
(when (org-export-footnote-first-reference-p ref info) ref))
|
||||||
|
info)))
|
||||||
|
(mapconcat
|
||||||
|
(lambda (ref)
|
||||||
|
(format
|
||||||
|
"\\footnotetext[%s]{%s}"
|
||||||
|
(org-export-get-footnote-number ref info)
|
||||||
|
(org-trim
|
||||||
|
(funcall
|
||||||
|
(if (org-element-property :inline-definition ref)
|
||||||
|
'org-export-secondary-string
|
||||||
|
'org-export-data)
|
||||||
|
(org-export-get-footnote-definition ref info) 'e-latex info))))
|
||||||
|
all-refs ""))))))))
|
||||||
|
|
||||||
|
|
||||||
;;;; Headline
|
;;;; Headline
|
||||||
|
|
|
@ -2563,9 +2563,10 @@ entities, export snippets, latex-fragments, subscript and
|
||||||
superscript.")
|
superscript.")
|
||||||
|
|
||||||
(defconst org-element-string-restrictions
|
(defconst org-element-string-restrictions
|
||||||
'((footnote-reference entity export-snippet inline-babel-call inline-src-block
|
'((footnote-reference entity export-snippet footnote-reference
|
||||||
latex-fragment line-break link macro radio-target
|
inline-babel-call inline-src-block latex-fragment
|
||||||
sub/superscript target text-markup time-stamp)
|
line-break link macro radio-target sub/superscript
|
||||||
|
target text-markup time-stamp)
|
||||||
(headline entity inline-babel-call inline-src-block latex-fragment link
|
(headline entity inline-babel-call inline-src-block latex-fragment link
|
||||||
macro radio-target statistics-cookie sub/superscript text-markup
|
macro radio-target statistics-cookie sub/superscript text-markup
|
||||||
time-stamp)
|
time-stamp)
|
||||||
|
|
|
@ -315,3 +315,30 @@ body\n")))
|
||||||
(let ((org-export-filter-parse-tree-functions '(skip-note-head)))
|
(let ((org-export-filter-parse-tree-functions '(skip-note-head)))
|
||||||
(org-test-with-temp-text "* Head1\n* Head2 (note)\n"
|
(org-test-with-temp-text "* Head1\n* Head2 (note)\n"
|
||||||
(should (equal (org-export-as 'test) "* Head1\n")))))))
|
(should (equal (org-export-as 'test) "* Head1\n")))))))
|
||||||
|
|
||||||
|
(ert-deftest test-org-export/footnotes ()
|
||||||
|
"Test footnotes specifications."
|
||||||
|
;; 1. Test nested footnotes.
|
||||||
|
(let ((org-footnote-section nil))
|
||||||
|
(org-test-with-temp-text "
|
||||||
|
Some text[fn:1] and some other text[fn:new:and an inline
|
||||||
|
footnote with another one[fn:label:reference to[fn:1] and a new
|
||||||
|
one[fn:label2:label2]].
|
||||||
|
|
||||||
|
[fn:1] with a footnote inside[fn:inside] and a new footnote [fn:label3:label3].
|
||||||
|
|
||||||
|
[fn:inside] like that."
|
||||||
|
(let* ((tree (org-element-parse-buffer))
|
||||||
|
(info (org-combine-plists
|
||||||
|
(org-export-initial-options) '(:with-footnotes t))))
|
||||||
|
(setq info (org-combine-plists
|
||||||
|
info (org-export-collect-tree-properties tree info 'test)))
|
||||||
|
(let* ((fn-numbers
|
||||||
|
(org-element-map
|
||||||
|
tree 'footnote-reference
|
||||||
|
(lambda (ref)
|
||||||
|
(or (org-export-get-footnote-number ref info) 'unknown)) info)))
|
||||||
|
;; 1.1. Every nested footnote has a number.
|
||||||
|
(should (every 'numberp fn-numbers))
|
||||||
|
;; 1.2. Can tell which are new and which aren't.
|
||||||
|
(should (= (apply 'max fn-numbers) 5)))))))
|
||||||
|
|
Loading…
Reference in New Issue