Add XEP-372 URI as data attribute to mention element

This commit is contained in:
JC Brand 2022-07-19 11:57:07 +02:00
parent 085de8405f
commit d8ea42a845
7 changed files with 47 additions and 27 deletions

View File

@ -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' });

View File

@ -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')

View File

@ -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);
}));

View File

@ -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>');
}));
});

View File

@ -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>`);
}));

View File

@ -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');
}));
});

View File

@ -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 }));
}
});
}