chat: Give `chatNewMessage` hook access to the raw message object

pull/5256/head
Richard Hansen 2021-10-26 21:58:34 -04:00
parent fc5a3f553d
commit 2597b940f4
4 changed files with 30 additions and 1 deletions

View File

@ -50,6 +50,10 @@
* The `helper.aNewPad()` function (accessible to client-side tests) now * The `helper.aNewPad()` function (accessible to client-side tests) now
accepts hook functions to inject when opening a pad. This can be used to accepts hook functions to inject when opening a pad. This can be used to
test any new client-side hooks your plugin provides. test any new client-side hooks your plugin provides.
* Chat improvements:
* The `chatNewMessage` client-side hook context has new properties:
* `message`: Provides access to the raw message object so that plugins can
see the original unprocessed message text and any added metadata.
# 1.8.14 # 1.8.14

View File

@ -296,7 +296,12 @@ Context properties:
* `authorName`: The display name of the user that wrote the message. * `authorName`: The display name of the user that wrote the message.
* `author`: The author ID of the user that wrote the message. * `author`: The author ID of the user that wrote the message.
* `text`: Sanitized message HTML, with URLs wrapped like `<a * `text`: Sanitized message HTML, with URLs wrapped like `<a
href="url">url</a>`. href="url">url</a>`. (Note that `message.text` is not sanitized or processed
in any way.)
* `message`: The raw message object as received from the server, except with
time correction and a default `userId` property if missing. Plugins must not
modify this object. Warning: Unlike `text`, `message.text` is not
pre-sanitized or processed in any way.
* `sticky` (boolean): Whether the gritter notification should fade out on its * `sticky` (boolean): Whether the gritter notification should fade out on its
own or just sit there until manually closed. own or just sit there until manually closed.
* `timestamp`: When the chat message was sent (milliseconds since epoch), * `timestamp`: When the chat message was sent (milliseconds since epoch),

View File

@ -131,6 +131,7 @@ exports.chat = (() => {
authorName: msg.userName != null ? msg.userName : html10n.get('pad.userlist.unnamed'), authorName: msg.userName != null ? msg.userName : html10n.get('pad.userlist.unnamed'),
author: msg.userId, author: msg.userId,
text: padutils.escapeHtmlWithClickableLinks(msg.text, '_blank'), text: padutils.escapeHtmlWithClickableLinks(msg.text, '_blank'),
message: msg,
sticky: false, sticky: false,
timestamp: msg.time, timestamp: msg.time,
timeStr: (() => { timeStr: (() => {

View File

@ -60,5 +60,24 @@ describe('chat hooks', function () {
]); ]);
}); });
} }
it('message is an object', async function () {
await Promise.all([
checkHook('chatNewMessage', ({message}) => {
expect(message).to.be.an('object');
}),
helper.sendChatMessage(`${this.test.title}{enter}`),
]);
});
it('message.text is not processed', async function () {
const msg = '<script>alert("foo");</script> https://etherpad.org';
await Promise.all([
checkHook('chatNewMessage', ({message: {text}}) => {
expect(text).to.equal(`${msg}\n`);
}),
helper.sendChatMessage(`${msg}{enter}`),
]);
});
}); });
}); });