UNPKG

@singleton-i18n/angular-client

Version:

Singleton client code for Angular 10.

399 lines 62.7 kB
/* * Copyright 2019-2021 VMware, Inc. * SPDX-License-Identifier: EPL-2.0 */ import { Decimal } from 'decimal.js-light'; import { NumberFormatTypes, RoundingMode, CurrenciesDataType } from './number.format.model'; import { isDefined, isEmptyObject, parseOption } from '../util'; import { Plural } from './plural/plural.formatter'; const DECIMAL_SEP = '.'; const ZERO_CHAR = '0'; const GROUP_SEP = ','; const DIGIT_CHAR = '#'; const PATTERN_SEP = ';'; const MIN_INTEGER_RANGE = 1; const MAX_INTEGER_RANGE = 21; const MIN_FRACTION_RANGE = 0; const MAX_FRACTION_RANGE = 20; function getCompactData(data, display) { const displayType = display === 'long' ? 'long' : 'short'; const compactData = data['decimalFormats-' + displayType].decimalFormat; let compactMap; let maxExponent = 0; compactMap = Object.keys(compactData).reduce((newItem, compactKey) => { const numberExponent = compactKey.split('0').length - 1; const pluralForm = compactKey.split('-')[2]; newItem[numberExponent] = newItem[numberExponent] || {}; newItem[numberExponent][pluralForm] = compactData[compactKey]; maxExponent = Math.max(numberExponent, maxExponent); return newItem; }, {}); compactMap.maxExponent = maxExponent; return compactMap; } class Formatter { decimal(data, locale) { const decimalFormats = data.numberFormats.decimalFormats; const symbol = data.numberSymbols; const formatsInfo = this.parseFormats(decimalFormats); const formatsData = data.numberFormats; return (value, formatOptions) => { let currentFormats = formatsInfo; let compactData; if (!isEmptyObject(formatOptions)) { currentFormats = this.resetFormats(formatsInfo, RoundingMode.ROUND_HALF_EVEN, formatOptions); if (formatOptions.notation && formatOptions.notation === 'compact') { compactData = getCompactData(formatsData, formatOptions.compactDisplay); } } return this.resetString(currentFormats, symbol, value, compactData, locale); }; } currencies(data, locale) { const formatsData = data.numberFormats; const currencyFormats = data.currencyFormats; const symbol = data.numberSymbols; const formatsInfo = this.parseFormats(currencyFormats); let nuDigits; if (data.defaultNumberingSystem !== 'latn') { nuDigits = data.numberingSystem._digits || undefined; } const currencySymbolFormatter = this.currencySymbol(data); return (value, currencyCode, formatOptions) => { const currentFormats = this.resetCurrencyFormatsInfo(formatsInfo, data, currencyCode, formatOptions); let compactData; if (!isEmptyObject(formatOptions) && formatOptions.notation === 'compact') { compactData = getCompactData(formatsData, formatOptions.compactDisplay); compactData.nuDigits = nuDigits; } const res = this.resetString(currentFormats, symbol, value, compactData, locale); const currencySymbol = currencySymbolFormatter(currencyCode); return res.replace(/\u00A4/g, currencySymbol); }; } currencySymbol(data) { return (currencyCode) => { const currencySymbol = data.currencySymbols[currencyCode] && data.currencySymbols[currencyCode].symbol ? data.currencySymbols[currencyCode].symbol : currencyCode; return currencySymbol; }; } percent(data) { const percentFormats = data.numberFormats.percentFormats; const symbol = data.numberSymbols; const formatsInfo = this.parseFormats(percentFormats); return (value, formatOptions) => { let currentFormats = formatsInfo; if (!isEmptyObject(formatOptions)) { currentFormats = this.resetFormats(formatsInfo, RoundingMode.ROUND_HALF_EVEN, formatOptions); } value = +this.resetPercentNumber(value); return this.resetString(currentFormats, symbol, value); }; } plural(data) { const decimalFormats = data.numberFormats.decimalFormats; let formatsInfo = this.parseFormats(decimalFormats); return (value, min, max) => { if (isDefined(max) || isDefined(min)) { formatsInfo = this.resetFormats(formatsInfo, RoundingMode.ROUND_HALF_EVEN); } return this.roundingNumber(value, formatsInfo.minFrac, formatsInfo.maxFrac, formatsInfo.round); }; } resetFormats(formats, round, formatOptions) { // assign the value type to a new object const finalFormats = Object.assign({}, formats); // in compact number formats, reset default digits if (formatOptions.notation && formatOptions.compactDisplay) { finalFormats.maxFrac = 0; finalFormats.minFrac = 0; finalFormats.minInt = 1; } if (isDefined(formatOptions.minFractionDigits)) { finalFormats.minFrac = parseOption('minFractionDigits', [MIN_FRACTION_RANGE, MAX_FRACTION_RANGE], formatOptions.minFractionDigits); } if (isDefined(formatOptions.maxFractionDigits)) { finalFormats.maxFrac = parseOption('maxFractionDigits', [MIN_FRACTION_RANGE, MAX_FRACTION_RANGE], formatOptions.maxFractionDigits); } else if (finalFormats.minFrac !== null && finalFormats.minFrac > finalFormats.maxFrac) { // in the currency formatting, if the maximum fraction digit undefined in pattern, set the min as max finalFormats.maxFrac = finalFormats.minFrac; } if (isDefined(formatOptions.minIntegerDigits)) { finalFormats.minInt = parseOption('minIntegerDigits', [MIN_INTEGER_RANGE, MAX_INTEGER_RANGE], formatOptions.minIntegerDigits); } if (isDefined(round)) { finalFormats.round = round; } return finalFormats; } /** * Get info from the formats * eg: ¤#,##0.00 * return: { gSize: 3, lgSize: 3, maxFrac: 2, minFrac: 2, minInt: 1, negPre: "-¤", posPre: "¤" } */ parseFormats(format, minusSign = '-') { const patternInfo = { 'minInt': 1, 'minFrac': 0, 'maxFrac': 0, 'posPre': '', 'posSuf': '', 'negPre': '', 'negSuf': '', 'gSize': 0, 'lgSize': 0, 'round': RoundingMode.ROUND_HALF_EVEN }; const patternParts = format.split(PATTERN_SEP); const positive = patternParts[0]; const negative = patternParts[1]; const positiveParts = positive.indexOf(DECIMAL_SEP) !== -1 ? positive.split(DECIMAL_SEP) : [ positive.substring(0, positive.lastIndexOf(ZERO_CHAR) + 1), positive.substring(positive.lastIndexOf(ZERO_CHAR) + 1) ]; const integer = positiveParts[0]; const fraction = positiveParts[1] || ''; patternInfo.posPre = integer.substr(0, integer.indexOf(DIGIT_CHAR)); for (let i = 0; i < fraction.length; i++) { const ch = fraction.charAt(i); if (ch === ZERO_CHAR) { patternInfo.minFrac = patternInfo.maxFrac = i + 1; } else if (ch === DIGIT_CHAR) { patternInfo.maxFrac = i + 1; } else { patternInfo.posSuf += ch; } } const groups = integer.split(GROUP_SEP); patternInfo.gSize = groups[1] ? groups[1].length : 0; patternInfo.lgSize = (groups[2] || groups[1]) ? (groups[2] || groups[1]).length : 0; if (negative) { const trunkLen = positive.length - patternInfo.posPre.length - patternInfo.posSuf.length; const pos = negative.indexOf(DIGIT_CHAR); patternInfo.negPre = negative.substr(0, pos).replace(/'/g, ''); patternInfo.negSuf = negative.substr(pos + trunkLen).replace(/'/g, ''); } else { patternInfo.negPre = minusSign + patternInfo.posPre; patternInfo.negSuf = patternInfo.posSuf; } return patternInfo; } parseNumber(numStr) { const digits = []; let numberOfIntegerDigits; let i; // Decimal point? if ((numberOfIntegerDigits = numStr.indexOf(DECIMAL_SEP)) > -1) { numStr = numStr.replace(DECIMAL_SEP, ''); } if (numberOfIntegerDigits < 0) { // There was no decimal point or exponent so it is an integer. numberOfIntegerDigits = numStr.length; } for (i = 0; i < numStr.length; i++) { digits.push(+numStr.charAt(i)); } return { digits: digits, integerLen: numberOfIntegerDigits }; } /** * rounding number */ roundingNumber(number, minFrac, maxFrac, mode) { // TODO exponent const digists = number.toString().replace(DECIMAL_SEP, '').length; const decimalIndex = number.toString().indexOf(DECIMAL_SEP); const numberOfIntegerDigits = decimalIndex > -1 ? decimalIndex : digists; const fractionLen = digists - numberOfIntegerDigits; if (minFrac > maxFrac) { throw new Error(`The minimum number of digits after fraction (${minFrac}) is higher than the maximum (${maxFrac}).`); } const newDecimal = new Decimal(number); const fractionSize = Math.min(Math.max(minFrac, fractionLen), maxFrac); const roundedNum = newDecimal.toFixed(fractionSize, mode); return roundedNum; } resetCurrencyFormatsInfo(formatsInfo, data, currencyCode, formatOptions) { if (!data.fractions[currencyCode] && isEmptyObject(formatOptions)) { return formatsInfo; } // assign the value type to a new object let finalFormats = Object.assign({}, formatsInfo); if (data.fractions[currencyCode]) { finalFormats.maxFrac = data.fractions[currencyCode][CurrenciesDataType.DIGIST]; finalFormats.minFrac = finalFormats.maxFrac; } const rounding = data.fractions[currencyCode] && data.fractions[currencyCode][CurrenciesDataType.ROUNDING]; finalFormats.round = !rounding || rounding === '0' ? formatsInfo.round : rounding; if (!isEmptyObject(formatOptions)) { finalFormats = this.resetFormats(finalFormats, finalFormats.round, formatOptions); } return finalFormats; } resetPercentNumber(num) { return new Decimal(num).times(100).valueOf(); } resetString(formatsInfo, symbol, value, compactData, locale) { let formattedText; const minFraction = formatsInfo.minFrac; const maxFraction = formatsInfo.maxFrac; const minInt = formatsInfo.minInt; // compact let numberExponent; let compactPattern; if (!isEmptyObject(compactData)) { numberExponent = Math.abs(Math.floor(value)).toString().length - 1; numberExponent = Math.min(numberExponent, compactData.maxExponent); // Use default plural form to perform initial decimal shift if (numberExponent >= 3) { compactPattern = compactData[numberExponent] && compactData[numberExponent].other; } // if compactPattern is 0, output the number. if (compactPattern === '0') { compactPattern = null; } else if (compactPattern) { const compactDigits = compactPattern.split('0').length - 1; const divisor = numberExponent - (compactDigits - 1); value = value / Math.pow(10, divisor); } } // number rounding let numberStr = this.roundingNumber(Math.abs(value), minFraction, maxFraction, formatsInfo.round); // if no min fraction limit, remove meaningless 0 if (!minFraction) { // if the number is >= 1e21 // use +numberStr will returns a string representing the number in exponential notation. numberStr = +numberStr >= 1e21 ? numberStr : String(+numberStr); } let compactPrefix = ''; let compactSuffix = ''; if (compactData && compactPattern) { // Get plural form after possible roundings const pluralFunc = new Plural().getFunc(locale); const pluralForm = pluralFunc && pluralFunc(+value) ? pluralFunc(+value) : 'other'; compactPattern = compactData[numberExponent][pluralForm] || compactPattern; // if the compact pattern contains protected . compactPattern = compactPattern.replace('\'.\'', '.'); const compactProperties = compactPattern.match(/^([^0]*)(0+)([^0]*)$/); compactPrefix = compactProperties[1]; compactSuffix = compactProperties[3]; } // parse the number string const parsedNumber = this.parseNumber(numberStr); let digits = parsedNumber.digits; let integerLen = parsedNumber.integerLen; let decimals = []; // padding zero for integer if integerLen < minInt for (; integerLen < minInt; integerLen++) { digits.unshift(0); } // extract decimals digits if (integerLen > 0) { decimals = digits.splice(integerLen, digits.length); } else { decimals = digits; digits = [0]; } if (compactData && compactData.nuDigits) { digits.forEach((item, idx) => { digits[idx] = compactData.nuDigits[+item]; }); decimals.forEach((item, idx) => { decimals[idx] = compactData.nuDigits[+item]; }); } // format the integer digits with grouping separators const groups = []; if (digits.length >= formatsInfo.lgSize) { groups.unshift(digits.splice(-formatsInfo.lgSize, digits.length).join('')); } while (digits.length > formatsInfo.gSize) { groups.unshift(digits.splice(-formatsInfo.gSize, digits.length).join('')); } if (digits.length) { groups.unshift(digits.join('')); } formattedText = groups.join(symbol.group); // append the decimal digits if (decimals.length) { formattedText += symbol.decimal + decimals.join(''); } // append the compact infos formattedText = compactPrefix + formattedText + compactSuffix; if (value < 0) { return formatsInfo.negPre + formattedText + formatsInfo.negSuf; } else { return formatsInfo.posPre + formattedText + formatsInfo.posSuf; } } } export class FormatterFactory { constructor() { this.mapping = {}; this.formatter = new Formatter(); } getFormatter(locale, type) { if (!this.mapping[locale]) { this.mapping[locale] = {}; } let formatter; if (this.mapping[locale] && this.mapping[locale][type]) { formatter = this.mapping[locale] && this.mapping[locale][type]; } return formatter; } currencies(data, locale) { let formatter = this.getFormatter(locale, NumberFormatTypes.CURRENCIES); if (!formatter) { formatter = this.formatter.currencies(data, locale); this.mapping[locale][NumberFormatTypes.CURRENCIES] = formatter; } return formatter; } currenySymbol(data, locale) { let formatter = this.getFormatter(locale, NumberFormatTypes.CURRENCYSYMBOL); if (!formatter) { formatter = this.formatter.currencySymbol(data); this.mapping[locale][NumberFormatTypes.CURRENCYSYMBOL] = formatter; } return formatter; } percent(data, locale) { let formatter = this.getFormatter(locale, NumberFormatTypes.PERCENT); if (!formatter) { formatter = this.formatter.percent(data); this.mapping[locale][NumberFormatTypes.PERCENT] = formatter; } return formatter; } decimal(data, locale) { let formatter = this.getFormatter(locale, NumberFormatTypes.DECIMAL); if (!formatter) { formatter = this.formatter.decimal(data, locale); this.mapping[locale][NumberFormatTypes.DECIMAL] = formatter; } return formatter; } roundNumberForPlural(data, locale) { let formatter = this.getFormatter(locale, NumberFormatTypes.PLURAL); if (!formatter) { formatter = this.formatter.plural(data); this.mapping[locale][NumberFormatTypes.PLURAL] = formatter; } return formatter; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibnVtYmVyLmZvcm1hdHRlci5qcyIsInNvdXJjZVJvb3QiOiIvaG9tZS9ybGlnZW5nL1Byb2plY3RzL0Rldm9wcy9DbGllbnRfQW5ndWxhcl9HaXRIdWJfTnBtanMvdmlwL2NpL3B1YjJvcmcvQ2xpZW50X0FuZ3VsYXJfR2l0SHViX05wbWpzL3NpbmdsZXRvbi9wcm9qZWN0cy9hbmd1bGFyLWNsaWVudC8iLCJzb3VyY2VzIjpbInNyYy9mb3JtYXR0ZXJzL251bWJlci5mb3JtYXR0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7OztHQUdHO0FBQ0gsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQzNDLE9BQU8sRUFDSCxpQkFBaUIsRUFHakIsWUFBWSxFQUNaLGtCQUFrQixFQUVyQixNQUFNLHVCQUF1QixDQUFDO0FBQy9CLE9BQU8sRUFBRSxTQUFTLEVBQUUsYUFBYSxFQUFFLFdBQVcsRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUNoRSxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFFbkQsTUFBTSxXQUFXLEdBQUcsR0FBRyxDQUFDO0FBQ3hCLE1BQU0sU0FBUyxHQUFHLEdBQUcsQ0FBQztBQUN0QixNQUFNLFNBQVMsR0FBRyxHQUFHLENBQUM7QUFDdEIsTUFBTSxVQUFVLEdBQUcsR0FBRyxDQUFDO0FBQ3ZCLE1BQU0sV0FBVyxHQUFHLEdBQUcsQ0FBQztBQUV4QixNQUFNLGlCQUFpQixHQUFHLENBQUMsQ0FBQztBQUM1QixNQUFNLGlCQUFpQixHQUFHLEVBQUUsQ0FBQztBQUM3QixNQUFNLGtCQUFrQixHQUFHLENBQUMsQ0FBQztBQUM3QixNQUFNLGtCQUFrQixHQUFHLEVBQUUsQ0FBQztBQVU5QixTQUFTLGNBQWMsQ0FBQyxJQUFTLEVBQUUsT0FBZTtJQUM5QyxNQUFNLFdBQVcsR0FBRyxPQUFPLEtBQUssTUFBTSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQztJQUMx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Q3JELElBQUksU0FBUyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUUsTUFBTSxFQUFFLGlCQUFpQixDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3JFLElBQUksQ0FBQyxTQUFTLEVBQUU7WUFDWixTQUFTLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDeEMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxpQkFBaUIsQ0FBQyxNQUFNLENBQUMsR0FBRyxTQUFTLENBQUM7U0FDOUQ7UUFDRCxPQUFPLFNBQVMsQ0FBQztJQUNyQixDQUFDO0NBQ0oiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IDIwMTktMjAyMSBWTXdhcmUsIEluYy5cbiAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBFUEwtMi4wXG4gKi9cbmltcG9ydCB7IERlY2ltYWwgfSBmcm9tICdkZWNpbWFsLmpzLWxpZ2h0JztcbmltcG9ydCB7XG4gICAgTnVtYmVyRm9ybWF0VHlwZXMsXG4gICAgRGF0YUZvck51bWJlcixcbiAgICBEYXRhRm9yQ3VycmVuY3ksXG4gICAgUm91bmRpbmdNb2RlLFxuICAgIEN1cnJlbmNpZXNEYXRhVHlwZSxcbiAgICBOdW1iZXJGb3JtYXRPcHRpb25zXG59IGZyb20gJy4vbnVtYmVyLmZvcm1hdC5tb2RlbCc7XG5pbXBvcnQgeyBpc0RlZmluZWQsIGlzRW1wdHlPYmplY3QsIHBhcnNlT3B0aW9uIH0gZnJvbSAnLi4vdXRpbCc7XG5pbXBvcnQgeyBQbHVyYWwgfSBmcm9tICcuL3BsdXJhbC9wbHVyYWwuZm9ybWF0dGVyJztcblxuY29uc3QgREVDSU1BTF9TRVAgPSAnLic7XG5jb25zdCBaRVJPX0NIQVIgPSAnMCc7XG5jb25zdCBHUk9VUF9TRVAgPSAnLCc7XG5jb25zdCBESUdJVF9DSEFSID0gJyMnO1xuY29uc3QgUEFUVEVSTl9TRVAgPSAnOyc7XG5cbmNvbnN0IE1JTl9JTlRFR0VSX1JBTkdFID0gMTtcbmNvbnN0IE1BWF9JTlRFR0VSX1JBTkdFID0gMjE7XG5jb25zdCBNSU5fRlJBQ1RJT05fUkFOR0UgPSAwO1xuY29uc3QgTUFYX0ZSQUNUSU9OX1JBTkdFID0gMjA7XG5cblxuaW50ZXJmYWNlIFBhcnNlZE51bWJlciB7XG4gICAgLy8gYW4gYXJyYXkgb2YgZGlnaXRzIGNvbnRhaW5pbmcgbGVhZGluZyB6ZXJvcyBhcyBuZWNlc3NhcnlcbiAgICBkaWdpdHM6IG51bWJlcltdO1xuICAgIC8vIHRoZSBudW1iZXIgb2YgdGhlIGRpZ2l0cyBpbiBgZGlnaXRzYCB0aGF0IGFyZSB0byB0aGUgbGVmdCBvZiB0aGUgZGVjaW1hbCBwb2ludFxuICAgIGludGVnZXJMZW46IG51bWJlcjtcbn1cblxuZnVuY3Rpb24gZ2V0Q29tcGFjdERhdGEoZGF0YTogYW55LCBkaXNwbGF5OiBzdHJpbmcpIHtcbiAgICBjb25zdCBkaXNwbGF5VHlwZSA9IGRpc3BsYXkgPT09ICdsb25nJyA/ICdsb25nJyA6ICdzaG9ydCc7XG4gICAgY29uc3QgY29tcGFjdERhdGEgPSBkYXRhWydkZWNpbWFsRm9ybWF0cy0nICsgZGlzcGxheVR5cGVdLmRlY2ltYWxGb3JtYXQ7XG4gICAgbGV0IGNvbXBhY3RNYXA6IGFueTtcbiAgICBsZXQgbWF4RXhwb25lbnQgPSAwO1xuICAgIGNvbXBhY3RNYXAgPSBPYmplY3Qua2V5cyhjb21wYWN0RGF0YSkucmVkdWNlKChuZXdJdGVtLCBjb21wYWN0S2V5KSA9PiB7XG4gICAgICAgIGNvbnN0IG51bWJlckV4cG9uZW50ID0gY29tcGFjdEtleS5zcGxpdCgnMCcpLmxlbmd0aCAtIDE7XG4gICAgICAgIGNvbnN0IHBsdXJhbEZvcm0gPSBjb21wYWN0S2V5LnNwbGl0KCctJylbMl07XG4gICAgICAgIG5ld0l0ZW1bbnVtYmVyRXhwb25lbnRdID0gbmV3SXRlbVtudW1iZXJFeHBvbmVudF0gfHwge307XG4gICAgICAgIG5ld0l0ZW1bbnVtYmVyRXhwb25lbnRdW3BsdXJhbEZvcm1dID0gY29tcGFjdERhdGFbY29tcGFjdEtleV07XG4gICAgICAgIG1heEV4cG9uZW50ID0gTWF0aC5tYXgobnVtYmVyRXhwb25lbnQsIG1heEV4cG9uZW50KTtcbiAgICAgICAgcmV0dXJuIG5ld0l0ZW07XG4gICAgfSwge30pO1xuXG4gICAgY29tcGFjdE1hcC5tYXhFeHBvbmVudCA9IG1heEV4cG9uZW50O1xuICAgIHJldHVybiBjb21wYWN0TWFwO1xufVxuXG5jbGFzcyBGb3JtYXR0ZXIge1xuICAgIGRlY2ltYWwoZGF0YTogRGF0YUZvck51bWJlciwgbG9jYWxlOiBzdHJpbmcpIHtcbiAgICAgICAgY29uc3QgZGVjaW1hbEZvcm1hdHMgPSBkYXRhLm51bWJlckZvcm1hdHMuZGVjaW1hbEZvcm1hdHM7XG4gICAgICAgIGNvbnN0IHN5bWJvbCA9IGRhdGEubnVtYmVyU3ltYm9scztcbiAgICAgICAgY29uc3QgZm9ybWF0c0luZm8gPSB0aGlzLnBhcnNlRm9ybWF0cyhkZWNpbWFsRm9ybWF0cyk7XG4gICAgICAgIGNvbnN0IGZvcm1hdHNEYXRhID0gZGF0YS5udW1iZXJGb3JtYXRzO1xuICAgICAgICByZXR1cm4gKHZhbHVlOiBudW1iZXIsIGZvcm1hdE9wdGlvbnM/OiBOdW1iZXJGb3JtYXRPcHRpb25zKSA9PiB7XG4gICAgICAgICAgICBsZXQgY3VycmVudEZvcm1hdHMgPSBmb3JtYXRzSW5mbztcbiAgICAgICAgICAgIGxldCBjb21wYWN0RGF0YTtcbiAgICAgICAgICAgIGlmICggIWlzRW1wdHlPYmplY3QoZm9ybWF0T3B0aW9ucykgKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudEZvcm1hdHMgPSB0aGlzLnJlc2V0Rm9ybWF0cyggZm9ybWF0c0luZm8sIFJvdW5kaW5nTW9kZS5ST1VORF9IQUxGX0VWRU4sIGZvcm1hdE9wdGlvbnMgKTtcbiAgICAgICAgICAgICAgICBpZiAoIGZvcm1hdE9wdGlvbnMubm90YXRpb24gJiYgZm9ybWF0T3B0aW9ucy5ub3RhdGlvbiA9PT0gJ2NvbXBhY3QnICkge1xuICAgICAgICAgICAgICAgICAgICBjb21wYWN0RGF0YSA9IGdldENvbXBhY3REYXRhKGZvcm1hdHNEYXRhLCBmb3JtYXRPcHRpb25zLmNvbXBhY3REaXNwbGF5KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5yZXNldFN0cmluZyhjdXJyZW50Rm9ybWF0cywgc3ltYm9sLCB2YWx1ZSwgY29tcGFjdERhdGEsIGxvY2FsZSk7XG4gICAgICAgIH07XG4gICAgfVxuICAgIGN1cnJlbmNpZXMoZGF0YTogRGF0YUZvckN1cnJlbmN5LCBsb2NhbGU6IHN0cmluZykge1xuICAgICAgICBjb25zdCBmb3JtYXRzRGF0YSA9IGRhdGEubnVtYmVyRm9ybWF0cztcbiAgICAgICAgY29uc3QgY3VycmVuY3lGb3JtYXRzID0gZGF0YS5jdXJyZW5jeUZvcm1hdHM7XG4gICAgICAgIGNvbnN0IHN5bWJvbCA9IGRhdGEubnVtYmVyU3ltYm9scztcbiAgICAgICAgY29uc3QgZm9ybWF0c0luZm8gPSB0aGlzLnBhcnNlRm9ybWF0cyhjdXJyZW5jeUZvcm1hdHMpO1xuICAgICAgICBsZXQgbnVEaWdpdHM6IHN0cmluZztcbiAgICAgICAgaWYgKCBkYXRhLmRlZmF1bHROdW1iZXJpbmdTeXN0ZW0gIT09ICdsYXRuJykge1xuICAgICAgICAgICAgbnVEaWdpdHMgPSBkYXRhLm51bWJlcmluZ1N5c3RlbS5fZGlnaXRzIHx8IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBjdXJyZW5jeVN5bWJvbEZvcm1hdHRlciA9IHRoaXMuY3VycmVuY3lTeW1ib2woZGF0YSk7XG4gICAgICAgIHJldHVybiAodmFsdWU6IG51bWJlciwgY3VycmVuY3lDb2RlOiBzdHJpbmcsIGZvcm1hdE9wdGlvbnM/OiBOdW1iZXJGb3JtYXRPcHRpb25zKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBjdXJyZW50Rm9ybWF0cyA9IHRoaXMucmVzZXRDdXJyZW5jeUZvcm1hdHNJbmZvKGZvcm1hdHNJbmZvLCBkYXRhLCBjdXJyZW5jeUNvZGUsIGZvcm1hdE9wdGlvbnMpO1xuICAgICAgICAgICAgbGV0IGNvbXBhY3REYXRhO1xuICAgICAgICAgICAgaWYgKCAhaXNFbXB0eU9iamVjdChmb3JtYXRPcHRpb25zKSAmJiBmb3JtYXRPcHRpb25zLm5vdGF0aW9uID09PSAnY29tcGFjdCcgKSB7XG4gICAgICAgICAgICAgICAgY29tcGFjdERhdGEgPSBnZXRDb21wYWN0RGF0YShmb3JtYXRzRGF0YSwgZm9ybWF0T3B0aW9ucy5jb21wYWN0RGlzcGxheSk7XG4gICAgICAgICAgICAgICAgY29tcGFjdERhdGEubnVEaWdpdHMgPSBudURpZ2l0cztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHJlcyA9IHRoaXMucmVzZXRTdHJpbmcoY3VycmVudEZvcm1hdHMsIHN5bWJvbCwgdmFsdWUsIGNvbXBhY3REYXRhLCBsb2NhbGUpO1xuICAgICAgICAgICAgY29uc3QgY3VycmVuY3lTeW1ib2wgPSBjdXJyZW5jeVN5bWJvbEZvcm1hdHRlcihjdXJyZW5jeUNvZGUpO1xuICAgICAgICAgICAgcmV0dXJuIHJlcy5yZXBsYWNlKC9cXHUwMEE0L2csIGN1cnJlbmN5U3ltYm9sKTtcbiAgICAgICAgfTtcbiAgICB9XG4gICAgY3VycmVuY3lTeW1ib2woZGF0YTogRGF0YUZvckN1cnJlbmN5KSB7XG4gICAgICAgIHJldHVybiAoY3VycmVuY3lDb2RlOiBzdHJpbmcpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGN1cnJlbmN5U3ltYm9sID0gZGF0YS5jdXJyZW5jeVN5bWJvbHNbY3VycmVuY3lDb2RlXSAmJiBkYXRhLmN1cnJlbmN5U3ltYm9sc1tjdXJyZW5jeUNvZGVdLnN5bWJvbFxuICAgICAgICAgICAgPyBkYXRhLmN1cnJlbmN5U3ltYm9sc1tjdXJyZW5jeUNvZGVdLnN5bWJvbFxuICAgICAgICAgICAgOiBjdXJyZW5jeUNvZGU7XG4gICAgICAgICAgICByZXR1cm4gY3VycmVuY3lTeW1ib2w7XG4gICAgICAgIH07XG4gICAgfVxuICAgIHBlcmNlbnQoZGF0YTogRGF0YUZvck51bWJlcikge1xuICAgICAgICBjb25zdCBwZXJjZW50Rm9ybWF0cyA9IGRhdGEubnVtYmVyRm9ybWF0cy5wZXJjZW50Rm9ybWF0cztcbiAgICAgICAgY29uc3Qgc3ltYm9sID0gZGF0YS5udW1iZXJTeW1ib2xzO1xuICAgICAgICBjb25zdCBmb3JtYXRzSW5mbyA9IHRoaXMucGFyc2VGb3JtYXRzKHBlcmNlbnRGb3JtYXRzKTtcbiAgICAgICAgcmV0dXJuICh2YWx1ZTogbnVtYmVyLCBmb3JtYXRPcHRpb25zPzogTnVtYmVyRm9ybWF0T3B0aW9ucykgPT4ge1xuICAgICAgICAgICAgbGV0IGN1cnJlbnRGb3JtYXRzID0gZm9ybWF0c0luZm87XG4gICAgICAgICAgICBpZiAoICFpc0VtcHR5T2JqZWN0KGZvcm1hdE9wdGlvbnMpICkge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRGb3JtYXRzID0gdGhpcy5yZXNldEZvcm1hdHMoIGZvcm1hdHNJbmZvLCBSb3VuZGluZ01vZGUuUk9VTkRfSEFMRl9FVkVOLCBmb3JtYXRPcHRpb25zICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YWx1ZSA9ICt0aGlzLnJlc2V0UGVyY2VudE51bWJlcih2YWx1ZSk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5yZXNldFN0cmluZyhjdXJyZW50Rm9ybWF0cywgc3ltYm9sLCB2YWx1ZSk7XG4gICAgICAgIH07XG4gICAgfVxuICAgIHBsdXJhbCggZGF0YTogRGF0YUZvck51bWJlcikge1xuICAgICAgICBjb25zdCBkZWNpbWFsRm9ybWF0cyA9IGRhdGEubnVtYmVyRm9ybWF0cy5kZWNpbWFsRm9ybWF0cztcbiAgICAgICAgbGV0IGZvcm1hdHNJbmZvID0gdGhpcy5wYXJzZUZvcm1hdHMoZGVjaW1hbEZvcm1hdHMpO1xuICAgICAgICByZXR1cm4gKHZhbHVlOiBudW1iZXIsIG1pbj86IG51bWJlciwgbWF4PzogbnVtYmVyKSA9PiB7XG4gICAgICAgICAgICBpZiAoIGlzRGVmaW5lZChtYXgpIHx8IGlzRGVmaW5lZChtaW4pICkge1xuICAgICAgICAgICAgICAgIGZvcm1hdHNJbmZvID0gdGhpcy5yZXNldEZvcm1hdHMoIGZvcm1hdHNJbmZvLCBSb3VuZGluZ01vZGUuUk9VTkRfSEFMRl9FVkVOICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5yb3VuZGluZ051bWJlcih2YWx1ZSwgZm9ybWF0c0luZm8ubWluRnJhYywgZm9ybWF0c0luZm8ubWF4RnJhYywgZm9ybWF0c0luZm8ucm91bmQpO1xuICAgICAgICB9O1xuICAgIH1cbiAgICByZXNldEZvcm1hdHMoIGZvcm1hdHM6IGFueSwgcm91bmQ6IFJvdW5kaW5nTW9kZSwgZm9ybWF0T3B0aW9ucz86IE51bWJlckZvcm1hdE9wdGlvbnMgKSB7XG4gICAgICAgIC8vIGFzc2lnbiB0aGUgdmFsdWUgdHlwZSB0byBhIG5ldyBvYmplY3RcbiAgICAgICAgY29uc3QgZmluYWxGb3JtYXRzID0gT2JqZWN0LmFzc2lnbih7fSwgZm9ybWF0cyk7XG4gICAgICAgIC8vIGluIGNvbXBhY3QgbnVtYmVyIGZvcm1hdHMsIHJlc2V0IGRlZmF1bHQgZGlnaXRzXG4gICAgICAgIGlmICggZm9ybWF0T3B0aW9ucy5ub3RhdGlvbiAmJiBmb3JtYXRPcHRpb25zLmNvbXBhY3REaXNwbGF5ICkge1xuICAgICAgICAgICAgZmluYWxGb3JtYXRzLm1heEZyYWMgPSAwO1xuICAgICAgICAgICAgZmluYWxGb3JtYXRzLm1pbkZyYWMgPSAwO1xuICAgICAgICAgICAgZmluYWxGb3JtYXRzLm1pbkludCA9IDE7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlzRGVmaW5lZChmb3JtYXRPcHRpb25zLm1pbkZyYWN0aW9uRGlnaXRzKSkge1xuICAgICAgICAgICAgZmluYWxGb3JtYXRzLm1pbkZyYWMgPSBwYXJzZU9wdGlvbignbWluRnJhY3Rpb25EaWdpdHMnLCBbTUlOX0ZSQUNUSU9OX1JBTkdFLCBNQVhfRlJBQ1RJT05fUkFOR0VdLCBmb3JtYXRPcHRpb25zLm1pbkZyYWN0aW9uRGlnaXRzKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNEZWZpbmVkKGZvcm1hdE9wdGlvbnMubWF4RnJhY3Rpb25EaWdpdHMpKSB7XG4gICAgICAgICAgICBmaW5hbEZvcm1hdHMubWF4RnJhYyA9IHBhcnNlT3B0aW9uKCdtYXhGcmFjdGlvbkRpZ2l0cycsIFtNSU5fRlJBQ1RJT05fUkFOR0UsIE1BWF9GUkFDVElPTl9SQU5HRV0sIGZvcm1hdE9wdGlvbnMubWF4RnJhY3Rpb25EaWdpdHMpO1xuICAgICAgICB9IGVsc2UgaWYgKGZpbmFsRm9ybWF0cy5taW5GcmFjICE9PSBudWxsICYmIGZpbmFsRm9ybWF0cy5taW5GcmFjID4gZmluYWxGb3JtYXRzLm1heEZyYWMpIHtcbiAgICAgICAgICAgIC8vIGluIHRoZSBjdXJyZW5jeSBmb3JtYXR0aW5nLCBpZiB0aGUgbWF4aW11bSBmcmFjdGlvbiBkaWdpdCB1bmRlZmluZWQgaW4gcGF0dGVybiwgc2V0IHRoZSBtaW4gYXMgbWF4XG4gICAgICAgICAgICBmaW5hbEZvcm1hdHMubWF4RnJhYyA9IGZpbmFsRm9ybWF0cy5taW5GcmFjO1xuICAgICAgICB9XG4gICAgICAgIGlmICggaXNEZWZpbmVkKGZvcm1hdE9wdGlvbnMubWluSW50ZWdlckRpZ2l0cykgKSB7XG4gICAgICAgICAgICBmaW5hbEZvcm1hdHMubWluSW50ID0gcGFyc2VPcHRpb24oJ21pbkludGVnZXJEaWdpdHMnLCBbTUlOX0lOVEVHRVJfUkFOR0UsIE1BWF9JTlRFR0VSX1JBTkdFXSwgZm9ybWF0T3B0aW9ucy5taW5JbnRlZ2VyRGlnaXRzKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIGlzRGVmaW5lZChyb3VuZCkgKSB7XG4gICAgICAgICAgICBmaW5hbEZvcm1hdHMucm91bmQgPSByb3VuZDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmluYWxGb3JtYXRzO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBHZXQgaW5mbyBmcm9tIHRoZSBmb3JtYXRzXG4gICAgICogZWc6IMKkIywjIzAuMDBcbiAgICAgKiByZXR1cm46IHsgZ1NpemU6IDMsIGxnU2l6ZTogMywgbWF4RnJhYzogMiwgbWluRnJhYzogMiwgbWluSW50OiAxLCBuZWdQcmU6IFwiLcKkXCIsIHBvc1ByZTogXCLCpFwiIH1cbiAgICAgKi9cbiAgICBwYXJzZUZvcm1hdHMoZm9ybWF0OiBzdHJpbmcsIG1pbnVzU2lnbiA9ICctJykge1xuICAgICAgICBjb25zdCBwYXR0ZXJuSW5mbyA9IHtcbiAgICAgICAgICAgICdtaW5JbnQnOiAxLFxuICAgICAgICAgICAgJ21pbkZyYWMnOiAwLFxuICAgICAgICAgICAgJ21heEZyYWMnOiAwLFxuICAgICAgICAgICAgJ3Bvc1ByZSc6ICcnLFxuICAgICAgICAgICAgJ3Bvc1N1Zic6ICcnLFxuICAgICAgICAgICAgJ25lZ1ByZSc6ICcnLFxuICAgICAgICAgICAgJ25lZ1N1Zic6ICcnLFxuICAgICAgICAgICAgJ2dTaXplJzogMCxcbiAgICAgICAgICAgICdsZ1NpemUnOiAwLFxuICAgICAgICAgICAgJ3JvdW5kJzogUm91bmRpbmdNb2RlLlJPVU5EX0hBTEZfRVZFTlxuICAgICAgICB9O1xuICAgICAgICBjb25zdCBwYXR0ZXJuUGFydHMgPSBmb3JtYXQuc3BsaXQoUEFUVEVSTl9TRVApO1xuICAgICAgICBjb25zdCBwb3NpdGl2ZSA9IHBhdHRlcm5QYXJ0c1swXTtcbiAgICAgICAgY29uc3QgbmVnYXRpdmUgPSBwYXR0ZXJuUGFydHNbMV07XG5cbiAgICAgICAgY29uc3QgcG9zaXRpdmVQYXJ0cyA9IHBvc2l0aXZlLmluZGV4T2YoREVDSU1BTF9TRVApICE9PSAtMVxuICAgICAgICAgICAgPyBwb3NpdGl2ZS5zcGxpdChERUNJTUFMX1NFUClcbiAgICAgICAgICAgIDogW1xuICAgICAgICAgICAgICAgIHBvc2l0aXZlLnN1YnN0cmluZygwLCBwb3NpdGl2ZS5sYXN0SW5kZXhPZihaRVJPX0NIQVIpICsgMSksXG4gICAgICAgICAgICAgICAgcG9zaXRpdmUuc3Vic3RyaW5nKHBvc2l0aXZlLmxhc3RJbmRleE9mKFpFUk9fQ0hBUikgKyAxKVxuICAgICAgICAgICAgXTtcbiAgICAgICAgY29uc3QgaW50ZWdlciA9IHBvc2l0aXZlUGFydHNbMF07XG4gICAgICAgIGNvbnN0IGZyYWN0aW9uID0gcG9zaXRpdmVQYXJ0c1sxXSB8fCAnJztcblxuICAgICAgICBwYXR0ZXJuSW5mby5wb3NQcmUgPSBpbnRlZ2VyLnN1YnN0cigwLCBpbnRlZ2VyLmluZGV4T2YoRElHSVRfQ0hBUikpO1xuXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZnJhY3Rpb24ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGNvbnN0IGNoID0gZnJhY3Rpb24uY2hhckF0KGkpO1xuICAgICAgICAgICAgaWYgKGNoID09PSBaRVJPX0NIQVIpIHtcbiAgICAgICAgICAgICAgICBwYXR0ZXJuSW5mby5taW5GcmFjID0gcGF0dGVybkluZm8ubWF4RnJhYyA9IGkgKyAxO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChjaCA9PT0gRElHSVRfQ0hBUikge1xuICAgICAgICAgICAgICAgIHBhdHRlcm5JbmZvLm1heEZyYWMgPSBpICsgMTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcGF0dGVybkluZm8ucG9zU3VmICs9IGNoO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZ3JvdXBzID0gaW50ZWdlci5zcGxpdChHUk9VUF9TRVApO1xuICAgICAgICBwYXR0ZXJuSW5mby5nU2l6ZSA9IGdyb3Vwc1sxXSA/IGdyb3Vwc1sxXS5sZW5ndGggOiAwO1xuICAgICAgICBwYXR0ZXJuSW5mby5sZ1NpemUgPSAoZ3JvdXBzWzJdIHx8IGdyb3Vwc1sxXSkgPyAoZ3JvdXBzWzJdIHx8IGdyb3Vwc1sxXSkubGVuZ3RoIDogMDtcblxuICAgICAgICBpZiAobmVnYXRpdmUpIHtcbiAgICAgICAgICAgIGNvbnN0IHRydW5rTGVuID0gcG9zaXRpdmUubGVuZ3RoIC0gcGF0dGVybkluZm8ucG9zUHJlLmxlbmd0aCAtIHBhdHRlcm5JbmZvLnBvc1N1Zi5sZW5ndGg7XG4gICAgICAgICAgICBjb25zdCBwb3MgPSBuZWdhdGl2ZS5pbmRleE9mKERJR0lUX0NIQVIpO1xuXG4gICAgICAgICAgICBwYXR0ZXJuSW5mby5uZWdQcmUgPSBuZWdhdGl2ZS5zdWJzdHIoMCwgcG9zKS5yZXBsYWNlKC8nL2csICcnKTtcbiAgICAgICAgICAgIHBhdHRlcm5JbmZvLm5lZ1N1ZiA9IG5lZ2F0aXZlLnN1YnN0cihwb3MgKyB0cnVua0xlbikucmVwbGFjZSgvJy9nLCAnJyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwYXR0ZXJuSW5mby5uZWdQcmUgPSBtaW51c1NpZ24gKyBwYXR0ZXJuS