nixos-render-docs: add example blocks

this is currently only supported by the docbook exporter, and even the
docbook exporter doesn't do much with them. we mirror the conversion
pandoc did for consistency with the previous manual chapter conversion,
which is to add just an anchor with the given id. future exporters that
go directly to html might want to do more.
This commit is contained in:
pennae 2023-02-08 09:37:34 +01:00
parent bb6526e0de
commit b59b0230ae
3 changed files with 52 additions and 1 deletions

View File

@ -252,6 +252,14 @@ class DocBookRenderer(Renderer):
def heading_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
env: MutableMapping[str, Any]) -> str:
return '</title>'
def example_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
env: MutableMapping[str, Any]) -> str:
if id := token.attrs.get('id'):
return f"<anchor xml:id={quoteattr(cast(str, id))} />"
return ""
def example_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

View File

@ -28,7 +28,7 @@ _md_escape_table = {
def md_escape(s: str) -> str:
return s.translate(_md_escape_table)
AttrBlockKind = Literal['admonition']
AttrBlockKind = Literal['admonition', 'example']
AdmonitionKind = Literal["note", "caution", "tip", "important", "warning"]
@ -74,6 +74,8 @@ class Renderer(markdown_it.renderer.RendererProtocol):
"heading_close": self.heading_close,
"ordered_list_open": self.ordered_list_open,
"ordered_list_close": self.ordered_list_close,
"example_open": self.example_open,
"example_close": self.example_close,
}
self._admonitions = {
@ -248,6 +250,12 @@ class Renderer(markdown_it.renderer.RendererProtocol):
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 example_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
env: MutableMapping[str, Any]) -> str:
raise RuntimeError("md token not supported", token)
def example_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
@ -288,6 +296,8 @@ def _parse_blockattrs(info: str) -> Optional[tuple[AttrBlockKind, Optional[str],
if id is not None:
return None
return ('admonition', id, classes)
if classes == ['example']:
return ('example', id, classes)
return None
def _attr_span_plugin(md: markdown_it.MarkdownIt) -> None:
@ -432,6 +442,11 @@ def _block_attr(md: markdown_it.MarkdownIt) -> None:
token.type = 'admonition_open'
token.meta['kind'] = classes[0]
stack.append('admonition_close')
elif kind == 'example':
token.type = 'example_open'
if id is not None:
token.attrs['id'] = id
stack.append('example_close')
else:
assert_never(kind)
elif token.type == 'container_blockattr_close':

View File

@ -422,3 +422,31 @@ def test_admonitions() -> None:
Token(type='admonition_close', tag='div', nesting=-1, attrs={}, map=None, level=0,
children=None, content='', markup=':::', info='', meta={}, block=True, hidden=False)
]
def test_example() -> None:
c = Converter({})
assert c._parse("::: {.example}") == [
Token(type='example_open', tag='div', nesting=1, attrs={}, map=[0, 1], level=0, children=None,
content='', markup=':::', info=' {.example}', meta={}, block=True, hidden=False),
Token(type='example_close', tag='div', nesting=-1, attrs={}, map=None, level=0, children=None,
content='', markup=':::', info='', meta={}, block=True, hidden=False)
]
assert c._parse("::: {#eid .example}") == [
Token(type='example_open', tag='div', nesting=1, attrs={'id': 'eid'}, map=[0, 1], level=0,
children=None, content='', markup=':::', info=' {#eid .example}', meta={}, block=True,
hidden=False),
Token(type='example_close', tag='div', nesting=-1, attrs={}, map=None, level=0, children=None,
content='', markup=':::', info='', meta={}, block=True, hidden=False)
]
assert c._parse("::: {.example .note}") == [
Token(type='paragraph_open', tag='p', nesting=1, attrs={}, map=[0, 1], level=0, children=None,
content='', markup='', info='', meta={}, block=True, hidden=False),
Token(type='inline', tag='', nesting=0, attrs={}, map=[0, 1], level=1,
content='::: {.example .note}', markup='', info='', meta={}, block=True, hidden=False,
children=[
Token(type='text', tag='', nesting=0, attrs={}, map=None, level=0, children=None,
content='::: {.example .note}', markup='', info='', meta={}, block=False, hidden=False)
]),
Token(type='paragraph_close', tag='p', nesting=-1, attrs={}, map=None, level=0, children=None,
content='', markup='', info='', meta={}, block=True, hidden=False)
]