libphonenumber-js
Version:
A simpler (and smaller) rewrite of Google Android's libphonenumber library in javascript
234 lines (188 loc) • 6.42 kB
JavaScript
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
var PatternParser = /*#__PURE__*/function () {
function PatternParser() {
_classCallCheck(this, PatternParser);
}
_createClass(PatternParser, [{
key: "parse",
value: function parse(pattern) {
this.context = [{
or: true,
instructions: []
}];
this.parsePattern(pattern);
if (this.context.length !== 1) {
throw new Error('Non-finalized contexts left when pattern parse ended');
}
var _this$context$ = this.context[0],
branches = _this$context$.branches,
instructions = _this$context$.instructions;
if (branches) {
return {
op: '|',
args: branches.concat([expandSingleElementArray(instructions)])
};
}
/* istanbul ignore if */
if (instructions.length === 0) {
throw new Error('Pattern is required');
}
if (instructions.length === 1) {
return instructions[0];
}
return instructions;
}
}, {
key: "startContext",
value: function startContext(context) {
this.context.push(context);
}
}, {
key: "endContext",
value: function endContext() {
this.context.pop();
}
}, {
key: "getContext",
value: function getContext() {
return this.context[this.context.length - 1];
}
}, {
key: "parsePattern",
value: function parsePattern(pattern) {
if (!pattern) {
throw new Error('Pattern is required');
}
var match = pattern.match(OPERATOR);
if (!match) {
if (ILLEGAL_CHARACTER_REGEXP.test(pattern)) {
throw new Error("Illegal characters found in a pattern: ".concat(pattern));
}
this.getContext().instructions = this.getContext().instructions.concat(pattern.split(''));
return;
}
var operator = match[1];
var before = pattern.slice(0, match.index);
var rightPart = pattern.slice(match.index + operator.length);
switch (operator) {
case '(?:':
if (before) {
this.parsePattern(before);
}
this.startContext({
or: true,
instructions: [],
branches: []
});
break;
case ')':
if (!this.getContext().or) {
throw new Error('")" operator must be preceded by "(?:" operator');
}
if (before) {
this.parsePattern(before);
}
if (this.getContext().instructions.length === 0) {
throw new Error('No instructions found after "|" operator in an "or" group');
}
var _this$getContext = this.getContext(),
branches = _this$getContext.branches;
branches.push(expandSingleElementArray(this.getContext().instructions));
this.endContext();
this.getContext().instructions.push({
op: '|',
args: branches
});
break;
case '|':
if (!this.getContext().or) {
throw new Error('"|" operator can only be used inside "or" groups');
}
if (before) {
this.parsePattern(before);
} // The top-level is an implicit "or" group, if required.
if (!this.getContext().branches) {
// `branches` are not defined only for the root implicit "or" operator.
/* istanbul ignore else */
if (this.context.length === 1) {
this.getContext().branches = [];
} else {
throw new Error('"branches" not found in an "or" group context');
}
}
this.getContext().branches.push(expandSingleElementArray(this.getContext().instructions));
this.getContext().instructions = [];
break;
case '[':
if (before) {
this.parsePattern(before);
}
this.startContext({
oneOfSet: true
});
break;
case ']':
if (!this.getContext().oneOfSet) {
throw new Error('"]" operator must be preceded by "[" operator');
}
this.endContext();
this.getContext().instructions.push({
op: '[]',
args: parseOneOfSet(before)
});
break;
/* istanbul ignore next */
default:
throw new Error("Unknown operator: ".concat(operator));
}
if (rightPart) {
this.parsePattern(rightPart);
}
}
}]);
return PatternParser;
}();
export { PatternParser as default };
function parseOneOfSet(pattern) {
var values = [];
var i = 0;
while (i < pattern.length) {
if (pattern[i] === '-') {
if (i === 0 || i === pattern.length - 1) {
throw new Error("Couldn't parse a one-of set pattern: ".concat(pattern));
}
var prevValue = pattern[i - 1].charCodeAt(0) + 1;
var nextValue = pattern[i + 1].charCodeAt(0) - 1;
var value = prevValue;
while (value <= nextValue) {
values.push(String.fromCharCode(value));
value++;
}
} else {
values.push(pattern[i]);
}
i++;
}
return values;
}
var ILLEGAL_CHARACTER_REGEXP = /[\(\)\[\]\?\:\|]/;
var OPERATOR = new RegExp( // any of:
'(' + // or operator
'\\|' + // or
'|' + // or group start
'\\(\\?\\:' + // or
'|' + // or group end
'\\)' + // or
'|' + // one-of set start
'\\[' + // or
'|' + // one-of set end
'\\]' + ')');
function expandSingleElementArray(array) {
if (array.length === 1) {
return array[0];
}
return array;
}
//# sourceMappingURL=AsYouTypeFormatter.PatternParser.js.map