/** * Zalgo Text Generator * Generates corrupted/glitched text using Unicode combining characters */ /* exported ZalgoGenerator */ class ZalgoGenerator { constructor() { // Combining diacritical marks that appear above characters this.above = [ '\u0300', '\u0301', '\u0302', '\u0303', '\u0304', '\u0305', '\u0306', '\u0307', '\u0308', '\u0309', '\u030A', '\u030B', '\u030C', '\u030D', '\u030E', '\u030F', '\u0310', '\u0311', '\u0312', '\u0313', '\u0314', '\u0315', '\u0316', '\u0317', '\u0318', '\u0319', '\u031A', '\u031B', '\u031C', '\u031D', '\u031E', '\u031F', '\u0320', '\u0321', '\u0322', '\u0323', '\u0324', '\u0325', '\u0326', '\u0327', '\u0328', '\u0329', '\u032A', '\u032B', '\u032C', '\u032D', '\u032E', '\u032F', '\u0330', '\u0331', '\u0332', '\u0333', '\u0334', '\u0335', '\u0336', '\u0337', '\u0338', '\u0339', '\u033A', '\u033B', '\u033C', '\u033D', '\u033E', '\u033F', '\u0340', '\u0341', '\u0342', '\u0343', '\u0344', '\u0345', '\u0346', '\u0347', '\u0348', '\u0349', '\u034A', '\u034B', '\u034C', '\u034D', '\u034E', '\u034F', '\u0350', '\u0351', '\u0352', '\u0353', '\u0354', '\u0355', '\u0356', '\u0357', '\u0358', '\u0359', '\u035A', '\u035B', '\u035C', '\u035D', '\u035E', '\u035F', '\u0360', '\u0361', '\u0362', '\u0363', '\u0364', '\u0365', '\u0366', '\u0367', '\u0368', '\u0369', '\u036A', '\u036B', '\u036C', '\u036D', '\u036E', '\u036F', ]; // Combining diacritical marks that appear in the middle this.middle = [ '\u0315', '\u031B', '\u0340', '\u0341', '\u0358', '\u0321', '\u0322', '\u0327', '\u0328', '\u0334', '\u0335', '\u0336', '\u034F', '\u035C', '\u035D', '\u035E', '\u035F', '\u0360', '\u0362', '\u0338', '\u0337', '\u0361', '\u0489', ]; // Combining diacritical marks that appear below characters this.below = [ '\u0316', '\u0317', '\u0318', '\u0319', '\u031C', '\u031D', '\u031E', '\u031F', '\u0320', '\u0324', '\u0325', '\u0326', '\u0329', '\u032A', '\u032B', '\u032C', '\u032D', '\u032E', '\u032F', '\u0330', '\u0331', '\u0332', '\u0333', '\u0339', '\u033A', '\u033B', '\u033C', '\u0345', '\u0347', '\u0348', '\u0349', '\u034D', '\u034E', '\u0353', '\u0354', '\u0355', '\u0356', '\u0359', '\u035A', '\u0323', ]; } /** * Get a random character from an array */ randomChar(array) { return array[Math.floor(Math.random() * array.length)]; } /** * Generate a specified number of random characters from an array */ randomChars(array, count) { let result = ''; for (let i = 0; i < count; i++) { result += this.randomChar(array); } return result; } /** * Generate zalgo text with specified intensity * @param {string} text - The input text to corrupt * @param {number} intensity - Corruption intensity (1-10) * @returns {string} - The corrupted zalgo text */ generate(text, intensity = 5) { if (!text) return ''; // Normalize intensity to 1-10 range intensity = Math.max(1, Math.min(10, intensity)); let result = ''; for (let char of text) { result += char; // Skip whitespace and newlines if (/\s/.test(char)) { continue; } // Calculate how many combining characters to add based on intensity // Higher intensity = more corruption const factor = intensity / 10; // Add characters above (0-3 based on intensity) const aboveCount = Math.floor(Math.random() * (4 * factor)); result += this.randomChars(this.above, aboveCount); // Add characters in middle (0-2 based on intensity) const middleCount = Math.floor(Math.random() * (3 * factor)); result += this.randomChars(this.middle, middleCount); // Add characters below (0-3 based on intensity) const belowCount = Math.floor(Math.random() * (4 * factor)); result += this.randomChars(this.below, belowCount); } return result; } /** * Remove zalgo corruption from text * @param {string} text - The corrupted text * @returns {string} - Clean text without combining characters */ clean(text) { // Remove all combining characters (Unicode category Mn) return text.replace(/[\u0300-\u036f\u0489]/g, ''); } }