File size: 3,126 Bytes
d1ceb73 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
import re
class DirectiveParser:
name = 'directive'
@staticmethod
def parse_type(m: re.Match):
raise NotImplementedError()
@staticmethod
def parse_title(m: re.Match):
raise NotImplementedError()
@staticmethod
def parse_content(m: re.Match):
raise NotImplementedError()
@classmethod
def parse_tokens(cls, block, text, state):
if state.depth() >= block.max_nested_level - 1 and cls.name in block.rules:
rules = list(block.rules)
rules.remove(cls.name)
else:
rules = block.rules
child = state.child_state(text)
block.parse(child, rules)
return child.tokens
@staticmethod
def parse_options(m: re.Match):
text = m.group('options')
if not text.strip():
return []
options = []
for line in re.split(r'\n+', text):
line = line.strip()[1:]
if not line:
continue
i = line.find(':')
k = line[:i]
v = line[i + 1:].strip()
options.append((k, v))
return options
class BaseDirective:
parser = DirectiveParser
directive_pattern = None
def __init__(self, plugins):
self._methods = {}
self.__plugins = plugins
def register(self, name, fn):
self._methods[name] = fn
def parse_method(self, block, m, state):
_type = self.parser.parse_type(m)
method = self._methods.get(_type)
if method:
try:
token = method(block, m, state)
except ValueError as e:
token = {'type': 'block_error', 'raw': str(e)}
else:
text = m.group(0)
token = {
'type': 'block_error',
'raw': text,
}
if isinstance(token, list):
for tok in token:
state.append_token(tok)
else:
state.append_token(token)
return token
def parse_directive(self, block, m, state):
raise NotImplementedError()
def register_block_parser(self, md, before=None):
md.block.register(
self.parser.name,
self.directive_pattern,
self.parse_directive,
before=before,
)
def __call__(self, md):
for plugin in self.__plugins:
plugin.parser = self.parser
plugin(self, md)
class DirectivePlugin:
def __init__(self):
self.parser = None
def parse_options(self, m: re.Match):
return self.parser.parse_options(m)
def parse_type(self, m: re.Match):
return self.parser.parse_type(m)
def parse_title(self, m: re.Match):
return self.parser.parse_title(m)
def parse_content(self, m: re.Match):
return self.parser.parse_content(m)
def parse_tokens(self, block, text, state):
return self.parser.parse_tokens(block, text, state)
def parse(self, block, m, state):
raise NotImplementedError()
def __call__(self, md):
raise NotImplementedError()
|