@catull/igniteui-angular
Version:
Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps
481 lines • 66.5 kB
JavaScript
import { isIE } from '../core/utils';
/**
*@hidden
*/
export class DatePickerUtil {
/**
* This method generates date parts structure based on editor mask and locale.
* @param maskValue: string
* @param locale: string
* @returns array containing information about date parts - type, position, format
*/
static parseDateFormat(maskValue, locale = DatePickerUtil.DEFAULT_LOCALE) {
let dateStruct = [];
if (maskValue === undefined && !isIE()) {
dateStruct = DatePickerUtil.getDefaultLocaleMask(locale);
}
else {
const mask = (maskValue) ? maskValue : DatePickerUtil.SHORT_DATE_MASK;
const maskArray = Array.from(mask);
const monthInitPosition = mask.indexOf("M" /* MonthChar */);
const dayInitPosition = mask.indexOf("d" /* DayChar */);
const yearInitPosition = mask.indexOf("y" /* YearChar */);
if (yearInitPosition !== -1) {
dateStruct.push({
type: "year" /* Year */,
initialPosition: yearInitPosition,
formatType: DatePickerUtil.getYearFormatType(mask)
});
}
if (monthInitPosition !== -1) {
dateStruct.push({
type: "month" /* Month */,
initialPosition: monthInitPosition,
formatType: DatePickerUtil.getMonthFormatType(mask)
});
}
if (dayInitPosition !== -1) {
dateStruct.push({
type: "day" /* Day */,
initialPosition: dayInitPosition,
formatType: DatePickerUtil.getDayFormatType(mask)
});
}
for (let i = 0; i < maskArray.length; i++) {
if (!DatePickerUtil.isDateChar(maskArray[i])) {
dateStruct.push({
type: DatePickerUtil.SEPARATOR,
initialPosition: i,
value: maskArray[i]
});
}
}
dateStruct.sort((a, b) => a.initialPosition - b.initialPosition);
DatePickerUtil.fillDatePartsPositions(dateStruct);
}
return dateStruct;
}
/**
* This method generates input mask based on date parts.
* @param dateStruct array
* @returns input mask
*/
static getInputMask(dateStruct) {
const inputMask = [];
for (let i = 0; i < dateStruct.length; i++) {
if (dateStruct[i].type === DatePickerUtil.SEPARATOR) {
inputMask.push(dateStruct[i].value);
}
else if (dateStruct[i].type === "day" /* Day */ || dateStruct[i].type === "month" /* Month */) {
inputMask.push('00');
}
else if (dateStruct[i].type === "year" /* Year */) {
switch (dateStruct[i].formatType) {
case "numeric" /* Numeric */: {
inputMask.push('0000');
break;
}
case "2-digit" /* TwoDigits */: {
inputMask.push('00');
break;
}
}
}
}
return inputMask.join('');
}
/**
* This method generates editor mask.
* @param dateStruct
* @returns editor mask
*/
static getMask(dateStruct) {
const mask = [];
for (let i = 0; i < dateStruct.length; i++) {
switch (dateStruct[i].formatType) {
case "numeric" /* Numeric */: {
if (dateStruct[i].type === "day" /* Day */) {
mask.push('d');
}
else if (dateStruct[i].type === "month" /* Month */) {
mask.push('M');
}
else {
mask.push('yyyy');
}
break;
}
case "2-digit" /* TwoDigits */: {
if (dateStruct[i].type === "day" /* Day */) {
mask.push('dd');
}
else if (dateStruct[i].type === "month" /* Month */) {
mask.push('MM');
}
else {
mask.push('yy');
}
}
}
if (dateStruct[i].type === DatePickerUtil.SEPARATOR) {
mask.push(dateStruct[i].value);
}
}
return mask.join('');
}
/**
* This method parses an input string base on date parts and returns a date and its validation state.
* @param dateFormatParts
* @param prevDateValue
* @param inputValue
* @returns object containing a date and its validation state
*/
static parseDateArray(dateFormatParts, prevDateValue, inputValue) {
const dayStr = DatePickerUtil.getDayValueFromInput(dateFormatParts, inputValue);
const monthStr = DatePickerUtil.getMonthValueFromInput(dateFormatParts, inputValue);
const yearStr = DatePickerUtil.getYearValueFromInput(dateFormatParts, inputValue);
const yearFormat = DatePickerUtil.getDateFormatPart(dateFormatParts, "year" /* Year */).formatType;
const day = (dayStr !== '') ? parseInt(dayStr, 10) : 1;
const month = (monthStr !== '') ? parseInt(monthStr, 10) - 1 : 0;
let year;
if (yearStr === '') {
year = (yearFormat === "2-digit" /* TwoDigits */) ? '00' : '2000';
}
else {
year = yearStr;
}
let yearPrefix;
if (prevDateValue) {
const originalYear = prevDateValue.getFullYear().toString();
if (originalYear.length === 4) {
yearPrefix = originalYear.substring(0, 2);
}
}
else {
yearPrefix = '20';
}
const fullYear = (yearFormat === "2-digit" /* TwoDigits */) ? yearPrefix.concat(year) : year;
if ((month < 0) || (month > 11) || (month === NaN)) {
return { state: "invalid" /* Invalid */, value: inputValue };
}
if ((day < 1) || (day > DatePickerUtil.daysInMonth(fullYear, month + 1)) || (day === NaN)) {
return { state: "invalid" /* Invalid */, value: inputValue };
}
return { state: "valid" /* Valid */, date: new Date(fullYear, month, day) };
}
static maskToPromptChars(mask) {
const result = mask.replace(/0|L/g, DatePickerUtil.PROMPT_CHAR);
return result;
}
/**
* This method replaces prompt chars with empty string.
* @param value
*/
static trimUnderlines(value) {
const result = value.replace(/_/g, '');
return result;
}
/**
* This method is used for spinning date parts.
* @param dateFormatParts
* @param inputValue
* @param position
* @param delta
* @param isSpinLoop
* @return modified text input
*/
static getModifiedDateInput(dateFormatParts, inputValue, position, delta, isSpinLoop) {
const datePart = DatePickerUtil.getDatePartOnPosition(dateFormatParts, position);
const datePartType = datePart.type;
const datePartFormatType = datePart.formatType;
let newValue;
const datePartValue = DatePickerUtil.getDateValueFromInput(dateFormatParts, datePartType, inputValue);
newValue = parseInt(datePartValue, 10);
let maxValue, minValue;
const minMax = DatePickerUtil.getMinMaxValue(dateFormatParts, datePart, inputValue);
minValue = minMax.min;
maxValue = minMax.max;
if (isNaN(newValue)) {
if (minValue === 'infinite') {
newValue = 2000;
}
else {
newValue = minValue;
}
}
let tempValue = newValue;
tempValue += delta;
// Infinite loop for full years
if (maxValue === 'infinite' && minValue === 'infinite') {
newValue = tempValue;
}
if (isSpinLoop) {
if (tempValue > maxValue) {
tempValue = minValue;
}
if (tempValue < minValue) {
tempValue = maxValue;
}
newValue = tempValue;
}
else {
if (tempValue <= maxValue && tempValue >= minValue) {
newValue = tempValue;
}
}
const startIdx = datePart.position[0];
const endIdx = datePart.position[1];
const start = inputValue.slice(0, startIdx);
const end = inputValue.slice(endIdx, inputValue.length);
let changedPart;
const prefix = DatePickerUtil.getNumericFormatPrefix(datePartFormatType);
changedPart = (newValue < 10) ? `${prefix}${newValue}` : `${newValue}`;
return `${start}${changedPart}${end}`;
}
/**
* This method returns date input with prompt chars.
* @param dateFormatParts
* @param date
* @param inputValue
* @returns date input including prompt chars
*/
static addPromptCharsEditMode(dateFormatParts, date, inputValue) {
const dateArray = Array.from(inputValue);
for (let i = 0; i < dateFormatParts.length; i++) {
if (dateFormatParts[i].formatType === "numeric" /* Numeric */) {
if ((dateFormatParts[i].type === "day" /* Day */ && date.getDate() < 10)
|| (dateFormatParts[i].type === "month" /* Month */ && date.getMonth() + 1 < 10)) {
dateArray.splice(dateFormatParts[i].position[0], 0, DatePickerUtil.PROMPT_CHAR);
dateArray.join('');
}
}
}
return dateArray.join('');
}
/**
* This method checks if date input is done.
* @param dateFormatParts
* @param input
* @returns input completeness
*/
static checkForCompleteDateInput(dateFormatParts, input) {
const dayValue = DatePickerUtil.getDayValueFromInput(dateFormatParts, input);
const monthValue = DatePickerUtil.getMonthValueFromInput(dateFormatParts, input);
const yearValue = DatePickerUtil.getYearValueFromInput(dateFormatParts, input);
const dayStr = DatePickerUtil.getDayValueFromInput(dateFormatParts, input, false);
const monthStr = DatePickerUtil.getMonthValueFromInput(dateFormatParts, input, false);
if (DatePickerUtil.isFullInput(dayValue, dayStr)
&& DatePickerUtil.isFullInput(monthValue, monthStr)
&& DatePickerUtil.isFullYearInput(dateFormatParts, yearValue)) {
return 'complete';
}
else if (dayValue === '' && monthValue === '' && yearValue === '') {
return 'empty';
}
else if (dayValue === '' || monthValue === '' || yearValue === '') {
return 'partial';
}
return '';
}
static getYearFormatType(format) {
switch (format.match(new RegExp("y" /* YearChar */, 'g')).length) {
case 1: {
// y (2020)
return "numeric" /* Numeric */;
}
case 4: {
// yyyy (2020)
return "numeric" /* Numeric */;
}
case 2: {
// yy (20)
return "2-digit" /* TwoDigits */;
}
}
}
static getMonthFormatType(format) {
switch (format.match(new RegExp("M" /* MonthChar */, 'g')).length) {
case 1: {
// M (8)
return "numeric" /* Numeric */;
}
case 2: {
// MM (08)
return "2-digit" /* TwoDigits */;
}
}
}
static getDayFormatType(format) {
switch (format.match(new RegExp("d" /* DayChar */, 'g')).length) {
case 1: {
// d (6)
return "numeric" /* Numeric */;
}
case 2: {
// dd (06)
return "2-digit" /* TwoDigits */;
}
}
}
static getDefaultLocaleMask(locale) {
const dateStruct = [];
const formatter = new Intl.DateTimeFormat(locale);
const formatToParts = formatter.formatToParts(new Date());
for (let i = 0; i < formatToParts.length; i++) {
if (formatToParts[i].type === DatePickerUtil.SEPARATOR) {
dateStruct.push({
type: DatePickerUtil.SEPARATOR,
value: formatToParts[i].value
});
}
else {
dateStruct.push({
type: formatToParts[i].type,
});
}
}
const formatterOptions = formatter.resolvedOptions();
for (let i = 0; i < dateStruct.length; i++) {
switch (dateStruct[i].type) {
case "day" /* Day */: {
dateStruct[i].formatType = formatterOptions.day;
break;
}
case "month" /* Month */: {
dateStruct[i].formatType = formatterOptions.month;
break;
}
case "year" /* Year */: {
dateStruct[i].formatType = formatterOptions.month;
break;
}
}
}
DatePickerUtil.fillDatePartsPositions(dateStruct);
return dateStruct;
}
static isDateChar(char) {
return (char === "y" /* YearChar */ || char === "M" /* MonthChar */ || char === "d" /* DayChar */);
}
static getNumericFormatPrefix(formatType) {
switch (formatType) {
case "2-digit" /* TwoDigits */: {
return '0';
}
case "numeric" /* Numeric */: {
return DatePickerUtil.PROMPT_CHAR;
}
}
}
static getMinMaxValue(dateFormatParts, datePart, inputValue) {
let maxValue, minValue;
switch (datePart.type) {
case "month" /* Month */: {
minValue = 1;
maxValue = DatePickerUtil.NUMBER_OF_MONTHS;
break;
}
case "day" /* Day */: {
minValue = 1;
maxValue = DatePickerUtil.daysInMonth(DatePickerUtil.getFullYearFromString(DatePickerUtil.getDateFormatPart(dateFormatParts, "year" /* Year */), inputValue), parseInt(DatePickerUtil.getMonthValueFromInput(dateFormatParts, inputValue), 10));
break;
}
case "year" /* Year */: {
if (datePart.formatType === "2-digit" /* TwoDigits */) {
minValue = 0;
maxValue = 99;
}
else {
// Infinite loop
minValue = 'infinite';
maxValue = 'infinite';
}
break;
}
}
return { min: minValue, max: maxValue };
}
static daysInMonth(fullYear, month) {
return new Date(fullYear, month, 0).getDate();
}
static getDateValueFromInput(dateFormatParts, type, inputValue, trim = true) {
const partPosition = DatePickerUtil.getDateFormatPart(dateFormatParts, type).position;
const result = inputValue.substring(partPosition[0], partPosition[1]);
return (trim) ? DatePickerUtil.trimUnderlines(result) : result;
}
static getDayValueFromInput(dateFormatParts, inputValue, trim = true) {
return DatePickerUtil.getDateValueFromInput(dateFormatParts, "day" /* Day */, inputValue, trim);
}
static getMonthValueFromInput(dateFormatParts, inputValue, trim = true) {
return DatePickerUtil.getDateValueFromInput(dateFormatParts, "month" /* Month */, inputValue, trim);
}
static getYearValueFromInput(dateFormatParts, inputValue, trim = true) {
return DatePickerUtil.getDateValueFromInput(dateFormatParts, "year" /* Year */, inputValue, trim);
}
static getDateFormatPart(dateFormatParts, type) {
const result = dateFormatParts.filter((datePart) => (datePart.type === type))[0];
return result;
}
static isFullInput(value, input) {
return (value !== '' && input.length === 2 && input.charAt(1) !== DatePickerUtil.PROMPT_CHAR);
}
static isFullYearInput(dateFormatParts, value) {
switch (DatePickerUtil.getDateFormatPart(dateFormatParts, "year" /* Year */).formatType) {
case "numeric" /* Numeric */: {
return (value !== '' && value.length === 4);
}
case "2-digit" /* TwoDigits */: {
return (value !== '' && value.length === 2);
}
default: {
return false;
}
}
}
static getDatePartOnPosition(dateFormatParts, position) {
const result = dateFormatParts.filter((element) => element.position[0] <= position && position <= element.position[1] && element.type !== DatePickerUtil.SEPARATOR)[0];
return result;
}
static getFullYearFromString(yearPart, inputValue) {
return parseInt(inputValue.substring(yearPart.position[0], yearPart.position[1]), 10);
}
static fillDatePartsPositions(dateArray) {
let currentPos = 0;
for (let i = 0; i < dateArray.length; i++) {
// Day|Month part positions
if (dateArray[i].type === "day" /* Day */ || dateArray[i].type === "month" /* Month */) {
// Offset 2 positions for number
dateArray[i].position = [currentPos, currentPos + 2];
currentPos += 2;
}
else if (dateArray[i].type === "year" /* Year */) {
// Year part positions
switch (dateArray[i].formatType) {
case "numeric" /* Numeric */: {
// Offset 4 positions for full year
dateArray[i].position = [currentPos, currentPos + 4];
currentPos += 4;
break;
}
case "2-digit" /* TwoDigits */: {
// Offset 2 positions for short year
dateArray[i].position = [currentPos, currentPos + 2];
currentPos += 2;
break;
}
}
}
else if (dateArray[i].type === DatePickerUtil.SEPARATOR) {
// Separator positions
dateArray[i].position = [currentPos, currentPos + 1];
currentPos++;
}
}
}
}
DatePickerUtil.SHORT_DATE_MASK = 'MM/dd/yy';
DatePickerUtil.SEPARATOR = 'literal';
DatePickerUtil.NUMBER_OF_MONTHS = 12;
DatePickerUtil.PROMPT_CHAR = '_';
DatePickerUtil.DEFAULT_LOCALE = 'en';
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZS1waWNrZXIudXRpbHMuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9pZ25pdGV1aS1hbmd1bGFyLyIsInNvdXJjZXMiOlsibGliL2RhdGUtcGlja2VyL2RhdGUtcGlja2VyLnV0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFzQ3JDOztHQUVHO0FBQ0gsTUFBTSxPQUFnQixjQUFjO0lBT2hDOzs7OztPQUtHO0lBQ0ksTUFBTSxDQUFDLGVBQWUsQ0FBQyxTQUFpQixFQUFFLFNBQWlCLGNBQWMsQ0FBQyxjQUFjO1FBQzNGLElBQUksVUFBVSxHQUFHLEVBQUUsQ0FBQztRQUNwQixJQUFJLFNBQVMsS0FBSyxTQUFTLElBQUksQ0FBQyxJQUFJLEVBQUUsRUFBRTtZQUNwQyxVQUFVLEdBQUcsY0FBYyxDQUFDLG9CQUFvQixDQUFDLE1BQU0sQ0FBQyxDQUFDO1NBQzVEO2FBQU07WUFDSCxNQUFNLElBQUksR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxlQUFlLENBQUM7WUFDdEUsTUFBTSxTQUFTLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUNuQyxNQUFNLGlCQUFpQixHQUFHLElBQUksQ0FBQyxPQUFPLHFCQUFxQixDQUFDO1lBQzVELE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQyxPQUFPLG1CQUFtQixDQUFDO1lBQ3hELE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLE9BQU8sb0JBQW9CLENBQUM7WUFFMUQsSUFBSSxnQkFBZ0IsS0FBSyxDQUFDLENBQUMsRUFBRTtnQkFDekIsVUFBVSxDQUFDLElBQUksQ0FBQztvQkFDWixJQUFJLG1CQUFnQjtvQkFDcEIsZUFBZSxFQUFFLGdCQUFnQjtvQkFDakMsVUFBVSxFQUFFLGNBQWMsQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUM7aUJB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VSxHQUFHLENBQUMsQ0FBQyxDQUFDO3dCQUNyRCxVQUFVLElBQUksQ0FBQyxDQUFDO3dCQUNoQixNQUFNO3FCQUNUO2lCQUNKO2FBQ0o7aUJBQU0sSUFBSSxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLGNBQWMsQ0FBQyxTQUFTLEVBQUU7Z0JBQ3ZELHNCQUFzQjtnQkFDdEIsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsR0FBRyxDQUFDLFVBQVUsRUFBRSxVQUFVLEdBQUcsQ0FBQyxDQUFDLENBQUM7Z0JBQ3JELFVBQVUsRUFBRSxDQUFDO2FBQ2hCO1NBQ0o7SUFDTCxDQUFDOztBQTlmdUIsOEJBQWUsR0FBRyxVQUFVLENBQUM7QUFDN0Isd0JBQVMsR0FBRyxTQUFTLENBQUM7QUFDdEIsK0JBQWdCLEdBQUcsRUFBRSxDQUFDO0FBQ3RCLDBCQUFXLEdBQUcsR0FBRyxDQUFDO0FBQ2xCLDZCQUFjLEdBQUcsSUFBSSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgaXNJRSB9IGZyb20gJy4uL2NvcmUvdXRpbHMnO1xuXG4vKipcbiAqIFRoaXMgZW51bSBpcyB1c2VkIHRvIGtlZXAgdGhlIGRhdGUgdmFsaWRhdGlvbiByZXN1bHQuXG4gKlxuICpAaGlkZGVuXG4gKi9cbmV4cG9ydCBjb25zdCBlbnVtIERhdGVTdGF0ZSB7XG4gICAgVmFsaWQgPSAndmFsaWQnLFxuICAgIEludmFsaWQgPSAnaW52YWxpZCcsXG59XG5cbi8qKlxuICpAaGlkZGVuXG4gKi9cbmNvbnN0IGVudW0gRm9ybWF0RGVzYyB7XG4gICAgTnVtZXJpYyA9ICdudW1lcmljJyxcbiAgICBUd29EaWdpdHMgPSAnMi1kaWdpdCdcbn1cblxuLyoqXG4gKkBoaWRkZW5cbiAqL1xuY29uc3QgZW51bSBEYXRlQ2hhcnMge1xuICAgIFllYXJDaGFyID0gJ3knLFxuICAgIE1vbnRoQ2hhciA9ICdNJyxcbiAgICBEYXlDaGFyID0gJ2QnXG59XG5cbi8qKlxuICpAaGlkZGVuXG4gKi9cbmNvbnN0IGVudW0gRGF0ZVBhcnRzIHtcbiAgICBEYXkgPSAnZGF5JyxcbiAgICBNb250aCA9ICdtb250aCcsXG4gICAgWWVhciA9ICd5ZWFyJ1xufVxuXG4vKipcbiAqQGhpZGRlblxuICovXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgRGF0ZVBpY2tlclV0aWwge1xuICAgIHByaXZhdGUgc3RhdGljIHJlYWRvbmx5IFNIT1JUX0RBVEVfTUFTSyA9ICdNTS9kZC95eSc7XG4gICAgcHJpdmF0ZSBzdGF0aWMgcmVhZG9ubHkgU0VQQVJBVE9SID0gJ2xpdGVyYWwnO1xuICAgIHByaXZhdGUgc3RhdGljIHJlYWRvbmx5IE5VTUJFUl9PRl9NT05USFMgPSAxMjtcbiAgICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBQUk9NUFRfQ0hBUiA9ICdfJztcbiAgICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBERUZBVUxUX0xPQ0FMRSA9ICdlbic7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBnZW5lcmF0ZXMgZGF0ZSBwYXJ0cyBzdHJ1Y3R1cmUgYmFzZWQgb24gZWRpdG9yIG1hc2sgYW5kIGxvY2FsZS5cbiAgICAgKiBAcGFyYW0gbWFza1ZhbHVlOiBzdHJpbmdcbiAgICAgKiBAcGFyYW0gbG9jYWxlOiBzdHJpbmdcbiAgICAgKiBAcmV0dXJucyBhcnJheSBjb250YWluaW5nIGluZm9ybWF0aW9uIGFib3V0IGRhdGUgcGFydHMgLSB0eXBlLCBwb3NpdGlvbiwgZm9ybWF0XG4gICAgICovXG4gICAgcHVibGljIHN0YXRpYyBwYXJzZURhdGVGb3JtYXQobWFza1ZhbHVlOiBzdHJpbmcsIGxvY2FsZTogc3RyaW5nID0gRGF0ZVBpY2tlclV0aWwuREVGQVVMVF9MT0NBTEUpOiBhbnlbXSB7XG4gICAgICAgIGxldCBkYXRlU3RydWN0ID0gW107XG4gICAgICAgIGlmIChtYXNrVmFsdWUgPT09IHVuZGVmaW5lZCAmJiAhaXNJRSgpKSB7XG4gICAgICAgICAgICBkYXRlU3RydWN0ID0gRGF0ZVBpY2tlclV0aWwuZ2V0RGVmYXVsdExvY2FsZU1hc2sobG9jYWxlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IG1hc2sgPSAobWFza1ZhbHVlKSA/IG1hc2tWYWx1ZSA6IERhdGVQaWNrZXJVdGlsLlNIT1JUX0RBVEVfTUFTSztcbiAgICAgICAgICAgIGNvbnN0IG1hc2tBcnJheSA9IEFycmF5LmZyb20obWFzayk7XG4gICAgICAgICAgICBjb25zdCBtb250aEluaXRQb3NpdGlvbiA9IG1hc2suaW5kZXhPZihEYXRlQ2hhcnMuTW9udGhDaGFyKTtcbiAgICAgICAgICAgIGNvbnN0IGRheUluaXRQb3NpdGlvbiA9IG1hc2suaW5kZXhPZihEYXRlQ2hhcnMuRGF5Q2hhcik7XG4gICAgICAgICAgICBjb25zdCB5ZWFySW5pdFBvc2l0aW9uID0gbWFzay5pbmRleE9mKERhdGVDaGFycy5ZZWFyQ2hhcik7XG5cbiAgICAgICAgICAgIGlmICh5ZWFySW5pdFBvc2l0aW9uICE9PSAtMSkge1xuICAgICAgICAgICAgICAgIGRhdGVTdHJ1Y3QucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6IERhdGVQYXJ0cy5ZZWFyLFxuICAgICAgICAgICAgICAgICAgICBpbml0aWFsUG9zaXRpb246IHllYXJJbml0UG9zaXRpb24sXG4gICAgICAgICAgICAgICAgICAgIGZvcm1hdFR5cGU6IERhdGVQaWNrZXJVdGlsLmdldFllYXJGb3JtYXRUeXBlKG1hc2spXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChtb250aEluaXRQb3NpdGlvbiAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICBkYXRlU3RydWN0LnB1c2goe1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiBEYXRlUGFydHMuTW9udGgsXG4gICAgICAgICAgICAgICAgICAgIGluaXRpYWxQb3NpdGlvbjogbW9udGhJbml0UG9zaXRpb24sXG4gICAgICAgICAgICAgICAgICAgIGZvcm1hdFR5cGU6IERhdGVQaWNrZXJVdGlsLmdldE1vbnRoRm9ybWF0VHlwZShtYXNrKVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoZGF5SW5pdFBvc2l0aW9uICE9PSAtMSkge1xuICAgICAgICAgICAgICAgIGRhdGVTdHJ1Y3QucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgIHR5cGU6IERhdGVQYXJ0cy5EYXksXG4gICAgICAgICAgICAgICAgICAgIGluaXRpYWxQb3NpdGlvbjogZGF5SW5pdFBvc2l0aW9uLFxuICAgICAgICAgICAgICAgICAgICBmb3JtYXRUeXBlOiBEYXRlUGlja2VyVXRpbC5nZXREYXlGb3JtYXRUeXBlKG1hc2spXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbWFza0FycmF5Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFEYXRlUGlja2VyVXRpbC5pc0RhdGVDaGFyKG1hc2tBcnJheVtpXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgZGF0ZVN0cnVjdC5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IERhdGVQaWNrZXJVdGlsLlNFUEFSQVRPUixcbiAgICAgICAgICAgICAgICAgICAgICAgIGluaXRpYWxQb3NpdGlvbjogaSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiBtYXNrQXJyYXlbaV1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBkYXRlU3RydWN0LnNvcnQoKGEsIGIpID0+IGEuaW5pdGlhbFBvc2l0aW9uIC0gYi5pbml0aWFsUG9zaXRpb24pO1xuICAgICAgICAgICAgRGF0ZVBpY2tlclV0aWwuZmlsbERhdGVQYXJ0c1Bvc2l0aW9ucyhkYXRlU3RydWN0KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZGF0ZVN0cnVjdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBnZW5lcmF0ZXMgaW5wdXQgbWFzayBiYXNlZCBvbiBkYXRlIHBhcnRzLlxuICAgICAqIEBwYXJhbSBkYXRlU3RydWN0IGFycmF5XG4gICAgICogQHJldHVybnMgaW5wdXQgbWFza1xuICAgICAqL1xuICAgIHB1YmxpYyBzdGF0aWMgZ2V0SW5wdXRNYXNrKGRhdGVTdHJ1Y3Q6IGFueVtdKTogc3RyaW5nIHtcbiAgICAgICAgY29uc3QgaW5wdXRNYXNrID0gW107XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZGF0ZVN0cnVjdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKGRhdGVTdHJ1Y3RbaV0udHlwZSA9PT0gRGF0ZVBpY2tlclV0aWwuU0VQQVJBVE9SKSB7XG4gICAgICAgICAgICAgICAgaW5wdXRNYXNrLnB1c2goZGF0ZVN0cnVjdFtpXS52YWx1ZSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGRhdGVTdHJ1Y3RbaV0udHlwZSA9PT0gRGF0ZVBhcnRzLkRheSB8fCBkYXRlU3RydWN0W2ldLnR5cGUgPT09IERhdGVQYXJ0cy5Nb250aCkge1xuICAgICAgICAgICAgICAgIGlucHV0TWFzay5wdXNoKCcwMCcpO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChkYXRlU3RydWN0W2ldLnR5cGUgPT09IERhdGVQYXJ0cy5ZZWFyKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChkYXRlU3RydWN0W2ldLmZvcm1hdFR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBGb3JtYXREZXNjLk51bWVyaWM6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0TWFzay5wdXNoKCcwMDAwJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjYXNlIEZvcm1hdERlc2MuVHdvRGlnaXRzOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbnB1dE1hc2sucHVzaCgnMDAnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBpbnB1dE1hc2suam9pbignJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgZ2VuZXJhdGVzIGVkaXRvciBtYXNrLlxuICAgICAqIEBwYXJhbSBkYXRlU3RydWN0XG4gICAgICogQHJldHVybnMgZWRpdG9yIG1hc2tcbiAgICAgKi9cbiAgICBwdWJsaWMgc3RhdGljIGdldE1hc2soZGF0ZVN0cnVjdDogYW55W10pOiBzdHJpbmcge1xuICAgICAgICBjb25zdCBtYXNrID0gW107XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZGF0ZVN0cnVjdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgc3dpdGNoIChkYXRlU3RydWN0W2ldLmZvcm1hdFR5cGUpIHtcbiAgICAgICAgICAgICAgICBjYXNlIEZvcm1hdERlc2MuTnVtZXJpYzoge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZGF0ZVN0cnVjdFtpXS50eXBlID09PSBEYXRlUGFydHMuRGF5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXNrLnB1c2goJ2QnKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChkYXRlU3RydWN0W2ldLnR5cGUgPT09IERhdGVQYXJ0cy5Nb250aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWFzay5wdXNoKCdNJyk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXNrLnB1c2goJ3l5eXknKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2FzZSBGb3JtYXREZXNjLlR3b0RpZ2l0czoge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZGF0ZVN0cnVjdFtpXS50eXBlID09PSBEYXRlUGFydHMuRGF5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXNrLnB1c2goJ2RkJyk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZGF0ZVN0cnVjdFtpXS50eXBlID09PSBEYXRlUGFydHMuTW9udGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hc2sucHVzaCgnTU0nKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hc2sucHVzaCgneXknKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGRhdGVTdHJ1Y3RbaV0udHlwZSA9PT0gRGF0ZVBpY2tlclV0aWwuU0VQQVJBVE9SKSB7XG4gICAgICAgICAgICAgICAgbWFzay5wdXNoKGRhdGVTdHJ1Y3RbaV0udmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG1hc2suam9pbignJyk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIHBhcnNlcyBhbiBpbnB1dCBzdHJpbmcgYmFzZSBvbiBkYXRlIHBhcnRzIGFuZCByZXR1cm5zIGEgZGF0ZSBhbmQgaXRzIHZhbGlkYXRpb24gc3RhdGUuXG4gICAgICogQHBhcmFtIGRhdGVGb3JtYXRQYXJ0c1xuICAgICAqIEBwYXJhbSBwcmV2RGF0ZVZhbHVlXG4gICAgICogQHBhcmFtIGlucHV0VmFsdWVcbiAgICAgKiBAcmV0dXJucyBvYmplY3QgY29udGFpbmluZyBhIGRhdGUgYW5kIGl0cyB2YWxpZGF0aW9uIHN0YXRlXG4gICAgICovXG4gICAgcHVibGljIHN0YXRpYyBwYXJzZURhdGVBcnJheShkYXRlRm9ybWF0UGFydHM6IGFueVtdLCBwcmV2RGF0ZVZhbHVlOiBEYXRlLCBpbnB1dFZhbHVlOiBzdHJpbmcpOiBhbnkge1xuICAgICAgICBjb25zdCBkYXlTdHIgPSBEYXRlUGlja2VyVXRpbC5nZXREYXlWYWx1ZUZyb21JbnB1dChkYXRlRm9ybWF0UGFydHMsIGlucHV0VmFsdWUpO1xuICAgICAgICBjb25zdCBtb250aFN0ciA9IERhdGVQaWNrZXJVdGlsLmdldE1vbnRoVmFsdWVGcm9tSW5wdXQoZGF0ZUZvcm1hdFBhcnRzLCBpbnB1dFZhbHVlKTtcbiAgICAgICAgY29uc3QgeWVhclN0ciA9IERhdGVQaWNrZXJVdGlsLmdldFllYXJWYWx1ZUZyb21JbnB1dChkYXRlRm9ybWF0UGFydHMsIGlucHV0VmFsdWUpO1xuICAgICAgICBjb25zdCB5ZWFyRm9ybWF0ID0gRGF0ZVBpY2tlclV0aWwuZ2V0RGF0ZUZvcm1hdFBhcnQoZGF0ZUZvcm1hdFBhcnRzLCBEYXRlUGFydHMuWWVhcikuZm9ybWF0VHlwZTtcbiAgICAgICAgY29uc3QgZGF5ID0gKGRheVN0ciAhPT0gJycpID8gcGFyc2VJbnQoZGF5U3RyLCAxMCkgOiAxO1xuICAgICAgICBjb25zdCBtb250aCA9IChtb250aFN0ciAhPT0gJycpID8gcGFyc2VJbnQobW9udGhTdHIsIDEwKSAtIDEgOiAwO1xuXG4gICAgICAgIGxldCB5ZWFyO1xuICAgICAgICBpZiAoeWVhclN0ciA9PT0gJycpIHtcbiAgICAgICAgICAgIHllYXIgPSAoeWVhckZvcm1hdCA9PT0gRm9ybWF0RGVzYy5Ud29EaWdpdHMpID8gJzAwJyA6ICcyMDAwJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHllYXIgPSB5ZWFyU3RyO1xuICAgICAgICB9XG4gICAgICAgIGxldCB5ZWFyUHJlZml4O1xuICAgICAgICBpZiAocHJldkRhdGVWYWx1ZSkge1xuICAgICAgICAgICAgY29uc3Qgb3JpZ2luYWxZZWFyID0gcHJldkRhdGVWYWx1ZS5nZXRGdWxsWWVhcigpLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICBpZiAob3JpZ2luYWxZZWFyLmxlbmd0aCA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHllYXJQcmVmaXggPSBvcmlnaW5hbFllYXIuc3Vic3RyaW5nKDAsIDIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgeWVhclByZWZpeCA9ICcyMCc7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZnVsbFllYXIgPSAoeWVhckZvcm1hdCA9PT0gRm9ybWF0RGVzYy5Ud29EaWdpdHMpID8geWVhclByZWZpeC5jb25jYXQoeWVhcikgOiB5ZWFyO1xuXG4gICAgICAgIGlmICgobW9udGggPCAwKSB8fCAobW9udGggPiAxMSkgfHwgKG1vbnRoID09PSBOYU4pKSB7XG4gICAgICAgICAgICByZXR1cm4geyBzdGF0ZTogRGF0ZVN0YXRlLkludmFsaWQsIHZhbHVlOiBpbnB1dFZhbHVlIH07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoKGRheSA8IDEpIHx8IChkYXkgPiBEYXRlUGlja2VyVXRpbC5kYXlzSW5Nb250aChmdWxsWWVhciwgbW9udGggKyAxKSkgfHwgKGRheSA9PT0gTmFOKSkge1xuICAgICAgICAgICAgcmV0dXJuIHsgc3RhdGU6IERhdGVTdGF0ZS5JbnZhbGlkLCB2YWx1ZTogaW5wdXRWYWx1ZSB9O1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHsgc3RhdGU6IERhdGVTdGF0ZS5WYWxpZCwgZGF0ZTogbmV3IERhdGUoZnVsbFllYXIsIG1vbnRoLCBkYXkpIH07XG4gICAgfVxuXG4gICAgcHVibGljIHN0YXRpYyBtYXNrVG9Qcm9tcHRDaGFycyhtYXNrOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBtYXNrLnJlcGxhY2UoLzB8TC9nLCBEYXRlUGlja2VyVXRpbC5QUk9NUFRfQ0hBUik7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgcmVwbGFjZXMgcHJvbXB0IGNoYXJzIHdpdGggZW1wdHkgc3RyaW5nLlxuICAgICAqIEBwYXJhbSB2YWx1ZVxuICAgICAqL1xuICAgIHB1YmxpYyBzdGF0aWMgdHJpbVVuZGVybGluZXModmFsdWU6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IHZhbHVlLnJlcGxhY2UoL18vZywgJycpO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIHVzZWQgZm9yIHNwaW5uaW5nIGRhdGUgcGFydHMuXG4gICAgICogQHBhcmFtIGRhdGVGb3JtYXRQYXJ0c1xuICAgICAqIEBwYXJhbSBpbnB1dFZhbHVlXG4gICAgICogQHBhcmFtIHBvc2l0aW9uXG4gICAgICogQHBhcmFtIGRlbHRhXG4gICAgICogQHBhcmFtIGlzU3Bpbkxvb3BcbiAgICAgKiBAcmV0dXJuIG1vZGlmaWVkIHRleHQgaW5wdXRcbiAgICAgKi9cbiAgICBwdWJsaWMgc3RhdGljIGdldE1vZGlmaWVkRGF0ZUlucHV0KGRhdGVGb3JtYXRQYXJ0czogYW55W10sXG4gICAgICAgIGlucHV0VmFsdWU6IHN0cmluZyxcbiAgICAgICAgcG9zaXRpb246IG51bWJlcixcbiAgICAgICAgZGVsdGE6IG51bWJlcixcbiAgICAgICAgaXNTcGluTG9vcDogYm9vbGVhbik6IHN0cmluZyB7XG4gICAgICAgIGNvbnN0IGRhdGVQYXJ0ID