conversejs / converse.js

Web-based XMPP/Jabber chat client written in JavaScript

Home Page:http://conversejs.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Multi-line nested quotes display incorrectly

BetaRays opened this issue · comments

Describe the bug
A message such as

> > a
> > b
> c
d

or

> > > a
> > b
c

should display quote levels going multiple lines, but only the first line has multiple levels, and only the first level spans multiple lines.

To Reproduce
Steps to reproduce the behavior:
Send (or receive) one of the above blocks as a message.

Expected behavior
Second-level quotes (and more) should be able to span multiple lines.

Screenshots
image
image

Environment (please complete the following information):

  • Desktop
  • Browser: Firefox
  • Converse.js version: both v10.1.6 and current master (04c3753).

Apparently this patch fixes it (see the context), but I don’t know why the zero-width spaces were there in the first place.

diff --git a/src/shared/styling.js b/src/shared/styling.js
index bf09a649a..d18e881c3 100644
--- a/src/shared/styling.js
+++ b/src/shared/styling.js
@@ -150,8 +150,7 @@ export function getDirectiveTemplate (d, text, offset, options) {
     if (isQuoteDirective(d)) {
         const newtext = text
             // Don't show the directive itself
-            .replace(/\n>\s/g, '\n\u200B\u200B')
-            .replace(/\n>/g, '\n\u200B')
+            .replace(/\n>\s?/g, '\n')
             .replace(/\n$/, ''); // Trim line-break at the end
         return template(newtext, offset, options);
     } else {

@jcbrand Should I open a merge request for this? Or is this a wrong solution?

(The only test this seems to break is one that expects the zero-width spaces to be present, but I can fix it and add a nested quote test.)

The zero-width spaces were added in this commit: 97be0bd, but they don’t seem to be the part that fixes the linked issue.
In any case, the zero-width spaces break this line: https://github.com/conversejs/converse.js/blob/master/src/shared/styling.js#L109.

I also tried this in order to keep the zero-width spaces, but that prevents the removal of > characters, which are added on the next lines.

diff --git a/src/shared/styling.js b/src/shared/styling.js
index bf09a649a..7dba22c45 100644
--- a/src/shared/styling.js
+++ b/src/shared/styling.js
@@ -106,7 +106,7 @@ function getDirectiveLength (d, text, i) {
     const begin = i;
     i += d.length;
     if (isQuoteDirective(d)) {
-        i += text.slice(i).split(/\n[^>]/).shift().length;
+        i += text.slice(i).split(/\n\u200B*[^>\u200B]/).shift().length;
         return i-begin;
     } else if (styling_map[d].type === 'span') {
         const line = text.slice(i).split('\n').shift();

I don’t know if the zero-width spaces have any use besides preventing this removal (which shouldn’t be done in this case).
The only issue I could find with the method removing them is the behavior of

> > a
> >
> > b

(note the absence of a space on the second line)
image

The issue with a > at the end of a line happens because a newline is considered a space by the \s template.

An option would be to use the explicit form of \s to remove \n: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Cheatsheet

Not using zero-width spaces breaks this message:

> https://conversejs.org/
> https://conversejs.org/

This was actually in a test, I don’t know why I thought tests were succeeding with my solution.

I found another solution that keeps zero-width spaces in place:

diff --git a/src/shared/styling.js b/src/shared/styling.js
index bf09a649a..efc5fad0a 100644
--- a/src/shared/styling.js
+++ b/src/shared/styling.js
@@ -106,7 +106,7 @@ function getDirectiveLength (d, text, i) {
     const begin = i;
     i += d.length;
     if (isQuoteDirective(d)) {
-        i += text.slice(i).split(/\n[^>]/).shift().length;
+        i += text.slice(i).split(/\n\u200B*[^>\u200B]/).shift().length;
         return i-begin;
     } else if (styling_map[d].type === 'span') {
         const line = text.slice(i).split('\n').shift();
@@ -150,8 +150,7 @@ export function getDirectiveTemplate (d, text, offset, options) {
     if (isQuoteDirective(d)) {
         const newtext = text
             // Don't show the directive itself
-            .replace(/\n>\s/g, '\n\u200B\u200B')
-            .replace(/\n>/g, '\n\u200B')
+            .replace(/\n\u200B*>\s?/g, m => `\n${'\u200B'.repeat(m.length - 1)}`)
             .replace(/\n$/, ''); // Trim line-break at the end
         return template(newtext, offset, options);
     } else {

I’ll make a pull request once I add some tests for nested quotes.