nixos-render-docs: drop options, env parameters
these weren't used for anything. options never was (and does not contain any information for the renderer that we *want* to honor), and env is not used because typed renderer state is much more useful for all our cases.
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
from collections.abc import Mapping, MutableMapping, Sequence
|
from collections.abc import Mapping, Sequence
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Any, cast, Optional
|
from typing import Any, cast, Optional
|
||||||
from urllib.parse import quote
|
from urllib.parse import quote
|
||||||
@@ -6,7 +6,6 @@ from urllib.parse import quote
|
|||||||
from .md import Renderer
|
from .md import Renderer
|
||||||
|
|
||||||
from markdown_it.token import Token
|
from markdown_it.token import Token
|
||||||
from markdown_it.utils import OptionsDict
|
|
||||||
|
|
||||||
_asciidoc_escapes = {
|
_asciidoc_escapes = {
|
||||||
# escape all dots, just in case one is pasted at SOL
|
# escape all dots, just in case one is pasted at SOL
|
||||||
@@ -95,142 +94,103 @@ class AsciiDocRenderer(Renderer):
|
|||||||
self._list_stack.pop()
|
self._list_stack.pop()
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
def text(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def text(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._parstack[-1].continuing = True
|
self._parstack[-1].continuing = True
|
||||||
return asciidoc_escape(token.content)
|
return asciidoc_escape(token.content)
|
||||||
def paragraph_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def paragraph_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._break()
|
return self._break()
|
||||||
def paragraph_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def paragraph_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return ""
|
return ""
|
||||||
def hardbreak(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def hardbreak(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return " +\n"
|
return " +\n"
|
||||||
def softbreak(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def softbreak(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return f" "
|
return f" "
|
||||||
def code_inline(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def code_inline(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._parstack[-1].continuing = True
|
self._parstack[-1].continuing = True
|
||||||
return f"``{asciidoc_escape(token.content)}``"
|
return f"``{asciidoc_escape(token.content)}``"
|
||||||
def code_block(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def code_block(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
return self.fence(token, tokens, i)
|
||||||
return self.fence(token, tokens, i, options, env)
|
def link_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
def link_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._parstack[-1].continuing = True
|
self._parstack[-1].continuing = True
|
||||||
return f"link:{quote(cast(str, token.attrs['href']), safe='/:')}["
|
return f"link:{quote(cast(str, token.attrs['href']), safe='/:')}["
|
||||||
def link_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def link_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return "]"
|
return "]"
|
||||||
def list_item_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def list_item_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._enter_block(True)
|
self._enter_block(True)
|
||||||
# allow the next token to be a block or an inline.
|
# allow the next token to be a block or an inline.
|
||||||
return f'\n{self._list_stack[-1].head} {{empty}}'
|
return f'\n{self._list_stack[-1].head} {{empty}}'
|
||||||
def list_item_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def list_item_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._leave_block()
|
self._leave_block()
|
||||||
return "\n"
|
return "\n"
|
||||||
def bullet_list_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def bullet_list_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._list_open(token, '*')
|
return self._list_open(token, '*')
|
||||||
def bullet_list_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def bullet_list_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._list_close()
|
return self._list_close()
|
||||||
def em_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def em_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return "__"
|
return "__"
|
||||||
def em_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def em_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return "__"
|
return "__"
|
||||||
def strong_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def strong_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return "**"
|
return "**"
|
||||||
def strong_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def strong_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return "**"
|
return "**"
|
||||||
def fence(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def fence(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
attrs = f"[source,{token.info}]\n" if token.info else ""
|
attrs = f"[source,{token.info}]\n" if token.info else ""
|
||||||
code = token.content
|
code = token.content
|
||||||
if code.endswith('\n'):
|
if code.endswith('\n'):
|
||||||
code = code[:-1]
|
code = code[:-1]
|
||||||
return f"{self._break(True)}{attrs}----\n{code}\n----"
|
return f"{self._break(True)}{attrs}----\n{code}\n----"
|
||||||
def blockquote_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def blockquote_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
pbreak = self._break(True)
|
pbreak = self._break(True)
|
||||||
self._enter_block(False)
|
self._enter_block(False)
|
||||||
return f"{pbreak}[quote]\n{self._parstack[-2].block_delim}\n"
|
return f"{pbreak}[quote]\n{self._parstack[-2].block_delim}\n"
|
||||||
def blockquote_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def blockquote_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._leave_block()
|
self._leave_block()
|
||||||
return f"\n{self._parstack[-1].block_delim}"
|
return f"\n{self._parstack[-1].block_delim}"
|
||||||
def note_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def note_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._admonition_open("NOTE")
|
return self._admonition_open("NOTE")
|
||||||
def note_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def note_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._admonition_close()
|
return self._admonition_close()
|
||||||
def caution_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def caution_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._admonition_open("CAUTION")
|
return self._admonition_open("CAUTION")
|
||||||
def caution_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def caution_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._admonition_close()
|
return self._admonition_close()
|
||||||
def important_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def important_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._admonition_open("IMPORTANT")
|
return self._admonition_open("IMPORTANT")
|
||||||
def important_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def important_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._admonition_close()
|
return self._admonition_close()
|
||||||
def tip_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def tip_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._admonition_open("TIP")
|
return self._admonition_open("TIP")
|
||||||
def tip_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def tip_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._admonition_close()
|
return self._admonition_close()
|
||||||
def warning_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def warning_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._admonition_open("WARNING")
|
return self._admonition_open("WARNING")
|
||||||
def warning_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def warning_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._admonition_close()
|
return self._admonition_close()
|
||||||
def dl_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def dl_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return f"{self._break()}[]"
|
return f"{self._break()}[]"
|
||||||
def dl_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def dl_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return ""
|
return ""
|
||||||
def dt_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def dt_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._break()
|
return self._break()
|
||||||
def dt_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def dt_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._enter_block(True)
|
self._enter_block(True)
|
||||||
return ":: {empty}"
|
return ":: {empty}"
|
||||||
def dd_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def dd_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return ""
|
return ""
|
||||||
def dd_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def dd_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._leave_block()
|
self._leave_block()
|
||||||
return "\n"
|
return "\n"
|
||||||
def myst_role(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def myst_role(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._parstack[-1].continuing = True
|
self._parstack[-1].continuing = True
|
||||||
content = asciidoc_escape(token.content)
|
content = asciidoc_escape(token.content)
|
||||||
if token.meta['name'] == 'manpage' and (url := self._manpage_urls.get(token.content)):
|
if token.meta['name'] == 'manpage' and (url := self._manpage_urls.get(token.content)):
|
||||||
return f"link:{quote(url, safe='/:')}[{content}]"
|
return f"link:{quote(url, safe='/:')}[{content}]"
|
||||||
return f"[.{token.meta['name']}]``{asciidoc_escape(token.content)}``"
|
return f"[.{token.meta['name']}]``{asciidoc_escape(token.content)}``"
|
||||||
def inline_anchor(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def inline_anchor(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._parstack[-1].continuing = True
|
self._parstack[-1].continuing = True
|
||||||
return f"[[{token.attrs['id']}]]"
|
return f"[[{token.attrs['id']}]]"
|
||||||
def attr_span_begin(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def attr_span_begin(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._parstack[-1].continuing = True
|
self._parstack[-1].continuing = True
|
||||||
(id_part, class_part) = ("", "")
|
(id_part, class_part) = ("", "")
|
||||||
if id := token.attrs.get('id'):
|
if id := token.attrs.get('id'):
|
||||||
@@ -240,22 +200,17 @@ class AsciiDocRenderer(Renderer):
|
|||||||
class_part = "kbd:["
|
class_part = "kbd:["
|
||||||
self._attrspans.append("]")
|
self._attrspans.append("]")
|
||||||
else:
|
else:
|
||||||
return super().attr_span_begin(token, tokens, i, options, env)
|
return super().attr_span_begin(token, tokens, i)
|
||||||
else:
|
else:
|
||||||
self._attrspans.append("")
|
self._attrspans.append("")
|
||||||
return id_part + class_part
|
return id_part + class_part
|
||||||
def attr_span_end(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def attr_span_end(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._attrspans.pop()
|
return self._attrspans.pop()
|
||||||
def heading_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def heading_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return token.markup.replace("#", "=") + " "
|
return token.markup.replace("#", "=") + " "
|
||||||
def heading_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def heading_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return "\n"
|
return "\n"
|
||||||
def ordered_list_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def ordered_list_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._list_open(token, '.')
|
return self._list_open(token, '.')
|
||||||
def ordered_list_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def ordered_list_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._list_close()
|
return self._list_close()
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
from collections.abc import Mapping, MutableMapping, Sequence
|
from collections.abc import Mapping, Sequence
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Any, cast, Optional
|
from typing import Any, cast, Optional
|
||||||
|
|
||||||
from .md import md_escape, md_make_code, Renderer
|
from .md import md_escape, md_make_code, Renderer
|
||||||
|
|
||||||
from markdown_it.token import Token
|
from markdown_it.token import Token
|
||||||
from markdown_it.utils import OptionsDict
|
|
||||||
|
|
||||||
@dataclass(kw_only=True)
|
@dataclass(kw_only=True)
|
||||||
class List:
|
class List:
|
||||||
@@ -57,39 +56,29 @@ class CommonMarkRenderer(Renderer):
|
|||||||
return s
|
return s
|
||||||
return f"\n{self._parstack[-1].indent}".join(s.splitlines())
|
return f"\n{self._parstack[-1].indent}".join(s.splitlines())
|
||||||
|
|
||||||
def text(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def text(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._parstack[-1].continuing = True
|
self._parstack[-1].continuing = True
|
||||||
return self._indent_raw(md_escape(token.content))
|
return self._indent_raw(md_escape(token.content))
|
||||||
def paragraph_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def paragraph_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._maybe_parbreak()
|
return self._maybe_parbreak()
|
||||||
def paragraph_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def paragraph_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return ""
|
return ""
|
||||||
def hardbreak(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def hardbreak(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return f" {self._break()}"
|
return f" {self._break()}"
|
||||||
def softbreak(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def softbreak(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._break()
|
return self._break()
|
||||||
def code_inline(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def code_inline(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._parstack[-1].continuing = True
|
self._parstack[-1].continuing = True
|
||||||
return md_make_code(token.content)
|
return md_make_code(token.content)
|
||||||
def code_block(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def code_block(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
return self.fence(token, tokens, i)
|
||||||
return self.fence(token, tokens, i, options, env)
|
def link_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
def link_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._parstack[-1].continuing = True
|
self._parstack[-1].continuing = True
|
||||||
self._link_stack.append(cast(str, token.attrs['href']))
|
self._link_stack.append(cast(str, token.attrs['href']))
|
||||||
return "["
|
return "["
|
||||||
def link_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def link_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return f"]({md_escape(self._link_stack.pop())})"
|
return f"]({md_escape(self._link_stack.pop())})"
|
||||||
def list_item_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def list_item_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
lst = self._list_stack[-1]
|
lst = self._list_stack[-1]
|
||||||
lbreak = "" if not lst.first_item_seen else self._break() * (1 if lst.compact else 2)
|
lbreak = "" if not lst.first_item_seen else self._break() * (1 if lst.compact else 2)
|
||||||
lst.first_item_seen = True
|
lst.first_item_seen = True
|
||||||
@@ -99,132 +88,99 @@ class CommonMarkRenderer(Renderer):
|
|||||||
lst.next_idx += 1
|
lst.next_idx += 1
|
||||||
self._enter_block(" " * (len(head) + 1))
|
self._enter_block(" " * (len(head) + 1))
|
||||||
return f'{lbreak}{head} '
|
return f'{lbreak}{head} '
|
||||||
def list_item_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def list_item_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._leave_block()
|
self._leave_block()
|
||||||
return ""
|
return ""
|
||||||
def bullet_list_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def bullet_list_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._list_stack.append(List(compact=bool(token.meta['compact'])))
|
self._list_stack.append(List(compact=bool(token.meta['compact'])))
|
||||||
return self._maybe_parbreak()
|
return self._maybe_parbreak()
|
||||||
def bullet_list_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def bullet_list_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._list_stack.pop()
|
self._list_stack.pop()
|
||||||
return ""
|
return ""
|
||||||
def em_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def em_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return "*"
|
return "*"
|
||||||
def em_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def em_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return "*"
|
return "*"
|
||||||
def strong_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def strong_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return "**"
|
return "**"
|
||||||
def strong_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def strong_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return "**"
|
return "**"
|
||||||
def fence(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def fence(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
code = token.content
|
code = token.content
|
||||||
if code.endswith('\n'):
|
if code.endswith('\n'):
|
||||||
code = code[:-1]
|
code = code[:-1]
|
||||||
pbreak = self._maybe_parbreak()
|
pbreak = self._maybe_parbreak()
|
||||||
return pbreak + self._indent_raw(md_make_code(code, info=token.info, multiline=True))
|
return pbreak + self._indent_raw(md_make_code(code, info=token.info, multiline=True))
|
||||||
def blockquote_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def blockquote_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
pbreak = self._maybe_parbreak()
|
pbreak = self._maybe_parbreak()
|
||||||
self._enter_block("> ")
|
self._enter_block("> ")
|
||||||
return pbreak + "> "
|
return pbreak + "> "
|
||||||
def blockquote_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def blockquote_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._leave_block()
|
self._leave_block()
|
||||||
return ""
|
return ""
|
||||||
def note_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def note_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._admonition_open("Note")
|
return self._admonition_open("Note")
|
||||||
def note_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def note_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._admonition_close()
|
return self._admonition_close()
|
||||||
def caution_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def caution_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._admonition_open("Caution")
|
return self._admonition_open("Caution")
|
||||||
def caution_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def caution_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._admonition_close()
|
return self._admonition_close()
|
||||||
def important_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def important_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._admonition_open("Important")
|
return self._admonition_open("Important")
|
||||||
def important_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def important_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._admonition_close()
|
return self._admonition_close()
|
||||||
def tip_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def tip_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._admonition_open("Tip")
|
return self._admonition_open("Tip")
|
||||||
def tip_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def tip_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._admonition_close()
|
return self._admonition_close()
|
||||||
def warning_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def warning_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._admonition_open("Warning")
|
return self._admonition_open("Warning")
|
||||||
def warning_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def warning_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._admonition_close()
|
return self._admonition_close()
|
||||||
def dl_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def dl_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._list_stack.append(List(compact=False))
|
self._list_stack.append(List(compact=False))
|
||||||
return ""
|
return ""
|
||||||
def dl_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def dl_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._list_stack.pop()
|
self._list_stack.pop()
|
||||||
return ""
|
return ""
|
||||||
def dt_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def dt_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
pbreak = self._maybe_parbreak()
|
pbreak = self._maybe_parbreak()
|
||||||
self._enter_block(" ")
|
self._enter_block(" ")
|
||||||
# add an opening zero-width non-joiner to separate *our* emphasis from possible
|
# add an opening zero-width non-joiner to separate *our* emphasis from possible
|
||||||
# emphasis in the provided term
|
# emphasis in the provided term
|
||||||
return f'{pbreak} - *{chr(0x200C)}'
|
return f'{pbreak} - *{chr(0x200C)}'
|
||||||
def dt_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def dt_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return f"{chr(0x200C)}*"
|
return f"{chr(0x200C)}*"
|
||||||
def dd_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def dd_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._parstack[-1].continuing = True
|
self._parstack[-1].continuing = True
|
||||||
return ""
|
return ""
|
||||||
def dd_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def dd_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._leave_block()
|
self._leave_block()
|
||||||
return ""
|
return ""
|
||||||
def myst_role(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def myst_role(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._parstack[-1].continuing = True
|
self._parstack[-1].continuing = True
|
||||||
content = md_make_code(token.content)
|
content = md_make_code(token.content)
|
||||||
if token.meta['name'] == 'manpage' and (url := self._manpage_urls.get(token.content)):
|
if token.meta['name'] == 'manpage' and (url := self._manpage_urls.get(token.content)):
|
||||||
return f"[{content}]({url})"
|
return f"[{content}]({url})"
|
||||||
return content # no roles in regular commonmark
|
return content # no roles in regular commonmark
|
||||||
def attr_span_begin(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def attr_span_begin(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
# there's no way we can emit attrspans correctly in all cases. we could use inline
|
# there's no way we can emit attrspans correctly in all cases. we could use inline
|
||||||
# html for ids, but that would not round-trip. same holds for classes. since this
|
# html for ids, but that would not round-trip. same holds for classes. since this
|
||||||
# renderer is only used for approximate options export and all of these things are
|
# renderer is only used for approximate options export and all of these things are
|
||||||
# not allowed in options we can ignore them for now.
|
# not allowed in options we can ignore them for now.
|
||||||
return ""
|
return ""
|
||||||
def attr_span_end(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def attr_span_end(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return ""
|
return ""
|
||||||
def heading_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def heading_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return token.markup + " "
|
return token.markup + " "
|
||||||
def heading_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def heading_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return "\n"
|
return "\n"
|
||||||
def ordered_list_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def ordered_list_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._list_stack.append(
|
self._list_stack.append(
|
||||||
List(next_idx = cast(int, token.attrs.get('start', 1)),
|
List(next_idx = cast(int, token.attrs.get('start', 1)),
|
||||||
compact = bool(token.meta['compact'])))
|
compact = bool(token.meta['compact'])))
|
||||||
return self._maybe_parbreak()
|
return self._maybe_parbreak()
|
||||||
def ordered_list_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def ordered_list_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._list_stack.pop()
|
self._list_stack.pop()
|
||||||
return ""
|
return ""
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
from collections.abc import Mapping, MutableMapping, Sequence
|
from collections.abc import Mapping, Sequence
|
||||||
from typing import Any, cast, Optional, NamedTuple
|
from typing import Any, cast, Optional, NamedTuple
|
||||||
|
|
||||||
import markdown_it
|
import markdown_it
|
||||||
from markdown_it.token import Token
|
from markdown_it.token import Token
|
||||||
from markdown_it.utils import OptionsDict
|
|
||||||
from xml.sax.saxutils import escape, quoteattr
|
from xml.sax.saxutils import escape, quoteattr
|
||||||
|
|
||||||
from .md import Renderer
|
from .md import Renderer
|
||||||
@@ -44,13 +43,11 @@ class DocBookRenderer(Renderer):
|
|||||||
self._headings = []
|
self._headings = []
|
||||||
self._attrspans = []
|
self._attrspans = []
|
||||||
|
|
||||||
def render(self, tokens: Sequence[Token], options: OptionsDict,
|
def render(self, tokens: Sequence[Token]) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
result = super().render(tokens)
|
||||||
result = super().render(tokens, options, env)
|
result += self._close_headings(None)
|
||||||
result += self._close_headings(None, env)
|
|
||||||
return result
|
return result
|
||||||
def renderInline(self, tokens: Sequence[Token], options: OptionsDict,
|
def renderInline(self, tokens: Sequence[Token]) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
# HACK to support docbook links and xrefs. link handling is only necessary because the docbook
|
# HACK to support docbook links and xrefs. link handling is only necessary because the docbook
|
||||||
# manpage stylesheet converts - in urls to a mathematical minus, which may be somewhat incorrect.
|
# manpage stylesheet converts - in urls to a mathematical minus, which may be somewhat incorrect.
|
||||||
for i, token in enumerate(tokens):
|
for i, token in enumerate(tokens):
|
||||||
@@ -64,135 +61,98 @@ class DocBookRenderer(Renderer):
|
|||||||
if tokens[i + 1].type == 'text' and tokens[i + 1].content == token.attrs['href']:
|
if tokens[i + 1].type == 'text' and tokens[i + 1].content == token.attrs['href']:
|
||||||
tokens[i + 1].content = ''
|
tokens[i + 1].content = ''
|
||||||
|
|
||||||
return super().renderInline(tokens, options, env)
|
return super().renderInline(tokens)
|
||||||
|
|
||||||
def text(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def text(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return escape(token.content)
|
return escape(token.content)
|
||||||
def paragraph_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def paragraph_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return "<para>"
|
return "<para>"
|
||||||
def paragraph_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def paragraph_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return "</para>"
|
return "</para>"
|
||||||
def hardbreak(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def hardbreak(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return "<literallayout>\n</literallayout>"
|
return "<literallayout>\n</literallayout>"
|
||||||
def softbreak(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def softbreak(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
# should check options.breaks() and emit hard break if so
|
# should check options.breaks() and emit hard break if so
|
||||||
return "\n"
|
return "\n"
|
||||||
def code_inline(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def code_inline(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return f"<literal>{escape(token.content)}</literal>"
|
return f"<literal>{escape(token.content)}</literal>"
|
||||||
def code_block(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def code_block(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return f"<programlisting>{escape(token.content)}</programlisting>"
|
return f"<programlisting>{escape(token.content)}</programlisting>"
|
||||||
def link_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def link_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._link_tags.append(token.tag)
|
self._link_tags.append(token.tag)
|
||||||
href = cast(str, token.attrs['href'])
|
href = cast(str, token.attrs['href'])
|
||||||
(attr, start) = ('linkend', 1) if href[0] == '#' else ('xlink:href', 0)
|
(attr, start) = ('linkend', 1) if href[0] == '#' else ('xlink:href', 0)
|
||||||
return f"<{token.tag} {attr}={quoteattr(href[start:])}>"
|
return f"<{token.tag} {attr}={quoteattr(href[start:])}>"
|
||||||
def link_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def link_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return f"</{self._link_tags.pop()}>"
|
return f"</{self._link_tags.pop()}>"
|
||||||
def list_item_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def list_item_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return "<listitem>"
|
return "<listitem>"
|
||||||
def list_item_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def list_item_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return "</listitem>\n"
|
return "</listitem>\n"
|
||||||
# HACK open and close para for docbook change size. remove soon.
|
# HACK open and close para for docbook change size. remove soon.
|
||||||
def bullet_list_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def bullet_list_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
spacing = ' spacing="compact"' if token.meta.get('compact', False) else ''
|
spacing = ' spacing="compact"' if token.meta.get('compact', False) else ''
|
||||||
return f"<para><itemizedlist{spacing}>\n"
|
return f"<para><itemizedlist{spacing}>\n"
|
||||||
def bullet_list_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def bullet_list_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return "\n</itemizedlist></para>"
|
return "\n</itemizedlist></para>"
|
||||||
def em_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def em_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return "<emphasis>"
|
return "<emphasis>"
|
||||||
def em_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def em_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return "</emphasis>"
|
return "</emphasis>"
|
||||||
def strong_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def strong_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return "<emphasis role=\"strong\">"
|
return "<emphasis role=\"strong\">"
|
||||||
def strong_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def strong_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return "</emphasis>"
|
return "</emphasis>"
|
||||||
def fence(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def fence(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
info = f" language={quoteattr(token.info)}" if token.info != "" else ""
|
info = f" language={quoteattr(token.info)}" if token.info != "" else ""
|
||||||
return f"<programlisting{info}>{escape(token.content)}</programlisting>"
|
return f"<programlisting{info}>{escape(token.content)}</programlisting>"
|
||||||
def blockquote_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def blockquote_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return "<para><blockquote>"
|
return "<para><blockquote>"
|
||||||
def blockquote_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def blockquote_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return "</blockquote></para>"
|
return "</blockquote></para>"
|
||||||
def note_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def note_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return "<para><note>"
|
return "<para><note>"
|
||||||
def note_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def note_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return "</note></para>"
|
return "</note></para>"
|
||||||
def caution_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def caution_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return "<para><caution>"
|
return "<para><caution>"
|
||||||
def caution_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def caution_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return "</caution></para>"
|
return "</caution></para>"
|
||||||
def important_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def important_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return "<para><important>"
|
return "<para><important>"
|
||||||
def important_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def important_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return "</important></para>"
|
return "</important></para>"
|
||||||
def tip_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def tip_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return "<para><tip>"
|
return "<para><tip>"
|
||||||
def tip_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def tip_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return "</tip></para>"
|
return "</tip></para>"
|
||||||
def warning_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def warning_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return "<para><warning>"
|
return "<para><warning>"
|
||||||
def warning_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def warning_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return "</warning></para>"
|
return "</warning></para>"
|
||||||
# markdown-it emits tokens based on the html syntax tree, but docbook is
|
# markdown-it emits tokens based on the html syntax tree, but docbook is
|
||||||
# slightly different. html has <dl>{<dt/>{<dd/>}}</dl>,
|
# slightly different. html has <dl>{<dt/>{<dd/>}}</dl>,
|
||||||
# docbook has <variablelist>{<varlistentry><term/><listitem/></varlistentry>}<variablelist>
|
# docbook has <variablelist>{<varlistentry><term/><listitem/></varlistentry>}<variablelist>
|
||||||
# we have to reject multiple definitions for the same term for time being.
|
# we have to reject multiple definitions for the same term for time being.
|
||||||
def dl_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def dl_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._deflists.append(Deflist())
|
self._deflists.append(Deflist())
|
||||||
return "<para><variablelist>"
|
return "<para><variablelist>"
|
||||||
def dl_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def dl_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._deflists.pop()
|
self._deflists.pop()
|
||||||
return "</variablelist></para>"
|
return "</variablelist></para>"
|
||||||
def dt_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def dt_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._deflists[-1].has_dd = False
|
self._deflists[-1].has_dd = False
|
||||||
return "<varlistentry><term>"
|
return "<varlistentry><term>"
|
||||||
def dt_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def dt_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return "</term>"
|
return "</term>"
|
||||||
def dd_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def dd_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
if self._deflists[-1].has_dd:
|
if self._deflists[-1].has_dd:
|
||||||
raise Exception("multiple definitions per term not supported")
|
raise Exception("multiple definitions per term not supported")
|
||||||
self._deflists[-1].has_dd = True
|
self._deflists[-1].has_dd = True
|
||||||
return "<listitem>"
|
return "<listitem>"
|
||||||
def dd_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def dd_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return "</listitem></varlistentry>"
|
return "</listitem></varlistentry>"
|
||||||
def myst_role(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def myst_role(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
if token.meta['name'] == 'command':
|
if token.meta['name'] == 'command':
|
||||||
return f"<command>{escape(token.content)}</command>"
|
return f"<command>{escape(token.content)}</command>"
|
||||||
if token.meta['name'] == 'file':
|
if token.meta['name'] == 'file':
|
||||||
@@ -215,8 +175,7 @@ class DocBookRenderer(Renderer):
|
|||||||
else:
|
else:
|
||||||
return ref
|
return ref
|
||||||
raise NotImplementedError("md node not supported yet", token)
|
raise NotImplementedError("md node not supported yet", token)
|
||||||
def attr_span_begin(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def attr_span_begin(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
# we currently support *only* inline anchors and the special .keycap class to produce
|
# we currently support *only* inline anchors and the special .keycap class to produce
|
||||||
# <keycap> docbook elements.
|
# <keycap> docbook elements.
|
||||||
(id_part, class_part) = ("", "")
|
(id_part, class_part) = ("", "")
|
||||||
@@ -227,31 +186,26 @@ class DocBookRenderer(Renderer):
|
|||||||
class_part = "<keycap>"
|
class_part = "<keycap>"
|
||||||
self._attrspans.append("</keycap>")
|
self._attrspans.append("</keycap>")
|
||||||
else:
|
else:
|
||||||
return super().attr_span_begin(token, tokens, i, options, env)
|
return super().attr_span_begin(token, tokens, i)
|
||||||
else:
|
else:
|
||||||
self._attrspans.append("")
|
self._attrspans.append("")
|
||||||
return id_part + class_part
|
return id_part + class_part
|
||||||
def attr_span_end(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def attr_span_end(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._attrspans.pop()
|
return self._attrspans.pop()
|
||||||
def ordered_list_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def ordered_list_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
start = f' startingnumber="{token.attrs["start"]}"' if 'start' in token.attrs else ""
|
start = f' startingnumber="{token.attrs["start"]}"' if 'start' in token.attrs else ""
|
||||||
spacing = ' spacing="compact"' if token.meta.get('compact', False) else ''
|
spacing = ' spacing="compact"' if token.meta.get('compact', False) else ''
|
||||||
return f"<orderedlist{start}{spacing}>"
|
return f"<orderedlist{start}{spacing}>"
|
||||||
def ordered_list_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def ordered_list_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return f"</orderedlist>"
|
return f"</orderedlist>"
|
||||||
def heading_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def heading_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
hlevel = int(token.tag[1:])
|
hlevel = int(token.tag[1:])
|
||||||
result = self._close_headings(hlevel, env)
|
result = self._close_headings(hlevel)
|
||||||
(tag, attrs) = self._heading_tag(token, tokens, i, options, env)
|
(tag, attrs) = self._heading_tag(token, tokens, i)
|
||||||
self._headings.append(Heading(tag, hlevel))
|
self._headings.append(Heading(tag, hlevel))
|
||||||
attrs_str = "".join([ f" {k}={quoteattr(v)}" for k, v in attrs.items() ])
|
attrs_str = "".join([ f" {k}={quoteattr(v)}" for k, v in attrs.items() ])
|
||||||
return result + f'<{tag}{attrs_str}>\n<title>'
|
return result + f'<{tag}{attrs_str}>\n<title>'
|
||||||
def heading_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def heading_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
heading = self._headings[-1]
|
heading = self._headings[-1]
|
||||||
result = '</title>'
|
result = '</title>'
|
||||||
if heading.container_tag == 'part':
|
if heading.container_tag == 'part':
|
||||||
@@ -263,16 +217,14 @@ class DocBookRenderer(Renderer):
|
|||||||
maybe_id = " xml:id=" + quoteattr(id + "-intro")
|
maybe_id = " xml:id=" + quoteattr(id + "-intro")
|
||||||
result += f"<partintro{maybe_id}>"
|
result += f"<partintro{maybe_id}>"
|
||||||
return result
|
return result
|
||||||
def example_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def example_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
if id := token.attrs.get('id'):
|
if id := token.attrs.get('id'):
|
||||||
return f"<anchor xml:id={quoteattr(cast(str, id))} />"
|
return f"<anchor xml:id={quoteattr(cast(str, id))} />"
|
||||||
return ""
|
return ""
|
||||||
def example_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def example_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
def _close_headings(self, level: Optional[int], env: MutableMapping[str, Any]) -> str:
|
def _close_headings(self, level: Optional[int]) -> str:
|
||||||
# we rely on markdown-it producing h{1..6} tags in token.tag for this to work
|
# we rely on markdown-it producing h{1..6} tags in token.tag for this to work
|
||||||
result = []
|
result = []
|
||||||
while len(self._headings):
|
while len(self._headings):
|
||||||
@@ -285,8 +237,7 @@ class DocBookRenderer(Renderer):
|
|||||||
break
|
break
|
||||||
return "\n".join(result)
|
return "\n".join(result)
|
||||||
|
|
||||||
def _heading_tag(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def _heading_tag(self, token: Token, tokens: Sequence[Token], i: int) -> tuple[str, dict[str, str]]:
|
||||||
env: MutableMapping[str, Any]) -> tuple[str, dict[str, str]]:
|
|
||||||
attrs = {}
|
attrs = {}
|
||||||
if id := token.attrs.get('id'):
|
if id := token.attrs.get('id'):
|
||||||
attrs['xml:id'] = cast(str, id)
|
attrs['xml:id'] = cast(str, id)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from collections.abc import Mapping, MutableMapping, Sequence
|
from collections.abc import Mapping, Sequence
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Any, cast, Iterable, Optional
|
from typing import Any, cast, Iterable, Optional
|
||||||
|
|
||||||
@@ -6,7 +6,6 @@ import re
|
|||||||
|
|
||||||
import markdown_it
|
import markdown_it
|
||||||
from markdown_it.token import Token
|
from markdown_it.token import Token
|
||||||
from markdown_it.utils import OptionsDict
|
|
||||||
|
|
||||||
from .md import Renderer
|
from .md import Renderer
|
||||||
|
|
||||||
@@ -123,36 +122,27 @@ class ManpageRenderer(Renderer):
|
|||||||
self._leave_block()
|
self._leave_block()
|
||||||
return ".RE"
|
return ".RE"
|
||||||
|
|
||||||
def render(self, tokens: Sequence[Token], options: OptionsDict,
|
def render(self, tokens: Sequence[Token]) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._do_parbreak_stack = [ False ]
|
self._do_parbreak_stack = [ False ]
|
||||||
self._font_stack = [ "\\fR" ]
|
self._font_stack = [ "\\fR" ]
|
||||||
return super().render(tokens, options, env)
|
return super().render(tokens)
|
||||||
|
|
||||||
def text(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def text(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return man_escape(token.content)
|
return man_escape(token.content)
|
||||||
def paragraph_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def paragraph_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._maybe_parbreak()
|
return self._maybe_parbreak()
|
||||||
def paragraph_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def paragraph_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return ""
|
return ""
|
||||||
def hardbreak(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def hardbreak(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return ".br"
|
return ".br"
|
||||||
def softbreak(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def softbreak(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return " "
|
return " "
|
||||||
def code_inline(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def code_inline(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
s = _protect_spaces(man_escape(token.content))
|
s = _protect_spaces(man_escape(token.content))
|
||||||
return f"\\fR\\(oq{s}\\(cq\\fP" if self.inline_code_is_quoted else s
|
return f"\\fR\\(oq{s}\\(cq\\fP" if self.inline_code_is_quoted else s
|
||||||
def code_block(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def code_block(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
return self.fence(token, tokens, i)
|
||||||
return self.fence(token, tokens, i, options, env)
|
def link_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
def link_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
href = cast(str, token.attrs['href'])
|
href = cast(str, token.attrs['href'])
|
||||||
self._link_stack.append(href)
|
self._link_stack.append(href)
|
||||||
text = ""
|
text = ""
|
||||||
@@ -161,8 +151,7 @@ class ManpageRenderer(Renderer):
|
|||||||
text = self._href_targets[href]
|
text = self._href_targets[href]
|
||||||
self._font_stack.append("\\fB")
|
self._font_stack.append("\\fB")
|
||||||
return f"\\fB{text}\0 <"
|
return f"\\fB{text}\0 <"
|
||||||
def link_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def link_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
href = self._link_stack.pop()
|
href = self._link_stack.pop()
|
||||||
text = ""
|
text = ""
|
||||||
if self.link_footnotes is not None:
|
if self.link_footnotes is not None:
|
||||||
@@ -174,8 +163,7 @@ class ManpageRenderer(Renderer):
|
|||||||
text = "\\fR" + man_escape(f"[{idx}]")
|
text = "\\fR" + man_escape(f"[{idx}]")
|
||||||
self._font_stack.pop()
|
self._font_stack.pop()
|
||||||
return f">\0 {text}{self._font_stack[-1]}"
|
return f">\0 {text}{self._font_stack[-1]}"
|
||||||
def list_item_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def list_item_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._enter_block()
|
self._enter_block()
|
||||||
lst = self._list_stack[-1]
|
lst = self._list_stack[-1]
|
||||||
maybe_space = '' if lst.compact or not lst.first_item_seen else '.sp\n'
|
maybe_space = '' if lst.compact or not lst.first_item_seen else '.sp\n'
|
||||||
@@ -189,36 +177,28 @@ class ManpageRenderer(Renderer):
|
|||||||
f'.RS {lst.width}\n'
|
f'.RS {lst.width}\n'
|
||||||
f"\\h'-{len(head) + 1}'\\fB{man_escape(head)}\\fP\\h'1'\\c"
|
f"\\h'-{len(head) + 1}'\\fB{man_escape(head)}\\fP\\h'1'\\c"
|
||||||
)
|
)
|
||||||
def list_item_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def list_item_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._leave_block()
|
self._leave_block()
|
||||||
return ".RE"
|
return ".RE"
|
||||||
def bullet_list_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def bullet_list_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._list_stack.append(List(width=4, compact=bool(token.meta['compact'])))
|
self._list_stack.append(List(width=4, compact=bool(token.meta['compact'])))
|
||||||
return self._maybe_parbreak()
|
return self._maybe_parbreak()
|
||||||
def bullet_list_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def bullet_list_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._list_stack.pop()
|
self._list_stack.pop()
|
||||||
return ""
|
return ""
|
||||||
def em_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def em_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._font_stack.append("\\fI")
|
self._font_stack.append("\\fI")
|
||||||
return "\\fI"
|
return "\\fI"
|
||||||
def em_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def em_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._font_stack.pop()
|
self._font_stack.pop()
|
||||||
return self._font_stack[-1]
|
return self._font_stack[-1]
|
||||||
def strong_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def strong_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._font_stack.append("\\fB")
|
self._font_stack.append("\\fB")
|
||||||
return "\\fB"
|
return "\\fB"
|
||||||
def strong_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def strong_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._font_stack.pop()
|
self._font_stack.pop()
|
||||||
return self._font_stack[-1]
|
return self._font_stack[-1]
|
||||||
def fence(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def fence(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
s = man_escape(token.content).rstrip('\n')
|
s = man_escape(token.content).rstrip('\n')
|
||||||
return (
|
return (
|
||||||
'.sp\n'
|
'.sp\n'
|
||||||
@@ -228,8 +208,7 @@ class ManpageRenderer(Renderer):
|
|||||||
'.fi\n'
|
'.fi\n'
|
||||||
'.RE'
|
'.RE'
|
||||||
)
|
)
|
||||||
def blockquote_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def blockquote_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
maybe_par = self._maybe_parbreak("\n")
|
maybe_par = self._maybe_parbreak("\n")
|
||||||
self._enter_block()
|
self._enter_block()
|
||||||
return (
|
return (
|
||||||
@@ -237,62 +216,44 @@ class ManpageRenderer(Renderer):
|
|||||||
".RS 4\n"
|
".RS 4\n"
|
||||||
f"\\h'-3'\\fI\\(lq\\(rq\\fP\\h'1'\\c"
|
f"\\h'-3'\\fI\\(lq\\(rq\\fP\\h'1'\\c"
|
||||||
)
|
)
|
||||||
def blockquote_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def blockquote_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._leave_block()
|
self._leave_block()
|
||||||
return ".RE"
|
return ".RE"
|
||||||
def note_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def note_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._admonition_open("Note")
|
return self._admonition_open("Note")
|
||||||
def note_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def note_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._admonition_close()
|
return self._admonition_close()
|
||||||
def caution_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def caution_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._admonition_open( "Caution")
|
return self._admonition_open( "Caution")
|
||||||
def caution_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def caution_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._admonition_close()
|
return self._admonition_close()
|
||||||
def important_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def important_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._admonition_open( "Important")
|
return self._admonition_open( "Important")
|
||||||
def important_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def important_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._admonition_close()
|
return self._admonition_close()
|
||||||
def tip_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def tip_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._admonition_open( "Tip")
|
return self._admonition_open( "Tip")
|
||||||
def tip_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def tip_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._admonition_close()
|
return self._admonition_close()
|
||||||
def warning_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def warning_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._admonition_open( "Warning")
|
return self._admonition_open( "Warning")
|
||||||
def warning_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def warning_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return self._admonition_close()
|
return self._admonition_close()
|
||||||
def dl_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def dl_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return ".RS 4"
|
return ".RS 4"
|
||||||
def dl_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def dl_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return ".RE"
|
return ".RE"
|
||||||
def dt_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def dt_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return ".PP"
|
return ".PP"
|
||||||
def dt_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def dt_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return ""
|
return ""
|
||||||
def dd_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def dd_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._enter_block()
|
self._enter_block()
|
||||||
return ".RS 4"
|
return ".RS 4"
|
||||||
def dd_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def dd_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._leave_block()
|
self._leave_block()
|
||||||
return ".RE"
|
return ".RE"
|
||||||
def myst_role(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def myst_role(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
if token.meta['name'] in [ 'command', 'env', 'option' ]:
|
if token.meta['name'] in [ 'command', 'env', 'option' ]:
|
||||||
return f'\\fB{man_escape(token.content)}\\fP'
|
return f'\\fB{man_escape(token.content)}\\fP'
|
||||||
elif token.meta['name'] in [ 'file', 'var' ]:
|
elif token.meta['name'] in [ 'file', 'var' ]:
|
||||||
@@ -303,23 +264,18 @@ class ManpageRenderer(Renderer):
|
|||||||
return f'\\fB{man_escape(page)}\\fP\\fR({man_escape(section)})\\fP'
|
return f'\\fB{man_escape(page)}\\fP\\fR({man_escape(section)})\\fP'
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError("md node not supported yet", token)
|
raise NotImplementedError("md node not supported yet", token)
|
||||||
def attr_span_begin(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def attr_span_begin(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
# mdoc knows no anchors so we can drop those, but classes must be rejected.
|
# mdoc knows no anchors so we can drop those, but classes must be rejected.
|
||||||
if 'class' in token.attrs:
|
if 'class' in token.attrs:
|
||||||
return super().attr_span_begin(token, tokens, i, options, env)
|
return super().attr_span_begin(token, tokens, i)
|
||||||
return ""
|
return ""
|
||||||
def attr_span_end(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def attr_span_end(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return ""
|
return ""
|
||||||
def heading_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def heading_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported in manpages", token)
|
raise RuntimeError("md token not supported in manpages", token)
|
||||||
def heading_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def heading_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported in manpages", token)
|
raise RuntimeError("md token not supported in manpages", token)
|
||||||
def ordered_list_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def ordered_list_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
# max item head width for a number, a dot, and one leading space and one trailing space
|
# max item head width for a number, a dot, and one leading space and one trailing space
|
||||||
width = 3 + len(str(cast(int, token.meta['end'])))
|
width = 3 + len(str(cast(int, token.meta['end'])))
|
||||||
self._list_stack.append(
|
self._list_stack.append(
|
||||||
@@ -327,7 +283,6 @@ class ManpageRenderer(Renderer):
|
|||||||
next_idx = cast(int, token.attrs.get('start', 1)),
|
next_idx = cast(int, token.attrs.get('start', 1)),
|
||||||
compact = bool(token.meta['compact'])))
|
compact = bool(token.meta['compact'])))
|
||||||
return self._maybe_parbreak()
|
return self._maybe_parbreak()
|
||||||
def ordered_list_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def ordered_list_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
self._list_stack.pop()
|
self._list_stack.pop()
|
||||||
return ""
|
return ""
|
||||||
|
|||||||
@@ -2,14 +2,13 @@ import argparse
|
|||||||
import json
|
import json
|
||||||
|
|
||||||
from abc import abstractmethod
|
from abc import abstractmethod
|
||||||
from collections.abc import Mapping, MutableMapping, Sequence
|
from collections.abc import Mapping, Sequence
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, cast, NamedTuple, Optional, Union
|
from typing import Any, cast, NamedTuple, Optional, Union
|
||||||
from xml.sax.saxutils import escape, quoteattr
|
from xml.sax.saxutils import escape, quoteattr
|
||||||
|
|
||||||
import markdown_it
|
import markdown_it
|
||||||
from markdown_it.token import Token
|
from markdown_it.token import Token
|
||||||
from markdown_it.utils import OptionsDict
|
|
||||||
|
|
||||||
from . import options
|
from . import options
|
||||||
from .docbook import DocBookRenderer, Heading
|
from .docbook import DocBookRenderer, Heading
|
||||||
@@ -30,8 +29,7 @@ class ManualDocBookRenderer(DocBookRenderer):
|
|||||||
'included_options': self.included_options,
|
'included_options': self.included_options,
|
||||||
}
|
}
|
||||||
|
|
||||||
def render(self, tokens: Sequence[Token], options: OptionsDict,
|
def render(self, tokens: Sequence[Token]) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
wanted = { 'h1': 'title' }
|
wanted = { 'h1': 'title' }
|
||||||
wanted |= { 'h2': 'subtitle' } if self._toplevel_tag == 'book' else {}
|
wanted |= { 'h2': 'subtitle' } if self._toplevel_tag == 'book' else {}
|
||||||
for (i, (tag, kind)) in enumerate(wanted.items()):
|
for (i, (tag, kind)) in enumerate(wanted.items()):
|
||||||
@@ -62,16 +60,15 @@ class ManualDocBookRenderer(DocBookRenderer):
|
|||||||
return (f'<book xmlns="http://docbook.org/ns/docbook"'
|
return (f'<book xmlns="http://docbook.org/ns/docbook"'
|
||||||
f' xmlns:xlink="http://www.w3.org/1999/xlink"'
|
f' xmlns:xlink="http://www.w3.org/1999/xlink"'
|
||||||
f' {maybe_id} version="5.0">'
|
f' {maybe_id} version="5.0">'
|
||||||
f' <title>{self.renderInline(tokens[1].children, options, env)}</title>'
|
f' <title>{self.renderInline(tokens[1].children)}</title>'
|
||||||
f' <subtitle>{self.renderInline(tokens[4].children, options, env)}</subtitle>'
|
f' <subtitle>{self.renderInline(tokens[4].children)}</subtitle>'
|
||||||
f' {super().render(tokens[6:], options, env)}'
|
f' {super().render(tokens[6:])}'
|
||||||
f'</book>')
|
f'</book>')
|
||||||
|
|
||||||
return super().render(tokens, options, env)
|
return super().render(tokens)
|
||||||
|
|
||||||
def _heading_tag(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def _heading_tag(self, token: Token, tokens: Sequence[Token], i: int) -> tuple[str, dict[str, str]]:
|
||||||
env: MutableMapping[str, Any]) -> tuple[str, dict[str, str]]:
|
(tag, attrs) = super()._heading_tag(token, tokens, i)
|
||||||
(tag, attrs) = super()._heading_tag(token, tokens, i, options, env)
|
|
||||||
# render() has already verified that we don't have supernumerary headings and since the
|
# render() has already verified that we don't have supernumerary headings and since the
|
||||||
# book tag is handled specially we can leave the check this simple
|
# book tag is handled specially we can leave the check this simple
|
||||||
if token.tag != 'h1':
|
if token.tag != 'h1':
|
||||||
@@ -81,8 +78,7 @@ class ManualDocBookRenderer(DocBookRenderer):
|
|||||||
'xmlns:xlink': "http://www.w3.org/1999/xlink",
|
'xmlns:xlink': "http://www.w3.org/1999/xlink",
|
||||||
})
|
})
|
||||||
|
|
||||||
def _included_thing(self, tag: str, token: Token, tokens: Sequence[Token], i: int,
|
def _included_thing(self, tag: str, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
options: OptionsDict, env: MutableMapping[str, Any]) -> str:
|
|
||||||
result = []
|
result = []
|
||||||
# close existing partintro. the generic render doesn't really need this because
|
# close existing partintro. the generic render doesn't really need this because
|
||||||
# it doesn't have a concept of structure in the way the manual does.
|
# it doesn't have a concept of structure in the way the manual does.
|
||||||
@@ -94,26 +90,21 @@ class ManualDocBookRenderer(DocBookRenderer):
|
|||||||
r = ManualDocBookRenderer(tag, self._manpage_urls)
|
r = ManualDocBookRenderer(tag, self._manpage_urls)
|
||||||
for (included, path) in token.meta['included']:
|
for (included, path) in token.meta['included']:
|
||||||
try:
|
try:
|
||||||
result.append(r.render(included, options, env))
|
result.append(r.render(included))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise RuntimeError(f"rendering {path}") from e
|
raise RuntimeError(f"rendering {path}") from e
|
||||||
return "".join(result)
|
return "".join(result)
|
||||||
def included_options(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def included_options(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return cast(str, token.meta['rendered-options'])
|
return cast(str, token.meta['rendered-options'])
|
||||||
|
|
||||||
# TODO minimize docbook diffs with existing conversions. remove soon.
|
# TODO minimize docbook diffs with existing conversions. remove soon.
|
||||||
def paragraph_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def paragraph_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
return super().paragraph_open(token, tokens, i) + "\n "
|
||||||
return super().paragraph_open(token, tokens, i, options, env) + "\n "
|
def paragraph_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
def paragraph_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
return "\n" + super().paragraph_close(token, tokens, i)
|
||||||
env: MutableMapping[str, Any]) -> str:
|
def code_block(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
return "\n" + super().paragraph_close(token, tokens, i, options, env)
|
|
||||||
def code_block(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
return f"<programlisting>\n{escape(token.content)}</programlisting>"
|
return f"<programlisting>\n{escape(token.content)}</programlisting>"
|
||||||
def fence(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def fence(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
info = f" language={quoteattr(token.info)}" if token.info != "" else ""
|
info = f" language={quoteattr(token.info)}" if token.info != "" else ""
|
||||||
return f"<programlisting{info}>\n{escape(token.content)}</programlisting>"
|
return f"<programlisting{info}>\n{escape(token.content)}</programlisting>"
|
||||||
|
|
||||||
@@ -134,8 +125,8 @@ class DocBookConverter(Converter[ManualDocBookRenderer]):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise RuntimeError(f"failed to render manual {file}") from e
|
raise RuntimeError(f"failed to render manual {file}") from e
|
||||||
|
|
||||||
def _parse(self, src: str, env: Optional[MutableMapping[str, Any]] = None) -> list[Token]:
|
def _parse(self, src: str) -> list[Token]:
|
||||||
tokens = super()._parse(src, env)
|
tokens = super()._parse(src)
|
||||||
for token in tokens:
|
for token in tokens:
|
||||||
if token.type != "fence" or not token.info.startswith("{=include=} "):
|
if token.type != "fence" or not token.info.startswith("{=include=} "):
|
||||||
continue
|
continue
|
||||||
@@ -145,12 +136,12 @@ class DocBookConverter(Converter[ManualDocBookRenderer]):
|
|||||||
self._parse_options(token)
|
self._parse_options(token)
|
||||||
elif typ in [ 'sections', 'chapters', 'preface', 'parts', 'appendix' ]:
|
elif typ in [ 'sections', 'chapters', 'preface', 'parts', 'appendix' ]:
|
||||||
token.type = 'included_' + typ
|
token.type = 'included_' + typ
|
||||||
self._parse_included_blocks(token, env)
|
self._parse_included_blocks(token)
|
||||||
else:
|
else:
|
||||||
raise RuntimeError(f"unsupported structural include type '{typ}'")
|
raise RuntimeError(f"unsupported structural include type '{typ}'")
|
||||||
return tokens
|
return tokens
|
||||||
|
|
||||||
def _parse_included_blocks(self, token: Token, env: Optional[MutableMapping[str, Any]]) -> None:
|
def _parse_included_blocks(self, token: Token) -> None:
|
||||||
assert token.map
|
assert token.map
|
||||||
included = token.meta['included'] = []
|
included = token.meta['included'] = []
|
||||||
for (lnum, line) in enumerate(token.content.splitlines(), token.map[0] + 2):
|
for (lnum, line) in enumerate(token.content.splitlines(), token.map[0] + 2):
|
||||||
@@ -161,7 +152,7 @@ class DocBookConverter(Converter[ManualDocBookRenderer]):
|
|||||||
try:
|
try:
|
||||||
self._base_paths.append(path)
|
self._base_paths.append(path)
|
||||||
with open(path, 'r') as f:
|
with open(path, 'r') as f:
|
||||||
tokens = self._parse(f.read(), env)
|
tokens = self._parse(f.read())
|
||||||
included.append((tokens, path))
|
included.append((tokens, path))
|
||||||
self._base_paths.pop()
|
self._base_paths.pop()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
@@ -104,169 +104,120 @@ class Renderer:
|
|||||||
def _join_inline(self, ls: Iterable[str]) -> str:
|
def _join_inline(self, ls: Iterable[str]) -> str:
|
||||||
return "".join(ls)
|
return "".join(ls)
|
||||||
|
|
||||||
def admonition_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def admonition_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
tag = token.meta['kind']
|
tag = token.meta['kind']
|
||||||
self._admonition_stack.append(tag)
|
self._admonition_stack.append(tag)
|
||||||
return self._admonitions[tag][0](token, tokens, i, options, env)
|
return self._admonitions[tag][0](token, tokens, i)
|
||||||
def admonition_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def admonition_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
return self._admonitions[self._admonition_stack.pop()][1](token, tokens, i)
|
||||||
return self._admonitions[self._admonition_stack.pop()][1](token, tokens, i, options, env)
|
|
||||||
|
|
||||||
def render(self, tokens: Sequence[Token], options: OptionsDict,
|
def render(self, tokens: Sequence[Token]) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
def do_one(i: int, token: Token) -> str:
|
def do_one(i: int, token: Token) -> str:
|
||||||
if token.type == "inline":
|
if token.type == "inline":
|
||||||
assert token.children is not None
|
assert token.children is not None
|
||||||
return self.renderInline(token.children, options, env)
|
return self.renderInline(token.children)
|
||||||
elif token.type in self.rules:
|
elif token.type in self.rules:
|
||||||
return self.rules[token.type](tokens[i], tokens, i, options, env)
|
return self.rules[token.type](tokens[i], tokens, i)
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError("md token not supported yet", token)
|
raise NotImplementedError("md token not supported yet", token)
|
||||||
return self._join_block(map(lambda arg: do_one(*arg), enumerate(tokens)))
|
return self._join_block(map(lambda arg: do_one(*arg), enumerate(tokens)))
|
||||||
def renderInline(self, tokens: Sequence[Token], options: OptionsDict,
|
def renderInline(self, tokens: Sequence[Token]) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
def do_one(i: int, token: Token) -> str:
|
def do_one(i: int, token: Token) -> str:
|
||||||
if token.type in self.rules:
|
if token.type in self.rules:
|
||||||
return self.rules[token.type](tokens[i], tokens, i, options, env)
|
return self.rules[token.type](tokens[i], tokens, i)
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError("md token not supported yet", token)
|
raise NotImplementedError("md token not supported yet", token)
|
||||||
return self._join_inline(map(lambda arg: do_one(*arg), enumerate(tokens)))
|
return self._join_inline(map(lambda arg: do_one(*arg), enumerate(tokens)))
|
||||||
|
|
||||||
def text(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def text(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def paragraph_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def paragraph_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def paragraph_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def paragraph_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def hardbreak(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def hardbreak(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def softbreak(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def softbreak(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def code_inline(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def code_inline(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def code_block(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def code_block(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def link_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def link_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def link_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def link_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def list_item_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def list_item_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def list_item_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def list_item_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def bullet_list_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def bullet_list_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def bullet_list_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def bullet_list_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def em_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def em_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def em_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def em_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def strong_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def strong_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def strong_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def strong_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def fence(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def fence(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def blockquote_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def blockquote_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def blockquote_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def blockquote_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def note_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def note_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def note_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def note_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def caution_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def caution_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def caution_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def caution_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def important_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def important_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def important_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def important_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def tip_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def tip_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def tip_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def tip_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def warning_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def warning_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def warning_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def warning_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def dl_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def dl_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def dl_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def dl_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def dt_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def dt_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def dt_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def dt_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def dd_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def dd_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def dd_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def dd_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def myst_role(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def myst_role(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def attr_span_begin(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def attr_span_begin(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def attr_span_end(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def attr_span_end(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def heading_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def heading_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def heading_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def heading_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def ordered_list_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def ordered_list_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def ordered_list_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def ordered_list_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def example_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def example_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
def example_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def example_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported", token)
|
raise RuntimeError("md token not supported", token)
|
||||||
|
|
||||||
def _is_escaped(src: str, pos: int) -> bool:
|
def _is_escaped(src: str, pos: int) -> bool:
|
||||||
@@ -510,10 +461,9 @@ class Converter(ABC, Generic[TR]):
|
|||||||
self._md.use(_block_attr)
|
self._md.use(_block_attr)
|
||||||
self._md.enable(["smartquotes", "replacements"])
|
self._md.enable(["smartquotes", "replacements"])
|
||||||
|
|
||||||
def _parse(self, src: str, env: Optional[MutableMapping[str, Any]] = None) -> list[Token]:
|
def _parse(self, src: str) -> list[Token]:
|
||||||
return self._md.parse(src, env if env is not None else {})
|
return self._md.parse(src, {})
|
||||||
|
|
||||||
def _render(self, src: str, env: Optional[MutableMapping[str, Any]] = None) -> str:
|
def _render(self, src: str) -> str:
|
||||||
env = {} if env is None else env
|
tokens = self._parse(src)
|
||||||
tokens = self._parse(src, env)
|
return self._renderer.render(tokens)
|
||||||
return self._renderer.render(tokens, self._md.options, env)
|
|
||||||
|
|||||||
@@ -4,8 +4,7 @@ import argparse
|
|||||||
import json
|
import json
|
||||||
|
|
||||||
from abc import abstractmethod
|
from abc import abstractmethod
|
||||||
from collections.abc import Mapping, MutableMapping, Sequence
|
from collections.abc import Mapping, Sequence
|
||||||
from markdown_it.utils import OptionsDict
|
|
||||||
from markdown_it.token import Token
|
from markdown_it.token import Token
|
||||||
from typing import Any, Generic, Optional
|
from typing import Any, Generic, Optional
|
||||||
from urllib.parse import quote
|
from urllib.parse import quote
|
||||||
@@ -174,29 +173,23 @@ class BaseConverter(Converter[md.TR], Generic[md.TR]):
|
|||||||
def finalize(self) -> str: raise NotImplementedError()
|
def finalize(self) -> str: raise NotImplementedError()
|
||||||
|
|
||||||
class OptionDocsRestrictions:
|
class OptionDocsRestrictions:
|
||||||
def heading_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def heading_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported in options doc", token)
|
raise RuntimeError("md token not supported in options doc", token)
|
||||||
def heading_close(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def heading_close(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported in options doc", token)
|
raise RuntimeError("md token not supported in options doc", token)
|
||||||
def attr_span_begin(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def attr_span_begin(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported in options doc", token)
|
raise RuntimeError("md token not supported in options doc", token)
|
||||||
def example_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def example_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
raise RuntimeError("md token not supported in options doc", token)
|
raise RuntimeError("md token not supported in options doc", token)
|
||||||
|
|
||||||
class OptionsDocBookRenderer(OptionDocsRestrictions, DocBookRenderer):
|
class OptionsDocBookRenderer(OptionDocsRestrictions, DocBookRenderer):
|
||||||
# TODO keep optionsDocBook diff small. remove soon if rendering is still good.
|
# TODO keep optionsDocBook diff small. remove soon if rendering is still good.
|
||||||
def ordered_list_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def ordered_list_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
token.meta['compact'] = False
|
token.meta['compact'] = False
|
||||||
return super().ordered_list_open(token, tokens, i, options, env)
|
return super().ordered_list_open(token, tokens, i)
|
||||||
def bullet_list_open(self, token: Token, tokens: Sequence[Token], i: int, options: OptionsDict,
|
def bullet_list_open(self, token: Token, tokens: Sequence[Token], i: int) -> str:
|
||||||
env: MutableMapping[str, Any]) -> str:
|
|
||||||
token.meta['compact'] = False
|
token.meta['compact'] = False
|
||||||
return super().bullet_list_open(token, tokens, i, options, env)
|
return super().bullet_list_open(token, tokens, i)
|
||||||
|
|
||||||
class DocBookConverter(BaseConverter[OptionsDocBookRenderer]):
|
class DocBookConverter(BaseConverter[OptionsDocBookRenderer]):
|
||||||
__option_block_separator__ = ""
|
__option_block_separator__ = ""
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
from collections.abc import Sequence, MutableMapping
|
from collections.abc import Sequence
|
||||||
from typing import Any, Callable, Optional, Tuple, NamedTuple
|
from typing import Any, Callable, Optional, Tuple, NamedTuple
|
||||||
|
|
||||||
from markdown_it.token import Token
|
from markdown_it.token import Token
|
||||||
from markdown_it.utils import OptionsDict
|
|
||||||
|
|
||||||
OptionLoc = str | dict[str, str]
|
OptionLoc = str | dict[str, str]
|
||||||
Option = dict[str, str | dict[str, str] | list[OptionLoc]]
|
Option = dict[str, str | dict[str, str] | list[OptionLoc]]
|
||||||
@@ -12,4 +11,4 @@ class RenderedOption(NamedTuple):
|
|||||||
lines: list[str]
|
lines: list[str]
|
||||||
links: Optional[list[str]] = None
|
links: Optional[list[str]] = None
|
||||||
|
|
||||||
RenderFn = Callable[[Token, Sequence[Token], int, OptionsDict, MutableMapping[str, Any]], str]
|
RenderFn = Callable[[Token, Sequence[Token], int], str]
|
||||||
|
|||||||
Reference in New Issue
Block a user