mirror of https://github.com/zulip/zulip.git
markdown: Fix merging of separate quotations.
Initally, when writing two or more quotes, having a blank line in between them, merges those quotes. This created confusion especially in "quote and reply". This commit fixes such issues. Now two or more quotes having a blank line in between them, will not get merged. This change is correct both for usability and for improving our compatibility with CommonMark. Fixes #14379.
This commit is contained in:
parent
cba7425cdc
commit
620e9cbf72
|
@ -55,22 +55,17 @@ export function wrap_code(code, lang) {
|
|||
}
|
||||
|
||||
function wrap_quote(text) {
|
||||
const paragraphs = text.split("\n\n");
|
||||
const paragraphs = text.split("\n");
|
||||
const quoted_paragraphs = [];
|
||||
|
||||
// Prefix each quoted paragraph with > at the
|
||||
// beginning of each line
|
||||
for (const paragraph of paragraphs) {
|
||||
const lines = paragraph.split("\n");
|
||||
quoted_paragraphs.push(
|
||||
lines
|
||||
.filter((line) => line !== "")
|
||||
.map((line) => "> " + line)
|
||||
.join("\n"),
|
||||
);
|
||||
quoted_paragraphs.push(lines.map((line) => "> " + line).join("\n"));
|
||||
}
|
||||
|
||||
return quoted_paragraphs.join("\n\n");
|
||||
return quoted_paragraphs.join("\n");
|
||||
}
|
||||
|
||||
function wrap_tex(tex) {
|
||||
|
|
|
@ -17,7 +17,7 @@ var block = {
|
|||
hr: /^( *[-*_]){3,} *(?:\n+|$)/,
|
||||
heading: /^ {0,3}(#{1,6}) +([^\n]*?)(?: +#+)? *(?:\n+|$)/,
|
||||
nptable: noop,
|
||||
blockquote: /^(?!( *>\s*($|\n))*($|\n))( *>[^\n]*(\n(?!def)[^\n]+)*\n*)+/,
|
||||
blockquote: /^(?!( *>\s*($|\n))*($|\n))( *>[^\n]*(\n(?!def)[^\n]+)*)+/,
|
||||
list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
|
||||
html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,
|
||||
def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
|
||||
|
|
|
@ -1546,6 +1546,34 @@ class BlockQuoteProcessor(markdown.blockprocessors.BlockQuoteProcessor):
|
|||
r'[ ]{0,3}>[ ]?(.*)')
|
||||
mention_re = re.compile(mention.find_mentions)
|
||||
|
||||
# run() is very slightly forked from the base class; see notes below.
|
||||
def run(self, parent: Element, blocks: List[Any]) -> None:
|
||||
block = blocks.pop(0)
|
||||
m = self.RE.search(block)
|
||||
if m:
|
||||
before = block[:m.start()] # Lines before blockquote
|
||||
# Pass lines before blockquote in recursively for parsing forst.
|
||||
self.parser.parseBlocks(parent, [before])
|
||||
# Remove ``> `` from beginning of each line.
|
||||
block = '\n'.join(
|
||||
[self.clean(line) for line in block[m.start():].split('\n')]
|
||||
)
|
||||
|
||||
# Zulip modification: The next line is patched to match
|
||||
# CommonMark rather than original Markdown. In original
|
||||
# Markdown, blockquotes with a blank line between them were
|
||||
# merged, which makes it impossible to break a blockquote with
|
||||
# a blank line intentionally.
|
||||
#
|
||||
# This is a new blockquote. Create a new parent element.
|
||||
quote = etree.SubElement(parent, 'blockquote')
|
||||
|
||||
# Recursively parse block with blockquote as parent.
|
||||
# change parser state so blockquotes embedded in lists use p tags
|
||||
self.parser.state.set('blockquote')
|
||||
self.parser.parseChunk(quote, block)
|
||||
self.parser.state.reset()
|
||||
|
||||
def clean(self, line: str) -> str:
|
||||
# Silence all the mentions inside blockquotes
|
||||
line = re.sub(self.mention_re, lambda m: "@_{}".format(m.group('match')), line)
|
||||
|
|
|
@ -427,12 +427,12 @@ class FencedBlockPreprocessor(markdown.preprocessors.Preprocessor):
|
|||
return code
|
||||
|
||||
def format_quote(self, text: str) -> str:
|
||||
paragraphs = text.split("\n\n")
|
||||
paragraphs = text.split("\n")
|
||||
quoted_paragraphs = []
|
||||
for paragraph in paragraphs:
|
||||
lines = paragraph.split("\n")
|
||||
quoted_paragraphs.append("\n".join("> " + line for line in lines if line != ''))
|
||||
return "\n\n".join(quoted_paragraphs)
|
||||
quoted_paragraphs.append("\n".join("> " + line for line in lines))
|
||||
return "\n".join(quoted_paragraphs)
|
||||
|
||||
def format_spoiler(self, header: str, text: str) -> str:
|
||||
output = []
|
||||
|
|
|
@ -111,6 +111,22 @@
|
|||
"input": ">\n>\ntext",
|
||||
"expected_output": "<blockquote>\n<p>text</p>\n</blockquote>"
|
||||
},
|
||||
{
|
||||
"name": "multiple_blockquote",
|
||||
"input": "> Hello World!\n\n> Hello Universe!",
|
||||
"expected_output": "<blockquote>\n<p>Hello World!</p>\n</blockquote>\n<blockquote>\n<p>Hello Universe!</p>\n</blockquote>"
|
||||
},
|
||||
{
|
||||
"name": "multiple_blockquote",
|
||||
"input": "```quote\nText in\nmultiple lines.\n```\n\n> Text in a single line.",
|
||||
"expected_output": "<blockquote>\n<p>Text in<br>\nmultiple lines.</p>\n</blockquote>\n<blockquote>\n<p>Text in a single line.</p>\n</blockquote>"
|
||||
},
|
||||
{
|
||||
"name": "multiple_blockquote_with_quote_and_reply",
|
||||
"input": "Hamlet said:\n~~~quote\nCan we talk ?\n~~~\n> Yes !!\n\nWelcome to Open Source.",
|
||||
"expected_output": "<p>Hamlet said:</p>\n<blockquote>\n<p>Can we talk ?</p>\n</blockquote>\n<blockquote>\n<p>Yes !!</p>\n</blockquote>\n<p>Welcome to Open Source.</p>",
|
||||
"text_content": "Hamlet said:\n> Can we talk ?\n\n> Yes !!\n\nWelcome to Open Source."
|
||||
},
|
||||
{
|
||||
"name": "fenced_quote_with_hashtag",
|
||||
"input": "```quote\n# line 1\n#line 2\n```",
|
||||
|
|
|
@ -87,7 +87,8 @@ class FencedBlockPreprocessorTest(ZulipTestCase):
|
|||
'',
|
||||
'> hi',
|
||||
'> bye',
|
||||
'',
|
||||
'> ',
|
||||
'> ',
|
||||
'',
|
||||
'',
|
||||
]
|
||||
|
@ -113,7 +114,8 @@ class FencedBlockPreprocessorTest(ZulipTestCase):
|
|||
'',
|
||||
'',
|
||||
'> bye',
|
||||
'',
|
||||
'> ',
|
||||
'> ',
|
||||
'',
|
||||
'',
|
||||
]
|
||||
|
@ -177,9 +179,11 @@ class FencedBlockPreprocessorTest(ZulipTestCase):
|
|||
expected = [
|
||||
'',
|
||||
'> hi',
|
||||
'',
|
||||
'> ',
|
||||
'> **py:hello()**',
|
||||
'',
|
||||
'> ',
|
||||
'> ',
|
||||
'> ',
|
||||
'',
|
||||
'',
|
||||
]
|
||||
|
|
Loading…
Reference in New Issue