UNPKG

slate

Version:

A completely customizable framework for building rich text editors.

658 lines (520 loc) 42.5 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: 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 _isPlainObject = require('is-plain-object'); var _isPlainObject2 = _interopRequireDefault(_isPlainObject); var _immutable = require('immutable'); var _character = require('./character'); var _character2 = _interopRequireDefault(_character); var _mark = require('./mark'); var _mark2 = _interopRequireDefault(_mark); var _leaf = require('./leaf'); var _leaf2 = _interopRequireDefault(_leaf); var _modelTypes = require('../constants/model-types'); var _modelTypes2 = _interopRequireDefault(_modelTypes); var _generateKey = require('../utils/generate-key'); var _generateKey2 = _interopRequireDefault(_generateKey); var _memoize = require('../utils/memoize'); var _memoize2 = _interopRequireDefault(_memoize); 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"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /** * Default properties. * * @type {Object} */ var DEFAULTS = { characters: new _immutable.List(), key: undefined }; /** * Text. * * @type {Text} */ var Text = function (_Record) { _inherits(Text, _Record); function Text() { _classCallCheck(this, Text); return _possibleConstructorReturn(this, (Text.__proto__ || Object.getPrototypeOf(Text)).apply(this, arguments)); } _createClass(Text, [{ key: 'addMark', /** * Add a `mark` at `index` and `length`. * * @param {Number} index * @param {Number} length * @param {Mark} mark * @return {Text} */ value: function addMark(index, length, mark) { var marks = new _immutable.Set([mark]); return this.addMarks(index, length, marks); } /** * Add a `set` of marks at `index` and `length`. * * @param {Number} index * @param {Number} length * @param {Set<Mark>} set * @return {Text} */ }, { key: 'addMarks', value: function addMarks(index, length, set) { var characters = this.characters.map(function (char, i) { if (i < index) return char; if (i >= index + length) return char; var _char = char, marks = _char.marks; marks = marks.union(set); char = char.set('marks', marks); return char; }); return this.set('characters', characters); } /** * Derive a set of decorated characters with `decorations`. * * @param {List<Decoration>} decorations * @return {List<Character>} */ }, { key: 'getDecoratedCharacters', value: function getDecoratedCharacters(decorations) { var node = this; var _node = node, key = _node.key, characters = _node.characters; // PERF: Exit early if there are no characters to be decorated. if (characters.size == 0) return characters; decorations.forEach(function (range) { var startKey = range.startKey, endKey = range.endKey, startOffset = range.startOffset, endOffset = range.endOffset, marks = range.marks; var hasStart = startKey == key; var hasEnd = endKey == key; var index = hasStart ? startOffset : 0; var length = hasEnd ? endOffset - index : characters.size; node = node.addMarks(index, length, marks); }); return node.characters; } /** * Get the decorations for the node from a `schema`. * * @param {Schema} schema * @return {Array} */ }, { key: 'getDecorations', value: function getDecorations(schema) { return schema.__getDecorations(this); } /** * Derive the leaves for a list of `characters`. * * @param {Array|Void} decorations (optional) * @return {List<Leaf>} */ }, { key: 'getLeaves', value: function getLeaves() { var decorations = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; var characters = this.getDecoratedCharacters(decorations); var leaves = []; // PERF: cache previous values for faster lookup. var prevChar = void 0; var prevLeaf = void 0; // If there are no characters, return one empty range. if (characters.size == 0) { leaves.push({}); } // Otherwise, loop the characters and build the leaves... else { characters.forEach(function (char, i) { var marks = char.marks, text = char.text; // The first one can always just be created. if (i == 0) { prevChar = char; prevLeaf = { text: text, marks: marks }; leaves.push(prevLeaf); return; } // Otherwise, compare the current and previous marks. var prevMarks = prevChar.marks; var isSame = (0, _immutable.is)(marks, prevMarks); // If the marks are the same, add the text to the previous range. if (isSame) { prevChar = char; prevLeaf.text += text; return; } // Otherwise, create a new range. prevChar = char; prevLeaf = { text: text, marks: marks }; leaves.push(prevLeaf); }, []); } // PERF: convert the leaves to immutable objects after iterating. leaves = new _immutable.List(leaves.map(function (object) { return new _leaf2.default(object); })); // Return the leaves. return leaves; } /** * Get all of the marks on the text. * * @return {OrderedSet<Mark>} */ }, { key: 'getMarks', value: function getMarks() { var array = this.getMarksAsArray(); return new _immutable.OrderedSet(array); } /** * Get all of the marks on the text as an array * * @return {Array} */ }, { key: 'getMarksAsArray', value: function getMarksAsArray() { return this.characters.reduce(function (array, char) { return array.concat(char.marks.toArray()); }, []); } /** * Get the marks on the text at `index`. * * @param {Number} index * @return {Set<Mark>} */ }, { key: 'getMarksAtIndex', value: function getMarksAtIndex(index) { if (index == 0) return _mark2.default.createSet(); var characters = this.characters; var char = characters.get(index - 1); if (!char) return _mark2.default.createSet(); return char.marks; } /** * Get a node by `key`, to parallel other nodes. * * @param {String} key * @return {Node|Null} */ }, { key: 'getNode', value: function getNode(key) { return this.key == key ? this : null; } /** * Check if the node has a node by `key`, to parallel other nodes. * * @param {String} key * @return {Boolean} */ }, { key: 'hasNode', value: function hasNode(key) { return !!this.getNode(key); } /** * Insert `text` at `index`. * * @param {Numbder} index * @param {String} text * @param {String} marks (optional) * @return {Text} */ }, { key: 'insertText', value: function insertText(index, text, marks) { var characters = this.characters; var chars = _character2.default.createList(text.split('').map(function (char) { return { text: char, marks: marks }; })); characters = characters.slice(0, index).concat(chars).concat(characters.slice(index)); return this.set('characters', characters); } /** * Regenerate the node's key. * * @return {Text} */ }, { key: 'regenerateKey', value: function regenerateKey() { var key = (0, _generateKey2.default)(); return this.set('key', key); } /** * Remove a `mark` at `index` and `length`. * * @param {Number} index * @param {Number} length * @param {Mark} mark * @return {Text} */ }, { key: 'removeMark', value: function removeMark(index, length, mark) { var characters = this.characters.map(function (char, i) { if (i < index) return char; if (i >= index + length) return char; var _char2 = char, marks = _char2.marks; marks = marks.remove(mark); char = char.set('marks', marks); return char; }); return this.set('characters', characters); } /** * Remove text from the text node at `index` for `length`. * * @param {Number} index * @param {Number} length * @return {Text} */ }, { key: 'removeText', value: function removeText(index, length) { var characters = this.characters; var start = index; var end = index + length; characters = characters.filterNot(function (char, i) { return start <= i && i < end; }); return this.set('characters', characters); } /** * Return a JSON representation of the text. * * @param {Object} options * @return {Object} */ }, { key: 'toJSON', value: function toJSON() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var object = { kind: this.kind, leaves: this.getLeaves().toArray().map(function (r) { return r.toJSON(); }) }; if (options.preserveKeys) { object.key = this.key; } return object; } /** * Alias `toJS`. */ }, { key: 'toJS', value: function toJS(options) { return this.toJSON(options); } /** * Update a `mark` at `index` and `length` with `properties`. * * @param {Number} index * @param {Number} length * @param {Mark} mark * @param {Object} properties * @return {Text} */ }, { key: 'updateMark', value: function updateMark(index, length, mark, properties) { var newMark = mark.merge(properties); var characters = this.characters.map(function (char, i) { if (i < index) return char; if (i >= index + length) return char; var _char3 = char, marks = _char3.marks; if (!marks.has(mark)) return char; marks = marks.remove(mark); marks = marks.add(newMark); char = char.set('marks', marks); return char; }); return this.set('characters', characters); } /** * Validate the text node against a `schema`. * * @param {Schema} schema * @return {Object|Void} */ }, { key: 'validate', value: function validate(schema) { return schema.validateNode(this); } }, { key: 'kind', /** * Get the node's kind. * * @return {String} */ get: function get() { return 'text'; } /** * Is the node empty? * * @return {Boolean} */ }, { key: 'isEmpty', get: function get() { return this.text == ''; } /** * Get the concatenated text of the node. * * @return {String} */ }, { key: 'text', get: function get() { return this.characters.reduce(function (string, char) { return string + char.text; }, ''); } }], [{ key: 'create', /** * Create a new `Text` with `attrs`. * * @param {Object|Array|List|String|Text} attrs * @return {Text} */ value: function create() { var attrs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; if (Text.isText(attrs)) { return attrs; } if (typeof attrs == 'string') { attrs = { leaves: [{ text: attrs }] }; } if ((0, _isPlainObject2.default)(attrs)) { if (attrs.text) { var _attrs = attrs, text = _attrs.text, marks = _attrs.marks, key = _attrs.key; attrs = { key: key, leaves: [{ text: text, marks: marks }] }; } return Text.fromJSON(attrs); } throw new Error('`Text.create` only accepts objects, arrays, strings or texts, but you passed it: ' + attrs); } /** * Create a list of `Texts` from `elements`. * * @param {Array<Text|Object>|List<Text|Object>} elements * @return {List<Text>} */ }, { key: 'createList', value: function createList() { var elements = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; if (_immutable.List.isList(elements) || Array.isArray(elements)) { var list = new _immutable.List(elements.map(Text.create)); return list; } throw new Error('`Text.createList` only accepts arrays or lists, but you passed it: ' + elements); } /** * Create a `Text` from a JSON `object`. * * @param {Object|Text} object * @return {Text} */ }, { key: 'fromJSON', value: function fromJSON(object) { if (Text.isText(object)) { return object; } var _object$leaves = object.leaves, leaves = _object$leaves === undefined ? [] : _object$leaves, _object$key = object.key, key = _object$key === undefined ? (0, _generateKey2.default)() : _object$key; var characters = leaves.map(_leaf2.default.fromJSON).reduce(function (l, r) { return l.concat(r.getCharacters()); }, new _immutable.List()); var node = new Text({ characters: characters, key: key }); return node; } /** * Alias `fromJS`. */ }, { key: 'isText', /** * Check if `any` is a `Text`. * * @param {Any} any * @return {Boolean} */ value: function isText(any) { return !!(any && any[_modelTypes2.default.TEXT]); } /** * Check if `any` is a list of texts. * * @param {Any} any * @return {Boolean} */ }, { key: 'isTextList', value: function isTextList(any) { return _immutable.List.isList(any) && any.every(function (item) { return Text.isText(item); }); } }]); return Text; }((0, _immutable.Record)(DEFAULTS)); /** * Attach a pseudo-symbol for type checking. */ Text.fromJS = Text.fromJSON; Text.prototype[_modelTypes2.default.TEXT] = true; /** * Memoize read methods. */ (0, _memoize2.default)(Text.prototype, ['getMarks', 'getMarksAsArray'], { takesArguments: false }); (0, _memoize2.default)(Text.prototype, ['getDecoratedCharacters', 'getDecorations', 'getLeaves', 'getMarksAtIndex', 'validate'], { takesArguments: true }); /** * Export. * * @type {Text} */ exports.default = Text; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9tb2RlbHMvdGV4dC5qcyJdLCJuYW1lcyI6WyJERUZBVUxUUyIsImNoYXJhY3RlcnMiLCJrZXkiLCJ1bmRlZmluZWQiLCJUZXh0IiwiaW5kZXgiLCJsZW5ndGgiLCJtYXJrIiwibWFya3MiLCJhZGRNYXJrcyIsInNldCIsIm1hcCIsImNoYXIiLCJpIiwidW5pb24iLCJkZWNvcmF0aW9ucyIsIm5vZGUiLCJzaXplIiwiZm9yRWFjaCIsInJhbmdlIiwic3RhcnRLZXkiLCJlbmRLZXkiLCJzdGFydE9mZnNldCIsImVuZE9mZnNldCIsImhhc1N0YXJ0IiwiaGFzRW5kIiwic2NoZW1hIiwiX19nZXREZWNvcmF0aW9ucyIsImdldERlY29yYXRlZENoYXJhY3RlcnMiLCJsZWF2ZXMiLCJwcmV2Q2hhciIsInByZXZMZWFmIiwicHVzaCIsInRleHQiLCJwcmV2TWFya3MiLCJpc1NhbWUiLCJvYmplY3QiLCJhcnJheSIsImdldE1hcmtzQXNBcnJheSIsInJlZHVjZSIsImNvbmNhdCIsInRvQXJyYXkiLCJjcmVhdGVTZXQiLCJnZXQiLCJnZXROb2RlIiwiY2hhcnMiLCJjcmVhdGVMaXN0Iiwic3BsaXQiLCJzbGljZSIsInJlbW92ZSIsInN0YXJ0IiwiZW5kIiwiZmlsdGVyTm90Iiwib3B0aW9ucyIsImtpbmQiLCJnZXRMZWF2ZXMiLCJyIiwidG9KU09OIiwicHJlc2VydmVLZXlzIiwicHJvcGVydGllcyIsIm5ld01hcmsiLCJtZXJnZSIsImhhcyIsImFkZCIsInZhbGlkYXRlTm9kZSIsInN0cmluZyIsImF0dHJzIiwiaXNUZXh0IiwiZnJvbUpTT04iLCJFcnJvciIsImVsZW1lbnRzIiwiaXNMaXN0IiwiQXJyYXkiLCJpc0FycmF5IiwibGlzdCIsImNyZWF0ZSIsImwiLCJnZXRDaGFyYWN0ZXJzIiwiYW55IiwiVEVYVCIsImV2ZXJ5IiwiaXRlbSIsImZyb21KUyIsInByb3RvdHlwZSIsInRha2VzQXJndW1lbnRzIl0sIm1hcHBpbmdzIjoiOzs7Ozs7OztB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QVosS0FBb0JBLElBQUlFLEtBQUosQ0FBVTtBQUFBLGVBQVE1RSxLQUFLK0QsTUFBTCxDQUFZYyxJQUFaLENBQVI7QUFBQSxPQUFWLENBQTNCO0FBQ0Q7Ozs7RUFyR2dCLHVCQUFPakYsUUFBUCxDOztBQStjbkI7Ozs7QUEvY01JLEksQ0ErRUc4RSxNLEdBQVM5RSxLQUFLZ0UsUTtBQW9ZdkJoRSxLQUFLK0UsU0FBTCxDQUFlLHFCQUFZSixJQUEzQixJQUFtQyxJQUFuQzs7QUFFQTs7OztBQUlBLHVCQUFRM0UsS0FBSytFLFNBQWIsRUFBd0IsQ0FDdEIsVUFEc0IsRUFFdEIsaUJBRnNCLENBQXhCLEVBR0c7QUFDREMsa0JBQWdCO0FBRGYsQ0FISDs7QUFPQSx1QkFBUWhGLEtBQUsrRSxTQUFiLEVBQXdCLENBQ3RCLHdCQURzQixFQUV0QixnQkFGc0IsRUFHdEIsV0FIc0IsRUFJdEIsaUJBSnNCLEVBS3RCLFVBTHNCLENBQXhCLEVBTUc7QUFDREMsa0JBQWdCO0FBRGYsQ0FOSDs7QUFVQTs7Ozs7O2tCQU1laEYsSSIsImZpbGUiOiJ0ZXh0LmpzIiwic291cmNlc0NvbnRlbnQiOlsiXG5pbXBvcnQgaXNQbGFpbk9iamVjdCBmcm9tICdpcy1wbGFpbi1vYmplY3QnXG5pbXBvcnQgeyBMaXN0LCBPcmRlcmVkU2V0LCBSZWNvcmQsIFNldCwgaXMgfSBmcm9tICdpbW11dGFibGUnXG5cbmltcG9ydCBDaGFyYWN0ZXIgZnJvbSAnLi9jaGFyYWN0ZXInXG5pbXBvcnQgTWFyayBmcm9tICcuL21hcmsnXG5pbXBvcnQgTGVhZiBmcm9tICcuL2xlYWYnXG5pbXBvcnQgTU9ERUxfVFlQRVMgZnJvbSAnLi4vY29uc3RhbnRzL21vZGVsLXR5cGVzJ1xuaW1wb3J0IGdlbmVyYXRlS2V5IGZyb20gJy4uL3V0aWxzL2dlbmVyYXRlLWtleSdcbmltcG9ydCBtZW1vaXplIGZyb20gJy4uL3V0aWxzL21lbW9pemUnXG5cbi8qKlxuICogRGVmYXVsdCBwcm9wZXJ0aWVzLlxuICpcbiAqIEB0eXBlIHtPYmplY3R9XG4gKi9cblxuY29uc3QgREVGQVVMVFMgPSB7XG4gIGNoYXJhY3RlcnM6IG5ldyBMaXN0KCksXG4gIGtleTogdW5kZWZpbmVkLFxufVxuXG4vKipcbiAqIFRleHQuXG4gKlxuICogQHR5cGUge1RleHR9XG4gKi9cblxuY2xhc3MgVGV4dCBleHRlbmRzIFJlY29yZChERUZBVUxUUykge1xuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBuZXcgYFRleHRgIHdpdGggYGF0dHJzYC5cbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R8QXJyYXl8TGlzdHxTdHJpbmd8VGV4dH0gYXR0cnNcbiAgICogQHJldHVybiB7VGV4dH1cbiAgICovXG5cbiAgc3RhdGljIGNyZWF0ZShhdHRycyA9ICcnKSB7XG4gICAgaWYgKFRleHQuaXNUZXh0KGF0dHJzKSkge1xuICAgICAgcmV0dXJuIGF0dHJzXG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBhdHRycyA9PSAnc3RyaW5nJykge1xuICAgICAgYXR0cnMgPSB7IGxlYXZlczogW3sgdGV4dDogYXR0cnMgfV0gfVxuICAgIH1cblxuICAgIGlmIChpc1BsYWluT2JqZWN0KGF0dHJzKSkge1xuICAgICAgaWYgKGF0dHJzLnRleHQpIHtcbiAgICAgICAgY29uc3QgeyB0ZXh0LCBtYXJrcywga2V5IH0gPSBhdHRyc1xuICAgICAgICBhdHRycyA9IHsga2V5LCBsZWF2ZXM6IFt7IHRleHQsIG1hcmtzIH1dIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIFRleHQuZnJvbUpTT04oYXR0cnMpXG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKGBcXGBUZXh0LmNyZWF0ZVxcYCBvbmx5IGFjY2VwdHMgb2JqZWN0cywgYXJyYXlzLCBzdHJpbmdzIG9yIHRleHRzLCBidXQgeW91IHBhc3NlZCBpdDogJHthdHRyc31gKVxuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhIGxpc3Qgb2YgYFRleHRzYCBmcm9tIGBlbGVtZW50c2AuXG4gICAqXG4gICAqIEBwYXJhbSB7QXJyYXk8VGV4dHxPYmplY3Q+fExpc3Q8VGV4dHxPYmplY3Q+fSBlbGVtZW50c1xuICAgKiBAcmV0dXJuIHtMaXN0PFRleHQ+fVxuICAgKi9cblxuICBzdGF0aWMgY3JlYXRlTGlzdChlbGVtZW50cyA9IFtdKSB7XG4gICAgaWYgKExpc3QuaXNMaXN0KGVsZW1lbnRzKSB8fCBBcnJheS5pc0FycmF5KGVsZW1lbnRzKSkge1xuICAgICAgY29uc3QgbGlzdCA9IG5ldyBMaXN0KGVsZW1lbnRzLm1hcChUZXh0LmNyZWF0ZSkpXG4gICAgICByZXR1cm4gbGlzdFxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihgXFxgVGV4dC5jcmVhdGVMaXN0XFxgIG9ubHkgYWNjZXB0cyBhcnJheXMgb3IgbGlzdHMsIGJ1dCB5b3UgcGFzc2VkIGl0OiAke2VsZW1lbnRzfWApXG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgYFRleHRgIGZyb20gYSBKU09OIGBvYmplY3RgLlxuICAgKlxuICAgKiBAcGFyYW0ge09iamVjdHxUZXh0fSBvYmplY3RcbiAgICogQHJldHVybiB7VGV4dH1cbiAgICovXG5cbiAgc3RhdGljIGZyb21KU09OKG9iamVjdCkge1xuICAgIGlmIChUZXh0LmlzVGV4dChvYmplY3QpKSB7XG4gICAgICByZXR1cm4gb2JqZWN0XG4gICAgfVxuXG4gICAgY29uc3Qge1xuICAgICAgbGVhdmVzID0gW10sXG4gICAgICBrZXkgPSBnZW5lcmF0ZUtleSgpLFxuICAgIH0gPSBvYmplY3RcblxuICAgIGNvbnN0IGNoYXJhY3RlcnMgPSBsZWF2ZXNcbiAgICAgIC5tYXAoTGVhZi5mcm9tSlNPTilcbiAgICAgIC5yZWR1Y2UoKGwsIHIpID0+IGwuY29uY2F0KHIuZ2V0Q2hhcmFjdGVycygpKSwgbmV3IExpc3QoKSlcblxuICAgIGNvbnN0IG5vZGUgPSBuZXcgVGV4dCh7XG4gICAgICBjaGFyYWN0ZXJzLFxuICAgICAga2V5LFxuICAgIH0pXG5cbiAgICByZXR1cm4gbm9kZVxuICB9XG5cbiAgLyoqXG4gICAqIEFsaWFzIGBmcm9tSlNgLlxuICAgKi9cblxuICBzdGF0aWMgZnJvbUpTID0gVGV4dC5mcm9tSlNPTlxuXG4gIC8qKlxuICAgKiBDaGVjayBpZiBgYW55YCBpcyBhIGBUZXh0YC5cbiAgICpcbiAgICogQHBhcmFtIHtBbnl9IGFueVxuICAgKiBAcmV0dXJuIHtCb29sZWFufVxuICAgKi9cblxuICBzdGF0aWMgaXNUZXh0KGFueSkge1xuICAgIHJldHVybiAhIShhbnkgJiYgYW55W01PREVMX1RZUEVTLlRFWFRdKVxuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIGlmIGBhbnlgIGlzIGEgbGlzdMKgb2YgdGV4dHMuXG4gICAqXG4gICAqIEBwYXJhbSB7QW55fSBhbnlcbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICovXG5cbiAgc3RhdGljIGlzVGV4dExpc3QoYW55KSB7XG4gICAgcmV0dXJuIExpc3QuaXNMaXN0KGFueSkgJiYgYW55LmV2ZXJ5KGl0ZW0gPT4gVGV4dC5pc1RleHQoaXRlbSkpXG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBub2RlJ3Mga2luZC5cbiAgICpcbiAgICogQHJldHVybiB7U3RyaW5nfVxuICAgKi9cblxuICBnZXQga2luZCgpIHtcbiAgICByZXR1cm4gJ3RleHQnXG4gIH1cblxuICAvKipcbiAgICogSXMgdGhlIG5vZGUgZW1wdHk/XG4gICAqXG4gICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAqL1xuXG4gIGdldCBpc0VtcHR5KCkge1xuICAgIHJldHVybiB0aGlzLnRleHQgPT0gJydcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIGNvbmNhdGVuYXRlZCB0ZXh0IG9mIHRoZSBub2RlLlxuICAgKlxuICAgKiBAcmV0dXJuIHtTdHJpbmd9XG4gICAqL1xuXG4gIGdldCB0ZXh0KCkge1xuICAgIHJldHVybiB0aGlzLmNoYXJhY3RlcnMucmVkdWNlKChzdHJpbmcsIGNoYXIpID0+IHN0cmluZyArIGNoYXIudGV4dCwgJycpXG4gIH1cblxuICAvKipcbiAgICogQWRkIGEgYG1hcmtgIGF0IGBpbmRleGAgYW5kIGBsZW5ndGhgLlxuICAgKlxuICAgKiBAcGFyYW0ge051bWJlcn0gaW5kZXhcbiAgICogQHBhcmFtIHtOdW1iZXJ9IGxlbmd0aFxuICAgKiBAcGFyYW0ge01hcmt9IG1hcmtcbiAgICogQHJldHVybiB7VGV4dH1cbiAgICovXG5cbiAgYWRkTWFyayhpbmRleCwgbGVuZ3RoLCBtYXJrKSB7XG4gICAgY29uc3QgbWFya3MgPSBuZXcgU2V0KFttYXJrXSlcbiAgICByZXR1cm4gdGhpcy5hZGRNYXJrcyhpbmRleCwgbGVuZ3RoLCBtYXJrcylcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgYSBgc2V0YCBvZiBtYXJrcyBhdCBgaW5kZXhgIGFuZCBgbGVuZ3RoYC5cbiAgICpcbiAgICogQHBhcmFtIHtOdW1iZXJ9IGluZGV4XG4gICAqIEBwYXJhbSB7TnVtYmVyfSBsZW5ndGhcbiAgICogQHBhcmFtIHtTZXQ8TWFyaz59IHNldFxuICAgKiBAcmV0dXJuIHtUZXh0fVxuICAgKi9cblxuICBhZGRNYXJrcyhpbmRleCwgbGVuZ3RoLCBzZXQpIHtcbiAgICBjb25zdCBjaGFyYWN0ZXJzID0gdGhpcy5jaGFyYWN0ZXJzLm1hcCgoY2hhciwgaSkgPT4ge1xuICAgICAgaWYgKGkgPCBpbmRleCkgcmV0dXJuIGNoYXJcbiAgICAgIGlmIChpID49IGluZGV4ICsgbGVuZ3RoKSByZXR1cm4gY2hhclxuICAgICAgbGV0IHsgbWFya3MgfSA9IGNoYXJcbiAgICAgIG1hcmtzID0gbWFya3MudW5pb24oc2V0KVxuICAgICAgY2hhciA9IGNoYXIuc2V0KCdtYXJrcycsIG1hcmtzKVxuICAgICAgcmV0dXJuIGNoYXJcbiAgICB9KVxuXG4gICAgcmV0dXJuIHRoaXMuc2V0KCdjaGFyYWN0ZXJzJywgY2hhcmFjdGVycylcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXJpdmUgYSBzZXQgb2YgZGVjb3JhdGVkIGNoYXJhY3RlcnMgd2l0aCBgZGVjb3JhdGlvbnNgLlxuICAgKlxuICAgKiBAcGFyYW0ge0xpc3Q8RGVjb3JhdGlvbj59IGRlY29yYXRpb25zXG4gICAqIEByZXR1cm4ge0xpc3Q8Q2hhcmFjdGVyPn1cbiAgICovXG5cbiAgZ2V0RGVjb3JhdGVkQ2hhcmFjdGVycyhkZWNvcmF0aW9ucykge1xuICAgIGxldCBub2RlID0gdGhpc1xuICAgIGNvbnN0IHsga2V5LCBjaGFyYWN0ZXJzIH0gPSBub2RlXG5cbiAgICAvLyBQRVJGOiBFeGl0IGVhcmx5IGlmIHRoZXJlIGFyZSBubyBjaGFyYWN0ZXJzIHRvIGJlIGRlY29yYXRlZC5cbiAgICBpZiAoY2hhcmFjdGVycy5zaXplID09IDApIHJldHVybiBjaGFyYWN0ZXJzXG5cbiAgICBkZWNvcmF0aW9ucy5mb3JFYWNoKChyYW5nZSkgPT4ge1xuICAgICAgY29uc3QgeyBzdGFydEtleSwgZW5kS2V5LCBzdGFydE9mZnNldCwgZW5kT2Zmc2V0LCBtYXJrcyB9ID0gcmFuZ2VcbiAgICAgIGNvbnN0IGhhc1N0YXJ0ID0gc3RhcnRLZXkgPT0ga2V5XG4gICAgICBjb25zdCBoYXNFbmQgPSBlbmRLZXkgPT0ga2V5XG4gICAgICBjb25zdCBpbmRleCA9IGhhc1N0YXJ0ID8gc3RhcnRPZmZzZXQgOiAwXG4gICAgICBjb25zdCBsZW5ndGggPSBoYXNFbmQgPyBlbmRPZmZzZXQgLSBpbmRleCA6IGNoYXJhY3RlcnMuc2l6ZVxuICAgICAgbm9kZSA9IG5vZGUuYWRkTWFya3MoaW5kZXgsIGxlbmd0aCwgbWFya3MpXG4gICAgfSlcblxuICAgIHJldHVybiBub2RlLmNoYXJhY3RlcnNcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIGRlY29yYXRpb25zIGZvciB0aGUgbm9kZSBmcm9tIGEgYHNjaGVtYWAuXG4gICAqXG4gICAqIEBwYXJhbSB7U2NoZW1hfSBzY2hlbWFcbiAgICogQHJldHVybiB7QXJyYXl9XG4gICAqL1xuXG4gIGdldERlY29yYXRpb25zKHNjaGVtYSkge1xuICAgIHJldHVybiBzY2hlbWEuX19nZXREZWNvcmF0aW9ucyh0aGlzKVxuICB9XG5cbiAgLyoqXG4gICAqIERlcml2ZSB0aGUgbGVhdmVzIGZvciBhIGxpc3Qgb2YgYGNoYXJhY3RlcnNgLlxuICAgKlxuICAgKiBAcGFyYW0ge0FycmF5fFZvaWR9IGRlY29yYXRpb25zIChvcHRpb25hbClcbiAgICogQHJldHVybiB7TGlzdDxMZWFmPn1cbiAgICovXG5cbiAgZ2V0TGVhdmVzKGRlY29yYXRpb25zID0gW10pIHtcbiAgICBjb25zdCBjaGFyYWN0ZXJzID0gdGhpcy5nZXREZWNvcmF0ZWRDaGFyYWN0ZXJzKGRlY29yYXRpb25zKVxuICAgIGxldCBsZWF2ZXMgPSBbXVxuXG4gICAgLy8gUEVSRjogY2FjaGUgcHJldmlvdXMgdmFsdWVzIGZvciBmYXN0ZXIgbG9va3VwLlxuICAgIGxldCBwcmV2Q2hhclxuICAgIGxldCBwcmV2TGVhZlxuXG4gICAgLy8gSWYgdGhlcmUgYXJlIG5vIGNoYXJhY3RlcnMsIHJldHVybiBvbmUgZW1wdHkgcmFuZ2UuXG4gICAgaWYgKGNoYXJhY3RlcnMuc2l6ZSA9PSAwKSB7XG4gICAgICBsZWF2ZXMucHVzaCh7fSlcbiAgICB9XG5cbiAgICAvLyBPdGhlcndpc2UsIGxvb3AgdGhlIGNoYXJhY3RlcnMgYW5kIGJ1aWxkIHRoZSBsZWF2ZXMuLi5cbiAgICBlbHNlIHtcbiAgICAgIGNoYXJhY3RlcnMuZm9yRWFjaCgoY2hhciwgaSkgPT4ge1xuICAgICAgICBjb25zdCB7IG1hcmtzLCB0ZXh0IH0gPSBjaGFyXG5cbiAgICAgICAgLy8gVGhlIGZpcnN0IG9uZSBjYW4gYWx3YXlzIGp1c3QgYmUgY3JlYXRlZC5cbiAgICAgICAgaWYgKGkgPT0gMCkge1xuICAgICAgICAgIHByZXZDaGFyID0gY2hhclxuICAgICAgICAgIHByZXZMZWFmID0geyB0ZXh0LCBtYXJrcyB9XG4gICAgICAgICAgbGVhdmVzLnB1c2gocHJldkxlYWYpXG4gICAgICAgICAgcmV0dXJuXG4gICAgICAgIH1cblxuICAgICAgICAvLyBPdGhlcndpc2UsIGNvbXBhcmUgdGhlIGN1cnJlbnQgYW5kIHByZXZpb3VzIG1hcmtzLlxuICAgICAgICBjb25zdCBwcmV2TWFya3MgPSBwcmV2Q2hhci5tYXJrc1xuICAgICAgICBjb25zdCBpc1NhbWUgPSBpcyhtYXJrcywgcHJldk1hcmtzKVxuXG4gICAgICAgIC8vIElmIHRoZSBtYXJrcyBhcmUgdGhlIHNhbWUsIGFkZCB0aGUgdGV4dCB0byB0aGUgcHJldmlvdXMgcmFuZ2UuXG4gICAgICAgIGlmIChpc1NhbWUpIHtcbiAgICAgICAgICBwcmV2Q2hhciA9IGNoYXJcbiAgICAgICAgICBwcmV2TGVhZi50ZXh0ICs9IHRleHRcbiAgICAgICAgICByZXR1cm5cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIE90aGVyd2lzZSwgY3JlYXRlIGEgbmV3IHJhbmdlLlxuICAgICAgICBwcmV2Q2hhciA9IGNoYXJcbiAgICAgICAgcHJldkxlYWYgPSB7IHRleHQsIG1hcmtzIH1cbiAgICAgICAgbGVhdmVzLnB1c2gocHJldkxlYWYpXG4gICAgICB9LCBbXSlcbiAgICB9XG5cbiAgICAvLyBQRVJGOiBjb252ZXJ0IHRoZSBsZWF2ZXMgdG8gaW1tdXRhYmxlIG9iamVjdHMgYWZ0ZXIgaXRlcmF0aW5nLlxuICAgIGxlYXZlcyA9IG5ldyBMaXN0KGxlYXZlcy5tYXAob2JqZWN0ID0+IG5ldyBMZWFmKG9iamVjdCkpKVxuXG4gICAgLy8gUmV0dXJuIHRoZSBsZWF2ZXMuXG4gICAgcmV0dXJuIGxlYXZlc1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBhbGwgb2YgdGhlIG1hcmtzIG9uIHRoZSB0ZXh0LlxuICAgKlxuICAgKiBAcmV0dXJuIHtPcmRlcmVkU2V0PE1hcms+fVxuICAgKi9cblxuICBnZXRNYXJrcygpIHtcbiAgICBjb25zdCBhcnJheSA9IHRoaXMuZ2V0TWFya3NBc0FycmF5KClcbiAgICByZXR1cm4gbmV3IE9yZGVyZWRTZXQoYXJyYXkpXG4gIH1cblxuICAvKipcbiAgICogR2V0IGFsbCBvZiB0aGUgbWFya3Mgb24gdGhlIHRleHQgYXMgYW4gYXJyYXlcbiAgICpcbiAgICogQHJldHVybiB7QXJyYXl9XG4gICAqL1xuXG4gIGdldE1hcmtzQXNBcnJheSgpIHtcbiAgICByZXR1cm4gdGhpcy5jaGFyYWN0ZXJzLnJlZHVjZSgoYXJyYXksIGNoYXIpID0+IHtcbiAgICAgIHJldHVybiBhcnJheS5jb25jYXQoY2hhci5tYXJrcy50b0FycmF5KCkpXG4gICAgfSwgW10pXG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBtYXJrcyBvbiB0aGUgdGV4dCBhdCBgaW5kZXhgLlxuICAgKlxuICAgKiBAcGFyYW0ge051bWJlcn0gaW5kZXhcbiAgICogQHJldHVybiB7U2V0PE1hcms+fVxuICAgKi9cblxuICBnZXRNYXJrc0F0SW5kZXgoaW5kZXgpIHtcbiAgICBpZiAoaW5kZXggPT0gMCkgcmV0dXJuIE1hcmsuY3JlYXRlU2V0KClcbiAgICBjb25zdCB7IGNoYXJhY3RlcnMgfSA9IHRoaXNcbiAgICBjb25zdCBjaGFyID0gY2hhcmFjdGVycy5nZXQoaW5kZXggLSAxKVxuICAgIGlmICghY2hhcikgcmV0dXJuIE1hcmsuY3JlYXRlU2V0KClcbiAgICByZXR1cm4gY2hhci5tYXJrc1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBhIG5vZGUgYnkgYGtleWAsIHRvIHBhcmFsbGVsIG90aGVyIG5vZGVzLlxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30ga2V5XG4gICAqIEByZXR1cm4ge05vZGV8TnVsbH1cbiAgICovXG5cbiAgZ2V0Tm9kZShrZXkpIHtcbiAgICByZXR1cm4gdGhpcy5rZXkgPT0ga2V5XG4gICAgICA/IHRoaXNcbiAgICAgIDogbnVsbFxuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIGlmIHRoZSBub2RlIGhhcyBhIG5vZGUgYnkgYGtleWAsIHRvIHBhcmFsbGVsIG90aGVyIG5vZGVzLlxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30ga2V5XG4gICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAqL1xuXG4gIGhhc05vZGUoa2V5KSB7XG4gICAgcmV0dXJuICEhdGhpcy5nZXROb2RlKGtleSlcbiAgfVxuXG4gIC8qKlxuICAgKiBJbnNlcnQgYHRleHRgIGF0IGBpbmRleGAuXG4gICAqXG4gICAqIEBwYXJhbSB7TnVtYmRlcn0gaW5kZXhcbiAgICogQHBhcmFtIHtTdHJpbmd9IHRleHRcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1hcmtzIChvcHRpb25hbClcbiAgICogQHJldHVybiB7VGV4dH1cbiAgICovXG5cbiAgaW5zZXJ0VGV4dChpbmRleCwgdGV4dCwgbWFya3MpIHtcbiAgICBsZXQgeyBjaGFyYWN0ZXJzIH0gPSB0aGlzXG4gICAgY29uc3QgY2hhcnMgPSBDaGFyYWN0ZXIuY3JlYXRlTGlzdCh0ZXh0LnNwbGl0KCcnKS5tYXAoY2hhciA9PiAoeyB0ZXh0OiBjaGFyLCBtYXJrcyB9KSkpXG5cbiAgICBjaGFyYWN0ZXJzID0gY2hhcmFjdGVycy5zbGljZSgwLCBpbmRleClcbiAgICAgIC5jb25jYXQoY2hhcnMpXG4gICAgICAuY29uY2F0KGNoYXJhY3RlcnMuc2xpY2UoaW5kZXgpKVxuXG4gICAgcmV0dXJuIHRoaXMuc2V0KCdjaGFyYWN0ZXJzJywgY2hhcmFjdGVycylcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWdlbmVyYXRlIHRoZSBub2RlJ3Mga2V5LlxuICAgKlxuICAgKiBAcmV0dXJuIHtUZXh0fVxuICAgKi9cblxuICByZWdlbmVyYXRlS2V5KCkge1xuICAgIGNvbnN0IGtleSA9IGdlbmVyYXRlS2V5KClcbiAgICByZXR1cm4gdGhpcy5zZXQoJ2tleScsIGtleSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmUgYSBgbWFya2AgYXQgYGluZGV4YCBhbmQgYGxlbmd0aGAuXG4gICAqXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBpbmRleFxuICAgKiBAcGFyYW0ge051bWJlcn0gbGVuZ3RoXG4gICAqIEBwYXJhbSB7TWFya30gbWFya1xuICAgKiBAcmV0dXJuIHtUZXh0fVxuICAgKi9cblxuICByZW1vdmVNYXJrKGluZGV4LCBsZW5ndGgsIG1hcmspIHtcbiAgICBjb25zdCBjaGFyYWN0ZXJzID0gdGhpcy5jaGFyYWN0ZXJzLm1hcCgoY2hhciwgaSkgPT4ge1xuICAgICAgaWYgKGkgPCBpbmRleCkgcmV0dXJuIGNoYXJcbiAgICAgIGlmIChpID49IGluZGV4ICsgbGVuZ3RoKSByZXR1cm4gY2hhclxuICAgICAgbGV0IHsgbWFya3MgfSA9IGNoYXJcbiAgICAgIG1hcmtzID0gbWFya3MucmVtb3ZlKG1hcmspXG4gICAgICBjaGFyID0gY2hhci5zZXQoJ21hcmtzJywgbWFya3MpXG4gICAgICByZXR1cm4gY2hhclxuICAgIH0pXG5cbiAgICByZXR1cm4gdGhpcy5zZXQoJ2NoYXJhY3RlcnMnLCBjaGFyYWN0ZXJzKVxuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZSB0ZXh0IGZyb20gdGhlIHRleHQgbm9kZSBhdCBgaW5kZXhgIGZvciBgbGVuZ3RoYC5cbiAgICpcbiAgICogQHBhcmFtIHtOdW1iZXJ9IGluZGV4XG4gICAqIEBwYXJhbSB7TnVtYmVyfSBsZW5ndGhcbiAgICogQHJldHVybiB7VGV4dH1cbiAgICovXG5cbiAgcmVtb3ZlVGV4dChpbmRleCwgbGVuZ3RoKSB7XG4gICAgbGV0IHsgY2hhcmFjdGVycyB9ID0gdGhpc1xuICAgIGNvbnN0IHN0YXJ0ID0gaW5kZXhcbiAgICBjb25zdCBlbmQgPSBpbmRleCArIGxlbmd0aFxuICAgIGNoYXJhY3RlcnMgPSBjaGFyYWN0ZXJzLmZpbHRlck5vdCgoY2hhciwgaSkgPT4gc3RhcnQgPD0gaSAmJiBpIDwgZW5kKVxuICAgIHJldHVybiB0aGlzLnNldCgnY2hhcmFjdGVycycsIGNoYXJhY3RlcnMpXG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIGEgSlNPTiByZXByZXNlbnRhdGlvbiBvZiB0aGUgdGV4dC5cbiAgICpcbiAgICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnNcbiAgICogQHJldHVybiB7T2JqZWN0fVxuICAgKi9cblxuICB0b0pTT04ob3B0aW9ucyA9IHt9KSB7XG4gICAgY29uc3Qgb2JqZWN0ID0ge1xuICAgICAga2luZDogdGhpcy5raW5kLFxuICAgICAgbGVhdmVzOiB0aGlzLmdldExlYXZlcygpLnRvQXJyYXkoKS5tYXAociA9PiByLnRvSlNPTigpKSxcbiAgICB9XG5cbiAgICBpZiAob3B0aW9ucy5wcmVzZXJ2ZUtleXMpIHtcbiAgICAgIG9iamVjdC5rZXkgPSB0aGlzLmtleVxuICAgIH1cblxuICAgIHJldHVybiBvYmplY3RcbiAgfVxuXG4gIC8qKlxuICAgKiBBbGlhcyBgdG9KU2AuXG4gICAqL1xuXG4gIHRvSlMob3B0aW9ucykge1xuICAgIHJldHVybiB0aGlzLnRvSlNPTihvcHRpb25zKVxuICB9XG5cbiAgLyoqXG4gICAqIFVwZGF0ZSBhIGBtYXJrYCBhdCBgaW5kZXhgIGFuZCBgbGVuZ3RoYCB3aXRoIGBwcm9wZXJ0aWVzYC5cbiAgICpcbiAgICogQHBhcmFtIHtOdW1iZXJ9IGluZGV4XG4gICAqIEBwYXJhbSB7TnVtYmVyfSBsZW5ndGhcbiAgICogQHBhcmFtIHtNYXJrfSBtYXJrXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBwcm9wZXJ0aWVzXG4gICAqIEByZXR1cm4ge1RleHR9XG4gICAqL1xuXG4gIHVwZGF0ZU1hcmsoaW5kZXgsIGxlbmd0aCwgbWFyaywgcHJvcGVydGllcykge1xuICAgIGNvbnN0IG5ld01hcmsgPSBtYXJrLm1lcmdlKHByb3BlcnRpZXMpXG5cbiAgICBjb25zdCBjaGFyYWN0ZXJzID0gdGhpcy5jaGFyYWN0ZXJzLm1hcCgoY2hhciwgaSkgPT4ge1xuICAgICAgaWYgKGkgPCBpbmRleCkgcmV0dXJuIGNoYXJcbiAgICAgIGlmIChpID49IGluZGV4ICsgbGVuZ3RoKSByZXR1cm4gY2hhclxuICAgICAgbGV0IHsgbWFya3MgfSA9IGNoYXJcbiAgICAgIGlmICghbWFya3MuaGFzKG1hcmspKSByZXR1cm4gY2hhclxuICAgICAgbWFya3MgPSBtYXJrcy5yZW1vdmUobWFyaylcbiAgICAgIG1hcmtzID0gbWFya3MuYWRkKG5ld01hcmspXG4gICAgICBjaGFyID0gY2hhci5zZXQoJ21hcmtzJywgbWFya3MpXG4gICAgICByZXR1cm4gY2hhclxuICAgIH0pXG5cbiAgICByZXR1cm4gdGhpcy5zZXQoJ2NoYXJhY3RlcnMnLCBjaGFyYWN0ZXJzKVxuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlIHRoZSB0ZXh0IG5vZGUgYWdhaW5zdCBhIGBzY2hlbWFgLlxuICAgKlxuICAgKiBAcGFyYW0ge1NjaGVtYX0gc2NoZW1hXG4gICAqIEByZXR1cm4ge09iamVjdHxWb2lkfVxuICAgKi9cblxuICB2YWxpZGF0ZShzY2hlbWEpIHtcbiAgICByZXR1cm4gc2NoZW1hLnZhbGlkYXRlTm9kZSh0aGlzKVxuICB9XG5cbn1cblxuLyoqXG4gKiBBdHRhY2ggYSBwc2V1ZG8tc3ltYm9sIGZvciB0eXBlIGNoZWNraW5nLlxuICovXG5cblRleHQucHJvdG90eXBlW01PREVMX1RZUEVTLlRFWFRdID0gdHJ1ZVxuXG4vKipcbiAqIE1lbW9pemUgcmVhZCBtZXRob2RzLlxuICovXG5cbm1lbW9pemUoVGV4dC5wcm90b3R5cGUsIFtcbiAgJ2dldE1hcmtzJyxcbiAgJ2dldE1hcmtzQXNBcnJheScsXG5dLCB7XG4gIHRha2VzQXJndW1lbnRzOiBmYWxzZSxcbn0pXG5cbm1lbW9pemUoVGV4dC5wcm90b3R5cGUsIFtcbiAgJ2dldERlY29yYXRlZENoYXJhY3RlcnMnLFxuICAnZ2V0RGVjb3JhdGlvbnMnLFxuICAnZ2V0TGVhdmVzJyxcbiAgJ2dldE1hcmtzQXRJbmRleCcsXG4gICd2YWxpZGF0ZSdcbl0sIHtcbiAgdGFrZXNBcmd1bWVudHM6IHRydWUsXG59KVxuXG4vKipcbiAqIEV4cG9ydC5cbiAqXG4gKiBAdHlwZSB7VGV4dH1cbiAqL1xuXG5leHBvcnQgZGVmYXVsdCBUZXh0XG4iXX0=