瀏覽代碼

Add XEP-372 URI as data attribute to mention element

JC Brand 3 年之前
父節點
當前提交
d8ea42a845

+ 1 - 1
src/headless/plugins/muc/muc.js

@@ -1284,7 +1284,7 @@ const ChatRoomMixin = {
         if (!args.startsWith('@')) {
             args = '@' + args;
         }
-        const [text, references] = this.parseTextForReferences(args); // eslint-disable-line no-unused-vars
+        const [_text, references] = this.parseTextForReferences(args); // eslint-disable-line no-unused-vars
         if (!references.length) {
             const message = __("Error: couldn't find a groupchat participant based on your arguments");
             this.createMessage({ message, 'type': 'error' });

+ 15 - 2
src/headless/shared/parsers.js

@@ -238,6 +238,11 @@ export function getErrorAttributes (stanza) {
     return {};
 }
 
+/**
+ * Given a message stanza, find and return any XEP-0372 references
+ * @param { XMLElement } stana - The message stanza
+ * @returns { Reference }
+ */
 export function getReferences (stanza) {
     return sizzle(`reference[xmlns="${Strophe.NS.REFERENCE}"]`, stanza).map(ref => {
         const anchor = ref.getAttribute('anchor');
@@ -248,9 +253,17 @@ export function getReferences (stanza) {
         }
         const begin = ref.getAttribute('begin');
         const end = ref.getAttribute('end');
+        /**
+         * @typedef { Object } Reference
+         * An object representing XEP-0372 reference data
+         * @property { string } begin
+         * @property { string } end
+         * @property { string } type
+         * @property { String } value
+         * @property { String } uri
+         */
         return {
-            'begin': begin,
-            'end': end,
+            begin, end,
             'type': ref.getAttribute('type'),
             'value': text.slice(begin, end),
             'uri': ref.getAttribute('uri')

+ 2 - 1
src/plugins/chatview/tests/styling.js

@@ -364,7 +364,8 @@ describe("An incoming chat Message", function () {
         await u.waitUntil(() => view.querySelectorAll('.chat-msg__text').length === 12);
         msg_el = Array.from(view.querySelectorAll('converse-chat-message-body')).pop();
         await u.waitUntil(() => msg_el.innerHTML.replace(/<!-.*?->/g, '') ===
-            `<blockquote>What do you think of it <span class="mention">romeo</span>?</blockquote>\n Did you see this <span class="mention">romeo</span>?`);
+            `<blockquote>What do you think of it <span class="mention" data-uri="romeo@montague.lit">romeo</span>?</blockquote>\n `+
+            `Did you see this <span class="mention" data-uri="romeo@montague.lit">romeo</span>?`);
 
         expect(true).toBe(true);
     }));

+ 1 - 1
src/plugins/muc-views/tests/me-messages.js

@@ -51,6 +51,6 @@ describe("A Groupchat Message", function () {
         await view.model.handleMessageStanza(msg);
         await u.waitUntil(() => view.querySelectorAll('.chat-msg__text').length === 3);
         await u.waitUntil(() => sizzle('.chat-msg__text:last', view).pop().innerHTML.replace(/<!-.*?->/g, '') ===
-            'mentions <span class="mention mention--self badge badge-info">romeo</span>');
+            'mentions <span class="mention mention--self badge badge-info" data-uri="xmpp:romeo@montague.lit">romeo</span>');
     }));
 });

+ 20 - 16
src/plugins/muc-views/tests/mentions.js

@@ -1,6 +1,6 @@
 /*global mock, converse */
 
-const { Strophe, $msg, $pres } = converse.env;
+const { Strophe, $msg, $pres, sizzle } = converse.env;
 const u = converse.env.utils;
 
 
