|
|
@@ -319,6 +319,180 @@ function getTests(pos, ndxIntlzr, tstPs) {
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
+ function handleGroup() {
|
|
|
+ match = handleMatch(maskToken.matches[maskToken.matches.indexOf(match) + 1], loopNdx, quantifierRecurse);
|
|
|
+ if (match) return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ function handleOptional() {
|
|
|
+ var optionalToken = match, mtchsNdx = matches.length;
|
|
|
+ match = resolveTestFromToken(match, ndxInitializer, loopNdx, quantifierRecurse);
|
|
|
+ if (matches.length > 0) { //check on matches.length instead of match to handle quantifier in a recursive call
|
|
|
+ //mark optionality in matches
|
|
|
+ matches.forEach(function (mtch, ndx) {
|
|
|
+ if (ndx >= mtchsNdx) {
|
|
|
+ mtch.match.optionality = mtch.match.optionality ? mtch.match.optionality + 1 : 1;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ latestMatch = matches[matches.length - 1].match;
|
|
|
+
|
|
|
+ if (quantifierRecurse === undefined && isFirstMatch(latestMatch, optionalToken)) { //prevent loop see #698
|
|
|
+ insertStop = true; //insert a stop
|
|
|
+ testPos = pos; //match the position after the group
|
|
|
+ } else {
|
|
|
+ return match; //make the loop continue when it is deliberately by a quantifier
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ function handleAlternator() {
|
|
|
+ var alternateToken = match,
|
|
|
+ malternateMatches = [],
|
|
|
+ maltMatches,
|
|
|
+ currentMatches = matches.slice(),
|
|
|
+ loopNdxCnt = loopNdx.length,
|
|
|
+ unMatchedAlternation = false;
|
|
|
+ var altIndex = ndxInitializer.length > 0 ? ndxInitializer.shift() : -1;
|
|
|
+ if (altIndex === -1 || typeof altIndex === "string") {
|
|
|
+ var currentPos = testPos,
|
|
|
+ ndxInitializerClone = ndxInitializer.slice(),
|
|
|
+ altIndexArr = [],
|
|
|
+ amndx;
|
|
|
+ if (typeof altIndex == "string") {
|
|
|
+ altIndexArr = altIndex.split(",");
|
|
|
+ } else {
|
|
|
+ for (amndx = 0; amndx < alternateToken.matches.length; amndx++) {
|
|
|
+ altIndexArr.push(amndx.toString());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (maskset.excludes[pos] !== undefined) {
|
|
|
+ var altIndexArrClone = altIndexArr.slice();
|
|
|
+ for (var i = 0, exl = maskset.excludes[pos].length; i < exl; i++) {
|
|
|
+ var excludeSet = maskset.excludes[pos][i].toString().split(":");
|
|
|
+ if (loopNdx.length == excludeSet[1]) {
|
|
|
+ altIndexArr.splice(altIndexArr.indexOf(excludeSet[0]), 1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (altIndexArr.length === 0) { //fully alternated => reset
|
|
|
+ delete maskset.excludes[pos];
|
|
|
+ altIndexArr = altIndexArrClone;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (opts.keepStatic === true || (isFinite(parseInt(opts.keepStatic)) && currentPos >= opts.keepStatic)) altIndexArr = altIndexArr.slice(0, 1);
|
|
|
+ for (var ndx = 0; ndx < altIndexArr.length; ndx++) {
|
|
|
+ amndx = parseInt(altIndexArr[ndx]);
|
|
|
+ matches = [];
|
|
|
+ //set the correct ndxInitializer
|
|
|
+ ndxInitializer = typeof altIndex === "string" ? resolveNdxInitializer(testPos, amndx, loopNdxCnt) || ndxInitializerClone.slice() : ndxInitializerClone.slice();
|
|
|
+ var tokenMatch = alternateToken.matches[amndx];
|
|
|
+ if (tokenMatch && handleMatch(tokenMatch, [amndx].concat(loopNdx), quantifierRecurse)) {
|
|
|
+ match = true;
|
|
|
+ } else {
|
|
|
+ if (ndx === 0) {
|
|
|
+ unMatchedAlternation = true;
|
|
|
+ }
|
|
|
+ if (tokenMatch && tokenMatch.matches && tokenMatch.matches.length > alternateToken.matches[0].matches.length) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ maltMatches = matches.slice();
|
|
|
+ testPos = currentPos;
|
|
|
+ matches = [];
|
|
|
+
|
|
|
+ //fuzzy merge matches
|
|
|
+ for (var ndx1 = 0; ndx1 < maltMatches.length; ndx1++) {
|
|
|
+ var altMatch = maltMatches[ndx1],
|
|
|
+ dropMatch = false;
|
|
|
+ altMatch.match.jit = altMatch.match.jit || unMatchedAlternation; //mark jit when there are unmatched alternations ex: mask: "(a|aa)"
|
|
|
+ altMatch.alternation = altMatch.alternation || loopNdxCnt;
|
|
|
+ setMergeLocators(altMatch);
|
|
|
+ for (var ndx2 = 0; ndx2 < malternateMatches.length; ndx2++) {
|
|
|
+ var altMatch2 = malternateMatches[ndx2];
|
|
|
+ if (typeof altIndex !== "string" || (altMatch.alternation !== undefined && altIndexArr.includes(altMatch.locator[altMatch.alternation].toString()))) {
|
|
|
+ if (altMatch.match.nativeDef === altMatch2.match.nativeDef) {
|
|
|
+ dropMatch = true;
|
|
|
+ setMergeLocators(altMatch2, altMatch);
|
|
|
+ break;
|
|
|
+ } else if (isSubsetOf(altMatch, altMatch2, opts)) {
|
|
|
+ if (setMergeLocators(altMatch, altMatch2)) {
|
|
|
+ dropMatch = true;
|
|
|
+ malternateMatches.splice(malternateMatches.indexOf(altMatch2), 0, altMatch);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ } else if (isSubsetOf(altMatch2, altMatch, opts)) {
|
|
|
+ setMergeLocators(altMatch2, altMatch);
|
|
|
+ break;
|
|
|
+ } else if (staticCanMatchDefinition(altMatch, altMatch2)) {
|
|
|
+ if (!isSameLevel(altMatch, altMatch2) && el.inputmask.userOptions.keepStatic === undefined) {
|
|
|
+ opts.keepStatic = true;
|
|
|
+ } else if (setMergeLocators(altMatch, altMatch2)) {
|
|
|
+ //insert match above general match
|
|
|
+ dropMatch = true;
|
|
|
+ malternateMatches.splice(malternateMatches.indexOf(altMatch2), 0, altMatch);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!dropMatch) {
|
|
|
+ malternateMatches.push(altMatch);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ matches = currentMatches.concat(malternateMatches);
|
|
|
+ testPos = pos;
|
|
|
+ insertStop = matches.length > 0; //insert a stopelemnt when there is an alternate - needed for non-greedy option
|
|
|
+ match = malternateMatches.length > 0; //set correct match state
|
|
|
+
|
|
|
+ //cloneback
|
|
|
+ ndxInitializer = ndxInitializerClone.slice();
|
|
|
+ } else {
|
|
|
+ match = handleMatch(alternateToken.matches[altIndex] || maskToken.matches[altIndex], [altIndex].concat(loopNdx), quantifierRecurse);
|
|
|
+ }
|
|
|
+ if (match) return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ function handleQuantifier() {
|
|
|
+ var qt = match, breakloop = false;
|
|
|
+ for (var qndx = (ndxInitializer.length > 0) ? ndxInitializer.shift() : 0; (qndx < (isNaN(qt.quantifier.max) ? qndx + 1 : qt.quantifier.max)) && testPos <= pos; qndx++) {
|
|
|
+ var tokenGroup = maskToken.matches[maskToken.matches.indexOf(qt) - 1];
|
|
|
+ match = handleMatch(tokenGroup, [qndx].concat(loopNdx), tokenGroup); //set the tokenGroup as quantifierRecurse marker
|
|
|
+ if (match) {
|
|
|
+ matches.forEach(function (mtch, ndx) {
|
|
|
+ if (IsMatchOf(tokenGroup, mtch.match))
|
|
|
+ latestMatch = mtch.match;
|
|
|
+ else latestMatch = matches[matches.length - 1].match;
|
|
|
+
|
|
|
+ //mark optionality
|
|
|
+ //TODO FIX RECURSIVE QUANTIFIERS
|
|
|
+ latestMatch.optionalQuantifier = qndx >= qt.quantifier.min;
|
|
|
+ // console.log(pos + " " + qt.quantifier.min + " " + latestMatch.optionalQuantifier);
|
|
|
+ //qndx + 1 as the index starts from 0
|
|
|
+ latestMatch.jit = (qndx + 1) * (tokenGroup.matches.indexOf(latestMatch) + 1) > qt.quantifier.jit;
|
|
|
+ if (latestMatch.optionalQuantifier && isFirstMatch(latestMatch, tokenGroup)) {
|
|
|
+ insertStop = true;
|
|
|
+ testPos = pos; //match the position after the group
|
|
|
+ if (opts.greedy && maskset.validPositions[pos - 1] == undefined && qndx > qt.quantifier.min && ["*", "+"].indexOf(qt.quantifier.max) != -1) {
|
|
|
+ matches.pop();
|
|
|
+ cacheDependency = undefined;
|
|
|
+ }
|
|
|
+ breakloop = true; //stop quantifierloop && search for next possible match
|
|
|
+ match = false; //mark match to false to make sure the loop in optionals continues
|
|
|
+ }
|
|
|
+ if (!breakloop && latestMatch.jit /*&& !latestMatch.optionalQuantifier*/) {
|
|
|
+ //always set jitOffset, isvalid checks when to apply
|
|
|
+ maskset.jitOffset[pos] = tokenGroup.matches.length - tokenGroup.matches.indexOf(latestMatch);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ if (breakloop) break; // search for next possible match
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
if (testPos > (pos + opts._maxTestPos)) {
|
|
|
throw "Inputmask: There is probably an error in your mask definition or in the code. Create an issue on github with an example of the mask you are using. " + maskset.mask;
|
|
|
}
|
|
|
@@ -339,170 +513,13 @@ function getTests(pos, ndxIntlzr, tstPs) {
|
|
|
}
|
|
|
} else if (match.matches !== undefined) {
|
|
|
if (match.isGroup && quantifierRecurse !== match) { //when a group pass along to the quantifier
|
|
|
- match = handleMatch(maskToken.matches[maskToken.matches.indexOf(match) + 1], loopNdx, quantifierRecurse);
|
|
|
- if (match) return true;
|
|
|
+ return handleGroup();
|
|
|
} else if (match.isOptional) {
|
|
|
- var optionalToken = match, mtchsNdx = matches.length;
|
|
|
- match = resolveTestFromToken(match, ndxInitializer, loopNdx, quantifierRecurse);
|
|
|
- if (match) {
|
|
|
- //mark optionality in matches
|
|
|
- matches.forEach(function (mtch, ndx) {
|
|
|
- if (ndx >= mtchsNdx) {
|
|
|
- mtch.match.optionality = mtch.match.optionality ? mtch.match.optionality + 1 : 1;
|
|
|
- }
|
|
|
- });
|
|
|
- latestMatch = matches[matches.length - 1].match;
|
|
|
-
|
|
|
- if (quantifierRecurse === undefined && isFirstMatch(latestMatch, optionalToken)) { //prevent loop see #698
|
|
|
- insertStop = true; //insert a stop
|
|
|
- testPos = pos; //match the position after the group
|
|
|
- } else {
|
|
|
- return true;
|
|
|
- }
|
|
|
- }
|
|
|
+ return handleOptional();
|
|
|
} else if (match.isAlternator) {
|
|
|
- var alternateToken = match,
|
|
|
- malternateMatches = [],
|
|
|
- maltMatches,
|
|
|
- currentMatches = matches.slice(),
|
|
|
- loopNdxCnt = loopNdx.length,
|
|
|
- unMatchedAlternation = false;
|
|
|
- var altIndex = ndxInitializer.length > 0 ? ndxInitializer.shift() : -1;
|
|
|
- if (altIndex === -1 || typeof altIndex === "string") {
|
|
|
- var currentPos = testPos,
|
|
|
- ndxInitializerClone = ndxInitializer.slice(),
|
|
|
- altIndexArr = [],
|
|
|
- amndx;
|
|
|
- if (typeof altIndex == "string") {
|
|
|
- altIndexArr = altIndex.split(",");
|
|
|
- } else {
|
|
|
- for (amndx = 0; amndx < alternateToken.matches.length; amndx++) {
|
|
|
- altIndexArr.push(amndx.toString());
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (maskset.excludes[pos] !== undefined) {
|
|
|
- var altIndexArrClone = altIndexArr.slice();
|
|
|
- for (var i = 0, exl = maskset.excludes[pos].length; i < exl; i++) {
|
|
|
- var excludeSet = maskset.excludes[pos][i].toString().split(":");
|
|
|
- if (loopNdx.length == excludeSet[1]) {
|
|
|
- altIndexArr.splice(altIndexArr.indexOf(excludeSet[0]), 1);
|
|
|
- }
|
|
|
- }
|
|
|
- if (altIndexArr.length === 0) { //fully alternated => reset
|
|
|
- delete maskset.excludes[pos];
|
|
|
- altIndexArr = altIndexArrClone;
|
|
|
- }
|
|
|
- }
|
|
|
- if (opts.keepStatic === true || (isFinite(parseInt(opts.keepStatic)) && currentPos >= opts.keepStatic)) altIndexArr = altIndexArr.slice(0, 1);
|
|
|
- for (var ndx = 0; ndx < altIndexArr.length; ndx++) {
|
|
|
- amndx = parseInt(altIndexArr[ndx]);
|
|
|
- matches = [];
|
|
|
- //set the correct ndxInitializer
|
|
|
- ndxInitializer = typeof altIndex === "string" ? resolveNdxInitializer(testPos, amndx, loopNdxCnt) || ndxInitializerClone.slice() : ndxInitializerClone.slice();
|
|
|
- var tokenMatch = alternateToken.matches[amndx];
|
|
|
- if (tokenMatch && handleMatch(tokenMatch, [amndx].concat(loopNdx), quantifierRecurse)) {
|
|
|
- match = true;
|
|
|
- } else {
|
|
|
- if (ndx === 0) {
|
|
|
- unMatchedAlternation = true;
|
|
|
- }
|
|
|
- if (tokenMatch && tokenMatch.matches && tokenMatch.matches.length > alternateToken.matches[0].matches.length) {
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- maltMatches = matches.slice();
|
|
|
- testPos = currentPos;
|
|
|
- matches = [];
|
|
|
-
|
|
|
- //fuzzy merge matches
|
|
|
- for (var ndx1 = 0; ndx1 < maltMatches.length; ndx1++) {
|
|
|
- var altMatch = maltMatches[ndx1],
|
|
|
- dropMatch = false;
|
|
|
- altMatch.match.jit = altMatch.match.jit || unMatchedAlternation; //mark jit when there are unmatched alternations ex: mask: "(a|aa)"
|
|
|
- altMatch.alternation = altMatch.alternation || loopNdxCnt;
|
|
|
- setMergeLocators(altMatch);
|
|
|
- for (var ndx2 = 0; ndx2 < malternateMatches.length; ndx2++) {
|
|
|
- var altMatch2 = malternateMatches[ndx2];
|
|
|
- if (typeof altIndex !== "string" || (altMatch.alternation !== undefined && altIndexArr.includes(altMatch.locator[altMatch.alternation].toString()))) {
|
|
|
- if (altMatch.match.nativeDef === altMatch2.match.nativeDef) {
|
|
|
- dropMatch = true;
|
|
|
- setMergeLocators(altMatch2, altMatch);
|
|
|
- break;
|
|
|
- } else if (isSubsetOf(altMatch, altMatch2, opts)) {
|
|
|
- if (setMergeLocators(altMatch, altMatch2)) {
|
|
|
- dropMatch = true;
|
|
|
- malternateMatches.splice(malternateMatches.indexOf(altMatch2), 0, altMatch);
|
|
|
- }
|
|
|
- break;
|
|
|
- } else if (isSubsetOf(altMatch2, altMatch, opts)) {
|
|
|
- setMergeLocators(altMatch2, altMatch);
|
|
|
- break;
|
|
|
- } else if (staticCanMatchDefinition(altMatch, altMatch2)) {
|
|
|
- if (!isSameLevel(altMatch, altMatch2) && el.inputmask.userOptions.keepStatic === undefined) {
|
|
|
- opts.keepStatic = true;
|
|
|
- } else if (setMergeLocators(altMatch, altMatch2)) {
|
|
|
- //insert match above general match
|
|
|
- dropMatch = true;
|
|
|
- malternateMatches.splice(malternateMatches.indexOf(altMatch2), 0, altMatch);
|
|
|
- }
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- if (!dropMatch) {
|
|
|
- malternateMatches.push(altMatch);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- matches = currentMatches.concat(malternateMatches);
|
|
|
- testPos = pos;
|
|
|
- insertStop = matches.length > 0; //insert a stopelemnt when there is an alternate - needed for non-greedy option
|
|
|
- match = malternateMatches.length > 0; //set correct match state
|
|
|
-
|
|
|
- //cloneback
|
|
|
- ndxInitializer = ndxInitializerClone.slice();
|
|
|
- } else {
|
|
|
- match = handleMatch(alternateToken.matches[altIndex] || maskToken.matches[altIndex], [altIndex].concat(loopNdx), quantifierRecurse);
|
|
|
- }
|
|
|
- if (match) return true;
|
|
|
+ return handleAlternator();
|
|
|
} else if (match.isQuantifier && quantifierRecurse !== maskToken.matches[maskToken.matches.indexOf(match) - 1]) {
|
|
|
- var qt = match, breakloop = false;
|
|
|
- for (var qndx = (ndxInitializer.length > 0) ? ndxInitializer.shift() : 0; (qndx < (isNaN(qt.quantifier.max) ? qndx + 1 : qt.quantifier.max)) && testPos <= pos; qndx++) {
|
|
|
- var tokenGroup = maskToken.matches[maskToken.matches.indexOf(qt) - 1];
|
|
|
- match = handleMatch(tokenGroup, [qndx].concat(loopNdx), tokenGroup); //set the tokenGroup as quantifierRecurse marker
|
|
|
- if (match) {
|
|
|
- matches.forEach(function (mtch, ndx) {
|
|
|
- if (IsMatchOf(tokenGroup, mtch.match))
|
|
|
- latestMatch = mtch.match;
|
|
|
- else latestMatch = matches[matches.length - 1].match;
|
|
|
-
|
|
|
- //mark optionality
|
|
|
- //TODO FIX RECURSIVE QUANTIFIERS
|
|
|
- latestMatch.optionalQuantifier = qndx >= qt.quantifier.min;
|
|
|
- // console.log(pos + " " + qt.quantifier.min + " " + latestMatch.optionalQuantifier);
|
|
|
- //qndx + 1 as the index starts from 0
|
|
|
- latestMatch.jit = (qndx + 1) * (tokenGroup.matches.indexOf(latestMatch) + 1) > qt.quantifier.jit;
|
|
|
- if (latestMatch.optionalQuantifier && isFirstMatch(latestMatch, tokenGroup)) {
|
|
|
- insertStop = true;
|
|
|
- testPos = pos; //match the position after the group
|
|
|
- if (opts.greedy && maskset.validPositions[pos - 1] == undefined && qndx > qt.quantifier.min && ["*", "+"].indexOf(qt.quantifier.max) != -1) {
|
|
|
- matches.pop();
|
|
|
- cacheDependency = undefined;
|
|
|
- }
|
|
|
- breakloop = true; //stop quantifierloop && search for next possible match
|
|
|
- }
|
|
|
- if (!breakloop && latestMatch.jit /*&& !latestMatch.optionalQuantifier*/) {
|
|
|
- //always set jitOffset, isvalid checks when to apply
|
|
|
- maskset.jitOffset[pos] = tokenGroup.matches.length - tokenGroup.matches.indexOf(latestMatch);
|
|
|
- }
|
|
|
- });
|
|
|
- if (breakloop) break;
|
|
|
- return true;
|
|
|
- }
|
|
|
- }
|
|
|
+ return handleQuantifier();
|
|
|
} else {
|
|
|
match = resolveTestFromToken(match, ndxInitializer, loopNdx, quantifierRecurse);
|
|
|
if (match) return true;
|