Render images from URLs
This commit is contained in:
parent
c738d085c4
commit
5a1b308edd
@ -1347,6 +1347,9 @@
|
|||||||
#conversejs .chatbox .chat-body .chat-info.chat-date {
|
#conversejs .chatbox .chat-body .chat-info.chat-date {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-top: 1em; }
|
margin-top: 1em; }
|
||||||
|
#conversejs .chatbox .chat-body .chat-image {
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%; }
|
||||||
#conversejs .chatbox .chat-body .chat-message {
|
#conversejs .chatbox .chat-body .chat-message {
|
||||||
margin: 0.3em; }
|
margin: 0.3em; }
|
||||||
#conversejs .chatbox .chat-body .chat-message span {
|
#conversejs .chatbox .chat-body .chat-message span {
|
||||||
|
@ -154,6 +154,10 @@
|
|||||||
margin-top: 1em;
|
margin-top: 1em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.chat-image {
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
}
|
||||||
.chat-message {
|
.chat-message {
|
||||||
margin: 0.3em;
|
margin: 0.3em;
|
||||||
span {
|
span {
|
||||||
|
126
spec/chatbox.js
126
spec/chatbox.js
@ -819,19 +819,6 @@
|
|||||||
expect(msg.html()).toEqual('<p>This message contains <em>some</em> <b>markup</b></p>');
|
expect(msg.html()).toEqual('<p>This message contains <em>some</em> <b>markup</b></p>');
|
||||||
}.bind(converse));
|
}.bind(converse));
|
||||||
|
|
||||||
it("can contain hyperlinks, which will be clickable", function () {
|
|
||||||
var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
|
|
||||||
test_utils.openChatBoxFor(contact_jid);
|
|
||||||
var view = this.chatboxviews.get(contact_jid);
|
|
||||||
var message = 'This message contains a hyperlink: www.opkode.com';
|
|
||||||
spyOn(view, 'sendMessage').andCallThrough();
|
|
||||||
test_utils.sendMessage(view, message);
|
|
||||||
expect(view.sendMessage).toHaveBeenCalled();
|
|
||||||
var msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
|
|
||||||
expect(msg.text()).toEqual(message);
|
|
||||||
expect(msg.html()).toEqual('This message contains a hyperlink: <a target="_blank" rel="noopener" href="http://www.opkode.com">www.opkode.com</a>');
|
|
||||||
}.bind(converse));
|
|
||||||
|
|
||||||
it("should display emoticons correctly", function () {
|
it("should display emoticons correctly", function () {
|
||||||
var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
|
var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||||
test_utils.openChatBoxFor(contact_jid);
|
test_utils.openChatBoxFor(contact_jid);
|
||||||
@ -856,40 +843,99 @@
|
|||||||
}
|
}
|
||||||
}.bind(converse));
|
}.bind(converse));
|
||||||
|
|
||||||
it("will have properly escaped URLs", function () {
|
it("can contain hyperlinks, which will be clickable", function () {
|
||||||
var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
|
var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||||
test_utils.openChatBoxFor(contact_jid);
|
test_utils.openChatBoxFor(contact_jid);
|
||||||
var view = this.chatboxviews.get(contact_jid);
|
var view = converse.chatboxviews.get(contact_jid);
|
||||||
|
var message = 'This message contains a hyperlink: www.opkode.com';
|
||||||
spyOn(view, 'sendMessage').andCallThrough();
|
spyOn(view, 'sendMessage').andCallThrough();
|
||||||
|
runs(function () {
|
||||||
|
test_utils.sendMessage(view, message);
|
||||||
|
});
|
||||||
|
waits(500);
|
||||||
|
runs(function () {
|
||||||
|
expect(view.sendMessage).toHaveBeenCalled();
|
||||||
|
var msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
|
||||||
|
expect(msg.text()).toEqual(message);
|
||||||
|
expect(msg.html()).toEqual('This message contains a hyperlink: <a target="_blank" rel="noopener" href="http://www.opkode.com">www.opkode.com</a>');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
var message = "http://www.opkode.com/'onmouseover='alert(1)'whatever";
|
it("will have properly escaped URLs", function () {
|
||||||
test_utils.sendMessage(view, message);
|
if (/PhantomJS/.test(window.navigator.userAgent)) {
|
||||||
expect(view.sendMessage).toHaveBeenCalled();
|
// Flaky under PhantomJS due to timeouts
|
||||||
var msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
|
return;
|
||||||
expect(msg.text()).toEqual(message);
|
}
|
||||||
expect(msg.html()).toEqual('<a target="_blank" rel="noopener" href="http://www.opkode.com/%27onmouseover=%27alert%281%29%27whatever">http://www.opkode.com/\'onmouseover=\'alert(1)\'whatever</a>');
|
// TODO: make these local urls
|
||||||
|
var message, msg;
|
||||||
|
var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||||
|
test_utils.openChatBoxFor(contact_jid);
|
||||||
|
var view = converse.chatboxviews.get(contact_jid);
|
||||||
|
spyOn(view, 'sendMessage').andCallThrough();
|
||||||
|
runs(function () {
|
||||||
|
message = "http://www.opkode.com/'onmouseover='alert(1)'whatever";
|
||||||
|
test_utils.sendMessage(view, message);
|
||||||
|
});
|
||||||
|
waits(500);
|
||||||
|
runs(function () {
|
||||||
|
expect(view.sendMessage).toHaveBeenCalled();
|
||||||
|
msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
|
||||||
|
expect(msg.text()).toEqual(message);
|
||||||
|
expect(msg.html()).toEqual('<a target="_blank" rel="noopener" href="http://www.opkode.com/%27onmouseover=%27alert%281%29%27whatever">http://www.opkode.com/\'onmouseover=\'alert(1)\'whatever</a>');
|
||||||
|
|
||||||
message = 'http://www.opkode.com/"onmouseover="alert(1)"whatever';
|
message = 'http://www.opkode.com/"onmouseover="alert(1)"whatever';
|
||||||
test_utils.sendMessage(view, message);
|
test_utils.sendMessage(view, message);
|
||||||
expect(view.sendMessage).toHaveBeenCalled();
|
});
|
||||||
msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
|
waits(500);
|
||||||
expect(msg.text()).toEqual(message);
|
runs(function () {
|
||||||
expect(msg.html()).toEqual('<a target="_blank" rel="noopener" href="http://www.opkode.com/%22onmouseover=%22alert%281%29%22whatever">http://www.opkode.com/"onmouseover="alert(1)"whatever</a>');
|
expect(view.sendMessage).toHaveBeenCalled();
|
||||||
|
msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
|
||||||
|
expect(msg.text()).toEqual(message);
|
||||||
|
expect(msg.html()).toEqual('<a target="_blank" rel="noopener" href="http://www.opkode.com/%22onmouseover=%22alert%281%29%22whatever">http://www.opkode.com/"onmouseover="alert(1)"whatever</a>');
|
||||||
|
|
||||||
message = "https://en.wikipedia.org/wiki/Ender's_Game";
|
message = "https://en.wikipedia.org/wiki/Ender's_Game";
|
||||||
test_utils.sendMessage(view, message);
|
test_utils.sendMessage(view, message);
|
||||||
expect(view.sendMessage).toHaveBeenCalled();
|
});
|
||||||
msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
|
waits(500);
|
||||||
expect(msg.text()).toEqual(message);
|
runs(function () {
|
||||||
expect(msg.html()).toEqual('<a target="_blank" rel="noopener" href="https://en.wikipedia.org/wiki/Ender%27s_Game">https://en.wikipedia.org/wiki/Ender\'s_Game</a>');
|
expect(view.sendMessage).toHaveBeenCalled();
|
||||||
|
msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
|
||||||
|
expect(msg.text()).toEqual(message);
|
||||||
|
expect(msg.html()).toEqual('<a target="_blank" rel="noopener" href="https://en.wikipedia.org/wiki/Ender%27s_Game">https://en.wikipedia.org/wiki/Ender\'s_Game</a>');
|
||||||
|
|
||||||
message = "https://en.wikipedia.org/wiki/Ender%27s_Game";
|
message = "https://en.wikipedia.org/wiki/Ender%27s_Game";
|
||||||
test_utils.sendMessage(view, message);
|
test_utils.sendMessage(view, message);
|
||||||
expect(view.sendMessage).toHaveBeenCalled();
|
});
|
||||||
msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
|
waits(500);
|
||||||
expect(msg.text()).toEqual(message);
|
runs(function () {
|
||||||
expect(msg.html()).toEqual('<a target="_blank" rel="noopener" href="https://en.wikipedia.org/wiki/Ender%27s_Game">https://en.wikipedia.org/wiki/Ender%27s_Game</a>');
|
expect(view.sendMessage).toHaveBeenCalled();
|
||||||
}.bind(converse));
|
msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
|
||||||
|
expect(msg.text()).toEqual(message);
|
||||||
|
expect(msg.html()).toEqual('<a target="_blank" rel="noopener" href="https://en.wikipedia.org/wiki/Ender%27s_Game">https://en.wikipedia.org/wiki/Ender%27s_Game</a>');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("will render images from their URLs", function () {
|
||||||
|
if (/PhantomJS/.test(window.navigator.userAgent)) {
|
||||||
|
// Doesn't work when running tests in PhantomJS, since
|
||||||
|
// the page is loaded via file:///
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var message = document.URL.split(window.location.pathname)[0] + "/logo/conversejs.svg";
|
||||||
|
var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||||
|
test_utils.openChatBoxFor(contact_jid);
|
||||||
|
var view = converse.chatboxviews.get(contact_jid);
|
||||||
|
spyOn(view, 'sendMessage').andCallThrough();
|
||||||
|
runs(function () {
|
||||||
|
test_utils.sendMessage(view, message);
|
||||||
|
});
|
||||||
|
waits(500);
|
||||||
|
runs(function () {
|
||||||
|
expect(view.sendMessage).toHaveBeenCalled();
|
||||||
|
var msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
|
||||||
|
expect(msg.html()).toEqual('<img src="'+message+'" class="chat-image">');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
}.bind(converse));
|
}.bind(converse));
|
||||||
|
|
||||||
|
38
src/utils.js
38
src/utils.js
@ -20,6 +20,16 @@
|
|||||||
'list-multi': 'dropdown'
|
'list-multi': 'dropdown'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var isImage = function (url) {
|
||||||
|
var deferred = new $.Deferred();
|
||||||
|
$("<img>", {
|
||||||
|
src: url,
|
||||||
|
error: deferred.reject,
|
||||||
|
load: deferred.resolve
|
||||||
|
});
|
||||||
|
return deferred.promise();
|
||||||
|
};
|
||||||
|
|
||||||
$.expr[':'].emptyVal = function(obj){
|
$.expr[':'].emptyVal = function(obj){
|
||||||
return obj.value === '';
|
return obj.value === '';
|
||||||
};
|
};
|
||||||
@ -34,19 +44,27 @@
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$.fn.throttledHTML = _.throttle($.fn.html, 500);
|
||||||
|
|
||||||
$.fn.addHyperlinks = function () {
|
$.fn.addHyperlinks = function () {
|
||||||
if (this.length > 0) {
|
if (this.length > 0) {
|
||||||
this.each(function (i, obj) {
|
this.each(function (i, obj) {
|
||||||
var x = $(obj).html();
|
var $obj = $(obj);
|
||||||
var list = x.match(/\b(https?:\/\/|www\.|https?:\/\/www\.)[^\s<]{2,200}\b/g );
|
var x = $obj.html();
|
||||||
if (list) {
|
_.each(x.match(/\b(https?:\/\/|www\.|https?:\/\/www\.)[^\s<]{2,200}\b/g), function (url) {
|
||||||
for (i=0; i<list.length; i++) {
|
isImage(url)
|
||||||
var prot = list[i].indexOf('http://') === 0 || list[i].indexOf('https://') === 0 ? '' : 'http://';
|
.then(function () {
|
||||||
var escaped_url = encodeURI(decodeURI(list[i])).replace(/[!'()]/g, escape).replace(/\*/g, "%2A");
|
event.target.className = 'chat-image';
|
||||||
x = x.replace(list[i], '<a target="_blank" rel="noopener" href="' + prot + escaped_url + '">'+ list[i] + '</a>' );
|
x = x.replace(url, event.target.outerHTML);
|
||||||
}
|
$obj.throttledHTML(x);
|
||||||
}
|
})
|
||||||
$(obj).html(x);
|
.fail(function () {
|
||||||
|
var prot = url.indexOf('http://') === 0 || url.indexOf('https://') === 0 ? '' : 'http://';
|
||||||
|
var escaped_url = encodeURI(decodeURI(url)).replace(/[!'()]/g, escape).replace(/\*/g, "%2A");
|
||||||
|
x = x.replace(url, '<a target="_blank" rel="noopener" href="' + prot + escaped_url + '">'+ url + '</a>' );
|
||||||
|
$obj.throttledHTML(x);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
|
Loading…
Reference in New Issue
Block a user