Correctly handle inline channels in messages

Fixes #15 and #11
This commit is contained in:
Pavel Djundik 2016-02-29 18:48:57 +02:00
parent b39b569a59
commit 56e1d3fac7
2 changed files with 30 additions and 32 deletions

View file

@ -1,8 +1,9 @@
Handlebars.registerHelper(
"parse", function(text) {
var wrap = wraplong(text);
text = escape(text);
text = Handlebars.Utils.escapeExpression(text);
text = colors(text);
text = channels(text);
text = uri(text);
if (wrap) {
return "<i class='wrap'>" + text + "</i>";
@ -23,17 +24,6 @@ function wraplong(text) {
return wrap;
}
function escape(text) {
var e = {
"<": "&lt;",
">": "&gt;",
"'": "&#39;"
};
return text.replace(/[<>']/g, function (c) {
return e[c];
});
}
function uri(text) {
return URI.withinString(text, function(url, start, end, source) {
if (url.indexOf("javascript:") === 0) {
@ -48,6 +38,19 @@ function uri(text) {
});
}
/**
* Channels names are strings of length up to fifty (50) characters.
* The only restriction on a channel name is that it SHALL NOT contain
* any spaces (' '), a control G (^G or ASCII 7), a comma (',').
* Channel prefix '&' is handled as '&amp;' because this parser is executed
* after entities in the message have been escaped. This prevents a couple of bugs.
*/
function channels(text) {
return text.replace(
/(^|\s|\x07|,)((?:#|&amp;)[^\x07\s\,]{1,49})/g,
'$1<span class="inline-channel" role="button" tabindex="0" data-chan="$2">$2</span>'
);
}
/**
* MIRC compliant colour and style parser

View file

@ -234,26 +234,6 @@ $(function() {
if (text.find("i").size() === 1) {
text = text.find("i");
}
// Channels names are strings (beginning with a '&' or '#' character)
// of length up to 200 characters.
// See https://tools.ietf.org/html/rfc1459#section-1.3
text.html(text.html().replace(/(^|\s)([#&][^\x07\x2C\s]{0,199})/ig,
'$1<span class="inline-channel" role="button" tabindex="0" data-chan="$2">$2</span>'));
text.find("span.inline-channel")
.on("click", function() {
var chan = $(".network")
.find(".chan.active")
.parent(".network")
.find(".chan[data-title='" + $(this).data("chan") + "']");
if (chan.size() === 1) {
chan.click();
} else {
socket.emit("input", {
target: chat.data("id"),
text: "/join " + $(this).data("chan")
});
}
});
if ((type === "message" || type === "action") && chan.hasClass("channel")) {
var nicks = chan.find(".users").data("nicks");
@ -529,6 +509,21 @@ $(function() {
});
});
chat.on("click", ".inline-channel", function() {
var chan = $(".network")
.find(".chan.active")
.parent(".network")
.find(".chan[data-title='" + $(this).data("chan") + "']");
if (chan.size() === 1) {
chan.click();
} else {
socket.emit("input", {
target: chat.data("id"),
text: "/join " + $(this).data("chan")
});
}
});
chat.on("click", ".messages", function() {
setTimeout(function() {
var text = "";