import logging import re from html.parser import HTMLParser from urllib.parse import urlparse import mistune from django.conf import settings from markupsafe import Markup from lxml import html from lxml.etree import ParserError, XMLSyntaxError from judge.highlight_code import highlight_code from judge.jinja2.markdown.lazy_load import lazy_load as lazy_load_processor from judge.jinja2.markdown.math import MathInlineGrammar, MathInlineLexer, MathRenderer from judge.utils.camo import client as camo_client from judge.utils.texoid import TEXOID_ENABLED, TexoidRenderer from .. import registry logger = logging.getLogger("judge.html") NOFOLLOW_WHITELIST = settings.NOFOLLOW_EXCLUDED class CodeSafeInlineGrammar(mistune.InlineGrammar): double_emphasis = re.compile(r"^\*{2}([\s\S]+?)()\*{2}(?!\*)") # **word** emphasis = re.compile(r"^\*((?:\*\*|[^\*])+?)()\*(?!\*)") # *word* class AwesomeInlineGrammar(MathInlineGrammar, CodeSafeInlineGrammar): pass class AwesomeInlineLexer(MathInlineLexer, mistune.InlineLexer): grammar_class = AwesomeInlineGrammar class AwesomeRenderer(MathRenderer, mistune.Renderer): def __init__(self, *args, **kwargs): self.nofollow = kwargs.pop("nofollow", True) self.texoid = TexoidRenderer() if kwargs.pop("texoid", False) else None self.parser = HTMLParser() super(AwesomeRenderer, self).__init__(*args, **kwargs) def _link_rel(self, href): if href: try: url = urlparse(href) except ValueError: return ' rel="nofollow"' else: if url.netloc and url.netloc not in NOFOLLOW_WHITELIST: return ' rel="nofollow"' return "" def autolink(self, link, is_email=False): text = link = mistune.escape(link) if is_email: link = "mailto:%s" % link return '%s' % (link, self._link_rel(link), text) def table(self, header, body): return ( '
%s
\n" % mistune.escape(code).rstrip()
return highlight_code(code, lang)
def block_html(self, html):
if self.texoid and html.startswith("%s" % mistune.escape(latex, smart_amp=False) elif "error" not in result: img = ( '''' ) % { "svg": result["svg"], "png": result["png"], "width": result["meta"]["width"], "height": result["meta"]["height"], "tail": " /" if self.options.get("use_xhtml") else "", } style = [ "max-width: 100%", "height: %s" % result["meta"]["height"], "max-height: %s" % result["meta"]["height"], "width: %s" % result["meta"]["height"], ] if "inline" in attr: tag = "span" else: tag = "div" style += ["text-align: center"] return '<%s style="%s">%s%s>' % (tag, ";".join(style), img, tag) else: return "
%s" % mistune.escape( result["error"], smart_amp=False ) return super(AwesomeRenderer, self).block_html(html) def header(self, text, level, *args, **kwargs): return super(AwesomeRenderer, self).header(text, level + 2, *args, **kwargs) def create_spoiler(value, style): respoiler = re.compile(r"(^\|\|(.+)\s+([\s\S]+?)\s*\|\|)", re.MULTILINE) matches = re.findall(respoiler, value) html = ( '