forked from text-mask/text-mask
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
26 changed files
with
474 additions
and
76 deletions.
There are no files selected for viewing
This file contains 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
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
import emailPipe from './emailPipe.js' | ||
|
||
const asterisk = '*' | ||
const dot = '.' | ||
const emptyString = '' | ||
const atSymbol = '@' | ||
const caretTrap = '[]' | ||
const space = ' ' | ||
const g = 'g' | ||
const anyNonWhitespaceRegExp = /[^\s]/ | ||
const anyNonDotOrWhitespaceRegExp = /[^.\s]/ | ||
const allWhitespaceRegExp = /\s/g | ||
|
||
function emailMask(rawValue, config) { | ||
rawValue = rawValue.replace(allWhitespaceRegExp, emptyString) | ||
|
||
const {placeholderChar, currentCaretPosition} = config | ||
const indexOfFirstAtSymbol = rawValue.indexOf(atSymbol) | ||
const indexOfLastDot = rawValue.lastIndexOf(dot) | ||
const indexOfTopLevelDomainDot = (indexOfLastDot < indexOfFirstAtSymbol) ? -1 : indexOfLastDot | ||
|
||
let localPartToDomainConnector = getConnector(rawValue, indexOfFirstAtSymbol + 1, atSymbol) | ||
let domainNameToTopLevelDomainConnector = getConnector(rawValue, indexOfTopLevelDomainDot - 1, dot) | ||
|
||
let localPart = getLocalPart(rawValue, indexOfFirstAtSymbol, placeholderChar) | ||
let domainName = getDomainName(rawValue, indexOfFirstAtSymbol, indexOfTopLevelDomainDot, placeholderChar) | ||
let topLevelDomain = getTopLevelDomain(rawValue, indexOfTopLevelDomainDot, placeholderChar, currentCaretPosition) | ||
|
||
localPart = convertToMask(localPart) | ||
domainName = convertToMask(domainName) | ||
topLevelDomain = convertToMask(topLevelDomain, true) | ||
|
||
const mask = localPart | ||
.concat(localPartToDomainConnector) | ||
.concat(domainName) | ||
.concat(domainNameToTopLevelDomainConnector) | ||
.concat(topLevelDomain) | ||
|
||
return mask | ||
} | ||
|
||
function getConnector(rawValue, indexOfConnection, connectionSymbol) { | ||
const connector = [] | ||
|
||
if (rawValue[indexOfConnection] === connectionSymbol) { | ||
connector.push(connectionSymbol) | ||
} else { | ||
connector.push(caretTrap, connectionSymbol) | ||
} | ||
|
||
connector.push(caretTrap) | ||
|
||
return connector | ||
} | ||
|
||
function getLocalPart(rawValue, indexOfFirstAtSymbol) { | ||
if (indexOfFirstAtSymbol === -1) { | ||
return rawValue | ||
} else { | ||
return rawValue.slice(0, indexOfFirstAtSymbol) | ||
} | ||
} | ||
|
||
function getDomainName(rawValue, indexOfFirstAtSymbol, indexOfTopLevelDomainDot, placeholderChar) { | ||
let domainName = emptyString | ||
|
||
if (indexOfFirstAtSymbol !== -1) { | ||
if (indexOfTopLevelDomainDot === -1) { | ||
domainName = rawValue.slice(indexOfFirstAtSymbol + 1, rawValue.length) | ||
} else { | ||
domainName = rawValue.slice(indexOfFirstAtSymbol + 1, indexOfTopLevelDomainDot) | ||
} | ||
} | ||
|
||
domainName = domainName.replace(new RegExp(`[\\s${placeholderChar}]`, g), emptyString) | ||
|
||
if (domainName === atSymbol) { | ||
return asterisk | ||
} else if (domainName.length < 1) { | ||
return space | ||
} else if (domainName[domainName.length - 1] === dot) { | ||
return domainName.slice(0, domainName.length - 1) | ||
} else { | ||
return domainName | ||
} | ||
} | ||
|
||
function getTopLevelDomain(rawValue, indexOfTopLevelDomainDot, placeholderChar, currentCaretPosition) { | ||
let topLevelDomain = emptyString | ||
|
||
if (indexOfTopLevelDomainDot !== -1) { | ||
topLevelDomain = rawValue.slice(indexOfTopLevelDomainDot + 1, rawValue.length) | ||
} | ||
|
||
topLevelDomain = topLevelDomain.replace(new RegExp(`[\\s${placeholderChar}.]`, g), emptyString) | ||
|
||
if (topLevelDomain.length === 0) { | ||
return (rawValue[indexOfTopLevelDomainDot - 1] === dot && currentCaretPosition !== rawValue.length) ? | ||
asterisk : | ||
emptyString | ||
} else { | ||
return topLevelDomain | ||
} | ||
} | ||
|
||
function convertToMask(str, noDots) { | ||
return str | ||
.split(emptyString) | ||
.map((char) => char === space ? char : (noDots) ? anyNonDotOrWhitespaceRegExp : anyNonWhitespaceRegExp) | ||
} | ||
|
||
export default {mask: emailMask, pipe: emailPipe} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
const atSymbol = '@' | ||
const allAtSymbolsRegExp = /@/g | ||
const emptyString = '' | ||
const atDot = '@.' | ||
const dot = '.' | ||
const dotDot = '..' | ||
const emptyArray = [] | ||
const allDotsRegExp = /\./g | ||
|
||
export default function emailPipe(conformedValue, config) { | ||
const {currentCaretPosition, rawValue, previousConformedValue, placeholderChar} = config | ||
|
||
let value = conformedValue | ||
|
||
value = removeAllAtSymbolsButFirst(value) | ||
|
||
const indexOfAtDot = value.indexOf(atDot) | ||
|
||
const emptyEmail = rawValue.match(new RegExp(`[^@\\s.${placeholderChar}]`)) === null | ||
|
||
if (emptyEmail) { | ||
return emptyString | ||
} | ||
|
||
if ( | ||
value.indexOf(dotDot) !== -1 || | ||
indexOfAtDot !== -1 && currentCaretPosition !== (indexOfAtDot + 1) || | ||
rawValue.indexOf(atSymbol) === -1 && previousConformedValue !== emptyString && rawValue.indexOf(dot) !== -1 | ||
) { | ||
return false | ||
} | ||
|
||
const indexOfAtSymbol = value.indexOf(atSymbol) | ||
const domainPart = value.slice(indexOfAtSymbol + 1, value.length) | ||
|
||
if ( | ||
(domainPart.match(allDotsRegExp) || emptyArray).length > 1 && | ||
value.substr(-1) === dot && | ||
currentCaretPosition !== rawValue.length | ||
) { | ||
value = value.slice(0, value.length - 1) | ||
} | ||
|
||
return value | ||
} | ||
|
||
function removeAllAtSymbolsButFirst(str) { | ||
let atSymbolCount = 0 | ||
|
||
return str.replace(allAtSymbolsRegExp, () => { | ||
atSymbolCount++ | ||
|
||
return (atSymbolCount === 1) ? atSymbol : emptyString | ||
}) | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
import createTextMaskInputElement from '../../core/src/createTextMaskInputElement.js' | ||
|
||
const emailMask = (isVerify()) ? | ||
require('../dist/emailMask.js').default : | ||
require('../src/emailMask.js').default | ||
|
||
describe('emailMask', () => { | ||
let inputElement | ||
let textMaskInputElement | ||
|
||
beforeEach(() => { | ||
inputElement = document.createElement('input') | ||
textMaskInputElement = createTextMaskInputElement({inputElement, mask: emailMask}) | ||
}) | ||
|
||
it('masks initial input as follows `a@ .`', () => { | ||
input('a', 1) | ||
expectResults('a@ .', 1) | ||
}) | ||
|
||
it('allows a dot at the end of the local part', () => { | ||
input('a', 1) | ||
expectResults('a@ .', 1) | ||
|
||
input('a.@ .', 2) | ||
expectResults('a.@ .', 2) | ||
}) | ||
|
||
it('moves the caret to after the @ symbol when user enters an @ symbol where the current @ symbol is', () => { | ||
input('a', 1) | ||
expectResults('a@ .', 1) | ||
|
||
input('a@@ .', 2) | ||
expectResults('a@_.', 2) | ||
}) | ||
|
||
it('moves the caret to after the TLD dot when user enters a dot where the current TLD dot is', () => { | ||
input('[email protected]', 7) | ||
expectResults('[email protected]', 7) | ||
|
||
input('[email protected]', 4) | ||
expectResults('[email protected]', 4) | ||
}) | ||
|
||
it('limits the number of @ symbols in input to 1', () => { | ||
input('[email protected]', 7) | ||
expectResults('[email protected]', 7) | ||
input('@[email protected]', 1) | ||
expectResults('@aa.com', 1) | ||
|
||
input('[email protected]', 7) | ||
expectResults('[email protected]', 7) | ||
input('a@[email protected]', 4) | ||
expectResults('[email protected]', 3) | ||
|
||
input('[email protected]', 7) | ||
expectResults('[email protected]', 7) | ||
input('[email protected]@m', 7) | ||
expectResults('[email protected]', 6) | ||
}) | ||
|
||
it('does not add a placeholder in the end when user types a dot after the TLD dot when there is no TLD', () => { | ||
input('a@a.', 4) | ||
expectResults('a@a.', 4) | ||
|
||
input('a@a..', 5) | ||
expectResults('a@a.', 4) | ||
}) | ||
|
||
it('removes the dot in the end if the domain part already contains a dot', () => { | ||
input('a@acom.', 7) | ||
expectResults('a@acom.', 7) | ||
|
||
input('[email protected].', 4) | ||
expectResults('[email protected]', 4) | ||
}) | ||
|
||
it('prevents two consecutive dots', () => { | ||
input('[email protected]', 9) | ||
expectResults('[email protected]', 9) | ||
|
||
input('[email protected]', 5) | ||
expectResults('[email protected]', 4) | ||
}) | ||
|
||
it('just moves the caret over when user enters a dot before the TLD dot', () => { | ||
input('[email protected]', 7) | ||
expectResults('[email protected]', 7) | ||
|
||
input('[email protected]', 4) | ||
expectResults('[email protected]', 4) | ||
}) | ||
|
||
it('works as expected', () => { | ||
input('a', 1) | ||
expectResults('a@ .', 1) | ||
|
||
input('@ .', 0) | ||
expectResults('', 0) | ||
|
||
input('a', 1) | ||
expectResults('a@ .', 1) | ||
|
||
input('a@@ .', 2) | ||
expectResults('a@_.', 2) | ||
|
||
input('a@f_.', 3) | ||
expectResults('a@f.', 3) | ||
|
||
input('af.', 1) | ||
expectResults('a@f.', 1) | ||
|
||
input('a.@f.', 2) | ||
expectResults('a.@f.', 2) | ||
|
||
input('m', 1) | ||
expectResults('m@ .', 1) | ||
|
||
input('m@k .', 3) | ||
expectResults('m@k.', 3) | ||
|
||
input('[email protected].', 3) | ||
expectResults('m@k.', 2) | ||
|
||
input('m@k', 3) | ||
expectResults('m@k.', 3) | ||
|
||
input('m@k..', 5) | ||
expectResults('m@k.', 4) | ||
|
||
input('[email protected]', 5) | ||
expectResults('[email protected]', 5) | ||
|
||
input('m@ks', 3) | ||
expectResults('m@ks.', 3) | ||
|
||
input('[email protected]', 6) | ||
expectResults('[email protected]', 6) | ||
|
||
input('[email protected]', 2) | ||
expectResults('[email protected]', 2) | ||
|
||
input('[email protected]', 3) | ||
expectResults('[email protected]', 3) | ||
}) | ||
|
||
function input(rawValue, currentCaretPosition) { | ||
inputElement.focus() | ||
inputElement.value = rawValue | ||
inputElement.selectionStart = currentCaretPosition | ||
textMaskInputElement.update() | ||
} | ||
|
||
function expectResults(conformedValue, adjustedCaretPosition) { | ||
expect(inputElement.value).to.equal(conformedValue) | ||
expect(inputElement.selectionStart).to.equal(adjustedCaretPosition) | ||
} | ||
}) |
Oops, something went wrong.