Skip to content

Instantly share code, notes, and snippets.

@maximkott
Last active April 15, 2024 20:43
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save maximkott/31dfdd37d4c0fee499de453faca17c83 to your computer and use it in GitHub Desktop.
Save maximkott/31dfdd37d4c0fee499de453faca17c83 to your computer and use it in GitHub Desktop.
mask a string in javascript
export const maskString = (
value: any,
mask: string,
maskPatterns: Record<string, RegExp | ((char: string) => boolean)>
) => {
value = value || '';
mask = mask || '';
maskPatterns = maskPatterns || {};
let maskedValue = '';
// array representation of string under test
const valueParts = value.split('');
// array representation of the mask
const maskParts = mask.split('');
// as long as there are still characters left in
// the original string, one must try to mask them
while (valueParts.length > 0) {
// take the first character and remove
// it from the original string
let unmaskedChar = valueParts.shift();
// as long as the character has not been masked
// one must try to find a mask
while (unmaskedChar !== null) {
// take the first mask character from
// the mask string
const maskChar = maskParts.shift();
const maskCharIsOptional = maskParts[0] === '?';
// remove '?' from the mask parts
if (maskCharIsOptional) {
maskParts.shift();
}
// make sure the masking character exists
// otherwise this means that the original string
// exceeds the masking pattern length
if (maskChar !== undefined) {
// try to find a pattern for the particular
// mask character
const maskPattern = maskPatterns[maskChar.toUpperCase()];
// if there is no pattern configured for
// this particular mask character, assume
// the mask character is a placeholder / formatting
// value that must be added to the string
if (maskPattern !== undefined) {
let check = false;
// mask pattern can be either a function
if (typeof maskPattern === 'function') {
check = maskPattern(unmaskedChar);
}
// or a regex string
else if (maskPattern instanceof RegExp) {
check = maskPattern.test(unmaskedChar);
}
// if character has passed the mask check,
// it can bee added to the final masked value
if (check) {
maskedValue += unmaskedChar;
unmaskedChar = null;
}
// the character did not pass the mask check,
// however, the mask was optional, we can skip it
else if (!check && maskCharIsOptional) {
}
// otherwise one must put the pattern back into
// the array so the next character can try to
// pass the mask check
else {
maskParts.unshift(maskChar);
unmaskedChar = null;
}
}
// mask character is a placeholder / formatting value
// and must be added to the masked string
else {
maskedValue += maskChar;
if (unmaskedChar === maskChar) {
unmaskedChar = null;
}
}
}
// no masking character could be found,
// the original string is probably longer
// then the mask pattern and therefore
// the leftovers can be cut off
else {
// reset current character to continue the loop
unmaskedChar = null;
}
}
}
return maskedValue;
};
// now you can do
console.log(maskString("+41 767007070", "+YXX? YX XXX XX XX", { X: /[0-9]/, Y: /[1-9]/ }))
// +41 76 700 70 70
console.log(maskString("+3800767007070", "+YXX? YX XXX XX XX", { X: /[0-9]/, Y: /[1-9]/ }))
// +380 76 700 70 70
@fredericoo
Copy link

Hey man just thank you for this quick and easy masking function. I made use of it with some changes. Highly appreciate it

@maximkott
Copy link
Author

@fredericoo I'm happy you found it useful 🙂

@kevintech
Copy link

2024, your snippet is one of the best I could find for this purpose. Thanks for sharing!!

@maximkott
Copy link
Author

@kevintech You're very welcome 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment