Fix links without contents in table of contents' entries

* lisp/ox.el (org-export-toc-entry-backend): New function.

* lisp/ox-html.el (org-html--format-toc-headline):
* lisp/ox-md.el (org-md--build-toc):
* lisp/ox-odt.el (org-odt-toc): Use new function.

* lisp/ox-texinfo.el (org-texinfo--sanitize-title):
(org-texinfo--wrap-float): Handle links without contents.

* testing/lisp/test-ox.el (test-org-export/toc-entry-backend): New
  test.

Reported-by: ConcreteVitamin <concretevitamin@gmail.com>
<http://lists.gnu.org/archive/html/emacs-orgmode/2017-10/msg00235.html>
This commit is contained in:
Nicolas Goaziou 2017-10-14 12:29:52 +02:00
parent 025dbd7f31
commit 827af59873
6 changed files with 127 additions and 36 deletions

View File

@ -2328,15 +2328,7 @@ INFO is a plist used as a communication channel."
(org-element-property :priority headline)))
(text (org-export-data-with-backend
(org-export-get-alt-title headline info)
;; Create an anonymous back-end that will ignore any
;; footnote-reference, link, radio-target and target
;; in table of contents.
(org-export-create-backend
:parent 'html
:transcoders '((footnote-reference . ignore)
(link . (lambda (object c i) c))
(radio-target . (lambda (object c i) c))
(target . ignore)))
(org-export-toc-entry-backend 'html)
info))
(tags (and (eq (plist-get info :with-tags) t)
(org-export-get-tags headline info))))

View File

@ -582,16 +582,7 @@ contents according to the current headline."
(format "[%s](#%s)"
(org-export-data-with-backend
(org-export-get-alt-title headline info)
;; Create an anonymous back-end that will
;; ignore any footnote-reference, link,
;; radio-target and target in table of
;; contents.
(org-export-create-backend
:parent 'md
:transcoders '((footnote-reference . ignore)
(link . (lambda (object c i) c))
(radio-target . (lambda (object c i) c))
(target . ignore)))
(org-export-toc-entry-backend 'md)
info)
(or (org-element-property :CUSTOM_ID headline)
(org-export-get-reference headline info))))

View File

