diff options
Diffstat (limited to 'src/mistune/directives/_base.py')
-rw-r--r-- | src/mistune/directives/_base.py | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/src/mistune/directives/_base.py b/src/mistune/directives/_base.py new file mode 100644 index 0000000..ad326c6 --- /dev/null +++ b/src/mistune/directives/_base.py @@ -0,0 +1,121 @@ +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() |