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.