mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-03 21:43:21 +00:00 
			
		
		
		
	message-edit: Patch html tags after edits on new lines.
This commit is contained in:
		@@ -74,6 +74,21 @@ def verify_html(html):
 | 
			
		||||
        return False
 | 
			
		||||
    return True
 | 
			
		||||
 | 
			
		||||
def check_tags(text):
 | 
			
		||||
    # type: (Text) -> Text
 | 
			
		||||
    # The current diffing algorithm produces malformed html when text is
 | 
			
		||||
    # added to existing new lines. This patch manually corrects that.
 | 
			
		||||
    in_tag = False
 | 
			
		||||
    if text.endswith('<'):
 | 
			
		||||
        text = text[:-1]
 | 
			
		||||
    for c in text:
 | 
			
		||||
        if c == '<':
 | 
			
		||||
            in_tag = True
 | 
			
		||||
        elif c == '>' and not in_tag:
 | 
			
		||||
            text = '<' + text
 | 
			
		||||
            break
 | 
			
		||||
    return text
 | 
			
		||||
 | 
			
		||||
def highlight_html_differences(s1, s2):
 | 
			
		||||
    # type: (Text, Text) -> Text
 | 
			
		||||
    differ = diff_match_patch()
 | 
			
		||||
@@ -85,9 +100,15 @@ def highlight_html_differences(s1, s2):
 | 
			
		||||
    idx = 0
 | 
			
		||||
    while idx < len(ops):
 | 
			
		||||
        op, text = ops[idx]
 | 
			
		||||
        next_op = None
 | 
			
		||||
        if idx != len(ops) - 1:
 | 
			
		||||
            next_op, next_text = ops[idx + 1]
 | 
			
		||||
        text = check_tags(text)
 | 
			
		||||
        if idx != 0:
 | 
			
		||||
            prev_op, prev_text = ops[idx - 1]
 | 
			
		||||
            prev_text = check_tags(prev_text)
 | 
			
		||||
            # Remove visual offset from editing newlines
 | 
			
		||||
            if '<p><br>' in text:
 | 
			
		||||
                text = text.replace('<p><br>', '<p>')
 | 
			
		||||
            elif prev_text.endswith('<p>') and text.startswith('<br>'):
 | 
			
		||||
                text = text[4:]
 | 
			
		||||
        if op == diff_match_patch.DIFF_DELETE:
 | 
			
		||||
            chunks, in_tag = chunkize(text, in_tag)
 | 
			
		||||
            retval += highlight_chunks(chunks, highlight_deleted)
 | 
			
		||||
 
 | 
			
		||||
