From c9ed91099f218c0973b08de58f71917162808fb2 Mon Sep 17 00:00:00 2001 From: Wolfsblvt Date: Fri, 6 Sep 2024 18:46:35 +0200 Subject: [PATCH 01/12] Add cssClass arg to /echo --- public/scripts/slash-commands.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/public/scripts/slash-commands.js b/public/scripts/slash-commands.js index 749578de8..e95797604 100644 --- a/public/scripts/slash-commands.js +++ b/public/scripts/slash-commands.js @@ -771,6 +771,11 @@ export function initDefaultSlashCommands() { new SlashCommandEnumValue('success', 'success', enumTypes.enum, '✅'), ], }), + SlashCommandNamedArgument.fromProps({ + name: 'cssClass', + description: 'additional css class to add to the toast message (e.g. for custom styling)', + typeList: [ARGUMENT_TYPE.STRING], + }), SlashCommandNamedArgument.fromProps({ name: 'timeout', description: 'time in milliseconds to display the toast message. Set this and \'extendedTimeout\' to 0 to show indefinitely until dismissed.', @@ -2181,7 +2186,7 @@ async function generateCallback(args, value) { /** * - * @param {{title?: string, severity?: string, timeout?: string, extendedTimeout?: string, preventDuplicates?: string, awaitDismissal?: string}} args - named arguments from the slash command + * @param {{title?: string, severity?: string, cssClass?: string, timeout?: string, extendedTimeout?: string, preventDuplicates?: string, awaitDismissal?: string}} args - named arguments from the slash command * @param {string} value - The string to echo (unnamed argument from the slash command) * @returns {Promise} The text that was echoed */ @@ -2217,6 +2222,10 @@ async function echoCallback(args, value) { options.onHidden = () => resolveToastDismissal(value); } + if (args.cssClass) { + options.toastClass = args.cssClass; + } + switch (severity) { case 'error': toastr.error(value, title, options); From a4e72da40fc9a2e25f17b2b1c2a2c490bc9e75f8 Mon Sep 17 00:00:00 2001 From: Wolfsblvt Date: Fri, 6 Sep 2024 18:55:50 +0200 Subject: [PATCH 02/12] Add color arg to /echo for custom color --- public/scripts/slash-commands.js | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/public/scripts/slash-commands.js b/public/scripts/slash-commands.js index e95797604..8676181f2 100644 --- a/public/scripts/slash-commands.js +++ b/public/scripts/slash-commands.js @@ -771,11 +771,6 @@ export function initDefaultSlashCommands() { new SlashCommandEnumValue('success', 'success', enumTypes.enum, '✅'), ], }), - SlashCommandNamedArgument.fromProps({ - name: 'cssClass', - description: 'additional css class to add to the toast message (e.g. for custom styling)', - typeList: [ARGUMENT_TYPE.STRING], - }), SlashCommandNamedArgument.fromProps({ name: 'timeout', description: 'time in milliseconds to display the toast message. Set this and \'extendedTimeout\' to 0 to show indefinitely until dismissed.', @@ -802,6 +797,15 @@ export function initDefaultSlashCommands() { defaultValue: 'false', enumList: commonEnumProviders.boolean('trueFalse')(), }), + SlashCommandNamedArgument.fromProps({ + name: 'cssClass', + description: 'additional css class to add to the toast message (e.g. for custom styling)', + typeList: [ARGUMENT_TYPE.STRING], + }), + SlashCommandNamedArgument.fromProps({ + name: 'color', + description: 'custom CSS color of the toast message. Accepts all valid CSS color values (e.g. \'red\', \'#FF0000\', \'rgb(255, 0, 0)\').
>Can be more customizable with the \'cssClass\' argument and custom classes.', + }) ], unnamedArgumentList: [ new SlashCommandArgument( @@ -2186,7 +2190,7 @@ async function generateCallback(args, value) { /** * - * @param {{title?: string, severity?: string, cssClass?: string, timeout?: string, extendedTimeout?: string, preventDuplicates?: string, awaitDismissal?: string}} args - named arguments from the slash command + * @param {{title?: string, severity?: string, timeout?: string, extendedTimeout?: string, preventDuplicates?: string, awaitDismissal?: string, cssClass?: string, color?: string}} args - named arguments from the slash command * @param {string} value - The string to echo (unnamed argument from the slash command) * @returns {Promise} The text that was echoed */ @@ -2226,22 +2230,27 @@ async function echoCallback(args, value) { options.toastClass = args.cssClass; } + let toast; switch (severity) { case 'error': - toastr.error(value, title, options); + toast = toastr.error(value, title, options); break; case 'warning': - toastr.warning(value, title, options); + toast = toastr.warning(value, title, options); break; case 'success': - toastr.success(value, title, options); + toast = toastr.success(value, title, options); break; case 'info': default: - toastr.info(value, title, options); + toast = toastr.info(value, title, options); break; } + if (args.color) { + toast.css('background-color', args.color); + } + if (awaitDismissal) { return new Promise((resolve) => { resolveToastDismissal = resolve; From 885a0145073f56e6ef811dfeaaa11e386f1a97af Mon Sep 17 00:00:00 2001 From: Wolfsblvt Date: Fri, 6 Sep 2024 19:03:21 +0200 Subject: [PATCH 03/12] Add escapeHtml arg to /echo --- public/scripts/slash-commands.js | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/public/scripts/slash-commands.js b/public/scripts/slash-commands.js index 8676181f2..3298b9605 100644 --- a/public/scripts/slash-commands.js +++ b/public/scripts/slash-commands.js @@ -805,7 +805,14 @@ export function initDefaultSlashCommands() { SlashCommandNamedArgument.fromProps({ name: 'color', description: 'custom CSS color of the toast message. Accepts all valid CSS color values (e.g. \'red\', \'#FF0000\', \'rgb(255, 0, 0)\').
>Can be more customizable with the \'cssClass\' argument and custom classes.', - }) + }), + SlashCommandNamedArgument.fromProps({ + name: 'escapeHtml', + description: 'whether to escape HTML in the toast message.', + typeList: [ARGUMENT_TYPE.BOOLEAN], + defaultValue: 'true', + enumList: commonEnumProviders.boolean('trueFalse')(), + }), ], unnamedArgumentList: [ new SlashCommandArgument( @@ -2190,7 +2197,7 @@ async function generateCallback(args, value) { /** * - * @param {{title?: string, severity?: string, timeout?: string, extendedTimeout?: string, preventDuplicates?: string, awaitDismissal?: string, cssClass?: string, color?: string}} args - named arguments from the slash command + * @param {{title?: string, severity?: string, timeout?: string, extendedTimeout?: string, preventDuplicates?: string, awaitDismissal?: string, cssClass?: string, color?: string, escapeHtml?: string}} args - named arguments from the slash command * @param {string} value - The string to echo (unnamed argument from the slash command) * @returns {Promise} The text that was echoed */ @@ -2217,6 +2224,8 @@ async function echoCallback(args, value) { if (args.timeout && !isNaN(parseInt(args.timeout))) options.timeOut = parseInt(args.timeout); if (args.extendedTimeout && !isNaN(parseInt(args.extendedTimeout))) options.extendedTimeOut = parseInt(args.extendedTimeout); if (isTrueBoolean(args.preventDuplicates)) options.preventDuplicates = true; + if (args.cssClass) options.toastClass = args.cssClass; + if (args.escapeHtml !== undefined) options.escapeHtml = isTrueBoolean(args.escapeHtml); // Prepare possible await handling let awaitDismissal = isTrueBoolean(args.awaitDismissal); @@ -2226,10 +2235,6 @@ async function echoCallback(args, value) { options.onHidden = () => resolveToastDismissal(value); } - if (args.cssClass) { - options.toastClass = args.cssClass; - } - let toast; switch (severity) { case 'error': From de8732fad6fa224da254fe0b35c9578f4d09ac7f Mon Sep 17 00:00:00 2001 From: Wolfsblvt Date: Fri, 6 Sep 2024 19:32:35 +0200 Subject: [PATCH 04/12] Add onClick arg to /echo executing closures - Adds the 'onclick' slash command arg to /echo - It utilizes the Closure object without serialization, using the exact same scope it received on creation. Should be mindful about memory leaks and possible parallel execution. --- public/scripts/slash-commands.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/public/scripts/slash-commands.js b/public/scripts/slash-commands.js index 3298b9605..7dac6e119 100644 --- a/public/scripts/slash-commands.js +++ b/public/scripts/slash-commands.js @@ -813,6 +813,11 @@ export function initDefaultSlashCommands() { defaultValue: 'true', enumList: commonEnumProviders.boolean('trueFalse')(), }), + SlashCommandNamedArgument.fromProps({ + name: 'onClick', + description: 'a closure to call when the toast is clicked. This executed closure receives scope as provided in the script. Careful about possible side effects when manipulating variables and more.', + typeList: [ARGUMENT_TYPE.CLOSURE], + }), ], unnamedArgumentList: [ new SlashCommandArgument( @@ -2197,7 +2202,7 @@ async function generateCallback(args, value) { /** * - * @param {{title?: string, severity?: string, timeout?: string, extendedTimeout?: string, preventDuplicates?: string, awaitDismissal?: string, cssClass?: string, color?: string, escapeHtml?: string}} args - named arguments from the slash command + * @param {{title?: string, severity?: string, timeout?: string, extendedTimeout?: string, preventDuplicates?: string, awaitDismissal?: string, cssClass?: string, color?: string, escapeHtml?: string, onClick?: SlashCommandClosure}} args - named arguments from the slash command * @param {string} value - The string to echo (unnamed argument from the slash command) * @returns {Promise} The text that was echoed */ @@ -2234,6 +2239,9 @@ async function echoCallback(args, value) { if (awaitDismissal) { options.onHidden = () => resolveToastDismissal(value); } + if (args.onClick) { + options.onclick = () => args.onClick.execute(); + } let toast; switch (severity) { From e48ff8daae54d5874918e0d6796b03d1d4163318 Mon Sep 17 00:00:00 2001 From: Wolfsblvt Date: Fri, 6 Sep 2024 19:49:32 +0200 Subject: [PATCH 05/12] Add check for closure type --- public/scripts/slash-commands.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/public/scripts/slash-commands.js b/public/scripts/slash-commands.js index 7dac6e119..a1c6aaaf4 100644 --- a/public/scripts/slash-commands.js +++ b/public/scripts/slash-commands.js @@ -2240,7 +2240,11 @@ async function echoCallback(args, value) { options.onHidden = () => resolveToastDismissal(value); } if (args.onClick) { - options.onclick = () => args.onClick.execute(); + if (args.onClick instanceof SlashCommandClosure) { + options.onclick = () => args.onClick.execute(); + } else { + toastr.warning('Invalid onClick provided for /echo command. This is not a closure'); + } } let toast; From ad04d0c9a29039e89077de4e0945094fb7354fc3 Mon Sep 17 00:00:00 2001 From: Wolfsblvt Date: Fri, 6 Sep 2024 20:01:45 +0200 Subject: [PATCH 06/12] Fix async closure call not clearing progress --- public/scripts/slash-commands.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/public/scripts/slash-commands.js b/public/scripts/slash-commands.js index a1c6aaaf4..243237a6c 100644 --- a/public/scripts/slash-commands.js +++ b/public/scripts/slash-commands.js @@ -2241,7 +2241,11 @@ async function echoCallback(args, value) { } if (args.onClick) { if (args.onClick instanceof SlashCommandClosure) { - options.onclick = () => args.onClick.execute(); + options.onclick = async () => { + // Execute the slash command directly, with its internal scope and everything. Clear progress at the end if the main script is already done. + await args.onClick.execute(); + await clearCommandProgress(); + }; } else { toastr.warning('Invalid onClick provided for /echo command. This is not a closure'); } From 0d9843cdd666021c8773da7b891875c4780d044f Mon Sep 17 00:00:00 2001 From: Wolfsblvt Date: Fri, 6 Sep 2024 20:21:32 +0200 Subject: [PATCH 07/12] clear onProgress before closure for no progress --- public/scripts/slash-commands.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/scripts/slash-commands.js b/public/scripts/slash-commands.js index 243237a6c..4ee796298 100644 --- a/public/scripts/slash-commands.js +++ b/public/scripts/slash-commands.js @@ -2242,9 +2242,9 @@ async function echoCallback(args, value) { if (args.onClick) { if (args.onClick instanceof SlashCommandClosure) { options.onclick = async () => { - // Execute the slash command directly, with its internal scope and everything. Clear progress at the end if the main script is already done. + // Execute the slash command directly, with its internal scope and everything. Clear progress handler so it doesn't interfere with command execution progress. + args.onClick.onProgress = null; await args.onClick.execute(); - await clearCommandProgress(); }; } else { toastr.warning('Invalid onClick provided for /echo command. This is not a closure'); From 25d8286dfcb77f16608d505b980e48c04a07376b Mon Sep 17 00:00:00 2001 From: Wolfsblvt Date: Fri, 6 Sep 2024 20:31:13 +0200 Subject: [PATCH 08/12] DOM.purify toast if HTML is allowed --- public/scripts/slash-commands.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/public/scripts/slash-commands.js b/public/scripts/slash-commands.js index 4ee796298..594003508 100644 --- a/public/scripts/slash-commands.js +++ b/public/scripts/slash-commands.js @@ -2251,6 +2251,11 @@ async function echoCallback(args, value) { } } + // If we allow HTML, we need to sanitize it to prevent security risks + if (!options.escapeHtml) { + value = DOMPurify.sanitize(value, { FORBID_TAGS: ['style'] }); + } + let toast; switch (severity) { case 'error': From fc942842b936151f0a8ee530dbc8120ea6881518 Mon Sep 17 00:00:00 2001 From: Sneha C Date: Fri, 6 Sep 2024 22:39:30 +0400 Subject: [PATCH 09/12] Update slash-commands.js added some examples to /echo command --- public/scripts/slash-commands.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/public/scripts/slash-commands.js b/public/scripts/slash-commands.js index 594003508..701baba31 100644 --- a/public/scripts/slash-commands.js +++ b/public/scripts/slash-commands.js @@ -834,6 +834,12 @@ export function initDefaultSlashCommands() {
  • /echo title="My Message" severity=info This is an info message
  • +
  • +
    /echo title="My Message" color=black This message is purple
    +
  • +
  • +
    /echo onClick={: /echo escapeHtml=false color=transparent cssClass=wider_dialogue_popup  :} timeout=5000 Clicking on this message within 10 seconds will open the image.
    +
  • `, From 50a716a59327550ec99f22815e97497279a15c14 Mon Sep 17 00:00:00 2001 From: Wolfsblvt Date: Fri, 6 Sep 2024 20:53:39 +0200 Subject: [PATCH 10/12] Update /echo docs helpstring --- public/scripts/slash-commands.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/public/scripts/slash-commands.js b/public/scripts/slash-commands.js index 701baba31..630c0fcb8 100644 --- a/public/scripts/slash-commands.js +++ b/public/scripts/slash-commands.js @@ -826,19 +826,19 @@ export function initDefaultSlashCommands() { ], helpString: `
    - Echoes the provided text to a toast message. Useful for pipes debugging. + Echoes the provided text to a toast message. Can be used to display informational messages or for pipes debugging.
    Example:
    • -
      /echo title="My Message" severity=info This is an info message
      +
      /echo title="My Message" severity=warning This is a warning message
    • -
      /echo title="My Message" color=black This message is purple
      +
      /echo color=purple This message is purple
    • -
      /echo onClick={: /echo escapeHtml=false color=transparent cssClass=wider_dialogue_popup  :} timeout=5000 Clicking on this message within 10 seconds will open the image.
      +
      /echo onClick={: /echo escapeHtml=false color=transparent cssClass=wider_dialogue_popup <img src="/img/five.png" /> :} timeout=5000 Clicking on this message within 5 seconds will open the image.
    From 63c6fbaf589139c74e8a0d0aaada3c15c8236c89 Mon Sep 17 00:00:00 2001 From: Wolfsblvt Date: Fri, 6 Sep 2024 21:18:16 +0200 Subject: [PATCH 11/12] /echo html allowed sanitize title too --- public/scripts/slash-commands.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/public/scripts/slash-commands.js b/public/scripts/slash-commands.js index 630c0fcb8..6fd85c25e 100644 --- a/public/scripts/slash-commands.js +++ b/public/scripts/slash-commands.js @@ -2227,7 +2227,7 @@ async function echoCallback(args, value) { // Make sure that the value is a string value = String(value); - const title = args.title ? args.title : undefined; + let title = args.title ? args.title : undefined; const severity = args.severity ? args.severity : 'info'; /** @type {ToastrOptions} */ @@ -2259,6 +2259,7 @@ async function echoCallback(args, value) { // If we allow HTML, we need to sanitize it to prevent security risks if (!options.escapeHtml) { + if (title) title = DOMPurify.sanitize(title, { FORBID_TAGS: ['style'] }); value = DOMPurify.sanitize(value, { FORBID_TAGS: ['style'] }); } From 50217e37b88d540cc3b5ae73024fb97054a22b87 Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Fri, 6 Sep 2024 22:27:53 +0300 Subject: [PATCH 12/12] Spell CSS consistently --- public/scripts/slash-commands.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/scripts/slash-commands.js b/public/scripts/slash-commands.js index 6fd85c25e..fcc6efb87 100644 --- a/public/scripts/slash-commands.js +++ b/public/scripts/slash-commands.js @@ -799,7 +799,7 @@ export function initDefaultSlashCommands() { }), SlashCommandNamedArgument.fromProps({ name: 'cssClass', - description: 'additional css class to add to the toast message (e.g. for custom styling)', + description: 'additional CSS class to add to the toast message (e.g. for custom styling)', typeList: [ARGUMENT_TYPE.STRING], }), SlashCommandNamedArgument.fromProps({