nixos-render-docs: promote heading id extraction to a core rule

this should've been a core rule from the beginning. not being a core
rule made it always run after smartquotes and replacements, which
could've wrecked the id.
This commit is contained in:
pennae 2023-02-08 13:28:09 +01:00
parent 4b06b82130
commit fd9f6c7501
2 changed files with 53 additions and 12 deletions

View file

@ -351,6 +351,22 @@ def _block_comment_plugin(md: markdown_it.MarkdownIt) -> None:
_HEADER_ID_RE = re.compile(r"\s*\{\s*\#([\w-]+)\s*\}\s*$")
def _heading_ids(md: markdown_it.MarkdownIt) -> None:
def heading_ids(state: markdown_it.rules_core.StateCore) -> None:
tokens = state.tokens
# this is purposely simple and doesn't support classes or other kinds of attributes.
for (i, token) in enumerate(tokens):
if token.type == 'heading_open':
children = tokens[i + 1].children
assert children is not None
if len(children) == 0 or children[-1].type != 'text':
continue
if m := _HEADER_ID_RE.search(children[-1].content):
tokens[i].attrs['id'] = m[1]
children[-1].content = children[-1].content[:-len(m[0])].rstrip()
md.core.ruler.before("replacements", "heading_ids", heading_ids)
class Converter(ABC):
__renderer__: Callable[[Mapping[str, str], markdown_it.MarkdownIt], Renderer]
@ -378,21 +394,10 @@ class Converter(ABC):
self._md.use(_attr_span_plugin)
self._md.use(_inline_comment_plugin)
self._md.use(_block_comment_plugin)
self._md.use(_heading_ids)
self._md.enable(["smartquotes", "replacements"])
def _post_parse(self, tokens: list[Token]) -> list[Token]:
for i in range(0, len(tokens)):
# parse header IDs. this is purposely simple and doesn't support
# classes or other inds of attributes.
if tokens[i].type == 'heading_open':
children = tokens[i + 1].children
assert children is not None
if len(children) == 0 or children[-1].type != 'text':
continue
if m := _HEADER_ID_RE.search(children[-1].content):
tokens[i].attrs['id'] = m[1]
children[-1].content = children[-1].content[:-len(m[0])].rstrip()
# markdown-it signifies wide lists by setting the wrapper paragraphs
# of each item to hidden. this is not useful for our stylesheets, which
# signify this with a special css class on list elements instead.

View file

@ -348,3 +348,39 @@ def test_block_comment() -> None:
assert c._parse("<!--\na\n-->") == []
assert c._parse("<!--\n\na\n\n-->") == []
assert c._parse("<!--\n\n```\n\n\n```\n\n-->") == []
def test_heading_attributes() -> None:
c = Converter({})
assert c._parse("# foo *bar* {#hid}") == [
Token(type='heading_open', tag='h1', nesting=1, attrs={'id': 'hid'}, map=[0, 1], level=0,
children=None, content='', markup='#', info='', meta={}, block=True, hidden=False),
Token(type='inline', tag='', nesting=0, attrs={}, map=[0, 1], level=1,
content='foo *bar* {#hid}', markup='', info='', meta={}, block=True, hidden=False,
children=[
Token(type='text', tag='', nesting=0, attrs={}, map=None, level=0, children=None,
content='foo ', markup='', info='', meta={}, block=False, hidden=False),
Token(type='em_open', tag='em', nesting=1, attrs={}, map=None, level=0, children=None,
content='', markup='*', info='', meta={}, block=False, hidden=False),
Token(type='text', tag='', nesting=0, attrs={}, map=None, level=1, children=None,
content='bar', markup='', info='', meta={}, block=False, hidden=False),
Token(type='em_close', tag='em', nesting=-1, attrs={}, map=None, level=0, children=None,
content='', markup='*', info='', meta={}, block=False, hidden=False),
Token(type='text', tag='', nesting=0, attrs={}, map=None, level=0, children=None,
content='', markup='', info='', meta={}, block=False, hidden=False)
]),
Token(type='heading_close', tag='h1', nesting=-1, attrs={}, map=None, level=0, children=None,
content='', markup='#', info='', meta={}, block=True, hidden=False)
]
assert c._parse("# foo--bar {#id-with--double-dashes}") == [
Token(type='heading_open', tag='h1', nesting=1, attrs={'id': 'id-with--double-dashes'}, map=[0, 1],
level=0, children=None, content='', markup='#', info='', meta={}, block=True, hidden=False),
Token(type='inline', tag='', nesting=0, attrs={}, map=[0, 1], level=1,
content='foo--bar {#id-with--double-dashes}', markup='', info='', meta={}, block=True,
hidden=False,
children=[
Token(type='text', tag='', nesting=0, attrs={}, map=None, level=0, children=None,
content='foobar', markup='', info='', meta={}, block=False, hidden=False)
]),
Token(type='heading_close', tag='h1', nesting=-1, attrs={}, map=None, level=0, children=None,
content='', markup='#', info='', meta={}, block=True, hidden=False)
]