Howdy, fellow Org hackers! This is a follow-up to my Git patch 4247798db, where I added support for links in Org headings exported via Texinfo.
I found that links in node-level constructs break Texinfo HTML menus: the inner (user-specific) link works but the outer (menu-specific) link does not, rendering the menu item unusable. Ouch! Links in other headings, specifically those exported as Texinfo list items, have no such problem, and those are super-important to have. I updated the code so that all title and TOC links are sanitized properly and everything works smoothly. Please see the attached patch. Thank you! Rudy
>From 4247798dbd360112119135a328b7b82d5395dbed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rudolf=20Adamkovi=C4=8D?= <rud...@adamkovic.org> Date: Sun, 16 Feb 2025 23:23:08 +0100 Subject: [PATCH] ox-texinfo: Sanitize links in headings to avoid broken Texinfo menus * lisp/ox-texinfo.el (org-texinfo-headline): Sanitize links in the titles of heading exported as chapters, sections, and the like, as they break Texinfo menus. (org-texinfo--build-menu): Sanitize TOC headings and rename `h' to `headline' to harmonize with `ox-html'. * testing/lisp/test-ox-texinfo.el (test-ox-texinfo/headings-with-links): Update the relevant test. --- lisp/ox-texinfo.el | 18 ++++++++++----- testing/lisp/test-ox-texinfo.el | 40 ++++++++++++++++++++++----------- 2 files changed, 39 insertions(+), 19 deletions(-) diff --git a/lisp/ox-texinfo.el b/lisp/ox-texinfo.el index 639d68443..866f1feaf 100644 --- a/lisp/ox-texinfo.el +++ b/lisp/ox-texinfo.el @@ -1132,8 +1132,11 @@ holding contextual information." (org-export-get-tags headline info))) (priority (and (plist-get info :with-priority) (org-element-property :priority headline))) - (text (org-texinfo--sanitize-title - (org-element-property :title headline) info)) + (text (funcall (if command + #'org-texinfo--sanitize-title-reference + #'org-texinfo--sanitize-title) + (org-element-property :title headline) + info)) (full-text (funcall (plist-get info :texinfo-format-headline-function) todo todo-type priority text tags)) @@ -1482,14 +1485,17 @@ is an integer, build the menu recursively, down to this depth." ((zerop level) "\n") (t (mapconcat - (lambda (h) - (let ((entries (org-texinfo--menu-entries h info))) + (lambda (headline) + (let ((entries (org-texinfo--menu-entries headline info))) (when entries (concat (format "%s\n\n%s\n" - (org-export-data (org-export-get-alt-title h info) info) + (org-export-data-with-backend + (org-export-get-alt-title headline info) + (org-export-toc-entry-backend 'texinfo) + info) (org-texinfo--format-entries entries info)) - (org-texinfo--build-menu h info (1- level)))))) + (org-texinfo--build-menu headline info (1- level)))))) (org-texinfo--menu-entries scope info) "")))) diff --git a/testing/lisp/test-ox-texinfo.el b/testing/lisp/test-ox-texinfo.el index 77605dccd..df176fbc2 100644 --- a/testing/lisp/test-ox-texinfo.el +++ b/testing/lisp/test-ox-texinfo.el @@ -428,14 +428,18 @@ body ;;; Headings with links (ert-deftest test-ox-texinfo/headings-with-links () - "Test node and chapter names." + "Test links are removed from headings conditionally. + +Headings exported as chapters, sections, and subsections must not +contain links in their titles, for such links break Texinfo menus. +Headings exported as list items have no such problem." (should (org-test-with-temp-text (string-join - (list "* Heading 1" - " ...." - "* Heading 2 ([[* Heading 1][Heading 1]])" - " ....") + (list "* Chapter [[https://example.com][Example]]" + "** Section [[https://example.com][Example]]" + "*** Subsection [[https://example.com][Example]]" + "**** Item [[https://example.com][Example]]") "\n") (let ((export-buffer "*Test Texinfo Export*") (org-export-show-temporary-export-buffer nil)) @@ -445,14 +449,24 @@ body (with-current-buffer export-buffer (goto-char (point-min)) (and - (re-search-forward "^* Heading 1::$") - (re-search-forward "^* Heading 2 (Heading 1)::$") - (re-search-forward "^@node Heading 1$") - (re-search-forward "^@chapter Heading 1$") - (re-search-forward "^@node Heading 2 (Heading 1)$") - (re-search-forward - "^@chapter Heading 2 (@ref{Heading 1, , Heading 1})$"))))))) - + (re-search-forward "^@menu$") + (re-search-forward "^\\* Chapter Example::$") + (re-search-forward "^Chapter Example$") + (re-search-forward "^\\* Section Example::$") + (re-search-forward "^Section Example$") + (re-search-forward "^\\* Subsection Example::$") + (re-search-forward "^@node Chapter Example$") + (re-search-forward "^@chapter Chapter Example$") + (re-search-forward "^@menu$") + (re-search-forward "^\\* Section Example::$") + (re-search-forward "^@node Section Example$") + (re-search-forward "^@section Section Example$") + (re-search-forward "^@menu$") + (re-search-forward "^\\* Subsection Example::$") + (re-search-forward "^@node Subsection Example$") + (re-search-forward "^@subsection Subsection Example$") + (re-search-forward "^@item$") + (re-search-forward "^@anchor{Item Example}Item @uref{https://example.com, Example}$"))))))) ;;; Definitions -- 2.39.5 (Apple Git-154)
-- "I do not fear death. I had been dead for billions and billions of years before I was born, and had not suffered the slightest inconvenience from it." --- Mark Twain, paraphrased Rudolf Adamkovič <rud...@adamkovic.org> [he/him] http://adamkovic.org