branch: externals/org commit 332695e8501dfffc02a2a78811f2969e566772f2 Author: Yue Yi <include...@qq.com> Commit: Ihor Radchenko <yanta...@posteo.net>
ox-html: Fix TOC generation for non-toplevel headlines * lisp/ox-html.el (org-html--toc-text): Correctly set initial level based on scope argument and improve docstring. * lisp/ox-html.el (org-html-toc): Pass scope argument to helper function. * testing/lisp/test-ox-html.el (org-html/test-toc-text): New tests for TOC generation. When exporting a document that starts with a headline of level > 1 (e.g., no top-level headline), the HTML table of contents was rendered incorrectly. This was caused by `org-html--toc-text' calculating the initial nesting level based on the first headline's level, which is incorrect for a global TOC that should always start from a base level of 0. This commit adjusts `org-html--toc-text' to correctly handle this by checking its optional `scope' argument. --- lisp/ox-html.el | 11 +++++++---- testing/lisp/test-ox-html.el | 17 +++++++++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/lisp/ox-html.el b/lisp/ox-html.el index 818bb127cd..2f014de915 100644 --- a/lisp/ox-html.el +++ b/lisp/ox-html.el @@ -2519,7 +2519,7 @@ of contents as a string, or nil if it is empty." (let* ((toc-id-counter (plist-get info :org-html--toc-counter)) (toc (concat (format "<div id=\"text-table-of-contents%s\" role=\"doc-toc\">" (if toc-id-counter (format "-%d" toc-id-counter) "")) - (org-html--toc-text toc-entries) + (org-html--toc-text toc-entries scope) "</div>\n"))) (plist-put info :org-html--toc-counter (1+ (or toc-id-counter 0))) (if scope toc @@ -2537,11 +2537,14 @@ of contents as a string, or nil if it is empty." toc (format "</%s>\n" outer-tag)))))))) -(defun org-html--toc-text (toc-entries) +(defun org-html--toc-text (toc-entries &optional scope) "Return innards of a table of contents, as a string. + TOC-ENTRIES is an alist where key is an entry title, as a string, -and value is its relative level, as an integer." - (let* ((prev-level (1- (cdar toc-entries))) +and value is its relative level, as an integer. Optional SCOPE, +when non-nil, indicates a TOC for a subtree, which affects the +initial nesting level." + (let* ((prev-level (if scope (1- (cdar toc-entries)) 0)) (start-level prev-level)) (concat (mapconcat diff --git a/testing/lisp/test-ox-html.el b/testing/lisp/test-ox-html.el index fdd40ae982..679d89d22b 100644 --- a/testing/lisp/test-ox-html.el +++ b/testing/lisp/test-ox-html.el @@ -1089,5 +1089,22 @@ entirely." "abcdefg\n")) (should (= (org-html-normalize-string-or-function 123 nil) 123))) + +;;; Rendering Table of Contents list + +(ert-deftest org-html/test-toc-text () + "Test the generation of HTML TOC lists by `org-html--toc-text'." + ;; Test 1: Standard TOC (scope is nil) + (let ((toc-entries '(("1" . 1) ("1.1" . 2) ("2" . 1))) + (expected "\n<ul>\n<li>1\n<ul>\n<li>1.1</li>\n</ul>\n</li>\n<li>2</li>\n</ul>\n")) + (should (string= (org-html--toc-text toc-entries nil) expected))) + ;; Test 2: TOC starting with a non-toplevel headline. + ;; This case, specific to a global TOC (scope is nil), checks + ;; if the function correctly wraps the output in outer lists + ;; to represent the skipped headline levels. + (let ((toc-entries '(("1" . 2) ("1.1" . 3) ("2" . 1))) + (expected "\n<ul>\n<li>\n<ul>\n<li>1\n<ul>\n<li>1.1</li>\n</ul>\n</li>\n</ul>\n</li>\n<li>2</li>\n</ul>\n")) + (should (string= (org-html--toc-text toc-entries nil) expected)))) + (provide 'test-ox-html) ;;; test-ox-html.el ends here