| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple, Union
- from .block_parser import BlockParser
- from .core import BaseRenderer, BlockState
- from .inline_parser import InlineParser
- from .plugins import Plugin
- 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: Optional[BaseRenderer] = None,
- block: Optional[BlockParser] = None,
- inline: Optional[InlineParser] = None,
- plugins: Optional[Iterable[Plugin]] = 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: List[Callable[["Markdown", BlockState], None]] = []
- self.before_render_hooks: List[Callable[["Markdown", BlockState], Any]] = []
- self.after_render_hooks: List[
- Callable[["Markdown", Union[str, List[Dict[str, Any]]], BlockState], Union[str, List[Dict[str, Any]]]]
- ] = []
- if plugins:
- for plugin in plugins:
- plugin(self)
- def use(self, plugin: Plugin) -> None:
- plugin(self)
- def render_state(self, state: BlockState) -> Union[str, List[Dict[str, Any]]]:
- data = self._iter_render(state.tokens, state)
- if self.renderer:
- return self.renderer(data, state)
- return list(data)
- def _iter_render(self, tokens: Iterable[Dict[str, Any]], state: BlockState) -> Iterable[Dict[str, Any]]:
- 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) -> Tuple[Union[str, List[Dict[str, Any]]], BlockState]:
- """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 hook2 in self.before_render_hooks:
- hook2(self, state)
- result = self.render_state(state)
- for hook3 in self.after_render_hooks:
- result = hook3(self, result, state)
- return result, state
- def read(
- self, filepath: str, encoding: str = "utf-8", state: Optional[BlockState] = None
- ) -> Tuple[Union[str, List[Dict[str, Any]]], BlockState]:
- if state is None:
- state = self.block.state_cls()
- state.env["__file__"] = filepath
- with open(filepath, "rb") as f:
- s = f.read()
- s2 = s.decode(encoding)
- return self.parse(s2, state)
- def __call__(self, s: str) -> Union[str, List[Dict[str, Any]]]:
- if s is None:
- s = "\n"
- return self.parse(s)[0]
|