Refactor /listvar, deprecate its "format" arg - Update /listvar - Fix toasts not doing correct HMTL here

697b3b2034c20ea15e48002929b696f85bfb3a64

Wolfsblvt <wolfsblvt@gmail.com>

3 files changed, +55 -33Ignore whitespace
public/scripts/slash-commands.js+4 -5
@@ -1524,21 +1524,21 @@ export function initDefaultSlashCommands() {
1524 SlashCommandParser.addCommandObject(SlashCommand.fromProps({1524 SlashCommandParser.addCommandObject(SlashCommand.fromProps({
1525 name: 'listinjects',1525 name: 'listinjects',
1526 callback: listInjectsCallback,1526 callback: listInjectsCallback,
1527 helpString: 'Lists all script injections for the current chat. Displays injects in a popup by default. Use the <code>format</code> argument to change the output format.',1527 helpString: 'Lists all script injections for the current chat. Displays injects in a popup by default. Use the <code>return</code> argument to change the return type.',
1528 returns: 'Optionalls the JSON object of script injections',1528 returns: 'Optionalls the JSON object of script injections',
1529 namedArgumentList: [1529 namedArgumentList: [
1530 SlashCommandNamedArgument.fromProps({1530 SlashCommandNamedArgument.fromProps({
1531 name: 'return',1531 name: 'return',
1532 description: 'The way how you want the return value to be provided',1532 description: 'The way how you want the return value to be provided',
1533 typeList: [ARGUMENT_TYPE.STRING],1533 typeList: [ARGUMENT_TYPE.STRING],
1534 defaultValue: 'object',1534 defaultValue: 'popup-html',
1535 enumList: slashCommandReturnHelper.enumList({ allowPipe: false, allowObject: true, allowChat: true, allowPopup: true, allowTextVersion: false }),1535 enumList: slashCommandReturnHelper.enumList({ allowPipe: false, allowObject: true, allowChat: true, allowPopup: true, allowTextVersion: false }),
1536 forceEnum: true,1536 forceEnum: true,
1537 }),1537 }),
1538 // TODO remove some day1538 // TODO remove some day
1539 SlashCommandNamedArgument.fromProps({1539 SlashCommandNamedArgument.fromProps({
1540 name: 'format',1540 name: 'format',
1541 description: 'DEPRECATED - use "return" instead - output format',1541 description: '!!! DEPRECATED - use "return" instead !!! output format)',
1542 typeList: [ARGUMENT_TYPE.STRING],1542 typeList: [ARGUMENT_TYPE.STRING],
1543 isRequired: true,1543 isRequired: true,
1544 forceEnum: true,1544 forceEnum: true,
@@ -1832,7 +1832,6 @@ async function listInjectsCallback(args) {
1832 }1832 }
18331833
1834 // Now the actual new return type handling1834 // Now the actual new return type handling
1835
1836 const buildTextValue = (injects) => {1835 const buildTextValue = (injects) => {
1837 const injectsStr = Object.entries(injects)1836 const injectsStr = Object.entries(injects)
1838 .map(([id, inject]) => {1837 .map(([id, inject]) => {
@@ -1844,7 +1843,7 @@ async function listInjectsCallback(args) {
1844 return `### Script injections:\n${injectsStr}`;1843 return `### Script injections:\n${injectsStr}`;
1845 };1844 };
18461845
1847 return await slashCommandReturnHelper.doReturn(returnType ?? 'object', chat_metadata.script_injects, { objectToStringFunc: buildTextValue });1846 return await slashCommandReturnHelper.doReturn(returnType ?? 'popup-html', chat_metadata.script_injects, { objectToStringFunc: buildTextValue });
1848}1847}
18491848
1850/**1849/**
public/scripts/slash-commands/SlashCommandReturnHelper.js+1 -1
@@ -58,7 +58,7 @@ export const slashCommandReturnHelper = {
5858
59 if (type.startsWith('popup')) await callGenericPopup(shouldHtml ? makeHtml(stringValue) : escapeHtml(stringValue), POPUP_TYPE.TEXT);59 if (type.startsWith('popup')) await callGenericPopup(shouldHtml ? makeHtml(stringValue) : escapeHtml(stringValue), POPUP_TYPE.TEXT);
60 if (type.startsWith('chat')) sendSystemMessage(system_message_types.GENERIC, shouldHtml ? makeHtml(stringValue) : escapeHtml(stringValue));60 if (type.startsWith('chat')) sendSystemMessage(system_message_types.GENERIC, shouldHtml ? makeHtml(stringValue) : escapeHtml(stringValue));
61 if (type.startsWith('toast')) toastr.info(stringValue, null, { escapeHtml: !shouldHtml }); // Toastr handles HTML conversion internally already61 if (type.startsWith('toast')) toastr.info(shouldHtml ? makeHtml(stringValue) : escapeHtml(stringValue), null, { escapeHtml: !shouldHtml });
6262
63 return '';63 return '';
64 }64 }
public/scripts/variables.js+50 -27
@@ -11,6 +11,7 @@ import { SlashCommandClosureResult } from './slash-commands/SlashCommandClosureR
11import { commonEnumProviders, enumIcons } from './slash-commands/SlashCommandCommonEnumsProvider.js';11import { commonEnumProviders, enumIcons } from './slash-commands/SlashCommandCommonEnumsProvider.js';
12import { SlashCommandEnumValue, enumTypes } from './slash-commands/SlashCommandEnumValue.js';12import { SlashCommandEnumValue, enumTypes } from './slash-commands/SlashCommandEnumValue.js';
13import { PARSER_FLAG, SlashCommandParser } from './slash-commands/SlashCommandParser.js';13import { PARSER_FLAG, SlashCommandParser } from './slash-commands/SlashCommandParser.js';
14import { slashCommandReturnHelper } from './slash-commands/SlashCommandReturnHelper.js';
14import { SlashCommandScope } from './slash-commands/SlashCommandScope.js';15import { SlashCommandScope } from './slash-commands/SlashCommandScope.js';
15import { isFalseBoolean, convertValueType, isTrueBoolean } from './utils.js';16import { isFalseBoolean, convertValueType, isTrueBoolean } from './utils.js';
1617
@@ -305,7 +306,31 @@ export function replaceVariableMacros(input) {
305}306}
306307
307async function listVariablesCallback(args) {308async function listVariablesCallback(args) {
308 const type = String(args?.format || '').toLowerCase().trim() || 'popup';309 /** @type {import('./slash-commands/SlashCommandReturnHelper.js').SlashCommandReturnType} */
310 let returnType = args.return;
311
312 // Old legacy return type handling
313 if (args.format) {
314 toastr.warning(`Legacy argument 'format' with value '${args.format}' is deprecated. Please use 'return' instead. Routing to the correct return type...`, 'Deprecation warning');
315 const type = String(args?.format).toLowerCase().trim();
316 if (!chat_metadata.script_injects || !Object.keys(chat_metadata.script_injects).length) {
317 type !== 'none' && toastr.info('No script injections for the current chat');
318 }
319 switch (type) {
320 case 'none':
321 returnType = 'none';
322 break;
323 case 'chat':
324 returnType = 'chat-html';
325 break;
326 case 'popup':
327 default:
328 returnType = 'popup-html';
329 break;
330 }
331 }
332
333 // Now the actual new return type handling
309 const scope = String(args?.scope || '').toLowerCase().trim() || 'all';334 const scope = String(args?.scope || '').toLowerCase().trim() || 'all';
310 if (!chat_metadata.variables) {335 if (!chat_metadata.variables) {
311 chat_metadata.variables = {};336 chat_metadata.variables = {};
@@ -317,35 +342,24 @@ async function listVariablesCallback(args) {
317 const localVariables = includeLocalVariables ? Object.entries(chat_metadata.variables).map(([name, value]) => `${name}: ${value}`) : [];342 const localVariables = includeLocalVariables ? Object.entries(chat_metadata.variables).map(([name, value]) => `${name}: ${value}`) : [];
318 const globalVariables = includeGlobalVariables ? Object.entries(extension_settings.variables.global).map(([name, value]) => `${name}: ${value}`) : [];343 const globalVariables = includeGlobalVariables ? Object.entries(extension_settings.variables.global).map(([name, value]) => `${name}: ${value}`) : [];
319344
345 const buildTextValue = (_) => {
346 const localVariablesString = localVariables.length > 0 ? localVariables.join('\n\n') : 'No local variables';
347 const globalVariablesString = globalVariables.length > 0 ? globalVariables.join('\n\n') : 'No global variables';
348 const chatName = getCurrentChatId();
349
350 const message = [
351 includeLocalVariables ? `### Local variables (${chatName}):\n${localVariablesString}` : '',
352 includeGlobalVariables ? `### Global variables:\n${globalVariablesString}` : '',
353 ].filter(x => x).join('\n\n');
354 return message;
355 };
356
320 const jsonVariables = [357 const jsonVariables = [
321 ...Object.entries(chat_metadata.variables).map(x => ({ key: x[0], value: x[1], scope: 'local' })),358 ...Object.entries(chat_metadata.variables).map(x => ({ key: x[0], value: x[1], scope: 'local' })),
322 ...Object.entries(extension_settings.variables.global).map(x => ({ key: x[0], value: x[1], scope: 'global' })),359 ...Object.entries(extension_settings.variables.global).map(x => ({ key: x[0], value: x[1], scope: 'global' })),
323 ];360 ];
324361
325 const localVariablesString = localVariables.length > 0 ? localVariables.join('\n\n') : 'No local variables';362 return await slashCommandReturnHelper.doReturn(returnType ?? 'popup-html', jsonVariables, { objectToStringFunc: buildTextValue });
326 const globalVariablesString = globalVariables.length > 0 ? globalVariables.join('\n\n') : 'No global variables';
327 const chatName = getCurrentChatId();
328
329 const converter = new showdown.Converter();
330 const message = [
331 includeLocalVariables ? `### Local variables (${chatName}):\n${localVariablesString}` : '',
332 includeGlobalVariables ? `### Global variables:\n${globalVariablesString}` : '',
333 ].filter(x => x).join('\n\n');
334 const htmlMessage = DOMPurify.sanitize(converter.makeHtml(message));
335
336 switch (type) {
337 case 'none':
338 break;
339 case 'chat':
340 sendSystemMessage(system_message_types.GENERIC, htmlMessage);
341 break;
342 case 'popup':
343 default:
344 await callGenericPopup(htmlMessage, POPUP_TYPE.TEXT);
345 break;
346 }
347
348 return JSON.stringify(jsonVariables);
349}363}
350364
351/**365/**
@@ -910,7 +924,7 @@ export function registerVariableCommands() {
910 name: 'listvar',924 name: 'listvar',
911 callback: listVariablesCallback,925 callback: listVariablesCallback,
912 aliases: ['listchatvar'],926 aliases: ['listchatvar'],
913 helpString: 'List registered chat variables. Displays variables in a popup by default. Use the <code>format</code> argument to change the output format.',927 helpString: 'List registered chat variables. Displays variables in a popup by default. Use the <code>return</code> argument to change the return type.',
914 returns: 'JSON list of local variables',928 returns: 'JSON list of local variables',
915 namedArgumentList: [929 namedArgumentList: [
916 SlashCommandNamedArgument.fromProps({930 SlashCommandNamedArgument.fromProps({
@@ -927,8 +941,17 @@ export function registerVariableCommands() {
927 ],941 ],
928 }),942 }),
929 SlashCommandNamedArgument.fromProps({943 SlashCommandNamedArgument.fromProps({
944 name: 'return',
945 description: 'The way how you want the return value to be provided',
946 typeList: [ARGUMENT_TYPE.STRING],
947 defaultValue: 'popup-html',
948 enumList: slashCommandReturnHelper.enumList({ allowPipe: false, allowObject: true, allowChat: true, allowPopup: true, allowTextVersion: false }),
949 forceEnum: true,
950 }),
951 // TODO remove some day
952 SlashCommandNamedArgument.fromProps({
930 name: 'format',953 name: 'format',
931 description: 'output format',954 description: '!!! DEPRECATED - use "return" instead !!! output format)',
932 typeList: [ARGUMENT_TYPE.STRING],955 typeList: [ARGUMENT_TYPE.STRING],
933 isRequired: true,956 isRequired: true,
934 forceEnum: true,957 forceEnum: true,