js/TextReplacer.js

/**
 * Class to process and apply string replacement rules.
 * Supports direct string replacement, regular expressions, and function-based replacements.
 */
class TextReplacer {
    /**
     * @param {Array<[string, string|Function]>} rules - Array of replacement rules.
     */
    constructor(rules) {
        if (!Array.isArray(rules)) {
            throw new TypeError("Rules must be an array of [pattern, replacement] pairs.");
        }
        this.rules = this.parseRules(rules);
    }

    /**
     * Parses the rules and converts them into appropriate types.
     * @param {Array<[string, string|Function]>} rules - Raw rules from user input.
     * @returns {Array<[string|RegExp, string|Function]>} - Parsed rules.
     */
    parseRules(rules) {
        console.log("%cParsing rules", "color: yellow", rules);
        let parsedRules = [];
        
        for (let i = 0; i < rules.length; i++) {
            let [pattern, replacement] = rules[i];
            
            if (!pattern) continue; // Skip blank patterns
            
            if (typeof pattern !== "string" || (typeof replacement !== "string" && typeof replacement !== "function")) {
                throw new TypeError("Each rule must be a [string, string|function] pair.");
            }
    
            if (common.isStringFunction(replacement)) {
                try {
                    replacement = eval(replacement); // Convert string to function
                    if (typeof replacement !== "function") {
                        throw new TypeError("Evaluated replacement is not a function.");
                    }
                } catch (error) {
                    console.error("Error evaluating function string:", replacement, error);
                    throw new Error("Invalid function definition in replacement rule.");
                }
            }
    
            if (common.isRegExp(pattern)) {
                try {
                    parsedRules.push([
                        new RegExp(pattern.slice(1, pattern.lastIndexOf('/')), pattern.slice(pattern.lastIndexOf('/') + 1)),
                        replacement || ""
                    ]);
                    continue;
                } catch (error) {
                    console.error("Error creating RegExp:", pattern, error);
                    throw new Error("Invalid regular expression pattern.");
                }
            }
    
            parsedRules.push([pattern, replacement || ""]);
        }
        
        return parsedRules;
    }
    

    /**
     * Applies the replacement rules to the given text.
     * @param {string} text - The input text to process.
     * @returns {string} - The modified text.
     */
    apply(text) {
        if (typeof text !== "string") {
            throw new TypeError("Input text must be a string.");
        }
        return this.rules.reduce((result, [pattern, replacement]) => {
            if (!pattern) return result;
            return result.replace(pattern, replacement);
        }, text);
    }
}

module.exports = TextReplacer;