From a8b5f8a95f22d65c1cafaa21492aec209883c32e Mon Sep 17 00:00:00 2001 From: Wolfsblvt Date: Thu, 9 Jan 2025 18:37:50 +0100 Subject: [PATCH 1/3] Add /css-var slash command - Add /css-var slash command to set CSS variables on some elements - Update gallery div id to something actually unique ("#draggable_gallery") --- public/scripts/extensions/gallery/index.js | 2 +- public/scripts/power-user.js | 89 +++++++++++++++++++ .../SlashCommandCommonEnumsProvider.js | 1 + 3 files changed, 91 insertions(+), 1 deletion(-) diff --git a/public/scripts/extensions/gallery/index.js b/public/scripts/extensions/gallery/index.js index a39634603..94b8c30c7 100644 --- a/public/scripts/extensions/gallery/index.js +++ b/public/scripts/extensions/gallery/index.js @@ -277,7 +277,7 @@ function makeMovable(id = 'gallery') { const newElement = $(template); newElement.css('background-color', 'var(--SmartThemeBlurTintColor)'); newElement.attr('forChar', id); - newElement.attr('id', `${id}`); + newElement.attr('id', `draggable_${id}`); newElement.find('.drag-grabber').attr('id', `${id}header`); newElement.find('.dragTitle').text('Image Gallery'); //add a div for the gallery diff --git a/public/scripts/power-user.js b/public/scripts/power-user.js index 1e69d3608..c25f275c7 100644 --- a/public/scripts/power-user.js +++ b/public/scripts/power-user.js @@ -3962,6 +3962,95 @@ $(document).ready(() => { `, })); + SlashCommandParser.addCommandObject(SlashCommand.fromProps({ + name: 'css-var', + /** @param {{to: string, varname: string }} args @param {string} value @returns {string} */ + callback: (args, value) => { + // Map enum to target selector + const targetSelector = { + chat: '#chat', + background: '#bg1', + gallery: '#draggable_gallery', + zoomedAvatar: 'div.zoomed_avatar', + }[args.to || 'chat']; + + if (!targetSelector) { + toastr.error(`Invalid target: ${args.to}`); + return; + } + + if (!args.varname) { + toastr.error('CSS variable name is required'); + return; + } + if (!args.varname.startsWith('--')) { + toastr.error('CSS variable names must start with "--"'); + return; + } + + const elements = document.querySelectorAll(targetSelector); + if (elements.length === 0) { + toastr.error(`No elements found for ${args.to ?? 'chat'} with selector "${targetSelector}"`); + return; + } + + elements.forEach(element => { + element.style.setProperty(args.varname, value); + }); + + console.info(`Set CSS variable "${args.varname}" to "${value}" on "${targetSelector}"`); + }, + namedArgumentList: [ + SlashCommandNamedArgument.fromProps({ + name: 'varname', + description: 'CSS variable name (starting with double dashes)', + typeList: [ARGUMENT_TYPE.STRING], + isRequired: true, + }), + SlashCommandNamedArgument.fromProps({ + name: 'to', + description: 'The target element to which the CSS variable will be applied', + typeList: [ARGUMENT_TYPE.STRING], + enumList: [ + new SlashCommandEnumValue('chat', null, enumTypes.enum, enumIcons.message), + new SlashCommandEnumValue('background', null, enumTypes.enum, enumIcons.image), + new SlashCommandEnumValue('zoomedAvatar', null, enumTypes.enum, enumIcons.character), + new SlashCommandEnumValue('gallery', null, enumTypes.enum, enumIcons.image), + ], + defaultValue: 'chat', + }), + ], + unnamedArgumentList: [ + SlashCommandArgument.fromProps({ + description: 'CSS variable value', + typeList: [ARGUMENT_TYPE.STRING], + isRequired: true, + }), + ], + helpString: ` +
+ Sets a CSS variable to a specified value on a target element. +
+ Only setting of variable names is supported. They have to be prefixed with double dashes ("--exampleVar"). + Setting actual CSS properties is not supported. Custom CSS in the theme settings can be used for that. +

+ This value will be gone after a page reload! +
+
+ Example: + +
+ `, + })); SlashCommandParser.addCommandObject(SlashCommand.fromProps({ name: 'movingui', callback: setmovingUIPreset, diff --git a/public/scripts/slash-commands/SlashCommandCommonEnumsProvider.js b/public/scripts/slash-commands/SlashCommandCommonEnumsProvider.js index b96b83a53..9003cb754 100644 --- a/public/scripts/slash-commands/SlashCommandCommonEnumsProvider.js +++ b/public/scripts/slash-commands/SlashCommandCommonEnumsProvider.js @@ -37,6 +37,7 @@ export const enumIcons = { voice: '🎤', server: '🖥️', popup: '🗔', + image: '🖼️', true: '✔️', false: '❌', From f869b26664516c6a67068c69d3a765c3c5c817b2 Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Thu, 9 Jan 2025 22:32:15 +0200 Subject: [PATCH 2/3] Ensure unique selectors for loaded extension files --- public/scripts/extensions.js | 12 +++++++----- public/scripts/utils.js | 10 ++++++++++ 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/public/scripts/extensions.js b/public/scripts/extensions.js index 307a50721..0c3dbfa2e 100644 --- a/public/scripts/extensions.js +++ b/public/scripts/extensions.js @@ -4,7 +4,7 @@ import { eventSource, event_types, saveSettings, saveSettingsDebounced, getReque import { showLoader } from './loader.js'; import { POPUP_RESULT, POPUP_TYPE, Popup, callGenericPopup } from './popup.js'; import { renderTemplate, renderTemplateAsync } from './templates.js'; -import { delay, isSubsetOf, setValueByPath } from './utils.js'; +import { delay, isSubsetOf, sanitizeSelector, setValueByPath } from './utils.js'; import { getContext } from './st-context.js'; import { isAdmin } from './user.js'; import { t } from './i18n.js'; @@ -509,10 +509,11 @@ function addExtensionStyle(name, manifest) { return new Promise((resolve, reject) => { const url = `/scripts/extensions/${name}/${manifest.css}`; + const id = sanitizeSelector(`${name}-css`); - if ($(`link[id="${name}"]`).length === 0) { + if ($(`link[id="${id}"]`).length === 0) { const link = document.createElement('link'); - link.id = name; + link.id = id; link.rel = 'stylesheet'; link.type = 'text/css'; link.href = url; @@ -540,11 +541,12 @@ function addExtensionScript(name, manifest) { return new Promise((resolve, reject) => { const url = `/scripts/extensions/${name}/${manifest.js}`; + const id = sanitizeSelector(`${name}-js`); let ready = false; - if ($(`script[id="${name}"]`).length === 0) { + if ($(`script[id="${id}"]`).length === 0) { const script = document.createElement('script'); - script.id = name; + script.id = id; script.type = 'module'; script.src = url; script.async = true; diff --git a/public/scripts/utils.js b/public/scripts/utils.js index eb944b586..60b49797a 100644 --- a/public/scripts/utils.js +++ b/public/scripts/utils.js @@ -67,6 +67,16 @@ export function escapeHtml(str) { return String(str).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"'); } +/** + * Make string safe for use as a CSS selector. + * @param {string} str String to sanitize + * @param {string} replacement Replacement for invalid characters + * @returns {string} Sanitized string + */ +export function sanitizeSelector(str, replacement = '_') { + return String(str).replace(/[^a-z0-9_-]/ig, replacement); +} + export function isValidUrl(value) { try { new URL(value); From efeedc12742154ad3d92189b0fde6e7b3c46f7ff Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Thu, 9 Jan 2025 22:39:40 +0200 Subject: [PATCH 3/3] Revert gallery selector changes --- public/scripts/extensions/gallery/index.js | 2 +- public/scripts/power-user.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/public/scripts/extensions/gallery/index.js b/public/scripts/extensions/gallery/index.js index 94b8c30c7..c34ea56e3 100644 --- a/public/scripts/extensions/gallery/index.js +++ b/public/scripts/extensions/gallery/index.js @@ -277,7 +277,7 @@ function makeMovable(id = 'gallery') { const newElement = $(template); newElement.css('background-color', 'var(--SmartThemeBlurTintColor)'); newElement.attr('forChar', id); - newElement.attr('id', `draggable_${id}`); + newElement.attr('id', id); newElement.find('.drag-grabber').attr('id', `${id}header`); newElement.find('.dragTitle').text('Image Gallery'); //add a div for the gallery diff --git a/public/scripts/power-user.js b/public/scripts/power-user.js index c25f275c7..b3b7f41d5 100644 --- a/public/scripts/power-user.js +++ b/public/scripts/power-user.js @@ -3970,7 +3970,7 @@ $(document).ready(() => { const targetSelector = { chat: '#chat', background: '#bg1', - gallery: '#draggable_gallery', + gallery: '#gallery', zoomedAvatar: 'div.zoomed_avatar', }[args.to || 'chat'];