@@ -58,10 +58,10 @@ describe("An incoming groupchat message", function () {
                 .c('reference', {'xmlns':'urn:xmpp:reference:0', 'begin':'15', 'end':'23', 'type':'mention', 'uri':'xmpp:mr.robot@montague.lit'}).nodeTree;
         await view.model.handleMessageStanza(msg);
         await u.waitUntil(() => view.querySelector('.chat-msg__text')?.innerHTML.replace(/<!-.*?->/g, '') ===
-            'hello <span class="mention">z3r0</span> '+
-            '<span class="mention mention--self badge badge-info">tom</span> '+
-            '<span class="mention">mr.robot</span>, how are you?');
-        let message = view.querySelector('.chat-msg__text')
+            'hello <span class="mention" data-uri="xmpp:z3r0@montague.lit">z3r0</span> '+
+            '<span class="mention mention--self badge badge-info" data-uri="xmpp:romeo@montague.lit">tom</span> '+
+            '<span class="mention" data-uri="xmpp:mr.robot@montague.lit">mr.robot</span>, how are you?');
+        let message = view.querySelector('.chat-msg__text');
         expect(message.classList.length).toEqual(1);
 
         msg = $msg({
@@ -69,15 +69,15 @@ describe("An incoming groupchat message", function () {
                 id: u.getUniqueId(),
                 to: 'romeo@montague.lit',
                 type: 'groupchat'
-            }).c('body').t('https://conversejs.org/@gibson').up()
-                .c('reference', {'xmlns':'urn:xmpp:reference:0', 'begin':'23', 'end':'29', 'type':'mention', 'uri':'xmpp:gibson@montague.lit'}).nodeTree;
+            }).c('body').t('@gibson').up()
+                .c('reference', {'xmlns':'urn:xmpp:reference:0', 'begin':'1', 'end':'7', 'type':'mention', 'uri':'xmpp:gibson@montague.lit'}).nodeTree;
         await view.model.handleMessageStanza(msg);
-        message = await u.waitUntil(() => view.querySelector('.chat-msg__text'));
+
+        await u.waitUntil(() => view.querySelectorAll('.chat-msg__text').length === 2);
+
+        message = sizzle('converse-chat-message:last .chat-msg__text', view).pop();
         expect(message.classList.length).toEqual(1);
-        expect(message.innerHTML.replace(/<!-.*?->/g, '')).toBe(
-            'hello <span class="mention">z3r0</span> '+
-            '<span class="mention mention--self badge badge-info">tom</span> '+
-            '<span class="mention">mr.robot</span>, how are you?');
+        expect(message.innerHTML.replace(/<!-.*?->/g, '')).toBe('@<span class="mention" data-uri="xmpp:gibson@montague.lit">gibson</span>');
     }));
 
     it("properly renders mentions that contain the pipe character",
@@ -125,7 +125,7 @@ describe("An incoming groupchat message", function () {
                     `</message>`);
 
         const message = await u.waitUntil(() => view.querySelector('.chat-msg__text'));
-        expect(message.innerHTML.replace(/<!-.*?->/g, '')).toBe('hello <span class="mention">ThUnD3r|Gr33n</span>');
+        expect(message.innerHTML.replace(/<!-.*?->/g, '')).toBe('hello <span class="mention" data-uri="xmpp:lounge@montague.lit/ThUnD3r%7CGr33n">ThUnD3r|Gr33n</span>');
     }));
 
     it("highlights all users mentioned via XEP-0372 references in a quoted message",
@@ -160,7 +160,9 @@ describe("An incoming groupchat message", function () {
 
         await view.model.handleMessageStanza(msg);
         await u.waitUntil(() => view.querySelector('.chat-msg__text')?.innerHTML.replace(/<!-.*?->/g, '') ===
-            '<blockquote>hello <span class="mention">z3r0</span> <span class="mention mention--self badge badge-info">tom</span> <span class="mention">mr.robot</span>, how are you?</blockquote>');
+            '<blockquote>hello <span class="mention" data-uri="xmpp:z3r0@montague.lit">z3r0</span> '+
+            '<span class="mention mention--self badge badge-info" data-uri="xmpp:romeo@montague.lit">tom</span> '+
+            '<span class="mention" data-uri="xmpp:mr.robot@montague.lit">mr.robot</span>, how are you?</blockquote>');
         const message = view.querySelector('.chat-msg__text');
         expect(message.classList.length).toEqual(1);
     }));
