summaryrefslogtreecommitdiff
path: root/src/mistune/directives/_base.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/mistune/directives/_base.py')
-rw-r--r--src/mistune/directives/_base.py121
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()