Styling: Take offset into consideration when adding templates
This commit is contained in:
parent
30e784b8ec
commit
35db01d316
@ -5,7 +5,7 @@ const u = converse.env.utils;
|
|||||||
const original_timeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;
|
const original_timeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;
|
||||||
|
|
||||||
|
|
||||||
fdescribe("Emojis", function () {
|
describe("Emojis", function () {
|
||||||
describe("The emoji picker", function () {
|
describe("The emoji picker", function () {
|
||||||
|
|
||||||
beforeEach(() => (jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000));
|
beforeEach(() => (jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000));
|
||||||
|
@ -300,6 +300,36 @@ describe("An incoming chat Message", function () {
|
|||||||
await u.waitUntil(() => msg_el.innerHTML.replace(/<!---->/g, '') ===
|
await u.waitUntil(() => msg_el.innerHTML.replace(/<!---->/g, '') ===
|
||||||
'<blockquote> ```\n (println "Hello, world!")</blockquote>\n'+
|
'<blockquote> ```\n (println "Hello, world!")</blockquote>\n'+
|
||||||
'The entire blockquote is a preformatted text block, but this line is plaintext!');
|
'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&mlon=-122.399677#map=18/37.786971/-122.399677">https://www.openstreetmap.org/?mlat=37.786971&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();
|
done();
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
@ -57,7 +57,13 @@ export class MessageText extends String {
|
|||||||
this.payload = [];
|
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 = [];
|
const objs = [];
|
||||||
try {
|
try {
|
||||||
const parse_options = { 'start': /\b(?:([a-z][a-z0-9.+-]*:\/\/)|xmpp:|mailto:|www\.)/gi };
|
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 url_text = text.slice(url_obj.start, url_obj.end);
|
||||||
const filtered_url = u.filterQueryParamsFromURL(url_text);
|
const filtered_url = u.filterQueryParamsFromURL(url_text);
|
||||||
this.addTemplateResult(
|
this.addTemplateResult(
|
||||||
url_obj.start,
|
url_obj.start+offset,
|
||||||
url_obj.end,
|
url_obj.end+offset,
|
||||||
this.show_images && u.isImageURL(url_text) && u.isImageDomainAllowed(url_text) ?
|
this.show_images && u.isImageURL(url_text) && u.isImageDomainAllowed(url_text) ?
|
||||||
u.convertToImageTag(filtered_url, this.onImgLoad, this.onImgClick) :
|
u.convertToImageTag(filtered_url, this.onImgLoad, this.onImgClick) :
|
||||||
u.convertUrlToHyperlink(filtered_url),
|
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 regex = /geo:([\-0-9.]+),([\-0-9.]+)(?:,([\-0-9.]+))?(?:\?(.*))?/g;
|
||||||
const matches = text.matchAll(regex);
|
const matches = text.matchAll(regex);
|
||||||
for (const m of matches) {
|
for (const m of matches) {
|
||||||
this.addTemplateResult(
|
this.addTemplateResult(
|
||||||
m.index,
|
m.index+offset,
|
||||||
m.index+m.input.length,
|
m.index+m.input.length+offset,
|
||||||
u.convertUrlToHyperlink(m.input.replace(regex, _converse.geouri_replacement))
|
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();
|
await api.emojis.initialize();
|
||||||
const references = [...getShortnameReferences(text.toString()), ...getCodePointReferences(text.toString())];
|
const references = [...getShortnameReferences(text.toString()), ...getCodePointReferences(text.toString())];
|
||||||
references.forEach(e => {
|
references.forEach(e => {
|
||||||
this.addTemplateResult(
|
this.addTemplateResult(
|
||||||
e.begin,
|
e.begin+offset,
|
||||||
e.end,
|
e.end+offset,
|
||||||
getEmojiMarkup(e, {'add_title_wrapper': true})
|
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) {
|
if (!this.model.collection) {
|
||||||
// This model doesn't belong to a collection anymore, so it must be
|
// This model doesn't belong to a collection anymore, so it must be
|
||||||
// have been removed in the meantime and can be ignored.
|
// have been removed in the meantime and can be ignored.
|
||||||
log.debug('addMentionReferences: ignoring dangling model');
|
log.debug('addMentions: ignoring dangling model');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const nick = this.model.collection.chatbox.get('nick');
|
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')) {
|
if (this.model.get('is_unstyled') || !api.settings.get('allow_message_styling')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -184,19 +213,20 @@ export class MessageText extends String {
|
|||||||
*/
|
*/
|
||||||
await api.trigger('beforeMessageBodyTransformed', this, {'Synchronous': true});
|
await api.trigger('beforeMessageBodyTransformed', this, {'Synchronous': true});
|
||||||
|
|
||||||
this.addStylingReferences();
|
this.addStyling();
|
||||||
const payload = this.marshall();
|
const payload = this.marshall();
|
||||||
|
let idx = 0; // The text index of the element in the payload
|
||||||
let offset = this.offset;
|
|
||||||
for (const text of payload) {
|
for (const text of payload) {
|
||||||
if (isString(text)) {
|
if (!text) {
|
||||||
this.addHyperlinks(text);
|
continue
|
||||||
this.addMapURLs(text);
|
} else if (isString(text)) {
|
||||||
await this.addEmojis(text);
|
this.addHyperlinks(text, idx);
|
||||||
this.addMentionReferences(text, offset);
|
this.addMapURLs(text, idx);
|
||||||
offset += text.length;
|
await this.addEmojis(text, idx);
|
||||||
|
this.addMentions(text, this.offset+idx);
|
||||||
|
idx += text.length;
|
||||||
} else {
|
} else {
|
||||||
offset += text.begin;
|
idx += text.end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user