@@ -423,7 +425,9 @@ describe("A sent groupchat message", function () {
             const last_msg_sel = 'converse-chat-message:last-child .chat-msg__text';
             await u.waitUntil(() =>
                 view.querySelector(last_msg_sel).innerHTML.replace(/<!-.*?->/g, '') ===
-                    'hello <span class="mention">z3r0</span> <span class="mention">gibson</span> <span class="mention">mr.robot</span>, how are you?'
+                'hello <span class="mention" data-uri="xmpp:z3r0@montague.lit">z3r0</span> '+
+                '<span class="mention" data-uri="xmpp:gibson@montague.lit">gibson</span> '+
+                '<span class="mention" data-uri="xmpp:mr.robot@montague.lit">mr.robot</span>, how are you?'
             );
 
             const sent_stanzas = _converse.connection.sent_stanzas;
@@ -537,7 +541,7 @@ describe("A sent groupchat message", function () {
         message_form.onKeyDown(enter_event);
         const message = await u.waitUntil(() => view.querySelector('.chat-msg__text'));
         expect(message.innerHTML.replace(/<!-.*?->/g, '')).toEqual(
-            `Welcome <span class="mention">gibson</span> <span title=":poop:">💩</span> `+
+            `Welcome <span class="mention" data-uri="xmpp:${muc_jid}/gibson">gibson</span> <span title=":poop:">💩</span> `+
             `We have a guide on how to do that here: `+
             `<a target="_blank" rel="noopener" href="https://conversejs.org/docs/html/index.html">https://conversejs.org/docs/html/index.html</a>`);
     }));

+ 4 - 2
src/plugins/muc-views/tests/styling.js

@@ -26,7 +26,9 @@ describe("An incoming groupchat Message", function () {
         const msg_el = Array.from(view.querySelectorAll('converse-chat-message-body')).pop();
         expect(msg_el.innerText).toBe(msg_text);
         await u.waitUntil(() => msg_el.innerHTML.replace(/<!-.*?->/g, '') ===
-            'This <span class="styling-directive">*</span><b>message mentions <span class="mention mention--self badge badge-info">romeo</span></b><span class="styling-directive">*</span>');
+            'This <span class="styling-directive">*</span>'+
+            '<b>message mentions <span class="mention mention--self badge badge-info" data-uri="xmpp:romeo@montague.lit">romeo</span></b>'+
+            '<span class="styling-directive">*</span>');
     }));
 
     it("will not have styling applied to mentioned nicknames themselves",
@@ -51,6 +53,6 @@ describe("An incoming groupchat Message", function () {
         const msg_el = Array.from(view.querySelectorAll('converse-chat-message-body')).pop();
         expect(msg_el.innerText).toBe(msg_text);
         await u.waitUntil(() => msg_el.innerHTML.replace(/<!-.*?->/g, '') ===
-            '<span class="mention">x_y_z_</span> hello');
+            '<span class="mention" data-uri="xmpp:xyz@montague.lit">x_y_z_</span> hello');
     }));
 });

+ 4 - 4
src/shared/rich-text.js

@@ -31,8 +31,8 @@ const isString = s => typeof s === 'string';
 // the zero-width whitespace character
 const collapseLineBreaks = text => text.replace(/\n\n+/g, m => `\n${'\u200B'.repeat(m.length - 2)}\n`);
 
-const tpl_mention_with_nick = o => html`<span class="mention mention--self badge badge-info">${o.mention}</span>`;
-const tpl_mention = o => html`<span class="mention">${o.mention}</span>`;
+const tpl_mention_with_nick = o => html`<span class="mention mention--self badge badge-info" data-uri="${o.uri}">${o.mention}</span>`;
+const tpl_mention = o => html`<span class="mention" data-uri="${o.uri}">${o.mention}</span>`;
 
 /**
  * @class RichText
@@ -201,9 +201,9 @@ export class RichText extends String {
             const end = Number(ref.end) - full_offset;
             const mention = text.slice(begin, end);
             if (mention === this.nick) {
-                this.addTemplateResult(begin + local_offset, end + local_offset, tpl_mention_with_nick({ mention }));
+                this.addTemplateResult(begin + local_offset, end + local_offset, tpl_mention_with_nick({...ref, mention }));
             } else {
-                this.addTemplateResult(begin + local_offset, end + local_offset, tpl_mention({ mention }));
+                this.addTemplateResult(begin + local_offset, end + local_offset, tpl_mention({...ref, mention }));
             }
         });
     }