nixos/make-options-doc: reuse markdown instance in mergeJSON

this doesn't construct a new (expensive) parser for every option, making
rendering about 30x faster.
This commit is contained in:
pennae
2022-08-03 00:44:34 +02:00
parent 3aebb4a2be
commit 7a091b2686

View File

@@ -3,6 +3,11 @@ import json
import sys
from typing import Any, Dict, List
# for MD conversion
import mistune
import re
from xml.sax.saxutils import escape, quoteattr
JSON = Dict[str, Any]
class Key:
@@ -41,26 +46,18 @@ def unpivot(options: Dict[Key, Option]) -> Dict[str, JSON]:
result[opt.name] = opt.value
return result
# converts in-place!
def convertMD(options: Dict[str, Any]) -> str:
import mistune
import re
from xml.sax.saxutils import escape, quoteattr
admonitions = {
'.warning': 'warning',
'.important': 'important',
'.note': 'note'
}
class Renderer(mistune.renderers.BaseRenderer):
def __init__(self, path):
self.path = path
def _get_method(self, name):
try:
return super(Renderer, self)._get_method(name)
except AttributeError:
def not_supported(*args, **kwargs):
raise NotImplementedError("md node not supported yet", self.path, name, args, **kwargs)
raise NotImplementedError("md node not supported yet", name, args, **kwargs)
return not_supported
def text(self, text):
@@ -122,42 +119,36 @@ def convertMD(options: Dict[str, Any]) -> str:
def finalize(self, data):
return "".join(data)
plugins = []
def p_command(md):
COMMAND_PATTERN = r'\{command\}`(.*?)`'
def command(md):
def parse(self, m, state):
return ('command', m.group(1))
md.inline.register_rule('command', COMMAND_PATTERN, parse)
md.inline.rules.append('command')
plugins.append(command)
def p_file(md):
FILE_PATTERN = r'\{file\}`(.*?)`'
def file(md):
def parse(self, m, state):
return ('file', m.group(1))
md.inline.register_rule('file', FILE_PATTERN, parse)
md.inline.rules.append('file')
plugins.append(file)
def p_option(md):
OPTION_PATTERN = r'\{option\}`(.*?)`'
def option(md):
def parse(self, m, state):
return ('option', m.group(1))
md.inline.register_rule('option', OPTION_PATTERN, parse)
md.inline.rules.append('option')
plugins.append(option)
def p_manpage(md):
MANPAGE_PATTERN = r'\{manpage\}`(.*?)\((.+?)\)`'
def manpage(md):
def parse(self, m, state):
return ('manpage', m.group(1), m.group(2))
md.inline.register_rule('manpage', MANPAGE_PATTERN, parse)
md.inline.rules.append('manpage')
plugins.append(manpage)
def p_admonition(md):
ADMONITION_PATTERN = re.compile(r'^::: \{([^\n]*?)\}\n(.*?)^:::\n', flags=re.MULTILINE|re.DOTALL)
def admonition(md):
def parse(self, m, state):
return {
'type': 'admonition',
@@ -166,12 +157,21 @@ def convertMD(options: Dict[str, Any]) -> str:
}
md.block.register_rule('admonition', ADMONITION_PATTERN, parse)
md.block.rules.append('admonition')
plugins.append(admonition)
md = mistune.create_markdown(renderer=Renderer(), plugins=[
p_command, p_file, p_option, p_manpage, p_admonition
])
# converts in-place!
def convertMD(options: Dict[str, Any]) -> str:
def convertString(path: str, text: str) -> str:
rendered = mistune.markdown(text, renderer=Renderer(path), plugins=plugins)
try:
rendered = md(text)
# keep trailing spaces so we can diff the generated XML to check for conversion bugs.
return rendered.rstrip() + text[len(text.rstrip()):]
except:
print(f"error in {path}")
raise
def optionIs(option: Dict[str, Any], key: str, typ: str) -> bool:
if key not in option: return False