feat: Reinitialize frontend with SvelteKit and TypeScript

- Delete old Vite+Svelte frontend
- Initialize new SvelteKit project with TypeScript
- Configure Tailwind CSS v4 + DaisyUI
- Implement JWT authentication with auto-refresh
- Create login page with form validation (Zod)
- Add protected route guards
- Update Docker configuration for single-stage build
- Add E2E tests with Playwright (6/11 passing)
- Fix Svelte 5 reactivity with $state() runes

Known issues:
- 5 E2E tests failing (timing/async issues)
- Token refresh implementation needs debugging
- Validation error display timing
This commit is contained in:
2026-02-17 16:19:59 -05:00
parent 54df6018f5
commit de2d83092e
28274 changed files with 3816354 additions and 90 deletions

View File

@@ -0,0 +1,73 @@
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
function _createForOfIteratorHelperLoose(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (t) return (t = t.call(r)).next.bind(t); if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var o = 0; return function () { return o >= r.length ? { done: !0 } : { done: !1, value: r[o++] }; }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
import isViablePhoneNumber from './isViablePhoneNumber.js';
// https://www.ietf.org/rfc/rfc3966.txt
/**
* @param {string} text - Phone URI (RFC 3966).
* @return {object} `{ ?number, ?ext }`.
*/
export function parseRFC3966(text) {
var number;
var ext;
// Replace "tel:" with "tel=" for parsing convenience.
text = text.replace(/^tel:/, 'tel=');
for (var _iterator = _createForOfIteratorHelperLoose(text.split(';')), _step; !(_step = _iterator()).done;) {
var part = _step.value;
var _part$split = part.split('='),
_part$split2 = _slicedToArray(_part$split, 2),
name = _part$split2[0],
value = _part$split2[1];
switch (name) {
case 'tel':
number = value;
break;
case 'ext':
ext = value;
break;
case 'phone-context':
// Only "country contexts" are supported.
// "Domain contexts" are ignored.
if (value[0] === '+') {
number = value + number;
}
break;
}
}
// If the phone number is not viable, then abort.
if (!isViablePhoneNumber(number)) {
return {};
}
var result = {
number: number
};
if (ext) {
result.ext = ext;
}
return result;
}
/**
* @param {object} - `{ ?number, ?extension }`.
* @return {string} Phone URI (RFC 3966).
*/
export function formatRFC3966(_ref) {
var number = _ref.number,
ext = _ref.ext;
if (!number) {
return '';
}
if (number[0] !== '+') {
throw new Error("\"formatRFC3966()\" expects \"number\" to be in E.164 format.");
}
return "tel:".concat(number).concat(ext ? ';ext=' + ext : '');
}
//# sourceMappingURL=RFC3966.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"RFC3966.js","names":["isViablePhoneNumber","parseRFC3966","text","number","ext","replace","_iterator","_createForOfIteratorHelperLoose","split","_step","done","part","value","_part$split","_part$split2","_slicedToArray","name","result","formatRFC3966","_ref","Error","concat"],"sources":["../../source/helpers/RFC3966.js"],"sourcesContent":["import isViablePhoneNumber from './isViablePhoneNumber.js'\r\n\r\n// https://www.ietf.org/rfc/rfc3966.txt\r\n\r\n/**\r\n * @param {string} text - Phone URI (RFC 3966).\r\n * @return {object} `{ ?number, ?ext }`.\r\n */\r\nexport function parseRFC3966(text) {\r\n\tlet number\r\n\tlet ext\r\n\r\n\t// Replace \"tel:\" with \"tel=\" for parsing convenience.\r\n\ttext = text.replace(/^tel:/, 'tel=')\r\n\r\n\tfor (const part of text.split(';')) {\r\n\t\tconst [name, value] = part.split('=')\r\n\t\tswitch (name) {\r\n\t\t\tcase 'tel':\r\n\t\t\t\tnumber = value\r\n\t\t\t\tbreak\r\n\t\t\tcase 'ext':\r\n\t\t\t\text = value\r\n\t\t\t\tbreak\r\n\t\t\tcase 'phone-context':\r\n\t\t\t\t// Only \"country contexts\" are supported.\r\n\t\t\t\t// \"Domain contexts\" are ignored.\r\n\t\t\t\tif (value[0] === '+') {\r\n\t\t\t\t\tnumber = value + number\r\n\t\t\t\t}\r\n\t\t\t\tbreak\r\n\t\t}\r\n\t}\r\n\r\n\t// If the phone number is not viable, then abort.\r\n\tif (!isViablePhoneNumber(number)) {\r\n\t\treturn {}\r\n\t}\r\n\r\n\tconst result = { number }\r\n\tif (ext) {\r\n\t\tresult.ext = ext\r\n\t}\r\n\treturn result\r\n}\r\n\r\n/**\r\n * @param {object} - `{ ?number, ?extension }`.\r\n * @return {string} Phone URI (RFC 3966).\r\n */\r\nexport function formatRFC3966({ number, ext }) {\r\n\tif (!number) {\r\n\t\treturn ''\r\n\t}\r\n\tif (number[0] !== '+') {\r\n\t\tthrow new Error(`\"formatRFC3966()\" expects \"number\" to be in E.164 format.`)\r\n\t}\r\n\treturn `tel:${number}${ext ? ';ext=' + ext : ''}`\r\n}"],"mappings":";;;;;;;AAAA,OAAOA,mBAAmB,MAAM,0BAA0B;;AAE1D;;AAEA;AACA;AACA;AACA;AACA,OAAO,SAASC,YAAYA,CAACC,IAAI,EAAE;EAClC,IAAIC,MAAM;EACV,IAAIC,GAAG;;EAEP;EACAF,IAAI,GAAGA,IAAI,CAACG,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC;EAEpC,SAAAC,SAAA,GAAAC,+BAAA,CAAmBL,IAAI,CAACM,KAAK,CAAC,GAAG,CAAC,GAAAC,KAAA,IAAAA,KAAA,GAAAH,SAAA,IAAAI,IAAA,GAAE;IAAA,IAAzBC,IAAI,GAAAF,KAAA,CAAAG,KAAA;IACd,IAAAC,WAAA,GAAsBF,IAAI,CAACH,KAAK,CAAC,GAAG,CAAC;MAAAM,YAAA,GAAAC,cAAA,CAAAF,WAAA;MAA9BG,IAAI,GAAAF,YAAA;MAAEF,KAAK,GAAAE,YAAA;IAClB,QAAQE,IAAI;MACX,KAAK,KAAK;QACTb,MAAM,GAAGS,KAAK;QACd;MACD,KAAK,KAAK;QACTR,GAAG,GAAGQ,KAAK;QACX;MACD,KAAK,eAAe;QACnB;QACA;QACA,IAAIA,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE;UACrBT,MAAM,GAAGS,KAAK,GAAGT,MAAM;QACxB;QACA;IACF;EACD;;EAEA;EACA,IAAI,CAACH,mBAAmB,CAACG,MAAM,CAAC,EAAE;IACjC,OAAO,CAAC,CAAC;EACV;EAEA,IAAMc,MAAM,GAAG;IAAEd,MAAM,EAANA;EAAO,CAAC;EACzB,IAAIC,GAAG,EAAE;IACRa,MAAM,CAACb,GAAG,GAAGA,GAAG;EACjB;EACA,OAAOa,MAAM;AACd;;AAEA;AACA;AACA;AACA;AACA,OAAO,SAASC,aAAaA,CAAAC,IAAA,EAAkB;EAAA,IAAfhB,MAAM,GAAAgB,IAAA,CAANhB,MAAM;IAAEC,GAAG,GAAAe,IAAA,CAAHf,GAAG;EAC1C,IAAI,CAACD,MAAM,EAAE;IACZ,OAAO,EAAE;EACV;EACA,IAAIA,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE;IACtB,MAAM,IAAIiB,KAAK,gEAA4D,CAAC;EAC7E;EACA,cAAAC,MAAA,CAAclB,MAAM,EAAAkB,MAAA,CAAGjB,GAAG,GAAG,OAAO,GAAGA,GAAG,GAAG,EAAE;AAChD","ignoreList":[]}

View File

@@ -0,0 +1,43 @@
import { parseRFC3966, formatRFC3966 } from './RFC3966.js';
describe('RFC3966', function () {
it('should format', function () {
expect(function () {
return formatRFC3966({
number: '123'
});
}).to["throw"]('expects "number" to be in E.164 format');
expect(formatRFC3966({})).to.equal('');
expect(formatRFC3966({
number: '+78005553535'
})).to.equal('tel:+78005553535');
expect(formatRFC3966({
number: '+78005553535',
ext: '123'
})).to.equal('tel:+78005553535;ext=123');
});
it('should parse', function () {
expect(parseRFC3966('tel:+78005553535')).to.deep.equal({
number: '+78005553535'
});
expect(parseRFC3966('tel:+78005553535;ext=123')).to.deep.equal({
number: '+78005553535',
ext: '123'
});
// With `phone-context`
expect(parseRFC3966('tel:8005553535;ext=123;phone-context=+7')).to.deep.equal({
number: '+78005553535',
ext: '123'
});
// "Domain contexts" are ignored
expect(parseRFC3966('tel:8005553535;ext=123;phone-context=www.leningrad.spb.ru')).to.deep.equal({
number: '8005553535',
ext: '123'
});
// Not a viable phone number.
expect(parseRFC3966('tel:3')).to.deep.equal({});
});
});
//# sourceMappingURL=RFC3966.test.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"RFC3966.test.js","names":["parseRFC3966","formatRFC3966","describe","it","expect","number","to","equal","ext","deep"],"sources":["../../source/helpers/RFC3966.test.js"],"sourcesContent":["import { parseRFC3966, formatRFC3966 } from './RFC3966.js'\r\n\r\ndescribe('RFC3966', () => {\r\n\tit('should format', () => {\r\n\t\texpect(() => formatRFC3966({ number: '123' })).to.throw('expects \"number\" to be in E.164 format')\r\n\t\texpect(formatRFC3966({})).to.equal('')\r\n\t\texpect(formatRFC3966({ number: '+78005553535' })).to.equal('tel:+78005553535')\r\n\t\texpect(formatRFC3966({ number: '+78005553535', ext: '123' })).to.equal('tel:+78005553535;ext=123')\r\n\t})\r\n\r\n\tit('should parse', () => {\r\n\t\texpect(parseRFC3966('tel:+78005553535')).to.deep.equal({\r\n\t\t\tnumber : '+78005553535'\r\n\t\t})\r\n\r\n\t\texpect(parseRFC3966('tel:+78005553535;ext=123')).to.deep.equal({\r\n\t\t\tnumber : '+78005553535',\r\n\t\t\text : '123'\r\n\t\t})\r\n\r\n\t\t// With `phone-context`\r\n\t\texpect(parseRFC3966('tel:8005553535;ext=123;phone-context=+7')).to.deep.equal({\r\n\t\t\tnumber : '+78005553535',\r\n\t\t\text : '123'\r\n\t\t})\r\n\r\n\t\t// \"Domain contexts\" are ignored\r\n\t\texpect(parseRFC3966('tel:8005553535;ext=123;phone-context=www.leningrad.spb.ru')).to.deep.equal({\r\n\t\t\tnumber : '8005553535',\r\n\t\t\text : '123'\r\n\t\t})\r\n\r\n\t\t// Not a viable phone number.\r\n\t\texpect(parseRFC3966('tel:3')).to.deep.equal({})\r\n\t})\r\n})\r\n"],"mappings":"AAAA,SAASA,YAAY,EAAEC,aAAa,QAAQ,cAAc;AAE1DC,QAAQ,CAAC,SAAS,EAAE,YAAM;EACzBC,EAAE,CAAC,eAAe,EAAE,YAAM;IACzBC,MAAM,CAAC;MAAA,OAAMH,aAAa,CAAC;QAAEI,MAAM,EAAE;MAAM,CAAC,CAAC;IAAA,EAAC,CAACC,EAAE,SAAM,CAAC,wCAAwC,CAAC;IACjGF,MAAM,CAACH,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAACK,EAAE,CAACC,KAAK,CAAC,EAAE,CAAC;IACtCH,MAAM,CAACH,aAAa,CAAC;MAAEI,MAAM,EAAE;IAAe,CAAC,CAAC,CAAC,CAACC,EAAE,CAACC,KAAK,CAAC,kBAAkB,CAAC;IAC9EH,MAAM,CAACH,aAAa,CAAC;MAAEI,MAAM,EAAE,cAAc;MAAEG,GAAG,EAAE;IAAM,CAAC,CAAC,CAAC,CAACF,EAAE,CAACC,KAAK,CAAC,0BAA0B,CAAC;EACnG,CAAC,CAAC;EAEFJ,EAAE,CAAC,cAAc,EAAE,YAAM;IACxBC,MAAM,CAACJ,YAAY,CAAC,kBAAkB,CAAC,CAAC,CAACM,EAAE,CAACG,IAAI,CAACF,KAAK,CAAC;MACtDF,MAAM,EAAG;IACV,CAAC,CAAC;IAEFD,MAAM,CAACJ,YAAY,CAAC,0BAA0B,CAAC,CAAC,CAACM,EAAE,CAACG,IAAI,CAACF,KAAK,CAAC;MAC9DF,MAAM,EAAG,cAAc;MACvBG,GAAG,EAAM;IACV,CAAC,CAAC;;IAEF;IACAJ,MAAM,CAACJ,YAAY,CAAC,yCAAyC,CAAC,CAAC,CAACM,EAAE,CAACG,IAAI,CAACF,KAAK,CAAC;MAC7EF,MAAM,EAAG,cAAc;MACvBG,GAAG,EAAM;IACV,CAAC,CAAC;;IAEF;IACAJ,MAAM,CAACJ,YAAY,CAAC,2DAA2D,CAAC,CAAC,CAACM,EAAE,CAACG,IAAI,CAACF,KAAK,CAAC;MAC/FF,MAAM,EAAG,YAAY;MACrBG,GAAG,EAAM;IACV,CAAC,CAAC;;IAEF;IACAJ,MAAM,CAACJ,YAAY,CAAC,OAAO,CAAC,CAAC,CAACM,EAAE,CAACG,IAAI,CAACF,KAAK,CAAC,CAAC,CAAC,CAAC;EAChD,CAAC,CAAC;AACH,CAAC,CAAC","ignoreList":[]}

View File

@@ -0,0 +1,36 @@
import { VALID_PUNCTUATION } from '../constants.js';
// Removes brackets and replaces dashes with spaces.
//
// E.g. "(999) 111-22-33" -> "999 111 22 33"
//
// For some reason Google's metadata contains `<intlFormat/>`s with brackets and dashes.
// Meanwhile, there's no single opinion about using punctuation in international phone numbers.
//
// For example, Google's `<intlFormat/>` for USA is `+1 213-373-4253`.
// And here's a quote from WikiPedia's "North American Numbering Plan" page:
// https://en.wikipedia.org/wiki/North_American_Numbering_Plan
//
// "The country calling code for all countries participating in the NANP is 1.
// In international format, an NANP number should be listed as +1 301 555 01 00,
// where 301 is an area code (Maryland)."
//
// I personally prefer the international format without any punctuation.
// For example, brackets are remnants of the old age, meaning that the
// phone number part in brackets (so called "area code") can be omitted
// if dialing within the same "area".
// And hyphens were clearly introduced for splitting local numbers into memorizable groups.
// For example, remembering "5553535" is difficult but "555-35-35" is much simpler.
// Imagine a man taking a bus from home to work and seeing an ad with a phone number.
// He has a couple of seconds to memorize that number until it passes by.
// If it were spaces instead of hyphens the man wouldn't necessarily get it,
// but with hyphens instead of spaces the grouping is more explicit.
// I personally think that hyphens introduce visual clutter,
// so I prefer replacing them with spaces in international numbers.
// In the modern age all output is done on displays where spaces are clearly distinguishable
// so hyphens can be safely replaced with spaces without losing any legibility.
//
export default function applyInternationalSeparatorStyle(formattedNumber) {
return formattedNumber.replace(new RegExp("[".concat(VALID_PUNCTUATION, "]+"), 'g'), ' ').trim();
}
//# sourceMappingURL=applyInternationalSeparatorStyle.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"applyInternationalSeparatorStyle.js","names":["VALID_PUNCTUATION","applyInternationalSeparatorStyle","formattedNumber","replace","RegExp","concat","trim"],"sources":["../../source/helpers/applyInternationalSeparatorStyle.js"],"sourcesContent":["import { VALID_PUNCTUATION } from '../constants.js'\r\n\r\n// Removes brackets and replaces dashes with spaces.\r\n//\r\n// E.g. \"(999) 111-22-33\" -> \"999 111 22 33\"\r\n//\r\n// For some reason Google's metadata contains `<intlFormat/>`s with brackets and dashes.\r\n// Meanwhile, there's no single opinion about using punctuation in international phone numbers.\r\n//\r\n// For example, Google's `<intlFormat/>` for USA is `+1 213-373-4253`.\r\n// And here's a quote from WikiPedia's \"North American Numbering Plan\" page:\r\n// https://en.wikipedia.org/wiki/North_American_Numbering_Plan\r\n//\r\n// \"The country calling code for all countries participating in the NANP is 1.\r\n// In international format, an NANP number should be listed as +1 301 555 01 00,\r\n// where 301 is an area code (Maryland).\"\r\n//\r\n// I personally prefer the international format without any punctuation.\r\n// For example, brackets are remnants of the old age, meaning that the\r\n// phone number part in brackets (so called \"area code\") can be omitted\r\n// if dialing within the same \"area\".\r\n// And hyphens were clearly introduced for splitting local numbers into memorizable groups.\r\n// For example, remembering \"5553535\" is difficult but \"555-35-35\" is much simpler.\r\n// Imagine a man taking a bus from home to work and seeing an ad with a phone number.\r\n// He has a couple of seconds to memorize that number until it passes by.\r\n// If it were spaces instead of hyphens the man wouldn't necessarily get it,\r\n// but with hyphens instead of spaces the grouping is more explicit.\r\n// I personally think that hyphens introduce visual clutter,\r\n// so I prefer replacing them with spaces in international numbers.\r\n// In the modern age all output is done on displays where spaces are clearly distinguishable\r\n// so hyphens can be safely replaced with spaces without losing any legibility.\r\n//\r\nexport default function applyInternationalSeparatorStyle(formattedNumber) {\r\n\treturn formattedNumber.replace(new RegExp(`[${VALID_PUNCTUATION}]+`, 'g'), ' ').trim()\r\n}"],"mappings":"AAAA,SAASA,iBAAiB,QAAQ,iBAAiB;;AAEnD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAe,SAASC,gCAAgCA,CAACC,eAAe,EAAE;EACzE,OAAOA,eAAe,CAACC,OAAO,CAAC,IAAIC,MAAM,KAAAC,MAAA,CAAKL,iBAAiB,SAAM,GAAG,CAAC,EAAE,GAAG,CAAC,CAACM,IAAI,CAAC,CAAC;AACvF","ignoreList":[]}

View File

@@ -0,0 +1,8 @@
import applyInternationalSeparatorStyle from './applyInternationalSeparatorStyle.js';
describe('applyInternationalSeparatorStyle', function () {
it('should change Google\'s international format style', function () {
expect(applyInternationalSeparatorStyle('(xxx) xxx-xx-xx')).to.equal('xxx xxx xx xx');
expect(applyInternationalSeparatorStyle('(xxx)xxx')).to.equal('xxx xxx');
});
});
//# sourceMappingURL=applyInternationalSeparatorStyle.test.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"applyInternationalSeparatorStyle.test.js","names":["applyInternationalSeparatorStyle","describe","it","expect","to","equal"],"sources":["../../source/helpers/applyInternationalSeparatorStyle.test.js"],"sourcesContent":["import applyInternationalSeparatorStyle from './applyInternationalSeparatorStyle.js'\r\n\r\ndescribe('applyInternationalSeparatorStyle', () => {\r\n\tit('should change Google\\'s international format style', () => {\r\n\t\texpect(applyInternationalSeparatorStyle('(xxx) xxx-xx-xx')).to.equal('xxx xxx xx xx')\r\n\t\texpect(applyInternationalSeparatorStyle('(xxx)xxx')).to.equal('xxx xxx')\r\n\t})\r\n})"],"mappings":"AAAA,OAAOA,gCAAgC,MAAM,uCAAuC;AAEpFC,QAAQ,CAAC,kCAAkC,EAAE,YAAM;EAClDC,EAAE,CAAC,oDAAoD,EAAE,YAAM;IAC9DC,MAAM,CAACH,gCAAgC,CAAC,iBAAiB,CAAC,CAAC,CAACI,EAAE,CAACC,KAAK,CAAC,eAAe,CAAC;IACrFF,MAAM,CAACH,gCAAgC,CAAC,UAAU,CAAC,CAAC,CAACI,EAAE,CAACC,KAAK,CAAC,SAAS,CAAC;EACzE,CAAC,CAAC;AACH,CAAC,CAAC","ignoreList":[]}

View File

@@ -0,0 +1,112 @@
import Metadata from '../metadata.js';
import mergeArrays from './mergeArrays.js';
export default function checkNumberLength(nationalNumber, country, metadata) {
return checkNumberLengthForType(nationalNumber, country, undefined, metadata);
}
// Checks whether a number is possible for a certain `country` based on the number length.
//
// This function is not supported by metadata generated with ancient versions of
// `libphonenumber-js` (before version `1.0.18`) which didn't include "possible lengths".
//
// There was also a known issue with `checkNumberLength()` function:
// if a number is possible only in a certain `country` among several `countries`
// that share the same "country calling code", that function would check
// the possibility of the phone number only in the "main" `country` for the "country calling code"
// and would not check if it's actually be possible in the speciifc `country`.
//
// For example, "+1310xxxx" numbers are valid in Canada.
// However, they are not possible in the US due to being too short.
// Since Canada and the US share the same country calling code — "+1" —
// `checkNumberLength()` function used to return not "IS_POSSIBLE" for "+1310xxxx" numbers.
//
// In such cases, when using "/max" metadata, `isValid()` could output `true`
// but at the same time `isPossible()` could output `false`, which was contradictory.
//
// See https://issuetracker.google.com/issues/335892662 for the discusson in Google's issues.
//
// The solution suggested by Google was implemented: an optional `country` argument
// was added to `checkNumberLength()` function. If present, that `country` will be used
// to check phone number length for that specific `country` rather than the "main" country
// for the shared "country calling code".
//
export function checkNumberLengthForType(nationalNumber, country, type, metadata) {
// If the exact `country` is specified, it's no necessarily already selected in `metadata`.
// Most likely, in cases when there're multiple countries corresponding to the same
// "country calling code", the "main" country for that "country calling code" will be selected.
if (country) {
metadata = new Metadata(metadata.metadata);
metadata.selectNumberingPlan(country);
}
var type_info = metadata.type(type);
// There should always be "<possiblePengths/>" set for every type element.
// This is declared in the XML schema.
// For size efficiency, where a sub-description (e.g. fixed-line)
// has the same "<possiblePengths/>" as the "general description", this is missing,
// so we fall back to the "general description". Where no numbers of the type
// exist at all, there is one possible length (-1) which is guaranteed
// not to match the length of any real phone number.
var possible_lengths = type_info && type_info.possibleLengths() || metadata.possibleLengths();
// let local_lengths = type_info && type.possibleLengthsLocal() || metadata.possibleLengthsLocal()
// Metadata before version `1.0.18` didn't contain `possible_lengths`.
if (!possible_lengths) {
return 'IS_POSSIBLE';
}
if (type === 'FIXED_LINE_OR_MOBILE') {
// No such country in metadata.
/* istanbul ignore next */
if (!metadata.type('FIXED_LINE')) {
// The rare case has been encountered where no fixedLine data is available
// (true for some non-geographic entities), so we just check mobile.
return checkNumberLengthForType(nationalNumber, country, 'MOBILE', metadata);
}
var mobile_type = metadata.type('MOBILE');
if (mobile_type) {
// Merge the mobile data in if there was any. "Concat" creates a new
// array, it doesn't edit possible_lengths in place, so we don't need a copy.
// Note that when adding the possible lengths from mobile, we have
// to again check they aren't empty since if they are this indicates
// they are the same as the general desc and should be obtained from there.
possible_lengths = mergeArrays(possible_lengths, mobile_type.possibleLengths());
// The current list is sorted; we need to merge in the new list and
// re-sort (duplicates are okay). Sorting isn't so expensive because
// the lists are very small.
// if (local_lengths) {
// local_lengths = mergeArrays(local_lengths, mobile_type.possibleLengthsLocal())
// } else {
// local_lengths = mobile_type.possibleLengthsLocal()
// }
}
}
// If the type doesn't exist then return 'INVALID_LENGTH'.
else if (type && !type_info) {
return 'INVALID_LENGTH';
}
var actual_length = nationalNumber.length;
// In `libphonenumber-js` all "local-only" formats are dropped for simplicity.
// // This is safe because there is never an overlap beween the possible lengths
// // and the local-only lengths; this is checked at build time.
// if (local_lengths && local_lengths.indexOf(nationalNumber.length) >= 0)
// {
// return 'IS_POSSIBLE_LOCAL_ONLY'
// }
var minimum_length = possible_lengths[0];
if (minimum_length === actual_length) {
return 'IS_POSSIBLE';
}
if (minimum_length > actual_length) {
return 'TOO_SHORT';
}
if (possible_lengths[possible_lengths.length - 1] < actual_length) {
return 'TOO_LONG';
}
// We skip the first element since we've already checked it.
return possible_lengths.indexOf(actual_length, 1) >= 0 ? 'IS_POSSIBLE' : 'INVALID_LENGTH';
}
//# sourceMappingURL=checkNumberLength.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,74 @@
import Metadata from '../metadata.js';
import metadata from '../../metadata.max.json' with { type: 'json' };
import oldMetadata from '../../test/metadata/1.0.0/metadata.min.json' with { type: 'json' };
import checkNumberLength, { checkNumberLengthForType } from './checkNumberLength.js';
describe('checkNumberLength', function () {
it('should check phone number length', function () {
// Too short.
expect(checkNumberLengthWithCountry('800555353', 'RU', 'FIXED_LINE')).to.equal('TOO_SHORT');
// Normal.
expect(checkNumberLengthWithCountry('8005553535', 'RU', 'FIXED_LINE')).to.equal('IS_POSSIBLE');
// Too long.
expect(checkNumberLengthWithCountry('80055535355', 'RU', 'FIXED_LINE')).to.equal('TOO_LONG');
// No such type.
expect(checkNumberLengthWithCountry('169454850', 'AC', 'VOIP')).to.equal('INVALID_LENGTH');
// No such possible length.
expect(checkNumberLengthWithCountry('1694548', 'AD', undefined)).to.equal('INVALID_LENGTH');
// FIXED_LINE_OR_MOBILE
expect(checkNumberLengthWithCountry('1694548', 'AD', 'FIXED_LINE_OR_MOBILE')).to.equal('INVALID_LENGTH');
// No mobile phones.
expect(checkNumberLengthWithCountry('8123', 'TA', 'FIXED_LINE_OR_MOBILE')).to.equal('IS_POSSIBLE');
// No "possible lengths" for "mobile".
expect(checkNumberLengthWithCountry('81234567', 'SZ', 'FIXED_LINE_OR_MOBILE')).to.equal('IS_POSSIBLE');
});
it('should check phone number length (no `country` specified)', function () {
// Too short.
expect(checkNumberLengthWithoutCountry('800555353', 'RU', 'FIXED_LINE')).to.equal('TOO_SHORT');
// Normal.
expect(checkNumberLengthWithoutCountry('8005553535', 'RU', 'FIXED_LINE')).to.equal('IS_POSSIBLE');
// Too long.
expect(checkNumberLengthWithoutCountry('80055535355', 'RU', 'FIXED_LINE')).to.equal('TOO_LONG');
// No such type.
expect(checkNumberLengthWithoutCountry('169454850', 'AC', 'VOIP')).to.equal('INVALID_LENGTH');
// No such possible length.
expect(checkNumberLengthWithoutCountry('1694548', 'AD', undefined)).to.equal('INVALID_LENGTH');
// FIXED_LINE_OR_MOBILE
expect(checkNumberLengthWithoutCountry('1694548', 'AD', 'FIXED_LINE_OR_MOBILE')).to.equal('INVALID_LENGTH');
// No mobile phones.
expect(checkNumberLengthWithoutCountry('8123', 'TA', 'FIXED_LINE_OR_MOBILE')).to.equal('IS_POSSIBLE');
// No "possible lengths" for "mobile".
expect(checkNumberLengthWithoutCountry('81234567', 'SZ', 'FIXED_LINE_OR_MOBILE')).to.equal('IS_POSSIBLE');
});
it('should work for old metadata', function () {
var _oldMetadata = new Metadata(oldMetadata);
_oldMetadata.country('RU');
expect(checkNumberLengthForType('8005553535', 'RU', 'FIXED_LINE', _oldMetadata)).to.equal('IS_POSSIBLE');
});
it('should work for old metadata (no `country` specified)', function () {
var _oldMetadata = new Metadata(oldMetadata);
_oldMetadata.country('RU');
expect(checkNumberLengthForType('8005553535', undefined, 'FIXED_LINE', _oldMetadata)).to.equal('IS_POSSIBLE');
});
it('should handle the cases when multiple countries share the same country calling code and a phone number is possible in non-"main" country and is not possible in the "main" country', function () {
var _metadata = new Metadata(metadata);
_metadata.country('US');
expect(checkNumberLength('3100000', undefined, _metadata)).to.equal('TOO_SHORT');
expect(checkNumberLength('3100000', 'US', _metadata)).to.equal('TOO_SHORT');
expect(checkNumberLength('3100000', 'CA', _metadata)).to.equal('IS_POSSIBLE');
});
});
function checkNumberLengthWithCountry(number, country, type) {
var _metadata = new Metadata(metadata);
_metadata.country(country);
return checkNumberLengthForType(number, country, type, _metadata);
}
function checkNumberLengthWithoutCountry(number, country, type) {
var _metadata = new Metadata(metadata);
_metadata.country(country);
return checkNumberLengthForType(number, undefined, type, _metadata);
}
//# sourceMappingURL=checkNumberLength.test.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,95 @@
import { VALID_DIGITS } from '../../constants.js';
// The RFC 3966 format for extensions.
var RFC3966_EXTN_PREFIX = ';ext=';
/**
* Helper method for constructing regular expressions for parsing. Creates
* an expression that captures up to max_length digits.
* @return {string} RegEx pattern to capture extension digits.
*/
var getExtensionDigitsPattern = function getExtensionDigitsPattern(maxLength) {
return "([".concat(VALID_DIGITS, "]{1,").concat(maxLength, "})");
};
/**
* Helper initialiser method to create the regular-expression pattern to match
* extensions.
* Copy-pasted from Google's `libphonenumber`:
* https://github.com/google/libphonenumber/blob/55b2646ec9393f4d3d6661b9c82ef9e258e8b829/javascript/i18n/phonenumbers/phonenumberutil.js#L759-L766
* @return {string} RegEx pattern to capture extensions.
*/
export default function createExtensionPattern(purpose) {
// We cap the maximum length of an extension based on the ambiguity of the way
// the extension is prefixed. As per ITU, the officially allowed length for
// extensions is actually 40, but we don't support this since we haven't seen real
// examples and this introduces many false interpretations as the extension labels
// are not standardized.
/** @type {string} */
var extLimitAfterExplicitLabel = '20';
/** @type {string} */
var extLimitAfterLikelyLabel = '15';
/** @type {string} */
var extLimitAfterAmbiguousChar = '9';
/** @type {string} */
var extLimitWhenNotSure = '6';
/** @type {string} */
var possibleSeparatorsBetweenNumberAndExtLabel = "[ \xA0\\t,]*";
// Optional full stop (.) or colon, followed by zero or more spaces/tabs/commas.
/** @type {string} */
var possibleCharsAfterExtLabel = "[:\\.\uFF0E]?[ \xA0\\t,-]*";
/** @type {string} */
var optionalExtnSuffix = "#?";
// Here the extension is called out in more explicit way, i.e mentioning it obvious
// patterns like "ext.".
/** @type {string} */
var explicitExtLabels = "(?:e?xt(?:ensi(?:o\u0301?|\xF3))?n?|\uFF45?\uFF58\uFF54\uFF4E?|\u0434\u043E\u0431|anexo)";
// One-character symbols that can be used to indicate an extension, and less
// commonly used or more ambiguous extension labels.
/** @type {string} */
var ambiguousExtLabels = "(?:[x\uFF58#\uFF03~\uFF5E]|int|\uFF49\uFF4E\uFF54)";
// When extension is not separated clearly.
/** @type {string} */
var ambiguousSeparator = "[- ]+";
// This is the same as possibleSeparatorsBetweenNumberAndExtLabel, but not matching
// comma as extension label may have it.
/** @type {string} */
var possibleSeparatorsNumberExtLabelNoComma = "[ \xA0\\t]*";
// ",," is commonly used for auto dialling the extension when connected. First
// comma is matched through possibleSeparatorsBetweenNumberAndExtLabel, so we do
// not repeat it here. Semi-colon works in Iphone and Android also to pop up a
// button with the extension number following.
/** @type {string} */
var autoDiallingAndExtLabelsFound = "(?:,{2}|;)";
/** @type {string} */
var rfcExtn = RFC3966_EXTN_PREFIX + getExtensionDigitsPattern(extLimitAfterExplicitLabel);
/** @type {string} */
var explicitExtn = possibleSeparatorsBetweenNumberAndExtLabel + explicitExtLabels + possibleCharsAfterExtLabel + getExtensionDigitsPattern(extLimitAfterExplicitLabel) + optionalExtnSuffix;
/** @type {string} */
var ambiguousExtn = possibleSeparatorsBetweenNumberAndExtLabel + ambiguousExtLabels + possibleCharsAfterExtLabel + getExtensionDigitsPattern(extLimitAfterAmbiguousChar) + optionalExtnSuffix;
/** @type {string} */
var americanStyleExtnWithSuffix = ambiguousSeparator + getExtensionDigitsPattern(extLimitWhenNotSure) + "#";
/** @type {string} */
var autoDiallingExtn = possibleSeparatorsNumberExtLabelNoComma + autoDiallingAndExtLabelsFound + possibleCharsAfterExtLabel + getExtensionDigitsPattern(extLimitAfterLikelyLabel) + optionalExtnSuffix;
/** @type {string} */
var onlyCommasExtn = possibleSeparatorsNumberExtLabelNoComma + "(?:,)+" + possibleCharsAfterExtLabel + getExtensionDigitsPattern(extLimitAfterAmbiguousChar) + optionalExtnSuffix;
// The first regular expression covers RFC 3966 format, where the extension is added
// using ";ext=". The second more generic where extension is mentioned with explicit
// labels like "ext:". In both the above cases we allow more numbers in extension than
// any other extension labels. The third one captures when single character extension
// labels or less commonly used labels are used. In such cases we capture fewer
// extension digits in order to reduce the chance of falsely interpreting two
// numbers beside each other as a number + extension. The fourth one covers the
// special case of American numbers where the extension is written with a hash
// at the end, such as "- 503#". The fifth one is exclusively for extension
// autodialling formats which are used when dialling and in this case we accept longer
// extensions. The last one is more liberal on the number of commas that acts as
// extension labels, so we have a strict cap on the number of digits in such extensions.
return rfcExtn + "|" + explicitExtn + "|" + ambiguousExtn + "|" + americanStyleExtnWithSuffix + "|" + autoDiallingExtn + "|" + onlyCommasExtn;
}
//# sourceMappingURL=createExtensionPattern.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,30 @@
import createExtensionPattern from './createExtensionPattern.js';
// Regexp of all known extension prefixes used by different regions followed by
// 1 or more valid digits, for use when parsing.
var EXTN_PATTERN = new RegExp('(?:' + createExtensionPattern() + ')$', 'i');
// Strips any extension (as in, the part of the number dialled after the call is
// connected, usually indicated with extn, ext, x or similar) from the end of
// the number, and returns it.
export default function extractExtension(number) {
var start = number.search(EXTN_PATTERN);
if (start < 0) {
return {};
}
// If we find a potential extension, and the number preceding this is a viable
// number, we assume it is an extension.
var numberWithoutExtension = number.slice(0, start);
var matches = number.match(EXTN_PATTERN);
var i = 1;
while (i < matches.length) {
if (matches[i]) {
return {
number: numberWithoutExtension,
ext: matches[i]
};
}
i++;
}
}
//# sourceMappingURL=extractExtension.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"extractExtension.js","names":["createExtensionPattern","EXTN_PATTERN","RegExp","extractExtension","number","start","search","numberWithoutExtension","slice","matches","match","i","length","ext"],"sources":["../../../source/helpers/extension/extractExtension.js"],"sourcesContent":["import createExtensionPattern from './createExtensionPattern.js'\r\n\r\n// Regexp of all known extension prefixes used by different regions followed by\r\n// 1 or more valid digits, for use when parsing.\r\nconst EXTN_PATTERN = new RegExp('(?:' + createExtensionPattern() + ')$', 'i')\r\n\r\n// Strips any extension (as in, the part of the number dialled after the call is\r\n// connected, usually indicated with extn, ext, x or similar) from the end of\r\n// the number, and returns it.\r\nexport default function extractExtension(number) {\r\n\tconst start = number.search(EXTN_PATTERN)\r\n\tif (start < 0) {\r\n\t\treturn {}\r\n\t}\r\n\t// If we find a potential extension, and the number preceding this is a viable\r\n\t// number, we assume it is an extension.\r\n\tconst numberWithoutExtension = number.slice(0, start)\r\n\tconst matches = number.match(EXTN_PATTERN)\r\n\tlet i = 1\r\n\twhile (i < matches.length) {\r\n\t\tif (matches[i]) {\r\n\t\t\treturn {\r\n\t\t\t\tnumber: numberWithoutExtension,\r\n\t\t\t\text: matches[i]\r\n\t\t\t}\r\n\t\t}\r\n\t\ti++\r\n\t}\r\n}"],"mappings":"AAAA,OAAOA,sBAAsB,MAAM,6BAA6B;;AAEhE;AACA;AACA,IAAMC,YAAY,GAAG,IAAIC,MAAM,CAAC,KAAK,GAAGF,sBAAsB,CAAC,CAAC,GAAG,IAAI,EAAE,GAAG,CAAC;;AAE7E;AACA;AACA;AACA,eAAe,SAASG,gBAAgBA,CAACC,MAAM,EAAE;EAChD,IAAMC,KAAK,GAAGD,MAAM,CAACE,MAAM,CAACL,YAAY,CAAC;EACzC,IAAII,KAAK,GAAG,CAAC,EAAE;IACd,OAAO,CAAC,CAAC;EACV;EACA;EACA;EACA,IAAME,sBAAsB,GAAGH,MAAM,CAACI,KAAK,CAAC,CAAC,EAAEH,KAAK,CAAC;EACrD,IAAMI,OAAO,GAAGL,MAAM,CAACM,KAAK,CAACT,YAAY,CAAC;EAC1C,IAAIU,CAAC,GAAG,CAAC;EACT,OAAOA,CAAC,GAAGF,OAAO,CAACG,MAAM,EAAE;IAC1B,IAAIH,OAAO,CAACE,CAAC,CAAC,EAAE;MACf,OAAO;QACNP,MAAM,EAAEG,sBAAsB;QAC9BM,GAAG,EAAEJ,OAAO,CAACE,CAAC;MACf,CAAC;IACF;IACAA,CAAC,EAAE;EACJ;AACD","ignoreList":[]}

View File

@@ -0,0 +1,141 @@
import stripIddPrefix from './stripIddPrefix.js';
import extractCountryCallingCodeFromInternationalNumberWithoutPlusSign from './extractCountryCallingCodeFromInternationalNumberWithoutPlusSign.js';
import Metadata from '../metadata.js';
import { MAX_LENGTH_COUNTRY_CODE } from '../constants.js';
/**
* Converts a phone number digits (possibly with a `+`)
* into a calling code and the rest phone number digits.
* The "rest phone number digits" could include
* a national prefix, carrier code, and national
* (significant) number.
* @param {string} number — Phone number digits (possibly with a `+`).
* @param {string} [country] — Country.
* @param {string} [defaultCountry] — Default country.
* @param {string} [defaultCallingCode] — Default calling code (some phone numbering plans are non-geographic).
* @param {object} metadata
* @return {object} `{ countryCallingCodeSource: string?, countryCallingCode: string?, number: string }`
* @example
* // Returns `{ countryCallingCode: "1", number: "2133734253" }`.
* extractCountryCallingCode('2133734253', null, 'US', null, metadata)
* extractCountryCallingCode('2133734253', null, null, '1', metadata)
* extractCountryCallingCode('+12133734253', null, null, null, metadata)
* extractCountryCallingCode('+12133734253', null, 'RU', null, metadata)
*/
export default function extractCountryCallingCode(number, country, defaultCountry, defaultCallingCode, metadata) {
if (!number) {
return {};
}
var isNumberWithIddPrefix;
// If this is not an international phone number,
// then either extract an "IDD" prefix, or extract a
// country calling code from a number by autocorrecting it
// by prepending a leading `+` in cases when it starts
// with the country calling code.
// https://wikitravel.org/en/International_dialling_prefix
// https://github.com/catamphetamine/libphonenumber-js/issues/376
if (number[0] !== '+') {
// Convert an "out-of-country" dialing phone number
// to a proper international phone number.
var numberWithoutIDD = stripIddPrefix(number, country || defaultCountry, defaultCallingCode, metadata);
// If an IDD prefix was stripped then
// convert the number to international one
// for subsequent parsing.
if (numberWithoutIDD && numberWithoutIDD !== number) {
isNumberWithIddPrefix = true;
number = '+' + numberWithoutIDD;
} else {
// Check to see if the number starts with the country calling code
// for the default country. If so, we remove the country calling code,
// and do some checks on the validity of the number before and after.
// https://github.com/catamphetamine/libphonenumber-js/issues/376
if (country || defaultCountry || defaultCallingCode) {
var _extractCountryCallin = extractCountryCallingCodeFromInternationalNumberWithoutPlusSign(number, country, defaultCountry, defaultCallingCode, metadata),
countryCallingCode = _extractCountryCallin.countryCallingCode,
shorterNumber = _extractCountryCallin.number;
if (countryCallingCode) {
return {
countryCallingCodeSource: 'FROM_NUMBER_WITHOUT_PLUS_SIGN',
countryCallingCode: countryCallingCode,
number: shorterNumber
};
}
}
return {
// No need to set it to `UNSPECIFIED`. It can be just `undefined`.
// countryCallingCodeSource: 'UNSPECIFIED',
number: number
};
}
}
// `number` can only be international at this point.
// Fast abortion: country codes do not begin with a '0'
if (number[1] === '0') {
return {};
}
metadata = new Metadata(metadata);
// The thing with country phone codes
// is that they are orthogonal to each other
// i.e. there's no such country phone code A
// for which country phone code B exists
// where B starts with A.
// Therefore, while scanning digits,
// if a valid country code is found,
// that means that it is the country code.
//
var i = 2;
while (i - 1 <= MAX_LENGTH_COUNTRY_CODE && i <= number.length) {
var _countryCallingCode = number.slice(1, i);
if (metadata.hasCallingCode(_countryCallingCode)) {
metadata.selectNumberingPlan(_countryCallingCode);
return {
countryCallingCodeSource: isNumberWithIddPrefix ? 'FROM_NUMBER_WITH_IDD' : 'FROM_NUMBER_WITH_PLUS_SIGN',
countryCallingCode: _countryCallingCode,
number: number.slice(i)
};
}
i++;
}
return {};
}
// The possible values for the returned `countryCallingCodeSource` are:
//
// Copy-pasted from:
// https://github.com/google/libphonenumber/blob/master/resources/phonenumber.proto
//
// // The source from which the country_code is derived. This is not set in the
// // general parsing method, but in the method that parses and keeps raw_input.
// // New fields could be added upon request.
// enum CountryCodeSource {
// // Default value returned if this is not set, because the phone number was
// // created using parse, not parseAndKeepRawInput. hasCountryCodeSource will
// // return false if this is the case.
// UNSPECIFIED = 0;
//
// // The country_code is derived based on a phone number with a leading "+",
// // e.g. the French number "+33 1 42 68 53 00".
// FROM_NUMBER_WITH_PLUS_SIGN = 1;
//
// // The country_code is derived based on a phone number with a leading IDD,
// // e.g. the French number "011 33 1 42 68 53 00", as it is dialled from US.
// FROM_NUMBER_WITH_IDD = 5;
//
// // The country_code is derived based on a phone number without a leading
// // "+", e.g. the French number "33 1 42 68 53 00" when defaultCountry is
// // supplied as France.
// FROM_NUMBER_WITHOUT_PLUS_SIGN = 10;
//
// // The country_code is derived NOT based on the phone number itself, but
// // from the defaultCountry parameter provided in the parsing function by the
// // clients. This happens mostly for numbers written in the national format
// // (without country code). For example, this would be set when parsing the
// // French number "01 42 68 53 00", when defaultCountry is supplied as
// // France.
// FROM_DEFAULT_COUNTRY = 20;
// }
//# sourceMappingURL=extractCountryCallingCode.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,18 @@
import extractCountryCallingCode from './extractCountryCallingCode.js';
import metadata from '../../metadata.min.json' with { type: 'json' };
describe('extractCountryCallingCode', function () {
it('should extract country calling code from a number', function () {
expect(extractCountryCallingCode('+78005553535', null, null, null, metadata)).to.deep.equal({
countryCallingCodeSource: 'FROM_NUMBER_WITH_PLUS_SIGN',
countryCallingCode: '7',
number: '8005553535'
});
expect(extractCountryCallingCode('+7800', null, null, null, metadata)).to.deep.equal({
countryCallingCodeSource: 'FROM_NUMBER_WITH_PLUS_SIGN',
countryCallingCode: '7',
number: '800'
});
expect(extractCountryCallingCode('', null, null, null, metadata)).to.deep.equal({});
});
});
//# sourceMappingURL=extractCountryCallingCode.test.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"extractCountryCallingCode.test.js","names":["extractCountryCallingCode","metadata","type","describe","it","expect","to","deep","equal","countryCallingCodeSource","countryCallingCode","number"],"sources":["../../source/helpers/extractCountryCallingCode.test.js"],"sourcesContent":["import extractCountryCallingCode from './extractCountryCallingCode.js'\r\nimport metadata from '../../metadata.min.json' with { type: 'json' }\r\n\r\ndescribe('extractCountryCallingCode', () => {\r\n\tit('should extract country calling code from a number', () => {\r\n\t\texpect(extractCountryCallingCode('+78005553535', null, null, null, metadata)).to.deep.equal({\r\n\t\t\tcountryCallingCodeSource: 'FROM_NUMBER_WITH_PLUS_SIGN',\r\n\t\t\tcountryCallingCode: '7',\r\n\t\t\tnumber: '8005553535'\r\n\t\t})\r\n\r\n\t\texpect(extractCountryCallingCode('+7800', null, null, null, metadata)).to.deep.equal({\r\n\t\t\tcountryCallingCodeSource: 'FROM_NUMBER_WITH_PLUS_SIGN',\r\n\t\t\tcountryCallingCode: '7',\r\n\t\t\tnumber: '800'\r\n\t\t})\r\n\r\n\t\texpect(extractCountryCallingCode('', null, null, null, metadata)).to.deep.equal({})\r\n\t})\r\n})\r\n"],"mappings":"AAAA,OAAOA,yBAAyB,MAAM,gCAAgC;AACtE,OAAOC,QAAQ,MAAM,yBAAyB,QAAQC,IAAI,EAAE,MAAM;AAElEC,QAAQ,CAAC,2BAA2B,EAAE,YAAM;EAC3CC,EAAE,CAAC,mDAAmD,EAAE,YAAM;IAC7DC,MAAM,CAACL,yBAAyB,CAAC,cAAc,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAEC,QAAQ,CAAC,CAAC,CAACK,EAAE,CAACC,IAAI,CAACC,KAAK,CAAC;MAC3FC,wBAAwB,EAAE,4BAA4B;MACtDC,kBAAkB,EAAE,GAAG;MACvBC,MAAM,EAAE;IACT,CAAC,CAAC;IAEFN,MAAM,CAACL,yBAAyB,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAEC,QAAQ,CAAC,CAAC,CAACK,EAAE,CAACC,IAAI,CAACC,KAAK,CAAC;MACpFC,wBAAwB,EAAE,4BAA4B;MACtDC,kBAAkB,EAAE,GAAG;MACvBC,MAAM,EAAE;IACT,CAAC,CAAC;IAEFN,MAAM,CAACL,yBAAyB,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAEC,QAAQ,CAAC,CAAC,CAACK,EAAE,CAACC,IAAI,CAACC,KAAK,CAAC,CAAC,CAAC,CAAC;EACpF,CAAC,CAAC;AACH,CAAC,CAAC","ignoreList":[]}

View File

@@ -0,0 +1,47 @@
import Metadata from '../metadata.js';
import matchesEntirely from './matchesEntirely.js';
import extractNationalNumber from './extractNationalNumber.js';
import checkNumberLength from './checkNumberLength.js';
import getCountryCallingCode from '../getCountryCallingCode.js';
/**
* Sometimes some people incorrectly input international phone numbers
* without the leading `+`. This function corrects such input.
* @param {string} number — Phone number digits.
* @param {string} [country] — Exact country of the phone number.
* @param {string} [defaultCountry]
* @param {string} [defaultCallingCode]
* @param {object} metadata
* @return {object} `{ countryCallingCode: string?, number: string }`.
*/
export default function extractCountryCallingCodeFromInternationalNumberWithoutPlusSign(number, country, defaultCountry, defaultCallingCode, metadata) {
var countryCallingCode = country || defaultCountry ? getCountryCallingCode(country || defaultCountry, metadata) : defaultCallingCode;
if (number.indexOf(countryCallingCode) === 0) {
metadata = new Metadata(metadata);
metadata.selectNumberingPlan(country || defaultCountry, countryCallingCode);
var possibleShorterNumber = number.slice(countryCallingCode.length);
var _extractNationalNumbe = extractNationalNumber(possibleShorterNumber, country, metadata),
possibleShorterNationalNumber = _extractNationalNumbe.nationalNumber;
var _extractNationalNumbe2 = extractNationalNumber(number, country, metadata),
nationalNumber = _extractNationalNumbe2.nationalNumber;
// If the number was not valid before but is valid now,
// or if it was too long before, we consider the number
// with the country calling code stripped to be a better result
// and keep that instead.
// For example, in Germany (+49), `49` is a valid area code,
// so if a number starts with `49`, it could be both a valid
// national German number or an international number without
// a leading `+`.
if (!matchesEntirely(nationalNumber, metadata.nationalNumberPattern()) && matchesEntirely(possibleShorterNationalNumber, metadata.nationalNumberPattern()) || checkNumberLength(nationalNumber, country, metadata) === 'TOO_LONG') {
return {
countryCallingCode: countryCallingCode,
number: possibleShorterNumber
};
}
}
return {
number: number
};
}
//# sourceMappingURL=extractCountryCallingCodeFromInternationalNumberWithoutPlusSign.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"extractCountryCallingCodeFromInternationalNumberWithoutPlusSign.js","names":["Metadata","matchesEntirely","extractNationalNumber","checkNumberLength","getCountryCallingCode","extractCountryCallingCodeFromInternationalNumberWithoutPlusSign","number","country","defaultCountry","defaultCallingCode","metadata","countryCallingCode","indexOf","selectNumberingPlan","possibleShorterNumber","slice","length","_extractNationalNumbe","possibleShorterNationalNumber","nationalNumber","_extractNationalNumbe2","nationalNumberPattern"],"sources":["../../source/helpers/extractCountryCallingCodeFromInternationalNumberWithoutPlusSign.js"],"sourcesContent":["import Metadata from '../metadata.js'\r\nimport matchesEntirely from './matchesEntirely.js'\r\nimport extractNationalNumber from './extractNationalNumber.js'\r\nimport checkNumberLength from './checkNumberLength.js'\r\nimport getCountryCallingCode from '../getCountryCallingCode.js'\r\n\r\n/**\r\n * Sometimes some people incorrectly input international phone numbers\r\n * without the leading `+`. This function corrects such input.\r\n * @param {string} number — Phone number digits.\r\n * @param {string} [country] — Exact country of the phone number.\r\n * @param {string} [defaultCountry]\r\n * @param {string} [defaultCallingCode]\r\n * @param {object} metadata\r\n * @return {object} `{ countryCallingCode: string?, number: string }`.\r\n */\r\nexport default function extractCountryCallingCodeFromInternationalNumberWithoutPlusSign(\r\n\tnumber,\r\n\tcountry,\r\n\tdefaultCountry,\r\n\tdefaultCallingCode,\r\n\tmetadata\r\n) {\r\n\tconst countryCallingCode = country || defaultCountry\r\n\t\t? getCountryCallingCode(country || defaultCountry, metadata)\r\n\t\t: defaultCallingCode\r\n\r\n\tif (number.indexOf(countryCallingCode) === 0) {\r\n\t\tmetadata = new Metadata(metadata)\r\n\t\tmetadata.selectNumberingPlan(country || defaultCountry, countryCallingCode)\r\n\r\n\t\tconst possibleShorterNumber = number.slice(countryCallingCode.length)\r\n\r\n\t\tconst {\r\n\t\t\tnationalNumber: possibleShorterNationalNumber,\r\n\t\t} = extractNationalNumber(\r\n\t\t\tpossibleShorterNumber,\r\n\t\t\tcountry,\r\n\t\t\tmetadata\r\n\t\t)\r\n\r\n\t\tconst {\r\n\t\t\tnationalNumber\r\n\t\t} = extractNationalNumber(\r\n\t\t\tnumber,\r\n\t\t\tcountry,\r\n\t\t\tmetadata\r\n\t\t)\r\n\r\n\t\t// If the number was not valid before but is valid now,\r\n\t\t// or if it was too long before, we consider the number\r\n\t\t// with the country calling code stripped to be a better result\r\n\t\t// and keep that instead.\r\n\t\t// For example, in Germany (+49), `49` is a valid area code,\r\n\t\t// so if a number starts with `49`, it could be both a valid\r\n\t\t// national German number or an international number without\r\n\t\t// a leading `+`.\r\n\t\tif (\r\n\t\t\t(\r\n\t\t\t\t!matchesEntirely(nationalNumber, metadata.nationalNumberPattern()) &&\r\n\t\t\t\tmatchesEntirely(possibleShorterNationalNumber, metadata.nationalNumberPattern())\r\n\t\t\t)\r\n\t\t\t||\r\n\t\t\tcheckNumberLength(nationalNumber, country, metadata) === 'TOO_LONG'\r\n\t\t) {\r\n\t\t\treturn {\r\n\t\t\t\tcountryCallingCode,\r\n\t\t\t\tnumber: possibleShorterNumber\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn { number }\r\n}"],"mappings":"AAAA,OAAOA,QAAQ,MAAM,gBAAgB;AACrC,OAAOC,eAAe,MAAM,sBAAsB;AAClD,OAAOC,qBAAqB,MAAM,4BAA4B;AAC9D,OAAOC,iBAAiB,MAAM,wBAAwB;AACtD,OAAOC,qBAAqB,MAAM,6BAA6B;;AAE/D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAe,SAASC,+DAA+DA,CACtFC,MAAM,EACNC,OAAO,EACPC,cAAc,EACdC,kBAAkB,EAClBC,QAAQ,EACP;EACD,IAAMC,kBAAkB,GAAGJ,OAAO,IAAIC,cAAc,GACjDJ,qBAAqB,CAACG,OAAO,IAAIC,cAAc,EAAEE,QAAQ,CAAC,GAC1DD,kBAAkB;EAErB,IAAIH,MAAM,CAACM,OAAO,CAACD,kBAAkB,CAAC,KAAK,CAAC,EAAE;IAC7CD,QAAQ,GAAG,IAAIV,QAAQ,CAACU,QAAQ,CAAC;IACjCA,QAAQ,CAACG,mBAAmB,CAACN,OAAO,IAAIC,cAAc,EAAEG,kBAAkB,CAAC;IAE3E,IAAMG,qBAAqB,GAAGR,MAAM,CAACS,KAAK,CAACJ,kBAAkB,CAACK,MAAM,CAAC;IAErE,IAAAC,qBAAA,GAEIf,qBAAqB,CACxBY,qBAAqB,EACrBP,OAAO,EACPG,QACD,CAAC;MALgBQ,6BAA6B,GAAAD,qBAAA,CAA7CE,cAAc;IAOf,IAAAC,sBAAA,GAEIlB,qBAAqB,CACxBI,MAAM,EACNC,OAAO,EACPG,QACD,CAAC;MALAS,cAAc,GAAAC,sBAAA,CAAdD,cAAc;;IAOf;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,IAEE,CAAClB,eAAe,CAACkB,cAAc,EAAET,QAAQ,CAACW,qBAAqB,CAAC,CAAC,CAAC,IAClEpB,eAAe,CAACiB,6BAA6B,EAAER,QAAQ,CAACW,qBAAqB,CAAC,CAAC,CAAC,IAGjFlB,iBAAiB,CAACgB,cAAc,EAAEZ,OAAO,EAAEG,QAAQ,CAAC,KAAK,UAAU,EAClE;MACD,OAAO;QACNC,kBAAkB,EAAlBA,kBAAkB;QAClBL,MAAM,EAAEQ;MACT,CAAC;IACF;EACD;EAEA,OAAO;IAAER,MAAM,EAANA;EAAO,CAAC;AAClB","ignoreList":[]}

View File

@@ -0,0 +1,65 @@
import extractPhoneContext, { isPhoneContextValid, PLUS_SIGN, RFC3966_PREFIX_, RFC3966_PHONE_CONTEXT_, RFC3966_ISDN_SUBADDRESS_ } from './extractPhoneContext.js';
import ParseError from '../ParseError.js';
/**
* @param {string} numberToParse
* @param {string} nationalNumber
* @return {}
*/
export default function extractFormattedPhoneNumberFromPossibleRfc3966NumberUri(numberToParse, _ref) {
var extractFormattedPhoneNumber = _ref.extractFormattedPhoneNumber;
var phoneContext = extractPhoneContext(numberToParse);
if (!isPhoneContextValid(phoneContext)) {
throw new ParseError('NOT_A_NUMBER');
}
var phoneNumberString;
if (phoneContext === null) {
// Extract a possible number from the string passed in.
// (this strips leading characters that could not be the start of a phone number)
phoneNumberString = extractFormattedPhoneNumber(numberToParse) || '';
} else {
phoneNumberString = '';
// If the phone context contains a phone number prefix, we need to capture
// it, whereas domains will be ignored.
if (phoneContext.charAt(0) === PLUS_SIGN) {
phoneNumberString += phoneContext;
}
// Now append everything between the "tel:" prefix and the phone-context.
// This should include the national number, an optional extension or
// isdn-subaddress component. Note we also handle the case when "tel:" is
// missing, as we have seen in some of the phone number inputs.
// In that case, we append everything from the beginning.
var indexOfRfc3966Prefix = numberToParse.indexOf(RFC3966_PREFIX_);
var indexOfNationalNumber;
// RFC 3966 "tel:" prefix is preset at this stage because
// `isPhoneContextValid()` requires it to be present.
/* istanbul ignore else */
if (indexOfRfc3966Prefix >= 0) {
indexOfNationalNumber = indexOfRfc3966Prefix + RFC3966_PREFIX_.length;
} else {
indexOfNationalNumber = 0;
}
var indexOfPhoneContext = numberToParse.indexOf(RFC3966_PHONE_CONTEXT_);
phoneNumberString += numberToParse.substring(indexOfNationalNumber, indexOfPhoneContext);
}
// Delete the isdn-subaddress and everything after it if it is present.
// Note extension won't appear at the same time with isdn-subaddress
// according to paragraph 5.3 of the RFC3966 spec.
var indexOfIsdn = phoneNumberString.indexOf(RFC3966_ISDN_SUBADDRESS_);
if (indexOfIsdn > 0) {
phoneNumberString = phoneNumberString.substring(0, indexOfIsdn);
}
// If both phone context and isdn-subaddress are absent but other
// parameters are present, the parameters are left in nationalNumber.
// This is because we are concerned about deleting content from a potential
// number string when there is no strong evidence that the number is
// actually written in RFC3966.
if (phoneNumberString !== '') {
return phoneNumberString;
}
}
//# sourceMappingURL=extractFormattedPhoneNumberFromPossibleRfc3966NumberUri.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"extractFormattedPhoneNumberFromPossibleRfc3966NumberUri.js","names":["extractPhoneContext","isPhoneContextValid","PLUS_SIGN","RFC3966_PREFIX_","RFC3966_PHONE_CONTEXT_","RFC3966_ISDN_SUBADDRESS_","ParseError","extractFormattedPhoneNumberFromPossibleRfc3966NumberUri","numberToParse","_ref","extractFormattedPhoneNumber","phoneContext","phoneNumberString","charAt","indexOfRfc3966Prefix","indexOf","indexOfNationalNumber","length","indexOfPhoneContext","substring","indexOfIsdn"],"sources":["../../source/helpers/extractFormattedPhoneNumberFromPossibleRfc3966NumberUri.js"],"sourcesContent":["import extractPhoneContext, {\r\n\tisPhoneContextValid,\r\n\tPLUS_SIGN,\r\n\tRFC3966_PREFIX_,\r\n\tRFC3966_PHONE_CONTEXT_,\r\n\tRFC3966_ISDN_SUBADDRESS_\r\n} from './extractPhoneContext.js'\r\n\r\nimport ParseError from '../ParseError.js'\r\n\r\n/**\r\n * @param {string} numberToParse\r\n * @param {string} nationalNumber\r\n * @return {}\r\n */\r\nexport default function extractFormattedPhoneNumberFromPossibleRfc3966NumberUri(numberToParse, {\r\n\textractFormattedPhoneNumber\r\n}) {\r\n\tconst phoneContext = extractPhoneContext(numberToParse)\r\n\tif (!isPhoneContextValid(phoneContext)) {\r\n\t\tthrow new ParseError('NOT_A_NUMBER')\r\n\t}\r\n\r\n\tlet phoneNumberString\r\n\r\n\tif (phoneContext === null) {\r\n\t\t// Extract a possible number from the string passed in.\r\n\t\t// (this strips leading characters that could not be the start of a phone number)\r\n\t\tphoneNumberString = extractFormattedPhoneNumber(numberToParse) || ''\r\n\t} else {\r\n\t\tphoneNumberString = ''\r\n\r\n\t\t// If the phone context contains a phone number prefix, we need to capture\r\n\t\t// it, whereas domains will be ignored.\r\n\t\tif (phoneContext.charAt(0) === PLUS_SIGN) {\r\n\t\t\tphoneNumberString += phoneContext\r\n\t\t}\r\n\r\n\t\t// Now append everything between the \"tel:\" prefix and the phone-context.\r\n\t\t// This should include the national number, an optional extension or\r\n\t\t// isdn-subaddress component. Note we also handle the case when \"tel:\" is\r\n\t\t// missing, as we have seen in some of the phone number inputs.\r\n\t\t// In that case, we append everything from the beginning.\r\n\t\tconst indexOfRfc3966Prefix = numberToParse.indexOf(RFC3966_PREFIX_)\r\n\t\tlet indexOfNationalNumber\r\n\t\t// RFC 3966 \"tel:\" prefix is preset at this stage because\r\n\t\t// `isPhoneContextValid()` requires it to be present.\r\n\t\t/* istanbul ignore else */\r\n\t\tif (indexOfRfc3966Prefix >= 0) {\r\n\t\t\tindexOfNationalNumber = indexOfRfc3966Prefix + RFC3966_PREFIX_.length\r\n\t\t} else {\r\n\t\t\tindexOfNationalNumber = 0\r\n\t\t}\r\n\t\tconst indexOfPhoneContext = numberToParse.indexOf(RFC3966_PHONE_CONTEXT_)\r\n\t\tphoneNumberString += numberToParse.substring(indexOfNationalNumber, indexOfPhoneContext)\r\n\t}\r\n\r\n\t// Delete the isdn-subaddress and everything after it if it is present.\r\n\t// Note extension won't appear at the same time with isdn-subaddress\r\n\t// according to paragraph 5.3 of the RFC3966 spec.\r\n\tconst indexOfIsdn = phoneNumberString.indexOf(RFC3966_ISDN_SUBADDRESS_)\r\n\tif (indexOfIsdn > 0) {\r\n\t\tphoneNumberString = phoneNumberString.substring(0, indexOfIsdn)\r\n\t}\r\n\t// If both phone context and isdn-subaddress are absent but other\r\n\t// parameters are present, the parameters are left in nationalNumber.\r\n\t// This is because we are concerned about deleting content from a potential\r\n\t// number string when there is no strong evidence that the number is\r\n\t// actually written in RFC3966.\r\n\r\n\tif (phoneNumberString !== '') {\r\n\t\treturn phoneNumberString\r\n\t}\r\n}"],"mappings":"AAAA,OAAOA,mBAAmB,IACzBC,mBAAmB,EACnBC,SAAS,EACTC,eAAe,EACfC,sBAAsB,EACtBC,wBAAwB,QAClB,0BAA0B;AAEjC,OAAOC,UAAU,MAAM,kBAAkB;;AAEzC;AACA;AACA;AACA;AACA;AACA,eAAe,SAASC,uDAAuDA,CAACC,aAAa,EAAAC,IAAA,EAE1F;EAAA,IADFC,2BAA2B,GAAAD,IAAA,CAA3BC,2BAA2B;EAE3B,IAAMC,YAAY,GAAGX,mBAAmB,CAACQ,aAAa,CAAC;EACvD,IAAI,CAACP,mBAAmB,CAACU,YAAY,CAAC,EAAE;IACvC,MAAM,IAAIL,UAAU,CAAC,cAAc,CAAC;EACrC;EAEA,IAAIM,iBAAiB;EAErB,IAAID,YAAY,KAAK,IAAI,EAAE;IAC1B;IACA;IACAC,iBAAiB,GAAGF,2BAA2B,CAACF,aAAa,CAAC,IAAI,EAAE;EACrE,CAAC,MAAM;IACNI,iBAAiB,GAAG,EAAE;;IAEtB;IACA;IACA,IAAID,YAAY,CAACE,MAAM,CAAC,CAAC,CAAC,KAAKX,SAAS,EAAE;MACzCU,iBAAiB,IAAID,YAAY;IAClC;;IAEA;IACA;IACA;IACA;IACA;IACA,IAAMG,oBAAoB,GAAGN,aAAa,CAACO,OAAO,CAACZ,eAAe,CAAC;IACnE,IAAIa,qBAAqB;IACzB;IACA;IACA;IACA,IAAIF,oBAAoB,IAAI,CAAC,EAAE;MAC9BE,qBAAqB,GAAGF,oBAAoB,GAAGX,eAAe,CAACc,MAAM;IACtE,CAAC,MAAM;MACND,qBAAqB,GAAG,CAAC;IAC1B;IACA,IAAME,mBAAmB,GAAGV,aAAa,CAACO,OAAO,CAACX,sBAAsB,CAAC;IACzEQ,iBAAiB,IAAIJ,aAAa,CAACW,SAAS,CAACH,qBAAqB,EAAEE,mBAAmB,CAAC;EACzF;;EAEA;EACA;EACA;EACA,IAAME,WAAW,GAAGR,iBAAiB,CAACG,OAAO,CAACV,wBAAwB,CAAC;EACvE,IAAIe,WAAW,GAAG,CAAC,EAAE;IACpBR,iBAAiB,GAAGA,iBAAiB,CAACO,SAAS,CAAC,CAAC,EAAEC,WAAW,CAAC;EAChE;EACA;EACA;EACA;EACA;EACA;;EAEA,IAAIR,iBAAiB,KAAK,EAAE,EAAE;IAC7B,OAAOA,iBAAiB;EACzB;AACD","ignoreList":[]}

View File

@@ -0,0 +1,116 @@
import extractNationalNumberFromPossiblyIncompleteNumber from './extractNationalNumberFromPossiblyIncompleteNumber.js';
import matchesEntirely from './matchesEntirely.js';
import checkNumberLength from './checkNumberLength.js';
import getCountryByCallingCode from './getCountryByCallingCode.js';
/**
* Strips national prefix and carrier code from a complete phone number.
* The difference from the non-"FromCompleteNumber" function is that
* it won't extract national prefix if the resultant number is too short
* to be a complete number for the selected phone numbering plan.
* @param {string} number — Complete phone number digits.
* @param {string?} country — Country, if known.
* @param {Metadata} metadata — Metadata with a phone numbering plan selected.
* @return {object} `{ nationalNumber: string, carrierCode: string? }`.
*/
export default function extractNationalNumber(number, country, metadata) {
// Parsing national prefixes and carrier codes
// is only required for local phone numbers
// but some people don't understand that
// and sometimes write international phone numbers
// with national prefixes (or maybe even carrier codes).
// http://ucken.blogspot.ru/2016/03/trunk-prefixes-in-skype4b.html
// Google's original library forgives such mistakes
// and so does this library, because it has been requested:
// https://github.com/catamphetamine/libphonenumber-js/issues/127
var _extractNationalNumbe = extractNationalNumberFromPossiblyIncompleteNumber(number, metadata),
carrierCode = _extractNationalNumbe.carrierCode,
nationalNumber = _extractNationalNumbe.nationalNumber;
if (nationalNumber !== number) {
if (!shouldHaveExtractedNationalPrefix(number, nationalNumber, metadata)) {
// Don't strip the national prefix.
return {
nationalNumber: number
};
}
// Check the national (significant) number length after extracting national prefix and carrier code.
// Legacy generated metadata (before `1.0.18`) didn't support the "possible lengths" feature.
if (metadata.numberingPlan.possibleLengths()) {
// If an exact `country` is not specified, attempt to detect it from the assumed national number.
if (!country) {
country = getCountryByCallingCode(metadata.numberingPlan.callingCode(), {
nationalNumber: nationalNumber,
metadata: metadata
});
}
// The number remaining after stripping the national prefix and carrier code
// should be long enough to have a possible length for the country.
// Otherwise, don't strip the national prefix and carrier code,
// since the original number could be a valid number.
// This check has been copy-pasted "as is" from Google's original library:
// https://github.com/google/libphonenumber/blob/876268eb1ad6cdc1b7b5bef17fc5e43052702d57/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java#L3236-L3250
// It doesn't check for the "possibility" of the original `number`.
// I guess it's fine not checking that one. It works as is anyway.
if (!isPossibleIncompleteNationalNumber(nationalNumber, country, metadata)) {
// Don't strip the national prefix.
return {
nationalNumber: number
};
}
}
}
return {
nationalNumber: nationalNumber,
carrierCode: carrierCode
};
}
// In some countries, the same digit could be a national prefix
// or a leading digit of a valid phone number.
// For example, in Russia, national prefix is `8`,
// and also `800 555 35 35` is a valid number
// in which `8` is not a national prefix, but the first digit
// of a national (significant) number.
// Same's with Belarus:
// `82004910060` is a valid national (significant) number,
// but `2004910060` is not.
// To support such cases (to prevent the code from always stripping
// national prefix), a condition is imposed: a national prefix
// is not extracted when the original number is "viable" and the
// resultant number is not, a "viable" national number being the one
// that matches `national_number_pattern`.
function shouldHaveExtractedNationalPrefix(nationalNumberBefore, nationalNumberAfter, metadata) {
// The equivalent in Google's code is:
// https://github.com/google/libphonenumber/blob/e326fa1fc4283bb05eb35cb3c15c18f98a31af33/java/libphonenumber/src/com/google/i18n/phonenumbers/PhoneNumberUtil.java#L2969-L3004
if (matchesEntirely(nationalNumberBefore, metadata.nationalNumberPattern()) && !matchesEntirely(nationalNumberAfter, metadata.nationalNumberPattern())) {
return false;
}
// This "is possible" national number (length) check has been commented out
// because it's superceded by the (effectively) same check done in the
// `extractNationalNumber()` function after it calls `shouldHaveExtractedNationalPrefix()`.
// In other words, why run the same check twice if it could only be run once.
// // Check the national (significant) number length after extracting national prefix and carrier code.
// // Fixes a minor "weird behavior" bug: https://gitlab.com/catamphetamine/libphonenumber-js/-/issues/57
// // (Legacy generated metadata (before `1.0.18`) didn't support the "possible lengths" feature).
// if (metadata.possibleLengths()) {
// if (isPossibleIncompleteNationalNumber(nationalNumberBefore, metadata) &&
// !isPossibleIncompleteNationalNumber(nationalNumberAfter, metadata)) {
// return false
// }
// }
return true;
}
function isPossibleIncompleteNationalNumber(nationalNumber, country, metadata) {
switch (checkNumberLength(nationalNumber, country, metadata)) {
case 'TOO_SHORT':
case 'INVALID_LENGTH':
// This library ignores "local-only" phone numbers (for simplicity).
// See the readme for more info on what are "local-only" phone numbers.
// case 'IS_POSSIBLE_LOCAL_ONLY':
return false;
default:
return true;
}
}
//# sourceMappingURL=extractNationalNumber.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,22 @@
import extractNationalNumber from './extractNationalNumber.js';
import Metadata from '../metadata.js';
import oldMetadata from '../../test/metadata/1.0.0/metadata.min.json' with { type: 'json' };
describe('extractNationalNumber', function () {
it('should extract a national number when using old metadata (no `country` or `defaultCountry` specified)', function () {
var _oldMetadata = new Metadata(oldMetadata);
_oldMetadata.selectNumberingPlan('RU');
expect(extractNationalNumber('88005553535', undefined, _oldMetadata)).to.deep.equal({
nationalNumber: '8005553535',
carrierCode: undefined
});
});
it('should extract a national number when using old metadata (`country` is specified)', function () {
var _oldMetadata = new Metadata(oldMetadata);
_oldMetadata.selectNumberingPlan('RU');
expect(extractNationalNumber('88005553535', 'RU', _oldMetadata)).to.deep.equal({
nationalNumber: '8005553535',
carrierCode: undefined
});
});
});
//# sourceMappingURL=extractNationalNumber.test.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"extractNationalNumber.test.js","names":["extractNationalNumber","Metadata","oldMetadata","type","describe","it","_oldMetadata","selectNumberingPlan","expect","undefined","to","deep","equal","nationalNumber","carrierCode"],"sources":["../../source/helpers/extractNationalNumber.test.js"],"sourcesContent":["import extractNationalNumber from './extractNationalNumber.js'\r\n\r\nimport Metadata from '../metadata.js'\r\nimport oldMetadata from '../../test/metadata/1.0.0/metadata.min.json' with { type: 'json' }\r\n\r\ndescribe('extractNationalNumber', function() {\r\n\tit('should extract a national number when using old metadata (no `country` or `defaultCountry` specified)', function() {\r\n\t\tconst _oldMetadata = new Metadata(oldMetadata)\r\n\t\t_oldMetadata.selectNumberingPlan('RU')\r\n\t\texpect(extractNationalNumber('88005553535', undefined, _oldMetadata)).to.deep.equal({\r\n\t\t\tnationalNumber: '8005553535',\r\n\t\t\tcarrierCode: undefined\r\n\t\t})\r\n\t})\r\n\r\n\tit('should extract a national number when using old metadata (`country` is specified)', function() {\r\n\t\tconst _oldMetadata = new Metadata(oldMetadata)\r\n\t\t_oldMetadata.selectNumberingPlan('RU')\r\n\t\texpect(extractNationalNumber('88005553535', 'RU', _oldMetadata)).to.deep.equal({\r\n\t\t\tnationalNumber: '8005553535',\r\n\t\t\tcarrierCode: undefined\r\n\t\t})\r\n\t})\r\n})"],"mappings":"AAAA,OAAOA,qBAAqB,MAAM,4BAA4B;AAE9D,OAAOC,QAAQ,MAAM,gBAAgB;AACrC,OAAOC,WAAW,MAAM,6CAA6C,QAAQC,IAAI,EAAE,MAAM;AAEzFC,QAAQ,CAAC,uBAAuB,EAAE,YAAW;EAC5CC,EAAE,CAAC,uGAAuG,EAAE,YAAW;IACtH,IAAMC,YAAY,GAAG,IAAIL,QAAQ,CAACC,WAAW,CAAC;IAC9CI,YAAY,CAACC,mBAAmB,CAAC,IAAI,CAAC;IACtCC,MAAM,CAACR,qBAAqB,CAAC,aAAa,EAAES,SAAS,EAAEH,YAAY,CAAC,CAAC,CAACI,EAAE,CAACC,IAAI,CAACC,KAAK,CAAC;MACnFC,cAAc,EAAE,YAAY;MAC5BC,WAAW,EAAEL;IACd,CAAC,CAAC;EACH,CAAC,CAAC;EAEFJ,EAAE,CAAC,mFAAmF,EAAE,YAAW;IAClG,IAAMC,YAAY,GAAG,IAAIL,QAAQ,CAACC,WAAW,CAAC;IAC9CI,YAAY,CAACC,mBAAmB,CAAC,IAAI,CAAC;IACtCC,MAAM,CAACR,qBAAqB,CAAC,aAAa,EAAE,IAAI,EAAEM,YAAY,CAAC,CAAC,CAACI,EAAE,CAACC,IAAI,CAACC,KAAK,CAAC;MAC9EC,cAAc,EAAE,YAAY;MAC5BC,WAAW,EAAEL;IACd,CAAC,CAAC;EACH,CAAC,CAAC;AACH,CAAC,CAAC","ignoreList":[]}

View File

@@ -0,0 +1,102 @@
/**
* Strips any national prefix (such as 0, 1) present in a
* (possibly incomplete) number provided.
* "Carrier codes" are only used in Colombia and Brazil,
* and only when dialing within those countries from a mobile phone to a fixed line number.
* Sometimes it won't actually strip national prefix
* and will instead prepend some digits to the `number`:
* for example, when number `2345678` is passed with `VI` country selected,
* it will return `{ number: "3402345678" }`, because `340` area code is prepended.
* @param {string} number — National number digits.
* @param {object} metadata — Metadata with country selected.
* @return {object} `{ nationalNumber: string, nationalPrefix: string? carrierCode: string? }`. Even if a national prefix was extracted, it's not necessarily present in the returned object, so don't rely on its presence in the returned object in order to find out whether a national prefix has been extracted or not.
*/
export default function extractNationalNumberFromPossiblyIncompleteNumber(number, metadata) {
if (number && metadata.numberingPlan.nationalPrefixForParsing()) {
// See METADATA.md for the description of
// `national_prefix_for_parsing` and `national_prefix_transform_rule`.
// Attempt to parse the first digits as a national prefix.
var prefixPattern = new RegExp('^(?:' + metadata.numberingPlan.nationalPrefixForParsing() + ')');
var prefixMatch = prefixPattern.exec(number);
if (prefixMatch) {
var nationalNumber;
var carrierCode;
// https://gitlab.com/catamphetamine/libphonenumber-js/-/blob/master/METADATA.md#national_prefix_for_parsing--national_prefix_transform_rule
// If a `national_prefix_for_parsing` has any "capturing groups"
// then it means that the national (significant) number is equal to
// those "capturing groups" transformed via `national_prefix_transform_rule`,
// and nothing could be said about the actual national prefix:
// what is it and was it even there.
// If a `national_prefix_for_parsing` doesn't have any "capturing groups",
// then everything it matches is a national prefix.
// To determine whether `national_prefix_for_parsing` matched any
// "capturing groups", the value of the result of calling `.exec()`
// is looked at, and if it has non-undefined values where there're
// "capturing groups" in the regular expression, then it means
// that "capturing groups" have been matched.
// It's not possible to tell whether there'll be any "capturing gropus"
// before the matching process, because a `national_prefix_for_parsing`
// could exhibit both behaviors.
var capturedGroupsCount = prefixMatch.length - 1;
var hasCapturedGroups = capturedGroupsCount > 0 && prefixMatch[capturedGroupsCount];
if (metadata.nationalPrefixTransformRule() && hasCapturedGroups) {
nationalNumber = number.replace(prefixPattern, metadata.nationalPrefixTransformRule());
// If there's more than one captured group,
// then carrier code is the second one.
if (capturedGroupsCount > 1) {
carrierCode = prefixMatch[1];
}
}
// If there're no "capturing groups",
// or if there're "capturing groups" but no
// `national_prefix_transform_rule`,
// then just strip the national prefix from the number,
// and possibly a carrier code.
// Seems like there could be more.
else {
// `prefixBeforeNationalNumber` is the whole substring matched by
// the `national_prefix_for_parsing` regular expression.
// There seem to be no guarantees that it's just a national prefix.
// For example, if there's a carrier code, it's gonna be a
// part of `prefixBeforeNationalNumber` too.
var prefixBeforeNationalNumber = prefixMatch[0];
nationalNumber = number.slice(prefixBeforeNationalNumber.length);
// If there's at least one captured group,
// then carrier code is the first one.
if (hasCapturedGroups) {
carrierCode = prefixMatch[1];
}
}
// Tries to guess whether a national prefix was present in the input.
// This is not something copy-pasted from Google's library:
// they don't seem to have an equivalent for that.
// So this isn't an "officially approved" way of doing something like that.
// But since there seems no other existing method, this library uses it.
var nationalPrefix;
if (hasCapturedGroups) {
var possiblePositionOfTheFirstCapturedGroup = number.indexOf(prefixMatch[1]);
var possibleNationalPrefix = number.slice(0, possiblePositionOfTheFirstCapturedGroup);
// Example: an Argentinian (AR) phone number `0111523456789`.
// `prefixMatch[0]` is `01115`, and `$1` is `11`,
// and the rest of the phone number is `23456789`.
// The national number is transformed via `9$1` to `91123456789`.
// National prefix `0` is detected being present at the start.
// if (possibleNationalPrefix.indexOf(metadata.numberingPlan.nationalPrefix()) === 0) {
if (possibleNationalPrefix === metadata.numberingPlan.nationalPrefix()) {
nationalPrefix = metadata.numberingPlan.nationalPrefix();
}
} else {
nationalPrefix = prefixMatch[0];
}
return {
nationalNumber: nationalNumber,
nationalPrefix: nationalPrefix,
carrierCode: carrierCode
};
}
}
return {
nationalNumber: number
};
}
//# sourceMappingURL=extractNationalNumberFromPossiblyIncompleteNumber.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,15 @@
import Metadata from '../metadata.js';
import metadata from '../../metadata.min.json' with { type: 'json' };
import extractNationalNumberFromPossiblyIncompleteNumber from './extractNationalNumberFromPossiblyIncompleteNumber.js';
describe('extractNationalNumberFromPossiblyIncompleteNumber', function () {
it('should parse a carrier code when there is no national prefix transform rule', function () {
var meta = new Metadata(metadata);
meta.country('AU');
expect(extractNationalNumberFromPossiblyIncompleteNumber('18311800123', meta)).to.deep.equal({
nationalPrefix: undefined,
carrierCode: '1831',
nationalNumber: '1800123'
});
});
});
//# sourceMappingURL=extractNationalNumberFromPossiblyIncompleteNumber.test.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"extractNationalNumberFromPossiblyIncompleteNumber.test.js","names":["Metadata","metadata","type","extractNationalNumberFromPossiblyIncompleteNumber","describe","it","meta","country","expect","to","deep","equal","nationalPrefix","undefined","carrierCode","nationalNumber"],"sources":["../../source/helpers/extractNationalNumberFromPossiblyIncompleteNumber.test.js"],"sourcesContent":["import Metadata from '../metadata.js'\r\nimport metadata from '../../metadata.min.json' with { type: 'json' }\r\nimport extractNationalNumberFromPossiblyIncompleteNumber from './extractNationalNumberFromPossiblyIncompleteNumber.js'\r\n\r\ndescribe('extractNationalNumberFromPossiblyIncompleteNumber', () => {\r\n\tit('should parse a carrier code when there is no national prefix transform rule', () => {\r\n\t\tconst meta = new Metadata(metadata)\r\n\t\tmeta.country('AU')\r\n\t\texpect(extractNationalNumberFromPossiblyIncompleteNumber('18311800123', meta)).to.deep.equal({\r\n\t\t\tnationalPrefix: undefined,\r\n\t\t\tcarrierCode: '1831',\r\n\t\t\tnationalNumber: '1800123'\r\n\t\t})\r\n\t})\r\n})"],"mappings":"AAAA,OAAOA,QAAQ,MAAM,gBAAgB;AACrC,OAAOC,QAAQ,MAAM,yBAAyB,QAAQC,IAAI,EAAE,MAAM;AAClE,OAAOC,iDAAiD,MAAM,wDAAwD;AAEtHC,QAAQ,CAAC,mDAAmD,EAAE,YAAM;EACnEC,EAAE,CAAC,6EAA6E,EAAE,YAAM;IACvF,IAAMC,IAAI,GAAG,IAAIN,QAAQ,CAACC,QAAQ,CAAC;IACnCK,IAAI,CAACC,OAAO,CAAC,IAAI,CAAC;IAClBC,MAAM,CAACL,iDAAiD,CAAC,aAAa,EAAEG,IAAI,CAAC,CAAC,CAACG,EAAE,CAACC,IAAI,CAACC,KAAK,CAAC;MAC5FC,cAAc,EAAEC,SAAS;MACzBC,WAAW,EAAE,MAAM;MACnBC,cAAc,EAAE;IACjB,CAAC,CAAC;EACH,CAAC,CAAC;AACH,CAAC,CAAC","ignoreList":[]}

View File

@@ -0,0 +1,82 @@
// When phone numbers are written in `RFC3966` format — `"tel:+12133734253"` —
// they can have their "calling code" part written separately in a `phone-context` parameter.
// Example: `"tel:12133734253;phone-context=+1"`.
// This function parses the full phone number from the local number and the `phone-context`
// when the `phone-context` contains a `+` sign.
import { VALID_DIGITS
// PLUS_CHARS
} from '../constants.js';
export var PLUS_SIGN = '+';
var RFC3966_VISUAL_SEPARATOR_ = '[\\-\\.\\(\\)]?';
var RFC3966_PHONE_DIGIT_ = '(' + '[' + VALID_DIGITS + ']' + '|' + RFC3966_VISUAL_SEPARATOR_ + ')';
var RFC3966_GLOBAL_NUMBER_DIGITS_ = '^' + '\\' + PLUS_SIGN + RFC3966_PHONE_DIGIT_ + '*' + '[' + VALID_DIGITS + ']' + RFC3966_PHONE_DIGIT_ + '*' + '$';
/**
* Regular expression of valid global-number-digits for the phone-context
* parameter, following the syntax defined in RFC3966.
*/
var RFC3966_GLOBAL_NUMBER_DIGITS_PATTERN_ = new RegExp(RFC3966_GLOBAL_NUMBER_DIGITS_, 'g');
// In this port of Google's library, we don't accept alpha characters in phone numbers.
// const ALPHANUM_ = VALID_ALPHA_ + VALID_DIGITS
var ALPHANUM_ = VALID_DIGITS;
var RFC3966_DOMAINLABEL_ = '[' + ALPHANUM_ + ']+((\\-)*[' + ALPHANUM_ + '])*';
var VALID_ALPHA_ = 'a-zA-Z';
var RFC3966_TOPLABEL_ = '[' + VALID_ALPHA_ + ']+((\\-)*[' + ALPHANUM_ + '])*';
var RFC3966_DOMAINNAME_ = '^(' + RFC3966_DOMAINLABEL_ + '\\.)*' + RFC3966_TOPLABEL_ + '\\.?$';
/**
* Regular expression of valid domainname for the phone-context parameter,
* following the syntax defined in RFC3966.
*/
var RFC3966_DOMAINNAME_PATTERN_ = new RegExp(RFC3966_DOMAINNAME_, 'g');
export var RFC3966_PREFIX_ = 'tel:';
export var RFC3966_PHONE_CONTEXT_ = ';phone-context=';
export var RFC3966_ISDN_SUBADDRESS_ = ';isub=';
/**
* Extracts the value of the phone-context parameter of `numberToExtractFrom`,
* following the syntax defined in RFC3966.
*
* @param {string} numberToExtractFrom
* @return {string|null} the extracted string (possibly empty), or `null` if no phone-context parameter is found.
*/
export default function extractPhoneContext(numberToExtractFrom) {
var indexOfPhoneContext = numberToExtractFrom.indexOf(RFC3966_PHONE_CONTEXT_);
// If no phone-context parameter is present
if (indexOfPhoneContext < 0) {
return null;
}
var phoneContextStart = indexOfPhoneContext + RFC3966_PHONE_CONTEXT_.length;
// If phone-context parameter is empty
if (phoneContextStart >= numberToExtractFrom.length) {
return '';
}
var phoneContextEnd = numberToExtractFrom.indexOf(';', phoneContextStart);
// If phone-context is not the last parameter
if (phoneContextEnd >= 0) {
return numberToExtractFrom.substring(phoneContextStart, phoneContextEnd);
} else {
return numberToExtractFrom.substring(phoneContextStart);
}
}
/**
* Returns whether the value of phoneContext follows the syntax defined in RFC3966.
*
* @param {string|null} phoneContext
* @return {boolean}
*/
export function isPhoneContextValid(phoneContext) {
if (phoneContext === null) {
return true;
}
if (phoneContext.length === 0) {
return false;
}
// Does phone-context value match pattern of global-number-digits or domainname.
return RFC3966_GLOBAL_NUMBER_DIGITS_PATTERN_.test(phoneContext) || RFC3966_DOMAINNAME_PATTERN_.test(phoneContext);
}
//# sourceMappingURL=extractPhoneContext.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,66 @@
import parsePhoneNumber_ from '../parsePhoneNumber.js';
import PhoneNumber from '../PhoneNumber.js';
import metadata from '../../metadata.min.json' with { type: 'json' };
function parsePhoneNumber() {
for (var _len = arguments.length, parameters = new Array(_len), _key = 0; _key < _len; _key++) {
parameters[_key] = arguments[_key];
}
parameters.push(metadata);
return parsePhoneNumber_.apply(this, parameters);
}
describe('extractPhoneContext', function () {
it('should parse RFC 3966 phone number URIs', function () {
// context = ";phone-context=" descriptor
// descriptor = domainname / global-number-digits
var NZ_NUMBER = new PhoneNumber('64', '33316005', metadata);
// Valid global-phone-digits
expectPhoneNumbersToBeEqual(parsePhoneNumber('tel:033316005;phone-context=+64'), NZ_NUMBER);
expectPhoneNumbersToBeEqual(parsePhoneNumber('tel:033316005;phone-context=+64;{this isn\'t part of phone-context anymore!}'), NZ_NUMBER);
var nzFromPhoneContext = new PhoneNumber('64', '3033316005', metadata);
expectPhoneNumbersToBeEqual(parsePhoneNumber('tel:033316005;phone-context=+64-3'), nzFromPhoneContext);
var brFromPhoneContext = new PhoneNumber('55', '5033316005', metadata);
expectPhoneNumbersToBeEqual(parsePhoneNumber('tel:033316005;phone-context=+(555)'), brFromPhoneContext);
var usFromPhoneContext = new PhoneNumber('1', '23033316005', metadata);
expectPhoneNumbersToBeEqual(parsePhoneNumber('tel:033316005;phone-context=+-1-2.3()'), usFromPhoneContext);
// Valid domainname.
expectPhoneNumbersToBeEqual(parsePhoneNumber('tel:033316005;phone-context=abc.nz', 'NZ'), NZ_NUMBER);
expectPhoneNumbersToBeEqual(parsePhoneNumber('tel:033316005;phone-context=www.PHONE-numb3r.com', 'NZ'), NZ_NUMBER);
expectPhoneNumbersToBeEqual(parsePhoneNumber('tel:033316005;phone-context=a', 'NZ'), NZ_NUMBER);
expectPhoneNumbersToBeEqual(parsePhoneNumber('tel:033316005;phone-context=3phone.J.', 'NZ'), NZ_NUMBER);
expectPhoneNumbersToBeEqual(parsePhoneNumber('tel:033316005;phone-context=a--z', 'NZ'), NZ_NUMBER);
// Should strip ISDN subaddress.
expectPhoneNumbersToBeEqual(parsePhoneNumber('tel:033316005;isub=/@;phone-context=+64', 'NZ'), NZ_NUMBER);
// // Should support incorrectly-written RFC 3966 phone numbers:
// // the ones written without a `tel:` prefix.
// expectPhoneNumbersToBeEqual(
// parsePhoneNumber('033316005;phone-context=+64', 'NZ'),
// NZ_NUMBER
// )
// Invalid descriptor.
expectToThrowForInvalidPhoneContext('tel:033316005;phone-context=');
expectToThrowForInvalidPhoneContext('tel:033316005;phone-context=+');
expectToThrowForInvalidPhoneContext('tel:033316005;phone-context=64');
expectToThrowForInvalidPhoneContext('tel:033316005;phone-context=++64');
expectToThrowForInvalidPhoneContext('tel:033316005;phone-context=+abc');
expectToThrowForInvalidPhoneContext('tel:033316005;phone-context=.');
expectToThrowForInvalidPhoneContext('tel:033316005;phone-context=3phone');
expectToThrowForInvalidPhoneContext('tel:033316005;phone-context=a-.nz');
expectToThrowForInvalidPhoneContext('tel:033316005;phone-context=a{b}c');
});
});
function expectToThrowForInvalidPhoneContext(string) {
expect(parsePhoneNumber(string)).to.be.undefined;
}
function expectPhoneNumbersToBeEqual(phoneNumber1, phoneNumber2) {
if (!phoneNumber1 || !phoneNumber2) {
return false;
}
return phoneNumber1.number === phoneNumber2.number && phoneNumber1.ext === phoneNumber2.ext;
}
//# sourceMappingURL=extractPhoneContext.test.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,33 @@
import applyInternationalSeparatorStyle from './applyInternationalSeparatorStyle.js';
// This was originally set to $1 but there are some countries for which the
// first group is not used in the national pattern (e.g. Argentina) so the $1
// group does not match correctly. Therefore, we use `\d`, so that the first
// group actually used in the pattern will be matched.
export var FIRST_GROUP_PATTERN = /(\$\d)/;
export default function formatNationalNumberUsingFormat(number, format, _ref) {
var useInternationalFormat = _ref.useInternationalFormat,
withNationalPrefix = _ref.withNationalPrefix,
carrierCode = _ref.carrierCode,
metadata = _ref.metadata;
var formattedNumber = number.replace(new RegExp(format.pattern()), useInternationalFormat ? format.internationalFormat() :
// This library doesn't use `domestic_carrier_code_formatting_rule`,
// because that one is only used when formatting phone numbers
// for dialing from a mobile phone, and this is not a dialing library.
// carrierCode && format.domesticCarrierCodeFormattingRule()
// // First, replace the $CC in the formatting rule with the desired carrier code.
// // Then, replace the $FG in the formatting rule with the first group
// // and the carrier code combined in the appropriate way.
// ? format.format().replace(FIRST_GROUP_PATTERN, format.domesticCarrierCodeFormattingRule().replace('$CC', carrierCode))
// : (
// withNationalPrefix && format.nationalPrefixFormattingRule()
// ? format.format().replace(FIRST_GROUP_PATTERN, format.nationalPrefixFormattingRule())
// : format.format()
// )
withNationalPrefix && format.nationalPrefixFormattingRule() ? format.format().replace(FIRST_GROUP_PATTERN, format.nationalPrefixFormattingRule()) : format.format());
if (useInternationalFormat) {
return applyInternationalSeparatorStyle(formattedNumber);
}
return formattedNumber;
}
//# sourceMappingURL=formatNationalNumberUsingFormat.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"formatNationalNumberUsingFormat.js","names":["applyInternationalSeparatorStyle","FIRST_GROUP_PATTERN","formatNationalNumberUsingFormat","number","format","_ref","useInternationalFormat","withNationalPrefix","carrierCode","metadata","formattedNumber","replace","RegExp","pattern","internationalFormat","nationalPrefixFormattingRule"],"sources":["../../source/helpers/formatNationalNumberUsingFormat.js"],"sourcesContent":["import applyInternationalSeparatorStyle from './applyInternationalSeparatorStyle.js'\r\n\r\n// This was originally set to $1 but there are some countries for which the\r\n// first group is not used in the national pattern (e.g. Argentina) so the $1\r\n// group does not match correctly. Therefore, we use `\\d`, so that the first\r\n// group actually used in the pattern will be matched.\r\nexport const FIRST_GROUP_PATTERN = /(\\$\\d)/\r\n\r\nexport default function formatNationalNumberUsingFormat(\r\n\tnumber,\r\n\tformat,\r\n\t{\r\n\t\tuseInternationalFormat,\r\n\t\twithNationalPrefix,\r\n\t\tcarrierCode,\r\n\t\tmetadata\r\n\t}\r\n) {\r\n\tconst formattedNumber = number.replace(\r\n\t\tnew RegExp(format.pattern()),\r\n\t\tuseInternationalFormat\r\n\t\t\t? format.internationalFormat()\r\n\t\t\t: (\r\n\t\t\t\t// This library doesn't use `domestic_carrier_code_formatting_rule`,\r\n\t\t\t\t// because that one is only used when formatting phone numbers\r\n\t\t\t\t// for dialing from a mobile phone, and this is not a dialing library.\r\n\t\t\t\t// carrierCode && format.domesticCarrierCodeFormattingRule()\r\n\t\t\t\t// \t// First, replace the $CC in the formatting rule with the desired carrier code.\r\n\t\t\t\t// \t// Then, replace the $FG in the formatting rule with the first group\r\n\t\t\t\t// \t// and the carrier code combined in the appropriate way.\r\n\t\t\t\t// \t? format.format().replace(FIRST_GROUP_PATTERN, format.domesticCarrierCodeFormattingRule().replace('$CC', carrierCode))\r\n\t\t\t\t// \t: (\r\n\t\t\t\t// \t\twithNationalPrefix && format.nationalPrefixFormattingRule()\r\n\t\t\t\t// \t\t\t? format.format().replace(FIRST_GROUP_PATTERN, format.nationalPrefixFormattingRule())\r\n\t\t\t\t// \t\t\t: format.format()\r\n\t\t\t\t// \t)\r\n\t\t\t\twithNationalPrefix && format.nationalPrefixFormattingRule()\r\n\t\t\t\t\t? format.format().replace(FIRST_GROUP_PATTERN, format.nationalPrefixFormattingRule())\r\n\t\t\t\t\t: format.format()\r\n\t\t\t)\r\n\t)\r\n\tif (useInternationalFormat) {\r\n\t\treturn applyInternationalSeparatorStyle(formattedNumber)\r\n\t}\r\n\treturn formattedNumber\r\n}"],"mappings":"AAAA,OAAOA,gCAAgC,MAAM,uCAAuC;;AAEpF;AACA;AACA;AACA;AACA,OAAO,IAAMC,mBAAmB,GAAG,QAAQ;AAE3C,eAAe,SAASC,+BAA+BA,CACtDC,MAAM,EACNC,MAAM,EAAAC,IAAA,EAOL;EAAA,IALAC,sBAAsB,GAAAD,IAAA,CAAtBC,sBAAsB;IACtBC,kBAAkB,GAAAF,IAAA,CAAlBE,kBAAkB;IAClBC,WAAW,GAAAH,IAAA,CAAXG,WAAW;IACXC,QAAQ,GAAAJ,IAAA,CAARI,QAAQ;EAGT,IAAMC,eAAe,GAAGP,MAAM,CAACQ,OAAO,CACrC,IAAIC,MAAM,CAACR,MAAM,CAACS,OAAO,CAAC,CAAC,CAAC,EAC5BP,sBAAsB,GACnBF,MAAM,CAACU,mBAAmB,CAAC,CAAC;EAE7B;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACAP,kBAAkB,IAAIH,MAAM,CAACW,4BAA4B,CAAC,CAAC,GACxDX,MAAM,CAACA,MAAM,CAAC,CAAC,CAACO,OAAO,CAACV,mBAAmB,EAAEG,MAAM,CAACW,4BAA4B,CAAC,CAAC,CAAC,GACnFX,MAAM,CAACA,MAAM,CAAC,CAEpB,CAAC;EACD,IAAIE,sBAAsB,EAAE;IAC3B,OAAON,gCAAgC,CAACU,eAAe,CAAC;EACzD;EACA,OAAOA,eAAe;AACvB","ignoreList":[]}

View File

@@ -0,0 +1,29 @@
import getCountryByNationalNumber from './getCountryByNationalNumber.js';
var USE_NON_GEOGRAPHIC_COUNTRY_CODE = false;
// Returns the exact country for the `nationalNumber`
// that belongs to the specified "country calling code".
export default function getCountryByCallingCode(callingCode, _ref) {
var nationalPhoneNumber = _ref.nationalNumber,
metadata = _ref.metadata;
/* istanbul ignore if */
if (USE_NON_GEOGRAPHIC_COUNTRY_CODE) {
if (metadata.isNonGeographicCallingCode(callingCode)) {
return '001';
}
}
var possibleCountries = metadata.getCountryCodesForCallingCode(callingCode);
if (!possibleCountries) {
return;
}
// If there's just one country corresponding to the country code,
// then just return it, without further phone number digits validation.
if (possibleCountries.length === 1) {
return possibleCountries[0];
}
return getCountryByNationalNumber(nationalPhoneNumber, {
countries: possibleCountries,
metadata: metadata.metadata
});
}
//# sourceMappingURL=getCountryByCallingCode.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"getCountryByCallingCode.js","names":["getCountryByNationalNumber","USE_NON_GEOGRAPHIC_COUNTRY_CODE","getCountryByCallingCode","callingCode","_ref","nationalPhoneNumber","nationalNumber","metadata","isNonGeographicCallingCode","possibleCountries","getCountryCodesForCallingCode","length","countries"],"sources":["../../source/helpers/getCountryByCallingCode.js"],"sourcesContent":["import getCountryByNationalNumber from './getCountryByNationalNumber.js'\r\n\r\nconst USE_NON_GEOGRAPHIC_COUNTRY_CODE = false\r\n\r\n// Returns the exact country for the `nationalNumber`\r\n// that belongs to the specified \"country calling code\".\r\nexport default function getCountryByCallingCode(callingCode, {\r\n\tnationalNumber: nationalPhoneNumber,\r\n\tmetadata\r\n}) {\r\n\t/* istanbul ignore if */\r\n\tif (USE_NON_GEOGRAPHIC_COUNTRY_CODE) {\r\n\t\tif (metadata.isNonGeographicCallingCode(callingCode)) {\r\n\t\t\treturn '001'\r\n\t\t}\r\n\t}\r\n\tconst possibleCountries = metadata.getCountryCodesForCallingCode(callingCode)\r\n\tif (!possibleCountries) {\r\n\t\treturn\r\n\t}\r\n\t// If there's just one country corresponding to the country code,\r\n\t// then just return it, without further phone number digits validation.\r\n\tif (possibleCountries.length === 1) {\r\n\t\treturn possibleCountries[0]\r\n\t}\r\n\treturn getCountryByNationalNumber(nationalPhoneNumber, {\r\n\t\tcountries: possibleCountries,\r\n\t\tmetadata: metadata.metadata\r\n\t})\r\n}"],"mappings":"AAAA,OAAOA,0BAA0B,MAAM,iCAAiC;AAExE,IAAMC,+BAA+B,GAAG,KAAK;;AAE7C;AACA;AACA,eAAe,SAASC,uBAAuBA,CAACC,WAAW,EAAAC,IAAA,EAGxD;EAAA,IAFcC,mBAAmB,GAAAD,IAAA,CAAnCE,cAAc;IACdC,QAAQ,GAAAH,IAAA,CAARG,QAAQ;EAER;EACA,IAAIN,+BAA+B,EAAE;IACpC,IAAIM,QAAQ,CAACC,0BAA0B,CAACL,WAAW,CAAC,EAAE;MACrD,OAAO,KAAK;IACb;EACD;EACA,IAAMM,iBAAiB,GAAGF,QAAQ,CAACG,6BAA6B,CAACP,WAAW,CAAC;EAC7E,IAAI,CAACM,iBAAiB,EAAE;IACvB;EACD;EACA;EACA;EACA,IAAIA,iBAAiB,CAACE,MAAM,KAAK,CAAC,EAAE;IACnC,OAAOF,iBAAiB,CAAC,CAAC,CAAC;EAC5B;EACA,OAAOT,0BAA0B,CAACK,mBAAmB,EAAE;IACtDO,SAAS,EAAEH,iBAAiB;IAC5BF,QAAQ,EAAEA,QAAQ,CAACA;EACpB,CAAC,CAAC;AACH","ignoreList":[]}

View File

@@ -0,0 +1,79 @@
function _createForOfIteratorHelperLoose(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (t) return (t = t.call(r)).next.bind(t); if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var o = 0; return function () { return o >= r.length ? { done: !0 } : { done: !1, value: r[o++] }; }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
import Metadata from '../metadata.js';
import getNumberType from './getNumberType.js';
// Returns the exact country that the `nationalPhoneNumber` belongs to
// in cases of ambiguity, i.e. when multiple countries share the same "country calling code".
export default function getCountryByNationalNumber(nationalPhoneNumber, _ref) {
var countries = _ref.countries,
metadata = _ref.metadata;
// Re-create `metadata` because it will be selecting a `country`.
metadata = new Metadata(metadata);
// const matchingCountries = []
for (var _iterator = _createForOfIteratorHelperLoose(countries), _step; !(_step = _iterator()).done;) {
var country = _step.value;
metadata.selectNumberingPlan(country);
// "Leading digits" patterns are only defined for about 20% of all countries.
// By definition, matching "leading digits" is a sufficient but not a necessary
// condition for a phone number to belong to a country.
// The point of "leading digits" check is that it's the fastest one to get a match.
// https://gitlab.com/catamphetamine/libphonenumber-js/blob/master/METADATA.md#leading_digits
// I'd suppose that "leading digits" patterns are mutually exclusive for different countries
// because of the intended use of that feature.
if (metadata.leadingDigits()) {
if (nationalPhoneNumber && nationalPhoneNumber.search(metadata.leadingDigits()) === 0) {
return country;
}
}
// Else perform full validation with all of those
// fixed-line/mobile/etc regular expressions.
else if (getNumberType({
phone: nationalPhoneNumber,
country: country
}, undefined, metadata.metadata)) {
// When multiple countries share the same "country calling code",
// type patterns aren't guaranteed to be unique among them.
// For example, both `US` and `CA` have the same pattern for `toll_free` numbers.
// https://gitlab.com/catamphetamine/libphonenumber-js/-/issues/103#note_1417147572
//
// That means that this `if` condition could be `true` for multiple countries from the list.
// Currently, it just returns the first one, which is also the "main" country for the "country calling code".
// In an example with `toll_free` numbers above, `"US"` would be returned even though
// it could as well be `"CA"`.
//
// There was also a time when this attempted to be overly smart
// and kept track of all such multiple matching countries
// and then picked the one that matched the `defaultCountry`, if provided.
// For example, with `toll_free` numbers above, and with `defaultCountry: "CA"`,
// it would've returned `"CA"` instead of `"US"`.
// Later it turned out that such "overly smart" behavior turned out to be just confusing,
// so this "overly smart" country detection was reverted to returning the "main" country
// for the "country calling code".
// https://gitlab.com/catamphetamine/libphonenumber-js/-/issues/154
//
return country;
//
// The "overly smart" behavior code:
//
// if (defaultCountry) {
// if (country === defaultCountry) {
// return country
// } else {
// matchingCountries.push(country)
// }
// } else {
// return country
// }
}
}
// // Return the first ("main") one of the `matchingCountries`.
// if (matchingCountries.length > 0) {
// return matchingCountries[0]
// }
}
//# sourceMappingURL=getCountryByNationalNumber.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"getCountryByNationalNumber.js","names":["Metadata","getNumberType","getCountryByNationalNumber","nationalPhoneNumber","_ref","countries","metadata","_iterator","_createForOfIteratorHelperLoose","_step","done","country","value","selectNumberingPlan","leadingDigits","search","phone","undefined"],"sources":["../../source/helpers/getCountryByNationalNumber.js"],"sourcesContent":["import Metadata from '../metadata.js'\r\nimport getNumberType from './getNumberType.js'\r\n\r\n// Returns the exact country that the `nationalPhoneNumber` belongs to\r\n// in cases of ambiguity, i.e. when multiple countries share the same \"country calling code\".\r\nexport default function getCountryByNationalNumber(nationalPhoneNumber, {\r\n\tcountries,\r\n\tmetadata\r\n}) {\r\n\t// Re-create `metadata` because it will be selecting a `country`.\r\n\tmetadata = new Metadata(metadata)\r\n\r\n\t// const matchingCountries = []\r\n\r\n\tfor (const country of countries) {\r\n\t\tmetadata.selectNumberingPlan(country)\r\n\t\t// \"Leading digits\" patterns are only defined for about 20% of all countries.\r\n\t\t// By definition, matching \"leading digits\" is a sufficient but not a necessary\r\n\t\t// condition for a phone number to belong to a country.\r\n\t\t// The point of \"leading digits\" check is that it's the fastest one to get a match.\r\n\t\t// https://gitlab.com/catamphetamine/libphonenumber-js/blob/master/METADATA.md#leading_digits\r\n\t\t// I'd suppose that \"leading digits\" patterns are mutually exclusive for different countries\r\n\t\t// because of the intended use of that feature.\r\n\t\tif (metadata.leadingDigits()) {\r\n\t\t\tif (nationalPhoneNumber &&\r\n\t\t\t\tnationalPhoneNumber.search(metadata.leadingDigits()) === 0) {\r\n\t\t\t\treturn country\r\n\t\t\t}\r\n\t\t}\r\n\t\t// Else perform full validation with all of those\r\n\t\t// fixed-line/mobile/etc regular expressions.\r\n\t\telse if (getNumberType({ phone: nationalPhoneNumber, country }, undefined, metadata.metadata)) {\r\n\t\t\t// When multiple countries share the same \"country calling code\",\r\n\t\t\t// type patterns aren't guaranteed to be unique among them.\r\n\t\t\t// For example, both `US` and `CA` have the same pattern for `toll_free` numbers.\r\n\t\t\t// https://gitlab.com/catamphetamine/libphonenumber-js/-/issues/103#note_1417147572\r\n\t\t\t//\r\n\t\t\t// That means that this `if` condition could be `true` for multiple countries from the list.\r\n\t\t\t// Currently, it just returns the first one, which is also the \"main\" country for the \"country calling code\".\r\n\t\t\t// In an example with `toll_free` numbers above, `\"US\"` would be returned even though\r\n\t\t\t// it could as well be `\"CA\"`.\r\n\t\t\t//\r\n\t\t\t// There was also a time when this attempted to be overly smart\r\n\t\t\t// and kept track of all such multiple matching countries\r\n\t\t\t// and then picked the one that matched the `defaultCountry`, if provided.\r\n\t\t\t// For example, with `toll_free` numbers above, and with `defaultCountry: \"CA\"`,\r\n\t\t\t// it would've returned `\"CA\"` instead of `\"US\"`.\r\n\t\t\t// Later it turned out that such \"overly smart\" behavior turned out to be just confusing,\r\n\t\t\t// so this \"overly smart\" country detection was reverted to returning the \"main\" country\r\n\t\t\t// for the \"country calling code\".\r\n\t\t\t// https://gitlab.com/catamphetamine/libphonenumber-js/-/issues/154\r\n\t\t\t//\r\n\t\t\treturn country\r\n\t\t\t//\r\n\t\t\t// The \"overly smart\" behavior code:\r\n\t\t\t//\r\n\t\t\t// if (defaultCountry) {\r\n\t\t\t// \tif (country === defaultCountry) {\r\n\t\t\t// \t\treturn country\r\n\t\t\t// \t} else {\r\n\t\t\t// \t\tmatchingCountries.push(country)\r\n\t\t\t// \t}\r\n\t\t\t// } else {\r\n\t\t\t// \treturn country\r\n\t\t\t// }\r\n\t\t}\r\n\t}\r\n\r\n\t// // Return the first (\"main\") one of the `matchingCountries`.\r\n\t// if (matchingCountries.length > 0) {\r\n\t// \treturn matchingCountries[0]\r\n\t// }\r\n}"],"mappings":";;;AAAA,OAAOA,QAAQ,MAAM,gBAAgB;AACrC,OAAOC,aAAa,MAAM,oBAAoB;;AAE9C;AACA;AACA,eAAe,SAASC,0BAA0BA,CAACC,mBAAmB,EAAAC,IAAA,EAGnE;EAAA,IAFFC,SAAS,GAAAD,IAAA,CAATC,SAAS;IACTC,QAAQ,GAAAF,IAAA,CAARE,QAAQ;EAER;EACAA,QAAQ,GAAG,IAAIN,QAAQ,CAACM,QAAQ,CAAC;;EAEjC;;EAEA,SAAAC,SAAA,GAAAC,+BAAA,CAAsBH,SAAS,GAAAI,KAAA,IAAAA,KAAA,GAAAF,SAAA,IAAAG,IAAA,GAAE;IAAA,IAAtBC,OAAO,GAAAF,KAAA,CAAAG,KAAA;IACjBN,QAAQ,CAACO,mBAAmB,CAACF,OAAO,CAAC;IACrC;IACA;IACA;IACA;IACA;IACA;IACA;IACA,IAAIL,QAAQ,CAACQ,aAAa,CAAC,CAAC,EAAE;MAC7B,IAAIX,mBAAmB,IACtBA,mBAAmB,CAACY,MAAM,CAACT,QAAQ,CAACQ,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE;QAC5D,OAAOH,OAAO;MACf;IACD;IACA;IACA;IAAA,KACK,IAAIV,aAAa,CAAC;MAAEe,KAAK,EAAEb,mBAAmB;MAAEQ,OAAO,EAAPA;IAAQ,CAAC,EAAEM,SAAS,EAAEX,QAAQ,CAACA,QAAQ,CAAC,EAAE;MAC9F;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA,OAAOK,OAAO;MACd;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;IACD;EACD;;EAEA;EACA;EACA;EACA;AACD","ignoreList":[]}

View File

@@ -0,0 +1,26 @@
import Metadata from '../metadata.js';
/**
* Pattern that makes it easy to distinguish whether a region has a single
* international dialing prefix or not. If a region has a single international
* prefix (e.g. 011 in USA), it will be represented as a string that contains
* a sequence of ASCII digits, and possibly a tilde, which signals waiting for
* the tone. If there are multiple available international prefixes in a
* region, they will be represented as a regex string that always contains one
* or more characters that are not ASCII digits or a tilde.
*/
var SINGLE_IDD_PREFIX_REG_EXP = /^[\d]+(?:[~\u2053\u223C\uFF5E][\d]+)?$/;
// If the `country` supports IDD calling, it returns a preferred IDD prefix.
// If the `country` doesn't support IDD calling, it returns `undefined`.
export default function getIddPrefix(country, callingCode, metadata) {
var countryMetadata = new Metadata(metadata);
countryMetadata.selectNumberingPlan(country, callingCode);
if (countryMetadata.defaultIDDPrefix()) {
return countryMetadata.defaultIDDPrefix();
}
if (SINGLE_IDD_PREFIX_REG_EXP.test(countryMetadata.IDDPrefix())) {
return countryMetadata.IDDPrefix();
}
}
//# sourceMappingURL=getIddPrefix.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"getIddPrefix.js","names":["Metadata","SINGLE_IDD_PREFIX_REG_EXP","getIddPrefix","country","callingCode","metadata","countryMetadata","selectNumberingPlan","defaultIDDPrefix","test","IDDPrefix"],"sources":["../../source/helpers/getIddPrefix.js"],"sourcesContent":["import Metadata from '../metadata.js'\r\n\r\n/**\r\n * Pattern that makes it easy to distinguish whether a region has a single\r\n * international dialing prefix or not. If a region has a single international\r\n * prefix (e.g. 011 in USA), it will be represented as a string that contains\r\n * a sequence of ASCII digits, and possibly a tilde, which signals waiting for\r\n * the tone. If there are multiple available international prefixes in a\r\n * region, they will be represented as a regex string that always contains one\r\n * or more characters that are not ASCII digits or a tilde.\r\n */\r\nconst SINGLE_IDD_PREFIX_REG_EXP = /^[\\d]+(?:[~\\u2053\\u223C\\uFF5E][\\d]+)?$/\r\n\r\n// If the `country` supports IDD calling, it returns a preferred IDD prefix.\r\n// If the `country` doesn't support IDD calling, it returns `undefined`.\r\nexport default function getIddPrefix(country, callingCode, metadata) {\r\n\tconst countryMetadata = new Metadata(metadata)\r\n\tcountryMetadata.selectNumberingPlan(country, callingCode)\r\n\tif (countryMetadata.defaultIDDPrefix()) {\r\n\t\treturn countryMetadata.defaultIDDPrefix()\r\n\t}\r\n\tif (SINGLE_IDD_PREFIX_REG_EXP.test(countryMetadata.IDDPrefix())) {\r\n\t\treturn countryMetadata.IDDPrefix()\r\n\t}\r\n}\r\n"],"mappings":"AAAA,OAAOA,QAAQ,MAAM,gBAAgB;;AAErC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAMC,yBAAyB,GAAG,wCAAwC;;AAE1E;AACA;AACA,eAAe,SAASC,YAAYA,CAACC,OAAO,EAAEC,WAAW,EAAEC,QAAQ,EAAE;EACpE,IAAMC,eAAe,GAAG,IAAIN,QAAQ,CAACK,QAAQ,CAAC;EAC9CC,eAAe,CAACC,mBAAmB,CAACJ,OAAO,EAAEC,WAAW,CAAC;EACzD,IAAIE,eAAe,CAACE,gBAAgB,CAAC,CAAC,EAAE;IACvC,OAAOF,eAAe,CAACE,gBAAgB,CAAC,CAAC;EAC1C;EACA,IAAIP,yBAAyB,CAACQ,IAAI,CAACH,eAAe,CAACI,SAAS,CAAC,CAAC,CAAC,EAAE;IAChE,OAAOJ,eAAe,CAACI,SAAS,CAAC,CAAC;EACnC;AACD","ignoreList":[]}

View File

@@ -0,0 +1,85 @@
function _createForOfIteratorHelperLoose(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (t) return (t = t.call(r)).next.bind(t); if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var o = 0; return function () { return o >= r.length ? { done: !0 } : { done: !1, value: r[o++] }; }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
import Metadata from '../metadata.js';
import matchesEntirely from './matchesEntirely.js';
var NON_FIXED_LINE_PHONE_TYPES = ['MOBILE', 'PREMIUM_RATE', 'TOLL_FREE', 'SHARED_COST', 'VOIP', 'PERSONAL_NUMBER', 'PAGER', 'UAN', 'VOICEMAIL'];
// Finds out national phone number type (fixed line, mobile, etc)
export default function getNumberType(input, options, metadata) {
// If assigning the `{}` default value is moved to the arguments above,
// code coverage would decrease for some weird reason.
options = options || {};
// When `parse()` returns an empty object — `{}` —
// that means that the phone number is malformed,
// so it can't possibly be valid.
if (!input.country && !input.countryCallingCode) {
return;
}
metadata = new Metadata(metadata);
metadata.selectNumberingPlan(input.country, input.countryCallingCode);
var nationalNumber = options.v2 ? input.nationalNumber : input.phone;
// The following is copy-pasted from the original function:
// https://github.com/googlei18n/libphonenumber/blob/3ea547d4fbaa2d0b67588904dfa5d3f2557c27ff/javascript/i18n/phonenumbers/phonenumberutil.js#L2835
// Is this national number even valid for this country
if (!matchesEntirely(nationalNumber, metadata.nationalNumberPattern())) {
return;
}
// Is it fixed line number
if (isNumberTypeEqualTo(nationalNumber, 'FIXED_LINE', metadata)) {
// Because duplicate regular expressions are removed
// to reduce metadata size, if "mobile" pattern is ""
// then it means it was removed due to being a duplicate of the fixed-line pattern.
//
if (metadata.type('MOBILE') && metadata.type('MOBILE').pattern() === '') {
return 'FIXED_LINE_OR_MOBILE';
}
// `MOBILE` type pattern isn't included if it matched `FIXED_LINE` one.
// For example, for "US" country.
// Old metadata (< `1.0.18`) had a specific "types" data structure
// that happened to be `undefined` for `MOBILE` in that case.
// Newer metadata (>= `1.0.18`) has another data structure that is
// not `undefined` for `MOBILE` in that case (it's just an empty array).
// So this `if` is just for backwards compatibility with old metadata.
if (!metadata.type('MOBILE')) {
return 'FIXED_LINE_OR_MOBILE';
}
// Check if the number happens to qualify as both fixed line and mobile.
// (no such country in the minimal metadata set)
/* istanbul ignore if */
if (isNumberTypeEqualTo(nationalNumber, 'MOBILE', metadata)) {
return 'FIXED_LINE_OR_MOBILE';
}
return 'FIXED_LINE';
}
for (var _iterator = _createForOfIteratorHelperLoose(NON_FIXED_LINE_PHONE_TYPES), _step; !(_step = _iterator()).done;) {
var type = _step.value;
if (isNumberTypeEqualTo(nationalNumber, type, metadata)) {
return type;
}
}
}
export function isNumberTypeEqualTo(nationalNumber, type, metadata) {
var typeDefinition = metadata.type(type);
if (!typeDefinition || !typeDefinition.pattern()) {
return false;
}
// Check if any possible number lengths are present;
// if so, we use them to avoid checking
// the validation pattern if they don't match.
// If they are absent, this means they match
// the general description, which we have
// already checked before a specific number type.
if (typeDefinition.possibleLengths() && typeDefinition.possibleLengths().indexOf(nationalNumber.length) < 0) {
return false;
}
return matchesEntirely(nationalNumber, typeDefinition.pattern());
}
//# sourceMappingURL=getNumberType.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,19 @@
import getNumberType from './getNumberType.js';
import oldMetadata from '../../test/metadata/1.0.0/metadata.min.json' with { type: 'json' };
import Metadata from '../metadata.js';
describe('getNumberType', function () {
it('should get number type when using old metadata', function () {
expect(getNumberType({
nationalNumber: '2133734253',
country: 'US'
}, {
v2: true
}, oldMetadata)).to.equal('FIXED_LINE_OR_MOBILE');
});
it('should return `undefined` when the phone number is a malformed one', function () {
expect(getNumberType({}, {
v2: true
}, oldMetadata)).to.be.undefined;
});
});
//# sourceMappingURL=getNumberType.test.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"getNumberType.test.js","names":["getNumberType","oldMetadata","type","Metadata","describe","it","expect","nationalNumber","country","v2","to","equal","be","undefined"],"sources":["../../source/helpers/getNumberType.test.js"],"sourcesContent":["import getNumberType from './getNumberType.js'\r\n\r\nimport oldMetadata from '../../test/metadata/1.0.0/metadata.min.json' with { type: 'json' }\r\n\r\nimport Metadata from '../metadata.js'\r\n\r\ndescribe('getNumberType', function() {\r\n\tit('should get number type when using old metadata', function() {\r\n\t\texpect(getNumberType(\r\n\t\t\t{\r\n\t\t\t\tnationalNumber: '2133734253',\r\n\t\t\t\tcountry: 'US'\r\n\t\t\t},\r\n\t\t\t{ v2: true },\r\n\t\t\toldMetadata\r\n\t\t)).to.equal('FIXED_LINE_OR_MOBILE')\r\n\t})\r\n\r\n\tit('should return `undefined` when the phone number is a malformed one', function() {\r\n\t\texpect(getNumberType(\r\n\t\t\t{},\r\n\t\t\t{ v2: true },\r\n\t\t\toldMetadata\r\n\t\t)).to.be.undefined\r\n\t})\r\n})"],"mappings":"AAAA,OAAOA,aAAa,MAAM,oBAAoB;AAE9C,OAAOC,WAAW,MAAM,6CAA6C,QAAQC,IAAI,EAAE,MAAM;AAEzF,OAAOC,QAAQ,MAAM,gBAAgB;AAErCC,QAAQ,CAAC,eAAe,EAAE,YAAW;EACpCC,EAAE,CAAC,gDAAgD,EAAE,YAAW;IAC/DC,MAAM,CAACN,aAAa,CACnB;MACCO,cAAc,EAAE,YAAY;MAC5BC,OAAO,EAAE;IACV,CAAC,EACD;MAAEC,EAAE,EAAE;IAAK,CAAC,EACZR,WACD,CAAC,CAAC,CAACS,EAAE,CAACC,KAAK,CAAC,sBAAsB,CAAC;EACpC,CAAC,CAAC;EAEFN,EAAE,CAAC,oEAAoE,EAAE,YAAW;IACnFC,MAAM,CAACN,aAAa,CACnB,CAAC,CAAC,EACF;MAAES,EAAE,EAAE;IAAK,CAAC,EACZR,WACD,CAAC,CAAC,CAACS,EAAE,CAACE,EAAE,CAACC,SAAS;EACnB,CAAC,CAAC;AACH,CAAC,CAAC","ignoreList":[]}

View File

@@ -0,0 +1,28 @@
import Metadata from '../metadata.js';
/**
* Returns a list of countries that the phone number could potentially belong to.
* @param {string} callingCode — Calling code.
* @param {string} nationalNumber — National (significant) number.
* @param {object} metadata — Metadata.
* @return {string[]} A list of possible countries.
*/
export default function getPossibleCountriesForNumber(callingCode, nationalNumber, metadata) {
var _metadata = new Metadata(metadata);
var possibleCountries = _metadata.getCountryCodesForCallingCode(callingCode);
if (!possibleCountries) {
return [];
}
return possibleCountries.filter(function (country) {
return couldNationalNumberBelongToCountry(nationalNumber, country, metadata);
});
}
function couldNationalNumberBelongToCountry(nationalNumber, country, metadata) {
var _metadata = new Metadata(metadata);
_metadata.selectNumberingPlan(country);
if (_metadata.numberingPlan.possibleLengths().indexOf(nationalNumber.length) >= 0) {
return true;
}
return false;
}
//# sourceMappingURL=getPossibleCountriesForNumber.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"getPossibleCountriesForNumber.js","names":["Metadata","getPossibleCountriesForNumber","callingCode","nationalNumber","metadata","_metadata","possibleCountries","getCountryCodesForCallingCode","filter","country","couldNationalNumberBelongToCountry","selectNumberingPlan","numberingPlan","possibleLengths","indexOf","length"],"sources":["../../source/helpers/getPossibleCountriesForNumber.js"],"sourcesContent":["import Metadata from '../metadata.js'\r\n\r\n/**\r\n * Returns a list of countries that the phone number could potentially belong to.\r\n * @param {string} callingCode — Calling code.\r\n * @param {string} nationalNumber — National (significant) number.\r\n * @param {object} metadata — Metadata.\r\n * @return {string[]} A list of possible countries.\r\n */\r\nexport default function getPossibleCountriesForNumber(callingCode, nationalNumber, metadata) {\r\n\tconst _metadata = new Metadata(metadata)\r\n\tlet possibleCountries = _metadata.getCountryCodesForCallingCode(callingCode)\r\n\tif (!possibleCountries) {\r\n\t\treturn []\r\n\t}\r\n\treturn possibleCountries.filter((country) => {\r\n\t\treturn couldNationalNumberBelongToCountry(nationalNumber, country, metadata)\r\n\t})\r\n}\r\n\r\nfunction couldNationalNumberBelongToCountry(nationalNumber, country, metadata) {\r\n\tconst _metadata = new Metadata(metadata)\r\n\t_metadata.selectNumberingPlan(country)\r\n\tif (_metadata.numberingPlan.possibleLengths().indexOf(nationalNumber.length) >= 0) {\r\n\t\treturn true\r\n\t}\r\n\treturn false\r\n}"],"mappings":"AAAA,OAAOA,QAAQ,MAAM,gBAAgB;;AAErC;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAe,SAASC,6BAA6BA,CAACC,WAAW,EAAEC,cAAc,EAAEC,QAAQ,EAAE;EAC5F,IAAMC,SAAS,GAAG,IAAIL,QAAQ,CAACI,QAAQ,CAAC;EACxC,IAAIE,iBAAiB,GAAGD,SAAS,CAACE,6BAA6B,CAACL,WAAW,CAAC;EAC5E,IAAI,CAACI,iBAAiB,EAAE;IACvB,OAAO,EAAE;EACV;EACA,OAAOA,iBAAiB,CAACE,MAAM,CAAC,UAACC,OAAO,EAAK;IAC5C,OAAOC,kCAAkC,CAACP,cAAc,EAAEM,OAAO,EAAEL,QAAQ,CAAC;EAC7E,CAAC,CAAC;AACH;AAEA,SAASM,kCAAkCA,CAACP,cAAc,EAAEM,OAAO,EAAEL,QAAQ,EAAE;EAC9E,IAAMC,SAAS,GAAG,IAAIL,QAAQ,CAACI,QAAQ,CAAC;EACxCC,SAAS,CAACM,mBAAmB,CAACF,OAAO,CAAC;EACtC,IAAIJ,SAAS,CAACO,aAAa,CAACC,eAAe,CAAC,CAAC,CAACC,OAAO,CAACX,cAAc,CAACY,MAAM,CAAC,IAAI,CAAC,EAAE;IAClF,OAAO,IAAI;EACZ;EACA,OAAO,KAAK;AACb","ignoreList":[]}

View File

@@ -0,0 +1,5 @@
var objectConstructor = {}.constructor;
export default function isObject(object) {
return object !== undefined && object !== null && object.constructor === objectConstructor;
}
//# sourceMappingURL=isObject.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"isObject.js","names":["objectConstructor","constructor","isObject","object","undefined"],"sources":["../../source/helpers/isObject.js"],"sourcesContent":["const objectConstructor = {}.constructor;\r\n\r\nexport default function isObject(object) {\r\n return object !== undefined && object !== null && object.constructor === objectConstructor;\r\n}\r\n"],"mappings":"AAAA,IAAMA,iBAAiB,GAAG,CAAC,CAAC,CAACC,WAAW;AAExC,eAAe,SAASC,QAAQA,CAACC,MAAM,EAAE;EACvC,OAAOA,MAAM,KAAKC,SAAS,IAAID,MAAM,KAAK,IAAI,IAAIA,MAAM,CAACF,WAAW,KAAKD,iBAAiB;AAC5F","ignoreList":[]}

View File

@@ -0,0 +1,77 @@
import { MIN_LENGTH_FOR_NSN, VALID_DIGITS, VALID_PUNCTUATION, PLUS_CHARS } from '../constants.js';
import createExtensionPattern from './extension/createExtensionPattern.js';
// Regular expression of viable phone numbers. This is location independent.
// Checks we have at least three leading digits, and only valid punctuation,
// alpha characters and digits in the phone number. Does not include extension
// data. The symbol 'x' is allowed here as valid punctuation since it is often
// used as a placeholder for carrier codes, for example in Brazilian phone
// numbers. We also allow multiple '+' characters at the start.
//
// Corresponds to the following:
// [digits]{minLengthNsn}|
// plus_sign*
// (([punctuation]|[star])*[digits]){3,}([punctuation]|[star]|[digits]|[alpha])*
//
// The first reg-ex is to allow short numbers (two digits long) to be parsed if
// they are entered as "15" etc, but only if there is no punctuation in them.
// The second expression restricts the number of digits to three or more, but
// then allows them to be in international form, and to have alpha-characters
// and punctuation. We split up the two reg-exes here and combine them when
// creating the reg-ex VALID_PHONE_NUMBER_PATTERN itself so we can prefix it
// with ^ and append $ to each branch.
//
// "Note VALID_PUNCTUATION starts with a -,
// so must be the first in the range" (c) Google devs.
// (wtf did they mean by saying that; probably nothing)
//
var MIN_LENGTH_PHONE_NUMBER_PATTERN = '[' + VALID_DIGITS + ']{' + MIN_LENGTH_FOR_NSN + '}';
//
// And this is the second reg-exp:
// (see MIN_LENGTH_PHONE_NUMBER_PATTERN for a full description of this reg-exp)
//
export var VALID_PHONE_NUMBER = '[' + PLUS_CHARS + ']{0,1}' + '(?:' + '[' + VALID_PUNCTUATION + ']*' + '[' + VALID_DIGITS + ']' + '){3,}' + '[' + VALID_PUNCTUATION + VALID_DIGITS + ']*';
// This regular expression isn't present in Google's `libphonenumber`
// and is only used to determine whether the phone number being input
// is too short for it to even consider it a "valid" number.
// This is just a way to differentiate between a really invalid phone
// number like "abcde" and a valid phone number that a user has just
// started inputting, like "+1" or "1": both these cases would be
// considered `NOT_A_NUMBER` by Google's `libphonenumber`, but this
// library can provide a more detailed error message — whether it's
// really "not a number", or is it just a start of a valid phone number.
var VALID_PHONE_NUMBER_START_REG_EXP = new RegExp('^' + '[' + PLUS_CHARS + ']{0,1}' + '(?:' + '[' + VALID_PUNCTUATION + ']*' + '[' + VALID_DIGITS + ']' + '){1,2}' + '$', 'i');
export var VALID_PHONE_NUMBER_WITH_EXTENSION = VALID_PHONE_NUMBER +
// Phone number extensions
'(?:' + createExtensionPattern() + ')?';
// The combined regular expression for valid phone numbers:
//
var VALID_PHONE_NUMBER_PATTERN = new RegExp(
// Either a short two-digit-only phone number
'^' + MIN_LENGTH_PHONE_NUMBER_PATTERN + '$' + '|' +
// Or a longer fully parsed phone number (min 3 characters)
'^' + VALID_PHONE_NUMBER_WITH_EXTENSION + '$', 'i');
// Checks to see if the string of characters could possibly be a phone number at
// all. At the moment, checks to see that the string begins with at least 2
// digits, ignoring any punctuation commonly found in phone numbers. This method
// does not require the number to be normalized in advance - but does assume
// that leading non-number symbols have been removed, such as by the method
// `extract_possible_number`.
//
export default function isViablePhoneNumber(number) {
return number.length >= MIN_LENGTH_FOR_NSN && VALID_PHONE_NUMBER_PATTERN.test(number);
}
// This is just a way to differentiate between a really invalid phone
// number like "abcde" and a valid phone number that a user has just
// started inputting, like "+1" or "1": both these cases would be
// considered `NOT_A_NUMBER` by Google's `libphonenumber`, but this
// library can provide a more detailed error message — whether it's
// really "not a number", or is it just a start of a valid phone number.
export function isViablePhoneNumberStart(number) {
return VALID_PHONE_NUMBER_START_REG_EXP.test(number);
}
//# sourceMappingURL=isViablePhoneNumber.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,12 @@
/**
* Checks whether the entire input sequence can be matched
* against the regular expression.
* @return {boolean}
*/
export default function matchesEntirely(text, regularExpressionText) {
// If the assigning of the `''` default value is moved to the arguments above,
// the code coverage would decrease for some weird reason.
text = text || '';
return new RegExp('^(?:' + regularExpressionText + ')$').test(text);
}
//# sourceMappingURL=matchesEntirely.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"matchesEntirely.js","names":["matchesEntirely","text","regularExpressionText","RegExp","test"],"sources":["../../source/helpers/matchesEntirely.js"],"sourcesContent":["/**\r\n * Checks whether the entire input sequence can be matched\r\n * against the regular expression.\r\n * @return {boolean}\r\n */\r\nexport default function matchesEntirely(text, regularExpressionText) {\r\n\t// If the assigning of the `''` default value is moved to the arguments above,\r\n\t// the code coverage would decrease for some weird reason.\r\n\ttext = text || ''\r\n\treturn new RegExp('^(?:' + regularExpressionText + ')$').test(text)\r\n}"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA,eAAe,SAASA,eAAeA,CAACC,IAAI,EAAEC,qBAAqB,EAAE;EACpE;EACA;EACAD,IAAI,GAAGA,IAAI,IAAI,EAAE;EACjB,OAAO,IAAIE,MAAM,CAAC,MAAM,GAAGD,qBAAqB,GAAG,IAAI,CAAC,CAACE,IAAI,CAACH,IAAI,CAAC;AACpE","ignoreList":[]}

View File

@@ -0,0 +1,11 @@
import matchesEntirely from './matchesEntirely.js';
describe('matchesEntirely', function () {
it('should work in edge cases', function () {
// No text.
expect(matchesEntirely(undefined, '')).to.equal(true);
// "OR" in regexp.
expect(matchesEntirely('911231231', '4\d{8}|[1-9]\d{7}')).to.equal(false);
});
});
//# sourceMappingURL=matchesEntirely.test.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"matchesEntirely.test.js","names":["matchesEntirely","describe","it","expect","undefined","to","equal"],"sources":["../../source/helpers/matchesEntirely.test.js"],"sourcesContent":["import matchesEntirely from './matchesEntirely.js'\r\n\r\ndescribe('matchesEntirely', () => {\r\n\tit('should work in edge cases', () => {\r\n\t\t// No text.\r\n\t\texpect(matchesEntirely(undefined, '')).to.equal(true)\r\n\r\n\t\t// \"OR\" in regexp.\r\n\t\texpect(matchesEntirely('911231231', '4\\d{8}|[1-9]\\d{7}')).to.equal(false)\r\n\t})\r\n})"],"mappings":"AAAA,OAAOA,eAAe,MAAM,sBAAsB;AAElDC,QAAQ,CAAC,iBAAiB,EAAE,YAAM;EACjCC,EAAE,CAAC,2BAA2B,EAAE,YAAM;IACrC;IACAC,MAAM,CAACH,eAAe,CAACI,SAAS,EAAE,EAAE,CAAC,CAAC,CAACC,EAAE,CAACC,KAAK,CAAC,IAAI,CAAC;;IAErD;IACAH,MAAM,CAACH,eAAe,CAAC,WAAW,EAAE,mBAAmB,CAAC,CAAC,CAACK,EAAE,CAACC,KAAK,CAAC,KAAK,CAAC;EAC1E,CAAC,CAAC;AACH,CAAC,CAAC","ignoreList":[]}

View File

@@ -0,0 +1,29 @@
function _createForOfIteratorHelperLoose(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (t) return (t = t.call(r)).next.bind(t); if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var o = 0; return function () { return o >= r.length ? { done: !0 } : { done: !1, value: r[o++] }; }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
/**
* Merges two arrays.
* @param {*} a
* @param {*} b
* @return {*}
*/
export default function mergeArrays(a, b) {
var merged = a.slice();
for (var _iterator = _createForOfIteratorHelperLoose(b), _step; !(_step = _iterator()).done;) {
var element = _step.value;
if (a.indexOf(element) < 0) {
merged.push(element);
}
}
return merged.sort(function (a, b) {
return a - b;
});
// ES6 version, requires Set polyfill.
// let merged = new Set(a)
// for (const element of b) {
// merged.add(i)
// }
// return Array.from(merged).sort((a, b) => a - b)
}
//# sourceMappingURL=mergeArrays.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"mergeArrays.js","names":["mergeArrays","a","b","merged","slice","_iterator","_createForOfIteratorHelperLoose","_step","done","element","value","indexOf","push","sort"],"sources":["../../source/helpers/mergeArrays.js"],"sourcesContent":["/**\r\n * Merges two arrays.\r\n * @param {*} a\r\n * @param {*} b\r\n * @return {*}\r\n */\r\nexport default function mergeArrays(a, b) {\r\n\tconst merged = a.slice()\r\n\r\n\tfor (const element of b) {\r\n\t\tif (a.indexOf(element) < 0) {\r\n\t\t\tmerged.push(element)\r\n\t\t}\r\n\t}\r\n\r\n\treturn merged.sort((a, b) => a - b)\r\n\r\n\t// ES6 version, requires Set polyfill.\r\n\t// let merged = new Set(a)\r\n\t// for (const element of b) {\r\n\t// \tmerged.add(i)\r\n\t// }\r\n\t// return Array.from(merged).sort((a, b) => a - b)\r\n}"],"mappings":";;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA,eAAe,SAASA,WAAWA,CAACC,CAAC,EAAEC,CAAC,EAAE;EACzC,IAAMC,MAAM,GAAGF,CAAC,CAACG,KAAK,CAAC,CAAC;EAExB,SAAAC,SAAA,GAAAC,+BAAA,CAAsBJ,CAAC,GAAAK,KAAA,IAAAA,KAAA,GAAAF,SAAA,IAAAG,IAAA,GAAE;IAAA,IAAdC,OAAO,GAAAF,KAAA,CAAAG,KAAA;IACjB,IAAIT,CAAC,CAACU,OAAO,CAACF,OAAO,CAAC,GAAG,CAAC,EAAE;MAC3BN,MAAM,CAACS,IAAI,CAACH,OAAO,CAAC;IACrB;EACD;EAEA,OAAON,MAAM,CAACU,IAAI,CAAC,UAACZ,CAAC,EAAEC,CAAC;IAAA,OAAKD,CAAC,GAAGC,CAAC;EAAA,EAAC;;EAEnC;EACA;EACA;EACA;EACA;EACA;AACD","ignoreList":[]}

View File

@@ -0,0 +1,7 @@
import mergeArrays from './mergeArrays.js';
describe('mergeArrays', function () {
it('should merge arrays', function () {
expect(mergeArrays([1, 2], [2, 3])).to.deep.equal([1, 2, 3]);
});
});
//# sourceMappingURL=mergeArrays.test.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"mergeArrays.test.js","names":["mergeArrays","describe","it","expect","to","deep","equal"],"sources":["../../source/helpers/mergeArrays.test.js"],"sourcesContent":["import mergeArrays from './mergeArrays.js'\r\n\r\ndescribe('mergeArrays', () => {\r\n\tit('should merge arrays', () => {\r\n\t\texpect(mergeArrays([1, 2], [2, 3])).to.deep.equal([1, 2, 3])\r\n\t})\r\n})"],"mappings":"AAAA,OAAOA,WAAW,MAAM,kBAAkB;AAE1CC,QAAQ,CAAC,aAAa,EAAE,YAAM;EAC7BC,EAAE,CAAC,qBAAqB,EAAE,YAAM;IAC/BC,MAAM,CAACH,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAACI,EAAE,CAACC,IAAI,CAACC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;EAC7D,CAAC,CAAC;AACH,CAAC,CAAC","ignoreList":[]}

View File

@@ -0,0 +1,115 @@
function _createForOfIteratorHelperLoose(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (t) return (t = t.call(r)).next.bind(t); if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var o = 0; return function () { return o >= r.length ? { done: !0 } : { done: !1, value: r[o++] }; }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
// These mappings map a character (key) to a specific digit that should
// replace it for normalization purposes. Non-European digits that
// may be used in phone numbers are mapped to a European equivalent.
//
// E.g. in Iraq they don't write `+442323234` but rather `+٤٤٢٣٢٣٢٣٤`.
//
export var DIGITS = {
'0': '0',
'1': '1',
'2': '2',
'3': '3',
'4': '4',
'5': '5',
'6': '6',
'7': '7',
'8': '8',
'9': '9',
"\uFF10": '0',
// Fullwidth digit 0
"\uFF11": '1',
// Fullwidth digit 1
"\uFF12": '2',
// Fullwidth digit 2
"\uFF13": '3',
// Fullwidth digit 3
"\uFF14": '4',
// Fullwidth digit 4
"\uFF15": '5',
// Fullwidth digit 5
"\uFF16": '6',
// Fullwidth digit 6
"\uFF17": '7',
// Fullwidth digit 7
"\uFF18": '8',
// Fullwidth digit 8
"\uFF19": '9',
// Fullwidth digit 9
"\u0660": '0',
// Arabic-indic digit 0
"\u0661": '1',
// Arabic-indic digit 1
"\u0662": '2',
// Arabic-indic digit 2
"\u0663": '3',
// Arabic-indic digit 3
"\u0664": '4',
// Arabic-indic digit 4
"\u0665": '5',
// Arabic-indic digit 5
"\u0666": '6',
// Arabic-indic digit 6
"\u0667": '7',
// Arabic-indic digit 7
"\u0668": '8',
// Arabic-indic digit 8
"\u0669": '9',
// Arabic-indic digit 9
"\u06F0": '0',
// Eastern-Arabic digit 0
"\u06F1": '1',
// Eastern-Arabic digit 1
"\u06F2": '2',
// Eastern-Arabic digit 2
"\u06F3": '3',
// Eastern-Arabic digit 3
"\u06F4": '4',
// Eastern-Arabic digit 4
"\u06F5": '5',
// Eastern-Arabic digit 5
"\u06F6": '6',
// Eastern-Arabic digit 6
"\u06F7": '7',
// Eastern-Arabic digit 7
"\u06F8": '8',
// Eastern-Arabic digit 8
"\u06F9": '9' // Eastern-Arabic digit 9
};
export function parseDigit(character) {
return DIGITS[character];
}
/**
* Parses phone number digits from a string.
* Drops all punctuation leaving only digits.
* Also converts wide-ascii and arabic-indic numerals to conventional numerals.
* E.g. in Iraq they don't write `+442323234` but rather `+٤٤٢٣٢٣٢٣٤`.
* @param {string} string
* @return {string}
* @example
* ```js
* parseDigits('8 (800) 555')
* // Outputs '8800555'.
* ```
*/
export default function parseDigits(string) {
var result = '';
// Using `.split('')` here instead of normal `for ... of`
// because the importing application doesn't neccessarily include an ES6 polyfill.
// The `.split('')` approach discards "exotic" UTF-8 characters
// (the ones consisting of four bytes) but digits
// (including non-European ones) don't fall into that range
// so such "exotic" characters would be discarded anyway.
for (var _iterator = _createForOfIteratorHelperLoose(string.split('')), _step; !(_step = _iterator()).done;) {
var character = _step.value;
var digit = parseDigit(character);
if (digit) {
result += digit;
}
}
return result;
}
//# sourceMappingURL=parseDigits.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"parseDigits.js","names":["DIGITS","parseDigit","character","parseDigits","string","result","_iterator","_createForOfIteratorHelperLoose","split","_step","done","value","digit"],"sources":["../../source/helpers/parseDigits.js"],"sourcesContent":["// These mappings map a character (key) to a specific digit that should\r\n// replace it for normalization purposes. Non-European digits that\r\n// may be used in phone numbers are mapped to a European equivalent.\r\n//\r\n// E.g. in Iraq they don't write `+442323234` but rather `+٤٤٢٣٢٣٢٣٤`.\r\n//\r\nexport const DIGITS = {\r\n\t'0': '0',\r\n\t'1': '1',\r\n\t'2': '2',\r\n\t'3': '3',\r\n\t'4': '4',\r\n\t'5': '5',\r\n\t'6': '6',\r\n\t'7': '7',\r\n\t'8': '8',\r\n\t'9': '9',\r\n\t'\\uFF10': '0', // Fullwidth digit 0\r\n\t'\\uFF11': '1', // Fullwidth digit 1\r\n\t'\\uFF12': '2', // Fullwidth digit 2\r\n\t'\\uFF13': '3', // Fullwidth digit 3\r\n\t'\\uFF14': '4', // Fullwidth digit 4\r\n\t'\\uFF15': '5', // Fullwidth digit 5\r\n\t'\\uFF16': '6', // Fullwidth digit 6\r\n\t'\\uFF17': '7', // Fullwidth digit 7\r\n\t'\\uFF18': '8', // Fullwidth digit 8\r\n\t'\\uFF19': '9', // Fullwidth digit 9\r\n\t'\\u0660': '0', // Arabic-indic digit 0\r\n\t'\\u0661': '1', // Arabic-indic digit 1\r\n\t'\\u0662': '2', // Arabic-indic digit 2\r\n\t'\\u0663': '3', // Arabic-indic digit 3\r\n\t'\\u0664': '4', // Arabic-indic digit 4\r\n\t'\\u0665': '5', // Arabic-indic digit 5\r\n\t'\\u0666': '6', // Arabic-indic digit 6\r\n\t'\\u0667': '7', // Arabic-indic digit 7\r\n\t'\\u0668': '8', // Arabic-indic digit 8\r\n\t'\\u0669': '9', // Arabic-indic digit 9\r\n\t'\\u06F0': '0', // Eastern-Arabic digit 0\r\n\t'\\u06F1': '1', // Eastern-Arabic digit 1\r\n\t'\\u06F2': '2', // Eastern-Arabic digit 2\r\n\t'\\u06F3': '3', // Eastern-Arabic digit 3\r\n\t'\\u06F4': '4', // Eastern-Arabic digit 4\r\n\t'\\u06F5': '5', // Eastern-Arabic digit 5\r\n\t'\\u06F6': '6', // Eastern-Arabic digit 6\r\n\t'\\u06F7': '7', // Eastern-Arabic digit 7\r\n\t'\\u06F8': '8', // Eastern-Arabic digit 8\r\n\t'\\u06F9': '9' // Eastern-Arabic digit 9\r\n}\r\n\r\nexport function parseDigit(character) {\r\n\treturn DIGITS[character]\r\n}\r\n\r\n/**\r\n * Parses phone number digits from a string.\r\n * Drops all punctuation leaving only digits.\r\n * Also converts wide-ascii and arabic-indic numerals to conventional numerals.\r\n * E.g. in Iraq they don't write `+442323234` but rather `+٤٤٢٣٢٣٢٣٤`.\r\n * @param {string} string\r\n * @return {string}\r\n * @example\r\n * ```js\r\n * parseDigits('8 (800) 555')\r\n * // Outputs '8800555'.\r\n * ```\r\n */\r\nexport default function parseDigits(string) {\r\n\tlet result = ''\r\n\t// Using `.split('')` here instead of normal `for ... of`\r\n\t// because the importing application doesn't neccessarily include an ES6 polyfill.\r\n\t// The `.split('')` approach discards \"exotic\" UTF-8 characters\r\n\t// (the ones consisting of four bytes) but digits\r\n\t// (including non-European ones) don't fall into that range\r\n\t// so such \"exotic\" characters would be discarded anyway.\r\n\tfor (const character of string.split('')) {\r\n\t\tconst digit = parseDigit(character)\r\n\t\tif (digit) {\r\n\t\t\tresult += digit\r\n\t\t}\r\n\t}\r\n\treturn result\r\n}"],"mappings":";;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,IAAMA,MAAM,GAAG;EACrB,GAAG,EAAE,GAAG;EACR,GAAG,EAAE,GAAG;EACR,GAAG,EAAE,GAAG;EACR,GAAG,EAAE,GAAG;EACR,GAAG,EAAE,GAAG;EACR,GAAG,EAAE,GAAG;EACR,GAAG,EAAE,GAAG;EACR,GAAG,EAAE,GAAG;EACR,GAAG,EAAE,GAAG;EACR,GAAG,EAAE,GAAG;EACR,QAAQ,EAAE,GAAG;EAAE;EACf,QAAQ,EAAE,GAAG;EAAE;EACf,QAAQ,EAAE,GAAG;EAAE;EACf,QAAQ,EAAE,GAAG;EAAE;EACf,QAAQ,EAAE,GAAG;EAAE;EACf,QAAQ,EAAE,GAAG;EAAE;EACf,QAAQ,EAAE,GAAG;EAAE;EACf,QAAQ,EAAE,GAAG;EAAE;EACf,QAAQ,EAAE,GAAG;EAAE;EACf,QAAQ,EAAE,GAAG;EAAE;EACf,QAAQ,EAAE,GAAG;EAAE;EACf,QAAQ,EAAE,GAAG;EAAE;EACf,QAAQ,EAAE,GAAG;EAAE;EACf,QAAQ,EAAE,GAAG;EAAE;EACf,QAAQ,EAAE,GAAG;EAAE;EACf,QAAQ,EAAE,GAAG;EAAE;EACf,QAAQ,EAAE,GAAG;EAAE;EACf,QAAQ,EAAE,GAAG;EAAE;EACf,QAAQ,EAAE,GAAG;EAAE;EACf,QAAQ,EAAE,GAAG;EAAE;EACf,QAAQ,EAAE,GAAG;EAAE;EACf,QAAQ,EAAE,GAAG;EAAE;EACf,QAAQ,EAAE,GAAG;EAAE;EACf,QAAQ,EAAE,GAAG;EAAE;EACf,QAAQ,EAAE,GAAG;EAAE;EACf,QAAQ,EAAE,GAAG;EAAE;EACf,QAAQ,EAAE,GAAG;EAAE;EACf,QAAQ,EAAE,GAAG;EAAE;EACf,QAAQ,EAAE,GAAG;EAAE;EACf,QAAQ,EAAE,GAAG,CAAE;AAChB,CAAC;AAED,OAAO,SAASC,UAAUA,CAACC,SAAS,EAAE;EACrC,OAAOF,MAAM,CAACE,SAAS,CAAC;AACzB;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAe,SAASC,WAAWA,CAACC,MAAM,EAAE;EAC3C,IAAIC,MAAM,GAAG,EAAE;EACf;EACA;EACA;EACA;EACA;EACA;EACA,SAAAC,SAAA,GAAAC,+BAAA,CAAwBH,MAAM,CAACI,KAAK,CAAC,EAAE,CAAC,GAAAC,KAAA,IAAAA,KAAA,GAAAH,SAAA,IAAAI,IAAA,GAAE;IAAA,IAA/BR,SAAS,GAAAO,KAAA,CAAAE,KAAA;IACnB,IAAMC,KAAK,GAAGX,UAAU,CAACC,SAAS,CAAC;IACnC,IAAIU,KAAK,EAAE;MACVP,MAAM,IAAIO,KAAK;IAChB;EACD;EACA,OAAOP,MAAM;AACd","ignoreList":[]}

View File

@@ -0,0 +1,7 @@
import parseDigits from './parseDigits.js';
describe('parseDigits', function () {
it('should parse digits', function () {
expect(parseDigits('+٤٤٢٣٢٣٢٣٤')).to.equal('442323234');
});
});
//# sourceMappingURL=parseDigits.test.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"parseDigits.test.js","names":["parseDigits","describe","it","expect","to","equal"],"sources":["../../source/helpers/parseDigits.test.js"],"sourcesContent":["import parseDigits from './parseDigits.js'\r\n\r\ndescribe('parseDigits', () => {\r\n\tit('should parse digits', () => {\r\n\t\texpect(parseDigits('+٤٤٢٣٢٣٢٣٤')).to.equal('442323234')\r\n\t})\r\n})"],"mappings":"AAAA,OAAOA,WAAW,MAAM,kBAAkB;AAE1CC,QAAQ,CAAC,aAAa,EAAE,YAAM;EAC7BC,EAAE,CAAC,qBAAqB,EAAE,YAAM;IAC/BC,MAAM,CAACH,WAAW,CAAC,YAAY,CAAC,CAAC,CAACI,EAAE,CAACC,KAAK,CAAC,WAAW,CAAC;EACxD,CAAC,CAAC;AACH,CAAC,CAAC","ignoreList":[]}

View File

@@ -0,0 +1,29 @@
import Metadata from '../metadata.js';
import { VALID_DIGITS } from '../constants.js';
var CAPTURING_DIGIT_PATTERN = new RegExp('([' + VALID_DIGITS + '])');
export default function stripIddPrefix(number, country, callingCode, metadata) {
if (!country) {
return;
}
// Check if the number is IDD-prefixed.
var countryMetadata = new Metadata(metadata);
countryMetadata.selectNumberingPlan(country, callingCode);
var IDDPrefixPattern = new RegExp(countryMetadata.IDDPrefix());
if (number.search(IDDPrefixPattern) !== 0) {
return;
}
// Strip IDD prefix.
number = number.slice(number.match(IDDPrefixPattern)[0].length);
// If there're any digits after an IDD prefix,
// then those digits are a country calling code.
// Since no country code starts with a `0`,
// the code below validates that the next digit (if present) is not `0`.
var matchedGroups = number.match(CAPTURING_DIGIT_PATTERN);
if (matchedGroups && matchedGroups[1] != null && matchedGroups[1].length > 0) {
if (matchedGroups[1] === '0') {
return;
}
}
return number;
}
//# sourceMappingURL=stripIddPrefix.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"stripIddPrefix.js","names":["Metadata","VALID_DIGITS","CAPTURING_DIGIT_PATTERN","RegExp","stripIddPrefix","number","country","callingCode","metadata","countryMetadata","selectNumberingPlan","IDDPrefixPattern","IDDPrefix","search","slice","match","length","matchedGroups"],"sources":["../../source/helpers/stripIddPrefix.js"],"sourcesContent":["import Metadata from '../metadata.js'\r\nimport { VALID_DIGITS } from '../constants.js'\r\n\r\nconst CAPTURING_DIGIT_PATTERN = new RegExp('([' + VALID_DIGITS + '])')\r\n\r\nexport default function stripIddPrefix(number, country, callingCode, metadata) {\r\n\tif (!country) {\r\n\t\treturn\r\n\t}\r\n\t// Check if the number is IDD-prefixed.\r\n\tconst countryMetadata = new Metadata(metadata)\r\n\tcountryMetadata.selectNumberingPlan(country, callingCode)\r\n\tconst IDDPrefixPattern = new RegExp(countryMetadata.IDDPrefix())\r\n\tif (number.search(IDDPrefixPattern) !== 0) {\r\n\t\treturn\r\n\t}\r\n\t// Strip IDD prefix.\r\n\tnumber = number.slice(number.match(IDDPrefixPattern)[0].length)\r\n\t// If there're any digits after an IDD prefix,\r\n\t// then those digits are a country calling code.\r\n\t// Since no country code starts with a `0`,\r\n\t// the code below validates that the next digit (if present) is not `0`.\r\n\tconst matchedGroups = number.match(CAPTURING_DIGIT_PATTERN)\r\n\tif (matchedGroups && matchedGroups[1] != null && matchedGroups[1].length > 0) {\r\n\t\tif (matchedGroups[1] === '0') {\r\n\t\t\treturn\r\n\t\t}\r\n\t}\r\n\treturn number\r\n}"],"mappings":"AAAA,OAAOA,QAAQ,MAAM,gBAAgB;AACrC,SAASC,YAAY,QAAQ,iBAAiB;AAE9C,IAAMC,uBAAuB,GAAG,IAAIC,MAAM,CAAC,IAAI,GAAGF,YAAY,GAAG,IAAI,CAAC;AAEtE,eAAe,SAASG,cAAcA,CAACC,MAAM,EAAEC,OAAO,EAAEC,WAAW,EAAEC,QAAQ,EAAE;EAC9E,IAAI,CAACF,OAAO,EAAE;IACb;EACD;EACA;EACA,IAAMG,eAAe,GAAG,IAAIT,QAAQ,CAACQ,QAAQ,CAAC;EAC9CC,eAAe,CAACC,mBAAmB,CAACJ,OAAO,EAAEC,WAAW,CAAC;EACzD,IAAMI,gBAAgB,GAAG,IAAIR,MAAM,CAACM,eAAe,CAACG,SAAS,CAAC,CAAC,CAAC;EAChE,IAAIP,MAAM,CAACQ,MAAM,CAACF,gBAAgB,CAAC,KAAK,CAAC,EAAE;IAC1C;EACD;EACA;EACAN,MAAM,GAAGA,MAAM,CAACS,KAAK,CAACT,MAAM,CAACU,KAAK,CAACJ,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAACK,MAAM,CAAC;EAC/D;EACA;EACA;EACA;EACA,IAAMC,aAAa,GAAGZ,MAAM,CAACU,KAAK,CAACb,uBAAuB,CAAC;EAC3D,IAAIe,aAAa,IAAIA,aAAa,CAAC,CAAC,CAAC,IAAI,IAAI,IAAIA,aAAa,CAAC,CAAC,CAAC,CAACD,MAAM,GAAG,CAAC,EAAE;IAC7E,IAAIC,aAAa,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE;MAC7B;IACD;EACD;EACA,OAAOZ,MAAM;AACd","ignoreList":[]}

View File

@@ -0,0 +1,17 @@
import stripIddPrefix from './stripIddPrefix.js';
import metadata from '../../metadata.min.json' with { type: 'json' };
describe('stripIddPrefix', function () {
it('should strip a valid IDD prefix', function () {
expect(stripIddPrefix('01178005553535', 'US', '1', metadata)).to.equal('78005553535');
});
it('should strip a valid IDD prefix (no country calling code)', function () {
expect(stripIddPrefix('011', 'US', '1', metadata)).to.equal('');
});
it('should strip a valid IDD prefix (valid country calling code)', function () {
expect(stripIddPrefix('0117', 'US', '1', metadata)).to.equal('7');
});
it('should strip a valid IDD prefix (not a valid country calling code)', function () {
expect(stripIddPrefix('0110', 'US', '1', metadata)).to.be.undefined;
});
});
//# sourceMappingURL=stripIddPrefix.test.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"stripIddPrefix.test.js","names":["stripIddPrefix","metadata","type","describe","it","expect","to","equal","be","undefined"],"sources":["../../source/helpers/stripIddPrefix.test.js"],"sourcesContent":["import stripIddPrefix from './stripIddPrefix.js'\r\n\r\nimport metadata from '../../metadata.min.json' with { type: 'json' }\r\n\r\ndescribe('stripIddPrefix', () => {\r\n\tit('should strip a valid IDD prefix', () => {\r\n\t\texpect(stripIddPrefix('01178005553535', 'US', '1', metadata)).to.equal('78005553535')\r\n\t})\r\n\r\n\tit('should strip a valid IDD prefix (no country calling code)', () => {\r\n\t\texpect(stripIddPrefix('011', 'US', '1', metadata)).to.equal('')\r\n\t})\r\n\r\n\tit('should strip a valid IDD prefix (valid country calling code)', () => {\r\n\t\texpect(stripIddPrefix('0117', 'US', '1', metadata)).to.equal('7')\r\n\t})\r\n\r\n\tit('should strip a valid IDD prefix (not a valid country calling code)', () => {\r\n\t\texpect(stripIddPrefix('0110', 'US', '1', metadata)).to.be.undefined\r\n\t})\r\n})"],"mappings":"AAAA,OAAOA,cAAc,MAAM,qBAAqB;AAEhD,OAAOC,QAAQ,MAAM,yBAAyB,QAAQC,IAAI,EAAE,MAAM;AAElEC,QAAQ,CAAC,gBAAgB,EAAE,YAAM;EAChCC,EAAE,CAAC,iCAAiC,EAAE,YAAM;IAC3CC,MAAM,CAACL,cAAc,CAAC,gBAAgB,EAAE,IAAI,EAAE,GAAG,EAAEC,QAAQ,CAAC,CAAC,CAACK,EAAE,CAACC,KAAK,CAAC,aAAa,CAAC;EACtF,CAAC,CAAC;EAEFH,EAAE,CAAC,2DAA2D,EAAE,YAAM;IACrEC,MAAM,CAACL,cAAc,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,EAAEC,QAAQ,CAAC,CAAC,CAACK,EAAE,CAACC,KAAK,CAAC,EAAE,CAAC;EAChE,CAAC,CAAC;EAEFH,EAAE,CAAC,8DAA8D,EAAE,YAAM;IACxEC,MAAM,CAACL,cAAc,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,EAAEC,QAAQ,CAAC,CAAC,CAACK,EAAE,CAACC,KAAK,CAAC,GAAG,CAAC;EAClE,CAAC,CAAC;EAEFH,EAAE,CAAC,oEAAoE,EAAE,YAAM;IAC9EC,MAAM,CAACL,cAAc,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,EAAEC,QAAQ,CAAC,CAAC,CAACK,EAAE,CAACE,EAAE,CAACC,SAAS;EACpE,CAAC,CAAC;AACH,CAAC,CAAC","ignoreList":[]}