Merge pull request #3648 from SillyTavern/regex-info-block Add info block for find regex flags

d4f6373bbcf4e5b5401f92183240415a338fab0e

Cohee <18619528+Cohee1207@users.noreply.github.com>

Signed
3 files changed, +67 -2Ignore whitespace
public/scripts/extensions/regex/editor.html+7 -0
@@ -16,6 +16,13 @@
1616 </small>
1717 <hr />
1818
19+ <div id="regex_info_block_wrapper">
20+ <div id="regex_info_block" class="info-block"></div>
21+ <a id="regex_info_block_flags_hint" href="http://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions#advanced_searching_with_flags" target="_blank" rel="noopener noreferrer">
22+ <i class="fa-solid fa-circle-info" title="Click here to learn more about regex flags."></i>
23+ </a>
24+ </div>
25+
1926 <div id="regex_test_mode" class="flex1 flex-container displayNone">
2027 <div class="flex1">
2128 <label class="title_restorable" for="regex_test_input">
public/scripts/extensions/regex/index.js+39 -2
@@ -7,7 +7,7 @@ import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from '
77import { enumIcons } from '../../slash-commands/SlashCommandCommonEnumsProvider.js';
88import { SlashCommandEnumValue, enumTypes } from '../../slash-commands/SlashCommandEnumValue.js';
99import { SlashCommandParser } from '../../slash-commands/SlashCommandParser.js';
1010import { download, getFileText, getSortableDelay, regexFromString, setInfoBlock, uuidv4 } from '../../utils.js';
1111import { regex_placement, runRegexScript, substitute_find_regex } from './engine.js';
1212import { t } from '../../i18n.js';
1313import { accountStorage } from '../../util/AccountStorage.js';
@@ -258,6 +258,8 @@ async function onRegexEditorOpenClick(existingId, isScoped) {
258258 });
259259
260260 function updateTestResult() {
261+ updateInfoBlock(editorHtml);
262+
261263 if (!editorHtml.find('#regex_test_mode').is(':visible')) {
262264 return;
263265 }
@@ -276,6 +278,7 @@ async function onRegexEditorOpenClick(existingId, isScoped) {
276278 }
277279
278280 editorHtml.find('input, textarea, select').on('input', updateTestResult);
281+ updateInfoBlock(editorHtml);
279282
280283 const popupResult = await callPopup(editorHtml, 'confirm', undefined, { okButton: t`Save` });
281284 if (popupResult) {
@@ -305,6 +308,40 @@ async function onRegexEditorOpenClick(existingId, isScoped) {
305308 }
306309}
307310
311+/**
312+ * Updates the info block in the regex editor with hints regarding the find regex.
313+ * @param {JQuery<HTMLElement>} editorHtml The editor HTML
314+ */
315+function updateInfoBlock(editorHtml) {
316+ const infoBlock = editorHtml.find('.info-block').get(0);
317+ const infoBlockFlagsHint = editorHtml.find('#regex_info_block_flags_hint');
318+ const findRegex = String(editorHtml.find('.find_regex').val());
319+
320+ infoBlockFlagsHint.hide();
321+
322+ // Clear the info block if the find regex is empty
323+ if (!findRegex) {
324+ setInfoBlock(infoBlock, t`Find Regex is empty`, 'info');
325+ return;
326+ }
327+
328+ try {
329+ const regex = regexFromString(findRegex);
330+ if (!regex) {
331+ throw new Error(t`Invalid Find Regex`);
332+ }
333+
334+ const flagInfo = [];
335+ flagInfo.push(regex.flags.includes('g') ? t`Applies to all matches` : t`Applies to the first match`);
336+ flagInfo.push(regex.flags.includes('i') ? t`Case insensitive` : t`Case sensitive`);
337+
338+ setInfoBlock(infoBlock, flagInfo.join('. '), 'hint');
339+ infoBlockFlagsHint.show();
340+ } catch (error) {
341+ setInfoBlock(infoBlock, error.message, 'error');
342+ }
343+}
344+
308345// Common settings migration function. Some parts will eventually be removed
309346// TODO: Maybe migrate placement to strings?
310347function migrateSettings() {
@@ -418,7 +455,7 @@ async function onRegexImportFileChange(file, isScoped) {
418455 }
419456}
420457
421458function purgeEmbeddedRegexScripts( { character }) {
422459 const avatar = character?.avatar;
423460
424461 if (avatar && extension_settings.character_allowed_regex?.includes(avatar)) {
public/scripts/extensions/regex/style.css+21 -0
@@ -105,3 +105,24 @@ input.enable_scoped {
105105.disable_regex:not(:checked) ~ .regex-toggle-on {
106106 display: block;
107107}
108+
109+#regex_info_block_wrapper {
110+ position: relative;
111+}
112+
113+#regex_info_block {
114+ margin: 10px 0;
115+ padding: 5px 20px;
116+ font-size: 0.9em;
117+}
118+
119+#regex_info_block_wrapper:has(#regex_info_block:empty) {
120+ display: none;
121+}
122+
123+#regex_info_block_flags_hint {
124+ position: absolute;
125+ top: 50%;
126+ right: 10px;
127+ transform: translateY(-50%);
128+}