@tripsnek/tmf
Version:
TypeScript Modeling Framework - A TypeScript port of the Eclipse Modeling Framework (EMF)
323 lines • 40.5 kB
JavaScript
/**
* A drop-in replacement for xml2js that converts XML to JavaScript objects
* with the same structure and behavior as xml2js.parseString()
*/
// Node type constants (in case Node global is not available)
const NODE_TYPES = {
ELEMENT_NODE: 1,
TEXT_NODE: 3,
CDATA_SECTION_NODE: 4,
};
export class XmlToJsParser {
options;
constructor(options = {}) {
this.options = {
explicitArray: options.explicitArray !== false,
mergeAttrs: options.mergeAttrs === true,
explicitRoot: options.explicitRoot !== false,
ignoreAttrs: options.ignoreAttrs === true,
trim: options.trim === true,
normalize: options.normalize === true,
...options,
};
}
/**
* Parse XML string to JavaScript object (async version)
*/
parseString(xml) {
return new Promise((resolve, reject) => {
try {
const result = this.parseStringSync(xml);
resolve(result);
}
catch (error) {
reject(error);
}
});
}
/**
* Parse XML string to JavaScript object (sync version)
*/
parseStringSync(xml) {
if (this.isDOMParserAvailable()) {
return this.parseInBrowser(xml);
}
else {
// For Node.js environment, we'll need to implement our own XML parser
// or use a lightweight alternative
return this.parseInNode(xml);
}
}
/**
* Check if DOMParser is available (browser environment)
*/
isDOMParserAvailable() {
return (typeof globalThis !== 'undefined' &&
typeof globalThis.DOMParser !== 'undefined');
}
/**
* Browser implementation using DOMParser
*/
parseInBrowser(xml) {
try {
const parser = new globalThis.DOMParser();
const xmlDoc = parser.parseFromString(xml, 'text/xml');
// Check for parser errors
const parserError = xmlDoc.querySelector('parsererror');
if (parserError) {
throw new Error(`XML Parse Error: ${parserError.textContent}`);
}
if (!xmlDoc.documentElement) {
throw new Error('Invalid XML: No document element found');
}
const result = this.domElementToJs(xmlDoc.documentElement, true); // true = isRootLevel
if (this.options.explicitRoot) {
return { [xmlDoc.documentElement.tagName]: result };
}
else {
return result;
}
}
catch (error) {
throw new Error(`XML parsing failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
/**
* Node.js implementation using simple regex-based parser
* This is a lightweight XML parser that handles most common cases
*/
parseInNode(xml) {
// Remove XML declaration and comments
xml = xml.replace(/<\?xml[^>]*\?>/g, '');
xml = xml.replace(/<!--[\s\S]*?-->/g, '');
xml = xml.trim();
const stack = [];
const result = {};
let current = result;
let isRootLevel = true;
// Simple regex to match XML tags and content
const tagRegex = /<\/?([^>\s]+)([^>]*)>/g;
let lastIndex = 0;
let match;
while ((match = tagRegex.exec(xml)) !== null) {
const [fullMatch, tagName, attributesStr] = match;
const isClosing = fullMatch.startsWith('</');
const isSelfClosing = fullMatch.endsWith('/>');
// Handle text content before this tag
if (match.index > lastIndex) {
const textContent = xml.substring(lastIndex, match.index);
if (textContent.trim()) {
this.addTextContent(current, textContent);
}
}
if (isClosing) {
// Closing tag - pop from stack
if (stack.length > 0) {
current = stack.pop();
if (stack.length === 0) {
isRootLevel = true;
}
}
}
else {
// Opening tag or self-closing tag
const element = {};
// Parse attributes
if (attributesStr) {
if (!this.options.ignoreAttrs && attributesStr.trim()) {
const attrs = this.parseAttributes(attributesStr);
if (Object.keys(attrs).length > 0) {
if (this.options.mergeAttrs) {
Object.assign(element, attrs);
}
else {
element.$ = attrs;
}
}
}
}
// Add element to current parent (don't force array for root level)
if (tagName)
this.addChildElement(current, tagName, element, isRootLevel);
// If not self-closing, push to stack for children
if (!isSelfClosing) {
stack.push(current);
current = element;
isRootLevel = false;
}
}
lastIndex = tagRegex.lastIndex;
}
// Handle any remaining text content
if (lastIndex < xml.length) {
const textContent = xml.substring(lastIndex);
if (textContent.trim()) {
this.addTextContent(current, textContent);
}
}
// Return the root element
const rootKeys = Object.keys(result);
if (rootKeys.length === 1 && this.options.explicitRoot) {
return result;
}
else if (rootKeys.length === 1) {
return result[rootKeys[0]];
}
else {
return result;
}
}
/**
* Convert DOM element to JavaScript object (for browser)
*/
domElementToJs(element, isRootLevel = false) {
const result = {};
// Handle attributes
if (!this.options.ignoreAttrs &&
element.attributes &&
element.attributes.length > 0) {
const attrs = {};
for (let i = 0; i < element.attributes.length; i++) {
const attr = element.attributes[i];
attrs[attr.name] = attr.value;
}
if (this.options.mergeAttrs) {
Object.assign(result, attrs);
}
else {
result.$ = attrs;
}
}
// Group child elements by tag name
const childElements = {};
const textParts = [];
// Process all child nodes
for (let i = 0; i < element.childNodes.length; i++) {
const child = element.childNodes[i];
if (child.nodeType === NODE_TYPES.ELEMENT_NODE) {
const childElement = child;
const tagName = childElement.tagName;
if (!childElements[tagName]) {
childElements[tagName] = [];
}
childElements[tagName].push(childElement);
}
else if (child.nodeType === NODE_TYPES.TEXT_NODE ||
child.nodeType === NODE_TYPES.CDATA_SECTION_NODE) {
const textContent = child.textContent || '';
if (textContent.trim()) {
textParts.push(textContent);
}
}
}
// Add child elements to result
for (const [tagName, elements] of Object.entries(childElements)) {
const childObjects = elements.map((el) => this.domElementToJs(el, false)); // children are not root level
// Use the helper method to maintain consistency with Node.js implementation
if (elements.length === 1) {
this.addChildElement(result, tagName, childObjects[0], false);
}
else {
// Multiple elements with same tag name always become arrays
result[tagName] = childObjects;
}
}
// Handle text content
if (textParts.length > 0 && Object.keys(childElements).length === 0) {
const textContent = textParts.join('');
const finalText = this.options.trim ? textContent.trim() : textContent;
if (this.options.normalize) {
result._ = finalText.replace(/\s+/g, ' ');
}
else {
result._ = finalText;
}
}
return result;
}
/**
* Parse attribute string into object
*/
parseAttributes(attributesStr) {
const attrs = {};
const attrRegex = /(\S+)=["']([^"']*)["']/g;
let match;
while ((match = attrRegex.exec(attributesStr)) !== null) {
const [, name, value] = match;
if (name)
attrs[name] = value;
}
return attrs;
}
/**
* Add text content to current element
*/
addTextContent(current, textContent) {
const trimmed = textContent.trim();
if (trimmed) {
const finalText = this.options.trim ? trimmed : textContent;
const normalizedText = this.options.normalize
? finalText.replace(/\s+/g, ' ')
: finalText;
if (current._) {
current._ += normalizedText;
}
else {
current._ = normalizedText;
}
}
}
/**
* Add child element to parent
*/
addChildElement(parent, tagName, element, isRootLevel = false) {
if (parent[tagName]) {
// Convert to array if not already
if (!Array.isArray(parent[tagName])) {
parent[tagName] = [parent[tagName]];
}
parent[tagName].push(element);
}
else {
// For root level elements, don't force array even if explicitArray is true
// xml2js only uses arrays for child elements, not the root element
if (this.options.explicitArray && !isRootLevel) {
parent[tagName] = [element];
}
else {
parent[tagName] = element;
}
}
}
}
// Default instance with xml2js-compatible defaults
const defaultParser = new XmlToJsParser({
explicitArray: true,
mergeAttrs: false,
explicitRoot: true,
ignoreAttrs: false,
trim: false,
normalize: false,
});
/**
* Drop-in replacement for xml2js.parseString()
*/
export function parseString(xml, callback) {
if (callback) {
defaultParser
.parseString(xml)
.then((result) => callback(null, result))
.catch((err) => callback(err));
return Promise.resolve();
}
else {
return defaultParser.parseString(xml);
}
}
/**
* Synchronous version
*/
export function parseStringSync(xml) {
return defaultParser.parseStringSync(xml);
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoieG1sLXRvLWpzLXBhcnNlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9saWIvZWNvcmUveG1sLXRvLWpzLXBhcnNlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7O0dBR0c7QUErQ0gsNkRBQTZEO0FBQzdELE1BQU0sVUFBVSxHQUFHO0lBQ2pCLFlBQVksRUFBRSxDQUFDO0lBQ2YsU0FBUyxFQUFFLENBQUM7SUFDWixrQkFBa0IsRUFBRSxDQUFDO0NBQ2IsQ0FBQztBQVdYLE1BQU0sT0FBTyxhQUFhO0lBQ2hCLE9BQU8sQ0FBMkI7SUFFMUMsWUFBWSxVQUEwQixFQUFFO1FBQ3RDLElBQUksQ0FBQyxPQUFPLEdBQUc7WUFDYixhQUFhLEVBQUUsT0FBTyxDQUFDLGFBQWEsS0FBSyxLQUFLO1lBQzlDLFVBQVUsRUFBRSxPQUFPLENBQUMsVUFBVSxLQUFLLElBQUk7WUFDdkMsWUFBWSxFQUFFLE9BQU8sQ0FBQyxZQUFZLEtBQUssS0FBSztZQUM1QyxXQUFXLEVBQUUsT0FBTyxDQUFDLFdBQVcsS0FBSyxJQUFJO1lBQ3pDLElBQUksRUFBRSxPQUFPLENBQUMsSUFBSSxLQUFLLElBQUk7WUFDM0IsU0FBUyxFQUFFLE9BQU8sQ0FBQyxTQUFTLEtBQUssSUFBSTtZQUNyQyxHQUFHLE9BQU87U0FDWCxDQUFDO0lBQ0osQ0FBQztJQUVEOztPQUVHO0lBQ0ksV0FBVyxDQUFDLEdBQVc7UUFDNUIsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtZQUNyQyxJQUFJLENBQUM7Z0JBQ0gsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsQ0FBQztnQkFDekMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ2xCLENBQUM7WUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO2dCQUNmLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUNoQixDQUFDO1FBQ0gsQ0FB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RUFBRSxDQUFDO0lBQzNCLENBQUM7U0FBTSxDQUFDO1FBQ04sT0FBTyxhQUFhLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3hDLENBQUM7QUFDSCxDQUFDO0FBRUQ7O0dBRUc7QUFDSCxNQUFNLFVBQVUsZUFBZSxDQUFDLEdBQVc7SUFDekMsT0FBTyxhQUFhLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0FBQzVDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcclxuICogQSBkcm9wLWluIHJlcGxhY2VtZW50IGZvciB4bWwyanMgdGhhdCBjb252ZXJ0cyBYTUwgdG8gSmF2YVNjcmlwdCBvYmplY3RzXHJcbiAqIHdpdGggdGhlIHNhbWUgc3RydWN0dXJlIGFuZCBiZWhhdmlvciBhcyB4bWwyanMucGFyc2VTdHJpbmcoKVxyXG4gKi9cclxuXHJcbi8vIFR5cGUgZGVjbGFyYXRpb25zIGZvciBET00gdHlwZXMgd2hlbiBub3QgYXZhaWxhYmxlXHJcbmRlY2xhcmUgZ2xvYmFsIHtcclxuICBpbnRlcmZhY2UgRE9NUGFyc2VyIHtcclxuICAgIHBhcnNlRnJvbVN0cmluZyhzb3VyY2U6IHN0cmluZywgbWltZVR5cGU6IHN0cmluZyk6IERvY3VtZW50O1xyXG4gIH1cclxuXHJcbiAgaW50ZXJmYWNlIERvY3VtZW50IHtcclxuICAgIGRvY3VtZW50RWxlbWVudDogRWxlbWVudCB8IG51bGw7XHJcbiAgICBxdWVyeVNlbGVjdG9yKHNlbGVjdG9yOiBzdHJpbmcpOiBFbGVtZW50IHwgbnVsbDtcclxuICB9XHJcblxyXG4gIGludGVyZmFjZSBFbGVtZW50IHtcclxuICAgIHRhZ05hbWU6IHN0cmluZztcclxuICAgIGF0dHJpYnV0ZXM6IE5hbWVkTm9kZU1hcDtcclxuICAgIGNoaWxkTm9kZXM6IE5vZGVMaXN0O1xyXG4gICAgdGV4dENvbnRlbnQ6IHN0cmluZyB8IG51bGw7XHJcbiAgfVxyXG5cclxuICBpbnRlcmZhY2UgTmFtZWROb2RlTWFwIHtcclxuICAgIGxlbmd0aDogbnVtYmVyO1xyXG4gICAgW2luZGV4OiBudW1iZXJdOiBBdHRyO1xyXG4gIH1cclxuXHJcbiAgaW50ZXJmYWNlIEF0dHIge1xyXG4gICAgbmFtZTogc3RyaW5nO1xyXG4gICAgdmFsdWU6IHN0cmluZztcclxuICB9XHJcblxyXG4gIGludGVyZmFjZSBOb2RlTGlzdCB7XHJcbiAgICBsZW5ndGg6IG51bWJlcjtcclxuICAgIFtpbmRleDogbnVtYmVyXTogTm9kZTtcclxuICB9XHJcblxyXG4gIGludGVyZmFjZSBOb2RlIHtcclxuICAgIG5vZGVUeXBlOiBudW1iZXI7XHJcbiAgICB0ZXh0Q29udGVudDogc3RyaW5nIHwgbnVsbDtcclxuICB9XHJcblxyXG4gIGNvbnN0IE5vZGU6IHtcclxuICAgIEVMRU1FTlRfTk9ERTogbnVtYmVyO1xyXG4gICAgVEVYVF9OT0RFOiBudW1iZXI7XHJcbiAgICBDREFUQV9TRUNUSU9OX05PREU6IG51bWJlcjtcclxuICB9O1xyXG59XHJcblxyXG4vLyBOb2RlIHR5cGUgY29uc3RhbnRzIChpbiBjYXNlIE5vZGUgZ2xvYmFsIGlzIG5vdCBhdmFpbGFibGUpXHJcbmNvbnN0IE5PREVfVFlQRVMgPSB7XHJcbiAgRUxFTUVOVF9OT0RFOiAxLFxyXG4gIFRFWFRfTk9ERTogMyxcclxuICBDREFUQV9TRUNUSU9OX05PREU6IDQsXHJcbn0gYXMgY29uc3Q7XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIFhtbFRvSnNPcHRpb25zIHtcclxuICBleHBsaWNpdEFycmF5PzogYm9vbGVhbjsgLy8gRGVmYXVsdDogdHJ1ZSAtIGFsd2F5cyB1c2UgYXJyYXlzIGZvciBjaGlsZCBlbGVtZW50c1xyXG4gIG1lcmdlQXR0cnM/OiBib29sZWFuOyAvLyBEZWZhdWx0OiBmYWxzZSAtIGtlZXAgYXR0cmlidXRlcyBpbiAkIG9iamVjdFxyXG4gIGV4cGxpY2l0Um9vdD86IGJvb2xlYW47IC8vIERlZmF1bHQ6IHRydWUgLSBrZWVwIHJvb3QgZWxlbWVudFxyXG4gIGlnbm9yZUF0dHJzPzogYm9vbGVhbjsgLy8gRGVmYXVsdDogZmFsc2UgLSBpbmNsdWRlIGF0dHJpYnV0ZXNcclxuICB0cmltPzogYm9vbGVhbjsgLy8gRGVmYXVsdDogZmFsc2UgLSB0cmltIHRleHQgY29udGVudFxyXG4gIG5vcm1hbGl6ZT86IGJvb2xlYW47IC8vIERlZmF1bHQ6IGZhbHNlIC0gbm9ybWFsaXplIHdoaXRlc3BhY2VcclxufVxyXG5cclxuZXhwb3J0IGNsYXNzIFhtbFRvSnNQYXJzZXIge1xyXG4gIHByaXZhdGUgb3B0aW9uczogUmVxdWlyZWQ8WG1sVG9Kc09wdGlvbnM+O1xyXG5cclxuICBjb25zdHJ1Y3RvcihvcHRpb25zOiBYbWxUb0pzT3B0aW9ucyA9IHt9KSB7XHJcbiAgICB0aGlzLm9wdGlvbnMgPSB7XHJcbiAgICAgIGV4cGxpY2l0QXJyYXk6IG9wdGlvbnMuZXhwbGljaXRBcnJheSAhPT0gZmFsc2UsXHJcbiAgICAgIG1lcmdlQXR0cnM6IG9wdGlvbnMubWVyZ2VBdHRycyA9PT0gdHJ1ZSxcclxuICAgICAgZXhwbGljaXRSb290OiBvcHRpb25zLmV4cGxpY2l0Um9vdCAhPT0gZmFsc2UsXHJcbiAgICAgIGlnbm9yZUF0dHJzOiBvcHRpb25zLmlnbm9yZUF0dHJzID09PSB0cnVlLFxyXG4gICAgICB0cmltOiBvcHRpb25zLnRyaW0gPT09IHRydWUsXHJcbiAgICAgIG5vcm1hbGl6ZTogb3B0aW9ucy5ub3JtYWxpemUgPT09IHRydWUsXHJcbiAgICAgIC4uLm9wdGlvbnMsXHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUGFyc2UgWE1MIHN0cmluZyB0byBKYXZhU2NyaXB0IG9iamVjdCAoYXN5bmMgdmVyc2lvbilcclxuICAgKi9cclxuICBwdWJsaWMgcGFyc2VTdHJpbmcoeG1sOiBzdHJpbmcpOiBQcm9taXNlPGFueT4ge1xyXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcclxuICAgICAgdHJ5IHtcclxuICAgICAgICBjb25zdCByZXN1bHQgPSB0aGlzLnBhcnNlU3RyaW5nU3luYyh4bWwpO1xyXG4gICAgICAgIHJlc29sdmUocmVzdWx0KTtcclxuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcclxuICAgICAgICByZWplY3QoZXJyb3IpO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFBhcnNlIFhNTCBzdHJpbmcgdG8gSmF2YVNjcmlwdCBvYmplY3QgKHN5bmMgdmVyc2lvbilcclxuICAgKi9cclxuICBwdWJsaWMgcGFyc2VTdHJpbmdTeW5jKHhtbDogc3RyaW5nKTogYW55IHtcclxuICAgIGlmICh0aGlzLmlzRE9NUGFyc2VyQXZhaWxhYmxlKCkpIHtcclxuICAgICAgcmV0dXJuIHRoaXMucGFyc2VJbkJyb3dzZXIoeG1sKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIC8vIEZvciBOb2RlLmpzIGVudmlyb25tZW50LCB3ZSdsbCBuZWVkIHRvIGltcGxlbWVudCBvdXIgb3duIFhNTCBwYXJzZXJcclxuICAgICAgLy8gb3IgdXNlIGEgbGlnaHR3ZWlnaHQgYWx0ZXJuYXRpdmVcclxuICAgICAgcmV0dXJuIHRoaXMucGFyc2VJbk5vZGUoeG1sKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIENoZWNrIGlmIERPTVBhcnNlciBpcyBhdmFpbGFibGUgKGJyb3dzZXIgZW52aXJvbm1lbnQpXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBpc0RPTVBhcnNlckF2YWlsYWJsZSgpOiBib29sZWFuIHtcclxuICAgIHJldHVybiAoXHJcbiAgICAgIHR5cGVvZiBnbG9iYWxUaGlzICE9PSAndW5kZWZpbmVkJyAmJlxyXG4gICAgICB0eXBlb2YgKGdsb2JhbFRoaXMgYXMgYW55KS5ET01QYXJzZXIgIT09ICd1bmRlZmluZWQnXHJcbiAgICApO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQnJvd3NlciBpbXBsZW1lbnRhdGlvbiB1c2luZyBET01QYXJzZXJcclxuICAgKi9cclxuICBwcml2YXRlIHBhcnNlSW5Ccm93c2VyKHhtbDogc3RyaW5nKTogYW55IHtcclxuICAgIHRyeSB7XHJcbiAgICAgIGNvbnN0IHBhcnNlciA9IG5ldyAoZ2xvYmFsVGhpcyBhcyBhbnkpLkRPTVBhcnNlcigpO1xyXG4gICAgICBjb25zdCB4bWxEb2MgPSBwYXJzZXIucGFyc2VGcm9tU3RyaW5nKHhtbCwgJ3RleHQveG1sJyk7XHJcblxyXG4gICAgICAvLyBDaGVjayBmb3IgcGFyc2VyIGVycm9yc1xyXG4gICAgICBjb25zdCBwYXJzZXJFcnJvciA9IHhtbERvYy5xdWVyeVNlbGVjdG9yKCdwYXJzZXJlcnJvcicpO1xyXG4gICAgICBpZiAocGFyc2VyRXJyb3IpIHtcclxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFhNTCBQYXJzZSBFcnJvcjogJHtwYXJzZXJFcnJvci50ZXh0Q29udGVudH1gKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgaWYgKCF4bWxEb2MuZG9jdW1lbnRFbGVtZW50KSB7XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIFhNTDogTm8gZG9jdW1lbnQgZWxlbWVudCBmb3VuZCcpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBjb25zdCByZXN1bHQgPSB0aGlzLmRvbUVsZW1lbnRUb0pzKHhtbERvYy5kb2N1bWVudEVsZW1lbnQsIHRydWUpOyAvLyB0cnVlID0gaXNSb290TGV2ZWxcclxuXHJcbiAgICAgIGlmICh0aGlzLm9wdGlvbnMuZXhwbGljaXRSb290KSB7XHJcbiAgICAgICAgcmV0dXJuIHsgW3htbERvYy5kb2N1bWVudEVsZW1lbnQudGFnTmFtZV06IHJlc3VsdCB9O1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHJldHVybiByZXN1bHQ7XHJcbiAgICAgIH1cclxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihcclxuICAgICAgICBgWE1MIHBhcnNpbmcgZmFpbGVkOiAke1xyXG4gICAgICAgICAgZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiAnVW5rbm93biBlcnJvcidcclxuICAgICAgICB9YFxyXG4gICAgICApO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogTm9kZS5qcyBpbXBsZW1lbnRhdGlvbiB1c2luZyBzaW1wbGUgcmVnZXgtYmFzZWQgcGFyc2VyXHJcbiAgICogVGhpcyBpcyBhIGxpZ2h0d2VpZ2h0IFhNTCBwYXJzZXIgdGhhdCBoYW5kbGVzIG1vc3QgY29tbW9uIGNhc2VzXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBwYXJzZUluTm9kZSh4bWw6IHN0cmluZyk6IGFueSB7XHJcbiAgICAvLyBSZW1vdmUgWE1MIGRlY2xhcmF0aW9uIGFuZCBjb21tZW50c1xyXG4gICAgeG1sID0geG1sLnJlcGxhY2UoLzxcXD94bWxbXj5dKlxcPz4vZywgJycpO1xyXG4gICAgeG1sID0geG1sLnJlcGxhY2UoLzwhLS1bXFxzXFxTXSo/LS0+L2csICcnKTtcclxuICAgIHhtbCA9IHhtbC50cmltKCk7XHJcblxyXG4gICAgY29uc3Qgc3RhY2s6IGFueVtdID0gW107XHJcbiAgICBjb25zdCByZXN1bHQ6IGFueSA9IHt9O1xyXG4gICAgbGV0IGN1cnJlbnQgPSByZXN1bHQ7XHJcbiAgICBsZXQgaXNSb290TGV2ZWwgPSB0cnVlO1xyXG5cclxuICAgIC8vIFNpbXBsZSByZWdleCB0byBtYXRjaCBYTUwgdGFncyBhbmQgY29udGVudFxyXG4gICAgY29uc3QgdGFnUmVnZXggPSAvPFxcLz8oW14+XFxzXSspKFtePl0qKT4vZztcclxuICAgIGxldCBsYXN0SW5kZXggPSAwO1xyXG4gICAgbGV0IG1hdGNoO1xyXG5cclxuICAgIHdoaWxlICgobWF0Y2ggPSB0YWdSZWdleC5leGVjKHhtbCkpICE9PSBudWxsKSB7XHJcbiAgICAgIGNvbnN0IFtmdWxsTWF0Y2gsIHRhZ05hbWUsIGF0dHJpYnV0ZXNTdHJdID0gbWF0Y2g7XHJcbiAgICAgIGNvbnN0IGlzQ2xvc2luZyA9IGZ1bGxNYXRjaC5zdGFydHNXaXRoKCc8LycpO1xyXG4gICAgICBjb25zdCBpc1NlbGZDbG9zaW5nID0gZnVsbE1hdGNoLmVuZHNXaXRoKCcvPicpO1xyXG5cclxuICAgICAgLy8gSGFuZGxlIHRleHQgY29udGVudCBiZWZvcmUgdGhpcyB0YWdcclxuICAgICAgaWYgKG1hdGNoLmluZGV4ID4gbGFzdEluZGV4KSB7XHJcbiAgICAgICAgY29uc3QgdGV4dENvbnRlbnQgPSB4bWwuc3Vic3RyaW5nKGxhc3RJbmRleCwgbWF0Y2guaW5kZXgpO1xyXG4gICAgICAgIGlmICh0ZXh0Q29udGVudC50cmltKCkpIHtcclxuICAgICAgICAgIHRoaXMuYWRkVGV4dENvbnRlbnQoY3VycmVudCwgdGV4dENvbnRlbnQpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgaWYgKGlzQ2xvc2luZykge1xyXG4gICAgICAgIC8vIENsb3NpbmcgdGFnIC0gcG9wIGZyb20gc3RhY2tcclxuICAgICAgICBpZiAoc3RhY2subGVuZ3RoID4gMCkge1xyXG4gICAgICAgICAgY3VycmVudCA9IHN0YWNrLnBvcCgpO1xyXG4gICAgICAgICAgaWYgKHN0YWNrLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICBpc1Jvb3RMZXZlbCA9IHRydWU7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIC8vIE9wZW5pbmcgdGFnIG9yIHNlbGYtY2xvc2luZyB0YWdcclxuICAgICAgICBjb25zdCBlbGVtZW50OiBhbnkgPSB7fTtcclxuXHJcbiAgICAgICAgLy8gUGFyc2UgYXR0cmlidXRlc1xyXG4gICAgICAgIGlmIChhdHRyaWJ1dGVzU3RyKSB7XHJcbiAgICAgICAgICBpZiAoIXRoaXMub3B0aW9ucy5pZ25vcmVBdHRycyAmJiBhdHRyaWJ1dGVzU3RyLnRyaW0oKSkge1xyXG4gICAgICAgICAgICBjb25zdCBhdHRycyA9IHRoaXMucGFyc2VBdHRyaWJ1dGVzKGF0dHJpYnV0ZXNTdHIpO1xyXG4gICAgICAgICAgICBpZiAoT2JqZWN0LmtleXMoYXR0cnMpLmxlbmd0aCA+IDApIHtcclxuICAgICAgICAgICAgICBpZiAodGhpcy5vcHRpb25zLm1lcmdlQXR0cnMpIHtcclxuICAgICAgICAgICAgICAgIE9iamVjdC5hc3NpZ24oZWxlbWVudCwgYXR0cnMpO1xyXG4gICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBlbGVtZW50LiQgPSBhdHRycztcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIEFkZCBlbGVtZW50IHRvIGN1cnJlbnQgcGFyZW50IChkb24ndCBmb3JjZSBhcnJheSBmb3Igcm9vdCBsZXZlbClcclxuICAgICAgICBpZiAodGFnTmFtZSlcclxuICAgICAgICAgIHRoaXMuYWRkQ2hpbGRFbGVtZW50KGN1cnJlbnQsIHRhZ05hbWUsIGVsZW1lbnQsIGlzUm9vdExldmVsKTtcclxuXHJcbiAgICAgICAgLy8gSWYgbm90IHNlbGYtY2xvc2luZywgcHVzaCB0byBzdGFjayBmb3IgY2hpbGRyZW5cclxuICAgICAgICBpZiAoIWlzU2VsZkNsb3NpbmcpIHtcclxuICAgICAgICAgIHN0YWNrLnB1c2goY3VycmVudCk7XHJcbiAgICAgICAgICBjdXJyZW50ID0gZWxlbWVudDtcclxuICAgICAgICAgIGlzUm9vdExldmVsID0gZmFsc2U7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICBsYXN0SW5kZXggPSB0YWdSZWdleC5sYXN0SW5kZXg7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gSGFuZGxlIGFueSByZW1haW5pbmcgdGV4dCBjb250ZW50XHJcbiAgICBpZiAobGFzdEluZGV4IDwgeG1sLmxlbmd0aCkge1xyXG4gICAgICBjb25zdCB0ZXh0Q29udGVudCA9IHhtbC5zdWJzdHJpbmcobGFzdEluZGV4KTtcclxuICAgICAgaWYgKHRleHRDb250ZW50LnRyaW0oKSkge1xyXG4gICAgICAgIHRoaXMuYWRkVGV4dENvbnRlbnQoY3VycmVudCwgdGV4dENvbnRlbnQpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy8gUmV0dXJuIHRoZSByb290IGVsZW1lbnRcclxuICAgIGNvbnN0IHJvb3RLZXlzID0gT2JqZWN0LmtleXMocmVzdWx0KTtcclxuICAgIGlmIChyb290S2V5cy5sZW5ndGggPT09IDEgJiYgdGhpcy5vcHRpb25zLmV4cGxpY2l0Um9vdCkge1xyXG4gICAgICByZXR1cm4gcmVzdWx0O1xyXG4gICAgfSBlbHNlIGlmIChyb290S2V5cy5sZW5ndGggPT09IDEpIHtcclxuICAgICAgcmV0dXJuIHJlc3VsdFtyb290S2V5c1swXSFdO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgcmV0dXJuIHJlc3VsdDtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIENvbnZlcnQgRE9NIGVsZW1lbnQgdG8gSmF2YVNjcmlwdCBvYmplY3QgKGZvciBicm93c2VyKVxyXG4gICAqL1xyXG4gIHByaXZhdGUgZG9tRWxlbWVudFRvSnMoZWxlbWVudDogYW55LCBpc1Jvb3RMZXZlbDogYm9vbGVhbiA9IGZhbHNlKTogYW55IHtcclxuICAgIGNvbnN0IHJlc3VsdDogYW55ID0ge307XHJcblxyXG4gICAgLy8gSGFuZGxlIGF0dHJpYnV0ZXNcclxuICAgIGlmIChcclxuICAgICAgIXRoaXMub3B0aW9ucy5pZ25vcmVBdHRycyAmJlxyXG4gICAgICBlbGVtZW50LmF0dHJpYnV0ZXMgJiZcclxuICAgICAgZWxlbWVudC5hdHRyaWJ1dGVzLmxlbmd0aCA+IDBcclxuICAgICkge1xyXG4gICAgICBjb25zdCBhdHRyczogYW55ID0ge307XHJcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZWxlbWVudC5hdHRyaWJ1dGVzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgY29uc3QgYXR0ciA9IGVsZW1lbnQuYXR0cmlidXRlc1tpXTtcclxuICAgICAgICBhdHRyc1thdHRyLm5hbWVdID0gYXR0ci52YWx1ZTtcclxuICAgICAgfVxyXG5cclxuICAgICAgaWYgKHRoaXMub3B0aW9ucy5tZXJnZUF0dHJzKSB7XHJcbiAgICAgICAgT2JqZWN0LmFzc2lnbihyZXN1bHQsIGF0dHJzKTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICByZXN1bHQuJCA9IGF0dHJzO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy8gR3JvdXAgY2hpbGQgZWxlbWVudHMgYnkgdGFnIG5hbWVcclxuICAgIGNvbnN0IGNoaWxkRWxlbWVudHM6IHsgW2tleTogc3RyaW5nXTogYW55W10gfSA9IHt9O1xyXG4gICAgY29uc3QgdGV4dFBhcnRzOiBzdHJpbmdbXSA9IFtdO1xyXG5cclxuICAgIC8vIFByb2Nlc3MgYWxsIGNoaWxkIG5vZGVzXHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGVsZW1lbnQuY2hpbGROb2Rlcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICBjb25zdCBjaGlsZCA9IGVsZW1lbnQuY2hpbGROb2Rlc1tpXTtcclxuXHJcbiAgICAgIGlmIChjaGlsZC5ub2RlVHlwZSA9PT0gTk9ERV9UWVBFUy5FTEVNRU5UX05PREUpIHtcclxuICAgICAgICBjb25zdCBjaGlsZEVsZW1lbnQgPSBjaGlsZDtcclxuICAgICAgICBjb25zdCB0YWdOYW1lID0gY2hpbGRFbGVtZW50LnRhZ05hbWU7XHJcblxyXG4gICAgICAgIGlmICghY2hpbGRFbGVtZW50c1t0YWdOYW1lXSkge1xyXG4gICAgICAgICAgY2hpbGRFbGVtZW50c1t0YWdOYW1lXSA9IFtdO1xyXG4gICAgICAgIH1cclxuICAgICAgICBjaGlsZEVsZW1lbnRzW3RhZ05hbWVdLnB1c2goY2hpbGRFbGVtZW50KTtcclxuICAgICAgfSBlbHNlIGlmIChcclxuICAgICAgICBjaGlsZC5ub2RlVHlwZSA9PT0gTk9ERV9UWVBFUy5URVhUX05PREUgfHxcclxuICAgICAgICBjaGlsZC5ub2RlVHlwZSA9PT0gTk9ERV9UWVBFUy5DREFUQV9TRUNUSU9OX05PREVcclxuICAgICAgKSB7XHJcbiAgICAgICAgY29uc3QgdGV4dENvbnRlbnQgPSBjaGlsZC50ZXh0Q29udGVudCB8fCAnJztcclxuICAgICAgICBpZiAodGV4dENvbnRlbnQudHJpbSgpKSB7XHJcbiAgICAgICAgICB0ZXh0UGFydHMucHVzaCh0ZXh0Q29udGVudCk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy8gQWRkIGNoaWxkIGVsZW1lbnRzIHRvIHJlc3VsdFxyXG4gICAgZm9yIChjb25zdCBbdGFnTmFtZSwgZWxlbWVudHNdIG9mIE9iamVjdC5lbnRyaWVzKGNoaWxkRWxlbWVudHMpKSB7XHJcbiAgICAgIGNvbnN0IGNoaWxkT2JqZWN0cyA9IGVsZW1lbnRzLm1hcCgoZWwpID0+IHRoaXMuZG9tRWxlbWVudFRvSnMoZWwsIGZhbHNlKSk7IC8vIGNoaWxkcmVuIGFyZSBub3Qgcm9vdCBsZXZlbFxyXG5cclxuICAgICAgLy8gVXNlIHRoZSBoZWxwZXIgbWV0aG9kIHRvIG1haW50YWluIGNvbnNpc3RlbmN5IHdpdGggTm9kZS5qcyBpbXBsZW1lbnRhdGlvblxyXG4gICAgICBpZiAoZWxlbWVudHMubGVuZ3RoID09PSAxKSB7XHJcbiAgICAgICAgdGhpcy5hZGRDaGlsZEVsZW1lbnQocmVzdWx0LCB0YWdOYW1lLCBjaGlsZE9iamVjdHNbMF0sIGZhbHNlKTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICAvLyBNdWx0aXBsZSBlbGVtZW50cyB3aXRoIHNhbWUgdGFnIG5hbWUgYWx3YXlzIGJlY29tZSBhcnJheXNcclxuICAgICAgICByZXN1bHRbdGFnTmFtZV0gPSBjaGlsZE9iamVjdHM7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvLyBIYW5kbGUgdGV4dCBjb250ZW50XHJcbiAgICBpZiAodGV4dFBhcnRzLmxlbmd0aCA+IDAgJiYgT2JqZWN0LmtleXMoY2hpbGRFbGVtZW50cykubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgIGNvbnN0IHRleHRDb250ZW50ID0gdGV4dFBhcnRzLmpvaW4oJycpO1xyXG4gICAgICBjb25zdCBmaW5hbFRleHQgPSB0aGlzLm9wdGlvbnMudHJpbSA/IHRleHRDb250ZW50LnRyaW0oKSA6IHRleHRDb250ZW50O1xyXG4gICAgICBpZiAodGhpcy5vcHRpb25zLm5vcm1hbGl6ZSkge1xyXG4gICAgICAgIHJlc3VsdC5fID0gZmluYWxUZXh0LnJlcGxhY2UoL1xccysvZywgJyAnKTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICByZXN1bHQuXyA9IGZpbmFsVGV4dDtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiByZXN1bHQ7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBQYXJzZSBhdHRyaWJ1dGUgc3RyaW5nIGludG8gb2JqZWN0XHJcbiAgICovXHJcbiAgcHJpdmF0ZSBwYXJzZUF0dHJpYnV0ZXMoYXR0cmlidXRlc1N0cjogc3RyaW5nKTogYW55IHtcclxuICAgIGNvbnN0IGF0dHJzOiBhbnkgPSB7fTtcclxuICAgIGNvbnN0IGF0dHJSZWdleCA9IC8oXFxTKyk9W1wiJ10oW15cIiddKilbXCInXS9nO1xyXG4gICAgbGV0IG1hdGNoO1xyXG5cclxuICAgIHdoaWxlICgobWF0Y2ggPSBhdHRyUmVnZXguZXhlYyhhdHRyaWJ1dGVzU3RyKSkgIT09IG51bGwpIHtcclxuICAgICAgY29uc3QgWywgbmFtZSwgdmFsdWVdID0gbWF0Y2g7XHJcbiAgICAgIGlmKG5hbWUpXHJcbiAgICAgICAgYXR0cnNbbmFtZV0gPSB2YWx1ZTtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gYXR0cnM7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBBZGQgdGV4dCBjb250ZW50IHRvIGN1cnJlbnQgZWxlbWVudFxyXG4gICAqL1xyXG4gIHByaXZhdGUgYWRkVGV4dENvbnRlbnQoY3VycmVudDogYW55LCB0ZXh0Q29udGVudDogc3RyaW5nKTogdm9pZCB7XHJcbiAgICBjb25zdCB0cmltbWVkID0gdGV4dENvbnRlbnQudHJpbSgpO1xyXG4gICAgaWYgKHRyaW1tZWQpIHtcclxuICAgICAgY29uc3QgZmluYWxUZXh0ID0gdGhpcy5vcHRpb25zLnRyaW0gPyB0cmltbWVkIDogdGV4dENvbnRlbnQ7XHJcbiAgICAgIGNvbnN0IG5vcm1hbGl6ZWRUZXh0ID0gdGhpcy5vcHRpb25zLm5vcm1hbGl6ZVxyXG4gICAgICAgID8gZmluYWxUZXh0LnJlcGxhY2UoL1xccysvZywgJyAnKVxyXG4gICAgICAgIDogZmluYWxUZXh0O1xyXG5cclxuICAgICAgaWYgKGN1cnJlbnQuXykge1xyXG4gICAgICAgIGN1cnJlbnQuXyArPSBub3JtYWxpemVkVGV4dDtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBjdXJyZW50Ll8gPSBub3JtYWxpemVkVGV4dDtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQWRkIGNoaWxkIGVsZW1lbnQgdG8gcGFyZW50XHJcbiAgICovXHJcbiAgcHJpdmF0ZSBhZGRDaGlsZEVsZW1lbnQoXHJcbiAgICBwYXJlbnQ6IGFueSxcclxuICAgIHRhZ05hbWU6IHN0cmluZyxcclxuICAgIGVsZW1lbnQ6IGFueSxcclxuICAgIGlzUm9vdExldmVsOiBib29sZWFuID0gZmFsc2VcclxuICApOiB2b2lkIHtcclxuICAgIGlmIChwYXJlbnRbdGFnTmFtZV0pIHtcclxuICAgICAgLy8gQ29udmVydCB0byBhcnJheSBpZiBub3QgYWxyZWFkeVxyXG4gICAgICBpZiAoIUFycmF5LmlzQXJyYXkocGFyZW50W3RhZ05hbWVdKSkge1xyXG4gICAgICAgIHBhcmVudFt0YWdOYW1lXSA9IFtwYXJlbnRbdGFnTmFtZV1dO1xyXG4gICAgICB9XHJcbiAgICAgIHBhcmVudFt0YWdOYW1lXS5wdXNoKGVsZW1lbnQpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgLy8gRm9yIHJvb3QgbGV2ZWwgZWxlbWVudHMsIGRvbid0IGZvcmNlIGFycmF5IGV2ZW4gaWYgZXhwbGljaXRBcnJheSBpcyB0cnVlXHJcbiAgICAgIC8vIHhtbDJqcyBvbmx5IHVzZXMgYXJyYXlzIGZvciBjaGlsZCBlbGVtZW50cywgbm90IHRoZSByb290IGVsZW1lbnRcclxuICAgICAgaWYgKHRoaXMub3B0aW9ucy5leHBsaWNpdEFycmF5ICYmICFpc1Jvb3RMZXZlbCkge1xyXG4gICAgICAgIHBhcmVudFt0YWdOYW1lXSA9IFtlbGVtZW50XTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBwYXJlbnRbdGFnTmFtZV0gPSBlbGVtZW50O1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcblxyXG4vLyBEZWZhdWx0IGluc3RhbmNlIHdpdGggeG1sMmpzLWNvbXBhdGlibGUgZGVmYXVsdHNcclxuY29uc3QgZGVmYXVsdFBhcnNlciA9IG5ldyBYbWxUb0pzUGFyc2VyKHtcclxuICBleHBsaWNpdEFycmF5OiB0cnVlLFxyXG4gIG1lcmdlQXR0cnM6IGZhbHNlLFxyXG4gIGV4cGxpY2l0Um9vdDogdHJ1ZSxcclxuICBpZ25vcmVBdHRyczogZmFsc2UsXHJcbiAgdHJpbTogZmFsc2UsXHJcbiAgbm9ybWFsaXplOiBmYWxzZSxcclxufSk7XHJcblxyXG4vKipcclxuICogRHJvcC1pbiByZXBsYWNlbWVudCBmb3IgeG1sMmpzLnBhcnNlU3RyaW5nKClcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBwYXJzZVN0cmluZyhcclxuICB4bWw6IHN0cmluZyxcclxuICBjYWxsYmFjaz86IChlcnI6IEVycm9yIHwgbnVsbCwgcmVzdWx0PzogYW55KSA9PiB2b2lkXHJcbik6IFByb21pc2U8YW55PiB7XHJcbiAgaWYgKGNhbGxiYWNrKSB7XHJcbiAgICBkZWZhdWx0UGFyc2VyXHJcbiAgICAgIC5wYXJzZVN0cmluZyh4bWwpXHJcbiAgICAgIC50aGVuKChyZXN1bHQpID0+IGNhbGxiYWNrKG51bGwsIHJlc3VsdCkpXHJcbiAgICAgIC5jYXRjaCgoZXJyKSA9PiBjYWxsYmFjayhlcnIpKTtcclxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcclxuICB9IGVsc2Uge1xyXG4gICAgcmV0dXJuIGRlZmF1bHRQYXJzZXIucGFyc2VTdHJpbmcoeG1sKTtcclxuICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBTeW5jaHJvbm91cyB2ZXJzaW9uXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VTdHJpbmdTeW5jKHhtbDogc3RyaW5nKTogYW55IHtcclxuICByZXR1cm4gZGVmYXVsdFBhcnNlci5wYXJzZVN0cmluZ1N5bmMoeG1sKTtcclxufVxyXG4iXX0=