UNPKG

igniteui-webcomponents

Version:

Ignite UI for Web Components is a complete library of UI components, giving you the ability to build modern web applications using encapsulation and the concept of reusable components in a dependency-free approach.

194 lines 6.4 kB
const FLAGS = new Set('aACL09#&?'); const REGEX = new Map([ ['C', /(?!^$)/u], ['&', /[^\p{Separator}]/u], ['a', /[\p{Letter}\d\p{Separator}]/u], ['A', /[\p{Letter}\d]/u], ['?', /[\p{Letter}\p{Separator}]/u], ['L', /\p{Letter}/u], ['0', /\d/], ['9', /[\d\p{Separator}]/u], ['#', /[\d\-+]/], ]); const REQUIRED = new Set('0#LA&'); const replaceIMENumbers = (string) => { return string.replace(/[0123456789]/g, (num) => ({ '1': '1', '2': '2', '3': '3', '4': '4', '5': '5', '6': '6', '7': '7', '8': '8', '9': '9', '0': '0', })[num]); }; export class MaskParser { constructor(options = { format: 'CCCCCCCCCC', promptCharacter: '_' }) { this.literals = new Map(); this._escapedMask = ''; this.options = options; this.parseMaskLiterals(); } get literalPositions() { return Array.from(this.literals.keys()); } get escapedMask() { return this._escapedMask; } get mask() { return this.options.format; } set mask(value) { this.options.format = value || this.options.format; this.parseMaskLiterals(); } get prompt() { return this.options.promptCharacter; } set prompt(value) { this.options.promptCharacter = value ? value.substring(0, 1) : this.options.promptCharacter; } parseMaskLiterals() { this.literals.clear(); this._escapedMask = this.mask; for (let i = 0, j = 0; i < this.mask.length; i++, j++) { const [current, next] = [this.mask.charAt(i), this.mask.charAt(i + 1)]; if (current === '\\' && FLAGS.has(next)) { this._escapedMask = this.replaceCharAt(this._escapedMask, j, ''); this.literals.set(j, next); i++; } else if (!FLAGS.has(current)) { this.literals.set(j, current); } } } isPromptChar(char) { return char === this.prompt; } replaceCharAt(string, pos, char) { return `${string.substring(0, pos)}${char}${string.substring(pos + 1)}`; } validate(char, maskedChar) { const regex = REGEX.get(maskedChar); return regex ? regex.test(char) : false; } getNonLiteralPositions(mask = '') { const positions = this.literalPositions; const result = []; const iter = Array.from(mask).entries(); for (const [pos, _] of iter) { if (!positions.includes(pos)) { result.push(pos); } } return result; } getRequiredNonLiteralPositions(mask) { const positions = this.literalPositions; const result = []; const iter = Array.from(mask).entries(); for (const [pos, char] of iter) { if (REQUIRED.has(char) && !positions.includes(pos)) { result.push(pos); } } return result; } getPreviousNonLiteralPosition(start) { const positions = this.literalPositions; for (let i = start; i > 0; i--) { if (!positions.includes(i)) return i; } return start; } getNextNonLiteralPosition(start) { const positions = this.literalPositions; for (let i = start; i < this._escapedMask.length; i++) { if (!positions.includes(i)) return i; } return start; } replace(maskString, value, start, end) { let masked = maskString ?? ''; const chars = Array.from(replaceIMENumbers(value)); const positions = this.literalPositions; const final = Math.min(end, masked.length); let cursor = start; for (let i = start; i < final || (chars.length && i < masked.length); i++) { if (positions.includes(i)) { if (chars[0] === masked[i]) { cursor = i + 1; chars.shift(); } continue; } if (chars[0] && !this.validate(chars[0], this._escapedMask[i]) && !this.isPromptChar(chars[0])) { break; } let char = this.prompt; if (chars.length) { cursor = i + 1; char = chars.shift(); } masked = this.replaceCharAt(masked, i, char); } return { value: masked, end: cursor }; } parse(masked = '') { const positions = this.literalPositions; const result = []; const iter = Array.from(masked).entries(); for (const [pos, char] of iter) { !positions.includes(pos) && !this.isPromptChar(char) ? result.push(char) : result.push(''); } return result.join(''); } isValidString(input = '') { const required = this.getRequiredNonLiteralPositions(this._escapedMask); if (required.length > this.parse(input).length) { return false; } return required.every((pos) => { const char = input.charAt(pos); return (this.validate(char, this._escapedMask.charAt(pos)) && !this.isPromptChar(char)); }); } apply(input = '') { const output = new Array(this._escapedMask.length).fill(this.prompt); for (const [pos, char] of this.literals.entries()) { output[pos] = char; } if (!input) { return output.join(''); } const nonLiteralPositions = this.getNonLiteralPositions(this._escapedMask); const values = nonLiteralPositions.map((pos, index) => { const char = input.charAt(index); return !this.validate(char, this._escapedMask.charAt(pos)) && !this.isPromptChar(char) ? this.prompt : char; }); if (values.length > nonLiteralPositions.length) { values.splice(nonLiteralPositions.length); } for (const [position, char] of values.entries()) { output[nonLiteralPositions[position]] = char; } return output.join(''); } } //# sourceMappingURL=mask-parser.js.map