Commit 35db01d3 authored by JC Brand's avatar JC Brand

Styling: Take offset into consideration when adding templates

parent 30e784b8
......@@ -5,7 +5,7 @@ const u = converse.env.utils;
const original_timeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;
fdescribe("Emojis", function () {
describe("Emojis", function () {
describe("The emoji picker", function () {
beforeEach(() => (jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000));
......
......@@ -300,6 +300,36 @@ describe("An incoming chat Message", function () {
await u.waitUntil(() => msg_el.innerHTML.replace(/<!---->/g, '') ===
'<blockquote> ```\n (println "Hello, world!")</blockquote>\n'+
'The entire blockquote is a preformatted text block, but this line is plaintext!');
msg_text = '> Also, icons.js is loaded from /dist, instead of dist.\nhttps://conversejs.org/docs/html/configuration.html#assets-path'
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> Also, icons.js is loaded from /dist, instead of dist.</blockquote>'+
'<a target="_blank" rel="noopener" href="https://conversejs.org/docs/html/configuration.html#assets-path">https://conversejs.org/docs/html/configuration.html#assets-path</a>');
msg_text = '> Where is it located?\ngeo:37.786971,-122.399677';
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> Where is it located?</blockquote>'+
'<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>');
msg_text = '> What do you think of it?\n :poop:';
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> What do you think of it?</blockquote> <span title=":poop:">💩</span>');
done();
}));
});
......
......@@ -57,7 +57,13 @@ export class MessageText extends String {
this.payload = [];
}
addHyperlinks (text) {
/**
* Look for `http` URIs and return templates that render them as URL links
* @param { String } text
* @param { Integer } offset - The index of the passed in text relative to
* the start of the message body text.
*/
addHyperlinks (text, offset) {
const objs = [];
try {
const parse_options = { 'start': /\b(?:([a-z][a-z0-9.+-]*:\/\/)|xmpp:|mailto:|www\.)/gi };
......@@ -73,8 +79,8 @@ export class MessageText extends String {
const url_text = text.slice(url_obj.start, url_obj.end);
const filtered_url = u.filterQueryParamsFromURL(url_text);
this.addTemplateResult(
url_obj.start,
url_obj.end,
url_obj.start+offset,
url_obj.end+offset,
this.show_images && u.isImageURL(url_text) && u.isImageDomainAllowed(url_text) ?
u.convertToImageTag(filtered_url, this.onImgLoad, this.onImgClick) :
u.convertUrlToHyperlink(filtered_url),
......@@ -82,35 +88,54 @@ export class MessageText extends String {
});
}
addMapURLs (text) {
/**
* Look for `geo` URIs and return templates that render them as URL links
* @param { String } text
* @param { Integer } offset - The index of the passed in text relative to
* the start of the message body text.
*/
addMapURLs (text, offset) {
const regex = /geo:([\-0-9.]+),([\-0-9.]+)(?:,([\-0-9.]+))?(?:\?(.*))?/g;
const matches = text.matchAll(regex);
for (const m of matches) {
this.addTemplateResult(
m.index,
m.index+m.input.length,
m.index+offset,
m.index+m.input.length+offset,
u.convertUrlToHyperlink(m.input.replace(regex, _converse.geouri_replacement))
);
}
}
async addEmojis (text) {
/**
* Look for emojis (shortnames or unicode) and add templates for rendering them.
* @param { String } text
* @param { Integer } offset - The index of the passed in text relative to
* the start of the message body text.
*/
async addEmojis (text, offset) {
await api.emojis.initialize();
const references = [...getShortnameReferences(text.toString()), ...getCodePointReferences(text.toString())];
references.forEach(e => {
this.addTemplateResult(
e.begin,
e.end,
e.begin+offset,
e.end+offset,
getEmojiMarkup(e, {'add_title_wrapper': true})
);
});
}
addMentionReferences (text, offset) {
/**
* Look for mentions included as XEP-0372 references and add templates for
* rendering them.
* @param { String } text
* @param { Integer } offset - The index of the passed in text relative to
* the start of the message body text.
*/
addMentions (text, offset) {
if (!this.model.collection) {
// This model doesn't belong to a collection anymore, so it must be
// have been removed in the meantime and can be ignored.
log.debug('addMentionReferences: ignoring dangling model');
log.debug('addMentions: ignoring dangling model');
return;
}
const nick = this.model.collection.chatbox.get('nick');
......@@ -129,7 +154,11 @@ export class MessageText extends String {
});
}
addStylingReferences () {
/**
* Look for XEP-0393 styling directives and add templates for rendering
* them.
*/
addStyling () {
if (this.model.get('is_unstyled') || !api.settings.get('allow_message_styling')) {
return;
}
......@@ -184,19 +213,20 @@ export class MessageText extends String {
*/
await api.trigger('beforeMessageBodyTransformed', this, {'Synchronous': true});
this.addStylingReferences();
this.addStyling();
const payload = this.marshall();
let offset = this.offset;
let idx = 0; // The text index of the element in the payload
for (const text of payload) {
if (isString(text)) {
this.addHyperlinks(text);
this.addMapURLs(text);
await this.addEmojis(text);
this.addMentionReferences(text, offset);
offset += text.length;
if (!text) {
continue
} else if (isString(text)) {
this.addHyperlinks(text, idx);
this.addMapURLs(text, idx);
await this.addEmojis(text, idx);
this.addMentions(text, this.offset+idx);
idx += text.length;
} else {
offset += text.begin;
idx += text.end;
}
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment