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:
Rohitt Vashishtha 2020-04-13 09:56:25 +05:30 committed by Tim Abbott
parent 2735860f01
commit ce6c57b714
2 changed files with 57 additions and 26 deletions

View File

@ -157,9 +157,10 @@ class BaseHandler:
def generic_handler(processor: Any, output: MutableSequence[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'):
return QuoteHandler(processor, output, fence)
return QuoteHandler(processor, output, fence, default_language)
elif lang in ('math', 'tex', 'latex'):
return TexHandler(processor, output, fence)
else:
@ -171,27 +172,32 @@ def remap_language(lang: str) -> str:
return lang
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)
if m:
fence = m.group('fence')
lang = m.group('lang')
handler = generic_handler(processor, output, fence, lang, run_content_validators)
if not lang and default_language:
lang = default_language
lang = remap_language(lang)
handler = generic_handler(processor, output, fence, lang, run_content_validators, default_language)
processor.push(handler)
else:
output.append(line)
class OuterHandler(BaseHandler):
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.processor = processor
self.run_content_validators = run_content_validators
self.default_language = default_language
def handle_line(self, line: str) -> None:
check_for_new_fence(self.processor, self.output, line,
self.run_content_validators)
self.run_content_validators, self.default_language)
def done(self) -> None:
self.processor.pop()
@ -229,17 +235,19 @@ class CodeHandler(BaseHandler):
self.processor.pop()
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.output = output
self.fence = fence
self.lines: List[str] = []
self.default_language = default_language
def handle_line(self, line: str) -> None:
if line.rstrip() == self.fence:
self.done()
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:
text = '\n'.join(self.lines)
@ -296,7 +304,12 @@ class FencedBlockPreprocessor(markdown.preprocessors.Preprocessor):
processor = self
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)
for line in lines:
@ -313,12 +326,6 @@ class FencedBlockPreprocessor(markdown.preprocessors.Preprocessor):
return output
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:
langclass = LANG_TAG % (lang,)
else:

View File

@ -1348,27 +1348,51 @@ class BugdownTest(ZulipTestCase):
text = "```{}\nconsole.log('Hello World');\n```\n"
# Render without default language
msg_with_js_before = bugdown_convert(text.format('js'))
msg_with_python_before = bugdown_convert(text.format('python'))
msg_without_language_before = bugdown_convert(text.format(''))
msg_with_js = bugdown_convert(text.format('js'))
msg_with_python = bugdown_convert(text.format('python'))
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
do_set_realm_property(realm, 'default_code_block_language', 'javascript')
msg_without_language_after = bugdown_convert(text.format(''))
msg_with_python_after = bugdown_convert(text.format('python'))
msg_without_language_default_js = bugdown_convert(text.format(''))
msg_with_python_default_js = bugdown_convert(text.format('python'))
# Render with default=python
do_set_realm_property(realm, 'default_code_block_language', 'python')
msg_without_language_later = bugdown_convert(text.format(''))
msg_with_none_later = bugdown_convert(text.format('none'))
msg_without_language_default_py = bugdown_convert(text.format(''))
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
do_set_realm_property(realm, 'default_code_block_language', None)
msg_without_language_final = bugdown_convert(text.format(''))
self.assertTrue(msg_with_js_before == msg_without_language_after)
self.assertTrue(msg_with_python_before == msg_with_python_after == msg_without_language_later)
self.assertTrue(msg_without_language_before == msg_with_none_later == msg_without_language_final)
self.assertTrue(msg_with_js == msg_without_language_default_js)
self.assertTrue(msg_with_python == msg_with_python_default_js == msg_without_language_default_py)
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:
user_profile = self.example_user('othello')