toolshed-8.x-1.x-dev/js/widgets/Accordion.js
js/widgets/Accordion.js
"use strict";
(({
theme,
t,
Toolshed: ts
}) => {
/**
* Function to create an HTMLElement to serve as the expand/collapse toggle
* for an AccordionItem.
*
* @return {HTMLElement}
* An HTMLElement to serve as the expand/collapse toggle for an
* AccordionItem.
*/
theme.accordionToggler = (expandText = 'Expand', collapseText = 'Collapse') => {
// Create top-level button element.
const btn = new ts.Element('button', {
class: 'toggler'
});
btn.innerHTML = `
<span class="toggler__collapse-text">${expandText}</span>
<span class="toggler__expand-text">${collapseText}</span>
`;
return btn;
};
let idCt = 1;
function uniqueId() {
// A unique ID for accordion items to use with "aria-controls" property.
return `ts-accordion-${idCt++}`;
}
/**
* Defines a collapsible accordion item.
*/
ts.AccordionItem = class AccordionItem extends ts.Element {
/**
* Class representing a single item of an Accordion which is expandable and
* collapsible. This item maintains its components and the state of the
* open and close states.
*
* @param {Element} el
* The whole accordion item.
* @param {Element} expander
* Element to use for toggling the body content.
* @param {Element} body
* The content area of the accordion item which is revealed or hidden
* when the accordion item is expanded or collapsed.
* @param {Accordion|AccordionItem} parent
* Parent accordion instance.
* @param {Object} settings
* Object of configurations to use to control the behavior of the
* accordion item.
*/
constructor(el, expander, body, parent = null, settings = {}) {
super(el, {
class: ['accordion-item', 'item--collapsible']
});
this.isExpanded = true;
this.parent = parent;
this.body = body;
this.expander = expander;
this.useAnimation = settings.animate || true;
this.animateTime = settings.animateTime || '0.3s';
this.children = [];
this.body.addClass('item__body');
this.expander.setAttrs({
'aria-expanded': this.isExpanded.toString(),
'aria-controls': body.id || (body.id = uniqueId())
});
this.onToggleExpand = AccordionItem[parent && settings.exclusive ? 'onClickExclusive' : 'onClickToggle'].bind(this);
expander.on('click', this.onToggleExpand);
}
/**
* Add a child accordion item.
*
* @param {AccordionItem} child
* Child accordion item to add.
*/
addChild(child) {
this.children.push(child);
}
/**
* Expand the accordion item's content display.
*
* @param {bool} allowAnimate
* Animate expand animations if an animation is configured.
*/
expand(allowAnimate = true) {
this.addClass('item--expanded');
this.removeClass('item--collapsed');
this.expander.setAttr('aria-expanded', 'true');
this.isExpanded = true;
this.expander.addClass('toggler--expanded');
this.expander.removeClass('toggler--collapsed');
if (allowAnimate && this.useAnimation) {
this.body.expand(this.animateTime);
} else {
this.body.style.display = '';
this.body.style.height = '';
}
}
/**
* Collapse the accordion item's content display.
*
* @param {bool} allowAnimate
* Should the collapse functionality expect to animate the transitions
* if the accordion item is setup to do animations.
*/
collapse(allowAnimate = true) {
this.addClass('item--collapsed');
this.removeClass('item--expanded');
this.expander.ariaExpanded = 'false';
this.isExpanded = false;
this.expander.addClass('toggler--collapsed');
this.expander.removeClass('toggler--expanded');
if (allowAnimate && this.useAnimation) {
this.body.collapse(this.animateTime);
} else {
this.body.style.display = 'none';
}
// Recursively close all the open child accordions.
this.children.forEach(child => {
if (child.isExpanded) child.collapse(false);
});
}
/**
* Expand and collapse of accordion items, without concern to the state of
* other accordion items. Multiple items can be open at once.
*
* @param {ClickEvent} e
* DOM click event object, containing information about the item being
* being clicked with the collapse functionality.
*/
static onClickToggle(e) {
e.preventDefault();
if (this.isExpanded) {
this.collapse();
} else {
this.expand();
}
}
/**
* Expand and collapse of accordion items but ensure only one item is open
* at a time.
*
* @param {ClickEvent} e
* DOM click event object, containing information about the item being
* being clicked with the collapse functionality.
*/
static onClickExclusive(e) {
e.preventDefault();
if (this.isExpanded) {
this.collapse();
} else {
// Recursively close all the open child accordions.
this.parent.children.forEach(child => {
if (child !== this && child.isExpanded) child.collapse();
});
this.expand();
}
}
/**
* Teardown any events and alterations this accordion item made to the DOM.
*/
destroy() {
this.expander.removeAttrs(['aria-expanded', 'aria-controls']);
this.expander.removeClass(['toggler--expanded', 'toggler--collapsed']);
this.removeClass(['accordion-item', 'item--collapsed', 'item--expanded', 'item--collapsible']);
// Reset the accordion body display.
this.body.style.display = '';
this.body.style.height = '';
// Clear the expander events.
this.expander.destroy();
super.destroy();
}
};
/**
* Defines a non-collapsible accordion item.
*/
class NonAccordionItem extends ts.Element {
/**
* Class representing a single item of an Accordion which is not expandable
* or collapsible.
*
* @param {Element} el
* The whole accordion item.
* @param {Accordion|AccordionItem} parent
* Parent accordion instance.
*/
constructor(el, parent) {
super(el, {
class: 'accordion-item'
});
this.el = el;
this.parent = parent;
this.children = [];
this.isExpanded = false;
}
/**
* Add a child accordion item.
*
* @param {AccordionItem} child
* Child accordion item to add.
*/
addChild(child) {
this.isExpanded = true;
this.children.push(child);
}
/**
* This class implements an expand function in order to have the same
* interface as the AccordionItem class, but since this is a
* non-collapsible accordion item, it does nothing.
*/
expand() {} // eslint-disable-line class-methods-use-this
/**
* This class implements a collapse function in order to have the same
* interface as the AccordionItem class, but since this is a
* non-collapsible accordion item, it just collapses any children.
*/
collapse() {
// Recursively close all the open child accordions.
this.children.forEach(child => {
if (child.isExpanded) child.collapse(false);
});
}
}
/**
* Accordion object definition.
*/
ts.Accordion = class Accordion extends ts.Element {
/**
* Create an accordion of expandable and collapsible items.
*
* @param {Element} el
* DOM element to turn into an accordion.
* @param {Object} configs
* A configuration options which determine the options:
* {
* initOpen: {bool|selector} [true],
* // Should accordion panels start of initially open.
* exclusive: {bool} [true],
* // Accordion only has one item open at a time.
* animate: {bool} [true],
* // Should the accordions expand and collapse animate.
* transitionDuration: {string} ['0.3s']
* // How long the expand/collapse transitions should last. Should be
* // a duration that a CSS transition can accept (such as '300ms' or
* // '0.3s').
* toggler: {DOMString|function|object}
* // The selector to find the element to toggle the collapse and expand, OR
* // A callback function to create the toggler element, OR
* // An object with `create` and `attacher` functions to create and
* // place the toggler into the DOM.
* itemSel: {DOMString}
* // The selector to use when locating each of the accordion items.
* bodySel: {DOMString}
* // The selector to use to find the item body within the item context.
* }
*/
constructor(el, configs) {
super(el, {
class: 'accordion'
});
this.items = new Map();
this.children = [];
this.configs = {
exclusive: true,
initOpen: true,
animate: true,
animateTime: '0.3s',
...configs
};
const {
exclusive,
initOpen,
itemSel,
bodySel
} = this.configs;
let toggleOpt = this.configs.toggler || theme.accordionToggler;
// If the expand option is just a selector, then the element is expected
// to already be in the document (otherwise not findable).
if (ts.isString(toggleOpt)) {
this.getToggler = item => new ts.Element(item.querySelector(toggleOpt) || 'button');
} else {
if (typeof toggleOpt === 'function') toggleOpt = {
create: toggleOpt
};
if (!toggleOpt.attach) {
toggleOpt.attach = (toggler, item) => item.insertBefore(toggler.el, item.querySelector(bodySel));
}
this.getToggler = item => {
let toggler = toggleOpt.create(item);
// If not already in the DOM, use the attach callback to insert it.
if (toggler && !toggler.parentNode) {
toggleOpt.attach(toggler, item);
}
return toggler;
};
}
// Build the accordion items allowing for a nested tree structure.
this.find(itemSel).forEach(el => this.buildTreeItem(el));
if (!initOpen || exclusive) {
this.children.forEach((child, i) => {
if (!initOpen || i !== 0) child.collapse(false);
});
}
}
/**
* Add a child accordion item.
*
* @param {AccordionItem} child
* Child accordion item to add.
*/
addChild(child) {
this.children.push(child);
}
/**
* Find the parent accordion item for this element.
*
* @param {DOMElement} el
* The element to search for the closest matching selector for.
* @param {string} selector
* Selector to use when identifying an accordion item.
*
* @return {Element|null}
* If an appropriate parent matching the item selector is found within
* the confines of the accordion element, it is returned. Otherwise,
* return the Element wrapping the accordion.
*/
findParent(el, selector) {
let cur = el;
do {
cur = cur.parentElement;
} while (cur && cur !== this.el && !cur.matches(selector));
return cur;
}
/**
* Recursively add accordion items to the tree structure.
*
* @param {DOMElement} el
* The HTMLElement tos transform into an accordion item.
*
* @return {AccordionItem|NonAccordionItem}
* An accordion item or a NonAccordionItem (item that doesn't collapse).
*/
buildTreeItem(el) {
let a = this.items.get(el);
// This element has already been built, don't need to rebuild subtree.
if (a) return a;
const {
itemSel,
bodySel
} = this.configs;
const parent = this.findParent(el, itemSel);
// Only create an accordion item if it has a parent item which exists
// within the Accordion scope.
if (!parent) throw new Error('Unable to find a parent buildTreeItem().');
const iParent = parent === this.el ? this : this.items.get(parent) || this.buildTreeItem(parent);
if (!iParent) throw new Error('No valid accordion parent available, or not a descendent of the accordion.');
// Only create a collapsible accordion item if it has a has a body to
// expand, and an expander (expand/collapse toggle). Otherwise create a
// non-collapsible accordion item.
let accord;
const body = el.querySelector(bodySel);
if (body) {
const expander = this.getToggler(el);
if (expander) {
// This accordion item should be made collapsible.
accord = new ts.AccordionItem(el, expander, new ts.Element(body), iParent, this.configs);
}
}
if (!accord) {
// This accordion item should be made non-collapsible.
accord = new NonAccordionItem(item, iParent);
}
// Add the accordion item to the accordion's 'items' list, and to its
// parent's list of children.
this.items.set(el, accord);
iParent.addChild(accord);
return accord;
}
/**
* Teardown any changes to the DOM as well as clearing AccordionItems.
*/
destroy() {
this.removeClass('accordion');
// Destroy all the accordion items.
this.items.forEach(item => item.destroy());
delete this.items;
delete this.children;
delete this.configs;
super.destroy();
}
};
})(Drupal);
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2lkZ2V0cy9BY2NvcmRpb24uanMiLCJuYW1lcyI6WyJ0aGVtZSIsInQiLCJUb29sc2hlZCIsInRzIiwiYWNjb3JkaW9uVG9nZ2xlciIsImV4cGFuZFRleHQiLCJjb2xsYXBzZVRleHQiLCJidG4iLCJFbGVtZW50IiwiY2xhc3MiLCJpbm5lckhUTUwiLCJpZEN0IiwidW5pcXVlSWQiLCJBY2NvcmRpb25JdGVtIiwiY29uc3RydWN0b3IiLCJlbCIsImV4cGFuZGVyIiwiYm9keSIsInBhcmVudCIsInNldHRpbmdzIiwiaXNFeHBhbmRlZCIsInVzZUFuaW1hdGlvbiIsImFuaW1hdGUiLCJhbmltYXRlVGltZSIsImNoaWxkcmVuIiwiYWRkQ2xhc3MiLCJzZXRBdHRycyIsInRvU3RyaW5nIiwiaWQiLCJvblRvZ2dsZUV4cGFuZCIsImV4Y2x1c2l2ZSIsImJpbmQiLCJvbiIsImFkZENoaWxkIiwiY2hpbGQiLCJwdXNoIiwiZXhwYW5kIiwiYWxsb3dBbmltYXRlIiwicmVtb3ZlQ2xhc3MiLCJzZXRBdHRyIiwic3R5bGUiLCJkaXNwbGF5IiwiaGVpZ2h0IiwiY29sbGFwc2UiLCJhcmlhRXhwYW5kZWQiLCJmb3JFYWNoIiwib25DbGlja1RvZ2dsZSIsImUiLCJwcmV2ZW50RGVmYXVsdCIsIm9uQ2xpY2tFeGNsdXNpdmUiLCJkZXN0cm95IiwicmVtb3ZlQXR0cnMiLCJOb25BY2NvcmRpb25JdGVtIiwiQWNjb3JkaW9uIiwiY29uZmlncyIsIml0ZW1zIiwiTWFwIiwiaW5pdE9wZW4iLCJpdGVtU2VsIiwiYm9keVNlbCIsInRvZ2dsZU9wdCIsInRvZ2dsZXIiLCJpc1N0cmluZyIsImdldFRvZ2dsZXIiLCJpdGVtIiwicXVlcnlTZWxlY3RvciIsImNyZWF0ZSIsImF0dGFjaCIsImluc2VydEJlZm9yZSIsInBhcmVudE5vZGUiLCJmaW5kIiwiYnVpbGRUcmVlSXRlbSIsImkiLCJmaW5kUGFyZW50Iiwic2VsZWN0b3IiLCJjdXIiLCJwYXJlbnRFbGVtZW50IiwibWF0Y2hlcyIsImEiLCJnZXQiLCJFcnJvciIsImlQYXJlbnQiLCJhY2NvcmQiLCJzZXQiLCJEcnVwYWwiXSwic291cmNlcyI6WyJ3aWRnZXRzL0FjY29yZGlvbi5lczYuanMiXSwic291cmNlc0NvbnRlbnQiOlsiKCh7IHRoZW1lLCB0LCBUb29sc2hlZDogdHMgfSkgPT4ge1xuICAvKipcbiAgICogRnVuY3Rpb24gdG8gY3JlYXRlIGFuIEhUTUxFbGVtZW50IHRvIHNlcnZlIGFzIHRoZSBleHBhbmQvY29sbGFwc2UgdG9nZ2xlXG4gICAqIGZvciBhbiBBY2NvcmRpb25JdGVtLlxuICAgKlxuICAgKiBAcmV0dXJuIHtIVE1MRWxlbWVudH1cbiAgICogICBBbiBIVE1MRWxlbWVudCB0byBzZXJ2ZSBhcyB0aGUgZXhwYW5kL2NvbGxhcHNlIHRvZ2dsZSBmb3IgYW5cbiAgICogICBBY2NvcmRpb25JdGVtLlxuICAgKi9cbiAgdGhlbWUuYWNjb3JkaW9uVG9nZ2xlciA9IChleHBhbmRUZXh0ID0gJ0V4cGFuZCcsIGNvbGxhcHNlVGV4dCA9ICdDb2xsYXBzZScpID0+IHtcbiAgICAvLyBDcmVhdGUgdG9wLWxldmVsIGJ1dHRvbiBlbGVtZW50LlxuICAgIGNvbnN0IGJ0biA9IG5ldyB0cy5FbGVtZW50KCdidXR0b24nLCB7IGNsYXNzOiAndG9nZ2xlcid9KTtcbiAgICBidG4uaW5uZXJIVE1MID0gYFxuICAgICAgPHNwYW4gY2xhc3M9XCJ0b2dnbGVyX19jb2xsYXBzZS10ZXh0XCI+JHtleHBhbmRUZXh0fTwvc3Bhbj5cbiAgICAgIDxzcGFuIGNsYXNzPVwidG9nZ2xlcl9fZXhwYW5kLXRleHRcIj4ke2NvbGxhcHNlVGV4dH08L3NwYW4+XG4gICAgYDtcblxuICAgIHJldHVybiBidG47XG4gIH07XG5cblxuICBsZXQgaWRDdCA9IDE7XG4gIGZ1bmN0aW9uIHVuaXF1ZUlkKCkge1xuICAgIC8vIEEgdW5pcXVlIElEIGZvciBhY2NvcmRpb24gaXRlbXMgdG8gdXNlIHdpdGggXCJhcmlhLWNvbnRyb2xzXCIgcHJvcGVydHkuXG4gICAgcmV0dXJuIGB0cy1hY2NvcmRpb24tJHtpZEN0Kyt9YDtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZWZpbmVzIGEgY29sbGFwc2libGUgYWNjb3JkaW9uIGl0ZW0uXG4gICAqL1xuICB0cy5BY2NvcmRpb25JdGVtID0gY2xhc3MgQWNjb3JkaW9uSXRlbSBleHRlbmRzIHRzLkVsZW1lbnQge1xuICAgIC8qKlxuICAgICAqIENsYXNzIHJlcHJlc2VudGluZyBhIHNpbmdsZSBpdGVtIG9mIGFuIEFjY29yZGlvbiB3aGljaCBpcyBleHBhbmRhYmxlIGFuZFxuICAgICAqIGNvbGxhcHNpYmxlLiBUaGlzIGl0ZW0gbWFpbnRhaW5zIGl0cyBjb21wb25lbnRzIGFuZCB0aGUgc3RhdGUgb2YgdGhlXG4gICAgICogb3BlbiBhbmQgY2xvc2Ugc3RhdGVzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtFbGVtZW50fSBlbFxuICAgICAqICAgVGhlIHdob2xlIGFjY29yZGlvbiBpdGVtLlxuICAgICAqIEBwYXJhbSB7RWxlbWVudH0gZXhwYW5kZXJcbiAgICAgKiAgIEVsZW1lbnQgdG8gdXNlIGZvciB0b2dnbGluZyB0aGUgYm9keSBjb250ZW50LlxuICAgICAqIEBwYXJhbSB7RWxlbWVudH0gYm9keVxuICAgICAqICAgVGhlIGNvbnRlbnQgYXJlYSBvZiB0aGUgYWNjb3JkaW9uIGl0ZW0gd2hpY2ggaXMgcmV2ZWFsZWQgb3IgaGlkZGVuXG4gICAgICogICB3aGVuIHRoZSBhY2NvcmRpb24gaXRlbSBpcyBleHBhbmRlZCBvciBjb2xsYXBzZWQuXG4gICAgICogQHBhcmFtIHtBY2NvcmRpb258QWNjb3JkaW9uSXRlbX0gcGFyZW50XG4gICAgICogICBQYXJlbnQgYWNjb3JkaW9uIGluc3RhbmNlLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzZXR0aW5nc1xuICAgICAqICAgT2JqZWN0IG9mIGNvbmZpZ3VyYXRpb25zIHRvIHVzZSB0byBjb250cm9sIHRoZSBiZWhhdmlvciBvZiB0aGVcbiAgICAgKiAgIGFjY29yZGlvbiBpdGVtLlxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGVsLCBleHBhbmRlciwgYm9keSwgcGFyZW50ID0gbnVsbCwgc2V0dGluZ3MgPSB7fSkge1xuICAgICAgc3VwZXIoZWwsIHtjbGFzczogWydhY2NvcmRpb24taXRlbScsICdpdGVtLS1jb2xsYXBzaWJsZSddfSk7XG5cbiAgICAgIHRoaXMuaXNFeHBhbmRlZCA9IHRydWU7XG4gICAgICB0aGlzLnBhcmVudCA9IHBhcmVudDtcbiAgICAgIHRoaXMuYm9keSA9IGJvZHk7XG4gICAgICB0aGlzLmV4cGFuZGVyID0gZXhwYW5kZXI7XG4gICAgICB0aGlzLnVzZUFuaW1hdGlvbiA9IHNldHRpbmdzLmFuaW1hdGUgfHwgdHJ1ZTtcbiAgICAgIHRoaXMuYW5pbWF0ZVRpbWUgPSBzZXR0aW5ncy5hbmltYXRlVGltZSB8fCAnMC4zcyc7XG4gICAgICB0aGlzLmNoaWxkcmVuID0gW107XG5cbiAgICAgIHRoaXMuYm9keS5hZGRDbGFzcygnaXRlbV9fYm9keScpO1xuICAgICAgdGhpcy5leHBhbmRlci5zZXRBdHRycyh7XG4gICAgICAgICdhcmlhLWV4cGFuZGVkJzogdGhpcy5pc0V4cGFuZGVkLnRvU3RyaW5nKCksXG4gICAgICAgICdhcmlhLWNvbnRyb2xzJzogYm9keS5pZCB8fCAoYm9keS5pZCA9IHVuaXF1ZUlkKCkpLFxuICAgICAgfSk7XG5cbiAgICAgIHRoaXMub25Ub2dnbGVFeHBhbmQgPSBBY2NvcmRpb25JdGVtW3BhcmVudCAmJiBzZXR0aW5ncy5leGNsdXNpdmUgPyAnb25DbGlja0V4Y2x1c2l2ZScgOiAnb25DbGlja1RvZ2dsZSddLmJpbmQodGhpcyk7XG4gICAgICBleHBhbmRlci5vbignY2xpY2snLCB0aGlzLm9uVG9nZ2xlRXhwYW5kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBZGQgYSBjaGlsZCBhY2NvcmRpb24gaXRlbS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7QWNjb3JkaW9uSXRlbX0gY2hpbGRcbiAgICAgKiAgIENoaWxkIGFjY29yZGlvbiBpdGVtIHRvIGFkZC5cbiAgICAgKi9cbiAgICBhZGRDaGlsZChjaGlsZCkge1xuICAgICAgdGhpcy5jaGlsZHJlbi5wdXNoKGNoaWxkKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFeHBhbmQgdGhlIGFjY29yZGlvbiBpdGVtJ3MgY29udGVudCBkaXNwbGF5LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtib29sfSBhbGxvd0FuaW1hdGVcbiAgICAgKiAgIEFuaW1hdGUgZXhwYW5kIGFuaW1hdGlvbnMgaWYgYW4gYW5pbWF0aW9uIGlzIGNvbmZpZ3VyZWQuXG4gICAgICovXG4gICAgZXhwYW5kKGFsbG93QW5pbWF0ZSA9IHRydWUpIHtcbiAgICAgIHRoaXMuYWRkQ2xhc3MoJ2l0ZW0tLWV4cGFuZGVkJyk7XG4gICAgICB0aGlzLnJlbW92ZUNsYXNzKCdpdGVtLS1jb2xsYXBzZWQnKTtcbiAgICAgIHRoaXMuZXhwYW5kZXIuc2V0QXR0cignYXJpYS1leHBhbmRlZCcsICd0cnVlJyk7XG4gICAgICB0aGlzLmlzRXhwYW5kZWQgPSB0cnVlO1xuICAgICAgdGhpcy5leHBhbmRlci5hZGRDbGFzcygndG9nZ2xlci0tZXhwYW5kZWQnKTtcbiAgICAgIHRoaXMuZXhwYW5kZXIucmVtb3ZlQ2xhc3MoJ3RvZ2dsZXItLWNvbGxhcHNlZCcpO1xuXG4gICAgICBpZiAoYWxsb3dBbmltYXRlICYmIHRoaXMudXNlQW5pbWF0aW9uKSB7XG4gICAgICAgIHRoaXMuYm9keS5leHBhbmQodGhpcy5hbmltYXRlVGltZSk7XG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgdGhpcy5ib2R5LnN0eWxlLmRpc3BsYXkgPSAnJztcbiAgICAgICAgdGhpcy5ib2R5LnN0eWxlLmhlaWdodCA9ICcnO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbGxhcHNlIHRoZSBhY2NvcmRpb24gaXRlbSdzIGNvbnRlbnQgZGlzcGxheS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7Ym9vbH0gYWxsb3dBbmltYXRlXG4gICAgICogICBTaG91bGQgdGhlIGNvbGxhcHNlIGZ1bmN0aW9uYWxpdHkgZXhwZWN0IHRvIGFuaW1hdGUgdGhlIHRyYW5zaXRpb25zXG4gICAgICogICBpZiB0aGUgYWNjb3JkaW9uIGl0ZW0gaXMgc2V0dXAgdG8gZG8gYW5pbWF0aW9ucy5cbiAgICAgKi9cbiAgICBjb2xsYXBzZShhbGxvd0FuaW1hdGUgPSB0cnVlKSB7XG4gICAgICB0aGlzLmFkZENsYXNzKCdpdGVtLS1jb2xsYXBzZWQnKTtcbiAgICAgIHRoaXMucmVtb3ZlQ2xhc3MoJ2l0ZW0tLWV4cGFuZGVkJyk7XG4gICAgICB0aGlzLmV4cGFuZGVyLmFyaWFFeHBhbmRlZCA9ICdmYWxzZSc7XG4gICAgICB0aGlzLmlzRXhwYW5kZWQgPSBmYWxzZTtcbiAgICAgIHRoaXMuZXhwYW5kZXIuYWRkQ2xhc3MoJ3RvZ2dsZXItLWNvbGxhcHNlZCcpO1xuICAgICAgdGhpcy5leHBhbmRlci5yZW1vdmVDbGFzcygndG9nZ2xlci0tZXhwYW5kZWQnKTtcblxuICAgICAgaWYgKGFsbG93QW5pbWF0ZSAmJiB0aGlzLnVzZUFuaW1hdGlvbikge1xuICAgICAgICB0aGlzLmJvZHkuY29sbGFwc2UodGhpcy5hbmltYXRlVGltZSk7XG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgdGhpcy5ib2R5LnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgICB9XG5cbiAgICAgIC8vIFJlY3Vyc2l2ZWx5IGNsb3NlIGFsbCB0aGUgb3BlbiBjaGlsZCBhY2NvcmRpb25zLlxuICAgICAgdGhpcy5jaGlsZHJlbi5mb3JFYWNoKChjaGlsZCkgPT4ge1xuICAgICAgICBpZiAoY2hpbGQuaXNFeHBhbmRlZCkgY2hpbGQuY29sbGFwc2UoZmFsc2UpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRXhwYW5kIGFuZCBjb2xsYXBzZSBvZiBhY2NvcmRpb24gaXRlbXMsIHdpdGhvdXQgY29uY2VybiB0byB0aGUgc3RhdGUgb2ZcbiAgICAgKiBvdGhlciBhY2NvcmRpb24gaXRlbXMuIE11bHRpcGxlIGl0ZW1zIGNhbiBiZSBvcGVuIGF0IG9uY2UuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0NsaWNrRXZlbnR9IGVcbiAgICAgKiAgIERPTSBjbGljayBldmVudCBvYmplY3QsIGNvbnRhaW5pbmcgaW5mb3JtYXRpb24gYWJvdXQgdGhlIGl0ZW0gYmVpbmdcbiAgICAgKiAgIGJlaW5nIGNsaWNrZWQgd2l0aCB0aGUgY29sbGFwc2UgZnVuY3Rpb25hbGl0eS5cbiAgICAgKi9cbiAgICBzdGF0aWMgb25DbGlja1RvZ2dsZShlKSB7XG4gICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgIGlmICh0aGlzLmlzRXhwYW5kZWQpIHtcbiAgICAgICAgdGhpcy5jb2xsYXBzZSgpO1xuICAgICAgfVxuICAgICAgZWxzZSB7XG4gICAgICAgIHRoaXMuZXhwYW5kKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRXhwYW5kIGFuZCBjb2xsYXBzZSBvZiBhY2NvcmRpb24gaXRlbXMgYnV0IGVuc3VyZSBvbmx5IG9uZSBpdGVtIGlzIG9wZW5cbiAgICAgKiBhdCBhIHRpbWUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0NsaWNrRXZlbnR9IGVcbiAgICAgKiAgIERPTSBjbGljayBldmVudCBvYmplY3QsIGNvbnRhaW5pbmcgaW5mb3JtYXRpb24gYWJvdXQgdGhlIGl0ZW0gYmVpbmdcbiAgICAgKiAgIGJlaW5nIGNsaWNrZWQgd2l0aCB0aGUgY29sbGFwc2UgZnVuY3Rpb25hbGl0eS5cbiAgICAgKi9cbiAgICBzdGF0aWMgb25DbGlja0V4Y2x1c2l2ZShlKSB7XG4gICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgIGlmICh0aGlzLmlzRXhwYW5kZWQpIHtcbiAgICAgICAgdGhpcy5jb2xsYXBzZSgpO1xuICAgICAgfVxuICAgICAgZWxzZSB7XG4gICAgICAgIC8vIFJlY3Vyc2l2ZWx5IGNsb3NlIGFsbCB0aGUgb3BlbiBjaGlsZCBhY2NvcmRpb25zLlxuICAgICAgICB0aGlzLnBhcmVudC5jaGlsZHJlbi5mb3JFYWNoKChjaGlsZCkgPT4ge1xuICAgICAgICAgIGlmIChjaGlsZCAhPT0gdGhpcyAmJiBjaGlsZC5pc0V4cGFuZGVkKSBjaGlsZC5jb2xsYXBzZSgpO1xuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLmV4cGFuZCgpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRlYXJkb3duIGFueSBldmVudHMgYW5kIGFsdGVyYXRpb25zIHRoaXMgYWNjb3JkaW9uIGl0ZW0gbWFkZSB0byB0aGUgRE9NLlxuICAgICAqL1xuICAgIGRlc3Ryb3koKSB7XG4gICAgICB0aGlzLmV4cGFuZGVyLnJlbW92ZUF0dHJzKFsnYXJpYS1leHBhbmRlZCcsICdhcmlhLWNvbnRyb2xzJ10pO1xuICAgICAgdGhpcy5leHBhbmRlci5yZW1vdmVDbGFzcyhbXG4gICAgICAgICd0b2dnbGVyLS1leHBhbmRlZCcsXG4gICAgICAgICd0b2dnbGVyLS1jb2xsYXBzZWQnLFxuICAgICAgXSk7XG4gICAgICB0aGlzLnJlbW92ZUNsYXNzKFtcbiAgICAgICAgJ2FjY29yZGlvbi1pdGVtJyxcbiAgICAgICAgJ2l0ZW0tLWNvbGxhcHNlZCcsXG4gICAgICAgICdpdGVtLS1leHBhbmRlZCcsXG4gICAgICAgICdpdGVtLS1jb2xsYXBzaWJsZScsXG4gICAgICBdKTtcblxuICAgICAgLy8gUmVzZXQgdGhlIGFjY29yZGlvbiBib2R5IGRpc3BsYXkuXG4gICAgICB0aGlzLmJvZHkuc3R5bGUuZGlzcGxheSA9ICcnO1xuICAgICAgdGhpcy5ib2R5LnN0eWxlLmhlaWdodCA9ICcnO1xuXG4gICAgICAvLyBDbGVhciB0aGUgZXhwYW5kZXIgZXZlbnRzLlxuICAgICAgdGhpcy5leHBhbmRlci5kZXN0cm95KCk7XG4gICAgICBzdXBlci5kZXN0cm95KCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIERlZmluZXMgYSBub24tY29sbGFwc2libGUgYWNjb3JkaW9uIGl0ZW0uXG4gICAqL1xuICBjbGFzcyBOb25BY2NvcmRpb25JdGVtIGV4dGVuZHMgdHMuRWxlbWVudCB7XG4gICAgLyoqXG4gICAgICogQ2xhc3MgcmVwcmVzZW50aW5nIGEgc2luZ2xlIGl0ZW0gb2YgYW4gQWNjb3JkaW9uIHdoaWNoIGlzIG5vdCBleHBhbmRhYmxlXG4gICAgICogb3IgY29sbGFwc2libGUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0VsZW1lbnR9IGVsXG4gICAgICogICBUaGUgd2hvbGUgYWNjb3JkaW9uIGl0ZW0uXG4gICAgICogQHBhcmFtIHtBY2NvcmRpb258QWNjb3JkaW9uSXRlbX0gcGFyZW50XG4gICAgICogICBQYXJlbnQgYWNjb3JkaW9uIGluc3RhbmNlLlxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGVsLCBwYXJlbnQpIHtcbiAgICAgIHN1cGVyKGVsLCB7Y2xhc3M6ICdhY2NvcmRpb24taXRlbSd9KTtcbiAgICAgIHRoaXMuZWwgPSBlbDtcbiAgICAgIHRoaXMucGFyZW50ID0gcGFyZW50O1xuICAgICAgdGhpcy5jaGlsZHJlbiA9IFtdO1xuICAgICAgdGhpcy5pc0V4cGFuZGVkID0gZmFsc2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkIGEgY2hpbGQgYWNjb3JkaW9uIGl0ZW0uXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0FjY29yZGlvbkl0ZW19IGNoaWxkXG4gICAgICogICBDaGlsZCBhY2NvcmRpb24gaXRlbSB0byBhZGQuXG4gICAgICovXG4gICAgYWRkQ2hpbGQoY2hpbGQpIHtcbiAgICAgIHRoaXMuaXNFeHBhbmRlZCA9IHRydWU7XG4gICAgICB0aGlzLmNoaWxkcmVuLnB1c2goY2hpbGQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgY2xhc3MgaW1wbGVtZW50cyBhbiBleHBhbmQgZnVuY3Rpb24gaW4gb3JkZXIgdG8gaGF2ZSB0aGUgc2FtZVxuICAgICAqIGludGVyZmFjZSBhcyB0aGUgQWNjb3JkaW9uSXRlbSBjbGFzcywgYnV0IHNpbmNlIHRoaXMgaXMgYVxuICAgICAqIG5vbi1jb2xsYXBzaWJsZSBhY2NvcmRpb24gaXRlbSwgaXQgZG9lcyBub3RoaW5nLlxuICAgICAqL1xuICAgIGV4cGFuZCgpIHt9IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgY2xhc3MtbWV0aG9kcy11c2UtdGhpc1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBjbGFzcyBpbXBsZW1lbnRzIGEgY29sbGFwc2UgZnVuY3Rpb24gaW4gb3JkZXIgdG8gaGF2ZSB0aGUgc2FtZVxuICAgICAqIGludGVyZmFjZSBhcyB0aGUgQWNjb3JkaW9uSXRlbSBjbGFzcywgYnV0IHNpbmNlIHRoaXMgaXMgYVxuICAgICAqIG5vbi1jb2xsYXBzaWJsZSBhY2NvcmRpb24gaXRlbSwgaXQganVzdCBjb2xsYXBzZXMgYW55IGNoaWxkcmVuLlxuICAgICAqL1xuICAgIGNvbGxhcHNlKCkge1xuICAgICAgLy8gUmVjdXJzaXZlbHkgY2xvc2UgYWxsIHRoZSBvcGVuIGNoaWxkIGFjY29yZGlvbnMuXG4gICAgICB0aGlzLmNoaWxkcmVuLmZvckVhY2goKGNoaWxkKSA9PiB7XG4gICAgICAgIGlmIChjaGlsZC5pc0V4cGFuZGVkKSBjaGlsZC5jb2xsYXBzZShmYWxzZSk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQWNjb3JkaW9uIG9iamVjdCBkZWZpbml0aW9uLlxuICAgKi9cbiAgdHMuQWNjb3JkaW9uID0gY2xhc3MgQWNjb3JkaW9uIGV4dGVuZHMgdHMuRWxlbWVudCB7XG4gICAgLyoqXG4gICAgICogQ3JlYXRlIGFuIGFjY29yZGlvbiBvZiBleHBhbmRhYmxlIGFuZCBjb2xsYXBzaWJsZSBpdGVtcy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7RWxlbWVudH0gZWxcbiAgICAgKiAgIERPTSBlbGVtZW50IHRvIHR1cm4gaW50byBhbiBhY2NvcmRpb24uXG4gICAgICogQHBhcmFtIHtPYmplY3R9IGNvbmZpZ3NcbiAgICAgKiAgIEEgY29uZmlndXJhdGlvbiBvcHRpb25zIHdoaWNoIGRldGVybWluZSB0aGUgb3B0aW9uczpcbiAgICAgKiAgIHtcbiAgICAgKiAgICAgaW5pdE9wZW46IHtib29sfHNlbGVjdG9yfSBbdHJ1ZV0sXG4gICAgICogICAgICAgLy8gU2hvdWxkIGFjY29yZGlvbiBwYW5lbHMgc3RhcnQgb2YgaW5pdGlhbGx5IG9wZW4uXG4gICAgICogICAgIGV4Y2x1c2l2ZToge2Jvb2x9IFt0cnVlXSxcbiAgICAgKiAgICAgICAvLyBBY2NvcmRpb24gb25seSBoYXMgb25lIGl0ZW0gb3BlbiBhdCBhIHRpbWUuXG4gICAgICogICAgIGFuaW1hdGU6IHtib29sfSBbdHJ1ZV0sXG4gICAgICogICAgICAgLy8gU2hvdWxkIHRoZSBhY2NvcmRpb25zIGV4cGFuZCBhbmQgY29sbGFwc2UgYW5pbWF0ZS5cbiAgICAgKiAgICAgdHJhbnNpdGlvbkR1cmF0aW9uOiB7c3RyaW5nfSBbJzAuM3MnXVxuICAgICAqICAgICAgIC8vIEhvdyBsb25nIHRoZSBleHBhbmQvY29sbGFwc2UgdHJhbnNpdGlvbnMgc2hvdWxkIGxhc3QuIFNob3VsZCBiZVxuICAgICAqICAgICAgIC8vIGEgZHVyYXRpb24gdGhhdCBhIENTUyB0cmFuc2l0aW9uIGNhbiBhY2NlcHQgKHN1Y2ggYXMgJzMwMG1zJyBvclxuICAgICAqICAgICAgIC8vICcwLjNzJykuXG4gICAgICogICAgIHRvZ2dsZXI6IHtET01TdHJpbmd8ZnVuY3Rpb258b2JqZWN0fVxuICAgICAqICAgICAgIC8vIFRoZSBzZWxlY3RvciB0byBmaW5kIHRoZSBlbGVtZW50IHRvIHRvZ2dsZSB0aGUgY29sbGFwc2UgYW5kIGV4cGFuZCwgT1JcbiAgICAgKiAgICAgICAvLyBBIGNhbGxiYWNrIGZ1bmN0aW9uIHRvIGNyZWF0ZSB0aGUgdG9nZ2xlciBlbGVtZW50LCBPUlxuICAgICAqICAgICAgIC8vIEFuIG9iamVjdCB3aXRoIGBjcmVhdGVgIGFuZCBgYXR0YWNoZXJgIGZ1bmN0aW9ucyB0byBjcmVhdGUgYW5kXG4gICAgICogICAgICAgLy8gcGxhY2UgdGhlIHRvZ2dsZXIgaW50byB0aGUgRE9NLlxuICAgICAqICAgICBpdGVtU2VsOiB7RE9NU3RyaW5nfVxuICAgICAqICAgICAgIC8vIFRoZSBzZWxlY3RvciB0byB1c2Ugd2hlbiBsb2NhdGluZyBlYWNoIG9mIHRoZSBhY2NvcmRpb24gaXRlbXMuXG4gICAgICogICAgIGJvZHlTZWw6IHtET01TdHJpbmd9XG4gICAgICogICAgICAgLy8gVGhlIHNlbGVjdG9yIHRvIHVzZSB0byBmaW5kIHRoZSBpdGVtIGJvZHkgd2l0aGluIHRoZSBpdGVtIGNvbnRleHQuXG4gICAgICogICB9XG4gICAgICovXG4gICAgY29uc3RydWN0b3IoZWwsIGNvbmZpZ3MpIHtcbiAgICAgIHN1cGVyKGVsLCB7IGNsYXNzOiAnYWNjb3JkaW9uJ30pO1xuXG4gICAgICB0aGlzLml0ZW1zID0gbmV3IE1hcCgpO1xuICAgICAgdGhpcy5jaGlsZHJlbiA9IFtdO1xuXG4gICAgICB0aGlzLmNvbmZpZ3MgPSB7XG4gICAgICAgIGV4Y2x1c2l2ZTogdHJ1ZSxcbiAgICAgICAgaW5pdE9wZW46IHRydWUsXG4gICAgICAgIGFuaW1hdGU6IHRydWUsXG4gICAgICAgIGFuaW1hdGVUaW1lOiAnMC4zcycsXG4gICAgICAgIC4uLmNvbmZpZ3MsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB7XG4gICAgICAgIGV4Y2x1c2l2ZSxcbiAgICAgICAgaW5pdE9wZW4sXG4gICAgICAgIGl0ZW1TZWwsXG4gICAgICAgIGJvZHlTZWwsXG4gICAgICB9ID0gdGhpcy5jb25maWdzO1xuXG4gICAgICBsZXQgdG9nZ2xlT3B0ID0gdGhpcy5jb25maWdzLnRvZ2dsZXIgfHwgdGhlbWUuYWNjb3JkaW9uVG9nZ2xlcjtcblxuICAgICAgLy8gSWYgdGhlIGV4cGFuZCBvcHRpb24gaXMganVzdCBhIHNlbGVjdG9yLCB0aGVuIHRoZSBlbGVtZW50IGlzIGV4cGVjdGVkXG4gICAgICAvLyB0byBhbHJlYWR5IGJlIGluIHRoZSBkb2N1bWVudCAob3RoZXJ3aXNlIG5vdCBmaW5kYWJsZSkuXG4gICAgICBpZiAodHMuaXNTdHJpbmcodG9nZ2xlT3B0KSkge1xuICAgICAgICB0aGlzLmdldFRvZ2dsZXIgPSAoaXRlbSkgPT4gbmV3IHRzLkVsZW1lbnQoaXRlbS5xdWVyeVNlbGVjdG9yKHRvZ2dsZU9wdCl8fCdidXR0b24nKTtcbiAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICBpZiAodHlwZW9mIHRvZ2dsZU9wdCA9PT0gJ2Z1bmN0aW9uJykgdG9nZ2xlT3B0ID0geyBjcmVhdGU6IHRvZ2dsZU9wdCB9O1xuXG4gICAgICAgIGlmICghdG9nZ2xlT3B0LmF0dGFjaCkge1xuICAgICAgICAgIHRvZ2dsZU9wdC5hdHRhY2ggPSAodG9nZ2xlciwgaXRlbSkgPT4gaXRlbS5pbnNlcnRCZWZvcmUodG9nZ2xlci5lbCwgaXRlbS5xdWVyeVNlbGVjdG9yKGJvZHlTZWwpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuZ2V0VG9nZ2xlciA9IChpdGVtKSA9PiB7XG4gICAgICAgICAgbGV0IHRvZ2dsZXIgPSB0b2dnbGVPcHQuY3JlYXRlKGl0ZW0pO1xuXG4gICAgICAgICAgLy8gSWYgbm90IGFscmVhZHkgaW4gdGhlIERPTSwgdXNlIHRoZSBhdHRhY2ggY2FsbGJhY2sgdG8gaW5zZXJ0IGl0LlxuICAgICAgICAgIGlmICh0b2dnbGVyICYmICF0b2dnbGVyLnBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgIHRvZ2dsZU9wdC5hdHRhY2godG9nZ2xlciwgaXRlbSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmV0dXJuIHRvZ2dsZXI7XG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIC8vIEJ1aWxkIHRoZSBhY2NvcmRpb24gaXRlbXMgYWxsb3dpbmcgZm9yIGEgbmVzdGVkIHRyZWUgc3RydWN0dXJlLlxuICAgICAgdGhpcy5maW5kKGl0ZW1TZWwpLmZvckVhY2goKGVsKSA9PiB0aGlzLmJ1aWxkVHJlZUl0ZW0oZWwpKTtcblxuICAgICAgaWYgKCFpbml0T3BlbiB8fCBleGNsdXNpdmUpIHtcbiAgICAgICAgdGhpcy5jaGlsZHJlbi5mb3JFYWNoKChjaGlsZCwgaSkgPT4ge1xuICAgICAgICAgIGlmICghaW5pdE9wZW4gfHwgaSAhPT0gMCkgY2hpbGQuY29sbGFwc2UoZmFsc2UpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBZGQgYSBjaGlsZCBhY2NvcmRpb24gaXRlbS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7QWNjb3JkaW9uSXRlbX0gY2hpbGRcbiAgICAgKiAgIENoaWxkIGFjY29yZGlvbiBpdGVtIHRvIGFkZC5cbiAgICAgKi9cbiAgICBhZGRDaGlsZChjaGlsZCkge1xuICAgICAgdGhpcy5jaGlsZHJlbi5wdXNoKGNoaWxkKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGaW5kIHRoZSBwYXJlbnQgYWNjb3JkaW9uIGl0ZW0gZm9yIHRoaXMgZWxlbWVudC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7RE9NRWxlbWVudH0gZWxcbiAgICAgKiAgIFRoZSBlbGVtZW50IHRvIHNlYXJjaCBmb3IgdGhlIGNsb3Nlc3QgbWF0Y2hpbmcgc2VsZWN0b3IgZm9yLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzZWxlY3RvclxuICAgICAqICAgU2VsZWN0b3IgdG8gdXNlIHdoZW4gaWRlbnRpZnlpbmcgYW4gYWNjb3JkaW9uIGl0ZW0uXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtFbGVtZW50fG51bGx9XG4gICAgICogICBJZiBhbiBhcHByb3ByaWF0ZSBwYXJlbnQgbWF0Y2hpbmcgdGhlIGl0ZW0gc2VsZWN0b3IgaXMgZm91bmQgd2l0aGluXG4gICAgICogICB0aGUgY29uZmluZXMgb2YgdGhlIGFjY29yZGlvbiBlbGVtZW50LCBpdCBpcyByZXR1cm5lZC4gT3RoZXJ3aXNlLFxuICAgICAqICAgcmV0dXJuIHRoZSBFbGVtZW50IHdyYXBwaW5nIHRoZSBhY2NvcmRpb24uXG4gICAgICovXG4gICAgZmluZFBhcmVudChlbCwgc2VsZWN0b3IpIHtcbiAgICAgIGxldCBjdXIgPSBlbDtcblxuICAgICAgZG8ge1xuICAgICAgICBjdXIgPSBjdXIucGFyZW50RWxlbWVudDtcbiAgICAgIH0gd2hpbGUgKGN1ciAmJiBjdXIgIT09IHRoaXMuZWwgJiYgIWN1ci5tYXRjaGVzKHNlbGVjdG9yKSk7XG5cbiAgICAgIHJldHVybiBjdXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVjdXJzaXZlbHkgYWRkIGFjY29yZGlvbiBpdGVtcyB0byB0aGUgdHJlZSBzdHJ1Y3R1cmUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0RPTUVsZW1lbnR9IGVsXG4gICAgICogICBUaGUgSFRNTEVsZW1lbnQgdG9zIHRyYW5zZm9ybSBpbnRvIGFuIGFjY29yZGlvbiBpdGVtLlxuICAgICAqXG4gICAgICogQHJldHVybiB7QWNjb3JkaW9uSXRlbXxOb25BY2NvcmRpb25JdGVtfVxuICAgICAqICAgQW4gYWNjb3JkaW9uIGl0ZW0gb3IgYSBOb25BY2NvcmRpb25JdGVtIChpdGVtIHRoYXQgZG9lc24ndCBjb2xsYXBzZSkuXG4gICAgICovXG4gICAgYnVpbGRUcmVlSXRlbShlbCkge1xuICAgICAgbGV0IGEgPSB0aGlzLml0ZW1zLmdldChlbCk7XG5cbiAgICAgIC8vIFRoaXMgZWxlbWVudCBoYXMgYWxyZWFkeSBiZWVuIGJ1aWx0LCBkb24ndCBuZWVkIHRvIHJlYnVpbGQgc3VidHJlZS5cbiAgICAgIGlmIChhKSByZXR1cm4gYTtcblxuICAgICAgY29uc3QgeyBpdGVtU2VsLCBib2R5U2VsIH0gPSB0aGlzLmNvbmZpZ3M7XG4gICAgICBjb25zdCBwYXJlbnQgPSB0aGlzLmZpbmRQYXJlbnQoZWwsIGl0ZW1TZWwpO1xuXG4gICAgICAvLyBPbmx5IGNyZWF0ZSBhbiBhY2NvcmRpb24gaXRlbSBpZiBpdCBoYXMgYSBwYXJlbnQgaXRlbSB3aGljaCBleGlzdHNcbiAgICAgIC8vIHdpdGhpbiB0aGUgQWNjb3JkaW9uIHNjb3BlLlxuICAgICAgaWYgKCFwYXJlbnQpIHRocm93IG5ldyBFcnJvcignVW5hYmxlIHRvIGZpbmQgYSBwYXJlbnQgYnVpbGRUcmVlSXRlbSgpLicpO1xuXG4gICAgICBjb25zdCBpUGFyZW50ID0gKHBhcmVudCA9PT0gdGhpcy5lbCkgPyB0aGlzIDogdGhpcy5pdGVtcy5nZXQocGFyZW50KSB8fCB0aGlzLmJ1aWxkVHJlZUl0ZW0ocGFyZW50KTtcbiAgICAgIGlmICghaVBhcmVudCkgdGhyb3cgbmV3IEVycm9yKCdObyB2YWxpZCBhY2NvcmRpb24gcGFyZW50IGF2YWlsYWJsZSwgb3Igbm90IGEgZGVzY2VuZGVudCBvZiB0aGUgYWNjb3JkaW9uLicpO1xuXG4gICAgICAvLyBPbmx5IGNyZWF0ZSBhIGNvbGxhcHNpYmxlIGFjY29yZGlvbiBpdGVtIGlmIGl0IGhhcyBhIGhhcyBhIGJvZHkgdG9cbiAgICAgIC8vIGV4cGFuZCwgYW5kIGFuIGV4cGFuZGVyIChleHBhbmQvY29sbGFwc2UgdG9nZ2xlKS4gT3RoZXJ3aXNlIGNyZWF0ZSBhXG4gICAgICAvLyBub24tY29sbGFwc2libGUgYWNjb3JkaW9uIGl0ZW0uXG4gICAgICBsZXQgYWNjb3JkO1xuICAgICAgY29uc3QgYm9keSA9IGVsLnF1ZXJ5U2VsZWN0b3IoYm9keVNlbCk7XG4gICAgICBpZiAoYm9keSkge1xuICAgICAgICBjb25zdCBleHBhbmRlciA9IHRoaXMuZ2V0VG9nZ2xlcihlbCk7XG5cbiAgICAgICAgaWYgKGV4cGFuZGVyKSB7XG4gICAgICAgICAgLy8gVGhpcyBhY2NvcmRpb24gaXRlbSBzaG91bGQgYmUgbWFkZSBjb2xsYXBzaWJsZS5cbiAgICAgICAgICBhY2NvcmQgPSBuZXcgdHMuQWNjb3JkaW9uSXRlbShlbCwgZXhwYW5kZXIsIG5ldyB0cy5FbGVtZW50KGJvZHkpLCBpUGFyZW50LCB0aGlzLmNvbmZpZ3MpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmICghYWNjb3JkKSB7XG4gICAgICAgIC8vIFRoaXMgYWNjb3JkaW9uIGl0ZW0gc2hvdWxkIGJlIG1hZGUgbm9uLWNvbGxhcHNpYmxlLlxuICAgICAgICBhY2NvcmQgPSBuZXcgTm9uQWNjb3JkaW9uSXRlbShpdGVtLCBpUGFyZW50KTtcbiAgICAgIH1cblxuICAgICAgLy8gQWRkIHRoZSBhY2NvcmRpb24gaXRlbSB0byB0aGUgYWNjb3JkaW9uJ3MgJ2l0ZW1zJyBsaXN0LCBhbmQgdG8gaXRzXG4gICAgICAvLyBwYXJlbnQncyBsaXN0IG9mIGNoaWxkcmVuLlxuICAgICAgdGhpcy5pdGVtcy5zZXQoZWwsIGFjY29yZCk7XG4gICAgICBpUGFyZW50LmFkZENoaWxkKGFjY29yZCk7XG5cbiAgICAgIHJldHVybiBhY2NvcmQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGVhcmRvd24gYW55IGNoYW5nZXMgdG8gdGhlIERPTSBhcyB3ZWxsIGFzIGNsZWFyaW5nIEFjY29yZGlvbkl0ZW1zLlxuICAgICAqL1xuICAgIGRlc3Ryb3koKSB7XG4gICAgICB0aGlzLnJlbW92ZUNsYXNzKCdhY2NvcmRpb24nKTtcblxuICAgICAgLy8gRGVzdHJveSBhbGwgdGhlIGFjY29yZGlvbiBpdGVtcy5cbiAgICAgIHRoaXMuaXRlbXMuZm9yRWFjaCgoaXRlbSkgPT4gaXRlbS5kZXN0cm95KCkpO1xuXG4gICAgICBkZWxldGUgdGhpcy5pdGVtcztcbiAgICAgIGRlbGV0ZSB0aGlzLmNoaWxkcmVuO1xuICAgICAgZGVsZXRlIHRoaXMuY29uZmlncztcblxuICAgICAgc3VwZXIuZGVzdHJveSgpO1xuICAgIH1cbiAgfTtcbn0pKERydXBhbCk7XG4iXSwibWFwcGluZ3MiOiI7O0FBQUEsQ0FBQyxDQUFDO0VBQUVBLEtBQUs7RUFBRUMsQ0FBQztFQUFFQyxRQUFRLEVBQUVDO0FBQUcsQ0FBQyxLQUFLO0VBQy9CO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7RUFDRUgsS0FBSyxDQUFDSSxnQkFBZ0IsR0FBRyxDQUFDQyxVQUFVLEdBQUcsUUFBUSxF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
