Преглед изворни кода

Styling: quotes should start on newlines

And when nested, have no spaces between them.
JC Brand пре 4 година
родитељ
комит
58586ab2e4
2 измењених фајлова са 28 додато и 5 уклоњено
  1. 19 3
      spec/styling.js
  2. 9 2
      src/shared/message/styling.js

+ 19 - 3
spec/styling.js

@@ -269,13 +269,21 @@ describe("An incoming chat Message", function () {
             'This is <span class="styling-directive">`</span><code>also _quoted_</code><span class="styling-directive">`</span></blockquote>\n'+
             'This is not quoted');
 
-        msg_text = `> > This is doubly quoted text`;
+        msg_text = `> > This is NOT doubly quoted text`;
         msg = mock.createChatMessage(_converse, contact_jid, msg_text)
         await _converse.handleMessageStanza(msg);
         await new Promise(resolve => view.model.messages.once('rendered', resolve));
         msg_el = Array.from(view.el.querySelectorAll('converse-chat-message-body')).pop();
         expect(msg_el.innerText).toBe(msg_text);
-                await u.waitUntil(() => msg_el.innerHTML.replace(/<!---->/g, '') === "<blockquote> <blockquote> This is doubly quoted text</blockquote></blockquote>");
+                await u.waitUntil(() => msg_el.innerHTML.replace(/<!---->/g, '') === "<blockquote> &gt; This is NOT doubly quoted text</blockquote>");
+
+        msg_text = `>> This is doubly quoted text`;
+        msg = mock.createChatMessage(_converse, contact_jid, msg_text)
+        await _converse.handleMessageStanza(msg);
+        await new Promise(resolve => view.model.messages.once('rendered', resolve));
+        msg_el = Array.from(view.el.querySelectorAll('converse-chat-message-body')).pop();
+        expect(msg_el.innerText).toBe(msg_text);
+                await u.waitUntil(() => msg_el.innerHTML.replace(/<!---->/g, '') === "<blockquote><blockquote> This is doubly quoted text</blockquote></blockquote>");
 
         msg_text = ">```\n>ignored\n> <span></span> (println \"Hello, world!\")\n>```\n> This should show up as monospace, preformatted text ^";
         msg = mock.createChatMessage(_converse, contact_jid, msg_text)
@@ -320,7 +328,7 @@ describe("An incoming chat Message", function () {
         await u.waitUntil(() => msg_el.innerHTML.replace(/<!---->/g, '') ===
             '<blockquote> Where is it located?</blockquote>\n'+
             '<a target="_blank" rel="noopener" '+
-               'href="https://www.openstreetmap.org/?mlat=37.786971&amp;mlon=-122.399677#map=18/37.786971/-122.399677">https://www.openstreetmap.org/?mlat=37.786971&amp;mlon=-122.399677#map=18/37.786971/-122.399677</a>');
+                'href="https://www.openstreetmap.org/?mlat=37.786971&amp;mlon=-122.399677#map=18/37.786971/-122.399677">https://www.openstreetmap.org/?mlat=37.786971&amp;mlon=-122.399677#map=18/37.786971/-122.399677</a>');
 
         msg_text = '> What do you think of it?\n :poop:';
         msg = mock.createChatMessage(_converse, contact_jid, msg_text)
@@ -339,6 +347,14 @@ describe("An incoming chat Message", function () {
         expect(msg_el.innerText).toBe(msg_text);
         await u.waitUntil(() => msg_el.innerHTML.replace(/<!---->/g, '') ===
             '<blockquote> What do you think of it?</blockquote>\n<span class="styling-directive">~</span><del>hello</del><span class="styling-directive">~</span>');
+
+        msg_text = 'hello world > this is not a quote';
+        msg = mock.createChatMessage(_converse, contact_jid, msg_text)
+        await _converse.handleMessageStanza(msg);
+        await new Promise(resolve => view.model.messages.once('rendered', resolve));
+        msg_el = Array.from(view.el.querySelectorAll('converse-chat-message-body')).pop();
+        expect(msg_el.innerText).toBe(msg_text);
+        await u.waitUntil(() => msg_el.innerHTML.replace(/<!---->/g, '') === 'hello world &gt; this is not a quote');
         done();
     }));
 });

+ 9 - 2
src/shared/message/styling.js

@@ -34,7 +34,6 @@ const styling_templates = {
 
 /**
  * Checks whether a given character "d" at index "i" of "text" is a valid opening or closing directive.
- * It's valid if it's not part of a word.
  * @param { String } d - The potential directive
  * @param { String } text - The text in which  the directive appears
  * @param { Number } i - The directive index
@@ -48,6 +47,14 @@ function isValidDirective (d, text, i, opening) {
         if (i > 1 && regex.test(text.slice(i-1))) {
             return false;
         }
+        const is_quote = isQuoteDirective(d);
+        if (is_quote && i > 0 && text[i-1] !== '\n') {
+            // Quote directives must be on newlines
+            return false;
+        } else if (!is_quote && d === text[i+1]) {
+            // Immediately followed by another directive of the same type
+            return false;
+        }
     } else {
         const regex = RegExp(dont_escape.includes(d) ? `^${d}(\\p{L}|\\p{N})` : `^\\${d}(\\p{L}|\\p{N})`, 'u');
         if (i < text.length-1 && regex.test(text.slice(i))) {
@@ -68,7 +75,7 @@ function getDirective (text, i, opening=true) {
     let d;
     if ((/(^```\s*\n|^```\s*$)/).test(text.slice(i)) && (i === 0 || text[i-1] === '\n' || text[i-1] === '>')) {
         d = text.slice(i, i+3);
-    } else if (styling_directives.includes(text.slice(i, i+1)) && text[i] !== text[i+1]) {
+    } else if (styling_directives.includes(text.slice(i, i+1))) {
         d = text.slice(i, i+1);
         if (!isValidDirective(d, text, i, opening)) return null;
     } else {