Hello, Org-mode maintainers,

ox-html can emit <h7>, <h8>, ... for deep headlines, which is invalid
HTML: the specification defines only <h1> through <h6>.  This happens
when :headline-levels is set high enough that org-export-low-level-p no
longer routes a headline to the list-item branch, while the computed
heading level is still above 6.

------------------------------->8<-------------------------------
(require 'ox-html)
(princ
 (org-export-string-as
  "* a\n** b\n*** c\n**** d\n***** e\n****** f\n"
  'html t
  '(:html-toplevel-hlevel 2 :headline-levels 6)))
------------------------------->8<-------------------------------

The heading tags emitted are:
<h2> <h3> <h4> <h5> <h6> <h7>

<h7> is not expected.

In org-html-headline the heading level is computed as

(level (+ (org-export-get-relative-level headline info)
          (1- (plist-get info :html-toplevel-hlevel))))

and used directly in the `<h%d>` format, without being capped at 6.  The
decision to render a headline as a list item uses org-export-low-level-p,
which only compares the *relative* level against :headline-levels and
does not account for the <h6> upper bound. So whenever

:headline-levels  >  7 - :html-toplevel-hlevel

a headline can satisfy relative <= :headline-levels (hence not be
low-level) while relative + :html-toplevel-hlevel - 1 > 6, producing
<h7> or deeper.  With the defaults (:headline-levels 3, :html-toplevel-hlevel 2)
the document is safe; the bug is reachable by setting :headline-levels
to 6 or more (with the default :html-toplevel-hlevel).

Treat a headline whose heading level exceeds 6 as low-level, in addition
to org-export-low-level-p, can solve this problem.  This keeps the
output within <h1>-<h6> and reuses the existing list-item rendering for
the overflow.  A patch is attached.

Regards.

Attachment: 0001-lisp-ox-html.el-Do-not-emit-headings-deeper-than-h6.patch
Description: Binary data

Reply via email to