diff --git a/pkgs/tools/nix/nixos-render-docs/src/nixos_render_docs/docbook.py b/pkgs/tools/nix/nixos-render-docs/src/nixos_render_docs/docbook.py
index 39ce50cc0421..3050093a5bd5 100644
--- a/pkgs/tools/nix/nixos-render-docs/src/nixos_render_docs/docbook.py
+++ b/pkgs/tools/nix/nixos-render-docs/src/nixos_render_docs/docbook.py
@@ -1,6 +1,6 @@
from collections.abc import Mapping, MutableMapping, Sequence
from frozendict import frozendict # type: ignore[attr-defined]
-from typing import Any, cast, Optional
+from typing import Any, cast, Optional, NamedTuple
import markdown_it
from markdown_it.token import Token
@@ -25,16 +25,27 @@ def make_xml_id(s: str) -> str:
class Deflist:
has_dd = False
+class Heading(NamedTuple):
+ container_tag: str
+ level: int
+
class DocBookRenderer(Renderer):
__output__ = "docbook"
_link_tags: list[str]
_deflists: list[Deflist]
+ _headings: list[Heading]
def __init__(self, manpage_urls: Mapping[str, str], parser: Optional[markdown_it.MarkdownIt] = None):
super().__init__(manpage_urls, parser)
self._link_tags = []
self._deflists = []
+ self._headings = []
+ def render(self, tokens: Sequence[Token], options: OptionsDict,
+ env: MutableMapping[str, Any]) -> str:
+ result = super().render(tokens, options, env)
+ result += self._close_headings(None, env)
+ return result
def renderInline(self, tokens: Sequence[Token], options: OptionsDict,
env: MutableMapping[str, Any]) -> str:
# HACK to support docbook links and xrefs. link handling is only necessary because the docbook
@@ -203,3 +214,36 @@ class DocBookRenderer(Renderer):
def inline_anchor(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
env: MutableMapping[str, Any]) -> str:
return f''
+ def ordered_list_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
+ env: MutableMapping[str, Any]) -> str:
+ start = f' startingnumber="{token.attrs["start"]}"' if 'start' in token.attrs else ""
+ return f""
+ def ordered_list_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
+ env: MutableMapping[str, Any]) -> str:
+ return f""
+ def heading_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
+ env: MutableMapping[str, Any]) -> str:
+ hlevel = int(token.tag[1:])
+ result = self._close_headings(hlevel, env)
+ (tag, attrs) = self._heading_tag(token, tokens, i, options, env)
+ self._headings.append(Heading(tag, hlevel))
+ attrs_str = "".join([ f" {k}={quoteattr(v)}" for k, v in attrs.items() ])
+ return result + f'<{tag}{attrs_str}>\n
'
+ def heading_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
+ env: MutableMapping[str, Any]) -> str:
+ return ''
+
+ def _close_headings(self, level: Optional[int], env: MutableMapping[str, Any]) -> str:
+ # we rely on markdown-it producing h{1..6} tags in token.tag for this to work
+ result = []
+ while len(self._headings):
+ if level is None or self._headings[-1].level >= level:
+ result.append(f"{self._headings[-1].container_tag}>")
+ self._headings.pop()
+ else:
+ break
+ return "\n".join(result)
+
+ def _heading_tag(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
+ env: MutableMapping[str, Any]) -> tuple[str, dict[str, str]]:
+ return ("section", {})
diff --git a/pkgs/tools/nix/nixos-render-docs/src/nixos_render_docs/md.py b/pkgs/tools/nix/nixos-render-docs/src/nixos_render_docs/md.py
index 3f4aa7c47679..7aaa56031a3e 100644
--- a/pkgs/tools/nix/nixos-render-docs/src/nixos_render_docs/md.py
+++ b/pkgs/tools/nix/nixos-render-docs/src/nixos_render_docs/md.py
@@ -64,6 +64,10 @@ class Renderer(markdown_it.renderer.RendererProtocol):
"container_admonition_open": self.admonition_open,
"container_admonition_close": self.admonition_close,
"inline_anchor": self.inline_anchor,
+ "heading_open": self.heading_open,
+ "heading_close": self.heading_close,
+ "ordered_list_open": self.ordered_list_open,
+ "ordered_list_close": self.ordered_list_close,
}
self._admonitions = {
@@ -218,6 +222,18 @@ class Renderer(markdown_it.renderer.RendererProtocol):
def inline_anchor(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
env: MutableMapping[str, Any]) -> str:
raise RuntimeError("md token not supported", token)
+ def heading_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
+ env: MutableMapping[str, Any]) -> str:
+ raise RuntimeError("md token not supported", token)
+ def heading_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
+ env: MutableMapping[str, Any]) -> str:
+ raise RuntimeError("md token not supported", token)
+ def ordered_list_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
+ env: MutableMapping[str, Any]) -> str:
+ raise RuntimeError("md token not supported", token)
+ def ordered_list_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
+ env: MutableMapping[str, Any]) -> str:
+ raise RuntimeError("md token not supported", token)
def _is_escaped(src: str, pos: int) -> bool:
found = 0
diff --git a/pkgs/tools/nix/nixos-render-docs/src/nixos_render_docs/options.py b/pkgs/tools/nix/nixos-render-docs/src/nixos_render_docs/options.py
index d165a5937091..839f29d43704 100644
--- a/pkgs/tools/nix/nixos-render-docs/src/nixos_render_docs/options.py
+++ b/pkgs/tools/nix/nixos-render-docs/src/nixos_render_docs/options.py
@@ -2,6 +2,9 @@ import argparse
import json
from abc import abstractmethod
+from collections.abc import MutableMapping, Sequence
+from markdown_it.utils import OptionsDict
+from markdown_it.token import Token
from typing import Any, Optional
from xml.sax.saxutils import escape, quoteattr
@@ -145,8 +148,16 @@ class BaseConverter(Converter):
@abstractmethod
def finalize(self) -> str: raise NotImplementedError()
+class OptionsDocBookRenderer(DocBookRenderer):
+ def heading_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
+ env: MutableMapping[str, Any]) -> str:
+ raise RuntimeError("md token not supported in options doc", token)
+ def heading_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
+ env: MutableMapping[str, Any]) -> str:
+ raise RuntimeError("md token not supported in options doc", token)
+
class DocBookConverter(BaseConverter):
- __renderer__ = DocBookRenderer
+ __renderer__ = OptionsDocBookRenderer
def _render_code(self, option: dict[str, Any], key: str) -> list[str]:
if lit := option_is(option, key, 'literalDocBook'):
diff --git a/pkgs/tools/nix/nixos-render-docs/src/tests/test_options.py b/pkgs/tools/nix/nixos-render-docs/src/tests/test_options.py
new file mode 100644
index 000000000000..5a02fabde0fb
--- /dev/null
+++ b/pkgs/tools/nix/nixos-render-docs/src/tests/test_options.py
@@ -0,0 +1,14 @@
+import nixos_render_docs
+
+from markdown_it.token import Token
+import pytest
+
+def test_option_headings() -> None:
+ c = nixos_render_docs.options.DocBookConverter({}, 'local', 'none', 'vars', 'opt-', False)
+ with pytest.raises(RuntimeError) as exc:
+ c._render("# foo")
+ assert exc.value.args[0] == 'md token not supported in options doc'
+ assert exc.value.args[1] == Token(
+ type='heading_open', tag='h1', nesting=1, attrs={}, map=[0, 1], level=0, children=None,
+ content='', markup='#', info='', meta={}, block=True, hidden=False
+ )