mirror of
https://github.com/zulip/zulip.git
synced 2025-11-15 11:22:04 +00:00
markdown: Set default code block language for quotes and latex as well.
In the original implementation, we were checking for the default language inside format_code, which resulted in the setting being ignored when set to quote, math, tex or latex. We shift the validation to `check_for_new_fence` We also update the tests to use a saner naming scheme for the variables.
This commit is contained in:
committed by
Tim Abbott
parent
2735860f01
commit
ce6c57b714
@@ -157,9 +157,10 @@ class BaseHandler:
|
|||||||
|
|
||||||
def generic_handler(processor: Any, output: MutableSequence[str],
|
def generic_handler(processor: Any, output: MutableSequence[str],
|
||||||
fence: str, lang: str,
|
fence: str, lang: str,
|
||||||
run_content_validators: Optional[bool]=False) -> BaseHandler:
|
run_content_validators: Optional[bool]=False,
|
||||||
|
default_language: Optional[str]=None) -> BaseHandler:
|
||||||
if lang in ('quote', 'quoted'):
|
if lang in ('quote', 'quoted'):
|
||||||
return QuoteHandler(processor, output, fence)
|
return QuoteHandler(processor, output, fence, default_language)
|
||||||
elif lang in ('math', 'tex', 'latex'):
|
elif lang in ('math', 'tex', 'latex'):
|
||||||
return TexHandler(processor, output, fence)
|
return TexHandler(processor, output, fence)
|
||||||
else:
|
else:
|
||||||
@@ -171,27 +172,32 @@ def remap_language(lang: str) -> str:
|
|||||||
return lang
|
return lang
|
||||||
|
|
||||||
def check_for_new_fence(processor: Any, output: MutableSequence[str], line: str,
|
def check_for_new_fence(processor: Any, output: MutableSequence[str], line: str,
|
||||||
run_content_validators: Optional[bool]=False) -> None:
|
run_content_validators: Optional[bool]=False,
|
||||||
|
default_language: Optional[str]=None) -> None:
|
||||||
m = FENCE_RE.match(line)
|
m = FENCE_RE.match(line)
|
||||||
if m:
|
if m:
|
||||||
fence = m.group('fence')
|
fence = m.group('fence')
|
||||||
lang = m.group('lang')
|
lang = m.group('lang')
|
||||||
|
if not lang and default_language:
|
||||||
handler = generic_handler(processor, output, fence, lang, run_content_validators)
|
lang = default_language
|
||||||
|
lang = remap_language(lang)
|
||||||
|
handler = generic_handler(processor, output, fence, lang, run_content_validators, default_language)
|
||||||
processor.push(handler)
|
processor.push(handler)
|
||||||
else:
|
else:
|
||||||
output.append(line)
|
output.append(line)
|
||||||
|
|
||||||
class OuterHandler(BaseHandler):
|
class OuterHandler(BaseHandler):
|
||||||
def __init__(self, processor: Any, output: MutableSequence[str],
|
def __init__(self, processor: Any, output: MutableSequence[str],
|
||||||
run_content_validators: Optional[bool]=False) -> None:
|
run_content_validators: Optional[bool]=False,
|
||||||
|
default_language: Optional[str]=None) -> None:
|
||||||
self.output = output
|
self.output = output
|
||||||
self.processor = processor
|
self.processor = processor
|
||||||
self.run_content_validators = run_content_validators
|
self.run_content_validators = run_content_validators
|
||||||
|
self.default_language = default_language
|
||||||
|
|
||||||
def handle_line(self, line: str) -> None:
|
def handle_line(self, line: str) -> None:
|
||||||
check_for_new_fence(self.processor, self.output, line,
|
check_for_new_fence(self.processor, self.output, line,
|
||||||
self.run_content_validators)
|
self.run_content_validators, self.default_language)
|
||||||
|
|
||||||
def done(self) -> None:
|
def done(self) -> None:
|
||||||
self.processor.pop()
|
self.processor.pop()
|
||||||
@@ -229,17 +235,19 @@ class CodeHandler(BaseHandler):
|
|||||||
self.processor.pop()
|
self.processor.pop()
|
||||||
|
|
||||||
class QuoteHandler(BaseHandler):
|
class QuoteHandler(BaseHandler):
|
||||||
def __init__(self, processor: Any, output: MutableSequence[str], fence: str) -> None:
|
def __init__(self, processor: Any, output: MutableSequence[str],
|
||||||
|
fence: str, default_language: Optional[str]=None) -> None:
|
||||||
self.processor = processor
|
self.processor = processor
|
||||||
self.output = output
|
self.output = output
|
||||||
self.fence = fence
|
self.fence = fence
|
||||||
self.lines: List[str] = []
|
self.lines: List[str] = []
|
||||||
|
self.default_language = default_language
|
||||||
|
|
||||||
def handle_line(self, line: str) -> None:
|
def handle_line(self, line: str) -> None:
|
||||||
if line.rstrip() == self.fence:
|
if line.rstrip() == self.fence:
|
||||||
self.done()
|
self.done()
|
||||||
else:
|
else:
|
||||||
check_for_new_fence(self.processor, self.lines, line)
|
check_for_new_fence(self.processor, self.lines, line, default_language=self.default_language)
|
||||||
|
|
||||||
def done(self) -> None:
|
def done(self) -> None:
|
||||||
text = '\n'.join(self.lines)
|
text = '\n'.join(self.lines)
|
||||||
@@ -296,7 +304,12 @@ class FencedBlockPreprocessor(markdown.preprocessors.Preprocessor):
|
|||||||
processor = self
|
processor = self
|
||||||
self.handlers: List[BaseHandler] = []
|
self.handlers: List[BaseHandler] = []
|
||||||
|
|
||||||
handler = OuterHandler(processor, output, self.run_content_validators)
|
default_language = None
|
||||||
|
try:
|
||||||
|
default_language = self.md.zulip_realm.default_code_block_language
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
handler = OuterHandler(processor, output, self.run_content_validators, default_language)
|
||||||
self.push(handler)
|
self.push(handler)
|
||||||
|
|
||||||
for line in lines:
|
for line in lines:
|
||||||
@@ -313,12 +326,6 @@ class FencedBlockPreprocessor(markdown.preprocessors.Preprocessor):
|
|||||||
return output
|
return output
|
||||||
|
|
||||||
def format_code(self, lang: str, text: str) -> str:
|
def format_code(self, lang: str, text: str) -> str:
|
||||||
if not lang:
|
|
||||||
try:
|
|
||||||
lang = self.md.zulip_realm.default_code_block_language
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
lang = remap_language(lang)
|
|
||||||
if lang:
|
if lang:
|
||||||
langclass = LANG_TAG % (lang,)
|
langclass = LANG_TAG % (lang,)
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -1348,27 +1348,51 @@ class BugdownTest(ZulipTestCase):
|
|||||||
text = "```{}\nconsole.log('Hello World');\n```\n"
|
text = "```{}\nconsole.log('Hello World');\n```\n"
|
||||||
|
|
||||||
# Render without default language
|
# Render without default language
|
||||||
msg_with_js_before = bugdown_convert(text.format('js'))
|
msg_with_js = bugdown_convert(text.format('js'))
|
||||||
msg_with_python_before = bugdown_convert(text.format('python'))
|
msg_with_python = bugdown_convert(text.format('python'))
|
||||||
msg_without_language_before = bugdown_convert(text.format(''))
|
msg_without_language = bugdown_convert(text.format(''))
|
||||||
|
msg_with_quote = bugdown_convert(text.format('quote'))
|
||||||
|
msg_with_math = bugdown_convert(text.format('math'))
|
||||||
|
|
||||||
# Render with default=javascript
|
# Render with default=javascript
|
||||||
do_set_realm_property(realm, 'default_code_block_language', 'javascript')
|
do_set_realm_property(realm, 'default_code_block_language', 'javascript')
|
||||||
msg_without_language_after = bugdown_convert(text.format(''))
|
msg_without_language_default_js = bugdown_convert(text.format(''))
|
||||||
msg_with_python_after = bugdown_convert(text.format('python'))
|
msg_with_python_default_js = bugdown_convert(text.format('python'))
|
||||||
|
|
||||||
# Render with default=python
|
# Render with default=python
|
||||||
do_set_realm_property(realm, 'default_code_block_language', 'python')
|
do_set_realm_property(realm, 'default_code_block_language', 'python')
|
||||||
msg_without_language_later = bugdown_convert(text.format(''))
|
msg_without_language_default_py = bugdown_convert(text.format(''))
|
||||||
msg_with_none_later = bugdown_convert(text.format('none'))
|
msg_with_none_default_py = bugdown_convert(text.format('none'))
|
||||||
|
|
||||||
|
# Render with default=quote
|
||||||
|
do_set_realm_property(realm, 'default_code_block_language', 'quote')
|
||||||
|
msg_without_language_default_quote = bugdown_convert(text.format(''))
|
||||||
|
|
||||||
|
# Render with default=math
|
||||||
|
do_set_realm_property(realm, 'default_code_block_language', 'math')
|
||||||
|
msg_without_language_default_math = bugdown_convert(text.format(''))
|
||||||
|
|
||||||
# Render without default language
|
# Render without default language
|
||||||
do_set_realm_property(realm, 'default_code_block_language', None)
|
do_set_realm_property(realm, 'default_code_block_language', None)
|
||||||
msg_without_language_final = bugdown_convert(text.format(''))
|
msg_without_language_final = bugdown_convert(text.format(''))
|
||||||
|
|
||||||
self.assertTrue(msg_with_js_before == msg_without_language_after)
|
self.assertTrue(msg_with_js == msg_without_language_default_js)
|
||||||
self.assertTrue(msg_with_python_before == msg_with_python_after == msg_without_language_later)
|
self.assertTrue(msg_with_python == msg_with_python_default_js == msg_without_language_default_py)
|
||||||
self.assertTrue(msg_without_language_before == msg_with_none_later == msg_without_language_final)
|
self.assertTrue(msg_with_quote == msg_without_language_default_quote)
|
||||||
|
self.assertTrue(msg_with_math == msg_without_language_default_math)
|
||||||
|
self.assertTrue(msg_without_language == msg_with_none_default_py == msg_without_language_final)
|
||||||
|
|
||||||
|
# Test checking inside nested quotes
|
||||||
|
nested_text = "````quote\n\n{}\n\n{}````".format(text.format('js'), text.format(''))
|
||||||
|
do_set_realm_property(realm, 'default_code_block_language', 'javascript')
|
||||||
|
rendered = bugdown_convert(nested_text)
|
||||||
|
with_language, without_language = re.findall(r'<pre>(.*?)$', rendered, re.MULTILINE)
|
||||||
|
self.assertTrue(with_language == without_language)
|
||||||
|
|
||||||
|
do_set_realm_property(realm, 'default_code_block_language', None)
|
||||||
|
rendered = bugdown_convert(nested_text)
|
||||||
|
with_language, without_language = re.findall(r'<pre>(.*?)$', rendered, re.MULTILINE)
|
||||||
|
self.assertFalse(with_language == without_language)
|
||||||
|
|
||||||
def test_mention_wildcard(self) -> None:
|
def test_mention_wildcard(self) -> None:
|
||||||
user_profile = self.example_user('othello')
|
user_profile = self.example_user('othello')
|
||||||
|
|||||||
Reference in New Issue
Block a user