from babel import dates from jinja2 import contextfilter, Markup import markdown from pathlib import Path from markdown.extensions import Extension from markdown.blockprocessors import BlockProcessor class Jinja2Processor(BlockProcessor): def test(self, parent, block): return block.startswith("{%") or block.startswith("{{") def run(self, parent, blocks): block = blocks.pop(0) sibling = self.lastChild(parent) if sibling is not None: if sibling.tail: sibling.tail = sibling.tail + block else: sibling.tail = block else: if parent.text: parent.text = parent.text + block else: parent.text = block return True class IgnoreExtension(Extension): def extendMarkdown(self, md, md_globals): md.parser.blockprocessors.add( "jinja2", Jinja2Processor(md.parser), ">hashheader" ) @contextfilter def markdown2html(context, text, render=True): result = markdown.markdown( text, extensions=[IgnoreExtension(), "markdown.extensions.extra"], output_format="html5", tab_length=2, ) if render: result = context.environment.from_string(result).render(context) if context.eval_ctx.autoescape: result = Markup(result) return result def merge_dict(a, b): if isinstance(a, list): return [merge_dict(i, b) for i in a] return {**a, **b} def fileglob(path, root): return [p.relative_to(root) for p in Path(root).glob(path)] def join_url(a, b): return a.rstrip("/") + "/" + b.lstrip("/") @contextfilter def format_date(context, *args, **kwargs): kwargs.setdefault("locale", context["request"].locale_name) return dates.format_date(*args, **kwargs) @contextfilter def format_datetime(context, *args, **kwargs): kwargs.setdefault("locale", context["request"].locale_name) return dates.format_datetime(*args, **kwargs)