diff --git a/public/scripts/utils.js b/public/scripts/utils.js index e23187e66..ac63fdbcc 100644 --- a/public/scripts/utils.js +++ b/public/scripts/utils.js @@ -1502,9 +1502,9 @@ export function select2ModifyOptions(element, items, { select = false, changeEve * Can be used on a single global array, querying data from the server or anything similar. * * @param {function():Select2Option[]} dataProvider - The provider/function to retrieve the data - can be as simple as "() => myData" for arrays - * @return {object} The ajax object with the transport function to use on the select2 ajax property + * @return {{transport: function}} The ajax object with the transport function to use on the select2 ajax property */ -export function getDynamicSelect2DataViaAjax(dataProvider) { +export function dynamicSelect2DataViaAjax(dataProvider) { function dynamicSelect2DataTransport(params, success, failure) { var items = dataProvider(); // fitering if params.data.q available @@ -1524,3 +1524,44 @@ export function getDynamicSelect2DataViaAjax(dataProvider) { }; return ajax; } + +/** + * Applies syntax highlighting to a given regex string by generating HTML with classes + * + * @param {string} regexStr - The javascript compatible regex string + * @returns {string} The html representation of the highlighted regex + */ +export function highlightRegex(regexStr) { + // Function to escape HTML special characters for safety + const escapeHtml = (str) => str.replace(/[&<>"']/g, match => ({ + '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' + })[match]); + + // Replace special characters with their HTML-escaped forms + regexStr = escapeHtml(regexStr); + + // Patterns that we want to highlight only if they are not escaped + const patterns = { + brackets: /(? { + regexStr = regexStr.replace(pattern, match => `${match}`); + }; + + // Apply highlighting patterns + wrapPattern(patterns.brackets, 'regex-brackets'); + wrapPattern(patterns.quantifiers, 'regex-quantifier'); + wrapPattern(patterns.operators, 'regex-operator'); + wrapPattern(patterns.specialChars, 'regex-special'); + wrapPattern(patterns.flags, 'regex-flags'); + wrapPattern(patterns.delimiters, 'regex-delimiter'); + + return `${regexStr}`; +} \ No newline at end of file diff --git a/public/scripts/world-info.js b/public/scripts/world-info.js index 81b912fb1..510fa6a91 100644 --- a/public/scripts/world-info.js +++ b/public/scripts/world-info.js @@ -1,5 +1,5 @@ import { saveSettings, callPopup, substituteParams, getRequestHeaders, chat_metadata, this_chid, characters, saveCharacterDebounced, menu_type, eventSource, event_types, getExtensionPromptByName, saveMetadata, getCurrentChatId, extension_prompt_roles } from '../script.js'; -import { download, debounce, initScrollHeight, resetScrollHeight, parseJsonFile, extractDataFromPng, getFileBuffer, getCharaFilename, getSortableDelay, escapeRegex, PAGINATION_TEMPLATE, navigation_option, waitUntilCondition, isTrueBoolean, setValueByPath, flashHighlight, select2ModifyOptions, getStringHash, getSelect2OptionId, getDynamicSelect2DataViaAjax } from './utils.js'; +import { download, debounce, initScrollHeight, resetScrollHeight, parseJsonFile, extractDataFromPng, getFileBuffer, getCharaFilename, getSortableDelay, escapeRegex, PAGINATION_TEMPLATE, navigation_option, waitUntilCondition, isTrueBoolean, setValueByPath, flashHighlight, select2ModifyOptions, getStringHash, getSelect2OptionId, dynamicSelect2DataViaAjax, highlightRegex } from './utils.js'; import { extension_settings, getContext } from './extensions.js'; import { NOTE_MODULE_NAME, metadata_keys, shouldWIAddPrompt } from './authors-note.js'; import { registerSlashCommand } from './slash-commands.js'; @@ -1332,6 +1332,7 @@ function getWorldEntry(name, data, entry) { const content = $('').addClass('item').text(item.text); const isRegex = isValidRegex(item.text); if (isRegex) { + content.html(highlightRegex(item.text)); content.addClass('regex_item').prepend($('').addClass('regex_icon').text("•*").attr('title', 'Regex')); } @@ -1348,7 +1349,7 @@ function getWorldEntry(name, data, entry) { if (!isMobile()) { input.select2({ - ajax: getDynamicSelect2DataViaAjax(() => worldEntryKeyOptionsCache), + ajax: dynamicSelect2DataViaAjax(() => worldEntryKeyOptionsCache), tags: true, tokenSeparators: [','], tokenizer: customTokenizer, diff --git a/public/style.css b/public/style.css index 3a32569c8..487206bd6 100644 --- a/public/style.css +++ b/public/style.css @@ -4035,4 +4035,13 @@ body:not(.movingUI) .drawer-content.maximized { height: 100vh; z-index: 9999; } -} \ No newline at end of file +} + +/* CSS styles using a consistent pastel color palette */ +.regex-brackets { color: #FFB347; } /* Pastel Orange */ +.regex-special { color: #B0E0E6; } /* Powder Blue */ +.regex-quantifier { color: #DDA0DD; } /* Plum */ +.regex-operator { color: #FFB6C1; } /* Light Pink */ +.regex-flags { color: #98FB98; } /* Pale Green */ +.regex-delimiter { font-weight: bold; color: #FF6961; } /* Pastel Red */ +.regex-highlight { color: #FAF8F6; } /* Pastel White */ \ No newline at end of file