Created
February 27, 2025 18:26
-
-
Save devanshbatham/6007f443f119435cc6d390dccf870d53 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function findUnicodeVariants(input) { | |
const results = []; | |
const inputLower = input.toLowerCase(); | |
const inputUpper = input.toUpperCase(); | |
const startSubstrLower = inputLower.slice(0, 2); // First 2 chars for substring check | |
const startSubstrUpper = inputUpper.slice(0, 2); | |
// Function to test a full-string variant | |
function testFullVariant(original, variant, pos, unicodeChar, codePoint) { | |
const upper = variant.toUpperCase(); | |
const lower = variant.toLowerCase(); | |
if (upper === inputUpper) { | |
results.push({ | |
type: "full", | |
original: input, | |
variant: variant, | |
substitutedChar: unicodeChar, | |
position: pos, | |
unicode: `U+${codePoint.toString(16).padStart(4, "0")}`, | |
conversion: "toUpperCase", | |
result: upper, | |
description: `Substituted '${input[pos]}' at position ${pos} with '${unicodeChar}' (${`U+${codePoint.toString(16).padStart(4, "0")}`}), uppercased to '${upper}'` | |
}); | |
} | |
if (lower === inputLower && lower !== upper) { | |
results.push({ | |
type: "full", | |
original: input, | |
variant: variant, | |
substitutedChar: unicodeChar, | |
position: pos, | |
unicode: `U+${codePoint.toString(16).padStart(4, "0")}`, | |
conversion: "toLowerCase", | |
result: lower, | |
description: `Substituted '${input[pos]}' at position ${pos} with '${unicodeChar}' (${`U+${codePoint.toString(16).padStart(4, "0")}`}), lowercased to '${lower}'` | |
}); | |
} | |
} | |
// Function to test a starting substring match | |
function testSubstringMatch(unicodeChar, codePoint) { | |
const upper = unicodeChar.toUpperCase(); | |
const lower = unicodeChar.toLowerCase(); | |
if (upper === startSubstrUpper && upper.length === 2) { | |
results.push({ | |
type: "substring", | |
original: input, | |
variant: unicodeChar, | |
substitutedChar: unicodeChar, | |
position: "start (0-1)", | |
unicode: `U+${codePoint.toString(16).padStart(4, "0")}`, | |
conversion: "toUpperCase", | |
result: upper, | |
description: `Single character '${unicodeChar}' (${`U+${codePoint.toString(16).padStart(4, "0")}`}) uppercased to '${upper}', matches start of '${input}'` | |
}); | |
} | |
if (lower === startSubstrLower && lower !== upper && lower.length === 2) { | |
results.push({ | |
type: "substring", | |
original: input, | |
variant: unicodeChar, | |
position: "start (0-1)", | |
unicode: `U+${codePoint.toString(16).padStart(4, "0")}`, | |
conversion: "toLowerCase", | |
result: lower, | |
description: `Single character '${unicodeChar}' (${`U+${codePoint.toString(16).padStart(4, "0")}`}) lowercased to '${lower}', matches start of '${input}'` | |
}); | |
} | |
} | |
// Scan Unicode characters, skipping ASCII (U+0000 to U+007F) | |
for (let i = 0x0080; i <= 0xFFFF; i++) { | |
const unicodeChar = String.fromCharCode(i); | |
const charUpper = unicodeChar.toUpperCase(); | |
const charLower = unicodeChar.toLowerCase(); | |
if (charUpper === charLower && charUpper === unicodeChar) continue; | |
// Check for full-string substitution | |
for (let pos = 0; pos < input.length; pos++) { | |
const prefix = input.slice(0, pos); | |
const suffix = input.slice(pos + 1); | |
const variant = prefix + unicodeChar + suffix; | |
testFullVariant(input, variant, pos, unicodeChar, i); | |
} | |
// Check for starting substring match | |
testSubstringMatch(unicodeChar, i); | |
} | |
return results; | |
} | |
// Function to display results without the JS file prefix | |
function displayResults(input) { | |
const variants = findUnicodeVariants(input); | |
if (variants.length === 0) { | |
console.log(`Found 0 non-ASCII Unicode variants for "${input}":`); | |
return; | |
} | |
console.log(`Found ${variants.length} non-ASCII Unicode variants for "${input}":`); | |
variants.forEach((result, index) => { | |
console.log(``); // Empty line before each variant | |
console.log(`Variant ${index + 1}:`); | |
console.log(`- Original: "${result.original}"`); | |
console.log(`- Variant: "${result.variant}"`); | |
console.log(`- Substituted: '${result.substitutedChar}' (${result.unicode}) at position ${result.position}`); | |
console.log(`- Conversion: ${result.conversion} → "${result.result}"`); | |
console.log(`- Description: ${result.description}`); | |
}); | |
console.log(``); // Empty line after last variant | |
} | |
// Test with some examples | |
const testStrings = ["script", "style", "div"]; | |
testStrings.forEach(str => { | |
displayResults(str); | |
console.log("-----------------------------------"); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment