ox: Correctly handle footnote section

* lisp/ox.el (org-export--collect-headline-numbering): Remove footnote
  section from TOC.
(org-export-collect-headlines): Do not count footnote section when
numbering a headline.
* testing/lisp/test-ox.el: Add tests.
This commit is contained in:
Nicolas Goaziou 2013-02-13 15:51:08 +01:00
parent a6ac2b5fed
commit 39ed70495c
2 changed files with 57 additions and 38 deletions

View File

@ -1795,19 +1795,21 @@ DATA is the parse tree. OPTIONS is the plist holding export
options.
Return an alist whose key is an headline and value is its
associated numbering \(in the shape of a list of numbers\)."
associated numbering \(in the shape of a list of numbers\) or nil
for a footnotes section."
(let ((numbering (make-vector org-export-max-depth 0)))
(org-element-map data 'headline
(lambda (headline)
(let ((relative-level
(1- (org-export-get-relative-level headline options))))
(cons
headline
(loop for n across numbering
for idx from 0 to org-export-max-depth
when (< idx relative-level) collect n
when (= idx relative-level) collect (aset numbering idx (1+ n))
when (> idx relative-level) do (aset numbering idx 0)))))
(unless (org-element-property :footnote-section-p headline)
(let ((relative-level
(1- (org-export-get-relative-level headline options))))
(cons
headline
(loop for n across numbering
for idx from 0 to org-export-max-depth
when (< idx relative-level) collect n
when (= idx relative-level) collect (aset numbering idx (1+ n))
when (> idx relative-level) do (aset numbering idx 0))))))
options)))
(defun org-export--populate-ignore-list (data options)
@ -4434,13 +4436,15 @@ the table of contents. Otherwise, it is set to the value of the
last headline level. See `org-export-headline-levels' for more
information.
Return a list of all exportable headlines as parsed elements."
Return a list of all exportable headlines as parsed elements.
Footnote sections, if any, will be ignored."
(unless (wholenump n) (setq n (plist-get info :headline-levels)))
(org-element-map (plist-get info :parse-tree) 'headline
(lambda (headline)
;; Strip contents from HEADLINE.
(let ((relative-level (org-export-get-relative-level headline info)))
(unless (> relative-level n) headline)))
(unless (org-element-property :footnote-section-p headline)
;; Strip contents from HEADLINE.
(let ((relative-level (org-export-get-relative-level headline info)))
(unless (> relative-level n) headline))))
info))
(defun org-export-collect-elements (type info &optional predicate)

View File

@ -794,29 +794,29 @@ body\n")))
(equal
'((1 . "A\n") (2 . "B") (3 . "C") (4 . "D"))
(org-test-with-parsed-data
"Text[fn:1] [1] [fn:label:C] [fn::D]\n\n[fn:1] A\n\n[1] B"
(org-element-map
tree 'footnote-reference
(lambda (ref)
(let ((def (org-export-get-footnote-definition ref info)))
(cons (org-export-get-footnote-number ref info)
(if (eq (org-element-property :type ref) 'inline) (car def)
(car (org-element-contents
(car (org-element-contents def))))))))
info))))
"Text[fn:1] [1] [fn:label:C] [fn::D]\n\n[fn:1] A\n\n[1] B"
(org-element-map
tree 'footnote-reference
(lambda (ref)
(let ((def (org-export-get-footnote-definition ref info)))
(cons (org-export-get-footnote-number ref info)
(if (eq (org-element-property :type ref) 'inline) (car def)
(car (org-element-contents
(car (org-element-contents def))))))))
info))))
;; 2. Test nested footnotes order.
(org-test-with-parsed-data
"Text[fn:1:A[fn:2]] [fn:3].\n\n[fn:2] B [fn:3] [fn::D].\n\n[fn:3] C."
(should
(equal
'((1 . "fn:1") (2 . "fn:2") (3 . "fn:3") (4))
(org-element-map
tree 'footnote-reference
(lambda (ref)
(when (org-export-footnote-first-reference-p ref info)
(cons (org-export-get-footnote-number ref info)
(org-element-property :label ref))))
info))))
"Text[fn:1:A[fn:2]] [fn:3].\n\n[fn:2] B [fn:3] [fn::D].\n\n[fn:3] C."
(should
(equal
'((1 . "fn:1") (2 . "fn:2") (3 . "fn:3") (4))
(org-element-map
tree 'footnote-reference
(lambda (ref)
(when (org-export-footnote-first-reference-p ref info)
(cons (org-export-get-footnote-number ref info)
(org-element-property :label ref))))
info))))
;; 3. Test nested footnote in invisible definitions.
(org-test-with-temp-text "Text[1]\n\n[1] B [2]\n\n[2] C."
;; Hide definitions.
@ -835,8 +835,8 @@ body\n")))
\[fn:2] B [fn:3] [fn::D].
\[fn:3] C."
(should (= (length (org-export-collect-footnote-definitions tree info))
4)))
(should (= (length (org-export-collect-footnote-definitions tree info))
4)))
;; 5. Test export of footnotes defined outside parsing scope.
(org-test-with-temp-text "[fn:1] Out of scope
* Title
@ -858,7 +858,22 @@ Paragraph[fn:1]"
(should
(org-test-with-parsed-data "[fn:1]"
(org-export-get-footnote-definition
(org-element-map tree 'footnote-reference 'identity info t) info)))))
(org-element-map tree 'footnote-reference 'identity info t) info)))
;; 7. Footnote section should be ignored in TOC and in headlines
;; numbering.
(should
(= 1 (let ((org-footnote-section "Footnotes"))
(length (org-test-with-parsed-data "* H1\n* Footnotes\n"
(org-export-collect-headlines info))))))
(should
(equal '(2)
(let ((org-footnote-section "Footnotes"))
(org-test-with-parsed-data "* H1\n* Footnotes\n* H2"
(org-element-map tree 'headline
(lambda (hl)
(when (equal (org-element-property :raw-value hl) "H2")
(org-export-get-headline-number hl info)))
info t)))))))