diff --git a/contrib/lisp/ox-groff.el b/contrib/lisp/ox-groff.el
index 1a15eca4d..9475a9fa8 100644
--- a/contrib/lisp/ox-groff.el
+++ b/contrib/lisp/ox-groff.el
@@ -1259,7 +1259,7 @@ INFO is a plist holding contextual information. See
;; description.
((string= type "radio")
(let ((destination (org-export-resolve-radio-link link info)))
- (when destination
+ (if (not destination) desc
(format "\\fI [%s] \\fP"
(org-export-solidify-link-text
(org-element-property :value destination))))))
diff --git a/lisp/ox-beamer.el b/lisp/ox-beamer.el
index b41548159..68a0479e5 100644
--- a/lisp/ox-beamer.el
+++ b/lisp/ox-beamer.el
@@ -681,7 +681,7 @@ used as a communication channel."
(cond
((equal type "radio")
(let ((destination (org-export-resolve-radio-link link info)))
- (when destination
+ (if (not destination) contents
(format "\\hyperlink%s{%s}{%s}"
(or (org-beamer--element-has-overlay-p link) "")
(org-export-solidify-link-text
diff --git a/lisp/ox-html.el b/lisp/ox-html.el
index eef4f5a63..822299bd8 100644
--- a/lisp/ox-html.el
+++ b/lisp/ox-html.el
@@ -2771,7 +2771,7 @@ INFO is a plist holding contextual information. See
;; link's description.
((string= type "radio")
(let ((destination (org-export-resolve-radio-link link info)))
- (when destination
+ (if (not destination) desc
(format "%s"
(org-export-solidify-link-text
(org-element-property :value destination))
diff --git a/lisp/ox-latex.el b/lisp/ox-latex.el
index 64c85eb47..478d5d405 100644
--- a/lisp/ox-latex.el
+++ b/lisp/ox-latex.el
@@ -1934,7 +1934,7 @@ INFO is a plist holding contextual information. See
;; description.
((string= type "radio")
(let ((destination (org-export-resolve-radio-link link info)))
- (when destination
+ (if (not destination) desc
(format "\\hyperref[%s]{%s}"
(org-export-solidify-link-text
(org-element-property :value destination))
diff --git a/lisp/ox-odt.el b/lisp/ox-odt.el
index adbb59617..26ed8725d 100644
--- a/lisp/ox-odt.el
+++ b/lisp/ox-odt.el
@@ -2741,7 +2741,7 @@ INFO is a plist holding contextual information. See
;; link's description.
((string= type "radio")
(let ((destination (org-export-resolve-radio-link link info)))
- (when destination
+ (if (not destination) desc
(format
"%s"
(org-export-solidify-link-text
diff --git a/lisp/ox-texinfo.el b/lisp/ox-texinfo.el
index 4677e5665..5927b3a04 100644
--- a/lisp/ox-texinfo.el
+++ b/lisp/ox-texinfo.el
@@ -451,18 +451,23 @@ INFO is a plist used as a communication channel. See
;; Else use format string.
(t (format fmt text)))))
-(defun org-texinfo--get-node (headline info)
- "Return node entry associated to HEADLINE.
-INFO is a plist used as a communication channel. The function
-guarantees the node name is unique."
+(defun org-texinfo--get-node (blob info)
+ "Return node or anchor associated to BLOB.
+BLOB is an element or object. INFO is a plist used as
+a communication channel. The function guarantees the node or
+anchor name is unique."
(let ((cache (plist-get info :texinfo-node-cache)))
- (or (cdr (assq headline cache))
- (let ((name (org-texinfo--sanitize-node
- (org-export-data
- (org-export-get-alt-title headline info) info))))
+ (or (cdr (assq blob cache))
+ (let ((name
+ (org-texinfo--sanitize-node
+ (case (org-element-type blob)
+ (headline
+ (org-export-data (org-export-get-alt-title blob info) info))
+ ((radio-target target) (org-element-property :value blob))
+ (otherwise (or (org-element-property :name blob) ""))))))
;; Ensure NAME is unique.
(while (rassoc name cache) (setq name (concat name "x")))
- (plist-put info :texinfo-node-cache (cons (cons headline name) cache))
+ (plist-put info :texinfo-node-cache (cons (cons blob name) cache))
name))))
;;;; Menu sanitizing
@@ -483,7 +488,7 @@ are not significant. Also remove the following characters: @
(defun org-texinfo--sanitize-content (text)
"Escape special characters in string TEXT.
Special characters are: @ { }"
- (replace-regexp-in-string "\\\([@{}]\\\)" "@\\1" text))
+ (replace-regexp-in-string "[@{}]" "@\\&" text))
;;; Template
@@ -904,55 +909,69 @@ INFO is a plist holding contextual information. See
((and (string= type "file") (file-name-absolute-p raw-path))
(concat "file:" raw-path))
(t raw-path)))
- (email (if (string= type "mailto")
- (let ((text (replace-regexp-in-string
- "@" "@@" raw-path)))
- (concat text (if desc (concat "," desc))))))
protocol)
(cond
- ;; Links pointing to a headline: Find destination and build
- ;; appropriate referencing command.
- ((member type '("custom-id" "id"))
- (let ((destination (org-export-resolve-id-link link info)))
+ ((equal type "radio")
+ (let ((destination (org-export-resolve-radio-link link info)))
+ (if (not destination) desc
+ (format "@ref{%s,,%s}"
+ (org-texinfo--get-node destination info)
+ desc))))
+ ((member type '("custom-id" "id" "fuzzy"))
+ (let ((destination
+ (if (equal type "fuzzy")
+ (org-export-resolve-fuzzy-link link info)
+ (org-export-resolve-id-link link info))))
(case (org-element-type destination)
+ ((nil)
+ (format org-texinfo-link-with-unknown-path-format
+ (org-texinfo--sanitize-content path)))
;; Id link points to an external file.
(plain-text
(if desc (format "@uref{file://%s,%s}" destination desc)
(format "@uref{file://%s}" destination)))
- ;; LINK points to a headline. Use the headline as the NODE target
(headline
(format "@ref{%s,%s}"
(org-texinfo--get-node destination info)
- (or desc "")))
+ (cond
+ (desc)
+ ((org-export-numbered-headline-p destination info)
+ (org-export-data
+ (org-element-property :title destination) info))
+ (t
+ (mapconcat
+ #'number-to-string
+ (org-export-get-headline-number destination info) ".")))))
(otherwise
- (let ((path (org-export-solidify-link-text path)))
- (if (not desc) (format "@ref{%s}" path)
- (format "@ref{%s,,%s}" path desc)))))))
- ((member type '("info"))
+ (let ((topic
+ (or desc
+ (if (and (eq (org-element-type destination) 'headline)
+ (not (org-export-numbered-headline-p
+ destination info)))
+ (org-export-data
+ (org-element-property :title destination) info))
+ (let ((n (org-export-get-ordinal destination info)))
+ (cond
+ ((not n) nil)
+ ((integerp n) n)
+ (t (mapconcat #'number-to-string n ".")))))))
+ (when topic
+ (format "@ref{%s,,%s}"
+ (org-texinfo--get-node destination info)
+ topic)))))))
+ ((equal type "info")
(let* ((info-path (split-string path "[:#]"))
(info-manual (car info-path))
(info-node (or (cadr info-path) "top"))
(title (or desc "")))
(format "@ref{%s,%s,,%s,}" info-node title info-manual)))
- ((member type '("fuzzy"))
- (let ((destination (org-export-resolve-fuzzy-link link info)))
- (case (org-element-type destination)
- ;; Id link points to an external file.
- (plain-text
- (if desc (format "@uref{file://%s,%s}" destination desc)
- (format "@uref{file://%s}" destination)))
- ;; LINK points to a headline. Use the headline as the NODE target
- (headline
- (format "@ref{%s,%s}"
- (org-texinfo--get-node destination info)
- (or desc "")))
- (otherwise
- (let ((path (org-export-solidify-link-text path)))
- (if (not desc) (format "@ref{%s}" path)
- (format "@ref{%s,,%s}" path desc)))))))
- ;; Special case for email addresses
- (email
- (format "@email{%s}" email))
+ ((string= type "mailto")
+ (format "@email{%s}"
+ (concat (org-texinfo--sanitize-content path)
+ (and desc (concat "," desc)))))
+ ((let ((protocol (nth 2 (assoc type org-link-protocols))))
+ (and (functionp protocol)
+ (funcall protocol (org-link-unescape path) desc 'texinfo))))
;; External link with a description part.
((and path desc) (format "@uref{%s,%s}" path desc))
;; External link without a description part.