@@ -1232,34 +1232,79 @@ class EditMessageTest(ZulipTestCase):
 | 
			
		||||
    def test_edit_message_history(self):
 | 
			
		||||
        # type: () -> None
 | 
			
		||||
        self.login(self.example_email("hamlet"))
 | 
			
		||||
        msg_id = self.send_message(self.example_email("hamlet"), "Scotland", Recipient.STREAM,
 | 
			
		||||
                                   subject="editing", content="content before edit")
 | 
			
		||||
        new_content = 'content after edit'
 | 
			
		||||
 | 
			
		||||
        result = self.client_patch("/json/messages/" + str(msg_id), {
 | 
			
		||||
            'message_id': msg_id, 'content': new_content
 | 
			
		||||
        # Single-line edit
 | 
			
		||||
        msg_id_1 = self.send_message(self.example_email("hamlet"),
 | 
			
		||||
                                     "Scotland",
 | 
			
		||||
                                     Recipient.STREAM,
 | 
			
		||||
                                     subject="editing",
 | 
			
		||||
                                     content="content before edit")
 | 
			
		||||
        new_content_1 = 'content after edit'
 | 
			
		||||
        result_1 = self.client_patch("/json/messages/" + str(msg_id_1), {
 | 
			
		||||
            'message_id': msg_id_1, 'content': new_content_1
 | 
			
		||||
        })
 | 
			
		||||
        self.assert_json_success(result)
 | 
			
		||||
        self.assert_json_success(result_1)
 | 
			
		||||
 | 
			
		||||
        message_edit_history = self.client_get("/json/messages/" + str(msg_id) + "/history")
 | 
			
		||||
        json_response = ujson.loads(message_edit_history.content.decode('utf-8'))
 | 
			
		||||
        message_history = json_response['message_history']
 | 
			
		||||
        message_edit_history_1 = self.client_get(
 | 
			
		||||
            "/json/messages/" + str(msg_id_1) + "/history")
 | 
			
		||||
        json_response_1 = ujson.loads(
 | 
			
		||||
            message_edit_history_1.content.decode('utf-8'))
 | 
			
		||||
        message_history_1 = json_response_1['message_history']
 | 
			
		||||
 | 
			
		||||
        # Check content of message after edit.
 | 
			
		||||
        self.assertEqual(message_history[0]['rendered_content'],
 | 
			
		||||
        self.assertEqual(message_history_1[0]['rendered_content'],
 | 
			
		||||
                         '<p>content before edit</p>')
 | 
			
		||||
        self.assertEqual(message_history[1]['rendered_content'],
 | 
			
		||||
        self.assertEqual(message_history_1[1]['rendered_content'],
 | 
			
		||||
                         '<p>content after edit</p>')
 | 
			
		||||
        self.assertEqual(message_history[1]['content_html_diff'],
 | 
			
		||||
        self.assertEqual(message_history_1[1]['content_html_diff'],
 | 
			
		||||
                         ('<p>content '
 | 
			
		||||
                          '<span class="highlight_text_deleted">before</span>'
 | 
			
		||||
                          '<span class="highlight_text_inserted">after</span>'
 | 
			
		||||
                          ' edit</p>'))
 | 
			
		||||
 | 
			
		||||
        # Check content of message before edit.
 | 
			
		||||
        self.assertEqual(message_history[1]['prev_rendered_content'],
 | 
			
		||||
        self.assertEqual(message_history_1[1]['prev_rendered_content'],
 | 
			
		||||
                         '<p>content before edit</p>')
 | 
			
		||||
 | 
			
		||||
        # Edits on new lines
 | 
			
		||||
        msg_id_2 = self.send_message(self.example_email("hamlet"),
 | 
			
		||||
                                     "Scotland",
 | 
			
		||||
                                     Recipient.STREAM,
 | 
			
		||||
                                     subject="editing",
 | 
			
		||||
                                     content=('content before edit, line 1\n'
 | 
			
		||||
                                              '\n'
 | 
			
		||||
                                              'content before edit, line 3'))
 | 
			
		||||
        new_content_2 = ('content before edit, line 1\n'
 | 
			
		||||
                         'content after edit, line 2\n'
 | 
			
		||||
                         'content before edit, line 3')
 | 
			
		||||
        result_2 = self.client_patch("/json/messages/" + str(msg_id_2), {
 | 
			
		||||
            'message_id': msg_id_2, 'content': new_content_2
 | 
			
		||||
        })
 | 
			
		||||
        self.assert_json_success(result_2)
 | 
			
		||||
 | 
			
		||||
        message_edit_history_2 = self.client_get(
 | 
			
		||||
            "/json/messages/" + str(msg_id_2) + "/history")
 | 
			
		||||
        json_response_2 = ujson.loads(
 | 
			
		||||
            message_edit_history_2.content.decode('utf-8'))
 | 
			
		||||
        message_history_2 = json_response_2['message_history']
 | 
			
		||||
 | 
			
		||||
        self.assertEqual(message_history_2[0]['rendered_content'],
 | 
			
		||||
                         ('<p>content before edit, line 1</p>\n'
 | 
			
		||||
                          '<p>content before edit, line 3</p>'))
 | 
			
		||||
        self.assertEqual(message_history_2[1]['rendered_content'],
 | 
			
		||||
                         ('<p>content before edit, line 1<br>\n'
 | 
			
		||||
                          'content after edit, line 2<br>\n'
 | 
			
		||||
                          'content before edit, line 3</p>'))
 | 
			
		||||
        self.assertEqual(message_history_2[1]['content_html_diff'],
 | 
			
		||||
                         ('<p>content before edit, line 1</p>'
 | 
			
		||||
                          '<span class="highlight_text_deleted">\n'
 | 
			
		||||
                          '</span><p><span class="highlight_text_inserted">\n'
 | 
			
		||||
                          'content after edit, line 2</span><br>'
 | 
			
		||||
                          '<span class="highlight_text_inserted">\n'
 | 
			
		||||
                          '</span>content before edit, line 3</p>'))
 | 
			
		||||
        self.assertEqual(message_history_2[1]['prev_rendered_content'],
 | 
			
		||||
                         ('<p>content before edit, line 1</p>\n'
 | 
			
		||||
                          '<p>content before edit, line 3</p>'))
 | 
			
		||||
 | 
			
		||||
    def test_edit_cases(self):
 | 
			
		||||
        # type: () -> None
 | 
			
		||||
        """This test verifies the accuracy of construction of Zulip's edit
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user