UNPKG

react-native-advanced-input-mask

Version:

Text input mask for React Native on iOS, Android and web. Synchronous and easy formatting without hustle

189 lines (167 loc) 5.01 kB
import FormatError from "./FormatError"; export default class FormatSanitizer { public static sanitize(formatString: string): string { FormatSanitizer.checkOpenBraces(formatString); const blocks = this.divideBlocksWithMixedCharacters( this.getFormatBlocks(formatString), ); return FormatSanitizer.sortFormatBlocks(blocks).join(""); } private static getFormatBlocks(formatString: string): string[] { const blocks: string[] = []; let currentBlock = ""; let escape = false; for (const char of formatString) { if (char === "\\") { if (!escape) { escape = true; currentBlock += char; continue; } } if ((char === "[" || char === "{") && !escape) { if (currentBlock.length > 0) { blocks.push(currentBlock); } currentBlock = ""; } currentBlock += char; if ((char === "]" || char === "}") && !escape) { blocks.push(currentBlock); currentBlock = ""; } escape = false; } if (currentBlock.length > 0) { blocks.push(currentBlock); } return blocks; } private static divideBlocksWithMixedCharacters(blocks: string[]): string[] { const resultingBlocks: string[] = []; for (const block of blocks) { if (block.startsWith("[")) { let blockBuffer = ""; for (let i = 0; i < block.length; i++) { const blockCharacter = block[i]; if (blockCharacter === "[") { blockBuffer += blockCharacter; continue; } if (blockCharacter === "]" && !blockBuffer.endsWith("\\")) { blockBuffer += blockCharacter; resultingBlocks.push(blockBuffer); break; } if ( (blockCharacter === "0" || blockCharacter === "9") && (blockBuffer.includes("A") || blockBuffer.includes("a") || blockBuffer.includes("-") || blockBuffer.includes("_")) ) { blockBuffer += "]"; resultingBlocks.push(blockBuffer); blockBuffer = "[" + blockCharacter; continue; } if ( (blockCharacter === "A" || blockCharacter === "a") && (blockBuffer.includes("0") || blockBuffer.includes("9") || blockBuffer.includes("-") || blockBuffer.includes("_")) ) { blockBuffer += "]"; resultingBlocks.push(blockBuffer); blockBuffer = "[" + blockCharacter; continue; } if ( (blockCharacter === "-" || blockCharacter === "_") && (blockBuffer.includes("0") || blockBuffer.includes("9") || blockBuffer.includes("A") || blockBuffer.includes("a")) ) { blockBuffer += "]"; resultingBlocks.push(blockBuffer); blockBuffer = "[" + blockCharacter; continue; } blockBuffer += blockCharacter; } } else { resultingBlocks.push(block); } } return resultingBlocks; } private static sortFormatBlocks(blocks: string[]): string[] { const sortedBlocks: string[] = []; for (const block of blocks) { let sortedBlock: string; if (block.startsWith("[")) { if ( block.includes("0") || block.includes("9") || block.includes("A") || block.includes("a") ) { sortedBlock = "[" + block.replace("[", "").replace("]", "").split("").sort().join("") + "]"; } else { // For `_` or `-`, temporarily replace for sorting sortedBlock = "[" + block .replace("[", "") .replace("]", "") .replace("_", "A") .replace("-", "a") .split("") .sort() .join("") + "]"; sortedBlock = sortedBlock.replace("A", "_").replace("a", "-"); } } else { sortedBlock = block; } sortedBlocks.push(sortedBlock); } return sortedBlocks; } private static checkOpenBraces(str: string): void { let escape = false; let squareBraceOpen = false; let curlyBraceOpen = false; for (const char of str) { if (char === "\\") { escape = !escape; continue; } if (char === "[") { if (squareBraceOpen) { throw new FormatError(); } squareBraceOpen = !escape; } if (char === "]" && !escape) { squareBraceOpen = false; } if (char === "{") { if (curlyBraceOpen) { throw new FormatError(); } curlyBraceOpen = !escape; } if (char === "}" && !escape) { curlyBraceOpen = false; } escape = false; } } }