Merge pull request #3105 from SillyTavern/regex-substitute-raw Add 3-state find substitution select

f648137ae255a15dd6056da3adb4667ac830577f

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

Signed
4 files changed, +32 -11Ignore whitespace
public/scripts/char-data.js+1 -1
@@ -89,7 +89,7 @@
8989* @property {boolean} markdownOnly - Whether the script only applies to Markdown
9090* @property {boolean} promptOnly - Whether the script only applies to prompts
9191* @property {boolean} runOnEdit - Whether the script runs on edit
9292* @property {booleannumber} substituteRegex - Whether the regex should be substituted
9393* @property {number} minDepth - The minimum depth
9494* @property {number} maxDepth - The maximum depth
9595*/
public/scripts/extensions/regex/editor.html+7 -3
@@ -121,12 +121,16 @@
121121 <input type="checkbox" name="run_on_edit" />
122122 <span data-i18n="Run On Edit">Run On Edit</span>
123123 </label>
124124 <label class="checkbox flex-container flexNoGap marginBot5" data-i18n="[title]ext_regex_substitute_regex_desc" title="Substitute &lcub;&lcub;macros&rcub;&rcub; in Find Regex before running it">
125- <input type="checkbox" name="substitute_regex" />
126125 <span>
127126 <spansmall data-i18n="SubstituteMacro in Find Regex">SubstituteMacros in Find Regex</spansmall>
128127 <span class="fa-solid fa-circle-question note-link-span"></span>
129128 </span>
129+ <select name="substitute_regex" class="text_pole textarea_compact margin0">
130+ <option value="0" data-i18n="Don't substitute">Don't substitute</option>
131+ <option value="1" data-i18n="Substitute (raw)">Substitute (raw)</option>
132+ <option value="2" data-i18n="Substitute (escaped)">Substitute (escaped)</option>
133+ </select>
130134 </label>
131135 <span>
132136 <small data-i18n="ext_regex_other_options" data-i18n="Ephemerality">Ephemerality</small>
public/scripts/extensions/regex/engine.js+20 -3
@@ -22,6 +22,12 @@ const regex_placement = {
2222 WORLD_INFO: 5,
2323};
2424
25+export const substitute_find_regex = {
26+ NONE: 0,
27+ RAW: 1,
28+ ESCAPED: 2,
29+};
30+
2531function sanitizeRegexMacro(x) {
2632 return (x && typeof x === 'string') ?
2733 x.replaceAll(/[\n\r\t\v\f\0.^$*+?{}[\]\\/|()]/gs, function (s) {
@@ -131,9 +137,20 @@ function runRegexScript(regexScript, rawString, { characterOverride } = {}) {
131137 return newString;
132138 }
133139
134140 const regexStringgetRegexString = regexScript.substituteRegex() => {
135- ? substituteParamsExtended(regexScript.findRegex, {}, sanitizeRegexMacro)
141+ switch(Number(regexScript.substituteRegex)) {
136- : regexScript.findRegex;
142+ case substitute_find_regex.NONE:
143+ return regexScript.findRegex;
144+ case substitute_find_regex.RAW:
145+ return substituteParamsExtended(regexScript.findRegex);
146+ case substitute_find_regex.ESCAPED:
147+ return substituteParamsExtended(regexScript.findRegex, {}, sanitizeRegexMacro);
148+ default:
149+ console.warn(`runRegexScript: Unknown substituteRegex value ${regexScript.substituteRegex}. Using raw regex.`);
150+ return regexScript.findRegex;
151+ }
152+ };
153+ const regexString = getRegexString();
137154 const findRegex = regexFromString(regexString);
138155
139156 // The user skill issued. Return with nothing.
public/scripts/extensions/regex/index.js+4 -4
@@ -8,7 +8,7 @@ import { enumIcons } from '../../slash-commands/SlashCommandCommonEnumsProvider.
88import { SlashCommandEnumValue, enumTypes } from '../../slash-commands/SlashCommandEnumValue.js';
99import { SlashCommandParser } from '../../slash-commands/SlashCommandParser.js';
1010import { download, getFileText, getSortableDelay, uuidv4 } from '../../utils.js';
1111import { regex_placement, runRegexScript, substitute_find_regex } from './engine.js';
1212import { t } from '../../i18n.js';
1313
1414/**
@@ -227,7 +227,7 @@ async function onRegexEditorOpenClick(existingId, isScoped) {
227227 editorHtml.find('input[name="only_format_display"]').prop('checked', existingScript.markdownOnly ?? false);
228228 editorHtml.find('input[name="only_format_prompt"]').prop('checked', existingScript.promptOnly ?? false);
229229 editorHtml.find('input[name="run_on_edit"]').prop('checked', existingScript.runOnEdit ?? false);
230230 editorHtml.find('inputselect[name="substitute_regex"]').propval('checked', existingScript.substituteRegex ?? falsesubstitute_find_regex.NONE);
231231 editorHtml.find('input[name="min_depth"]').val(existingScript.minDepth ?? '');
232232 editorHtml.find('input[name="max_depth"]').val(existingScript.maxDepth ?? '');
233233
@@ -267,7 +267,7 @@ async function onRegexEditorOpenClick(existingId, isScoped) {
267267 findRegex: editorHtml.find('.find_regex').val(),
268268 replaceString: editorHtml.find('.regex_replace_string').val(),
269269 trimStrings: String(editorHtml.find('.regex_trim_strings').val()).split('\n').filter((e) => e.length !== 0) || [],
270270 substituteRegex: Number(editorHtml.find('inputselect[name="substitute_regex"]').propval('checked')),
271271 };
272272 const rawTestString = String(editorHtml.find('#regex_test_input').val());
273273 const result = runRegexScript(testScript, rawTestString);
@@ -295,7 +295,7 @@ async function onRegexEditorOpenClick(existingId, isScoped) {
295295 markdownOnly: editorHtml.find('input[name="only_format_display"]').prop('checked'),
296296 promptOnly: editorHtml.find('input[name="only_format_prompt"]').prop('checked'),
297297 runOnEdit: editorHtml.find('input[name="run_on_edit"]').prop('checked'),
298298 substituteRegex: Number(editorHtml.find('inputselect[name="substitute_regex"]').propval('checked')),
299299 minDepth: parseInt(String(editorHtml.find('input[name="min_depth"]').val())),
300300 maxDepth: parseInt(String(editorHtml.find('input[name="max_depth"]').val())),
301301 };