Improve spoiler
This commit is contained in:
parent
3c6108298c
commit
627cf37996
7 changed files with 27 additions and 55 deletions
|
@ -12,11 +12,6 @@ from lxml.etree import ParserError, XMLSyntaxError
|
||||||
from judge.highlight_code import highlight_code
|
from judge.highlight_code import highlight_code
|
||||||
from judge.jinja2.markdown.lazy_load import lazy_load as lazy_load_processor
|
from judge.jinja2.markdown.lazy_load import lazy_load as lazy_load_processor
|
||||||
from judge.jinja2.markdown.math import MathInlineGrammar, MathInlineLexer, MathRenderer
|
from judge.jinja2.markdown.math import MathInlineGrammar, MathInlineLexer, MathRenderer
|
||||||
from judge.jinja2.markdown.spoiler import (
|
|
||||||
SpoilerInlineGrammar,
|
|
||||||
SpoilerInlineLexer,
|
|
||||||
SpoilerRenderer,
|
|
||||||
)
|
|
||||||
from judge.utils.camo import client as camo_client
|
from judge.utils.camo import client as camo_client
|
||||||
from judge.utils.texoid import TEXOID_ENABLED, TexoidRenderer
|
from judge.utils.texoid import TEXOID_ENABLED, TexoidRenderer
|
||||||
from .. import registry
|
from .. import registry
|
||||||
|
@ -25,23 +20,22 @@ logger = logging.getLogger("judge.html")
|
||||||
|
|
||||||
NOFOLLOW_WHITELIST = settings.NOFOLLOW_EXCLUDED
|
NOFOLLOW_WHITELIST = settings.NOFOLLOW_EXCLUDED
|
||||||
|
|
||||||
|
|
||||||
class CodeSafeInlineGrammar(mistune.InlineGrammar):
|
class CodeSafeInlineGrammar(mistune.InlineGrammar):
|
||||||
double_emphasis = re.compile(r"^\*{2}([\s\S]+?)()\*{2}(?!\*)") # **word**
|
double_emphasis = re.compile(r"^\*{2}([\s\S]+?)()\*{2}(?!\*)") # **word**
|
||||||
emphasis = re.compile(r"^\*((?:\*\*|[^\*])+?)()\*(?!\*)") # *word*
|
emphasis = re.compile(r"^\*((?:\*\*|[^\*])+?)()\*(?!\*)") # *word*
|
||||||
|
|
||||||
|
|
||||||
class AwesomeInlineGrammar(
|
class AwesomeInlineGrammar(
|
||||||
MathInlineGrammar, SpoilerInlineGrammar, CodeSafeInlineGrammar
|
MathInlineGrammar, CodeSafeInlineGrammar
|
||||||
):
|
):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class AwesomeInlineLexer(MathInlineLexer, SpoilerInlineLexer, mistune.InlineLexer):
|
class AwesomeInlineLexer(MathInlineLexer, mistune.InlineLexer):
|
||||||
grammar_class = AwesomeInlineGrammar
|
grammar_class = AwesomeInlineGrammar
|
||||||
|
|
||||||
|
|
||||||
class AwesomeRenderer(MathRenderer, SpoilerRenderer, mistune.Renderer):
|
class AwesomeRenderer(MathRenderer, mistune.Renderer):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
self.nofollow = kwargs.pop("nofollow", True)
|
self.nofollow = kwargs.pop("nofollow", True)
|
||||||
self.texoid = TexoidRenderer() if kwargs.pop("texoid", False) else None
|
self.texoid = TexoidRenderer() if kwargs.pop("texoid", False) else None
|
||||||
|
@ -129,14 +123,28 @@ class AwesomeRenderer(MathRenderer, SpoilerRenderer, mistune.Renderer):
|
||||||
return super(AwesomeRenderer, self).header(text, level + 2, *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 = "<details><summary style=\"color: brown\">" \
|
||||||
|
+ "<span class=\"spoiler-summary\">{summary}</span>" \
|
||||||
|
+ "</summary>{detail}</details>"
|
||||||
|
|
||||||
|
for entire, summary, detail in matches:
|
||||||
|
detail = markdown(detail, style)
|
||||||
|
new_html = html.format(summary=summary, detail=detail)
|
||||||
|
value = value.replace(entire, new_html)
|
||||||
|
return value
|
||||||
|
|
||||||
@registry.filter
|
@registry.filter
|
||||||
def markdown(value, style, math_engine=None, lazy_load=False):
|
def markdown(value, style, math_engine=None, lazy_load=False, hard_wrap=False):
|
||||||
styles = settings.MARKDOWN_STYLES.get(style, settings.MARKDOWN_DEFAULT_STYLE)
|
styles = settings.MARKDOWN_STYLES.get(style, settings.MARKDOWN_DEFAULT_STYLE)
|
||||||
escape = styles.get("safe_mode", True)
|
escape = styles.get("safe_mode", True)
|
||||||
nofollow = styles.get("nofollow", True)
|
nofollow = styles.get("nofollow", True)
|
||||||
texoid = TEXOID_ENABLED and styles.get("texoid", False)
|
texoid = TEXOID_ENABLED and styles.get("texoid", False)
|
||||||
math = hasattr(settings, "MATHOID_URL") and styles.get("math", False)
|
math = hasattr(settings, "MATHOID_URL") and styles.get("math", False)
|
||||||
|
|
||||||
|
value = create_spoiler(value, style)
|
||||||
post_processors = []
|
post_processors = []
|
||||||
if styles.get("use_camo", False) and camo_client is not None:
|
if styles.get("use_camo", False) and camo_client is not None:
|
||||||
post_processors.append(camo_client.update_tree)
|
post_processors.append(camo_client.update_tree)
|
||||||
|
@ -155,7 +163,7 @@ def markdown(value, style, math_engine=None, lazy_load=False):
|
||||||
inline=AwesomeInlineLexer,
|
inline=AwesomeInlineLexer,
|
||||||
parse_block_html=1,
|
parse_block_html=1,
|
||||||
parse_inline_html=1,
|
parse_inline_html=1,
|
||||||
hard_wrap=True,
|
hard_wrap=hard_wrap,
|
||||||
)
|
)
|
||||||
result = markdown(value)
|
result = markdown(value)
|
||||||
if post_processors:
|
if post_processors:
|
||||||
|
|
|
@ -11,8 +11,8 @@ mistune._pre_tags.append("latex")
|
||||||
|
|
||||||
class MathInlineGrammar(mistune.InlineGrammar):
|
class MathInlineGrammar(mistune.InlineGrammar):
|
||||||
block_math = re.compile(r"^\$\$(.*?)\$\$|^\\\[(.*?)\\\]", re.DOTALL)
|
block_math = re.compile(r"^\$\$(.*?)\$\$|^\\\[(.*?)\\\]", re.DOTALL)
|
||||||
math = re.compile(r"^~(.*?)~|\$(.*?)\$|^\\\((.*?)\\\)", re.DOTALL)
|
math = re.compile(r"^~(.*?)~|^\$(.*?)\$|^\\\((.*?)\\\)", re.DOTALL)
|
||||||
text = re.compile(r"^[\s\S]+?(?=[\\<!\[_*`~$]|\\[\[(]|https?://| {2,}\n|$)")
|
text = re.compile(r"^[\s\S]+?(?=[\\<!\[_*`$]|\\[\[(]|https?://| {2,}\n|$)")
|
||||||
|
|
||||||
|
|
||||||
class MathInlineLexer(mistune.InlineLexer):
|
class MathInlineLexer(mistune.InlineLexer):
|
||||||
|
@ -31,7 +31,7 @@ class MathInlineLexer(mistune.InlineLexer):
|
||||||
return self.renderer.block_math(m.group(1) or m.group(2))
|
return self.renderer.block_math(m.group(1) or m.group(2))
|
||||||
|
|
||||||
def output_math(self, m):
|
def output_math(self, m):
|
||||||
return self.renderer.math(m.group(1) or m.group(2))
|
return self.renderer.math(m.group(1) or m.group(2) or m.group(3))
|
||||||
|
|
||||||
def output_inline_html(self, m):
|
def output_inline_html(self, m):
|
||||||
tag = m.group(1)
|
tag = m.group(1)
|
||||||
|
@ -60,10 +60,10 @@ class MathRenderer(mistune.Renderer):
|
||||||
|
|
||||||
def block_math(self, math):
|
def block_math(self, math):
|
||||||
if self.mathoid is None or not math:
|
if self.mathoid is None or not math:
|
||||||
return r"\[%s\]" % mistune.escape(str(math))
|
return r"$$%s$$" % mistune.escape(str(math))
|
||||||
return self.mathoid.display_math(math)
|
return self.mathoid.display_math(math)
|
||||||
|
|
||||||
def math(self, math):
|
def math(self, math):
|
||||||
if self.mathoid is None or not math:
|
if self.mathoid is None or not math:
|
||||||
return r"\(%s\)" % mistune.escape(str(math))
|
return r"$%s$" % mistune.escape(str(math))
|
||||||
return self.mathoid.inline_math(math)
|
return self.mathoid.inline_math(math)
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
import re
|
|
||||||
import mistune
|
|
||||||
|
|
||||||
|
|
||||||
class SpoilerInlineGrammar(mistune.InlineGrammar):
|
|
||||||
spoiler = re.compile(r"^\|\|(.+?)\s+([\s\S]+?)\s*\|\|")
|
|
||||||
|
|
||||||
|
|
||||||
class SpoilerInlineLexer(mistune.InlineLexer):
|
|
||||||
grammar_class = SpoilerInlineGrammar
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
self.default_rules.insert(0, "spoiler")
|
|
||||||
super(SpoilerInlineLexer, self).__init__(*args, **kwargs)
|
|
||||||
|
|
||||||
def output_spoiler(self, m):
|
|
||||||
return self.renderer.spoiler(m.group(1), m.group(2))
|
|
||||||
|
|
||||||
|
|
||||||
class SpoilerRenderer(mistune.Renderer):
|
|
||||||
def spoiler(self, summary, text):
|
|
||||||
return """<details>
|
|
||||||
<summary style="color: brown">
|
|
||||||
<span class="spoiler-summary">%s</span>
|
|
||||||
</summary>
|
|
||||||
<div class="spoiler-text">%s</div>
|
|
||||||
</details>""" % (
|
|
||||||
summary,
|
|
||||||
text,
|
|
||||||
)
|
|
|
@ -293,11 +293,4 @@ a.view-pdf {
|
||||||
}
|
}
|
||||||
details summary {
|
details summary {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
|
||||||
details[open] p {
|
|
||||||
background: #def;
|
|
||||||
padding: 0.3em !important;
|
|
||||||
border: 1px solid grey;
|
|
||||||
border-radius: 4px;
|
|
||||||
margin-top: 0 !important;
|
|
||||||
}
|
}
|
|
@ -3,6 +3,7 @@ window.MathJax = {
|
||||||
tex2jax: {
|
tex2jax: {
|
||||||
inlineMath: [
|
inlineMath: [
|
||||||
['~', '~'],
|
['~', '~'],
|
||||||
|
['$', '$'],
|
||||||
['\\(', '\\)']
|
['\\(', '\\)']
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -190,7 +190,7 @@ let META_HEADER = [
|
||||||
}
|
}
|
||||||
|
|
||||||
function check_new_message(message, tmp_id, room) {
|
function check_new_message(message, tmp_id, room) {
|
||||||
if (room == "{{room}}") {
|
if (room == room_id) {
|
||||||
$.get({
|
$.get({
|
||||||
url: "{{ url('chat_message_ajax') }}",
|
url: "{{ url('chat_message_ajax') }}",
|
||||||
data: {
|
data: {
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="message-text message-text-other">
|
<div class="message-text message-text-other">
|
||||||
{{message.body | markdown('comment', MATH_ENGINE)|reference|str|safe }}
|
{{message.body | markdown('comment', MATH_ENGINE, hard_wrap=True)|reference|str|safe }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</span>
|
</span>
|
||||||
|
|
Loading…
Reference in a new issue