mirror of
https://github.com/NixOS/nixpkgs.git
synced 2024-11-16 14:54:29 +01:00
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:
parent
4b06b82130
commit
fd9f6c7501
2 changed files with 53 additions and 12 deletions
|
@ -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.
|
||||
|
|
|
@ -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='foo–bar', 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)
|
||||
]
|
||||
|
|
Loading…
Reference in a new issue