diff --git a/public/scripts/extensions/regex/engine.js b/public/scripts/extensions/regex/engine.js index 069e71aad..7cd22c511 100644 --- a/public/scripts/extensions/regex/engine.js +++ b/public/scripts/extensions/regex/engine.js @@ -6,20 +6,33 @@ export { runRegexScript, }; +/** + * @enum {number} Where the regex script should be applied + */ const regex_placement = { - // MD Display is deprecated. Do not use. + /** + * @deprecated MD Display is deprecated. Do not use. + */ MD_DISPLAY: 0, USER_INPUT: 1, AI_OUTPUT: 2, SLASH_COMMAND: 3, }; +/** + * @enum {number} How the regex script should replace the matched string + */ const regex_replace_strategy = { REPLACE: 0, OVERLAY: 1, }; -// Originally from: https://github.com/IonicaBizau/regex-parser.js/blob/master/lib/index.js +/** + * Instantiates a regular expression from a string. + * @param {string} input The input string. + * @returns {RegExp} The regular expression instance. + * @copyright Originally from: https://github.com/IonicaBizau/regex-parser.js/blob/master/lib/index.js + */ function regexFromString(input) { try { // Parse input @@ -37,8 +50,21 @@ function regexFromString(input) { } } -// Parent function to fetch a regexed version of a raw string +/** + * Parent function to fetch a regexed version of a raw string + * @param {string} rawString The raw string to be regexed + * @param {regex_placement} placement The placement of the string + * @param {RegexParams} params The parameters to use for the regex script + * @returns {string} The regexed string + * @typedef {{characterOverride?: string, isMarkdown?: boolean, isPrompt?: boolean }} RegexParams The parameters to use for the regex script + */ function getRegexedString(rawString, placement, { characterOverride, isMarkdown, isPrompt } = {}) { + // WTF have you passed me? + if (typeof rawString !== 'string') { + console.warn('getRegexedString: rawString is not a string. Returning empty string.'); + return ''; + } + let finalString = rawString; if (extension_settings.disabledExtensions.includes('regex') || !rawString || placement === undefined) { return finalString; @@ -66,8 +92,9 @@ function getRegexedString(rawString, placement, { characterOverride, isMarkdown, * Runs the provided regex script on the given string * @param {object} regexScript The regex script to run * @param {string} rawString The string to run the regex script on - * @param {object} params The parameters to use for the regex script + * @param {RegexScriptParams} params The parameters to use for the regex script * @returns {string} The new string + * @typedef {{characterOverride?: string}} RegexScriptParams The parameters to use for the regex script */ function runRegexScript(regexScript, rawString, { characterOverride } = {}) { let newString = rawString; @@ -75,7 +102,6 @@ function runRegexScript(regexScript, rawString, { characterOverride } = {}) { return newString; } - let match; const findRegex = regexFromString(regexScript.substituteRegex ? substituteParams(regexScript.findRegex) : regexScript.findRegex); // The user skill issued. Return with nothing. @@ -83,46 +109,31 @@ function runRegexScript(regexScript, rawString, { characterOverride } = {}) { return newString; } - while ((match = findRegex.exec(rawString)) !== null) { - const fencedMatch = match[0]; - const capturedMatch = match[1]; + newString = rawString.replace(findRegex, (fencedMatch) => { + let trimFencedMatch = filterString(fencedMatch, regexScript.trimStrings, { characterOverride }); - let trimCapturedMatch; - let trimFencedMatch; - if (capturedMatch) { - const tempTrimCapture = filterString(capturedMatch, regexScript.trimStrings, { characterOverride }); - trimFencedMatch = fencedMatch.replaceAll(capturedMatch, tempTrimCapture); - trimCapturedMatch = tempTrimCapture; - } else { - trimFencedMatch = filterString(fencedMatch, regexScript.trimStrings, { characterOverride }); - } - - // TODO: Use substrings for replacement. But not necessary at this time. - // A substring is from match.index to match.index + match[0].length or fencedMatch.length const subReplaceString = substituteRegexParams( regexScript.replaceString, - trimCapturedMatch ?? trimFencedMatch, + trimFencedMatch, { characterOverride, replaceStrategy: regexScript.replaceStrategy ?? regex_replace_strategy.REPLACE, }, ); - if (!newString) { - newString = rawString.slice(0, match.index) + rawString.slice(match.index).replace(fencedMatch, subReplaceString); - } else { - newString = newString.slice(0, match.index) + newString.slice(match.index).replace(fencedMatch, subReplaceString); - } - // If the regex isn't global, break out of the loop - if (!findRegex.flags.includes('g')) { - break; - } - } + return subReplaceString; + }); return newString; } -// Filters anything to trim from the regex match +/** + * Filters anything to trim from the regex match + * @param {string} rawString The raw string to filter + * @param {string[]} trimStrings The strings to trim + * @param {RegexScriptParams} params The parameters to use for the regex filter + * @returns {string} The filtered string + */ function filterString(rawString, trimStrings, { characterOverride } = {}) { let finalString = rawString; trimStrings.forEach((trimString) => { @@ -133,7 +144,14 @@ function filterString(rawString, trimStrings, { characterOverride } = {}) { return finalString; } -// Substitutes regex-specific and normal parameters +/** + * Substitutes regex-specific and normal parameters + * @param {string} rawString + * @param {string} regexMatch + * @param {RegexSubstituteParams} params The parameters to use for the regex substitution + * @returns {string} The substituted string + * @typedef {{characterOverride?: string, replaceStrategy?: number}} RegexSubstituteParams The parameters to use for the regex substitution + */ function substituteRegexParams(rawString, regexMatch, { characterOverride, replaceStrategy } = {}) { let finalString = rawString; finalString = substituteParams(finalString, undefined, characterOverride); @@ -188,8 +206,13 @@ function substituteRegexParams(rawString, regexMatch, { characterOverride, repla return finalString; } -// Splices common sentence symbols and whitespace from the beginning and end of a string -// Using a for loop due to sequential ordering +/** + * Splices common sentence symbols and whitespace from the beginning and end of a string. + * Using a for loop due to sequential ordering. + * @param {string} rawString The raw string to splice + * @param {boolean} isSuffix String is a suffix + * @returns {string} The spliced string + */ function spliceSymbols(rawString, isSuffix) { let offset = 0;