File size: 3,319 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 |
from typing import Optional
from .core import BlockState
from .block_parser import BlockParser
from .inline_parser import InlineParser
class Markdown:
"""Markdown instance to convert markdown text into HTML or other formats.
Here is an example with the HTMLRenderer::
from mistune import HTMLRenderer
md = Markdown(renderer=HTMLRenderer(escape=False))
md('hello **world**')
:param renderer: a renderer to convert parsed tokens
:param block: block level syntax parser
:param inline: inline level syntax parser
:param plugins: mistune plugins to use
"""
def __init__(self, renderer=None,
block: Optional[BlockParser]=None,
inline: Optional[InlineParser]=None,
plugins=None):
if block is None:
block = BlockParser()
if inline is None:
inline = InlineParser()
self.renderer = renderer
self.block: BlockParser = block
self.inline: InlineParser = inline
self.before_parse_hooks = []
self.before_render_hooks = []
self.after_render_hooks = []
if plugins:
for plugin in plugins:
plugin(self)
def use(self, plugin):
plugin(self)
def render_state(self, state: BlockState):
data = self._iter_render(state.tokens, state)
if self.renderer:
return self.renderer(data, state)
return list(data)
def _iter_render(self, tokens, state):
for tok in tokens:
if 'children' in tok:
children = self._iter_render(tok['children'], state)
tok['children'] = list(children)
elif 'text' in tok:
text = tok.pop('text')
# process inline text
# avoid striping emsp or other unicode spaces
tok['children'] = self.inline(text.strip(' \r\n\t\f'), state.env)
yield tok
def parse(self, s: str, state: Optional[BlockState]=None):
"""Parse and convert the given markdown string. If renderer is None,
the returned **result** will be parsed markdown tokens.
:param s: markdown string
:param state: instance of BlockState
:returns: result, state
"""
if state is None:
state = self.block.state_cls()
# normalize line separator
s = s.replace('\r\n', '\n')
s = s.replace('\r', '\n')
if not s.endswith('\n'):
s += '\n'
state.process(s)
for hook in self.before_parse_hooks:
hook(self, state)
self.block.parse(state)
for hook in self.before_render_hooks:
hook(self, state)
result = self.render_state(state)
for hook in self.after_render_hooks:
result = hook(self, result, state)
return result, state
def read(self, filepath, encoding='utf-8', state=None):
if state is None:
state = self.block.state_cls()
state.env['__file__'] = filepath
with open(filepath, 'rb') as f:
s = f.read()
s = s.decode(encoding)
return self.parse(s, state)
def __call__(self, s: str):
if s is None:
s = '\n'
return self.parse(s)[0]
|