react-scripts
Version:
Configuration and scripts for Create React App.
669 lines (568 loc) • 55.2 kB
JavaScript
'use strict';
exports.__esModule = true;
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };
var _cssSyntaxError = require('./css-syntax-error');
var _cssSyntaxError2 = _interopRequireDefault(_cssSyntaxError);
var _stringifier = require('./stringifier');
var _stringifier2 = _interopRequireDefault(_stringifier);
var _stringify = require('./stringify');
var _stringify2 = _interopRequireDefault(_stringify);
var _warnOnce = require('./warn-once');
var _warnOnce2 = _interopRequireDefault(_warnOnce);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* @typedef {object} position
* @property {number} line - source line in file
* @property {number} column - source column in file
*/
/**
* @typedef {object} source
* @property {Input} input - {@link Input} with input file
* @property {position} start - The starting position of the node’s source
* @property {position} end - The ending position of the node’s source
*/
var cloneNode = function cloneNode(obj, parent) {
var cloned = new obj.constructor();
for (var i in obj) {
if (!obj.hasOwnProperty(i)) continue;
var value = obj[i];
var type = typeof value === 'undefined' ? 'undefined' : _typeof(value);
if (i === 'parent' && type === 'object') {
if (parent) cloned[i] = parent;
} else if (i === 'source') {
cloned[i] = value;
} else if (value instanceof Array) {
cloned[i] = value.map(function (j) {
return cloneNode(j, cloned);
});
} else if (i !== 'before' && i !== 'after' && i !== 'between' && i !== 'semicolon') {
if (type === 'object' && value !== null) value = cloneNode(value);
cloned[i] = value;
}
}
return cloned;
};
/**
* All node classes inherit the following common methods.
*
* @abstract
* @ignore
*/
var Node = function () {
/**
* @param {object} [defaults] - value for node properties
*/
function Node() {
var defaults = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
_classCallCheck(this, Node);
this.raws = {};
for (var name in defaults) {
this[name] = defaults[name];
}
}
/**
* Returns a CssSyntaxError instance containing the original position
* of the node in the source, showing line and column numbers and also
* a small excerpt to facilitate debugging.
*
* If present, an input source map will be used to get the original position
* of the source, even from a previous compilation step
* (e.g., from Sass compilation).
*
* This method produces very useful error messages.
*
* @param {string} message - error description
* @param {object} [opts] - options
* @param {string} opts.plugin - plugin name that created this error.
* PostCSS will set it automatically.
* @param {string} opts.word - a word inside a node’s string that should
* be highlighted as the source of the error
* @param {number} opts.index - an index inside a node’s string that should
* be highlighted as the source of the error
*
* @return {CssSyntaxError} error object to throw it
*
* @example
* if ( !variables[name] ) {
* throw decl.error('Unknown variable ' + name, { word: name });
* // CssSyntaxError: postcss-vars:a.sass:4:3: Unknown variable $black
* // color: $black
* // a
* // ^
* // background: white
* }
*/
Node.prototype.error = function error(message) {
var opts = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
if (this.source) {
var pos = this.positionBy(opts);
return this.source.input.error(message, pos.line, pos.column, opts);
} else {
return new _cssSyntaxError2.default(message);
}
};
/**
* This method is provided as a convenience wrapper for {@link Result#warn}.
*
* @param {Result} result - the {@link Result} instance
* that will receive the warning
* @param {string} text - warning message
* @param {object} [opts] - options
* @param {string} opts.plugin - plugin name that created this warning.
* PostCSS will set it automatically.
* @param {string} opts.word - a word inside a node’s string that should
* be highlighted as the source of the warning
* @param {number} opts.index - an index inside a node’s string that should
* be highlighted as the source of the warning
*
* @return {Warning} created warning object
*
* @example
* const plugin = postcss.plugin('postcss-deprecated', () => {
* return (css, result) => {
* css.walkDecls('bad', decl => {
* decl.warn(result, 'Deprecated property bad');
* });
* };
* });
*/
Node.prototype.warn = function warn(result, text, opts) {
var data = { node: this };
for (var i in opts) {
data[i] = opts[i];
}return result.warn(text, data);
};
/**
* Removes the node from its parent and cleans the parent properties
* from the node and its children.
*
* @example
* if ( decl.prop.match(/^-webkit-/) ) {
* decl.remove();
* }
*
* @return {Node} node to make calls chain
*/
Node.prototype.remove = function remove() {
if (this.parent) {
this.parent.removeChild(this);
}
this.parent = undefined;
return this;
};
/**
* Returns a CSS string representing the node.
*
* @param {stringifier|syntax} [stringifier] - a syntax to use
* in string generation
*
* @return {string} CSS string of this node
*
* @example
* postcss.rule({ selector: 'a' }).toString() //=> "a {}"
*/
Node.prototype.toString = function toString() {
var stringifier = arguments.length <= 0 || arguments[0] === undefined ? _stringify2.default : arguments[0];
if (stringifier.stringify) stringifier = stringifier.stringify;
var result = '';
stringifier(this, function (i) {
result += i;
});
return result;
};
/**
* Returns a clone of the node.
*
* The resulting cloned node and its (cloned) children will have
* a clean parent and code style properties.
*
* @param {object} [overrides] - new properties to override in the clone.
*
* @example
* const cloned = decl.clone({ prop: '-moz-' + decl.prop });
* cloned.raws.before //=> undefined
* cloned.parent //=> undefined
* cloned.toString() //=> -moz-transform: scale(0)
*
* @return {Node} clone of the node
*/
Node.prototype.clone = function clone() {
var overrides = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
var cloned = cloneNode(this);
for (var name in overrides) {
cloned[name] = overrides[name];
}
return cloned;
};
/**
* Shortcut to clone the node and insert the resulting cloned node
* before the current node.
*
* @param {object} [overrides] - new properties to override in the clone.
*
* @example
* decl.cloneBefore({ prop: '-moz-' + decl.prop });
*
* @return {Node} - new node
*/
Node.prototype.cloneBefore = function cloneBefore() {
var overrides = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
var cloned = this.clone(overrides);
this.parent.insertBefore(this, cloned);
return cloned;
};
/**
* Shortcut to clone the node and insert the resulting cloned node
* after the current node.
*
* @param {object} [overrides] - new properties to override in the clone.
*
* @return {Node} - new node
*/
Node.prototype.cloneAfter = function cloneAfter() {
var overrides = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
var cloned = this.clone(overrides);
this.parent.insertAfter(this, cloned);
return cloned;
};
/**
* Inserts node(s) before the current node and removes the current node.
*
* @param {...Node} nodes - node(s) to replace current one
*
* @example
* if ( atrule.name == 'mixin' ) {
* atrule.replaceWith(mixinRules[atrule.params]);
* }
*
* @return {Node} current node to methods chain
*/
Node.prototype.replaceWith = function replaceWith() {
if (this.parent) {
for (var _len = arguments.length, nodes = Array(_len), _key = 0; _key < _len; _key++) {
nodes[_key] = arguments[_key];
}
for (var _iterator = nodes, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
var _ref;
if (_isArray) {
if (_i >= _iterator.length) break;
_ref = _iterator[_i++];
} else {
_i = _iterator.next();
if (_i.done) break;
_ref = _i.value;
}
var node = _ref;
this.parent.insertBefore(this, node);
}
this.remove();
}
return this;
};
/**
* Removes the node from its current parent and inserts it
* at the end of `newParent`.
*
* This will clean the `before` and `after` code {@link Node#raws} data
* from the node and replace them with the indentation style of `newParent`.
* It will also clean the `between` property
* if `newParent` is in another {@link Root}.
*
* @param {Container} newParent - container node where the current node
* will be moved
*
* @example
* atrule.moveTo(atrule.root());
*
* @return {Node} current node to methods chain
*/
Node.prototype.moveTo = function moveTo(newParent) {
this.cleanRaws(this.root() === newParent.root());
this.remove();
newParent.append(this);
return this;
};
/**
* Removes the node from its current parent and inserts it into
* a new parent before `otherNode`.
*
* This will also clean the node’s code style properties just as it would
* in {@link Node#moveTo}.
*
* @param {Node} otherNode - node that will be before current node
*
* @return {Node} current node to methods chain
*/
Node.prototype.moveBefore = function moveBefore(otherNode) {
this.cleanRaws(this.root() === otherNode.root());
this.remove();
otherNode.parent.insertBefore(otherNode, this);
return this;
};
/**
* Removes the node from its current parent and inserts it into
* a new parent after `otherNode`.
*
* This will also clean the node’s code style properties just as it would
* in {@link Node#moveTo}.
*
* @param {Node} otherNode - node that will be after current node
*
* @return {Node} current node to methods chain
*/
Node.prototype.moveAfter = function moveAfter(otherNode) {
this.cleanRaws(this.root() === otherNode.root());
this.remove();
otherNode.parent.insertAfter(otherNode, this);
return this;
};
/**
* Returns the next child of the node’s parent.
* Returns `undefined` if the current node is the last child.
*
* @return {Node|undefined} next node
*
* @example
* if ( comment.text === 'delete next' ) {
* const next = comment.next();
* if ( next ) {
* next.remove();
* }
* }
*/
Node.prototype.next = function next() {
var index = this.parent.index(this);
return this.parent.nodes[index + 1];
};
/**
* Returns the previous child of the node’s parent.
* Returns `undefined` if the current node is the first child.
*
* @return {Node|undefined} previous node
*
* @example
* const annotation = decl.prev();
* if ( annotation.type == 'comment' ) {
* readAnnotation(annotation.text);
* }
*/
Node.prototype.prev = function prev() {
var index = this.parent.index(this);
return this.parent.nodes[index - 1];
};
Node.prototype.toJSON = function toJSON() {
var fixed = {};
for (var name in this) {
if (!this.hasOwnProperty(name)) continue;
if (name === 'parent') continue;
var value = this[name];
if (value instanceof Array) {
fixed[name] = value.map(function (i) {
if ((typeof i === 'undefined' ? 'undefined' : _typeof(i)) === 'object' && i.toJSON) {
return i.toJSON();
} else {
return i;
}
});
} else if ((typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object' && value.toJSON) {
fixed[name] = value.toJSON();
} else {
fixed[name] = value;
}
}
return fixed;
};
/**
* Returns a {@link Node#raws} value. If the node is missing
* the code style property (because the node was manually built or cloned),
* PostCSS will try to autodetect the code style property by looking
* at other nodes in the tree.
*
* @param {string} prop - name of code style property
* @param {string} [defaultType] - name of default value, it can be missed
* if the value is the same as prop
*
* @example
* const root = postcss.parse('a { background: white }');
* root.nodes[0].append({ prop: 'color', value: 'black' });
* root.nodes[0].nodes[1].raws.before //=> undefined
* root.nodes[0].nodes[1].raw('before') //=> ' '
*
* @return {string} code style value
*/
Node.prototype.raw = function raw(prop, defaultType) {
var str = new _stringifier2.default();
return str.raw(this, prop, defaultType);
};
/**
* Finds the Root instance of the node’s tree.
*
* @example
* root.nodes[0].nodes[0].root() === root
*
* @return {Root} root parent
*/
Node.prototype.root = function root() {
var result = this;
while (result.parent) {
result = result.parent;
}return result;
};
Node.prototype.cleanRaws = function cleanRaws(keepBetween) {
delete this.raws.before;
delete this.raws.after;
if (!keepBetween) delete this.raws.between;
};
Node.prototype.positionInside = function positionInside(index) {
var string = this.toString();
var column = this.source.start.column;
var line = this.source.start.line;
for (var i = 0; i < index; i++) {
if (string[i] === '\n') {
column = 1;
line += 1;
} else {
column += 1;
}
}
return { line: line, column: column };
};
Node.prototype.positionBy = function positionBy(opts) {
var pos = this.source.start;
if (opts.index) {
pos = this.positionInside(opts.index);
} else if (opts.word) {
var index = this.toString().indexOf(opts.word);
if (index !== -1) pos = this.positionInside(index);
}
return pos;
};
Node.prototype.removeSelf = function removeSelf() {
(0, _warnOnce2.default)('Node#removeSelf is deprecated. Use Node#remove.');
return this.remove();
};
Node.prototype.replace = function replace(nodes) {
(0, _warnOnce2.default)('Node#replace is deprecated. Use Node#replaceWith');
return this.replaceWith(nodes);
};
Node.prototype.style = function style(own, detect) {
(0, _warnOnce2.default)('Node#style() is deprecated. Use Node#raw()');
return this.raw(own, detect);
};
Node.prototype.cleanStyles = function cleanStyles(keepBetween) {
(0, _warnOnce2.default)('Node#cleanStyles() is deprecated. Use Node#cleanRaws()');
return this.cleanRaws(keepBetween);
};
_createClass(Node, [{
key: 'before',
get: function get() {
(0, _warnOnce2.default)('Node#before is deprecated. Use Node#raws.before');
return this.raws.before;
},
set: function set(val) {
(0, _warnOnce2.default)('Node#before is deprecated. Use Node#raws.before');
this.raws.before = val;
}
}, {
key: 'between',
get: function get() {
(0, _warnOnce2.default)('Node#between is deprecated. Use Node#raws.between');
return this.raws.between;
},
set: function set(val) {
(0, _warnOnce2.default)('Node#between is deprecated. Use Node#raws.between');
this.raws.between = val;
}
/**
* @memberof Node#
* @member {string} type - String representing the node’s type.
* Possible values are `root`, `atrule`, `rule`,
* `decl`, or `comment`.
*
* @example
* postcss.decl({ prop: 'color', value: 'black' }).type //=> 'decl'
*/
/**
* @memberof Node#
* @member {Container} parent - the node’s parent node.
*
* @example
* root.nodes[0].parent == root;
*/
/**
* @memberof Node#
* @member {source} source - the input source of the node
*
* The property is used in source map generation.
*
* If you create a node manually (e.g., with `postcss.decl()`),
* that node will not have a `source` property and will be absent
* from the source map. For this reason, the plugin developer should
* consider cloning nodes to create new ones (in which case the new node’s
* source will reference the original, cloned node) or setting
* the `source` property manually.
*
* ```js
* // Bad
* const prefixed = postcss.decl({
* prop: '-moz-' + decl.prop,
* value: decl.value
* });
*
* // Good
* const prefixed = decl.clone({ prop: '-moz-' + decl.prop });
* ```
*
* ```js
* if ( atrule.name == 'add-link' ) {
* const rule = postcss.rule({ selector: 'a', source: atrule.source });
* atrule.parent.insertBefore(atrule, rule);
* }
* ```
*
* @example
* decl.source.input.from //=> '/home/ai/a.sass'
* decl.source.start //=> { line: 10, column: 2 }
* decl.source.end //=> { line: 10, column: 12 }
*/
/**
* @memberof Node#
* @member {object} raws - Information to generate byte-to-byte equal
* node string as it was in the origin input.
*
* Every parser saves its own properties,
* but the default CSS parser uses:
*
* * `before`: the space symbols before the node. It also stores `*`
* and `_` symbols before the declaration (IE hack).
* * `after`: the space symbols after the last child of the node
* to the end of the node.
* * `between`: the symbols between the property and value
* for declarations, selector and `{` for rules, or last parameter
* and `{` for at-rules.
* * `semicolon`: contains true if the last child has
* an (optional) semicolon.
* * `afterName`: the space between the at-rule name and its parameters.
* * `left`: the space symbols between `/*` and the comment’s text.
* * `right`: the space symbols between the comment’s text
* and <code>*/</code>.
* * `important`: the content of the important statement,
* if it is not just `!important`.
*
* PostCSS cleans selectors, declaration values and at-rule parameters
* from comments and extra spaces, but it stores origin content in raws
* properties. As such, if you don’t change a declaration’s value,
* PostCSS will use the raw value with comments.
*
* @example
* const root = postcss.parse('a {\n color:black\n}')
* root.first.first.raws //=> { before: '\n ', between: ':' }
*/
}]);
return Node;
}();
exports.default = Node;
module.exports = exports['default'];
//# sourceMappingURL=data:application/json;base64,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O21CQUVELEssa0JBQU0sRyxFQUFLLE0sRUFBUTtBQUNmLGdDQUFTLDRDQUFUO0FBQ0EsZUFBTyxLQUFLLEdBQUwsQ0FBUyxHQUFULEVBQWMsTUFBZCxDQUFQO0FBQ0gsSzs7bUJBRUQsVyx3QkFBWSxXLEVBQWE7QUFDckIsZ0NBQVMsd0RBQVQ7QUFDQSxlQUFPLEtBQUssU0FBTCxDQUFlLFdBQWYsQ0FBUDtBQUNILEs7Ozs7NEJBRVk7QUFDVCxvQ0FBUyxpREFBVDtBQUNBLG1CQUFPLEtBQUssSUFBTCxDQUFVLE1BQWpCO0FBQ0gsUzswQkFFVSxHLEVBQUs7QUFDWixvQ0FBUyxpREFBVDtBQUNBLGlCQUFLLElBQUwsQ0FBVSxNQUFWLEdBQW1CLEdBQW5CO0FBQ0g7Ozs0QkFFYTtBQUNWLG9DQUFTLG1EQUFUO0FBQ0EsbUJBQU8sS0FBSyxJQUFMLENBQVUsT0FBakI7QUFDSCxTOzBCQUVXLEcsRUFBSztBQUNiLG9DQUFTLG1EQUFUO0FBQ0EsaUJBQUssSUFBTCxDQUFVLE9BQVYsR0FBb0IsR0FBcEI7QUFDSDs7QUFFRDs7Ozs7Ozs7OztBQVVBOzs7Ozs7OztBQVFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBcUNBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7a0JBb0NXLEkiLCJmaWxlIjoibm9kZS5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBDc3NTeW50YXhFcnJvciBmcm9tICcuL2Nzcy1zeW50YXgtZXJyb3InO1xuaW1wb3J0IFN0cmluZ2lmaWVyICAgIGZyb20gJy4vc3RyaW5naWZpZXInO1xuaW1wb3J0IHN0cmluZ2lmeSAgICAgIGZyb20gJy4vc3RyaW5naWZ5JztcbmltcG9ydCB3YXJuT25jZSAgICAgICBmcm9tICcuL3dhcm4tb25jZSc7XG5cbi8qKlxuICogQHR5cGVkZWYge29iamVjdH0gcG9zaXRpb25cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBsaW5lICAgLSBzb3VyY2UgbGluZSBpbiBmaWxlXG4gKiBAcHJvcGVydHkge251bWJlcn0gY29sdW1uIC0gc291cmNlIGNvbHVtbiBpbiBmaWxlXG4gKi9cblxuLyoqXG4gKiBAdHlwZWRlZiB7b2JqZWN0fSBzb3VyY2VcbiAqIEBwcm9wZXJ0eSB7SW5wdXR9IGlucHV0ICAgIC0ge0BsaW5rIElucHV0fSB3aXRoIGlucHV0IGZpbGVcbiAqIEBwcm9wZXJ0eSB7cG9zaXRpb259IHN0YXJ0IC0gVGhlIHN0YXJ0aW5nIHBvc2l0aW9uIG9mIHRoZSBub2Rl4oCZcyBzb3VyY2VcbiAqIEBwcm9wZXJ0eSB7cG9zaXRpb259IGVuZCAgIC0gVGhlIGVuZGluZyBwb3NpdGlvbiBvZiB0aGUgbm9kZeKAmXMgc291cmNlXG4gKi9cblxubGV0IGNsb25lTm9kZSA9IGZ1bmN0aW9uIChvYmosIHBhcmVudCkge1xuICAgIGxldCBjbG9uZWQgPSBuZXcgb2JqLmNvbnN0cnVjdG9yKCk7XG5cbiAgICBmb3IgKCBsZXQgaSBpbiBvYmogKSB7XG4gICAgICAgIGlmICggIW9iai5oYXNPd25Qcm9wZXJ0eShpKSApIGNvbnRpbnVlO1xuICAgICAgICBsZXQgdmFsdWUgPSBvYmpbaV07XG4gICAgICAgIGxldCB0eXBlICA9IHR5cGVvZiB2YWx1ZTtcblxuICAgICAgICBpZiAoIGkgPT09ICdwYXJlbnQnICYmIHR5cGUgPT09ICdvYmplY3QnICkge1xuICAgICAgICAgICAgaWYgKHBhcmVudCkgY2xvbmVkW2ldID0gcGFyZW50O1xuICAgICAgICB9IGVsc2UgaWYgKCBpID09PSAnc291cmNlJyApIHtcbiAgICAgICAgICAgIGNsb25lZFtpXSA9IHZhbHVlO1xuICAgICAgICB9IGVsc2UgaWYgKCB2YWx1ZSBpbnN0YW5jZW9mIEFycmF5ICkge1xuICAgICAgICAgICAgY2xvbmVkW2ldID0gdmFsdWUubWFwKCBqID0+IGNsb25lTm9kZShqLCBjbG9uZWQpICk7XG4gICAgICAgIH0gZWxzZSBpZiAoIGkgIT09ICdiZWZvcmUnICAmJiBpICE9PSAnYWZ0ZXInICYmXG4gICAgICAgICAgICAgICAgICAgIGkgIT09ICdiZXR3ZWVuJyAmJiBpICE9PSAnc2VtaWNvbG9uJyApIHtcbiAgICAgICAgICAgIGlmICggdHlwZSA9PT0gJ29iamVjdCcgJiYgdmFsdWUgIT09IG51bGwgKSB2YWx1ZSA9IGNsb25lTm9kZSh2YWx1ZSk7XG4gICAgICAgICAgICBjbG9uZWRbaV0gPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjbG9uZWQ7XG59O1xuXG4vKipcbiAqIEFsbCBub2RlIGNsYXNzZXMgaW5oZXJpdCB0aGUgZm9sbG93aW5nIGNvbW1vbiBtZXRob2RzLlxuICpcbiAqIEBhYnN0cmFjdFxuICogQGlnbm9yZVxuICovXG5jbGFzcyBOb2RlIHtcblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBbZGVmYXVsdHNdIC0gdmFsdWUgZm9yIG5vZGUgcHJvcGVydGllc1xuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGRlZmF1bHRzID0geyB9KSB7XG4gICAgICAgIHRoaXMucmF3cyA9IHsgfTtcbiAgICAgICAgZm9yICggbGV0IG5hbWUgaW4gZGVmYXVsdHMgKSB7XG4gICAgICAgICAgICB0aGlzW25hbWVdID0gZGVmYXVsdHNbbmFtZV07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGEgQ3NzU3ludGF4RXJyb3IgaW5zdGFuY2UgY29udGFpbmluZyB0aGUgb3JpZ2luYWwgcG9zaXRpb25cbiAgICAgKiBvZiB0aGUgbm9kZSBpbiB0aGUgc291cmNlLCBzaG93aW5nIGxpbmUgYW5kIGNvbHVtbiBudW1iZXJzIGFuZCBhbHNvXG4gICAgICogYSBzbWFsbCBleGNlcnB0IHRvIGZhY2lsaXRhdGUgZGVidWdnaW5nLlxuICAgICAqXG4gICAgICogSWYgcHJlc2VudCwgYW4gaW5wdXQgc291cmNlIG1hcCB3aWxsIGJlIHVzZWQgdG8gZ2V0IHRoZSBvcmlnaW5hbCBwb3NpdGlvblxuICAgICAqIG9mIHRoZSBzb3VyY2UsIGV2ZW4gZnJvbSBhIHByZXZpb3VzIGNvbXBpbGF0aW9uIHN0ZXBcbiAgICAgKiAoZS5nLiwgZnJvbSBTYXNzIGNvbXBpbGF0aW9uKS5cbiAgICAgKlxuICAgICAqIFRoaXMgbWV0aG9kIHByb2R1Y2VzIHZlcnkgdXNlZnVsIGVycm9yIG1lc3NhZ2VzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgICAgIC0gZXJyb3IgZGVzY3JpcHRpb25cbiAgICAgKiBAcGFyYW0ge29iamVjdH0gW29wdHNdICAgICAgLSBvcHRpb25zXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMucGx1Z2luIC0gcGx1Z2luIG5hbWUgdGhhdCBjcmVhdGVkIHRoaXMgZXJyb3IuXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUG9zdENTUyB3aWxsIHNldCBpdCBhdXRvbWF0aWNhbGx5LlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLndvcmQgICAtIGEgd29yZCBpbnNpZGUgYSBub2Rl4oCZcyBzdHJpbmcgdGhhdCBzaG91bGRcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiZSBoaWdobGlnaHRlZCBhcyB0aGUgc291cmNlIG9mIHRoZSBlcnJvclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBvcHRzLmluZGV4ICAtIGFuIGluZGV4IGluc2lkZSBhIG5vZGXigJlzIHN0cmluZyB0aGF0IHNob3VsZFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJlIGhpZ2hsaWdodGVkIGFzIHRoZSBzb3VyY2Ugb2YgdGhlIGVycm9yXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtDc3NTeW50YXhFcnJvcn0gZXJyb3Igb2JqZWN0IHRvIHRocm93IGl0XG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGlmICggIXZhcmlhYmxlc1tuYW1lXSApIHtcbiAgICAgKiAgIHRocm93IGRlY2wuZXJyb3IoJ1Vua25vd24gdmFyaWFibGUgJyArIG5hbWUsIHsgd29yZDogbmFtZSB9KTtcbiAgICAgKiAgIC8vIENzc1N5bnRheEVycm9yOiBwb3N0Y3NzLXZhcnM6YS5zYXNzOjQ6MzogVW5rbm93biB2YXJpYWJsZSAkYmxhY2tcbiAgICAgKiAgIC8vICAgY29sb3I6ICRibGFja1xuICAgICAqICAgLy8gYVxuICAgICAqICAgLy8gICAgICAgICAgXlxuICAgICAqICAgLy8gICBiYWNrZ3JvdW5kOiB3aGl0ZVxuICAgICAqIH1cbiAgICAgKi9cbiAgICBlcnJvcihtZXNzYWdlLCBvcHRzID0geyB9KSB7XG4gICAgICAgIGlmICggdGhpcy5zb3VyY2UgKSB7XG4gICAgICAgICAgICBsZXQgcG9zID0gdGhpcy5wb3NpdGlvbkJ5KG9wdHMpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc291cmNlLmlucHV0LmVycm9yKG1lc3NhZ2UsIHBvcy5saW5lLCBwb3MuY29sdW1uLCBvcHRzKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgQ3NzU3ludGF4RXJyb3IobWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBwcm92aWRlZCBhcyBhIGNvbnZlbmllbmNlIHdyYXBwZXIgZm9yIHtAbGluayBSZXN1bHQjd2Fybn0uXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1Jlc3VsdH0gcmVzdWx0ICAgICAgLSB0aGUge0BsaW5rIFJlc3VsdH0gaW5zdGFuY2VcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGF0IHdpbGwgcmVjZWl2ZSB0aGUgd2FybmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSB0ZXh0ICAgICAgICAtIHdhcm5pbmcgbWVzc2FnZVxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBbb3B0c10gICAgICAtIG9wdGlvbnNcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy5wbHVnaW4gLSBwbHVnaW4gbmFtZSB0aGF0IGNyZWF0ZWQgdGhpcyB3YXJuaW5nLlxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBvc3RDU1Mgd2lsbCBzZXQgaXQgYXV0b21hdGljYWxseS5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy53b3JkICAgLSBhIHdvcmQgaW5zaWRlIGEgbm9kZeKAmXMgc3RyaW5nIHRoYXQgc2hvdWxkXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmUgaGlnaGxpZ2h0ZWQgYXMgdGhlIHNvdXJjZSBvZiB0aGUgd2FybmluZ1xuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBvcHRzLmluZGV4ICAtIGFuIGluZGV4IGluc2lkZSBhIG5vZGXigJlzIHN0cmluZyB0aGF0IHNob3VsZFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJlIGhpZ2hsaWdodGVkIGFzIHRoZSBzb3VyY2Ugb2YgdGhlIHdhcm5pbmdcbiAgICAgKlxuICAgICAqIEByZXR1cm4ge1dhcm5pbmd9IGNyZWF0ZWQgd2FybmluZyBvYmplY3RcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogY29uc3QgcGx1Z2luID0gcG9zdGNzcy5wbHVnaW4oJ3Bvc3Rjc3MtZGVwcmVjYXRlZCcsICgpID0+IHtcbiAgICAgKiAgIHJldHVybiAoY3NzLCByZXN1bHQpID0+IHtcbiAgICAgKiAgICAgY3NzLndhbGtEZWNscygnYmFkJywgZGVjbCA9PiB7XG4gICAgICogICAgICAgZGVjbC53YXJuKHJlc3VsdCwgJ0RlcHJlY2F0ZWQgcHJvcGVydHkgYmFkJyk7XG4gICAgICogICAgIH0pO1xuICAgICAqICAgfTtcbiAgICAgKiB9KTtcbiAgICAgKi9cbiAgICB3YXJuKHJlc3VsdCwgdGV4dCwgb3B0cykge1xuICAgICAgICBsZXQgZGF0YSA9IHsgbm9kZTogdGhpcyB9O1xuICAgICAgICBmb3IgKCBsZXQgaSBpbiBvcHRzICkgZGF0YVtpXSA9IG9wdHNbaV07XG4gICAgICAgIHJldHVybiByZXN1bHQud2Fybih0ZXh0LCBkYXRhKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIHRoZSBub2RlIGZyb20gaXRzIHBhcmVudCBhbmQgY2xlYW5zIHRoZSBwYXJlbnQgcHJvcGVydGllc1xuICAgICAqIGZyb20gdGhlIG5vZGUgYW5kIGl0cyBjaGlsZHJlbi5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogaWYgKCBkZWNsLnByb3AubWF0Y2goL14td2Via2l0LS8pICkge1xuICAgICAqICAgZGVjbC5yZW1vdmUoKTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtOb2RlfSBub2RlIHRvIG1ha2UgY2FsbHMgY2hhaW5cbiAgICAgKi9cbiAgICByZW1vdmUoKSB7XG4gICAgICAgIGlmICggdGhpcy5wYXJlbnQgKSB7XG4gICAgICAgICAgICB0aGlzLnBhcmVudC5yZW1vdmVDaGlsZCh0aGlzKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnBhcmVudCA9IHVuZGVmaW5lZDtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhIENTUyBzdHJpbmcgcmVwcmVzZW50aW5nIHRoZSBub2RlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmdpZmllcnxzeW50YXh9IFtzdHJpbmdpZmllcl0gLSBhIHN5bnRheCB0byB1c2VcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluIHN0cmluZyBnZW5lcmF0aW9uXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtzdHJpbmd9IENTUyBzdHJpbmcgb2YgdGhpcyBub2RlXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIHBvc3Rjc3MucnVsZSh7IHNlbGVjdG9yOiAnYScgfSkudG9TdHJpbmcoKSAvLz0+IFwiYSB7fVwiXG4gICAgICovXG4gICAgdG9TdHJpbmcoc3RyaW5naWZpZXIgPSBzdHJpbmdpZnkpIHtcbiAgICAgICAgaWYgKCBzdHJpbmdpZmllci5zdHJpbmdpZnkgKSBzdHJpbmdpZmllciA9IHN0cmluZ2lmaWVyLnN0cmluZ2lmeTtcbiAgICAgICAgbGV0IHJlc3VsdCAgPSAnJztcbiAgICAgICAgc3RyaW5naWZpZXIodGhpcywgaSA9PiB7XG4gICAgICAgICAgICByZXN1bHQgKz0gaTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhIGNsb25lIG9mIHRoZSBub2RlLlxuICAgICAqXG4gICAgICogVGhlIHJlc3VsdGluZyBjbG9uZWQgbm9kZSBhbmQgaXRzIChjbG9uZWQpIGNoaWxkcmVuIHdpbGwgaGF2ZVxuICAgICAqIGEgY2xlYW4gcGFyZW50IGFuZCBjb2RlIHN0eWxlIHByb3BlcnRpZXMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gW292ZXJyaWRlc10gLSBuZXcgcHJvcGVydGllcyB0byBvdmVycmlkZSBpbiB0aGUgY2xvbmUuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGNvbnN0IGNsb25lZCA9IGRlY2wuY2xvbmUoeyBwcm9wOiAnLW1vei0nICsgZGVjbC5wcm9wIH0pO1xuICAgICAqIGNsb25lZC5yYXdzLmJlZm9yZSAgLy89PiB1bmRlZmluZWRcbiAgICAgKiBjbG9uZWQucGFyZW50ICAgICAgIC8vPT4gdW5kZWZpbmVkXG4gICAgICogY2xvbmVkLnRvU3RyaW5nKCkgICAvLz0+IC1tb3otdHJhbnNmb3JtOiBzY2FsZSgwKVxuICAgICAqXG4gICAgICogQHJldHVybiB7Tm9kZX0gY2xvbmUgb2YgdGhlIG5vZGVcbiAgICAgKi9cbiAgICBjbG9uZShvdmVycmlkZXMgPSB7IH0pIHtcbiAgICAgICAgbGV0IGNsb25lZCA9IGNsb25lTm9kZSh0aGlzKTtcbiAgICAgICAgZm9yICggbGV0IG5hbWUgaW4gb3ZlcnJpZGVzICkge1xuICAgICAgICAgICAgY2xvbmVkW25hbWVdID0gb3ZlcnJpZGVzW25hbWVdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjbG9uZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2hvcnRjdXQgdG8gY2xvbmUgdGhlIG5vZGUgYW5kIGluc2VydCB0aGUgcmVzdWx0aW5nIGNsb25lZCBub2RlXG4gICAgICogYmVmb3JlIHRoZSBjdXJyZW50IG5vZGUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gW292ZXJyaWRlc10gLSBuZXcgcHJvcGVydGllcyB0byBvdmVycmlkZSBpbiB0aGUgY2xvbmUuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGRlY2wuY2xvbmVCZWZvcmUoeyBwcm9wOiAnLW1vei0nICsgZGVjbC5wcm9wIH0pO1xuICAgICAqXG4gICAgICogQHJldHVybiB7Tm9kZX0gLSBuZXcgbm9kZVxuICAgICAqL1xuICAgIGNsb25lQmVmb3JlKG92ZXJyaWRlcyA9IHsgfSkge1xuICAgICAgICBsZXQgY2xvbmVkID0gdGhpcy5jbG9uZShvdmVycmlkZXMpO1xuICAgICAgICB0aGlzLnBhcmVudC5pbnNlcnRCZWZvcmUodGhpcywgY2xvbmVkKTtcbiAgICAgICAgcmV0dXJuIGNsb25lZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTaG9ydGN1dCB0byBjbG9uZSB0aGUgbm9kZSBhbmQgaW5zZXJ0IHRoZSByZXN1bHRpbmcgY2xvbmVkIG5vZGVcbiAgICAgKiBhZnRlciB0aGUgY3VycmVudCBub2RlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtvYmplY3R9IFtvdmVycmlkZXNdIC0gbmV3IHByb3BlcnRpZXMgdG8gb3ZlcnJpZGUgaW4gdGhlIGNsb25lLlxuICAgICAqXG4gICAgICogQHJldHVybiB7Tm9kZX0gLSBuZXcgbm9kZVxuICAgICAqL1xuICAgIGNsb25lQWZ0ZXIob3ZlcnJpZGVzID0geyB9KSB7XG4gICAgICAgIGxldCBjbG9uZWQgPSB0aGlzLmNsb25lKG92ZXJyaWRlcyk7XG4gICAgICAgIHRoaXMucGFyZW50Lmluc2VydEFmdGVyKHRoaXMsIGNsb25lZCk7XG4gICAgICAgIHJldHVybiBjbG9uZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSW5zZXJ0cyBub2RlKHMpIGJlZm9yZSB0aGUgY3VycmVudCBub2RlIGFuZCByZW1vdmVzIHRoZSBjdXJyZW50IG5vZGUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gey4uLk5vZGV9IG5vZGVzIC0gbm9kZShzKSB0byByZXBsYWNlIGN1cnJlbnQgb25lXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGlmICggYXRydWxlLm5hbWUgPT0gJ21peGluJyApIHtcbiAgICAgKiAgIGF0cnVsZS5yZXBsYWNlV2l0aChtaXhpblJ1bGVzW2F0cnVsZS5wYXJhbXNdKTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtOb2RlfSBjdXJyZW50IG5vZGUgdG8gbWV0aG9kcyBjaGFpblxuICAgICAqL1xuICAgIHJlcGxhY2VXaXRoKC4uLm5vZGVzKSB7XG4gICAgICAgIGlmICh0aGlzLnBhcmVudCkge1xuICAgICAgICAgICAgZm9yIChsZXQgbm9kZSBvZiBub2Rlcykge1xuICAgICAgICAgICAgICAgIHRoaXMucGFyZW50Lmluc2VydEJlZm9yZSh0aGlzLCBub2RlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5yZW1vdmUoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgdGhlIG5vZGUgZnJvbSBpdHMgY3VycmVudCBwYXJlbnQgYW5kIGluc2VydHMgaXRcbiAgICAgKiBhdCB0aGUgZW5kIG9mIGBuZXdQYXJlbnRgLlxuICAgICAqXG4gICAgICogVGhpcyB3aWxsIGNsZWFuIHRoZSBgYmVmb3JlYCBhbmQgYGFmdGVyYCBjb2RlIHtAbGluayBOb2RlI3Jhd3N9IGRhdGFcbiAgICAgKiBmcm9tIHRoZSBub2RlIGFuZCByZXBsYWNlIHRoZW0gd2l0aCB0aGUgaW5kZW50YXRpb24gc3R5bGUgb2YgYG5ld1BhcmVudGAuXG4gICAgICogSXQgd2lsbCBhbHNvIGNsZWFuIHRoZSBgYmV0d2VlbmAgcHJvcGVydHlcbiAgICAgKiBpZiBgbmV3UGFyZW50YCBpcyBpbiBhbm90aGVyIHtAbGluayBSb290fS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7Q29udGFpbmVyfSBuZXdQYXJlbnQgLSBjb250YWluZXIgbm9kZSB3aGVyZSB0aGUgY3VycmVudCBub2RlXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpbGwgYmUgbW92ZWRcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYXRydWxlLm1vdmVUbyhhdHJ1bGUucm9vdCgpKTtcbiAgICAgKlxuICAgICAqIEByZXR1cm4ge05vZGV9IGN1cnJlbnQgbm9kZSB0byBtZXRob2RzIGNoYWluXG4gICAgICovXG4gICAgbW92ZVRvKG5ld1BhcmVudCkge1xuICAgICAgICB0aGlzLmNsZWFuUmF3cyh0aGlzLnJvb3QoKSA9PT0gbmV3UGFyZW50LnJvb3QoKSk7XG4gICAgICAgIHRoaXMucmVtb3ZlKCk7XG4gICAgICAgIG5ld1BhcmVudC5hcHBlbmQodGhpcyk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgdGhlIG5vZGUgZnJvbSBpdHMgY3VycmVudCBwYXJlbnQgYW5kIGluc2VydHMgaXQgaW50b1xuICAgICAqIGEgbmV3IHBhcmVudCBiZWZvcmUgYG90aGVyTm9kZWAuXG4gICAgICpcbiAgICAgKiBUaGlzIHdpbGwgYWxzbyBjbGVhbiB0aGUgbm9kZeKAmXMgY29kZSBzdHlsZSBwcm9wZXJ0aWVzIGp1c3QgYXMgaXQgd291bGRcbiAgICAgKiBpbiB7QGxpbmsgTm9kZSNtb3ZlVG99LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtOb2RlfSBvdGhlck5vZGUgLSBub2RlIHRoYXQgd2lsbCBiZSBiZWZvcmUgY3VycmVudCBub2RlXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtOb2RlfSBjdXJyZW50IG5vZGUgdG8gbWV0aG9kcyBjaGFpblxuICAgICAqL1xuICAgIG1vdmVCZWZvcmUob3RoZXJOb2RlKSB7XG4gICAgICAgIHRoaXMuY2xlYW5SYXdzKHRoaXMucm9vdCgpID09PSBvdGhlck5vZGUucm9vdCgpKTtcbiAgICAgICAgdGhpcy5yZW1vdmUoKTtcbiAgICAgICAgb3RoZXJOb2RlLnBhcmVudC5pbnNlcnRCZWZvcmUob3RoZXJOb2RlLCB0aGlzKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyB0aGUgbm9kZSBmcm9tIGl0cyBjdXJyZW50IHBhcmVudCBhbmQgaW5zZXJ0cyBpdCBpbnRvXG4gICAgICogYSBuZXcgcGFyZW50IGFmdGVyIGBvdGhlck5vZGVgLlxuICAgICAqXG4gICAgICogVGhpcyB3aWxsIGFsc28gY2xlYW4gdGhlIG5vZGXigJlzIGNvZGUgc3R5bGUgcHJvcGVydGllcyBqdXN0IGFzIGl0IHdvdWxkXG4gICAgICogaW4ge0BsaW5rIE5vZGUjbW92ZVRvfS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7Tm9kZX0gb3RoZXJOb2RlIC0gbm9kZSB0aGF0IHdpbGwgYmUgYWZ0ZXIgY3VycmVudCBub2RlXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtOb2RlfSBjdXJyZW50IG5vZGUgdG8gbWV0aG9kcyBjaGFpblxuICAgICAqL1xuICAgIG1vdmVBZnRlcihvdGhlck5vZGUpIHtcbiAgICAgICAgdGhpcy5jbGVhblJhd3ModGhpcy5yb290KCkgPT09IG90aGVyTm9kZS5yb290KCkpO1xuICAgICAgICB0aGlzLnJlbW92ZSgpO1xuICAgICAgICBvdGhlck5vZGUucGFyZW50Lmluc2VydEFmdGVyKG90aGVyTm9kZSwgdGhpcyk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIG5leHQgY2hpbGQgb2YgdGhlIG5vZGXigJlzIHBhcmVudC5cbiAgICAgKiBSZXR1cm5zIGB1bmRlZmluZWRgIGlmIHRoZSBjdXJyZW50IG5vZGUgaXMgdGhlIGxhc3QgY2hpbGQuXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtOb2RlfHVuZGVmaW5lZH0gbmV4dCBub2RlXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGlmICggY29tbWVudC50ZXh0ID09PSAnZGVsZXRlIG5leHQnICkge1xuICAgICAqICAgY29uc3QgbmV4dCA9IGNvbW1lbnQubmV4dCgpO1xuICAgICAqICAgaWYgKCBuZXh0ICkge1xuICAgICAqICAgICBuZXh0LnJlbW92ZSgpO1xuICAgICAqICAgfVxuICAgICAqIH1cbiAgICAgKi9cbiAgICBuZXh0KCkge1xuICAgICAgICBsZXQgaW5kZXggPSB0aGlzLnBhcmVudC5pbmRleCh0aGlzKTtcbiAgICAgICAgcmV0dXJuIHRoaXMucGFyZW50Lm5vZGVzW2luZGV4ICsgMV07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgcHJldmlvdXMgY2hpbGQgb2YgdGhlIG5vZGXigJlzIHBhcmVudC5cbiAgICAgKiBSZXR1cm5zIGB1bmRlZmluZWRgIGlmIHRoZSBjdXJyZW50IG5vZGUgaXMgdGhlIGZpcnN0IGNoaWxkLlxuICAgICAqXG4gICAgICogQHJldHVybiB7Tm9kZXx1bmRlZmluZWR9IHByZXZpb3VzIG5vZGVcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogY29uc3QgYW5ub3RhdGlvbiA9IGRlY2wucHJldigpO1xuICAgICAqIGlmICggYW5ub3RhdGlvbi50eXBlID09ICdjb21tZW50JyApIHtcbiAgICAgKiAgcmVhZEFubm90YXRpb24oYW5ub3RhdGlvbi50ZXh0KTtcbiAgICAgKiB9XG4gICAgICovXG4gICAgcHJldigpIHtcbiAgICAgICAgbGV0IGluZGV4ID0gdGhpcy5wYXJlbnQuaW5kZXgodGhpcyk7XG4gICAgICAgIHJldHVybiB0aGlzLnBhcmVudC5ub2Rlc1tpbmRleCAtIDFdO1xuICAgIH1cblxuICAgIHRvSlNPTigpIHtcbiAgICAgICAgbGV0IGZpeGVkID0geyB9O1xuXG4gICAgICAgIGZvciAoIGxldCBuYW1lIGluIHRoaXMgKSB7XG4gICAgICAgICAgICBpZiAoICF0aGlzLmhhc093blByb3BlcnR5KG5hbWUpICkgY29udGludWU7XG4gICAgICAgICAgICBpZiAoIG5hbWUgPT09ICdwYXJlbnQnICkgY29udGludWU7XG4gICAgICAgICAgICBsZXQgdmFsdWUgPSB0aGlzW25hbWVdO1xuXG4gICAgICAgICAgICBpZiAoIHZhbHVlIGluc3RhbmNlb2YgQXJyYXkgKSB7XG4gICAgICAgICAgICAgICAgZml4ZWRbbmFtZV0gPSB2YWx1ZS5tYXAoIGkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIHR5cGVvZiBpID09PSAnb2JqZWN0JyAmJiBpLnRvSlNPTiApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpLnRvSlNPTigpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgJiYgdmFsdWUudG9KU09OICkge1xuICAgICAgICAgICAgICAgIGZpeGVkW25hbWVdID0gdmFsdWUudG9KU09OKCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGZpeGVkW25hbWVdID0gdmFsdWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZml4ZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhIHtAbGluayBOb2RlI3Jhd3N9IHZhbHVlLiBJZiB0aGUgbm9kZSBpcyBtaXNzaW5nXG4gICAgICogdGhlIGNvZGUgc3R5bGUgcHJvcGVydHkgKGJlY2F1c2UgdGhlIG5vZGUgd2FzIG1hbnVhbGx5IGJ1aWx0IG9yIGNsb25lZCksXG4gICAgICogUG9zdENTUyB3aWxsIHRyeSB0byBhdXRvZGV0ZWN0IHRoZSBjb2RlIHN0eWxlIHByb3BlcnR5IGJ5IGxvb2tpbmdcbiAgICAgKiBhdCBvdGhlciBub2RlcyBpbiB0aGUgdHJlZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBwcm9wICAgICAgICAgIC0gbmFtZSBvZiBjb2RlIHN0eWxlIHByb3BlcnR5XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtkZWZhdWx0VHlwZV0gLSBuYW1lIG9mIGRlZmF1bHQgdmFsdWUsIGl0IGNhbiBiZSBtaXNzZWRcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIHRoZSB2YWx1ZSBpcyB0aGUgc2FtZSBhcyBwcm9wXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGNvbnN0IHJvb3QgPSBwb3N0Y3NzLnBhcnNlKCdhIHsgYmFja2dyb3VuZDogd2hpdGUgfScpO1xuICAgICAqIHJvb3Qubm9kZXNbMF0uYXBwZW5kKHsgcHJvcDogJ2NvbG9yJywgdmFsdWU6ICdibGFjaycgfSk7XG4gICAgICogcm9vdC5ub2Rlc1swXS5ub2Rlc1sxXS5yYXdzLmJlZm9yZSAgIC8vPT4gdW5kZWZpbmVkXG4gICAgICogcm9vdC5ub2Rlc1swXS5ub2Rlc1sxXS5yYXcoJ2JlZm9yZScpIC8vPT4gJyAnXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtzdHJpbmd9IGNvZGUgc3R5bGUgdmFsdWVcbiAgICAgKi9cbiAgICByYXcocHJvcCwgZGVmYXVsdFR5cGUpIHtcbiAgICAgICAgbGV0IHN0ciA9IG5ldyBTdHJpbmdpZmllcigpO1xuICAgICAgICByZXR1cm4gc3RyLnJhdyh0aGlzLCBwcm9wLCBkZWZhdWx0VHlwZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRmluZHMgdGhlIFJvb3QgaW5zdGFuY2Ugb2YgdGhlIG5vZGXigJlzIHRyZWUuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIHJvb3Qubm9kZXNbMF0ubm9kZXNbMF0ucm9vdCgpID09PSByb290XG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtSb290fSByb290IHBhcmVudFxuICAgICAqL1xuICAgIHJvb3QoKSB7XG4gICAgICAgIGxldCByZXN1bHQgPSB0aGlzO1xuICAgICAgICB3aGlsZSAoIHJlc3VsdC5wYXJlbnQgKSByZXN1bHQgPSByZXN1bHQucGFyZW50O1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIGNsZWFuUmF3cyhrZWVwQmV0d2Vlbikge1xuICAgICAgICBkZWxldGUgdGhpcy5yYXdzLmJlZm9yZTtcbiAgICAgICAgZGVsZXRlIHRoaXMucmF3cy5hZnRlcjtcbiAgICAgICAgaWYgKCAha2VlcEJldHdlZW4gKSBkZWxldGUgdGhpcy5yYXdzLmJldHdlZW47XG4gICAgfVxuXG4gICAgcG9zaXRpb25JbnNpZGUoaW5kZXgpIHtcbiAgICAgICAgbGV0IHN0cmluZyA9IHRoaXMudG9TdHJpbmcoKTtcbiAgICAgICAgbGV0IGNvbHVtbiA9IHRoaXMuc291cmNlLnN0YXJ0LmNvbHVtbjtcbiAgICAgICAgbGV0IGxpbmUgICA9IHRoaXMuc291cmNlLnN0YXJ0LmxpbmU7XG5cbiAgICAgICAgZm9yICggbGV0IGkgPSAwOyBpIDwgaW5kZXg7IGkrKyApIHtcbiAgICAgICAgICAgIGlmICggc3RyaW5nW2ldID09PSAnXFxuJyApIHtcbiAgICAgICAgICAgICAgICBjb2x1bW4gPSAxO1xuICAgICAgICAgICAgICAgIGxpbmUgICs9IDE7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbHVtbiArPSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHsgbGluZSwgY29sdW1uIH07XG4gICAgfVxuXG4gICAgcG9zaXRpb25CeShvcHRzKSB7XG4gICAgICAgIGxldCBwb3MgPSB0aGlzLnNvdXJjZS5zdGFydDtcbiAgICAgICAgaWYgKCBvcHRzLmluZGV4ICkge1xuICAgICAgICAgICAgcG9zID0gdGhpcy5wb3NpdGlvbkluc2lkZShvcHRzLmluZGV4KTtcbiAgICAgICAgfSBlbHNlIGlmICggb3B0cy53b3JkICkge1xuICAgICAgICAgICAgbGV0IGluZGV4ID0gdGhpcy50b1N0cmluZygpLmluZGV4T2Yob3B0cy53b3JkKTtcbiAgICAgICAgICAgIGlmICggaW5kZXggIT09IC0xICkgcG9zID0gdGhpcy5wb3NpdGlvbkluc2lkZShpbmRleCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHBvcztcbiAgICB9XG5cbiAgICByZW1vdmVTZWxmKCkge1xuICAgICAgICB3YXJuT25jZSgnTm9kZSNyZW1vdmVTZWxmIGlzIGRlcHJlY2F0ZWQuIFVzZSBOb2RlI3JlbW92ZS4nKTtcbiAgICAgICAgcmV0dXJuIHRoaXMucmVtb3ZlKCk7XG4gICAgfVxuXG4gICAgcmVwbGFjZShub2Rlcykge1xuICAgICAgICB3YXJuT25jZSgnTm9kZSNyZXBsYWNlIGlzIGRlcHJlY2F0ZWQuIFVzZSBOb2RlI3JlcGxhY2VXaXRoJyk7XG4gICAgICAgIHJldHVybiB0aGlzLnJlcGxhY2VXaXRoKG5vZGVzKTtcbiAgICB9XG5cbiAgICBzdHlsZShvd24sIGRldGVjdCkge1xuICAgICAgICB3YXJuT25jZSgnTm9kZSNzdHlsZSgpIGlzIGRlcHJlY2F0ZWQuIFVzZSBOb2RlI3JhdygpJyk7XG4gICAgICAgIHJldHVybiB0aGlzLnJhdyhvd24sIGRldGVjdCk7XG4gICAgfVxuXG4gICAgY2xlYW5TdHlsZXMoa2VlcEJldHdlZW4pIHtcbiAgICAgICAgd2Fybk9uY2UoJ05vZGUjY2xlYW5TdHlsZXMoKSBpcyBkZXByZWNhdGVkLiBVc2UgTm9kZSNjbGVhblJhd3MoKScpO1xuICAgICAgICByZXR1cm4gdGhpcy5jbGVhblJhd3Moa2VlcEJldHdlZW4pO1xuICAgIH1cblxuICAgIGdldCBiZWZvcmUoKSB7XG4gICAgICAgIHdhcm5PbmNlKCdOb2RlI2JlZm9yZSBpcyBkZXByZWNhdGVkLiBVc2UgTm9kZSNyYXdzLmJlZm9yZScpO1xuICAgICAgICByZXR1cm4gdGhpcy5yYXdzLmJlZm9yZTtcbiAgICB9X