Styling: Fix offsetting of mentions mixed in with styles

This commit is contained in:
JC Brand 2020-12-09 15:58:09 +01:00
parent 8572c86941
commit af2df84fc1
3 changed files with 54 additions and 14 deletions

View File

@ -355,6 +355,35 @@ describe("An incoming chat Message", function () {
msg_el = Array.from(view.el.querySelectorAll('converse-chat-message-body')).pop(); msg_el = Array.from(view.el.querySelectorAll('converse-chat-message-body')).pop();
expect(msg_el.innerText).toBe(msg_text); expect(msg_el.innerText).toBe(msg_text);
await u.waitUntil(() => msg_el.innerHTML.replace(/<!---->/g, '') === 'hello world &gt; this is not a quote'); await u.waitUntil(() => msg_el.innerHTML.replace(/<!---->/g, '') === 'hello world &gt; this is not a quote');
msg_text = '> What do you think of it romeo?\n Did you see this romeo?';
msg = $msg({
from: contact_jid,
to: _converse.connection.jid,
type: 'chat',
id: (new Date()).getTime()
}).c('body').t(msg_text).up()
.c('reference', {
'xmlns':'urn:xmpp:reference:0',
'begin':'26',
'end':'31',
'type':'mention',
'uri': _converse.bare_jid
})
.c('reference', {
'xmlns':'urn:xmpp:reference:0',
'begin':'51',
'end':'56',
'type':'mention',
'uri': _converse.bare_jid
}).nodeTree;
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>What do you think of it <span class="mention">romeo</span>?</blockquote>\n Did you see this <span class="mention">romeo</span>?`);
done(); done();
})); }));
}); });

View File

@ -150,8 +150,7 @@ export function getDirectiveTemplate (d, text, model, offset) {
if (isQuoteDirective(d)) { if (isQuoteDirective(d)) {
const newtext = text const newtext = text
.replace(/\n>/g, '\n') // Don't show the directive itself .replace(/\n>/g, '\n') // Don't show the directive itself
.replace(/\n$/, '') // Trim line-break at the end .replace(/\n$/, ''); // Trim line-break at the end
.replace(/^ /, ''); // Trim leading space inside codeblock
return template(newtext, model, offset); return template(newtext, model, offset);
} else { } else {
return template(text, model, offset); return template(text, model, offset);

View File

@ -34,7 +34,7 @@ export class MessageText extends String {
/** /**
* Create a new {@link MessageText} instance. * Create a new {@link MessageText} instance.
* @param { String } text - The plain text that was received from the `<message>` stanza. * @param { String } text - The text to be annotated
* @param { Message } model - The model representing the message to which * @param { Message } model - The model representing the message to which
* this MessageText instance belongs * this MessageText instance belongs
* @param { Integer } offset - The offset of this particular piece of text * @param { Integer } offset - The offset of this particular piece of text
@ -140,15 +140,15 @@ export class MessageText extends String {
const nick = this.model.collection.chatbox.get('nick'); const nick = this.model.collection.chatbox.get('nick');
this.model.get('references')?.forEach(ref => { this.model.get('references')?.forEach(ref => {
const begin = Number(ref.begin)-offset; const begin = Number(ref.begin)-offset;
if (begin >= text.length) { if (begin < 0 || begin >= offset+text.length) {
return; return;
} }
const end = Number(ref.end)-offset; const end = Number(ref.end)-offset;
const mention = text.slice(begin, end); const mention = text.slice(begin, end);
if (mention === nick) { if (mention === nick) {
this.addTemplateResult(begin, end, tpl_mention_with_nick({mention})); this.addTemplateResult(begin+offset, end+offset, tpl_mention_with_nick({mention}));
} else { } else {
this.addTemplateResult(begin, end, tpl_mention({mention})); this.addTemplateResult(begin+offset, end+offset, tpl_mention({mention}));
} }
}); });
} }
@ -167,12 +167,19 @@ export class MessageText extends String {
while (i < this.length) { while (i < this.length) {
const { d, length } = getDirectiveAndLength(this, i); const { d, length } = getDirectiveAndLength(this, i);
if (d && length) { if (d && length) {
const begin = d === '```' ? i+d.length+1 : i+d.length; const is_quote = isQuoteDirective(d);
const end = i+length; const end = i+length;
const slice_end = isQuoteDirective(d) ? end : end-d.length; const slice_end = is_quote ? end : end-d.length;
let slice_begin = d === '```' ? i+d.length+1 : i+d.length;
if (is_quote && this[slice_begin] === ' ') {
// Trim leading space inside codeblock
slice_begin += 1;
}
const offset = slice_begin;
const text = this.slice(slice_begin, slice_end);
references.push({ references.push({
'begin': i, 'begin': i,
'template': getDirectiveTemplate(d, this.slice(begin, slice_end), this.model, i+d.length), 'template': getDirectiveTemplate(d, text, this.model, offset),
end, end,
}); });
i = end; i = end;
@ -198,7 +205,7 @@ export class MessageText extends String {
* instance and add references via the passed in function. * instance and add references via the passed in function.
* @param { Function } func * @param { Function } func
*/ */
addReferences (func) { addAnnotations (func) {
const payload = this.marshall(); const payload = this.marshall();
let idx = 0; // The text index of the element in the payload let idx = 0; // The text index of the element in the payload
for (const text of payload) { for (const text of payload) {
@ -235,12 +242,12 @@ export class MessageText extends String {
await api.trigger('beforeMessageBodyTransformed', this, {'Synchronous': true}); await api.trigger('beforeMessageBodyTransformed', this, {'Synchronous': true});
this.addStyling(); this.addStyling();
this.addReferences(this.addMentions); this.addAnnotations(this.addMentions);
this.addReferences(this.addHyperlinks); this.addAnnotations(this.addHyperlinks);
this.addReferences(this.addMapURLs); this.addAnnotations(this.addMapURLs);
await api.emojis.initialize(); await api.emojis.initialize();
this.addReferences(this.addEmojis); this.addAnnotations(this.addEmojis);
/** /**
* Synchronous event which provides a hook for transforming a chat message's body text * Synchronous event which provides a hook for transforming a chat message's body text
@ -288,6 +295,11 @@ export class MessageText extends String {
return convertASCII2Emoji(text.replace(/\n\n+/g, '\n\n')); return convertASCII2Emoji(text.replace(/\n\n+/g, '\n\n'));
} }
/**
* Take the annotations and return an array of text and TemplateResult
* instances to be rendered to the DOM.
* @method MessageText#marshall
*/
marshall () { marshall () {
let list = [this.toString()]; let list = [this.toString()];
this.references this.references