@botique/libphonenumber-js
Version:
A simpler (and smaller) rewrite of Google Android's popular libphonenumber library
980 lines (850 loc) • 34.6 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _from = require('babel-runtime/core-js/array/from');
var _from2 = _interopRequireDefault(_from);
var _slicedToArray2 = require('babel-runtime/helpers/slicedToArray');
var _slicedToArray3 = _interopRequireDefault(_slicedToArray2);
var _set = require('babel-runtime/core-js/set');
var _set2 = _interopRequireDefault(_set);
var _keys = require('babel-runtime/core-js/object/keys');
var _keys2 = _interopRequireDefault(_keys);
var _getIterator2 = require('babel-runtime/core-js/get-iterator');
var _getIterator3 = _interopRequireDefault(_getIterator2);
exports.default = function (input, version, included_countries, extended, included_phone_number_types) {
// Validate `included_phone_number_types`
if (included_phone_number_types) {
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = (0, _getIterator3.default)(included_phone_number_types), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var _type = _step.value;
if (phone_number_types.indexOf(_type) < 0) {
return _bluebird2.default.reject('Unknown phone number type: ' + _type);
}
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
}
// Parse the XML metadata
return _bluebird2.default.promisify(_xml2js.parseString)(input).then(function (xml) {
// https://github.com/googlei18n/libphonenumber/blob/master/resources/PhoneNumberMetadata.xml
// https://github.com/googlei18n/libphonenumber/blob/master/resources/phonemetadata.proto
// https://github.com/googlei18n/libphonenumber/blob/master/javascript/i18n/phonenumbers/phonenumberutil.js
// https://github.com/googlei18n/libphonenumber/blob/master/javascript/i18n/phonenumbers/asyoutypeformatter.js
var country_calling_code_to_countries = {};
var countries = {};
var _iteratorNormalCompletion2 = true;
var _didIteratorError2 = false;
var _iteratorError2 = undefined;
try {
var _loop = function _loop() {
var territory = _step2.value;
// A two-letter country code
var country_code = territory.$.id;
// Skip this country if it has not been explicitly included
if (included_countries && !included_countries.has(country_code)) {
return 'continue';
}
// Country metadata
var country = {
// Phone code related fields:
// Phone code for phone numbers in this country.
//
// E.g. `1` for both USA and Canada.
//
phone_code: territory.$.countryCode,
// In case of several countries
// having the same country phone code,
// these leading digits are the means
// of classifying an international phone number
// whether it belongs to a certain country.
//
// E.g. for Antigua and Barbuda
// country phone code is `1` (same as USA)
// and leading digits are `268`.
//
leading_digits: territory.$.leadingDigits,
// The regular expression of all possible
// national (significant) numbers for this country.
national_number_pattern: territory.generalDesc[0].nationalNumberPattern[0].replace(/\s/g, ''),
// National prefix related fields:
// aka "trunk code".
// This is the prefix prepended to a
// national (significant) phone number
// when dialed from within the country.
// E.g. `0` for UK.
national_prefix: territory.$.nationalPrefix,
// In some (many) countries the national prefix
// is not just a constant digit (like `0` in UK)
// but can be different depending on the phone number
// (and can be also absent for some phone numbers).
//
// So `national_prefix_for_parsing` is used when parsing
// a national-prefixed (local) phone number
// into a national significant phone number
// extracting that possible national prefix out of it.
//
national_prefix_for_parsing: territory.$.nationalPrefixForParsing ? territory.$.nationalPrefixForParsing.replace(/\s/g, '') : undefined,
// If `national_prefix_for_parsing` regular expression
// contains "captured groups", then `national_prefix_transform_rule`
// defines how the national-prefixed (local) phone number is
// parsed into a national significant phone number.
//
// Pseudocode:
//
// national_prefix_pattern = regular_expression('^(?:' + national_prefix_for_parsing + ')')
// national_significant_number = all_digits.replace(national_prefix_pattern, national_prefix_transform_rule)
//
// E.g. if a country's national numbers are 6-digit
// and national prefix is always `0`,
// then `national_prefix_for_parsing` could be `0(\d{6})`
// and the corresponding `national_prefix_transform_rule` would be `$1`
// (which is the default behaviour).
//
// Currently this feature is only used in
// Argentina, Brazil, Mexico and San Marino
// due to their messy telephone numbering plans.
//
// For example, mobile numbers in Argentina are written in two completely
// different ways when dialed in-country and out-of-country
// (e.g. 0343 15 555 1212 is exactly the same number as +54 9 343 555 1212).
// Therefore for Argentina `national_prefix_transform_rule` is `9$1`.
//
national_prefix_transform_rule: territory.$.nationalPrefixTransformRule,
// Controls how national prefix is written
// in a formatted local phone number.
//
// E.g. in Armenia national prefix is `0`
// and `national_prefix_formatting_rule` is `($NP$FG)`
// which means that a national significant phone number `xxxxxxxx`
// matching phone number pattern `(\d{2})(\d{6})` with format `$1 $2`
// is written as a local phone number `(0xx) xxxxxx`.
//
national_prefix_formatting_rule: national_prefix_formatting_rule(territory.$.nationalPrefixFormattingRule, territory.$.nationalPrefix),
// Is it possible that a national (significant)
// phone number has leading zeroes?
//
// E.g. in Gabon some numbers start with a `0`
// while the national prefix is also `0`
// which is optional for mobile numbers.
//
national_prefix_is_optional_when_formatting: territory.$.nationalPrefixOptionalWhenFormatting ? Boolean(territory.$.nationalPrefixOptionalWhenFormatting) : undefined,
// I suppose carrier codes can be omitted.
// They are required only for Brazil and Columbia,
// and only when calling to fixed line numbers
// from mobile phones within those countries.
// I guess people living in those countries
// would know that they need to add carrier codes.
// Other people don't need to know that.
// Anyway, if someone sends a Pull Request
// implementing carrier codes as Google's `libphonenumber` does
// then such Pull Request will likely be merged.
//
// // In some countries carrier code is required
// // to dial certain phone numbers.
// //
// // E.g. in Colombia calling to fixed line numbers
// // from mobile phones requires a carrier code when called within Colombia.
// // Or, for example, Brazilian fixed line and mobile numbers
// // need to be dialed with a carrier code when called within Brazil.
// // Without that, most of the carriers won't connect the call.
// // These are the only two cases when "carrier codes" are required.
// //
// carrier_code_formatting_rule: territory.$.carrierCodeFormattingRule,
// These `types` will be purged later,
// if they're not needed (which is most likely).
// See `country_calling_code_to_countries` ambiguity for more info.
//
types: get_phone_number_types(territory),
// Will be filtered out during compression phase
examples: get_phone_number_examples(territory)
// Check that national (significant) phone number pattern
// is set for this country (no "default" value here)
};if (!country.national_number_pattern) {
throw new Error('"generalDesc.nationalNumberPattern" is missing for country ' + country_code + ' metadata');
}
// Some countries don't have `availableFormats` specified,
// because those formats are inherited from the "main country for region".
if (territory.availableFormats) {
country.formats = territory.availableFormats[0].numberFormat.map(function (number_format) {
return {
pattern: number_format.$.pattern,
leading_digits_patterns: number_format.leadingDigits ? number_format.leadingDigits.map(function (leading_digits) {
return leading_digits.replace(/\s/g, '');
}) : undefined,
national_prefix_formatting_rule: national_prefix_formatting_rule(number_format.$.nationalPrefixFormattingRule, territory.$.nationalPrefix),
national_prefix_is_optional_when_formatting: number_format.$.nationalPrefixOptionalWhenFormatting,
format: number_format.format[0],
international_format: number_format.intlFormat ? number_format.intlFormat[0] : undefined
};
})
// Screw local-only formats
.filter(function (format) {
return format.international_format !== 'NA';
});
// Sanity check (using no "default" for this field)
var _iteratorNormalCompletion5 = true;
var _didIteratorError5 = false;
var _iteratorError5 = undefined;
try {
for (var _iterator5 = (0, _getIterator3.default)(country.formats), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {
var format = _step5.value;
// Never happens
if (!format.format) {
throw new Error('No phone number format "format" supplied for pattern ' + format.pattern + ' for ' + country_code);
}
// Never happens
if (format.format.indexOf(_AsYouType.DIGIT_PLACEHOLDER) >= 0) {
throw new Error('Phone number format "' + format.format + '" contains a reserved "' + _AsYouType.DIGIT_PLACEHOLDER + '" symbol for pattern ' + format.pattern + ' for ' + country_code);
}
}
} catch (err) {
_didIteratorError5 = true;
_iteratorError5 = err;
} finally {
try {
if (!_iteratorNormalCompletion5 && _iterator5.return) {
_iterator5.return();
}
} finally {
if (_didIteratorError5) {
throw _iteratorError5;
}
}
}
}
// Add this country's metadata
// to the metadata map.
countries[country_code] = country;
// Register this country's "country phone code"
if (!country_calling_code_to_countries[country.phone_code]) {
country_calling_code_to_countries[country.phone_code] = [];
}
// In case of several countries
// having the same country phone code.
//
// E.g. for USA and Canada, USA is the
// "main country for phone code 1".
//
// (maybe this field is not used at all
// in which case this field is to be removed)
//
if (territory.$.mainCountryForCode === "true") {
country_calling_code_to_countries[country.phone_code].unshift(country_code);
} else {
country_calling_code_to_countries[country.phone_code].push(country_code);
}
};
for (var _iterator2 = (0, _getIterator3.default)(xml.phoneNumberMetadata.territories[0].territory), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
var _ret = _loop();
if (_ret === 'continue') continue;
}
// Some countries don't have `availableFormats` specified,
// because those formats are meant to be copied
// from the "main country for region".
} catch (err) {
_didIteratorError2 = true;
_iteratorError2 = err;
} finally {
try {
if (!_iteratorNormalCompletion2 && _iterator2.return) {
_iterator2.return();
}
} finally {
if (_didIteratorError2) {
throw _iteratorError2;
}
}
}
var _iteratorNormalCompletion3 = true;
var _didIteratorError3 = false;
var _iteratorError3 = undefined;
try {
for (var _iterator3 = (0, _getIterator3.default)((0, _keys2.default)(countries)), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
var _country_code = _step3.value;
var _country = countries[_country_code];
var main_country_for_region_code = country_calling_code_to_countries[_country.phone_code][0];
var main_country_for_region = countries[main_country_for_region_code];
_country.formats = main_country_for_region.formats;
// Some countries like Saint Helena and Falkland Islands
// ('AC', 'FK', 'KI', 'NU', 'SH', 'TA', ...)
// don't have any phone number formats
// and phone numbers are formatted as a block in those countries.
if (!_country.formats) {
_country.formats = [];
}
}
// Turns out that `<generalDesc><nationalNumberPattern/></generalDesc>`
// is not preemptive at all: it's too unspecific for the cases
// when several countries correspond to the same country phone code
// (e.g. NANPA: US, Canada, etc — all correspond to the same `1` country phone code).
// For these cases all those bulky `<fixedLine/>`, `<mobile/>`, etc
// patterns are required. Therefore retain them for these rare cases.
//
// This increases metadata size by 5 KiloBytes.
//
} catch (err) {
_didIteratorError3 = true;
_iteratorError3 = err;
} finally {
try {
if (!_iteratorNormalCompletion3 && _iterator3.return) {
_iterator3.return();
}
} finally {
if (_didIteratorError3) {
throw _iteratorError3;
}
}
}
var visited_countries = {};
var _iteratorNormalCompletion4 = true;
var _didIteratorError4 = false;
var _iteratorError4 = undefined;
try {
for (var _iterator4 = (0, _getIterator3.default)((0, _keys2.default)(country_calling_code_to_countries)), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
var country_calling_code = _step4.value;
var country_codes = country_calling_code_to_countries[country_calling_code];
var _iteratorNormalCompletion6 = true;
var _didIteratorError6 = false;
var _iteratorError6 = undefined;
try {
for (var _iterator6 = (0, _getIterator3.default)(country_codes), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) {
var _country_code2 = _step6.value;
if (visited_countries[_country_code2]) {
continue;
}
visited_countries[_country_code2] = true;
// Populate possible lengths
populate_possible_lengths(countries[_country_code2]);
}
// Purge `types` regular expressions (they are huge)
// when they're not needed for resolving country phone code
// to country phone number matching.
// E.g. when there's a one-to-one correspondence
// between a country phone code and a country code
} catch (err) {
_didIteratorError6 = true;
_iteratorError6 = err;
} finally {
try {
if (!_iteratorNormalCompletion6 && _iterator6.return) {
_iterator6.return();
}
} finally {
if (_didIteratorError6) {
throw _iteratorError6;
}
}
}
var all_types_required = country_codes.length > 1;
if (!extended && !included_phone_number_types && !all_types_required) {
delete countries[country_codes[0]].types;
continue;
}
var _iteratorNormalCompletion7 = true;
var _didIteratorError7 = false;
var _iteratorError7 = undefined;
try {
for (var _iterator7 = (0, _getIterator3.default)(country_codes), _step7; !(_iteratorNormalCompletion7 = (_step7 = _iterator7.next()).done); _iteratorNormalCompletion7 = true) {
var _country_code3 = _step7.value;
// Leading digits for a country are sufficient
// to resolve country phone code ambiguity.
// So retaining all phone number type regular expressions
// is not required in this case.
if (!extended && !included_phone_number_types) {
if (countries[_country_code3].leading_digits) {
delete countries[_country_code3].types;
continue;
}
}
var types = countries[_country_code3].types;
// Find duplicate regular expressions for types
// and just discard such duplicate types
// to reduce metadata size (by 5 KiloBytes).
// Or retain regular expressions just for the
// specified phone number types (if configured).
var _iteratorNormalCompletion8 = true;
var _didIteratorError8 = false;
var _iteratorError8 = undefined;
try {
for (var _iterator8 = (0, _getIterator3.default)(phone_number_types), _step8; !(_iteratorNormalCompletion8 = (_step8 = _iterator8.next()).done); _iteratorNormalCompletion8 = true) {
var _type2 = _step8.value;
if (!types[_type2]) {
continue;
}
// Retain regular expressions just for the
// specified phone number types (if configured).
if (included_phone_number_types) {
if (!all_types_required && !included_phone_number_types.has(_type2)) {
delete types[_type2];
}
}
// Remove redundant types
// (other types having the same regular expressions as this one)
else {
// Sometimes fixed line pattern is the same as for mobile.
if (types.fixed_line && types.mobile && types.fixed_line.pattern === types.mobile.pattern) {
types.mobile.pattern = '';
}
}
}
} catch (err) {
_didIteratorError8 = true;
_iteratorError8 = err;
} finally {
try {
if (!_iteratorNormalCompletion8 && _iterator8.return) {
_iterator8.return();
}
} finally {
if (_didIteratorError8) {
throw _iteratorError8;
}
}
}
}
} catch (err) {
_didIteratorError7 = true;
_iteratorError7 = err;
} finally {
try {
if (!_iteratorNormalCompletion7 && _iterator7.return) {
_iterator7.return();
}
} finally {
if (_didIteratorError7) {
throw _iteratorError7;
}
}
}
}
} catch (err) {
_didIteratorError4 = true;
_iteratorError4 = err;
} finally {
try {
if (!_iteratorNormalCompletion4 && _iterator4.return) {
_iterator4.return();
}
} finally {
if (_didIteratorError4) {
throw _iteratorError4;
}
}
}
return {
version: version,
countries: countries,
country_calling_codes: country_calling_code_to_countries
};
});
};
var _xml2js = require('xml2js');
var _bluebird = require('bluebird');
var _bluebird2 = _interopRequireDefault(_bluebird);
var _AsYouType = require('../AsYouType');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var phone_number_types = ['premium_rate', 'toll_free', 'shared_cost', 'voip', 'personal_number', 'pager', 'uan', 'voice_mail', 'fixed_line', 'mobile'];
// Excessive fields from "PhoneNumberMetadata.xml"
// aren't included to reduce code complexity and size:
//
// * `<references>` — a link to ITU (International Telecommunication Union)
// document describing phone numbering plan for a country
//
// * `<noInternationalDialling>` — who needs to input non-internationally-dialable phones
//
// * `<areaCodeOptional>` — we aren't in the XXth century,
// it's a globalized world, so write your
// phone numbers with area codes.
//
// * `<fixedLine>`, `<mobile>`, `<pager>`,
// `<tollFree>`, `<premiumRate>`,
// `<sharedCost>`, `<personalNumber>`,
// `<voip>`, `<uan>`, `<voicemail>` — who needs that in the XXIst century.
// just go mobile and stop talking nonsense.
//
// * `internationalPrefix`,
// `preferredInternationalPrefix` — who needs to parse (or format) those weird
// "internationally dialed" phone numbers
// like "011 ..." in the USA.
// this isn't XXth century, just use mobile phones.
//
// * `preferredExtnPrefix` — screw phone number extensions
//
// * `leadingZeroPossible` — (aka "italian leading zero")
// who needs to parse a phone number into an integer.
// just keep it as a string.
//
// * `carrierCodeFormattingRule` — only used in Brazil and Colombia
// when dialing from within those countries
// from mobile phones to fixed line phone numbers.
// i guess brazilians and colombians
// already know when to add those carrier codes
// by themselves (and when not to add them)
//
// * `mobileNumberPortableRegion` — is only used to disable phone number type detection
//
// * `<possibleLengths>` — is a redundant field to speed up testing of
// whether a phone number format can be used to format
// a particular national (significant) phone number.
//
// `libphonenumber/BuildMetadataFromXml.java` was used as a reference.
// https://github.com/googlei18n/libphonenumber/blob/master/tools/java/common/src/com/google/i18n/phonenumbers/BuildMetadataFromXml.java
//
// There are three Xml metadata files in Google's `libphonenumber`:
//
// * PhoneNumberMetadata.xml — core data, used both for parse/format and "as you type"
//
// * PhoneNumberAlternateFormats.xml — alternative phone number formats.
// is presumably used for parsing phone numbers
// written in "alternative" formats.
// is not used by "as you type"
// presumably because of formats ambiguity
// when combined with the core data.
// this metadata is not used in this library
// as there's no clear description on what to do with it
// and how it works in the original `libphonenumber` code.
//
// * ShortNumberMetadata.xml — emergency numbers, etc. not used in this library.
//
// @returns
//
// {
// country_calling_codes:
// {
// '7': ['RU', 'KZ', ...],
// ...
// },
// countries:
// {
// RU:
// {
// phone_code: "7",
// national_number_pattern: "[347-9]\\d{9}",
// national_prefix: "8",
// national_prefix_formatting_rule: "8 ($1)",
// national_prefix_is_optional_when_formatting: true,
// types:
// {
// fixed_line: "(?:3(?:0[12]|4[1-35-79]|5[1-3]|65|8[1-58]|9[0145])|4(?:01|1[1356]|2[13467]|7[1-5]|8[1-7]|9[1-689])|8(?:1[1-8]|2[01]|3[13-6]|4[0-8]|5[15]|6[1-35-79]|7[1-37-9]))\\d{7}",
// mobile: "9\\d{9}",
// ...
// },
// examples:
// {
// fixed_line: '4955553535',
// mobile: '9991234567',
// ...
// },
// formats:
// [{
// pattern: "([3489]\\d{2})(\\d{3})(\\d{2})(\\d{2})",
// leading_digits_patterns: ["[3489]"],
// format: "$1 $2-$3-$4"
// },
// ...]
// },
// ...
// }
// }
//
// `country_calling_codes` map is kinda redundant.
// Not sure why did I choose to place country phone codes
// into a separate structure inside metadata instead of generating it in runtime.
// One extra feature it gives though is it tells what's the
// "default" country for a given country phone code.
// E.g. for country phone code `1` the "default" country is "US"
// and therefore "US" is the first country code in the
// `country_calling_codes["1"]` list.
// The "default" country is the one other countries
// with the same country phone code inherit phone number formatting rules from.
// For example, "CA" (Canada) inhertis phone number formatting rules from "US".
//
// `country_calling_codes` data takes about 3 KiloBytes
// so it could kinda make sense to drop it from the metadata file
// replacing it with a "default" country flag (something like `1` for "yes").
// In that scenario `country_calling_codes` would be generated on startup.
// It would have to also provide an exported `getCountryPhoneCodes()` function
// which would take `metadata` and return `country_calling_codes` map
// because some people use that `country_calling_codes` map in their projects.
//
// On the other hand, having `country_calling_codes`
// prepopulated yields more elegance to the exports
// because if `country_calling_codes` wasn't part of metadata
// it would have to be computed somewhere in global scope
// therefore the modules wouldn't be strictly "pure"
// so maybe `country_calling_codes` stays as part of metadata.
//
// Replaces $NP with national prefix and $FG with the first group ($1)
function national_prefix_formatting_rule(rule, national_prefix) {
if (!rule) {
return;
}
// Replace $NP with national prefix and $FG with the first group ($1)
return rule.replace('$NP', national_prefix).replace('$FG', '$1');
}
// Extracts various phone number type patterns from country XML metadata
function get_phone_number_types(territory) {
return phone_number_types.reduce(function (output, type) {
var camel_cased_type = underscore_to_camel_case(type);
var pattern = territory[camel_cased_type] && territory[camel_cased_type][0].nationalNumberPattern[0].replace(/\s/g, '');
var possible_lengths = territory[camel_cased_type] && territory[camel_cased_type][0].possibleLengths[0].$.national;
var possible_lengths_local = territory[camel_cased_type] && territory[camel_cased_type][0].possibleLengths[0].$.localOnly;
if (pattern) {
output[type] = {
pattern: pattern,
possible_lengths: possible_lengths
// possible_lengths_local
};
}
return output;
}, {});
}
// Extracts various phone number type examples from country XML metadata
function get_phone_number_examples(territory) {
return phone_number_types.reduce(function (output, type) {
var camel_cased_type = underscore_to_camel_case(type);
var example = territory[camel_cased_type] && territory[camel_cased_type][0].exampleNumber[0];
if (example) {
output[type] = example;
}
return output;
}, {});
}
function underscore_to_camel_case(string) {
return string.replace(/(\_\w)/g, function (match) {
return match[1].toUpperCase();
});
}
/**
* Parses a possible length string into a set of the integers that are covered.
*
* @param {string} possible_length_string - A string specifying the possible lengths of phone numbers. Follows
* this syntax: ranges or elements are separated by commas, and ranges are specified in
* [min-max] notation, inclusive. For example, [3-5],7,9,[11-14] should be parsed to
* 3,4,5,7,9,11,12,13,14.
* @return {Set}
*/
function parse_possible_lengths(possible_length_string) {
if (possible_length_string.length === 0) {
throw new TypeError('Empty possibleLength string found.');
}
var lengths = new _set2.default();
var _iteratorNormalCompletion9 = true;
var _didIteratorError9 = false;
var _iteratorError9 = undefined;
try {
for (var _iterator9 = (0, _getIterator3.default)(possible_length_string.split(',')), _step9; !(_iteratorNormalCompletion9 = (_step9 = _iterator9.next()).done); _iteratorNormalCompletion9 = true) {
var length = _step9.value;
if (length.length == 0) {
throw new TypeError('Leading, trailing or adjacent commas in possible length string ' + length + ', these should only separate numbers or ranges.');
}
if (length[0] === '[') {
if (length[length.length - 1] !== ']') {
throw new TypeError('Missing end of range character in possible length string ' + length + '.');
}
// Strip the leading and trailing [], and split on the -.
var min_max = length.slice(1, length.length - 1).split('-').map(function (_) {
return parseInt(_);
});
if (min_max.length !== 2) {
throw new TypeError('Ranges must have exactly one - character: missing for ' + length + '.');
}
var _min_max = (0, _slicedToArray3.default)(min_max, 2),
min = _min_max[0],
max = _min_max[1];
// We don't even accept [6-7] since we prefer the shorter 6,7 variant;
// for a range to be in use the hyphen needs to replace at least one digit.
if (max - min < 2) {
throw new TypeError('The first number in a range should be two or more digits lower than the second. Culprit possibleLength string: ' + length);
}
for (var i = min; i <= max; i++) {
if (lengths.has(i)) {
throw new TypeError('Duplicate length element found (' + i + ') in possibleLength string ' + length + '.');
}
lengths.add(i);
}
} else {
var _i = parseInt(length);
if (lengths.has(_i)) {
throw new TypeError('Duplicate length element found (' + _i + ') in possibleLength string ' + length + '.');
}
lengths.add(_i);
}
}
} catch (err) {
_didIteratorError9 = true;
_iteratorError9 = err;
} finally {
try {
if (!_iteratorNormalCompletion9 && _iterator9.return) {
_iterator9.return();
}
} finally {
if (_didIteratorError9) {
throw _iteratorError9;
}
}
}
return lengths;
}
var arrays_are_equal = function arrays_are_equal(a1, a2) {
return a1.length === a2.length && a1.every(function (_, i) {
return _ === a2[i];
});
};
function populate_possible_lengths(metadata) {
var types = metadata.types;
var possible_lengths = new _set2.default();
var possible_lengths_local = new _set2.default();
var _iteratorNormalCompletion10 = true;
var _didIteratorError10 = false;
var _iteratorError10 = undefined;
try {
for (var _iterator10 = (0, _getIterator3.default)((0, _keys2.default)(types)), _step10; !(_iteratorNormalCompletion10 = (_step10 = _iterator10.next()).done); _iteratorNormalCompletion10 = true) {
var _type = _step10.value;
var type_possible_lengths = parse_possible_lengths(types[_type].possible_lengths);
var _iteratorNormalCompletion13 = true;
var _didIteratorError13 = false;
var _iteratorError13 = undefined;
try {
for (var _iterator13 = (0, _getIterator3.default)(type_possible_lengths), _step13; !(_iteratorNormalCompletion13 = (_step13 = _iterator13.next()).done); _iteratorNormalCompletion13 = true) {
var _i2 = _step13.value;
possible_lengths.add(_i2);
}
} catch (err) {
_didIteratorError13 = true;
_iteratorError13 = err;
} finally {
try {
if (!_iteratorNormalCompletion13 && _iterator13.return) {
_iterator13.return();
}
} finally {
if (_didIteratorError13) {
throw _iteratorError13;
}
}
}
types[_type].possible_lengths = (0, _from2.default)(type_possible_lengths);
if (types[_type].possible_lengths_local) {
var type_possible_lengths_local = parse_possible_lengths(types[_type].possible_lengths_local);
var _iteratorNormalCompletion14 = true;
var _didIteratorError14 = false;
var _iteratorError14 = undefined;
try {
for (var _iterator14 = (0, _getIterator3.default)(type_possible_lengths_local), _step14; !(_iteratorNormalCompletion14 = (_step14 = _iterator14.next()).done); _iteratorNormalCompletion14 = true) {
var i = _step14.value;
possible_lengths_local.add(i);
}
} catch (err) {
_didIteratorError14 = true;
_iteratorError14 = err;
} finally {
try {
if (!_iteratorNormalCompletion14 && _iterator14.return) {
_iterator14.return();
}
} finally {
if (_didIteratorError14) {
throw _iteratorError14;
}
}
}
types[_type].possible_lengths_local = (0, _from2.default)(type_possible_lengths_local);
}
}
} catch (err) {
_didIteratorError10 = true;
_iteratorError10 = err;
} finally {
try {
if (!_iteratorNormalCompletion10 && _iterator10.return) {
_iterator10.return();
}
} finally {
if (_didIteratorError10) {
throw _iteratorError10;
}
}
}
var _iteratorNormalCompletion11 = true;
var _didIteratorError11 = false;
var _iteratorError11 = undefined;
try {
for (var _iterator11 = (0, _getIterator3.default)(possible_lengths_local), _step11; !(_iteratorNormalCompletion11 = (_step11 = _iterator11.next()).done); _iteratorNormalCompletion11 = true) {
var _i3 = _step11.value;
if (possible_lengths.has(_i3)) {
possible_lengths_local.delete(_i3);
}
}
} catch (err) {
_didIteratorError11 = true;
_iteratorError11 = err;
} finally {
try {
if (!_iteratorNormalCompletion11 && _iterator11.return) {
_iterator11.return();
}
} finally {
if (_didIteratorError11) {
throw _iteratorError11;
}
}
}
metadata.possible_lengths = (0, _from2.default)(possible_lengths);
metadata.possible_lengths.sort(function (a, b) {
return a - b;
});
if (possible_lengths_local.size > 0) {
metadata.possible_lengths_local = (0, _from2.default)(possible_lengths_local);
metadata.possible_lengths_local.sort(function (a, b) {
return a - b;
});
}
// Remove duplicates.
var _iteratorNormalCompletion12 = true;
var _didIteratorError12 = false;
var _iteratorError12 = undefined;
try {
for (var _iterator12 = (0, _getIterator3.default)((0, _keys2.default)(types)), _step12; !(_iteratorNormalCompletion12 = (_step12 = _iterator12.next()).done); _iteratorNormalCompletion12 = true) {
var _type3 = _step12.value;
if (arrays_are_equal(types[_type3].possible_lengths, metadata.possible_lengths)) {
delete types[_type3].possible_lengths;
}
if (types[_type3].possible_lengths_local && metadata.possible_lengths_local && arrays_are_equal(types[_type3].possible_lengths_local, metadata.possible_lengths_local)) {
delete types[_type3].possible_lengths_local;
}
}
} catch (err) {
_didIteratorError12 = true;
_iteratorError12 = err;
} finally {
try {
if (!_iteratorNormalCompletion12 && _iterator12.return) {
_iterator12.return();
}
} finally {
if (_didIteratorError12) {
throw _iteratorError12;
}
}
}
}
//# sourceMappingURL=generate.js.map