@ -1159,12 +1159,8 @@ table of contents as a string, or nil."
;; Likewise, links, footnote references and regular targets are also
;; suppressed.
(let* ((headlines (org-export-collect-headlines info depth scope))
(backend (org-export-create-backend
:parent (org-export-backend-name (plist-get info :back-end))
:transcoders '((footnote-reference . ignore)
(link . (lambda (object c i) c))
(radio-target . (lambda (object c i) c))
(target . ignore)))))
(backend (org-export-toc-entry-backend
(org-export-backend-name (plist-get info :back-end)))))
(when headlines
(org-odt--format-toc
(and (not scope) (org-export-translate "Table of Contents" :utf-8 info))

View File

@ -499,8 +499,12 @@ export state, as a plist."
(org-export-create-backend
:parent 'texinfo
:transcoders '((footnote-reference . ignore)
(link . (lambda (object c i) c))
(radio-target . (lambda (object c i) c))
(link . (lambda (l c i)
(or c
(org-export-data
(org-element-property :raw-link l)
i))))
(radio-target . (lambda (_r c _i) c))
(target . ignore)))
info))
@ -519,18 +523,27 @@ strings (e.g., returned by `org-export-get-caption')."
(let* ((backend
(org-export-create-backend
:parent 'texinfo
:transcoders '((link . (lambda (object c i) c))
(radio-target . (lambda (object c i) c))
:transcoders '((link . (lambda (l c i)
(or c
(org-export-data
(org-element-property :raw-link l)
i))))
(radio-target . (lambda (_r c _i) c))
(target . ignore))))
(short-backend
(org-export-create-backend
:parent 'texinfo
:transcoders '((footnote-reference . ignore)
(inline-src-block . ignore)
(link . (lambda (object c i) c))
(radio-target . (lambda (object c i) c))
(target . ignore)
(verbatim . ignore))))
:transcoders
'((footnote-reference . ignore)
(inline-src-block . ignore)
(link . (lambda (l c i)
(or c
(org-export-data
(org-element-property :raw-link l)
i))))
(radio-target . (lambda (_r c _i) c))
(target . ignore)
(verbatim . ignore))))
(short-str
(if (and short caption)
(format "@shortcaption{%s}\n"

View File

@ -5176,7 +5176,7 @@ return nil."
info 'first-match)))
;;;; For Tables Of Contents
;;;; For Tables of Contents
;;
;; `org-export-collect-headlines' builds a list of all exportable
;; headline elements, maybe limited to a certain depth. One can then
@ -5186,6 +5186,9 @@ return nil."
;; Once the generic function `org-export-collect-elements' is defined,
;; `org-export-collect-tables', `org-export-collect-figures' and
;; `org-export-collect-listings' can be derived from it.
;;
;; `org-export-toc-entry-backend' builds a special anonymous back-end
;; useful to export table of contents' entries.
(defun org-export-collect-headlines (info &optional n scope)
"Collect headlines in order to build a table of contents.
@ -5271,6 +5274,32 @@ INFO is a plist used as a communication channel.
Return a list of src-block elements with a caption."
(org-export-collect-elements 'src-block info))
(defun org-export-toc-entry-backend (parent &rest transcoders)
"Return an export back-end appropriate for table of contents entries.
PARENT is an export back-end the returned back-end should inherit
from.
By default, the back-end removes footnote references and targets.
It also changes links and radio targets into regular text.
TRANSCODERS optional argument, when non-nil, specifies additional
transcoders. A transcoder follows the pattern (TYPE . FUNCTION)
where type is an element or object type and FUNCTION the function
transcoding it."
(declare (indent 1))
(org-export-create-backend
:parent parent
:transcoders
(append transcoders
`((footnote-reference . ,#'ignore)
(link . ,(lambda (l c i)
(or c
(org-export-data
(org-element-property :raw-link l)
i))))
(radio-target . ,(lambda (_r c _) c))
(target . ,#'ignore)))))
;;;; Smart Quotes
;;

View File

@ -4320,6 +4320,76 @@ Another text. (ref:text)
(let ((scope (org-element-map tree 'headline #'identity info t)))
(length (org-export-collect-headlines info 1 scope)))))))
(ert-deftest test-org-export/toc-entry-backend ()
"Test `org-export-toc-entry-backend' specifications."
;; Ignore targets.
(should
(equal "H \n"
(org-test-with-temp-text "* H <<target>>"
(let (org-export-registered-backends)
(org-export-define-backend 'test
'((headline . (lambda (h _c i) (org-export-data-with-backend
(org-element-property :title h)
(org-export-toc-entry-backend 'test)
i)))))
(org-export-as 'test)))))
;; Ignore footnote references.
(should
(equal "H \n"
(org-test-with-temp-text "[fn:1] Definition\n* H [fn:1]"
(let (org-export-registered-backends)
(org-export-define-backend 'test
'((headline . (lambda (h _c i) (org-export-data-with-backend
(org-element-property :title h)
(org-export-toc-entry-backend 'test)
i)))))
(org-export-as 'test)))))
;; Replace plain links with contents, or with path.
(should
(equal "H Org mode\n"
(org-test-with-temp-text "* H [[http://orgmode.org][Org mode]]"
(let (org-export-registered-backends)
(org-export-define-backend 'test
'((headline . (lambda (h _c i) (org-export-data-with-backend
(org-element-property :title h)
(org-export-toc-entry-backend 'test)
i)))))
(org-export-as 'test)))))
(should
(equal "H http://orgmode.org\n"
(org-test-with-temp-text "* H [[http://orgmode.org]]"
(let (org-export-registered-backends)
(org-export-define-backend 'test
'((headline . (lambda (h _c i) (org-export-data-with-backend
(org-element-property :title h)
(org-export-toc-entry-backend 'test)
i)))))
(org-export-as 'test)))))
;; Replace radio targets with contents.
(should
(equal "H radio\n"
(org-test-with-temp-text "* H <<<radio>>>"
(let (org-export-registered-backends)
(org-export-define-backend 'test
'((headline . (lambda (h _c i) (org-export-data-with-backend
(org-element-property :title h)
(org-export-toc-entry-backend 'test)
i)))))
(org-export-as 'test)))))
;; With optional argument TRANSCODERS, specify other
;; transformations.
(should
(equal "H bold\n"
(org-test-with-temp-text "* H *bold*"
(let (org-export-registered-backends)
(org-export-define-backend 'test
'((headline . (lambda (h _c i) (org-export-data-with-backend
(org-element-property :title h)
(org-export-toc-entry-backend 'test
'(bold . (lambda (_b c _i) c)))
i)))))
(org-export-as 'test))))))
;;; Templates