25 lines
167 KiB
JavaScript
25 lines
167 KiB
JavaScript
"use strict";
|
|
/*
|
|
* ATTENTION: An "eval-source-map" devtool has been used.
|
|
* This devtool is neither made for production nor for readable output files.
|
|
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
|
|
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
|
|
* or disable the default devtool with "devtool: false".
|
|
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
|
|
*/
|
|
exports.id = "vendor-chunks/@lexical+list@0.41.0";
|
|
exports.ids = ["vendor-chunks/@lexical+list@0.41.0"];
|
|
exports.modules = {
|
|
|
|
/***/ "(rsc)/./node_modules/.pnpm/@lexical+list@0.41.0/node_modules/@lexical/list/LexicalList.dev.mjs":
|
|
/*!************************************************************************************************!*\
|
|
!*** ./node_modules/.pnpm/@lexical+list@0.41.0/node_modules/@lexical/list/LexicalList.dev.mjs ***!
|
|
\************************************************************************************************/
|
|
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
|
|
|
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ $createListItemNode: () => (/* binding */ $createListItemNode),\n/* harmony export */ $createListNode: () => (/* binding */ $createListNode),\n/* harmony export */ $getListDepth: () => (/* binding */ $getListDepth),\n/* harmony export */ $handleListInsertParagraph: () => (/* binding */ $handleListInsertParagraph),\n/* harmony export */ $insertList: () => (/* binding */ $insertList),\n/* harmony export */ $isListItemNode: () => (/* binding */ $isListItemNode),\n/* harmony export */ $isListNode: () => (/* binding */ $isListNode),\n/* harmony export */ $removeList: () => (/* binding */ $removeList),\n/* harmony export */ CheckListExtension: () => (/* binding */ CheckListExtension),\n/* harmony export */ INSERT_CHECK_LIST_COMMAND: () => (/* binding */ INSERT_CHECK_LIST_COMMAND),\n/* harmony export */ INSERT_ORDERED_LIST_COMMAND: () => (/* binding */ INSERT_ORDERED_LIST_COMMAND),\n/* harmony export */ INSERT_UNORDERED_LIST_COMMAND: () => (/* binding */ INSERT_UNORDERED_LIST_COMMAND),\n/* harmony export */ ListExtension: () => (/* binding */ ListExtension),\n/* harmony export */ ListItemNode: () => (/* binding */ ListItemNode),\n/* harmony export */ ListNode: () => (/* binding */ ListNode),\n/* harmony export */ REMOVE_LIST_COMMAND: () => (/* binding */ REMOVE_LIST_COMMAND),\n/* harmony export */ UPDATE_LIST_START_COMMAND: () => (/* binding */ UPDATE_LIST_START_COMMAND),\n/* harmony export */ insertList: () => (/* binding */ insertList),\n/* harmony export */ registerCheckList: () => (/* binding */ registerCheckList),\n/* harmony export */ registerList: () => (/* binding */ registerList),\n/* harmony export */ registerListStrictIndentTransform: () => (/* binding */ registerListStrictIndentTransform),\n/* harmony export */ removeList: () => (/* binding */ removeList)\n/* harmony export */ });\n/* harmony import */ var _lexical_extension__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @lexical/extension */ \"(rsc)/./node_modules/.pnpm/@lexical+extension@0.41.0/node_modules/@lexical/extension/LexicalExtension.dev.mjs\");\n/* harmony import */ var _lexical_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @lexical/utils */ \"(rsc)/./node_modules/.pnpm/@lexical+utils@0.41.0/node_modules/@lexical/utils/LexicalUtils.dev.mjs\");\n/* harmony import */ var lexical__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! lexical */ \"(rsc)/./node_modules/.pnpm/lexical@0.41.0/node_modules/lexical/Lexical.dev.mjs\");\n/* harmony import */ var _lexical_selection__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @lexical/selection */ \"(rsc)/./node_modules/.pnpm/@lexical+selection@0.41.0/node_modules/@lexical/selection/LexicalSelection.dev.mjs\");\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\n\n\n\n\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\n// Do not require this module directly! Use normal `invariant` calls.\n\nfunction formatDevErrorMessage(message) {\n throw new Error(message);\n}\n\n/**\n * Checks the depth of listNode from the root node.\n * @param listNode - The ListNode to be checked.\n * @returns The depth of the ListNode.\n */\nfunction $getListDepth(listNode) {\n let depth = 1;\n let parent = listNode.getParent();\n while (parent != null) {\n if ($isListItemNode(parent)) {\n const parentList = parent.getParent();\n if ($isListNode(parentList)) {\n depth++;\n parent = parentList.getParent();\n continue;\n }\n {\n formatDevErrorMessage(`A ListItemNode must have a ListNode for a parent.`);\n }\n }\n return depth;\n }\n return depth;\n}\n\n/**\n * Finds the nearest ancestral ListNode and returns it, throws an invariant if listItem is not a ListItemNode.\n * @param listItem - The node to be checked.\n * @returns The ListNode found.\n */\nfunction $getTopListNode(listItem) {\n let list = listItem.getParent();\n if (!$isListNode(list)) {\n {\n formatDevErrorMessage(`A ListItemNode must have a ListNode for a parent.`);\n }\n }\n let parent = list;\n while (parent !== null) {\n parent = parent.getParent();\n if ($isListNode(parent)) {\n list = parent;\n }\n }\n return list;\n}\n\n/**\n * A recursive Depth-First Search (Postorder Traversal) that finds all of a node's children\n * that are of type ListItemNode and returns them in an array.\n * @param node - The ListNode to start the search.\n * @returns An array containing all nodes of type ListItemNode found.\n */\n// This should probably be $getAllChildrenOfType\nfunction $getAllListItems(node) {\n let listItemNodes = [];\n const listChildren = node.getChildren().filter($isListItemNode);\n for (let i = 0; i < listChildren.length; i++) {\n const listItemNode = listChildren[i];\n const firstChild = listItemNode.getFirstChild();\n if ($isListNode(firstChild)) {\n listItemNodes = listItemNodes.concat($getAllListItems(firstChild));\n } else {\n listItemNodes.push(listItemNode);\n }\n }\n return listItemNodes;\n}\n\n/**\n * Checks to see if the passed node is a ListItemNode and has a ListNode as a child.\n * @param node - The node to be checked.\n * @returns true if the node is a ListItemNode and has a ListNode child, false otherwise.\n */\nfunction isNestedListNode(node) {\n return $isListItemNode(node) && $isListNode(node.getFirstChild());\n}\n\n/**\n * Takes a deeply nested ListNode or ListItemNode and traverses up the branch to delete the first\n * ancestral ListNode (which could be the root ListNode) or ListItemNode with siblings, essentially\n * bringing the deeply nested node up the branch once. Would remove sublist if it has siblings.\n * Should not break ListItem -> List -> ListItem chain as empty List/ItemNodes should be removed on .remove().\n * @param sublist - The nested ListNode or ListItemNode to be brought up the branch.\n */\nfunction $removeHighestEmptyListParent(sublist) {\n // Nodes may be repeatedly indented, to create deeply nested lists that each\n // contain just one bullet.\n // Our goal is to remove these (empty) deeply nested lists. The easiest\n // way to do that is crawl back up the tree until we find a node that has siblings\n // (e.g. is actually part of the list contents) and delete that, or delete\n // the root of the list (if no list nodes have siblings.)\n let emptyListPtr = sublist;\n while (emptyListPtr.getNextSibling() == null && emptyListPtr.getPreviousSibling() == null) {\n const parent = emptyListPtr.getParent();\n if (parent == null || !($isListItemNode(parent) || $isListNode(parent))) {\n break;\n }\n emptyListPtr = parent;\n }\n emptyListPtr.remove();\n}\n\n/**\n * Wraps a node into a ListItemNode.\n * @param node - The node to be wrapped into a ListItemNode\n * @returns The ListItemNode which the passed node is wrapped in.\n */\nfunction $wrapInListItem(node) {\n const listItemWrapper = $createListItemNode();\n return listItemWrapper.append(node);\n}\n\n/**\n * Calculates the start value for a new list created by splitting an existing list.\n */\nfunction $getNewListStart(list, listItem) {\n return list.getStart() + listItem.getIndexWithinParent();\n}\n\nfunction $isSelectingEmptyListItem(anchorNode, nodes) {\n return $isListItemNode(anchorNode) && (nodes.length === 0 || nodes.length === 1 && anchorNode.is(nodes[0]) && anchorNode.getChildrenSize() === 0);\n}\n\n/**\n * Inserts a new ListNode. If the selection's anchor node is an empty ListItemNode and is a child of\n * the root/shadow root, it will replace the ListItemNode with a ListNode and the old ListItemNode.\n * Otherwise it will replace its parent with a new ListNode and re-insert the ListItemNode and any previous children.\n * If the selection's anchor node is not an empty ListItemNode, it will add a new ListNode or merge an existing ListNode,\n * unless the the node is a leaf node, in which case it will attempt to find a ListNode up the branch and replace it with\n * a new ListNode, or create a new ListNode at the nearest root/shadow root.\n * @param listType - The type of list, \"number\" | \"bullet\" | \"check\".\n */\nfunction $insertList(listType) {\n const selection = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$getSelection)();\n if (selection !== null) {\n let nodes = selection.getNodes();\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isRangeSelection)(selection)) {\n const anchorAndFocus = selection.getStartEndPoints();\n if (!(anchorAndFocus !== null)) {\n formatDevErrorMessage(`insertList: anchor should be defined`);\n }\n const [anchor] = anchorAndFocus;\n const anchorNode = anchor.getNode();\n const anchorNodeParent = anchorNode.getParent();\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isRootOrShadowRoot)(anchorNode)) {\n const firstChild = anchorNode.getFirstChild();\n if (firstChild) {\n nodes = firstChild.selectStart().getNodes();\n } else {\n const paragraph = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$createParagraphNode)();\n anchorNode.append(paragraph);\n nodes = paragraph.select().getNodes();\n }\n } else if ($isSelectingEmptyListItem(anchorNode, nodes)) {\n const list = $createListNode(listType);\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isRootOrShadowRoot)(anchorNodeParent)) {\n anchorNode.replace(list);\n const listItem = $createListItemNode();\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isElementNode)(anchorNode)) {\n listItem.setFormat(anchorNode.getFormatType());\n listItem.setIndent(anchorNode.getIndent());\n }\n list.append(listItem);\n } else if ($isListItemNode(anchorNode)) {\n const parent = anchorNode.getParentOrThrow();\n append(list, parent.getChildren());\n parent.replace(list);\n }\n return;\n }\n }\n const handled = new Set();\n for (let i = 0; i < nodes.length; i++) {\n const node = nodes[i];\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isElementNode)(node) && node.isEmpty() && !$isListItemNode(node) && !handled.has(node.getKey())) {\n $createListOrMerge(node, listType);\n continue;\n }\n let parent = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isLeafNode)(node) ? node.getParent() : $isListItemNode(node) && node.isEmpty() ? node : null;\n while (parent != null) {\n const parentKey = parent.getKey();\n if ($isListNode(parent)) {\n if (!handled.has(parentKey)) {\n const newListNode = $createListNode(listType);\n append(newListNode, parent.getChildren());\n parent.replace(newListNode);\n handled.add(parentKey);\n }\n break;\n } else {\n const nextParent = parent.getParent();\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isRootOrShadowRoot)(nextParent) && !handled.has(parentKey)) {\n handled.add(parentKey);\n $createListOrMerge(parent, listType);\n break;\n }\n parent = nextParent;\n }\n }\n }\n }\n}\nfunction append(node, nodesToAppend) {\n node.splice(node.getChildrenSize(), 0, nodesToAppend);\n}\nfunction $createListOrMerge(node, listType) {\n if ($isListNode(node)) {\n return node;\n }\n const previousSibling = node.getPreviousSibling();\n const nextSibling = node.getNextSibling();\n const listItem = $createListItemNode();\n append(listItem, node.getChildren());\n let targetList;\n if ($isListNode(previousSibling) && listType === previousSibling.getListType()) {\n previousSibling.append(listItem);\n // if the same type of list is on both sides, merge them.\n if ($isListNode(nextSibling) && listType === nextSibling.getListType()) {\n append(previousSibling, nextSibling.getChildren());\n nextSibling.remove();\n }\n targetList = previousSibling;\n } else if ($isListNode(nextSibling) && listType === nextSibling.getListType()) {\n nextSibling.getFirstChildOrThrow().insertBefore(listItem);\n targetList = nextSibling;\n } else {\n const list = $createListNode(listType);\n list.append(listItem);\n node.replace(list);\n targetList = list;\n }\n // listItem needs to be attached to root prior to setting indent\n listItem.setFormat(node.getFormatType());\n listItem.setIndent(node.getIndent());\n\n // Preserve element-anchored selections by updating them to anchor to the listItem instead of the listNode.\n const selection = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$getSelection)();\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isRangeSelection)(selection)) {\n if (targetList.getKey() === selection.anchor.key) {\n selection.anchor.set(listItem.getKey(), selection.anchor.offset, 'element');\n }\n if (targetList.getKey() === selection.focus.key) {\n selection.focus.set(listItem.getKey(), selection.focus.offset, 'element');\n }\n }\n node.remove();\n return targetList;\n}\n\n/**\n * A recursive function that goes through each list and their children, including nested lists,\n * appending list2 children after list1 children and updating ListItemNode values.\n * @param list1 - The first list to be merged.\n * @param list2 - The second list to be merged.\n */\nfunction mergeLists(list1, list2) {\n const listItem1 = list1.getLastChild();\n const listItem2 = list2.getFirstChild();\n if (listItem1 && listItem2 && isNestedListNode(listItem1) && isNestedListNode(listItem2)) {\n mergeLists(listItem1.getFirstChild(), listItem2.getFirstChild());\n listItem2.remove();\n }\n const toMerge = list2.getChildren();\n if (toMerge.length > 0) {\n list1.append(...toMerge);\n }\n list2.remove();\n}\n\n/**\n * Searches for the nearest ancestral ListNode and removes it. If selection is an empty ListItemNode\n * it will remove the whole list, including the ListItemNode. For each ListItemNode in the ListNode,\n * removeList will also generate new ParagraphNodes in the removed ListNode's place. Any child node\n * inside a ListItemNode will be appended to the new ParagraphNodes.\n */\nfunction $removeList() {\n const selection = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$getSelection)();\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isRangeSelection)(selection)) {\n const listNodes = new Set();\n const nodes = selection.getNodes();\n const anchorNode = selection.anchor.getNode();\n if ($isSelectingEmptyListItem(anchorNode, nodes)) {\n listNodes.add($getTopListNode(anchorNode));\n } else {\n for (let i = 0; i < nodes.length; i++) {\n const node = nodes[i];\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isLeafNode)(node)) {\n const listItemNode = (0,_lexical_utils__WEBPACK_IMPORTED_MODULE_1__.$getNearestNodeOfType)(node, ListItemNode);\n if (listItemNode != null) {\n listNodes.add($getTopListNode(listItemNode));\n }\n }\n }\n }\n for (const listNode of listNodes) {\n let insertionPoint = listNode;\n const listItems = $getAllListItems(listNode);\n for (const listItemNode of listItems) {\n const paragraph = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$createParagraphNode)().setTextStyle(selection.style).setTextFormat(selection.format);\n append(paragraph, listItemNode.getChildren());\n insertionPoint.insertAfter(paragraph);\n insertionPoint = paragraph;\n\n // When the anchor and focus fall on the textNode\n // we don't have to change the selection because the textNode will be appended to\n // the newly generated paragraph.\n // When selection is in empty nested list item, selection is actually on the listItemNode.\n // When the corresponding listItemNode is deleted and replaced by the newly generated paragraph\n // we should manually set the selection's focus and anchor to the newly generated paragraph.\n if (listItemNode.__key === selection.anchor.key) {\n (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$setPointFromCaret)(selection.anchor, (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$normalizeCaret)((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$getChildCaret)(paragraph, 'next')));\n }\n if (listItemNode.__key === selection.focus.key) {\n (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$setPointFromCaret)(selection.focus, (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$normalizeCaret)((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$getChildCaret)(paragraph, 'next')));\n }\n listItemNode.remove();\n }\n listNode.remove();\n }\n }\n}\n\n/**\n * Takes the value of a child ListItemNode and makes it the value the ListItemNode\n * should be if it isn't already. Also ensures that checked is undefined if the\n * parent does not have a list type of 'check'.\n * @param list - The list whose children are updated.\n */\nfunction updateChildrenListItemValue(list) {\n const isNotChecklist = list.getListType() !== 'check';\n let value = list.getStart();\n for (const child of list.getChildren()) {\n if ($isListItemNode(child)) {\n if (child.getValue() !== value) {\n child.setValue(value);\n }\n if (isNotChecklist && child.getLatest().__checked != null) {\n child.setChecked(undefined);\n }\n if (!$isListNode(child.getFirstChild())) {\n value++;\n }\n }\n }\n}\n\n/**\n * Merge the next sibling list if same type.\n * <ul> will merge with <ul>, but NOT <ul> with <ol>.\n * @param list - The list whose next sibling should be potentially merged\n */\nfunction mergeNextSiblingListIfSameType(list) {\n const nextSibling = list.getNextSibling();\n if ($isListNode(nextSibling) && list.getListType() === nextSibling.getListType()) {\n mergeLists(list, nextSibling);\n }\n}\n\n/**\n * Adds an empty ListNode/ListItemNode chain at listItemNode, so as to\n * create an indent effect. Won't indent ListItemNodes that have a ListNode as\n * a child, but does merge sibling ListItemNodes if one has a nested ListNode.\n * @param listItemNode - The ListItemNode to be indented.\n */\nfunction $handleIndent(listItemNode) {\n // go through each node and decide where to move it.\n const removed = new Set();\n if (isNestedListNode(listItemNode) || removed.has(listItemNode.getKey())) {\n return;\n }\n const parent = listItemNode.getParent();\n\n // We can cast both of the below `isNestedListNode` only returns a boolean type instead of a user-defined type guards\n const nextSibling = listItemNode.getNextSibling();\n const previousSibling = listItemNode.getPreviousSibling();\n // if there are nested lists on either side, merge them all together.\n\n if (isNestedListNode(nextSibling) && isNestedListNode(previousSibling)) {\n const innerList = previousSibling.getFirstChild();\n if ($isListNode(innerList)) {\n innerList.append(listItemNode);\n const nextInnerList = nextSibling.getFirstChild();\n if ($isListNode(nextInnerList)) {\n const children = nextInnerList.getChildren();\n append(innerList, children);\n nextSibling.remove();\n removed.add(nextSibling.getKey());\n }\n }\n } else if (isNestedListNode(nextSibling)) {\n // if the ListItemNode is next to a nested ListNode, merge them\n const innerList = nextSibling.getFirstChild();\n if ($isListNode(innerList)) {\n const firstChild = innerList.getFirstChild();\n if (firstChild !== null) {\n firstChild.insertBefore(listItemNode);\n }\n }\n } else if (isNestedListNode(previousSibling)) {\n const innerList = previousSibling.getFirstChild();\n if ($isListNode(innerList)) {\n innerList.append(listItemNode);\n }\n } else {\n // otherwise, we need to create a new nested ListNode\n\n if ($isListNode(parent)) {\n const newListItem = $createListItemNode().setTextFormat(listItemNode.getTextFormat()).setTextStyle(listItemNode.getTextStyle());\n const newList = $createListNode(parent.getListType()).setTextFormat(parent.getTextFormat()).setTextStyle(parent.getTextStyle());\n newListItem.append(newList);\n newList.append(listItemNode);\n if (previousSibling) {\n previousSibling.insertAfter(newListItem);\n } else if (nextSibling) {\n nextSibling.insertBefore(newListItem);\n } else {\n parent.append(newListItem);\n }\n }\n }\n}\n\n/**\n * Removes an indent by removing an empty ListNode/ListItemNode chain. An indented ListItemNode\n * has a great grandparent node of type ListNode, which is where the ListItemNode will reside\n * within as a child.\n * @param listItemNode - The ListItemNode to remove the indent (outdent).\n */\nfunction $handleOutdent(listItemNode) {\n // go through each node and decide where to move it.\n\n if (isNestedListNode(listItemNode)) {\n return;\n }\n const parentList = listItemNode.getParent();\n const grandparentListItem = parentList ? parentList.getParent() : undefined;\n const greatGrandparentList = grandparentListItem ? grandparentListItem.getParent() : undefined;\n // If it doesn't have these ancestors, it's not indented.\n\n if ($isListNode(greatGrandparentList) && $isListItemNode(grandparentListItem) && $isListNode(parentList)) {\n // if it's the first child in it's parent list, insert it into the\n // great grandparent list before the grandparent\n const firstChild = parentList ? parentList.getFirstChild() : undefined;\n const lastChild = parentList ? parentList.getLastChild() : undefined;\n if (listItemNode.is(firstChild)) {\n grandparentListItem.insertBefore(listItemNode);\n if (parentList.isEmpty()) {\n grandparentListItem.remove();\n }\n // if it's the last child in it's parent list, insert it into the\n // great grandparent list after the grandparent.\n } else if (listItemNode.is(lastChild)) {\n grandparentListItem.insertAfter(listItemNode);\n if (parentList.isEmpty()) {\n grandparentListItem.remove();\n }\n } else {\n // otherwise, we need to split the siblings into two new nested lists\n const listType = parentList.getListType();\n const previousSiblingsListItem = $createListItemNode();\n const previousSiblingsList = $createListNode(listType);\n previousSiblingsListItem.append(previousSiblingsList);\n listItemNode.getPreviousSiblings().forEach(sibling => previousSiblingsList.append(sibling));\n const nextSiblingsListItem = $createListItemNode();\n const nextSiblingsList = $createListNode(listType);\n nextSiblingsListItem.append(nextSiblingsList);\n append(nextSiblingsList, listItemNode.getNextSiblings());\n // put the sibling nested lists on either side of the grandparent list item in the great grandparent.\n grandparentListItem.insertBefore(previousSiblingsListItem);\n grandparentListItem.insertAfter(nextSiblingsListItem);\n // replace the grandparent list item (now between the siblings) with the outdented list item.\n grandparentListItem.replace(listItemNode);\n }\n }\n}\n\n/**\n * Attempts to insert a ParagraphNode at selection and selects the new node. The selection must contain a ListItemNode\n * or a node that does not already contain text. If its grandparent is the root/shadow root, it will get the ListNode\n * (which should be the parent node) and insert the ParagraphNode as a sibling to the ListNode. If the ListNode is\n * nested in a ListItemNode instead, it will add the ParagraphNode after the grandparent ListItemNode.\n * Throws an invariant if the selection is not a child of a ListNode.\n * @returns true if a ParagraphNode was inserted successfully, false if there is no selection\n * or the selection does not contain a ListItemNode or the node already holds text.\n */\nfunction $handleListInsertParagraph(restoreNumbering = false) {\n const selection = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$getSelection)();\n if (!(0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isRangeSelection)(selection) || !selection.isCollapsed()) {\n return false;\n }\n // Only run this code on empty list items (including whitespace-only)\n const anchor = selection.anchor.getNode();\n let listItem = null;\n if ($isListItemNode(anchor) && anchor.getChildrenSize() === 0) {\n // Truly empty list item (element selection)\n listItem = anchor;\n } else if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isTextNode)(anchor)) {\n // Check if the entire list item contains only whitespace text nodes\n const parentListItem = anchor.getParent();\n if ($isListItemNode(parentListItem) && parentListItem.getChildren().every(node => (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isTextNode)(node) && node.getTextContent().trim() === '')) {\n listItem = parentListItem;\n }\n }\n if (listItem === null) {\n return false;\n }\n const topListNode = $getTopListNode(listItem);\n const parent = listItem.getParent();\n if (!$isListNode(parent)) {\n formatDevErrorMessage(`A ListItemNode must have a ListNode for a parent.`);\n }\n const grandparent = parent.getParent();\n let replacementNode;\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isRootOrShadowRoot)(grandparent)) {\n replacementNode = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$createParagraphNode)();\n topListNode.insertAfter(replacementNode);\n } else if ($isListItemNode(grandparent)) {\n replacementNode = $createListItemNode();\n grandparent.insertAfter(replacementNode);\n } else {\n return false;\n }\n replacementNode.setTextStyle(selection.style).setTextFormat(selection.format).select();\n const nextSiblings = listItem.getNextSiblings();\n if (nextSiblings.length > 0) {\n const newStart = restoreNumbering ? $getNewListStart(parent, listItem) : 1;\n const newList = $createListNode(parent.getListType(), newStart);\n if ($isListItemNode(replacementNode)) {\n const newListItem = $createListItemNode();\n newListItem.append(newList);\n replacementNode.insertAfter(newListItem);\n } else {\n replacementNode.insertAfter(newList);\n }\n newList.append(...nextSiblings);\n }\n\n // Don't leave hanging nested empty lists\n $removeHighestEmptyListParent(listItem);\n return true;\n}\n\nfunction applyMarkerStyles(dom, node, prevNode) {\n const styles = (0,_lexical_selection__WEBPACK_IMPORTED_MODULE_2__.getStyleObjectFromCSS)(node.__textStyle);\n for (const k in styles) {\n dom.style.setProperty(`--listitem-marker-${k}`, styles[k]);\n }\n if (prevNode) {\n for (const k in (0,_lexical_selection__WEBPACK_IMPORTED_MODULE_2__.getStyleObjectFromCSS)(prevNode.__textStyle)) {\n if (!(k in styles)) {\n dom.style.removeProperty(`--listitem-marker-${k}`);\n }\n }\n }\n}\n\n/** @noInheritDoc */\nclass ListItemNode extends lexical__WEBPACK_IMPORTED_MODULE_0__.ElementNode {\n /** @internal */\n __value;\n /** @internal */\n __checked;\n\n /** @internal */\n $config() {\n return this.config('listitem', {\n $transform: node => {\n if (node.__checked == null) {\n return;\n }\n const parent = node.getParent();\n if ($isListNode(parent)) {\n if (parent.getListType() !== 'check' && node.getChecked() != null) {\n node.setChecked(undefined);\n }\n }\n },\n extends: lexical__WEBPACK_IMPORTED_MODULE_0__.ElementNode,\n importDOM: (0,lexical__WEBPACK_IMPORTED_MODULE_0__.buildImportMap)({\n li: () => ({\n conversion: $convertListItemElement,\n priority: 0\n })\n })\n });\n }\n constructor(value = 1, checked = undefined, key) {\n super(key);\n this.__value = value === undefined ? 1 : value;\n this.__checked = checked;\n }\n afterCloneFrom(prevNode) {\n super.afterCloneFrom(prevNode);\n this.__value = prevNode.__value;\n this.__checked = prevNode.__checked;\n }\n createDOM(config) {\n const element = document.createElement('li');\n this.updateListItemDOM(null, element, config);\n return element;\n }\n updateListItemDOM(prevNode, dom, config) {\n updateListItemChecked(dom, this, prevNode);\n dom.value = this.__value;\n $setListItemThemeClassNames(dom, config.theme, this);\n const prevStyle = prevNode ? prevNode.__style : '';\n const nextStyle = this.__style;\n if (prevStyle !== nextStyle) {\n if (nextStyle === '') {\n dom.removeAttribute('style');\n } else {\n dom.style.cssText = nextStyle;\n }\n }\n applyMarkerStyles(dom, this, prevNode);\n }\n updateDOM(prevNode, dom, config) {\n // @ts-expect-error - this is always HTMLListItemElement\n const element = dom;\n this.updateListItemDOM(prevNode, element, config);\n return false;\n }\n updateFromJSON(serializedNode) {\n return super.updateFromJSON(serializedNode).setValue(serializedNode.value).setChecked(serializedNode.checked);\n }\n exportDOM(editor) {\n const element = this.createDOM(editor._config);\n const formatType = this.getFormatType();\n if (formatType) {\n element.style.textAlign = formatType;\n }\n const direction = this.getDirection();\n if (direction) {\n element.dir = direction;\n }\n return {\n element\n };\n }\n exportJSON() {\n return {\n ...super.exportJSON(),\n checked: this.getChecked(),\n value: this.getValue()\n };\n }\n append(...nodes) {\n for (let i = 0; i < nodes.length; i++) {\n const node = nodes[i];\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isElementNode)(node) && this.canMergeWith(node)) {\n const children = node.getChildren();\n this.append(...children);\n node.remove();\n } else {\n super.append(node);\n }\n }\n return this;\n }\n replace(replaceWithNode, includeChildren) {\n if ($isListItemNode(replaceWithNode)) {\n return super.replace(replaceWithNode);\n }\n this.setIndent(0);\n const list = this.getParentOrThrow();\n if (!$isListNode(list)) {\n return replaceWithNode;\n }\n if (list.__first === this.getKey()) {\n list.insertBefore(replaceWithNode);\n } else if (list.__last === this.getKey()) {\n list.insertAfter(replaceWithNode);\n } else {\n // Split the list\n const newList = $createListNode(list.getListType());\n let nextSibling = this.getNextSibling();\n while (nextSibling) {\n const nodeToAppend = nextSibling;\n nextSibling = nextSibling.getNextSibling();\n newList.append(nodeToAppend);\n }\n list.insertAfter(replaceWithNode);\n replaceWithNode.insertAfter(newList);\n }\n if (includeChildren) {\n if (!(0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isElementNode)(replaceWithNode)) {\n formatDevErrorMessage(`includeChildren should only be true for ElementNodes`);\n }\n this.getChildren().forEach(child => {\n replaceWithNode.append(child);\n });\n }\n this.remove();\n if (list.getChildrenSize() === 0) {\n list.remove();\n }\n return replaceWithNode;\n }\n insertAfter(node, restoreSelection = true) {\n const listNode = this.getParentOrThrow();\n if (!$isListNode(listNode)) {\n {\n formatDevErrorMessage(`insertAfter: list node is not parent of list item node`);\n }\n }\n if ($isListItemNode(node)) {\n return super.insertAfter(node, restoreSelection);\n }\n const siblings = this.getNextSiblings();\n\n // Split the lists and insert the node in between them\n listNode.insertAfter(node, restoreSelection);\n if (siblings.length !== 0) {\n const newListNode = $createListNode(listNode.getListType());\n siblings.forEach(sibling => newListNode.append(sibling));\n node.insertAfter(newListNode, restoreSelection);\n }\n return node;\n }\n remove(preserveEmptyParent) {\n const prevSibling = this.getPreviousSibling();\n const nextSibling = this.getNextSibling();\n super.remove(preserveEmptyParent);\n if (prevSibling && nextSibling && isNestedListNode(prevSibling) && isNestedListNode(nextSibling)) {\n mergeLists(prevSibling.getFirstChild(), nextSibling.getFirstChild());\n nextSibling.remove();\n }\n }\n insertNewAfter(_, restoreSelection = true) {\n const newElement = $createListItemNode().updateFromJSON(this.exportJSON()).setChecked(this.getChecked() ? false : undefined);\n this.insertAfter(newElement, restoreSelection);\n return newElement;\n }\n collapseAtStart(selection) {\n const paragraph = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$createParagraphNode)();\n const children = this.getChildren();\n children.forEach(child => paragraph.append(child));\n const listNode = this.getParentOrThrow();\n const listNodeParent = listNode.getParentOrThrow();\n const isIndented = $isListItemNode(listNodeParent);\n if (listNode.getChildrenSize() === 1) {\n if (isIndented) {\n // if the list node is nested, we just want to remove it,\n // effectively unindenting it.\n listNode.remove();\n listNodeParent.select();\n } else {\n listNode.insertBefore(paragraph);\n listNode.remove();\n // If we have selection on the list item, we'll need to move it\n // to the paragraph\n const anchor = selection.anchor;\n const focus = selection.focus;\n const key = paragraph.getKey();\n if (anchor.type === 'element' && anchor.getNode().is(this)) {\n anchor.set(key, anchor.offset, 'element');\n }\n if (focus.type === 'element' && focus.getNode().is(this)) {\n focus.set(key, focus.offset, 'element');\n }\n }\n } else {\n listNode.insertBefore(paragraph);\n this.remove();\n }\n return true;\n }\n getValue() {\n const self = this.getLatest();\n return self.__value;\n }\n setValue(value) {\n const self = this.getWritable();\n self.__value = value;\n return self;\n }\n getChecked() {\n const self = this.getLatest();\n let listType;\n const parent = this.getParent();\n if ($isListNode(parent)) {\n listType = parent.getListType();\n }\n return listType === 'check' ? Boolean(self.__checked) : undefined;\n }\n setChecked(checked) {\n const self = this.getWritable();\n self.__checked = checked;\n return self;\n }\n toggleChecked() {\n const self = this.getWritable();\n return self.setChecked(!self.__checked);\n }\n getIndent() {\n // If we don't have a parent, we are likely serializing\n const parent = this.getParent();\n if (parent === null || !this.isAttached()) {\n return this.getLatest().__indent;\n }\n // ListItemNode should always have a ListNode for a parent.\n let listNodeParent = parent.getParentOrThrow();\n let indentLevel = 0;\n while ($isListItemNode(listNodeParent)) {\n listNodeParent = listNodeParent.getParentOrThrow().getParentOrThrow();\n indentLevel++;\n }\n return indentLevel;\n }\n setIndent(indent) {\n if (!(typeof indent === 'number')) {\n formatDevErrorMessage(`Invalid indent value.`);\n }\n indent = Math.floor(indent);\n if (!(indent >= 0)) {\n formatDevErrorMessage(`Indent value must be non-negative.`);\n }\n let currentIndent = this.getIndent();\n while (currentIndent !== indent) {\n if (currentIndent < indent) {\n $handleIndent(this);\n currentIndent++;\n } else {\n $handleOutdent(this);\n currentIndent--;\n }\n }\n return this;\n }\n\n /** @deprecated @internal */\n canInsertAfter(node) {\n return $isListItemNode(node);\n }\n\n /** @deprecated @internal */\n canReplaceWith(replacement) {\n return $isListItemNode(replacement);\n }\n canMergeWith(node) {\n return $isListItemNode(node) || (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isParagraphNode)(node);\n }\n extractWithChild(child, selection) {\n if (!(0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isRangeSelection)(selection)) {\n return false;\n }\n const anchorNode = selection.anchor.getNode();\n const focusNode = selection.focus.getNode();\n return this.isParentOf(anchorNode) && this.isParentOf(focusNode) && this.getTextContent().length === selection.getTextContent().length;\n }\n isParentRequired() {\n return true;\n }\n createParentElementNode() {\n return $createListNode('bullet');\n }\n canMergeWhenEmpty() {\n return true;\n }\n}\nfunction $setListItemThemeClassNames(dom, editorThemeClasses, node) {\n const classesToAdd = [];\n const classesToRemove = [];\n const listTheme = editorThemeClasses.list;\n const listItemClassName = listTheme ? listTheme.listitem : undefined;\n let nestedListItemClassName;\n if (listTheme && listTheme.nested) {\n nestedListItemClassName = listTheme.nested.listitem;\n }\n if (listItemClassName !== undefined) {\n classesToAdd.push(...(0,lexical__WEBPACK_IMPORTED_MODULE_0__.normalizeClassNames)(listItemClassName));\n }\n if (listTheme) {\n const parentNode = node.getParent();\n const isCheckList = $isListNode(parentNode) && parentNode.getListType() === 'check';\n const checked = node.getChecked();\n if (!isCheckList || checked) {\n classesToRemove.push(listTheme.listitemUnchecked);\n }\n if (!isCheckList || !checked) {\n classesToRemove.push(listTheme.listitemChecked);\n }\n if (isCheckList) {\n classesToAdd.push(checked ? listTheme.listitemChecked : listTheme.listitemUnchecked);\n }\n }\n if (nestedListItemClassName !== undefined) {\n const nestedListItemClasses = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.normalizeClassNames)(nestedListItemClassName);\n if (node.getChildren().some(child => $isListNode(child))) {\n classesToAdd.push(...nestedListItemClasses);\n } else {\n classesToRemove.push(...nestedListItemClasses);\n }\n }\n if (classesToRemove.length > 0) {\n (0,lexical__WEBPACK_IMPORTED_MODULE_0__.removeClassNamesFromElement)(dom, ...classesToRemove);\n }\n if (classesToAdd.length > 0) {\n (0,lexical__WEBPACK_IMPORTED_MODULE_0__.addClassNamesToElement)(dom, ...classesToAdd);\n }\n}\nfunction updateListItemChecked(dom, listItemNode, prevListItemNode) {\n const parent = listItemNode.getParent();\n const isCheckbox = $isListNode(parent) && parent.getListType() === 'check' &&\n // Only add attributes for leaf list items\n !$isListNode(listItemNode.getFirstChild());\n if (!isCheckbox) {\n dom.removeAttribute('role');\n dom.removeAttribute('tabIndex');\n dom.removeAttribute('aria-checked');\n } else {\n dom.setAttribute('role', 'checkbox');\n dom.setAttribute('tabIndex', '-1');\n if (!prevListItemNode || listItemNode.__checked !== prevListItemNode.__checked) {\n dom.setAttribute('aria-checked', listItemNode.getChecked() ? 'true' : 'false');\n }\n }\n}\nfunction $convertListItemElement(domNode) {\n const isGitHubCheckList = domNode.classList.contains('task-list-item');\n if (isGitHubCheckList) {\n for (const child of domNode.children) {\n if (child.tagName === 'INPUT') {\n return $convertCheckboxInput(child);\n }\n }\n }\n const isJoplinCheckList = domNode.classList.contains('joplin-checkbox');\n if (isJoplinCheckList) {\n for (const child of domNode.children) {\n if (child.classList.contains('checkbox-wrapper') && child.children.length > 0 && child.children[0].tagName === 'INPUT') {\n return $convertCheckboxInput(child.children[0]);\n }\n }\n }\n const ariaCheckedAttr = domNode.getAttribute('aria-checked');\n const checked = ariaCheckedAttr === 'true' ? true : ariaCheckedAttr === 'false' ? false : undefined;\n return {\n node: $createListItemNode(checked)\n };\n}\nfunction $convertCheckboxInput(domNode) {\n const isCheckboxInput = domNode.getAttribute('type') === 'checkbox';\n if (!isCheckboxInput) {\n return {\n node: null\n };\n }\n const checked = domNode.hasAttribute('checked');\n return {\n node: $createListItemNode(checked)\n };\n}\n\n/**\n * Creates a new List Item node, passing true/false will convert it to a checkbox input.\n * @param checked - Is the List Item a checkbox and, if so, is it checked? undefined/null: not a checkbox, true/false is a checkbox and checked/unchecked, respectively.\n * @returns The new List Item.\n */\nfunction $createListItemNode(checked) {\n return (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$applyNodeReplacement)(new ListItemNode(undefined, checked));\n}\n\n/**\n * Checks to see if the node is a ListItemNode.\n * @param node - The node to be checked.\n * @returns true if the node is a ListItemNode, false otherwise.\n */\nfunction $isListItemNode(node) {\n return node instanceof ListItemNode;\n}\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\n/** @noInheritDoc */\nclass ListNode extends lexical__WEBPACK_IMPORTED_MODULE_0__.ElementNode {\n /** @internal */\n __tag;\n /** @internal */\n __start;\n /** @internal */\n __listType;\n\n /** @internal */\n $config() {\n return this.config('list', {\n $transform: node => {\n mergeNextSiblingListIfSameType(node);\n updateChildrenListItemValue(node);\n },\n extends: lexical__WEBPACK_IMPORTED_MODULE_0__.ElementNode,\n importDOM: (0,lexical__WEBPACK_IMPORTED_MODULE_0__.buildImportMap)({\n ol: () => ({\n conversion: $convertListNode,\n priority: 0\n }),\n ul: () => ({\n conversion: $convertListNode,\n priority: 0\n })\n })\n });\n }\n constructor(listType = 'number', start = 1, key) {\n super(key);\n const _listType = TAG_TO_LIST_TYPE[listType] || listType;\n this.__listType = _listType;\n this.__tag = _listType === 'number' ? 'ol' : 'ul';\n this.__start = start;\n }\n afterCloneFrom(prevNode) {\n super.afterCloneFrom(prevNode);\n this.__listType = prevNode.__listType;\n this.__tag = prevNode.__tag;\n this.__start = prevNode.__start;\n }\n getTag() {\n return this.getLatest().__tag;\n }\n setListType(type) {\n const writable = this.getWritable();\n writable.__listType = type;\n writable.__tag = type === 'number' ? 'ol' : 'ul';\n return writable;\n }\n getListType() {\n return this.getLatest().__listType;\n }\n getStart() {\n return this.getLatest().__start;\n }\n setStart(start) {\n const self = this.getWritable();\n self.__start = start;\n return self;\n }\n\n // View\n\n createDOM(config, _editor) {\n const tag = this.__tag;\n const dom = document.createElement(tag);\n if (this.__start !== 1) {\n dom.setAttribute('start', String(this.__start));\n }\n // @ts-expect-error Internal field.\n dom.__lexicalListType = this.__listType;\n $setListThemeClassNames(dom, config.theme, this);\n return dom;\n }\n updateDOM(prevNode, dom, config) {\n if (prevNode.__tag !== this.__tag || prevNode.__listType !== this.__listType) {\n return true;\n }\n $setListThemeClassNames(dom, config.theme, this);\n if (prevNode.__start !== this.__start) {\n dom.setAttribute('start', String(this.__start));\n }\n return false;\n }\n updateFromJSON(serializedNode) {\n return super.updateFromJSON(serializedNode).setListType(serializedNode.listType).setStart(serializedNode.start);\n }\n exportDOM(editor) {\n const element = this.createDOM(editor._config, editor);\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.isHTMLElement)(element)) {\n if (this.__start !== 1) {\n element.setAttribute('start', String(this.__start));\n }\n if (this.__listType === 'check') {\n element.setAttribute('__lexicalListType', 'check');\n }\n }\n return {\n element\n };\n }\n exportJSON() {\n return {\n ...super.exportJSON(),\n listType: this.getListType(),\n start: this.getStart(),\n tag: this.getTag()\n };\n }\n canBeEmpty() {\n return false;\n }\n canIndent() {\n return false;\n }\n splice(start, deleteCount, nodesToInsert) {\n let listItemNodesToInsert = nodesToInsert;\n for (let i = 0; i < nodesToInsert.length; i++) {\n const node = nodesToInsert[i];\n if (!$isListItemNode(node)) {\n if (listItemNodesToInsert === nodesToInsert) {\n listItemNodesToInsert = [...nodesToInsert];\n }\n listItemNodesToInsert[i] = $createListItemNode().append((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isElementNode)(node) && !($isListNode(node) || node.isInline()) ? (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$createTextNode)(node.getTextContent()) : node);\n }\n }\n return super.splice(start, deleteCount, listItemNodesToInsert);\n }\n extractWithChild(child) {\n return $isListItemNode(child);\n }\n}\nfunction $setListThemeClassNames(dom, editorThemeClasses, node) {\n const classesToAdd = [];\n const classesToRemove = [];\n const listTheme = editorThemeClasses.list;\n if (listTheme !== undefined) {\n const listLevelsClassNames = listTheme[`${node.__tag}Depth`] || [];\n const listDepth = $getListDepth(node) - 1;\n const normalizedListDepth = listDepth % listLevelsClassNames.length;\n const listLevelClassName = listLevelsClassNames[normalizedListDepth];\n const listClassName = listTheme[node.__tag];\n let nestedListClassName;\n const nestedListTheme = listTheme.nested;\n const checklistClassName = listTheme.checklist;\n if (nestedListTheme !== undefined && nestedListTheme.list) {\n nestedListClassName = nestedListTheme.list;\n }\n if (listClassName !== undefined) {\n classesToAdd.push(listClassName);\n }\n if (checklistClassName !== undefined && node.__listType === 'check') {\n classesToAdd.push(checklistClassName);\n }\n if (listLevelClassName !== undefined) {\n classesToAdd.push(...(0,lexical__WEBPACK_IMPORTED_MODULE_0__.normalizeClassNames)(listLevelClassName));\n for (let i = 0; i < listLevelsClassNames.length; i++) {\n if (i !== normalizedListDepth) {\n classesToRemove.push(node.__tag + i);\n }\n }\n }\n if (nestedListClassName !== undefined) {\n const nestedListItemClasses = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.normalizeClassNames)(nestedListClassName);\n if (listDepth > 1) {\n classesToAdd.push(...nestedListItemClasses);\n } else {\n classesToRemove.push(...nestedListItemClasses);\n }\n }\n }\n if (classesToRemove.length > 0) {\n (0,lexical__WEBPACK_IMPORTED_MODULE_0__.removeClassNamesFromElement)(dom, ...classesToRemove);\n }\n if (classesToAdd.length > 0) {\n (0,lexical__WEBPACK_IMPORTED_MODULE_0__.addClassNamesToElement)(dom, ...classesToAdd);\n }\n}\n\n/*\n * This function normalizes the children of a ListNode after the conversion from HTML,\n * ensuring that they are all ListItemNodes and contain either a single nested ListNode\n * or some other inline content.\n */\nfunction $normalizeChildren(nodes) {\n const normalizedListItems = [];\n for (let i = 0; i < nodes.length; i++) {\n const node = nodes[i];\n if ($isListItemNode(node)) {\n normalizedListItems.push(node);\n const children = node.getChildren();\n if (children.length > 1) {\n children.forEach(child => {\n if ($isListNode(child)) {\n normalizedListItems.push($wrapInListItem(child));\n }\n });\n }\n } else {\n normalizedListItems.push($wrapInListItem(node));\n }\n }\n return normalizedListItems;\n}\nfunction isDomChecklist(domNode) {\n if (domNode.getAttribute('__lexicallisttype') === 'check' ||\n // is github checklist\n domNode.classList.contains('contains-task-list') ||\n // is joplin checklist\n domNode.getAttribute('data-is-checklist') === '1') {\n return true;\n }\n // if children are checklist items, the node is a checklist ul. Applicable for googledoc checklist pasting.\n for (const child of domNode.childNodes) {\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.isHTMLElement)(child) && child.hasAttribute('aria-checked')) {\n return true;\n }\n }\n return false;\n}\nfunction $convertListNode(domNode) {\n const nodeName = domNode.nodeName.toLowerCase();\n let node = null;\n if (nodeName === 'ol') {\n // @ts-ignore\n const start = domNode.start;\n node = $createListNode('number', start);\n } else if (nodeName === 'ul') {\n if (isDomChecklist(domNode)) {\n node = $createListNode('check');\n } else {\n node = $createListNode('bullet');\n }\n }\n return {\n after: $normalizeChildren,\n node\n };\n}\nconst TAG_TO_LIST_TYPE = {\n ol: 'number',\n ul: 'bullet'\n};\n\n/**\n * Creates a ListNode of listType.\n * @param listType - The type of list to be created. Can be 'number', 'bullet', or 'check'.\n * @param start - Where an ordered list starts its count, start = 1 if left undefined.\n * @returns The new ListNode\n */\nfunction $createListNode(listType = 'number', start = 1) {\n return (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$applyNodeReplacement)(new ListNode(listType, start));\n}\n\n/**\n * Checks to see if the node is a ListNode.\n * @param node - The node to be checked.\n * @returns true if the node is a ListNode, false otherwise.\n */\nfunction $isListNode(node) {\n return node instanceof ListNode;\n}\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nconst INSERT_CHECK_LIST_COMMAND = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.createCommand)('INSERT_CHECK_LIST_COMMAND');\n\n/**\n * Registers the checklist plugin with the editor.\n * @param editor The LexicalEditor instance.\n * @param options Optional configuration.\n * - disableTakeFocusOnClick: If true, clicking a checklist item will not focus the editor (useful for mobile).\n */\nfunction registerCheckList(editor, options) {\n const disableTakeFocusOnClick = options && options.disableTakeFocusOnClick || false;\n const configHandleClick = event => {\n handleClick(event, disableTakeFocusOnClick);\n };\n const configHandleSelectDefaults = event => {\n handleSelectDefaults(event, disableTakeFocusOnClick);\n };\n return (0,lexical__WEBPACK_IMPORTED_MODULE_0__.mergeRegister)(editor.registerCommand(INSERT_CHECK_LIST_COMMAND, () => {\n $insertList('check');\n return true;\n }, lexical__WEBPACK_IMPORTED_MODULE_0__.COMMAND_PRIORITY_LOW), editor.registerCommand(lexical__WEBPACK_IMPORTED_MODULE_0__.KEY_ARROW_DOWN_COMMAND, event => {\n return handleArrowUpOrDown(event, editor, false);\n }, lexical__WEBPACK_IMPORTED_MODULE_0__.COMMAND_PRIORITY_LOW), editor.registerCommand(lexical__WEBPACK_IMPORTED_MODULE_0__.KEY_ARROW_UP_COMMAND, event => {\n return handleArrowUpOrDown(event, editor, true);\n }, lexical__WEBPACK_IMPORTED_MODULE_0__.COMMAND_PRIORITY_LOW), editor.registerCommand(lexical__WEBPACK_IMPORTED_MODULE_0__.KEY_ESCAPE_COMMAND, () => {\n const activeItem = getActiveCheckListItem();\n if (activeItem != null) {\n const rootElement = editor.getRootElement();\n if (rootElement != null) {\n rootElement.focus();\n }\n return true;\n }\n return false;\n }, lexical__WEBPACK_IMPORTED_MODULE_0__.COMMAND_PRIORITY_LOW), editor.registerCommand(lexical__WEBPACK_IMPORTED_MODULE_0__.KEY_SPACE_COMMAND, event => {\n const activeItem = getActiveCheckListItem();\n if (activeItem != null && editor.isEditable()) {\n editor.update(() => {\n const listItemNode = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$getNearestNodeFromDOMNode)(activeItem);\n if ($isListItemNode(listItemNode)) {\n event.preventDefault();\n listItemNode.toggleChecked();\n }\n });\n return true;\n }\n return false;\n }, lexical__WEBPACK_IMPORTED_MODULE_0__.COMMAND_PRIORITY_LOW), editor.registerCommand(lexical__WEBPACK_IMPORTED_MODULE_0__.KEY_ARROW_LEFT_COMMAND, event => {\n return editor.getEditorState().read(() => {\n const selection = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$getSelection)();\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isRangeSelection)(selection) && selection.isCollapsed()) {\n const {\n anchor\n } = selection;\n const isElement = anchor.type === 'element';\n if (isElement || anchor.offset === 0) {\n const anchorNode = anchor.getNode();\n const elementNode = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$findMatchingParent)(anchorNode, node => (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isElementNode)(node) && !node.isInline());\n if ($isListItemNode(elementNode)) {\n const parent = elementNode.getParent();\n if ($isListNode(parent) && parent.getListType() === 'check' && (isElement || elementNode.getFirstDescendant() === anchorNode)) {\n const domNode = editor.getElementByKey(elementNode.__key);\n if (domNode != null && document.activeElement !== domNode) {\n domNode.focus();\n event.preventDefault();\n return true;\n }\n }\n }\n }\n }\n return false;\n });\n }, lexical__WEBPACK_IMPORTED_MODULE_0__.COMMAND_PRIORITY_LOW), editor.registerRootListener((rootElement, prevElement) => {\n if (rootElement !== null) {\n rootElement.addEventListener('click', configHandleClick);\n // Use capture so we run before other listeners that might move focus.\n rootElement.addEventListener('pointerdown', configHandleSelectDefaults, {\n capture: true\n });\n // Some browsers / integrations still generate mousedown events; handle them too.\n rootElement.addEventListener('mousedown', configHandleSelectDefaults, {\n capture: true\n });\n // Intercept touchstart to stop the mobile browser from placing the caret\n // and opening the keyboard when tapping the checklist marker.\n rootElement.addEventListener('touchstart', configHandleSelectDefaults, {\n capture: true,\n passive: false\n });\n }\n if (prevElement !== null) {\n prevElement.removeEventListener('click', configHandleClick);\n prevElement.removeEventListener('pointerdown', configHandleSelectDefaults, {\n capture: true\n });\n prevElement.removeEventListener('mousedown', configHandleSelectDefaults, {\n capture: true\n });\n prevElement.removeEventListener('touchstart', configHandleSelectDefaults, {\n capture: true\n });\n }\n }));\n}\nfunction handleCheckItemEvent(event, callback) {\n const target = event.target;\n if (!(0,lexical__WEBPACK_IMPORTED_MODULE_0__.isHTMLElement)(target)) {\n return;\n }\n\n // Ignore clicks on LI that have nested lists\n const firstChild = target.firstChild;\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.isHTMLElement)(firstChild) && (firstChild.tagName === 'UL' || firstChild.tagName === 'OL')) {\n return;\n }\n const parentNode = target.parentNode;\n\n // @ts-ignore internal field\n if (!parentNode || parentNode.__lexicalListType !== 'check') {\n return;\n }\n let clientX = null;\n let pointerType = null;\n if ('clientX' in event) {\n clientX = event.clientX;\n } else if ('touches' in event) {\n const touches = event.touches;\n if (touches.length > 0) {\n clientX = touches[0].clientX;\n pointerType = 'touch';\n }\n }\n\n // If we couldn't resolve a clientX (unexpected input), bail out.\n if (clientX == null) {\n return;\n }\n const rect = target.getBoundingClientRect();\n const zoom = (0,_lexical_utils__WEBPACK_IMPORTED_MODULE_1__.calculateZoomLevel)(target);\n const clientXInPixels = clientX / zoom;\n\n // Use getComputedStyle if available, otherwise fallback to 0px width\n const beforeStyles = window.getComputedStyle ? window.getComputedStyle(target, '::before') : {\n width: '0px'\n };\n const beforeWidthInPixels = parseFloat(beforeStyles.width);\n\n // Make click area slightly larger for touch devices to improve accessibility\n // Determine whether this is a touch event; some environments may supply\n // pointerType on PointerEvent while touch events use the `touches` API above.\n const isTouchEvent = pointerType === 'touch' || event.pointerType === 'touch';\n const clickAreaPadding = isTouchEvent ? 32 : 0; // Add 32px padding for touch events\n\n if (target.dir === 'rtl' ? clientXInPixels < rect.right + clickAreaPadding && clientXInPixels > rect.right - beforeWidthInPixels - clickAreaPadding : clientXInPixels > rect.left - clickAreaPadding && clientXInPixels < rect.left + beforeWidthInPixels + clickAreaPadding) {\n callback();\n }\n}\nfunction handleClick(event, disableFocusOnClick) {\n handleCheckItemEvent(event, () => {\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.isHTMLElement)(event.target)) {\n const domNode = event.target;\n const editor = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.getNearestEditorFromDOMNode)(domNode);\n if (editor != null && editor.isEditable()) {\n editor.update(() => {\n const node = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$getNearestNodeFromDOMNode)(domNode);\n if ($isListItemNode(node)) {\n if (disableFocusOnClick) {\n (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$addUpdateTag)(lexical__WEBPACK_IMPORTED_MODULE_0__.SKIP_SELECTION_FOCUS_TAG);\n (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$addUpdateTag)(lexical__WEBPACK_IMPORTED_MODULE_0__.SKIP_DOM_SELECTION_TAG);\n } else {\n domNode.focus();\n }\n node.toggleChecked();\n }\n });\n }\n }\n });\n}\n\n/**\n * Prevents default focus switch behavior\n *\n * @param event might be of type PointerEvent, MouseEvent, or TouchEvent, hence the generic Event type\n *\n */\nfunction handleSelectDefaults(event, disableTakeFocusOnClick) {\n handleCheckItemEvent(event, () => {\n // Prevents caret moving when clicking on check mark.\n event.preventDefault();\n if (disableTakeFocusOnClick) {\n event.stopPropagation();\n }\n });\n}\nfunction getActiveCheckListItem() {\n const activeElement = document.activeElement;\n return (0,lexical__WEBPACK_IMPORTED_MODULE_0__.isHTMLElement)(activeElement) && activeElement.tagName === 'LI' && activeElement.parentNode != null &&\n // @ts-ignore internal field\n activeElement.parentNode.__lexicalListType === 'check' ? activeElement : null;\n}\nfunction findCheckListItemSibling(node, backward) {\n let sibling = backward ? node.getPreviousSibling() : node.getNextSibling();\n let parent = node;\n\n // Going up in a tree to get non-null sibling\n while (sibling == null && $isListItemNode(parent)) {\n // Get li -> parent ul/ol -> parent li\n parent = parent.getParentOrThrow().getParent();\n if (parent != null) {\n sibling = backward ? parent.getPreviousSibling() : parent.getNextSibling();\n }\n }\n\n // Going down in a tree to get first non-nested list item\n while ($isListItemNode(sibling)) {\n const firstChild = backward ? sibling.getLastChild() : sibling.getFirstChild();\n if (!$isListNode(firstChild)) {\n return sibling;\n }\n sibling = backward ? firstChild.getLastChild() : firstChild.getFirstChild();\n }\n return null;\n}\nfunction handleArrowUpOrDown(event, editor, backward) {\n const activeItem = getActiveCheckListItem();\n if (activeItem != null) {\n editor.update(() => {\n const listItem = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$getNearestNodeFromDOMNode)(activeItem);\n if (!$isListItemNode(listItem)) {\n return;\n }\n const nextListItem = findCheckListItemSibling(listItem, backward);\n if (nextListItem != null) {\n nextListItem.selectStart();\n const dom = editor.getElementByKey(nextListItem.__key);\n if (dom != null) {\n event.preventDefault();\n setTimeout(() => {\n dom.focus();\n }, 0);\n }\n }\n });\n }\n return false;\n}\n\n/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nconst UPDATE_LIST_START_COMMAND = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.createCommand)('UPDATE_LIST_START_COMMAND');\nconst INSERT_UNORDERED_LIST_COMMAND = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.createCommand)('INSERT_UNORDERED_LIST_COMMAND');\nconst INSERT_ORDERED_LIST_COMMAND = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.createCommand)('INSERT_ORDERED_LIST_COMMAND');\nconst REMOVE_LIST_COMMAND = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.createCommand)('REMOVE_LIST_COMMAND');\nfunction registerList(editor, options) {\n const removeListener = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.mergeRegister)(editor.registerCommand(INSERT_ORDERED_LIST_COMMAND, () => {\n $insertList('number');\n return true;\n }, lexical__WEBPACK_IMPORTED_MODULE_0__.COMMAND_PRIORITY_LOW), editor.registerCommand(UPDATE_LIST_START_COMMAND, payload => {\n const {\n listNodeKey,\n newStart\n } = payload;\n const listNode = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$getNodeByKey)(listNodeKey);\n if (!$isListNode(listNode)) {\n return false;\n }\n if (listNode.getListType() === 'number') {\n listNode.setStart(newStart);\n updateChildrenListItemValue(listNode);\n }\n return true;\n }, lexical__WEBPACK_IMPORTED_MODULE_0__.COMMAND_PRIORITY_LOW), editor.registerCommand(INSERT_UNORDERED_LIST_COMMAND, () => {\n $insertList('bullet');\n return true;\n }, lexical__WEBPACK_IMPORTED_MODULE_0__.COMMAND_PRIORITY_LOW), editor.registerCommand(REMOVE_LIST_COMMAND, () => {\n $removeList();\n return true;\n }, lexical__WEBPACK_IMPORTED_MODULE_0__.COMMAND_PRIORITY_LOW), editor.registerCommand(lexical__WEBPACK_IMPORTED_MODULE_0__.INSERT_PARAGRAPH_COMMAND, () => {\n const shouldRestore = options && options.restoreNumbering;\n return $handleListInsertParagraph(!!shouldRestore);\n }, lexical__WEBPACK_IMPORTED_MODULE_0__.COMMAND_PRIORITY_LOW), editor.registerNodeTransform(ListItemNode, node => {\n const firstChild = node.getFirstChild();\n if (firstChild) {\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isTextNode)(firstChild)) {\n const style = firstChild.getStyle();\n const format = firstChild.getFormat();\n if (node.getTextStyle() !== style) {\n node.setTextStyle(style);\n }\n if (node.getTextFormat() !== format) {\n node.setTextFormat(format);\n }\n }\n } else {\n // If it's empty, check the selection\n const selection = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$getSelection)();\n if ((0,lexical__WEBPACK_IMPORTED_MODULE_0__.$isRangeSelection)(selection) && (selection.style !== node.getTextStyle() || selection.format !== node.getTextFormat()) && selection.isCollapsed() && node.is(selection.anchor.getNode())) {\n node.setTextStyle(selection.style).setTextFormat(selection.format);\n }\n }\n }), editor.registerNodeTransform(lexical__WEBPACK_IMPORTED_MODULE_0__.TextNode, node => {\n const listItemParentNode = node.getParent();\n if ($isListItemNode(listItemParentNode) && node.is(listItemParentNode.getFirstChild())) {\n const style = node.getStyle();\n const format = node.getFormat();\n if (style !== listItemParentNode.getTextStyle() || format !== listItemParentNode.getTextFormat()) {\n listItemParentNode.setTextStyle(style).setTextFormat(format);\n }\n }\n }));\n return removeListener;\n}\nfunction registerListStrictIndentTransform(editor) {\n const $formatListIndentStrict = listItemNode => {\n const listNode = listItemNode.getParent();\n if ($isListNode(listItemNode.getFirstChild()) || !$isListNode(listNode)) {\n return;\n }\n const startingListItemNode = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.$findMatchingParent)(listItemNode, node => $isListItemNode(node) && $isListNode(node.getParent()) && $isListItemNode(node.getPreviousSibling()));\n if (startingListItemNode === null && listItemNode.getIndent() > 0) {\n listItemNode.setIndent(0);\n } else if ($isListItemNode(startingListItemNode)) {\n const prevListItemNode = startingListItemNode.getPreviousSibling();\n if ($isListItemNode(prevListItemNode)) {\n const endListItemNode = $findChildrenEndListItemNode(prevListItemNode);\n const endListNode = endListItemNode.getParent();\n if ($isListNode(endListNode)) {\n const prevDepth = $getListDepth(endListNode);\n const depth = $getListDepth(listNode);\n if (prevDepth + 1 < depth) {\n listItemNode.setIndent(prevDepth);\n }\n }\n }\n }\n };\n const $processListWithStrictIndent = listNode => {\n const queue = [listNode];\n while (queue.length > 0) {\n const node = queue.shift();\n if (!$isListNode(node)) {\n continue;\n }\n for (const child of node.getChildren()) {\n if ($isListItemNode(child)) {\n $formatListIndentStrict(child);\n const firstChild = child.getFirstChild();\n if ($isListNode(firstChild)) {\n queue.push(firstChild);\n }\n }\n }\n }\n };\n return editor.registerNodeTransform(ListNode, $processListWithStrictIndent);\n}\nfunction $findChildrenEndListItemNode(listItemNode) {\n let current = listItemNode;\n let firstChild = current.getFirstChild();\n while ($isListNode(firstChild)) {\n const lastChild = firstChild.getLastChild();\n if ($isListItemNode(lastChild)) {\n current = lastChild;\n firstChild = current.getFirstChild();\n } else {\n break;\n }\n }\n return current;\n}\n\n/**\n * @deprecated use {@link $insertList} from an update or command listener.\n *\n * Inserts a new ListNode. If the selection's anchor node is an empty ListItemNode and is a child of\n * the root/shadow root, it will replace the ListItemNode with a ListNode and the old ListItemNode.\n * Otherwise it will replace its parent with a new ListNode and re-insert the ListItemNode and any previous children.\n * If the selection's anchor node is not an empty ListItemNode, it will add a new ListNode or merge an existing ListNode,\n * unless the the node is a leaf node, in which case it will attempt to find a ListNode up the branch and replace it with\n * a new ListNode, or create a new ListNode at the nearest root/shadow root.\n * @param editor - The lexical editor.\n * @param listType - The type of list, \"number\" | \"bullet\" | \"check\".\n */\nfunction insertList(editor, listType) {\n editor.update(() => $insertList(listType));\n}\n\n/**\n * @deprecated use {@link $removeList} from an update or command listener.\n *\n * Searches for the nearest ancestral ListNode and removes it. If selection is an empty ListItemNode\n * it will remove the whole list, including the ListItemNode. For each ListItemNode in the ListNode,\n * removeList will also generate new ParagraphNodes in the removed ListNode's place. Any child node\n * inside a ListItemNode will be appended to the new ParagraphNodes.\n * @param editor - The lexical editor.\n */\nfunction removeList(editor) {\n editor.update(() => $removeList());\n}\n/**\n * Configures {@link ListNode}, {@link ListItemNode} and registers\n * the strict indent transform if `hasStrictIndent` is true (default false).\n */\nconst ListExtension = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.defineExtension)({\n build(editor, config, state) {\n return (0,_lexical_extension__WEBPACK_IMPORTED_MODULE_3__.namedSignals)(config);\n },\n config: (0,lexical__WEBPACK_IMPORTED_MODULE_0__.safeCast)({\n hasStrictIndent: false,\n shouldPreserveNumbering: false\n }),\n name: '@lexical/list/List',\n nodes: () => [ListNode, ListItemNode],\n register(editor, config, state) {\n const stores = state.getOutput();\n return (0,lexical__WEBPACK_IMPORTED_MODULE_0__.mergeRegister)((0,_lexical_extension__WEBPACK_IMPORTED_MODULE_3__.effect)(() => {\n return registerList(editor, {\n restoreNumbering: stores.shouldPreserveNumbering.value\n });\n }), (0,_lexical_extension__WEBPACK_IMPORTED_MODULE_3__.effect)(() => stores.hasStrictIndent.value ? registerListStrictIndentTransform(editor) : undefined));\n }\n});\n/**\n * Registers checklist functionality for {@link ListNode} and\n * {@link ListItemNode} with a\n * {@link INSERT_CHECK_LIST_COMMAND} listener and\n * the expected keyboard and mouse interactions for\n * checkboxes.\n */\nconst CheckListExtension = (0,lexical__WEBPACK_IMPORTED_MODULE_0__.defineExtension)({\n config: (0,lexical__WEBPACK_IMPORTED_MODULE_0__.safeCast)({\n disableTakeFocusOnClick: false\n }),\n dependencies: [ListExtension],\n name: '@lexical/list/CheckList',\n register: registerCheckList\n});\n\n\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKHJzYykvLi9ub2RlX21vZHVsZXMvLnBucG0vQGxleGljYWwrbGlzdEAwLjQxLjAvbm9kZV9tb2R1bGVzL0BsZXhpY2FsL2xpc3QvTGV4aWNhbExpc3QuZGV2Lm1qcyIsIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUUwRDtBQUN5SDtBQUN3ZDtBQUNobEI7O0FBRTNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCLHlCQUF5QjtBQUMzQztBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFD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QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxvQkFBb0IsbUJBQW1CO0FBQ3ZDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0Esb0JBQW9CLG1CQUFtQjtBQUN2QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxlQUFlLEdBQUcsb0JBQW9CO0FBQ3JEO0FBQ0E7QUFDQSxzQkFBc0Isd0RBQWU7QUFDckM7QUFDQSxXQUFXLGdFQUFZO0FBQ3ZCLEdBQUc7QUFDSCxVQUFVLGlEQUFRO0FBQ2xCO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLHNEQUFhLENBQUMsMERBQU07QUFDL0I7QUFDQTtBQUNBLE9BQU87QUFDUCxLQUFLLEdBQUcsMERBQU07QUFDZDtBQUNBLENBQUM7QUFDRDtBQUNBLDBDQUEwQyxnQkFBZ0I7QUFDMUQsSUFBSSxvQkFBb0I7QUFDeEIsSUFBSSxpQ0FBaUM7QUFDckM7QUFDQTtBQUNBO0FBQ0EsMkJBQTJCLHdEQUFlO0FBQzFDLFVBQVUsaURBQVE7QUFDbEI7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFZ2IiLCJzb3VyY2VzIjpbIi9Vc2Vycy9tYXJjbWludGVsL1Byb2plY3RzL2UtdGliLmNvbS9ub2RlX21vZHVsZXMvLnBucG0vQGxleGljYWwrbGlzdEAwLjQxLjAvbm9kZV9tb2R1bGVzL0BsZXhpY2FsL2xpc3QvTGV4aWNhbExpc3QuZGV2Lm1qcyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgTWV0YSBQbGF0Zm9ybXMsIEluYy4gYW5kIGFmZmlsaWF0ZXMuXG4gKlxuICogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4gKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4gKlxuICovXG5cbmltcG9ydCB7IGVmZmVjdCwgbmFtZWRTaWduYWxzIH0gZnJvbSAnQGxleGljYWwvZXh0ZW5zaW9uJztcbmltcG9ydCB7ICRnZXROZWFyZXN0Tm9kZU9mVHlwZSwgcmVtb3ZlQ2xhc3NOYW1lc0Zyb21FbGVtZW50LCBhZGRDbGFzc05hbWVzVG9FbGVtZW50LCBpc0hUTUxFbGVtZW50LCBtZXJnZVJlZ2lzdGVyLCAkZmluZE1hdGNoaW5nUGFyZW50LCBjYWxjdWxhdGVab29tTGV2ZWwgfSBmcm9tICdAbGV4aWNhbC91dGlscyc7XG5pbXBvcnQgeyAkZ2V0U2VsZWN0aW9uLCAkaXNSYW5nZVNlbGVjdGlvbiwgJGlzUm9vdE9yU2hhZG93Um9vdCwgJGNyZWF0ZVBhcmFncmFwaE5vZGUsICRpc0VsZW1lbnROb2RlLCAkaXNMZWFmTm9kZSwgJHNldFBvaW50RnJvbUNhcmV0LCAkbm9ybWFsaXplQ2FyZXQsICRnZXRDaGlsZENhcmV0LCAkaXNUZXh0Tm9kZSwgRWxlbWVudE5vZGUsIGJ1aWxkSW1wb3J0TWFwLCAkaXNQYXJhZ3JhcGhOb2RlLCAkYXBwbHlOb2RlUmVwbGFjZW1lbnQsIG5vcm1hbGl6ZUNsYXNzTmFtZXMsICRjcmVhdGVUZXh0Tm9kZSwgY3JlYXRlQ29tbWFuZCwgQ09NTUFORF9QUklPUklUWV9MT1csIEtFWV9BUlJPV19ET1dOX0NPTU1BTkQsIEtFWV9BUlJPV19VUF9DT01NQU5ELCBLRVlfRVNDQVBFX0NPTU1BTkQsIEtFWV9TUEFDRV9DT01NQU5ELCAkZ2V0TmVhcmVzdE5vZGVGcm9tRE9NTm9kZSwgS0VZX0FSUk9XX0xFRlRfQ09NTUFORCwgZ2V0TmVhcmVzdEVkaXRvckZyb21ET01Ob2RlLCAkYWRkVXBkYXRlVGFnLCBTS0lQX1NFTEVDVElPTl9GT0NVU19UQUcsIFNLSVBfRE9NX1NFTEVDVElPTl9UQUcsIGRlZmluZUV4dGVuc2lvbiwgc2FmZUNhc3QsICRnZXROb2RlQnlLZXksIElOU0VSVF9QQVJBR1JBUEhfQ09NTUFORCwgVGV4dE5vZGUgfSBmcm9tICdsZXhpY2FsJztcbmltcG9ydCB7IGdldFN0eWxlT2JqZWN0RnJvbUNTUyB9IGZyb20gJ0BsZXhpY2FsL3NlbGVjdGlvbic7XG5cbi8qKlxuICogQ29weXJpZ2h0IChjKSBNZXRhIFBsYXRmb3JtcywgSW5jLiBhbmQgYWZmaWxpYXRlcy5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqXG4gKi9cblxuLy8gRG8gbm90IHJlcXVpcmUgdGhpcyBtb2R1bGUgZGlyZWN0bHkhIFVzZSBub3JtYWwgYGludmFyaWFudGAgY2FsbHMuXG5cbmZ1bmN0aW9uIGZvcm1hdERldkVycm9yTWVzc2FnZShtZXNzYWdlKSB7XG4gIHRocm93IG5ldyBFcnJvcihtZXNzYWdlKTtcbn1cblxuLyoqXG4gKiBDaGVja3MgdGhlIGRlcHRoIG9mIGxpc3ROb2RlIGZyb20gdGhlIHJvb3Qgbm9kZS5cbiAqIEBwYXJhbSBsaXN0Tm9kZSAtIFRoZSBMaXN0Tm9kZSB0byBiZSBjaGVja2VkLlxuICogQHJldHVybnMgVGhlIGRlcHRoIG9mIHRoZSBMaXN0Tm9kZS5cbiAqL1xuZnVuY3Rpb24gJGdldExpc3REZXB0aChsaXN0Tm9kZSkge1xuICBsZXQgZGVwdGggPSAxO1xuICBsZXQgcGFyZW50ID0gbGlzdE5vZGUuZ2V0UGFyZW50KCk7XG4gIHdoaWxlIChwYXJlbnQgIT0gbnVsbCkge1xuICAgIGlmICgkaXNMaXN0SXRlbU5vZGUocGFyZW50KSkge1xuICAgICAgY29uc3QgcGFyZW50TGlzdCA9IHBhcmVudC5nZXRQYXJlbnQoKTtcbiAgICAgIGlmICgkaXNMaXN0Tm9kZShwYXJlbnRMaXN0KSkge1xuICAgICAgICBkZXB0aCsrO1xuICAgICAgICBwYXJlbnQgPSBwYXJlbnRMaXN0LmdldFBhcmVudCgpO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIHtcbiAgICAgICAgZm9ybWF0RGV2RXJyb3JNZXNzYWdlKGBBIExpc3RJdGVtTm9kZSBtdXN0IGhhdmUgYSBMaXN0Tm9kZSBmb3IgYSBwYXJlbnQuYCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBkZXB0aDtcbiAgfVxuICByZXR1cm4gZGVwdGg7XG59XG5cbi8qKlxuICogRmluZHMgdGhlIG5lYXJlc3QgYW5jZXN0cmFsIExpc3ROb2RlIGFuZCByZXR1cm5zIGl0LCB0aHJvd3MgYW4gaW52YXJpYW50IGlmIGxpc3RJdGVtIGlzIG5vdCBhIExpc3RJdGVtTm9kZS5cbiAqIEBwYXJhbSBsaXN0SXRlbSAtIFRoZSBub2RlIHRvIGJlIGNoZWNrZWQuXG4gKiBAcmV0dXJucyBUaGUgTGlzdE5vZGUgZm91bmQuXG4gKi9cbmZ1bmN0aW9uICRnZXRUb3BMaXN0Tm9kZShsaXN0SXRlbSkge1xuICBsZXQgbGlzdCA9IGxpc3RJdGVtLmdldFBhcmVudCgpO1xuICBpZiAoISRpc0xpc3ROb2RlKGxpc3QpKSB7XG4gICAge1xuICAgICAgZm9ybWF0RGV2RXJyb3JNZXNzYWdlKGBBIExpc3RJdGVtTm9kZSBtdXN0IGhhdmUgYSBMaXN0Tm9kZSBmb3IgYSBwYXJlbnQuYCk7XG4gICAgfVxuICB9XG4gIGxldCBwYXJlbnQgPSBsaXN0O1xuICB3aGlsZSAocGFyZW50ICE9PSBudWxsKSB7XG4gICAgcGFyZW50ID0gcGFyZW50LmdldFBhcmVudCgpO1xuICAgIGlmICgkaXNMaXN0Tm9kZShwYXJlbnQpKSB7XG4gICAgICBsaXN0ID0gcGFyZW50O1xuICAgIH1cbiAgfVxuICByZXR1cm4gbGlzdDtcbn1cblxuLyoqXG4gKiBBIHJlY3Vyc2l2ZSBEZXB0aC1GaXJzdCBTZWFyY2ggKFBvc3RvcmRlciBUcmF2ZXJzYWwpIHRoYXQgZmluZHMgYWxsIG9mIGEgbm9kZSdzIGNoaWxkcmVuXG4gKiB0aGF0IGFyZSBvZiB0eXBlIExpc3RJdGVtTm9kZSBhbmQgcmV0dXJucyB0aGVtIGluIGFuIGFycmF5LlxuICogQHBhcmFtIG5vZGUgLSBUaGUgTGlzdE5vZGUgdG8gc3RhcnQgdGhlIHNlYXJjaC5cbiAqIEByZXR1cm5zIEFuIGFycmF5IGNvbnRhaW5pbmcgYWxsIG5vZGVzIG9mIHR5cGUgTGlzdEl0ZW1Ob2RlIGZvdW5kLlxuICovXG4vLyBUaGlzIHNob3VsZCBwcm9iYWJseSBiZSAkZ2V0QWxsQ2hpbGRyZW5PZlR5cGVcbmZ1bmN0aW9uICRnZXRBbGxMaXN0SXRlbXMobm9kZSkge1xuICBsZXQgbGlzdEl0ZW1Ob2RlcyA9IFtdO1xuICBjb25zdCBsaXN0Q2hpbGRyZW4gPSBub2RlLmdldENoaWxkcmVuKCkuZmlsdGVyKCRpc0xpc3RJdGVtTm9kZSk7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdENoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgY29uc3QgbGlzdEl0ZW1Ob2RlID0gbGlzdENoaWxkcmVuW2ldO1xuICAgIGNvbnN0IGZpcnN0Q2hpbGQgPSBsaXN0SXRlbU5vZGUuZ2V0Rmlyc3RDaGlsZCgpO1xuICAgIGlmICgkaXNMaXN0Tm9kZShmaXJzdENoaWxkKSkge1xuICAgICAgbGlzdEl0ZW1Ob2RlcyA9IGxpc3RJdGVtTm9kZXMuY29uY2F0KCRnZXRBbGxMaXN0SXRlbXMoZmlyc3RDaGlsZCkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBsaXN0SXRlbU5vZGVzLnB1c2gobGlzdEl0ZW1Ob2RlKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGxpc3RJdGVtTm9kZXM7XG59XG5cbi8qKlxuICogQ2hlY2tzIHRvIHNlZSBpZiB0aGUgcGFzc2VkIG5vZGUgaXMgYSBMaXN0SXRlbU5vZGUgYW5kIGhhcyBhIExpc3ROb2RlIGFzIGEgY2hpbGQuXG4gKiBAcGFyYW0gbm9kZSAtIFRoZSBub2RlIHRvIGJlIGNoZWNrZWQuXG4gKiBAcmV0dXJucyB0cnVlIGlmIHRoZSBub2RlIGlzIGEgTGlzdEl0ZW1Ob2RlIGFuZCBoYXMgYSBMaXN0Tm9kZSBjaGlsZCwgZmFsc2Ugb3RoZXJ3aXNlLlxuICovXG5mdW5jdGlvbiBpc05lc3RlZExpc3ROb2RlKG5vZGUpIHtcbiAgcmV0dXJuICRpc0xpc3RJdGVtTm9kZShub2RlKSAmJiAkaXNMaXN0Tm9kZShub2RlLmdldEZpcnN0Q2hpbGQoKSk7XG59XG5cbi8qKlxuICogVGFrZXMgYSBkZWVwbHkgbmVzdGVkIExpc3ROb2RlIG9yIExpc3RJdGVtTm9kZSBhbmQgdHJhdmVyc2VzIHVwIHRoZSBicmFuY2ggdG8gZGVsZXRlIHRoZSBmaXJzdFxuICogYW5jZXN0cmFsIExpc3ROb2RlICh3aGljaCBjb3VsZCBiZSB0aGUgcm9vdCBMaXN0Tm9kZSkgb3IgTGlzdEl0ZW1Ob2RlIHdpdGggc2libGluZ3MsIGVzc2VudGlhbGx5XG4gKiBicmluZ2luZyB0aGUgZGVlcGx5IG5lc3RlZCBub2RlIHVwIHRoZSBicmFuY2ggb25jZS4gV291bGQgcmVtb3ZlIHN1Ymxpc3QgaWYgaXQgaGFzIHNpYmxpbmdzLlxuICogU2hvdWxkIG5vdCBicmVhayBMaXN0SXRlbSAtPiBMaXN0IC0+IExpc3RJdGVtIGNoYWluIGFzIGVtcHR5IExpc3QvSXRlbU5vZGVzIHNob3VsZCBiZSByZW1vdmVkIG9uIC5yZW1vdmUoKS5cbiAqIEBwYXJhbSBzdWJsaXN0IC0gVGhlIG5lc3RlZCBMaXN0Tm9kZSBvciBMaXN0SXRlbU5vZGUgdG8gYmUgYnJvdWdodCB1cCB0aGUgYnJhbmNoLlxuICovXG5mdW5jdGlvbiAkcmVtb3ZlSGlnaGVzdEVtcHR5TGlzdFBhcmVudChzdWJsaXN0KSB7XG4gIC8vIE5vZGVzIG1heSBiZSByZXBlYXRlZGx5IGluZGVudGVkLCB0byBjcmVhdGUgZGVlcGx5IG5lc3RlZCBsaXN0cyB0aGF0IGVhY2hcbiAgLy8gY29udGFpbiBqdXN0IG9uZSBidWxsZXQuXG4gIC8vIE91ciBnb2FsIGlzIHRvIHJlbW92ZSB0aGVzZSAoZW1wdHkpIGRlZXBseSBuZXN0ZWQgbGlzdHMuIFRoZSBlYXNpZXN0XG4gIC8vIHdheSB0byBkbyB0aGF0IGlzIGNyYXdsIGJhY2sgdXAgdGhlIHRyZWUgdW50aWwgd2UgZmluZCBhIG5vZGUgdGhhdCBoYXMgc2libGluZ3NcbiAgLy8gKGUuZy4gaXMgYWN0dWFsbHkgcGFydCBvZiB0aGUgbGlzdCBjb250ZW50cykgYW5kIGRlbGV0ZSB0aGF0LCBvciBkZWxldGVcbiAgLy8gdGhlIHJvb3Qgb2YgdGhlIGxpc3QgKGlmIG5vIGxpc3Qgbm9kZXMgaGF2ZSBzaWJsaW5ncy4pXG4gIGxldCBlbXB0eUxpc3RQdHIgPSBzdWJsaXN0O1xuICB3aGlsZSAoZW1wdHlMaXN0UHRyLmdldE5leHRTaWJsaW5nKCkgPT0gbnVsbCAmJiBlbXB0eUxpc3RQdHIuZ2V0UHJldmlvdXNTaWJsaW5nKCkgPT0gbnVsbCkge1xuICAgIGNvbnN0IHBhcmVudCA9IGVtcHR5TGlzdFB0ci5nZXRQYXJlbnQoKTtcbiAgICBpZiAocGFyZW50ID09IG51bGwgfHwgISgkaXNMaXN0SXRlbU5vZGUocGFyZW50KSB8fCAkaXNMaXN0Tm9kZShwYXJlbnQpKSkge1xuICAgICAgYnJlYWs7XG4gICAgfVxuICAgIGVtcHR5TGlzdFB0ciA9IHBhcmVudDtcbiAgfVxuICBlbXB0eUxpc3RQdHIucmVtb3ZlKCk7XG59XG5cbi8qKlxuICogV3JhcHMgYSBub2RlIGludG8gYSBMaXN0SXRlbU5vZGUuXG4gKiBAcGFyYW0gbm9kZSAtIFRoZSBub2RlIHRvIGJlIHdyYXBwZWQgaW50byBhIExpc3RJdGVtTm9kZVxuICogQHJldHVybnMgVGhlIExpc3RJdGVtTm9kZSB3aGljaCB0aGUgcGFzc2VkIG5vZGUgaXMgd3JhcHBlZCBpbi5cbiAqL1xuZnVuY3Rpb24gJHdyYXBJbkxpc3RJdGVtKG5vZGUpIHtcbiAgY29uc3QgbGlzdEl0ZW1XcmFwcGVyID0gJGNyZWF0ZUxpc3RJdGVtTm9kZSgpO1xuICByZXR1cm4gbGlzdEl0ZW1XcmFwcGVyLmFwcGVuZChub2RlKTtcbn1cblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBzdGFydCB2YWx1ZSBmb3IgYSBuZXcgbGlzdCBjcmVhdGVkIGJ5IHNwbGl0dGluZyBhbiBleGlzdGluZyBsaXN0LlxuICovXG5mdW5jdGlvbiAkZ2V0TmV3TGlzdFN0YXJ0KGxpc3QsIGxpc3RJdGVtKSB7XG4gIHJldHVybiBsaXN0LmdldFN0YXJ0KCkgKyBsaXN0SXRlbS5nZXRJbmRleFdpdGhpblBhcmVudCgpO1xufVxuXG5mdW5jdGlvbiAkaXNTZWxlY3RpbmdFbXB0eUxpc3RJdGVtKGFuY2hvck5vZGUsIG5vZGVzKSB7XG4gIHJldHVybiAkaXNMaXN0SXRlbU5vZGUoYW5jaG9yTm9kZSkgJiYgKG5vZGVzLmxlbmd0aCA9PT0gMCB8fCBub2Rlcy5sZW5ndGggPT09IDEgJiYgYW5jaG9yTm9kZS5pcyhub2Rlc1swXSkgJiYgYW5jaG9yTm9kZS5nZXRDaGlsZHJlblNpemUoKSA9PT0gMCk7XG59XG5cbi8qKlxuICogSW5zZXJ0cyBhIG5ldyBMaXN0Tm9kZS4gSWYgdGhlIHNlbGVjdGlvbidzIGFuY2hvciBub2RlIGlzIGFuIGVtcHR5IExpc3RJdGVtTm9kZSBhbmQgaXMgYSBjaGlsZCBvZlxuICogdGhlIHJvb3Qvc2hhZG93IHJvb3QsIGl0IHdpbGwgcmVwbGFjZSB0aGUgTGlzdEl0ZW1Ob2RlIHdpdGggYSBMaXN0Tm9kZSBhbmQgdGhlIG9sZCBMaXN0SXRlbU5vZGUuXG4gKiBPdGhlcndpc2UgaXQgd2lsbCByZXBsYWNlIGl0cyBwYXJlbnQgd2l0aCBhIG5ldyBMaXN0Tm9kZSBhbmQgcmUtaW5zZXJ0IHRoZSBMaXN0SXRlbU5vZGUgYW5kIGFueSBwcmV2aW91cyBjaGlsZHJlbi5cbiAqIElmIHRoZSBzZWxlY3Rpb24ncyBhbmNob3Igbm9kZSBpcyBub3QgYW4gZW1wdHkgTGlzdEl0ZW1Ob2RlLCBpdCB3aWxsIGFkZCBhIG5ldyBMaXN0Tm9kZSBvciBtZXJnZSBhbiBleGlzdGluZyBMaXN0Tm9kZSxcbiAqIHVubGVzcyB0aGUgdGhlIG5vZGUgaXMgYSBsZWFmIG5vZGUsIGluIHdoaWNoIGNhc2UgaXQgd2lsbCBhdHRlbXB0IHRvIGZpbmQgYSBMaXN0Tm9kZSB1cCB0aGUgYnJhbmNoIGFuZCByZXBsYWNlIGl0IHdpdGhcbiAqIGEgbmV3IExpc3ROb2RlLCBvciBjcmVhdGUgYSBuZXcgTGlzdE5vZGUgYXQgdGhlIG5lYXJlc3Qgcm9vdC9zaGFkb3cgcm9vdC5cbiAqIEBwYXJhbSBsaXN0VHlwZSAtIFRoZSB0eXBlIG9mIGxpc3QsIFwibnVtYmVyXCIgfCBcImJ1bGxldFwiIHwgXCJjaGVja1wiLlxuICovXG5mdW5jdGlvbiAkaW5zZXJ0TGlzdChsaXN0VHlwZSkge1xuICBjb25zdCBzZWxlY3Rpb24gPSAkZ2V0U2VsZWN0aW9uKCk7XG4gIGlmIChzZWxlY3Rpb24gIT09IG51bGwpIHtcbiAgICBsZXQgbm9kZXMgPSBzZWxlY3Rpb24uZ2V0Tm9kZXMoKTtcbiAgICBpZiAoJGlzUmFuZ2VTZWxlY3Rpb24oc2VsZWN0aW9uKSkge1xuICAgICAgY29uc3QgYW5jaG9yQW5kRm9jdXMgPSBzZWxlY3Rpb24uZ2V0U3RhcnRFbmRQb2ludHMoKTtcbiAgICAgIGlmICghKGFuY2hvckFuZEZvY3VzICE9PSBudWxsKSkge1xuICAgICAgICBmb3JtYXREZXZFcnJvck1lc3NhZ2UoYGluc2VydExpc3Q6IGFuY2hvciBzaG91bGQgYmUgZGVmaW5lZGApO1xuICAgICAgfVxuICAgICAgY29uc3QgW2FuY2hvcl0gPSBhbmNob3JBbmRGb2N1cztcbiAgICAgIGNvbnN0IGFuY2hvck5vZGUgPSBhbmNob3IuZ2V0Tm9kZSgpO1xuICAgICAgY29uc3QgYW5jaG9yTm9kZVBhcmVudCA9IGFuY2hvck5vZGUuZ2V0UGFyZW50KCk7XG4gICAgICBpZiAoJGlzUm9vdE9yU2hhZG93Um9vdChhbmNob3JOb2RlKSkge1xuICAgICAgICBjb25zdCBmaXJzdENoaWxkID0gYW5jaG9yTm9kZS5nZXRGaXJzdENoaWxkKCk7XG4gICAgICAgIGlmIChmaXJzdENoaWxkKSB7XG4gICAgICAgICAgbm9kZXMgPSBmaXJzdENoaWxkLnNlbGVjdFN0YXJ0KCkuZ2V0Tm9kZXMoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb25zdCBwYXJhZ3JhcGggPSAkY3JlYXRlUGFyYWdyYXBoTm9kZSgpO1xuICAgICAgICAgIGFuY2hvck5vZGUuYXBwZW5kKHBhcmFncmFwaCk7XG4gICAgICAgICAgbm9kZXMgPSBwYXJhZ3JhcGguc2VsZWN0KCkuZ2V0Tm9kZXMoKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICgkaXNTZWxlY3RpbmdFbXB0eUxpc3RJdGVtKGFuY2hvck5vZGUsIG5vZGVzKSkge1xuICAgICAgICBjb25zdCBsaXN0ID0gJGNyZWF0ZUxpc3ROb2RlKGxpc3RUeXBlKTtcbiAgICAgICAgaWYgKCRpc1Jvb3RPclNoYWRvd1Jvb3QoYW5jaG9yTm9kZVBhcmVudCkpIHtcbiAgICAgICAgICBhbmNob3JOb2RlLnJlcGxhY2UobGlzdCk7XG4gICAgICAgICAgY29uc3QgbGlzdEl0ZW0gPSAkY3JlYXRlTGlzdEl0ZW1Ob2RlKCk7XG4gICAgICAgICAgaWYgKCRpc0VsZW1lbnROb2RlKGFuY2hvck5vZGUpKSB7XG4gICAgICAgICAgICBsaXN0SXRlbS5zZXRGb3JtYXQoYW5jaG9yTm9kZS5nZXRGb3JtYXRUeXBlKCkpO1xuICAgICAgICAgICAgbGlzdEl0ZW0uc2V0SW5kZW50KGFuY2hvck5vZGUuZ2V0SW5kZW50KCkpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBsaXN0LmFwcGVuZChsaXN0SXRlbSk7XG4gICAgICAgIH0gZWxzZSBpZiAoJGlzTGlzdEl0ZW1Ob2RlKGFuY2hvck5vZGUpKSB7XG4gICAgICAgICAgY29uc3QgcGFyZW50ID0gYW5jaG9yTm9kZS5nZXRQYXJlbnRPclRocm93KCk7XG4gICAgICAgICAgYXBwZW5kKGxpc3QsIHBhcmVudC5nZXRDaGlsZHJlbigpKTtcbiAgICAgICAgICBwYXJlbnQucmVwbGFjZShsaXN0KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgfVxuICAgIGNvbnN0IGhhbmRsZWQgPSBuZXcgU2V0KCk7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBub2Rlcy5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3Qgbm9kZSA9IG5vZGVzW2ldO1xuICAgICAgaWYgKCRpc0VsZW1lbnROb2RlKG5vZGUpICYmIG5vZGUuaXNFbXB0eSgpICYmICEkaXNMaXN0SXRlbU5vZGUobm9kZSkgJiYgIWhhbmRsZWQuaGFzKG5vZGUuZ2V0S2V5KCkpKSB7XG4gICAgICAgICRjcmVhdGVMaXN0T3JNZXJnZShub2RlLCBsaXN0VHlwZSk7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgbGV0IHBhcmVudCA9ICRpc0xlYWZOb2RlKG5vZGUpID8gbm9kZS5nZXRQYXJlbnQoKSA6ICRpc0xpc3RJdGVtTm9kZShub2RlKSAmJiBub2RlLmlzRW1wdHkoKSA/IG5vZGUgOiBudWxsO1xuICAgICAgd2hpbGUgKHBhcmVudCAhPSBudWxsKSB7XG4gICAgICAgIGNvbnN0IHBhcmVudEtleSA9IHBhcmVudC5nZXRLZXkoKTtcbiAgICAgICAgaWYgKCRpc0xpc3ROb2RlKHBhcmVudCkpIHtcbiAgICAgICAgICBpZiAoIWhhbmRsZWQuaGFzKHBhcmVudEtleSkpIHtcbiAgICAgICAgICAgIGNvbnN0IG5ld0xpc3ROb2RlID0gJGNyZWF0ZUxpc3ROb2RlKGxpc3RUeXBlKTtcbiAgICAgICAgICAgIGFwcGVuZChuZXdMaXN0Tm9kZSwgcGFyZW50LmdldENoaWxkcmVuKCkpO1xuICAgICAgICAgICAgcGFyZW50LnJlcGxhY2UobmV3TGlzdE5vZGUpO1xuICAgICAgICAgICAgaGFuZGxlZC5hZGQocGFyZW50S2V5KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uc3QgbmV4dFBhcmVudCA9IHBhcmVudC5nZXRQYXJlbnQoKTtcbiAgICAgICAgICBpZiAoJGlzUm9vdE9yU2hhZG93Um9vdChuZXh0UGFyZW50KSAmJiAhaGFuZGxlZC5oYXMocGFyZW50S2V5KSkge1xuICAgICAgICAgICAgaGFuZGxlZC5hZGQocGFyZW50S2V5KTtcbiAgICAgICAgICAgICRjcmVhdGVMaXN0T3JNZXJnZShwYXJlbnQsIGxpc3RUeXBlKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBwYXJlbnQgPSBuZXh0UGFyZW50O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5mdW5jdGlvbiBhcHBlbmQobm9kZSwgbm9kZXNUb0FwcGVuZCkge1xuICBub2RlLnNwbGljZShub2RlLmdldENoaWxkcmVuU2l6ZSgpLCAwLCBub2Rlc1RvQXBwZW5kKTtcbn1cbmZ1bmN0aW9uICRjcmVhdGVMaXN0T3JNZXJnZShub2RlLCBsaXN0VHlwZSkge1xuICBpZiAoJGlzTGlzdE5vZGUobm9kZSkpIHtcbiAgICByZXR1cm4gbm9kZTtcbiAgfVxuICBjb25zdCBwcmV2aW91c1NpYmxpbmcgPSBub2RlLmdldFByZXZpb3VzU2libGluZygpO1xuICBjb25zdCBuZXh0U2libGluZyA9IG5vZGUuZ2V0TmV4dFNpYmxpbmcoKTtcbiAgY29uc3QgbGlzdEl0ZW0gPSAkY3JlYXRlTGlzdEl0ZW1Ob2RlKCk7XG4gIGFwcGVuZChsaXN0SXRlbSwgbm9kZS5nZXRDaGlsZHJlbigpKTtcbiAgbGV0IHRhcmdldExpc3Q7XG4gIGlmICgkaXNMaXN0Tm9kZShwcmV2aW91c1NpYmxpbmcpICYmIGxpc3RUeXBlID09PSBwcmV2aW91c1NpYmxpbmcuZ2V0TGlzdFR5cGUoKSkge1xuICAgIHByZXZpb3VzU2libGluZy5hcHBlbmQobGlzdEl0ZW0pO1xuICAgIC8vIGlmIHRoZSBzYW1lIHR5cGUgb2YgbGlzdCBpcyBvbiBib3RoIHNpZGVzLCBtZXJnZSB0aGVtLlxuICAgIGlmICgkaXNMaXN0Tm9kZShuZXh0U2libGluZykgJiYgbGlzdFR5cGUgPT09IG5leHRTaWJsaW5nLmdldExpc3RUeXBlKCkpIHtcbiAgICAgIGFwcGVuZChwcmV2aW91c1NpYmxpbmcsIG5leHRTaWJsaW5nLmdldENoaWxkcmVuKCkpO1xuICAgICAgbmV4dFNpYmxpbmcucmVtb3ZlKCk7XG4gICAgfVxuICAgIHRhcmdldExpc3QgPSBwcmV2aW91c1NpYmxpbmc7XG4gIH0gZWxzZSBpZiAoJGlzTGlzdE5vZGUobmV4dFNpYmxpbmcpICYmIGxpc3RUeXBlID09PSBuZXh0U2libGluZy5nZXRMaXN0VHlwZSgpKSB7XG4gICAgbmV4dFNpYmxpbmcuZ2V0Rmlyc3RDaGlsZE9yVGhyb3coKS5pbnNlcnRCZWZvcmUobGlzdEl0ZW0pO1xuICAgIHRhcmdldExpc3QgPSBuZXh0U2libGluZztcbiAgfSBlbHNlIHtcbiAgICBjb25zdCBsaXN0ID0gJGNyZWF0ZUxpc3ROb2RlKGxpc3RUeXBlKTtcbiAgICBsaXN0LmFwcGVuZChsaXN0SXRlbSk7XG4gICAgbm9kZS5yZXBsYWNlKGxpc3QpO1xuICAgIHRhcmdldExpc3QgPSBsaXN0O1xuICB9XG4gIC8vIGxpc3RJdGVtIG5lZWRzIHRvIGJlIGF0dGFjaGVkIHRvIHJvb3QgcHJpb3IgdG8gc2V0dGluZyBpbmRlbnRcbiAgbGlzdEl0ZW0uc2V0Rm9ybWF0KG5vZGUuZ2V0Rm9ybWF0VHlwZSgpKTtcbiAgbGlzdEl0ZW0uc2V0SW5kZW50KG5vZGUuZ2V0SW5kZW50KCkpO1xuXG4gIC8vIFByZXNlcnZlIGVsZW1lbnQtYW5jaG9yZWQgc2VsZWN0aW9ucyBieSB1cGRhdGluZyB0aGVtIHRvIGFuY2hvciB0byB0aGUgbGlzdEl0ZW0gaW5zdGVhZCBvZiB0aGUgbGlzdE5vZGUuXG4gIGNvbnN0IHNlbGVjdGlvbiA9ICRnZXRTZWxlY3Rpb24oKTtcbiAgaWYgKCRpc1JhbmdlU2VsZWN0aW9uKHNlbGVjdGlvbikpIHtcbiAgICBpZiAodGFyZ2V0TGlzdC5nZXRLZXkoKSA9PT0gc2VsZWN0aW9uLmFuY2hvci5rZXkpIHtcbiAgICAgIHNlbGVjdGlvbi5hbmNob3Iuc2V0KGxpc3RJdGVtLmdldEtleSgpLCBzZWxlY3Rpb24uYW5jaG9yLm9mZnNldCwgJ2VsZW1lbnQnKTtcbiAgICB9XG4gICAgaWYgKHRhcmdldExpc3QuZ2V0S2V5KCkgPT09IHNlbGVjdGlvbi5mb2N1cy5rZXkpIHtcbiAgICAgIHNlbGVjdGlvbi5mb2N1cy5zZXQobGlzdEl0ZW0uZ2V0S2V5KCksIHNlbGVjdGlvbi5mb2N1cy5vZmZzZXQsICdlbGVtZW50Jyk7XG4gICAgfVxuICB9XG4gIG5vZGUucmVtb3ZlKCk7XG4gIHJldHVybiB0YXJnZXRMaXN0O1xufVxuXG4vKipcbiAqIEEgcmVjdXJzaXZlIGZ1bmN0aW9uIHRoYXQgZ29lcyB0aHJvdWdoIGVhY2ggbGlzdCBhbmQgdGhlaXIgY2hpbGRyZW4sIGluY2x1ZGluZyBuZXN0ZWQgbGlzdHMsXG4gKiBhcHBlbmRpbmcgbGlzdDIgY2hpbGRyZW4gYWZ0ZXIgbGlzdDEgY2hpbGRyZW4gYW5kIHVwZGF0aW5nIExpc3RJdGVtTm9kZSB2YWx1ZXMuXG4gKiBAcGFyYW0gbGlzdDEgLSBUaGUgZmlyc3QgbGlzdCB0byBiZSBtZXJnZWQuXG4gKiBAcGFyYW0gbGlzdDIgLSBUaGUgc2Vjb25kIGxpc3QgdG8gYmUgbWVyZ2VkLlxuICovXG5mdW5jdGlvbiBtZXJnZUxpc3RzKGxpc3QxLCBsaXN0Mikge1xuICBjb25zdCBsaXN0SXRlbTEgPSBsaXN0MS5nZXRMYXN0Q2hpbGQoKTtcbiAgY29uc3QgbGlzdEl0ZW0yID0gbGlzdDIuZ2V0Rmlyc3RDaGlsZCgpO1xuICBpZiAobGlzdEl0ZW0xICYmIGxpc3RJdGVtMiAmJiBpc05lc3RlZExpc3ROb2RlKGxpc3RJdGVtMSkgJiYgaXNOZXN0ZWRMaXN0Tm9kZShsaXN0SXRlbTIpKSB7XG4gICAgbWVyZ2VMaXN0cyhsaXN0SXRlbTEuZ2V0Rmlyc3RDaGlsZCgpLCBsaXN0SXRlbTIuZ2V0Rmlyc3RDaGlsZCgpKTtcbiAgICBsaXN0SXRlbTIucmVtb3ZlKCk7XG4gIH1cbiAgY29uc3QgdG9NZXJnZSA9IGxpc3QyLmdldENoaWxkcmVuKCk7XG4gIGlmICh0b01lcmdlLmxlbmd0aCA+IDApIHtcbiAgICBsaXN0MS5hcHBlbmQoLi4udG9NZXJnZSk7XG4gIH1cbiAgbGlzdDIucmVtb3ZlKCk7XG59XG5cbi8qKlxuICogU2VhcmNoZXMgZm9yIHRoZSBuZWFyZXN0IGFuY2VzdHJhbCBMaXN0Tm9kZSBhbmQgcmVtb3ZlcyBpdC4gSWYgc2VsZWN0aW9uIGlzIGFuIGVtcHR5IExpc3RJdGVtTm9kZVxuICogaXQgd2lsbCByZW1vdmUgdGhlIHdob2xlIGxpc3QsIGluY2x1ZGluZyB0aGUgTGlzdEl0ZW1Ob2RlLiBGb3IgZWFjaCBMaXN0SXRlbU5vZGUgaW4gdGhlIExpc3ROb2RlLFxuICogcmVtb3ZlTGlzdCB3aWxsIGFsc28gZ2VuZXJhdGUgbmV3IFBhcmFncmFwaE5vZGVzIGluIHRoZSByZW1vdmVkIExpc3ROb2RlJ3MgcGxhY2UuIEFueSBjaGlsZCBub2RlXG4gKiBpbnNpZGUgYSBMaXN0SXRlbU5vZGUgd2lsbCBiZSBhcHBlbmRlZCB0byB0aGUgbmV3IFBhcmFncmFwaE5vZGVzLlxuICovXG5mdW5jdGlvbiAkcmVtb3ZlTGlzdCgpIHtcbiAgY29uc3Qgc2VsZWN0aW9uID0gJGdldFNlbGVjdGlvbigpO1xuICBpZiAoJGlzUmFuZ2VTZWxlY3Rpb24oc2VsZWN0aW9uKSkge1xuICAgIGNvbnN0IGxpc3ROb2RlcyA9IG5ldyBTZXQoKTtcbiAgICBjb25zdCBub2RlcyA9IHNlbGVjdGlvbi5nZXROb2RlcygpO1xuICAgIGNvbnN0IGFuY2hvck5vZGUgPSBzZWxlY3Rpb24uYW5jaG9yLmdldE5vZGUoKTtcbiAgICBpZiAoJGlzU2VsZWN0aW5nRW1wdHlMaXN0SXRlbShhbmNob3JOb2RlLCBub2RlcykpIHtcbiAgICAgIGxpc3ROb2Rlcy5hZGQoJGdldFRvcExpc3ROb2RlKGFuY2hvck5vZGUpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBub2Rlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBub2RlID0gbm9kZXNbaV07XG4gICAgICAgIGlmICgkaXNMZWFmTm9kZShub2RlKSkge1xuICAgICAgICAgIGNvbnN0IGxpc3RJdGVtTm9kZSA9ICRnZXROZWFyZXN0Tm9kZU9mVHlwZShub2RlLCBMaXN0SXRlbU5vZGUpO1xuICAgICAgICAgIGlmIChsaXN0SXRlbU5vZGUgIT0gbnVsbCkge1xuICAgICAgICAgICAgbGlzdE5vZGVzLmFkZCgkZ2V0VG9wTGlzdE5vZGUobGlzdEl0ZW1Ob2RlKSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIGZvciAoY29uc3QgbGlzdE5vZGUgb2YgbGlzdE5vZGVzKSB7XG4gICAgICBsZXQgaW5zZXJ0aW9uUG9pbnQgPSBsaXN0Tm9kZTtcbiAgICAgIGNvbnN0IGxpc3RJdGVtcyA9ICRnZXRBbGxMaXN0SXRlbXMobGlzdE5vZGUpO1xuICAgICAgZm9yIChjb25zdCBsaXN0SXRlbU5vZGUgb2YgbGlzdEl0ZW1zKSB7XG4gICAgICAgIGNvbnN0IHBhcmFncmFwaCA9ICRjcmVhdGVQYXJhZ3JhcGhOb2RlKCkuc2V0VGV4dFN0eWxlKHNlbGVjdGlvbi5zdHlsZSkuc2V0VGV4dEZvcm1hdChzZWxlY3Rpb24uZm9ybWF0KTtcbiAgICAgICAgYXBwZW5kKHBhcmFncmFwaCwgbGlzdEl0ZW1Ob2RlLmdldENoaWxkcmVuKCkpO1xuICAgICAgICBpbnNlcnRpb25Qb2ludC5pbnNlcnRBZnRlcihwYXJhZ3JhcGgpO1xuICAgICAgICBpbnNlcnRpb25Qb2ludCA9IHBhcmFncmFwaDtcblxuICAgICAgICAvLyBXaGVuIHRoZSBhbmNob3IgYW5kIGZvY3VzIGZhbGwgb24gdGhlIHRleHROb2RlXG4gICAgICAgIC8vIHdlIGRvbid0IGhhdmUgdG8gY2hhbmdlIHRoZSBzZWxlY3Rpb24gYmVjYXVzZSB0aGUgdGV4dE5vZGUgd2lsbCBiZSBhcHBlbmRlZCB0b1xuICAgICAgICAvLyB0aGUgbmV3bHkgZ2VuZXJhdGVkIHBhcmFncmFwaC5cbiAgICAgICAgLy8gV2hlbiBzZWxlY3Rpb24gaXMgaW4gZW1wdHkgbmVzdGVkIGxpc3QgaXRlbSwgc2VsZWN0aW9uIGlzIGFjdHVhbGx5IG9uIHRoZSBsaXN0SXRlbU5vZGUuXG4gICAgICAgIC8vIFdoZW4gdGhlIGNvcnJlc3BvbmRpbmcgbGlzdEl0ZW1Ob2RlIGlzIGRlbGV0ZWQgYW5kIHJlcGxhY2VkIGJ5IHRoZSBuZXdseSBnZW5lcmF0ZWQgcGFyYWdyYXBoXG4gICAgICAgIC8vIHdlIHNob3VsZCBtYW51YWxseSBzZXQgdGhlIHNlbGVjdGlvbidzIGZvY3VzIGFuZCBhbmNob3IgdG8gdGhlIG5ld2x5IGdlbmVyYXRlZCBwYXJhZ3JhcGguXG4gICAgICAgIGlmIChsaXN0SXRlbU5vZGUuX19rZXkgPT09IHNlbGVjdGlvbi5hbmNob3Iua2V5KSB7XG4gICAgICAgICAgJHNldFBvaW50RnJvbUNhcmV0KHNlbGVjdGlvbi5hbmNob3IsICRub3JtYWxpemVDYXJldCgkZ2V0Q2hpbGRDYXJldChwYXJhZ3JhcGgsICduZXh0JykpKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobGlzdEl0ZW1Ob2RlLl9fa2V5ID09PSBzZWxlY3Rpb24uZm9jdXMua2V5KSB7XG4gICAgICAgICAgJHNldFBvaW50RnJvbUNhcmV0KHNlbGVjdGlvbi5mb2N1cywgJG5vcm1hbGl6ZUNhcmV0KCRnZXRDaGlsZENhcmV0KHBhcmFncmFwaCwgJ25leHQnKSkpO1xuICAgICAgICB9XG4gICAgICAgIGxpc3RJdGVtTm9kZS5yZW1vdmUoKTtcbiAgICAgIH1cbiAgICAgIGxpc3ROb2RlLnJlbW92ZSgpO1xuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIFRha2VzIHRoZSB2YWx1ZSBvZiBhIGNoaWxkIExpc3RJdGVtTm9kZSBhbmQgbWFrZXMgaXQgdGhlIHZhbHVlIHRoZSBMaXN0SXRlbU5vZGVcbiAqIHNob3VsZCBiZSBpZiBpdCBpc24ndCBhbHJlYWR5LiBBbHNvIGVuc3VyZXMgdGhhdCBjaGVja2VkIGlzIHVuZGVmaW5lZCBpZiB0aGVcbiAqIHBhcmVudCBkb2VzIG5vdCBoYXZlIGEgbGlzdCB0eXBlIG9mICdjaGVjaycuXG4gKiBAcGFyYW0gbGlzdCAtIFRoZSBsaXN0IHdob3NlIGNoaWxkcmVuIGFyZSB1cGRhdGVkLlxuICovXG5mdW5jdGlvbiB1cGRhdGVDaGlsZHJlbkxpc3RJdGVtVmFsdWUobGlzdCkge1xuICBjb25zdCBpc05vdENoZWNrbGlzdCA9IGxpc3QuZ2V0TGlzdFR5cGUoKSAhPT0gJ2NoZWNrJztcbiAgbGV0IHZhbHVlID0gbGlzdC5nZXRTdGFydCgpO1xuICBmb3IgKGNvbnN0IGNoaWxkIG9mIGxpc3QuZ2V0Q2hpbGRyZW4oKSkge1xuICAgIGlmICgkaXNMaXN0SXRlbU5vZGUoY2hpbGQpKSB7XG4gICAgICBpZiAoY2hpbGQuZ2V0VmFsdWUoKSAhPT0gdmFsdWUpIHtcbiAgICAgICAgY2hpbGQuc2V0VmFsdWUodmFsdWUpO1xuICAgICAgfVxuICAgICAgaWYgKGlzTm90Q2hlY2tsaXN0ICYmIGNoaWxkLmdldExhdGVzdCgpLl9fY2hlY2tlZCAhPSBudWxsKSB7XG4gICAgICAgIGNoaWxkLnNldENoZWNrZWQodW5kZWZpbmVkKTtcbiAgICAgIH1cbiAgICAgIGlmICghJGlzTGlzdE5vZGUoY2hpbGQuZ2V0Rmlyc3RDaGlsZCgpKSkge1xuICAgICAgICB2YWx1ZSsrO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIE1lcmdlIHRoZSBuZXh0IHNpYmxpbmcgbGlzdCBpZiBzYW1lIHR5cGUuXG4gKiA8dWw+IHdpbGwgbWVyZ2Ugd2l0aCA8dWw+LCBidXQgTk9UIDx1bD4gd2l0aCA8b2w+LlxuICogQHBhcmFtIGxpc3QgLSBUaGUgbGlzdCB3aG9zZSBuZXh0IHNpYmxpbmcgc2hvdWxkIGJlIHBvdGVudGlhbGx5IG1lcmdlZFxuICovXG5mdW5jdGlvbiBtZXJnZU5leHRTaWJsaW5nTGlzdElmU2FtZVR5cGUobGlzdCkge1xuICBjb25zdCBuZXh0U2libGluZyA9IGxpc3QuZ2V0TmV4dFNpYmxpbmcoKTtcbiAgaWYgKCRpc0xpc3ROb2RlKG5leHRTaWJsaW5nKSAmJiBsaXN0LmdldExpc3RUeXBlKCkgPT09IG5leHRTaWJsaW5nLmdldExpc3RUeXBlKCkpIHtcbiAgICBtZXJnZUxpc3RzKGxpc3QsIG5leHRTaWJsaW5nKTtcbiAgfVxufVxuXG4vKipcbiAqIEFkZHMgYW4gZW1wdHkgTGlzdE5vZGUvTGlzdEl0ZW1Ob2RlIGNoYWluIGF0IGxpc3RJdGVtTm9kZSwgc28gYXMgdG9cbiAqIGNyZWF0ZSBhbiBpbmRlbnQgZWZmZWN0LiBXb24ndCBpbmRlbnQgTGlzdEl0ZW1Ob2RlcyB0aGF0IGhhdmUgYSBMaXN0Tm9kZSBhc1xuICogYSBjaGlsZCwgYnV0IGRvZXMgbWVyZ2Ugc2libGluZyBMaXN0SXRlbU5vZGVzIGlmIG9uZSBoYXMgYSBuZXN0ZWQgTGlzdE5vZGUuXG4gKiBAcGFyYW0gbGlzdEl0ZW1Ob2RlIC0gVGhlIExpc3RJdGVtTm9kZSB0byBiZSBpbmRlbnRlZC5cbiAqL1xuZnVuY3Rpb24gJGhhbmRsZUluZGVudChsaXN0SXRlbU5vZGUpIHtcbiAgLy8gZ28gdGhyb3VnaCBlYWNoIG5vZGUgYW5kIGRlY2lkZSB3aGVyZSB0byBtb3ZlIGl0LlxuICBjb25zdCByZW1vdmVkID0gbmV3IFNldCgpO1xuICBpZiAoaXNOZXN0ZWRMaXN0Tm9kZShsaXN0SXRlbU5vZGUpIHx8IHJlbW92ZWQuaGFzKGxpc3RJdGVtTm9kZS5nZXRLZXkoKSkpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgY29uc3QgcGFyZW50ID0gbGlzdEl0ZW1Ob2RlLmdldFBhcmVudCgpO1xuXG4gIC8vIFdlIGNhbiBjYXN0IGJvdGggb2YgdGhlIGJlbG93IGBpc05lc3RlZExpc3ROb2RlYCBvbmx5IHJldHVybnMgYSBib29sZWFuIHR5cGUgaW5zdGVhZCBvZiBhIHVzZXItZGVmaW5lZCB0eXBlIGd1YXJkc1xuICBjb25zdCBuZXh0U2libGluZyA9IGxpc3RJdGVtTm9kZS5nZXROZXh0U2libGluZygpO1xuICBjb25zdCBwcmV2aW91c1NpYmxpbmcgPSBsaXN0SXRlbU5vZGUuZ2V0UHJldmlvdXNTaWJsaW5nKCk7XG4gIC8vIGlmIHRoZXJlIGFyZSBuZXN0ZWQgbGlzdHMgb24gZWl0aGVyIHNpZGUsIG1lcmdlIHRoZW0gYWxsIHRvZ2V0aGVyLlxuXG4gIGlmIChpc05lc3RlZExpc3ROb2RlKG5leHRTaWJsaW5nKSAmJiBpc05lc3RlZExpc3ROb2RlKHByZXZpb3VzU2libGluZykpIHtcbiAgICBjb25zdCBpbm5lckxpc3QgPSBwcmV2aW91c1NpYmxpbmcuZ2V0Rmlyc3RDaGlsZCgpO1xuICAgIGlmICgkaXNMaXN0Tm9kZShpbm5lckxpc3QpKSB7XG4gICAgICBpbm5lckxpc3QuYXBwZW5kKGxpc3RJdGVtTm9kZSk7XG4gICAgICBjb25zdCBuZXh0SW5uZXJMaXN0ID0gbmV4dFNpYmxpbmcuZ2V0Rmlyc3RDaGlsZCgpO1xuICAgICAgaWYgKCRpc0xpc3ROb2RlKG5leHRJbm5lckxpc3QpKSB7XG4gICAgICAgIGNvbnN0IGNoaWxkcmVuID0gbmV4dElubmVyTGlzdC5nZXRDaGlsZHJlbigpO1xuICAgICAgICBhcHBlbmQoaW5uZXJMaXN0LCBjaGlsZHJlbik7XG4gICAgICAgIG5leHRTaWJsaW5nLnJlbW92ZSgpO1xuICAgICAgICByZW1vdmVkLmFkZChuZXh0U2libGluZy5nZXRLZXkoKSk7XG4gICAgICB9XG4gICAgfVxuICB9IGVsc2UgaWYgKGlzTmVzdGVkTGlzdE5vZGUobmV4dFNpYmxpbmcpKSB7XG4gICAgLy8gaWYgdGhlIExpc3RJdGVtTm9kZSBpcyBuZXh0IHRvIGEgbmVzdGVkIExpc3ROb2RlLCBtZXJnZSB0aGVtXG4gICAgY29uc3QgaW5uZXJMaXN0ID0gbmV4dFNpYmxpbmcuZ2V0Rmlyc3RDaGlsZCgpO1xuICAgIGlmICgkaXNMaXN0Tm9kZShpbm5lckxpc3QpKSB7XG4gICAgICBjb25zdCBmaXJzdENoaWxkID0gaW5uZXJMaXN0LmdldEZpcnN0Q2hpbGQoKTtcbiAgICAgIGlmIChmaXJzdENoaWxkICE9PSBudWxsKSB7XG4gICAgICAgIGZpcnN0Q2hpbGQuaW5zZXJ0QmVmb3JlKGxpc3RJdGVtTm9kZSk7XG4gICAgICB9XG4gICAgfVxuICB9IGVsc2UgaWYgKGlzTmVzdGVkTGlzdE5vZGUocHJldmlvdXNTaWJsaW5nKSkge1xuICAgIGNvbnN0IGlubmVyTGlzdCA9IHByZXZpb3VzU2libGluZy5nZXRGaXJzdENoaWxkKCk7XG4gICAgaWYgKCRpc0xpc3ROb2RlKGlubmVyTGlzdCkpIHtcbiAgICAgIGlubmVyTGlzdC5hcHBlbmQobGlzdEl0ZW1Ob2RlKTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgLy8gb3RoZXJ3aXNlLCB3ZSBuZWVkIHRvIGNyZWF0ZSBhIG5ldyBuZXN0ZWQgTGlzdE5vZGVcblxuICAgIGlmICgkaXNMaXN0Tm9kZShwYXJlbnQpKSB7XG4gICAgICBjb25zdCBuZXdMaXN0SXRlbSA9ICRjcmVhdGVMaXN0SXRlbU5vZGUoKS5zZXRUZXh0Rm9ybWF0KGxpc3RJdGVtTm9kZS5nZXRUZXh0Rm9ybWF0KCkpLnNldFRleHRTdHlsZShsaXN0SXRlbU5vZGUuZ2V0VGV4dFN0eWxlKCkpO1xuICAgICAgY29uc3QgbmV3TGlzdCA9ICRjcmVhdGVMaXN0Tm9kZShwYXJlbnQuZ2V0TGlzdFR5cGUoKSkuc2V0VGV4dEZvcm1hdChwYXJlbnQuZ2V0VGV4dEZvcm1hdCgpKS5zZXRUZXh0U3R5bGUocGFyZW50LmdldFRleHRTdHlsZSgpKTtcbiAgICAgIG5ld0xpc3RJdGVtLmFwcGVuZChuZXdMaXN0KTtcbiAgICAgIG5ld0xpc3QuYXBwZW5kKGxpc3RJdGVtTm9kZSk7XG4gICAgICBpZiAocHJldmlvdXNTaWJsaW5nKSB7XG4gICAgICAgIHByZXZpb3VzU2libGluZy5pbnNlcnRBZnRlcihuZXdMaXN0SXRlbSk7XG4gICAgICB9IGVsc2UgaWYgKG5leHRTaWJsaW5nKSB7XG4gICAgICAgIG5leHRTaWJsaW5nLmluc2VydEJlZm9yZShuZXdMaXN0SXRlbSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwYXJlbnQuYXBwZW5kKG5ld0xpc3RJdGVtKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBSZW1vdmVzIGFuIGluZGVudCBieSByZW1vdmluZyBhbiBlbXB0eSBMaXN0Tm9kZS9MaXN0SXRlbU5vZGUgY2hhaW4uIEFuIGluZGVudGVkIExpc3RJdGVtTm9kZVxuICogaGFzIGEgZ3JlYXQgZ3JhbmRwYXJlbnQgbm9kZSBvZiB0eXBlIExpc3ROb2RlLCB3aGljaCBpcyB3aGVyZSB0aGUgTGlzdEl0ZW1Ob2RlIHdpbGwgcmVzaWRlXG4gKiB3aXRoaW4gYXMgYSBjaGlsZC5cbiAqIEBwYXJhbSBsaXN0SXRlbU5vZGUgLSBUaGUgTGlzdEl0ZW1Ob2RlIHRvIHJlbW92ZSB0aGUgaW5kZW50IChvdXRkZW50KS5cbiAqL1xuZnVuY3Rpb24gJGhhbmRsZU91dGRlbnQobGlzdEl0ZW1Ob2RlKSB7XG4gIC8vIGdvIHRocm91Z2ggZWFjaCBub2RlIGFuZCBkZWNpZGUgd2hlcmUgdG8gbW92ZSBpdC5cblxuICBpZiAoaXNOZXN0ZWRMaXN0Tm9kZShsaXN0SXRlbU5vZGUpKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIGNvbnN0IHBhcmVudExpc3QgPSBsaXN0SXRlbU5vZGUuZ2V0UGFyZW50KCk7XG4gIGNvbnN0IGdyYW5kcGFyZW50TGlzdEl0ZW0gPSBwYXJlbnRMaXN0ID8gcGFyZW50TGlzdC5nZXRQYXJlbnQoKSA6IHVuZGVmaW5lZDtcbiAgY29uc3QgZ3JlYXRHcmFuZHBhcmVudExpc3QgPSBncmFuZHBhcmVudExpc3RJdGVtID8gZ3JhbmRwYXJlbnRMaXN0SXRlbS5nZXRQYXJlbnQoKSA6IHVuZGVmaW5lZDtcbiAgLy8gSWYgaXQgZG9lc24ndCBoYXZlIHRoZXNlIGFuY2VzdG9ycywgaXQncyBub3QgaW5kZW50ZWQuXG5cbiAgaWYgKCRpc0xpc3ROb2RlKGdyZWF0R3JhbmRwYXJlbnRMaXN0KSAmJiAkaXNMaXN0SXRlbU5vZGUoZ3JhbmRwYXJlbnRMaXN0SXRlbSkgJiYgJGlzTGlzdE5vZGUocGFyZW50TGlzdCkpIHtcbiAgICAvLyBpZiBpdCdzIHRoZSBmaXJzdCBjaGlsZCBpbiBpdCdzIHBhcmVudCBsaXN0LCBpbnNlcnQgaXQgaW50byB0aGVcbiAgICAvLyBncmVhdCBncmFuZHBhcmVudCBsaXN0IGJlZm9yZSB0aGUgZ3JhbmRwYXJlbnRcbiAgICBjb25zdCBmaXJzdENoaWxkID0gcGFyZW50TGlzdCA/IHBhcmVudExpc3QuZ2V0Rmlyc3RDaGlsZCgpIDogdW5kZWZpbmVkO1xuICAgIGNvbnN0IGxhc3RDaGlsZCA9IHBhcmVudExpc3QgPyBwYXJlbnRMaXN0LmdldExhc3RDaGlsZCgpIDogdW5kZWZpbmVkO1xuICAgIGlmIChsaXN0SXRlbU5vZGUuaXMoZmlyc3RDaGlsZCkpIHtcbiAgICAgIGdyYW5kcGFyZW50TGlzdEl0ZW0uaW5zZXJ0QmVmb3JlKGxpc3RJdGVtTm9kZSk7XG4gICAgICBpZiAocGFyZW50TGlzdC5pc0VtcHR5KCkpIHtcbiAgICAgICAgZ3JhbmRwYXJlbnRMaXN0SXRlbS5yZW1vdmUoKTtcbiAgICAgIH1cbiAgICAgIC8vIGlmIGl0J3MgdGhlIGxhc3QgY2hpbGQgaW4gaXQncyBwYXJlbnQgbGlzdCwgaW5zZXJ0IGl0IGludG8gdGhlXG4gICAgICAvLyBncmVhdCBncmFuZHBhcmVudCBsaXN0IGFmdGVyIHRoZSBncmFuZHBhcmVudC5cbiAgICB9IGVsc2UgaWYgKGxpc3RJdGVtTm9kZS5pcyhsYXN0Q2hpbGQpKSB7XG4gICAgICBncmFuZHBhcmVudExpc3RJdGVtLmluc2VydEFmdGVyKGxpc3RJdGVtTm9kZSk7XG4gICAgICBpZiAocGFyZW50TGlzdC5pc0VtcHR5KCkpIHtcbiAgICAgICAgZ3JhbmRwYXJlbnRMaXN0SXRlbS5yZW1vdmUoKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLy8gb3RoZXJ3aXNlLCB3ZSBuZWVkIHRvIHNwbGl0IHRoZSBzaWJsaW5ncyBpbnRvIHR3byBuZXcgbmVzdGVkIGxpc3RzXG4gICAgICBjb25zdCBsaXN0VHlwZSA9IHBhcmVudExpc3QuZ2V0TGlzdFR5cGUoKTtcbiAgICAgIGNvbnN0IHByZXZpb3VzU2libGluZ3NMaXN0SXRlbSA9ICRjcmVhdGVMaXN0SXRlbU5vZGUoKTtcbiAgICAgIGNvbnN0IHByZXZpb3VzU2libGluZ3NMaXN0ID0gJGNyZWF0ZUxpc3ROb2RlKGxpc3RUeXBlKTtcbiAgICAgIHByZXZpb3VzU2libGluZ3NMaXN0SXRlbS5hcHBlbmQocHJldmlvdXNTaWJsaW5nc0xpc3QpO1xuICAgICAgbGlzdEl0ZW1Ob2RlLmdldFByZXZpb3VzU2libGluZ3MoKS5mb3JFYWNoKHNpYmxpbmcgPT4gcHJldmlvdXNTaWJsaW5nc0xpc3QuYXBwZW5kKHNpYmxpbmcpKTtcbiAgICAgIGNvbnN0IG5leHRTaWJsaW5nc0xpc3RJdGVtID0gJGNyZWF0ZUxpc3RJdGVtTm9kZSgpO1xuICAgICAgY29uc3QgbmV4dFNpYmxpbmdzTGlzdCA9ICRjcmVhdGVMaXN0Tm9kZShsaXN0VHlwZSk7XG4gICAgICBuZXh0U2libGluZ3NMaXN0SXRlbS5hcHBlbmQobmV4dFNpYmxpbmdzTGlzdCk7XG4gICAgICBhcHBlbmQobmV4dFNpYmxpbmdzTGlzdCwgbGlzdEl0ZW1Ob2RlLmdldE5leHRTaWJsaW5ncygpKTtcbiAgICAgIC8vIHB1dCB0aGUgc2libGluZyBuZXN0ZWQgbGlzdHMgb24gZWl0aGVyIHNpZGUgb2YgdGhlIGdyYW5kcGFyZW50IGxpc3QgaXRlbSBpbiB0aGUgZ3JlYXQgZ3JhbmRwYXJlbnQuXG4gICAgICBncmFuZHBhcmVudExpc3RJdGVtLmluc2VydEJlZm9yZShwcmV2aW91c1NpYmxpbmdzTGlzdEl0ZW0pO1xuICAgICAgZ3JhbmRwYXJlbnRMaXN0SXRlbS5pbnNlcnRBZnRlcihuZXh0U2libGluZ3NMaXN0SXRlbSk7XG4gICAgICAvLyByZXBsYWNlIHRoZSBncmFuZHBhcmVudCBsaXN0IGl0ZW0gKG5vdyBiZXR3ZWVuIHRoZSBzaWJsaW5ncykgd2l0aCB0aGUgb3V0ZGVudGVkIGxpc3QgaXRlbS5cbiAgICAgIGdyYW5kcGFyZW50TGlzdEl0ZW0ucmVwbGFjZShsaXN0SXRlbU5vZGUpO1xuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIEF0dGVtcHRzIHRvIGluc2VydCBhIFBhcmFncmFwaE5vZGUgYXQgc2VsZWN0aW9uIGFuZCBzZWxlY3RzIHRoZSBuZXcgbm9kZS4gVGhlIHNlbGVjdGlvbiBtdXN0IGNvbnRhaW4gYSBMaXN0SXRlbU5vZGVcbiAqIG9yIGEgbm9kZSB0aGF0IGRvZXMgbm90IGFscmVhZHkgY29udGFpbiB0ZXh0LiBJZiBpdHMgZ3JhbmRwYXJlbnQgaXMgdGhlIHJvb3Qvc2hhZG93IHJvb3QsIGl0IHdpbGwgZ2V0IHRoZSBMaXN0Tm9kZVxuICogKHdoaWNoIHNob3VsZCBiZSB0aGUgcGFyZW50IG5vZGUpIGFuZCBpbnNlcnQgdGhlIFBhcmFncmFwaE5vZGUgYXMgYSBzaWJsaW5nIHRvIHRoZSBMaXN0Tm9kZS4gSWYgdGhlIExpc3ROb2RlIGlzXG4gKiBuZXN0ZWQgaW4gYSBMaXN0SXRlbU5vZGUgaW5zdGVhZCwgaXQgd2lsbCBhZGQgdGhlIFBhcmFncmFwaE5vZGUgYWZ0ZXIgdGhlIGdyYW5kcGFyZW50IExpc3RJdGVtTm9kZS5cbiAqIFRocm93cyBhbiBpbnZhcmlhbnQgaWYgdGhlIHNlbGVjdGlvbiBpcyBub3QgYSBjaGlsZCBvZiBhIExpc3ROb2RlLlxuICogQHJldHVybnMgdHJ1ZSBpZiBhIFBhcmFncmFwaE5vZGUgd2FzIGluc2VydGVkIHN1Y2Nlc3NmdWxseSwgZmFsc2UgaWYgdGhlcmUgaXMgbm8gc2VsZWN0aW9uXG4gKiBvciB0aGUgc2VsZWN0aW9uIGRvZXMgbm90IGNvbnRhaW4gYSBMaXN0SXRlbU5vZGUgb3IgdGhlIG5vZGUgYWxyZWFkeSBob2xkcyB0ZXh0LlxuICovXG5mdW5jdGlvbiAkaGFuZGxlTGlzdEluc2VydFBhcmFncmFwaChyZXN0b3JlTnVtYmVyaW5nID0gZmFsc2UpIHtcbiAgY29uc3Qgc2VsZWN0aW9uID0gJGdldFNlbGVjdGlvbigpO1xuICBpZiAoISRpc1JhbmdlU2VsZWN0aW9uKHNlbGVjdGlvbikgfHwgIXNlbGVjdGlvbi5pc0NvbGxhcHNlZCgpKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIC8vIE9ubHkgcnVuIHRoaXMgY29kZSBvbiBlbXB0eSBsaXN0IGl0ZW1zIChpbmNsdWRpbmcgd2hpdGVzcGFjZS1vbmx5KVxuICBjb25zdCBhbmNob3IgPSBzZWxlY3Rpb24uYW5jaG9yLmdldE5vZGUoKTtcbiAgbGV0IGxpc3RJdGVtID0gbnVsbDtcbiAgaWYgKCRpc0xpc3RJdGVtTm9kZShhbmNob3IpICYmIGFuY2hvci5nZXRDaGlsZHJlblNpemUoKSA9PT0gMCkge1xuICAgIC8vIFRydWx5IGVtcHR5IGxpc3QgaXRlbSAoZWxlbWVudCBzZWxlY3Rpb24pXG4gICAgbGlzdEl0ZW0gPSBhbmNob3I7XG4gIH0gZWxzZSBpZiAoJGlzVGV4dE5vZGUoYW5jaG9yKSkge1xuICAgIC8vIENoZWNrIGlmIHRoZSBlbnRpcmUgbGlzdCBpdGVtIGNvbnRhaW5zIG9ubHkgd2hpdGVzcGFjZSB0ZXh0IG5vZGVzXG4gICAgY29uc3QgcGFyZW50TGlzdEl0ZW0gPSBhbmNob3IuZ2V0UGFyZW50KCk7XG4gICAgaWYgKCRpc0xpc3RJdGVtTm9kZShwYXJlbnRMaXN0SXRlbSkgJiYgcGFyZW50TGlzdEl0ZW0uZ2V0Q2hpbGRyZW4oKS5ldmVyeShub2RlID0+ICRpc1RleHROb2RlKG5vZGUpICYmIG5vZGUuZ2V0VGV4dENvbnRlbnQoKS50cmltKCkgPT09ICcnKSkge1xuICAgICAgbGlzdEl0ZW0gPSBwYXJlbnRMaXN0SXRlbTtcbiAgICB9XG4gIH1cbiAgaWYgKGxpc3RJdGVtID09PSBudWxsKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIGNvbnN0IHRvcExpc3ROb2RlID0gJGdldFRvcExpc3ROb2RlKGxpc3RJdGVtKTtcbiAgY29uc3QgcGFyZW50ID0gbGlzdEl0ZW0uZ2V0UGFyZW50KCk7XG4gIGlmICghJGlzTGlzdE5vZGUocGFyZW50KSkge1xuICAgIGZvcm1hdERldkVycm9yTWVzc2FnZShgQSBMaXN0SXRlbU5vZGUgbXVzdCBoYXZlIGEgTGlzdE5vZGUgZm9yIGEgcGFyZW50LmApO1xuICB9XG4gIGNvbnN0IGdyYW5kcGFyZW50ID0gcGFyZW50LmdldFBhcmVudCgpO1xuICBsZXQgcmVwbGFjZW1lbnROb2RlO1xuICBpZiAoJGlzUm9vdE9yU2hhZG93Um9vdChncmFuZHBhcmVudCkpIHtcbiAgICByZXBsYWNlbWVudE5vZGUgPSAkY3JlYXRlUGFyYWdyYXBoTm9kZSgpO1xuICAgIHRvcExpc3ROb2RlLmluc2VydEFmdGVyKHJlcGxhY2VtZW50Tm9kZSk7XG4gIH0gZWxzZSBpZiAoJGlzTGlzdEl0ZW1Ob2RlKGdyYW5kcGFyZW50KSkge1xuICAgIHJlcGxhY2VtZW50Tm9kZSA9ICRjcmVhdGVMaXN0SXRlbU5vZGUoKTtcbiAgICBncmFuZHBhcmVudC5pbnNlcnRBZnRlcihyZXBsYWNlbWVudE5vZGUpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICByZXBsYWNlbWVudE5vZGUuc2V0VGV4dFN0eWxlKHNlbGVjdGlvbi5zdHlsZSkuc2V0VGV4dEZvcm1hdChzZWxlY3Rpb24uZm9ybWF0KS5zZWxlY3QoKTtcbiAgY29uc3QgbmV4dFNpYmxpbmdzID0gbGlzdEl0ZW0uZ2V0TmV4dFNpYmxpbmdzKCk7XG4gIGlmIChuZXh0U2libGluZ3MubGVuZ3RoID4gMCkge1xuICAgIGNvbnN0IG5ld1N0YXJ0ID0gcmVzdG9yZU51bWJlcmluZyA/ICRnZXROZXdMaXN0U3RhcnQocGFyZW50LCBsaXN0SXRlbSkgOiAxO1xuICAgIGNvbnN0IG5ld0xpc3QgPSAkY3JlYXRlTGlzdE5vZGUocGFyZW50LmdldExpc3RUeXBlKCksIG5ld1N0YXJ0KTtcbiAgICBpZiAoJGlzTGlzdEl0ZW1Ob2RlKHJlcGxhY2VtZW50Tm9kZSkpIHtcbiAgICAgIGNvbnN0IG5ld0xpc3RJdGVtID0gJGNyZWF0ZUxpc3RJdGVtTm9kZSgpO1xuICAgICAgbmV3TGlzdEl0ZW0uYXBwZW5kKG5ld0xpc3QpO1xuICAgICAgcmVwbGFjZW1lbnROb2RlLmluc2VydEFmdGVyKG5ld0xpc3RJdGVtKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmVwbGFjZW1lbnROb2RlLmluc2VydEFmdGVyKG5ld0xpc3QpO1xuICAgIH1cbiAgICBuZXdMaXN0LmFwcGVuZCguLi5uZXh0U2libGluZ3MpO1xuICB9XG5cbiAgLy8gRG9uJ3QgbGVhdmUgaGFuZ2luZyBuZXN0ZWQgZW1wdHkgbGlzdHNcbiAgJHJlbW92ZUhpZ2hlc3RFbXB0eUxpc3RQYXJlbnQobGlzdEl0ZW0pO1xuICByZXR1cm4gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gYXBwbHlNYXJrZXJTdHlsZXMoZG9tLCBub2RlLCBwcmV2Tm9kZSkge1xuICBjb25zdCBzdHlsZXMgPSBnZXRTdHlsZU9iamVjdEZyb21DU1Mobm9kZS5fX3RleHRTdHlsZSk7XG4gIGZvciAoY29uc3QgayBpbiBzdHlsZXMpIHtcbiAgICBkb20uc3R5bGUuc2V0UHJvcGVydHkoYC0tbGlzdGl0ZW0tbWFya2VyLSR7a31gLCBzdHlsZXNba10pO1xuICB9XG4gIGlmIChwcmV2Tm9kZSkge1xuICAgIGZvciAoY29uc3QgayBpbiBnZXRTdHlsZU9iamVjdEZyb21DU1MocHJldk5vZGUuX190ZXh0U3R5bGUpKSB7XG4gICAgICBpZiAoIShrIGluIHN0eWxlcykpIHtcbiAgICAgICAgZG9tLnN0eWxlLnJlbW92ZVByb3BlcnR5KGAtLWxpc3RpdGVtLW1hcmtlci0ke2t9YCk7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbi8qKiBAbm9Jbmhlcml0RG9jICovXG5jbGFzcyBMaXN0SXRlbU5vZGUgZXh0ZW5kcyBFbGVtZW50Tm9kZSB7XG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgX192YWx1ZTtcbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBfX2NoZWNrZWQ7XG5cbiAgLyoqIEBpbnRlcm5hbCAqL1xuICAkY29uZmlnKCkge1xuICAgIHJldHVybiB0aGlzLmNvbmZpZygnbGlzdGl0ZW0nLCB7XG4gICAgICAkdHJhbnNmb3JtOiBub2RlID0+IHtcbiAgICAgICAgaWYgKG5vZGUuX19jaGVja2VkID09IG51bGwpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgcGFyZW50ID0gbm9kZS5nZXRQYXJlbnQoKTtcbiAgICAgICAgaWYgKCRpc0xpc3ROb2RlKHBhcmVudCkpIHtcbiAgICAgICAgICBpZiAocGFyZW50LmdldExpc3RUeXBlKCkgIT09ICdjaGVjaycgJiYgbm9kZS5nZXRDaGVja2VkKCkgIT0gbnVsbCkge1xuICAgICAgICAgICAgbm9kZS5zZXRDaGVja2VkKHVuZGVmaW5lZCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgZXh0ZW5kczogRWxlbWVudE5vZGUsXG4gICAgICBpbXBvcnRET006IGJ1aWxkSW1wb3J0TWFwKHtcbiAgICAgICAgbGk6ICgpID0+ICh7XG4gICAgICAgICAgY29udmVyc2lvbjogJGNvbnZlcnRMaXN0SXRlbUVsZW1lbnQsXG4gICAgICAgICAgcHJpb3JpdHk6IDBcbiAgICAgICAgfSlcbiAgICAgIH0pXG4gICAgfSk7XG4gIH1cbiAgY29uc3RydWN0b3IodmFsdWUgPSAxLCBjaGVja2VkID0gdW5kZWZpbmVkLCBrZXkpIHtcbiAgICBzdXBlcihrZXkpO1xuICAgIHRoaXMuX192YWx1ZSA9IHZhbHVlID09PSB1bmRlZmluZWQgPyAxIDogdmFsdWU7XG4gICAgdGhpcy5fX2NoZWNrZWQgPSBjaGVja2VkO1xuICB9XG4gIGFmdGVyQ2xvbmVGcm9tKHByZXZOb2RlKSB7XG4gICAgc3VwZXIuYWZ0ZXJDbG9uZUZyb20ocHJldk5vZGUpO1xuICAgIHRoaXMuX192YWx1ZSA9IHByZXZOb2RlLl9fdmFsdWU7XG4gICAgdGhpcy5fX2NoZWNrZWQgPSBwcmV2Tm9kZS5fX2NoZWNrZWQ7XG4gIH1cbiAgY3JlYXRlRE9NKGNvbmZpZykge1xuICAgIGNvbnN0IGVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdsaScpO1xuICAgIHRoaXMudXBkYXRlTGlzdEl0ZW1ET00obnVsbCwgZWxlbWVudCwgY29uZmlnKTtcbiAgICByZXR1cm4gZWxlbWVudDtcbiAgfVxuICB1cGRhdGVMaXN0SXRlbURPTShwcmV2Tm9kZSwgZG9tLCBjb25maWcpIHtcbiAgICB1cGRhdGVMaXN0SXRlbUNoZWNrZWQoZG9tLCB0aGlzLCBwcmV2Tm9kZSk7XG4gICAgZG9tLnZhbHVlID0gdGhpcy5fX3ZhbHVlO1xuICAgICRzZXRMaXN0SXRlbVRoZW1lQ2xhc3NOYW1lcyhkb20sIGNvbmZpZy50aGVtZSwgdGhpcyk7XG4gICAgY29uc3QgcHJldlN0eWxlID0gcHJldk5vZGUgPyBwcmV2Tm9kZS5fX3N0eWxlIDogJyc7XG4gICAgY29uc3QgbmV4dFN0eWxlID0gdGhpcy5fX3N0eWxlO1xuICAgIGlmIChwcmV2U3R5bGUgIT09IG5leHRTdHlsZSkge1xuICAgICAgaWYgKG5leHRTdHlsZSA9PT0gJycpIHtcbiAgICAgICAgZG9tLnJlbW92ZUF0dHJpYnV0ZSgnc3R5bGUnKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRvbS5zdHlsZS5jc3NUZXh0ID0gbmV4dFN0eWxlO1xuICAgICAgfVxuICAgIH1cbiAgICBhcHBseU1hcmtlclN0eWxlcyhkb20sIHRoaXMsIHByZXZOb2RlKTtcbiAgfVxuICB1cGRhdGVET00ocHJldk5vZGUsIGRvbSwgY29uZmlnKSB7XG4gICAgLy8gQHRzLWV4cGVjdC1lcnJvciAtIHRoaXMgaXMgYWx3YXlzIEhUTUxMaXN0SXRlbUVsZW1lbnRcbiAgICBjb25zdCBlbGVtZW50ID0gZG9tO1xuICAgIHRoaXMudXBkYXRlTGlzdEl0ZW1ET00ocHJldk5vZGUsIGVsZW1lbnQsIGNvbmZpZyk7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHVwZGF0ZUZyb21KU09OKHNlcmlhbGl6ZWROb2RlKSB7XG4gICAgcmV0dXJuIHN1cGVyLnVwZGF0ZUZyb21KU09OKHNlcmlhbGl6ZWROb2RlKS5zZXRWYWx1ZShzZXJpYWxpemVkTm9kZS52YWx1ZSkuc2V0Q2hlY2tlZChzZXJpYWxpemVkTm9kZS5jaGVja2VkKTtcbiAgfVxuICBleHBvcnRET00oZWRpdG9yKSB7XG4gICAgY29uc3QgZWxlbWVudCA9IHRoaXMuY3JlYXRlRE9NKGVkaXRvci5fY29uZmlnKTtcbiAgICBjb25zdCBmb3JtYXRUeXBlID0gdGhpcy5nZXRGb3JtYXRUeXBlKCk7XG4gICAgaWYgKGZvcm1hdFR5cGUpIHtcbiAgICAgIGVsZW1lbnQuc3R5bGUudGV4dEFsaWduID0gZm9ybWF0VHlwZTtcbiAgICB9XG4gICAgY29uc3QgZGlyZWN0aW9uID0gdGhpcy5nZXREaXJlY3Rpb24oKTtcbiAgICBpZiAoZGlyZWN0aW9uKSB7XG4gICAgICBlbGVtZW50LmRpciA9IGRpcmVjdGlvbjtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIGVsZW1lbnRcbiAgICB9O1xuICB9XG4gIGV4cG9ydEpTT04oKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLnN1cGVyLmV4cG9ydEpTT04oKSxcbiAgICAgIGNoZWNrZWQ6IHRoaXMuZ2V0Q2hlY2tlZCgpLFxuICAgICAgdmFsdWU6IHRoaXMuZ2V0VmFsdWUoKVxuICAgIH07XG4gIH1cbiAgYXBwZW5kKC4uLm5vZGVzKSB7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBub2Rlcy5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3Qgbm9kZSA9IG5vZGVzW2ldO1xuICAgICAgaWYgKCRpc0VsZW1lbnROb2RlKG5vZGUpICYmIHRoaXMuY2FuTWVyZ2VXaXRoKG5vZGUpKSB7XG4gICAgICAgIGNvbnN0IGNoaWxkcmVuID0gbm9kZS5nZXRDaGlsZHJlbigpO1xuICAgICAgICB0aGlzLmFwcGVuZCguLi5jaGlsZHJlbik7XG4gICAgICAgIG5vZGUucmVtb3ZlKCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzdXBlci5hcHBlbmQobm9kZSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0aGlzO1xuICB9XG4gIHJlcGxhY2UocmVwbGFjZVdpdGhOb2RlLCBpbmNsdWRlQ2hpbGRyZW4pIHtcbiAgICBpZiAoJGlzTGlzdEl0ZW1Ob2RlKHJlcGxhY2VXaXRoTm9kZSkpIHtcbiAgICAgIHJldHVybiBzdXBlci5yZXBsYWNlKHJlcGxhY2VXaXRoTm9kZSk7XG4gICAgfVxuICAgIHRoaXMuc2V0SW5kZW50KDApO1xuICAgIGNvbnN0IGxpc3QgPSB0aGlzLmdldFBhcmVudE9yVGhyb3coKTtcbiAgICBpZiAoISRpc0xpc3ROb2RlKGxpc3QpKSB7XG4gICAgICByZXR1cm4gcmVwbGFjZVdpdGhOb2RlO1xuICAgIH1cbiAgICBpZiAobGlzdC5fX2ZpcnN0ID09PSB0aGlzLmdldEtleSgpKSB7XG4gICAgICBsaXN0Lmluc2VydEJlZm9yZShyZXBsYWNlV2l0aE5vZGUpO1xuICAgIH0gZWxzZSBpZiAobGlzdC5fX2xhc3QgPT09IHRoaXMuZ2V0S2V5KCkpIHtcbiAgICAgIGxpc3QuaW5zZXJ0QWZ0ZXIocmVwbGFjZVdpdGhOb2RlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gU3BsaXQgdGhlIGxpc3RcbiAgICAgIGNvbnN0IG5ld0xpc3QgPSAkY3JlYXRlTGlzdE5vZGUobGlzdC5nZXRMaXN0VHlwZSgpKTtcbiAgICAgIGxldCBuZXh0U2libGluZyA9IHRoaXMuZ2V0TmV4dFNpYmxpbmcoKTtcbiAgICAgIHdoaWxlIChuZXh0U2libGluZykge1xuICAgICAgICBjb25zdCBub2RlVG9BcHBlbmQgPSBuZXh0U2libGluZztcbiAgICAgICAgbmV4dFNpYmxpbmcgPSBuZXh0U2libGluZy5nZXROZXh0U2libGluZygpO1xuICAgICAgICBuZXdMaXN0LmFwcGVuZChub2RlVG9BcHBlbmQpO1xuICAgICAgfVxuICAgICAgbGlzdC5pbnNlcnRBZnRlcihyZXBsYWNlV2l0aE5vZGUpO1xuICAgICAgcmVwbGFjZVdpdGhOb2RlLmluc2VydEFmdGVyKG5ld0xpc3QpO1xuICAgIH1cbiAgICBpZiAoaW5jbHVkZUNoaWxkcmVuKSB7XG4gICAgICBpZiAoISRpc0VsZW1lbnROb2RlKHJlcGxhY2VXaXRoTm9kZSkpIHtcbiAgICAgICAgZm9ybWF0RGV2RXJyb3JNZXNzYWdlKGBpbmNsdWRlQ2hpbGRyZW4gc2hvdWxkIG9ubHkgYmUgdHJ1ZSBmb3IgRWxlbWVudE5vZGVzYCk7XG4gICAgICB9XG4gICAgICB0aGlzLmdldENoaWxkcmVuKCkuZm9yRWFjaChjaGlsZCA9PiB7XG4gICAgICAgIHJlcGxhY2VXaXRoTm9kZS5hcHBlbmQoY2hpbGQpO1xuICAgICAgfSk7XG4gICAgfVxuICAgIHRoaXMucmVtb3ZlKCk7XG4gICAgaWYgKGxpc3QuZ2V0Q2hpbGRyZW5TaXplKCkgPT09IDApIHtcbiAgICAgIGxpc3QucmVtb3ZlKCk7XG4gICAgfVxuICAgIHJldHVybiByZXBsYWNlV2l0aE5vZGU7XG4gIH1cbiAgaW5zZXJ0QWZ0ZXIobm9kZSwgcmVzdG9yZVNlbGVjdGlvbiA9IHRydWUpIHtcbiAgICBjb25zdCBsaXN0Tm9kZSA9IHRoaXMuZ2V0UGFyZW50T3JUaHJvdygpO1xuICAgIGlmICghJGlzTGlzdE5vZGUobGlzdE5vZGUpKSB7XG4gICAgICB7XG4gICAgICAgIGZvcm1hdERldkVycm9yTWVzc2FnZShgaW5zZXJ0QWZ0ZXI6IGxpc3Qgbm9kZSBpcyBub3QgcGFyZW50IG9mIGxpc3QgaXRlbSBub2RlYCk7XG4gICAgICB9XG4gICAgfVxuICAgIGlmICgkaXNMaXN0SXRlbU5vZGUobm9kZSkpIHtcbiAgICAgIHJldHVybiBzdXBlci5pbnNlcnRBZnRlcihub2RlLCByZXN0b3JlU2VsZWN0aW9uKTtcbiAgICB9XG4gICAgY29uc3Qgc2libGluZ3MgPSB0aGlzLmdldE5leHRTaWJsaW5ncygpO1xuXG4gICAgLy8gU3BsaXQgdGhlIGxpc3RzIGFuZCBpbnNlcnQgdGhlIG5vZGUgaW4gYmV0d2VlbiB0aGVtXG4gICAgbGlzdE5vZGUuaW5zZXJ0QWZ0ZXIobm9kZSwgcmVzdG9yZVNlbGVjdGlvbik7XG4gICAgaWYgKHNpYmxpbmdzLmxlbmd0aCAhPT0gMCkge1xuICAgICAgY29uc3QgbmV3TGlzdE5vZGUgPSAkY3JlYXRlTGlzdE5vZGUobGlzdE5vZGUuZ2V0TGlzdFR5cGUoKSk7XG4gICAgICBzaWJsaW5ncy5mb3JFYWNoKHNpYmxpbmcgPT4gbmV3TGlzdE5vZGUuYXBwZW5kKHNpYmxpbmcpKTtcbiAgICAgIG5vZGUuaW5zZXJ0QWZ0ZXIobmV3TGlzdE5vZGUsIHJlc3RvcmVTZWxlY3Rpb24pO1xuICAgIH1cbiAgICByZXR1cm4gbm9kZTtcbiAgfVxuICByZW1vdmUocHJlc2VydmVFbXB0eVBhcmVudCkge1xuICAgIGNvbnN0IHByZXZTaWJsaW5nID0gdGhpcy5nZXRQcmV2aW91c1NpYmxpbmcoKTtcbiAgICBjb25zdCBuZXh0U2libGluZyA9IHRoaXMuZ2V0TmV4dFNpYmxpbmcoKTtcbiAgICBzdXBlci5yZW1vdmUocHJlc2VydmVFbXB0eVBhcmVudCk7XG4gICAgaWYgKHByZXZTaWJsaW5nICYmIG5leHRTaWJsaW5nICYmIGlzTmVzdGVkTGlzdE5vZGUocHJldlNpYmxpbmcpICYmIGlzTmVzdGVkTGlzdE5vZGUobmV4dFNpYmxpbmcpKSB7XG4gICAgICBtZXJnZUxpc3RzKHByZXZTaWJsaW5nLmdldEZpcnN0Q2hpbGQoKSwgbmV4dFNpYmxpbmcuZ2V0Rmlyc3RDaGlsZCgpKTtcbiAgICAgIG5leHRTaWJsaW5nLnJlbW92ZSgpO1xuICAgIH1cbiAgfVxuICBpbnNlcnROZXdBZnRlcihfLCByZXN0b3JlU2VsZWN0aW9uID0gdHJ1ZSkge1xuICAgIGNvbnN0IG5ld0VsZW1lbnQgPSAkY3JlYXRlTGlzdEl0ZW1Ob2RlKCkudXBkYXRlRnJvbUpTT04odGhpcy5leHBvcnRKU09OKCkpLnNldENoZWNrZWQodGhpcy5nZXRDaGVja2VkKCkgPyBmYWxzZSA6IHVuZGVmaW5lZCk7XG4gICAgdGhpcy5pbnNlcnRBZnRlcihuZXdFbGVtZW50LCByZXN0b3JlU2VsZWN0aW9uKTtcbiAgICByZXR1cm4gbmV3RWxlbWVudDtcbiAgfVxuICBjb2xsYXBzZUF0U3RhcnQoc2VsZWN0aW9uKSB7XG4gICAgY29uc3QgcGFyYWdyYXBoID0gJGNyZWF0ZVBhcmFncmFwaE5vZGUoKTtcbiAgICBjb25zdCBjaGlsZHJlbiA9IHRoaXMuZ2V0Q2hpbGRyZW4oKTtcbiAgICBjaGlsZHJlbi5mb3JFYWNoKGNoaWxkID0+IHBhcmFncmFwaC5hcHBlbmQoY2hpbGQpKTtcbiAgICBjb25zdCBsaXN0Tm9kZSA9IHRoaXMuZ2V0UGFyZW50T3JUaHJvdygpO1xuICAgIGNvbnN0IGxpc3ROb2RlUGFyZW50ID0gbGlzdE5vZGUuZ2V0UGFyZW50T3JUaHJvdygpO1xuICAgIGNvbnN0IGlzSW5kZW50ZWQgPSAkaXNMaXN0SXRlbU5vZGUobGlzdE5vZGVQYXJlbnQpO1xuICAgIGlmIChsaXN0Tm9kZS5nZXRDaGlsZHJlblNpemUoKSA9PT0gMSkge1xuICAgICAgaWYgKGlzSW5kZW50ZWQpIHtcbiAgICAgICAgLy8gaWYgdGhlIGxpc3Qgbm9kZSBpcyBuZXN0ZWQsIHdlIGp1c3Qgd2FudCB0byByZW1vdmUgaXQsXG4gICAgICAgIC8vIGVmZmVjdGl2ZWx5IHVuaW5kZW50aW5nIGl0LlxuICAgICAgICBsaXN0Tm9kZS5yZW1vdmUoKTtcbiAgICAgICAgbGlzdE5vZGVQYXJlbnQuc2VsZWN0KCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBsaXN0Tm9kZS5pbnNlcnRCZWZvcmUocGFyYWdyYXBoKTtcbiAgICAgICAgbGlzdE5vZGUucmVtb3ZlKCk7XG4gICAgICAgIC8vIElmIHdlIGhhdmUgc2VsZWN0aW9uIG9uIHRoZSBsaXN0IGl0ZW0sIHdlJ2xsIG5lZWQgdG8gbW92ZSBpdFxuICAgICAgICAvLyB0byB0aGUgcGFyYWdyYXBoXG4gICAgICAgIGNvbnN0IGFuY2hvciA9IHNlbGVjdGlvbi5hbmNob3I7XG4gICAgICAgIGNvbnN0IGZvY3VzID0gc2VsZWN0aW9uLmZvY3VzO1xuICAgICAgICBjb25zdCBrZXkgPSBwYXJhZ3JhcGguZ2V0S2V5KCk7XG4gICAgICAgIGlmIChhbmNob3IudHlwZSA9PT0gJ2VsZW1lbnQnICYmIGFuY2hvci5nZXROb2RlKCkuaXModGhpcykpIHtcbiAgICAgICAgICBhbmNob3Iuc2V0KGtleSwgYW5jaG9yLm9mZnNldCwgJ2VsZW1lbnQnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZm9jdXMudHlwZSA9PT0gJ2VsZW1lbnQnICYmIGZvY3VzLmdldE5vZGUoKS5pcyh0aGlzKSkge1xuICAgICAgICAgIGZvY3VzLnNldChrZXksIGZvY3VzLm9mZnNldCwgJ2VsZW1lbnQnKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBsaXN0Tm9kZS5pbnNlcnRCZWZvcmUocGFyYWdyYXBoKTtcbiAgICAgIHRoaXMucmVtb3ZlKCk7XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9XG4gIGdldFZhbHVlKCkge1xuICAgIGNvbnN0IHNlbGYgPSB0aGlzLmdldExhdGVzdCgpO1xuICAgIHJldHVybiBzZWxmLl9fdmFsdWU7XG4gIH1cbiAgc2V0VmFsdWUodmFsdWUpIHtcbiAgICBjb25zdCBzZWxmID0gdGhpcy5nZXRXcml0YWJsZSgpO1xuICAgIHNlbGYuX192YWx1ZSA9IHZhbHVlO1xuICAgIHJldHVybiBzZWxmO1xuICB9XG4gIGdldENoZWNrZWQoKSB7XG4gICAgY29uc3Qgc2VsZiA9IHRoaXMuZ2V0TGF0ZXN0KCk7XG4gICAgbGV0IGxpc3RUeXBlO1xuICAgIGNvbnN0IHBhcmVudCA9IHRoaXMuZ2V0UGFyZW50KCk7XG4gICAgaWYgKCRpc0xpc3ROb2RlKHBhcmVudCkpIHtcbiAgICAgIGxpc3RUeXBlID0gcGFyZW50LmdldExpc3RUeXBlKCk7XG4gICAgfVxuICAgIHJldHVybiBsaXN0VHlwZSA9PT0gJ2NoZWNrJyA/IEJvb2xlYW4oc2VsZi5fX2NoZWNrZWQpIDogdW5kZWZpbmVkO1xuICB9XG4gIHNldENoZWNrZWQoY2hlY2tlZCkge1xuICAgIGNvbnN0IHNlbGYgPSB0aGlzLmdldFdyaXRhYmxlKCk7XG4gICAgc2VsZi5fX2NoZWNrZWQgPSBjaGVja2VkO1xuICAgIHJldHVybiBzZWxmO1xuICB9XG4gIHRvZ2dsZUNoZWNrZWQoKSB7XG4gICAgY29uc3Qgc2VsZiA9IHRoaXMuZ2V0V3JpdGFibGUoKTtcbiAgICByZXR1cm4gc2VsZi5zZXRDaGVja2VkKCFzZWxmLl9fY2hlY2tlZCk7XG4gIH1cbiAgZ2V0SW5kZW50KCkge1xuICAgIC8vIElmIHdlIGRvbid0IGhhdmUgYSBwYXJlbnQsIHdlIGFyZSBsaWtlbHkgc2VyaWFsaXppbmdcbiAgICBjb25zdCBwYXJlbnQgPSB0aGlzLmdldFBhcmVudCgpO1xuICAgIGlmIChwYXJlbnQgPT09IG51bGwgfHwgIXRoaXMuaXNBdHRhY2hlZCgpKSB7XG4gICAgICByZXR1cm4gdGhpcy5nZXRMYXRlc3QoKS5fX2luZGVudDtcbiAgICB9XG4gICAgLy8gTGlzdEl0ZW1Ob2RlIHNob3VsZCBhbHdheXMgaGF2ZSBhIExpc3ROb2RlIGZvciBhIHBhcmVudC5cbiAgICBsZXQgbGlzdE5vZGVQYXJlbnQgPSBwYXJlbnQuZ2V0UGFyZW50T3JUaHJvdygpO1xuICAgIGxldCBpbmRlbnRMZXZlbCA9IDA7XG4gICAgd2hpbGUgKCRpc0xpc3RJdGVtTm9kZShsaXN0Tm9kZVBhcmVudCkpIHtcbiAgICAgIGxpc3ROb2RlUGFyZW50ID0gbGlzdE5vZGVQYXJlbnQuZ2V0UGFyZW50T3JUaHJvdygpLmdldFBhcmVudE9yVGhyb3coKTtcbiAgICAgIGluZGVudExldmVsKys7XG4gICAgfVxuICAgIHJldHVybiBpbmRlbnRMZXZlbDtcbiAgfVxuICBzZXRJbmRlbnQoaW5kZW50KSB7XG4gICAgaWYgKCEodHlwZW9mIGluZGVudCA9PT0gJ251bWJlcicpKSB7XG4gICAgICBmb3JtYXREZXZFcnJvck1lc3NhZ2UoYEludmFsaWQgaW5kZW50IHZhbHVlLmApO1xuICAgIH1cbiAgICBpbmRlbnQgPSBNYXRoLmZsb29yKGluZGVudCk7XG4gICAgaWYgKCEoaW5kZW50ID49IDApKSB7XG4gICAgICBmb3JtYXREZXZFcnJvck1lc3NhZ2UoYEluZGVudCB2YWx1ZSBtdXN0IGJlIG5vbi1uZWdhdGl2ZS5gKTtcbiAgICB9XG4gICAgbGV0IGN1cnJlbnRJbmRlbnQgPSB0aGlzLmdldEluZGVudCgpO1xuICAgIHdoaWxlIChjdXJyZW50SW5kZW50ICE9PSBpbmRlbnQpIHtcbiAgICAgIGlmIChjdXJyZW50SW5kZW50IDwgaW5kZW50KSB7XG4gICAgICAgICRoYW5kbGVJbmRlbnQodGhpcyk7XG4gICAgICAgIGN1cnJlbnRJbmRlbnQrKztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgICRoYW5kbGVPdXRkZW50KHRoaXMpO1xuICAgICAgICBjdXJyZW50SW5kZW50LS07XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqIEBkZXByZWNhdGVkIEBpbnRlcm5hbCAqL1xuICBjYW5JbnNlcnRBZnRlcihub2RlKSB7XG4gICAgcmV0dXJuICRpc0xpc3RJdGVtTm9kZShub2RlKTtcbiAgfVxuXG4gIC8qKiBAZGVwcmVjYXRlZCBAaW50ZXJuYWwgKi9cbiAgY2FuUmVwbGFjZVdpdGgocmVwbGFjZW1lbnQpIHtcbiAgICByZXR1cm4gJGlzTGlzdEl0ZW1Ob2RlKHJlcGxhY2VtZW50KTtcbiAgfVxuICBjYW5NZXJnZVdpdGgobm9kZSkge1xuICAgIHJldHVybiAkaXNMaXN0SXRlbU5vZGUobm9kZSkgfHwgJGlzUGFyYWdyYXBoTm9kZShub2RlKTtcbiAgfVxuICBleHRyYWN0V2l0aENoaWxkKGNoaWxkLCBzZWxlY3Rpb24pIHtcbiAgICBpZiAoISRpc1JhbmdlU2VsZWN0aW9uKHNlbGVjdGlvbikpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgY29uc3QgYW5jaG9yTm9kZSA9IHNlbGVjdGlvbi5hbmNob3IuZ2V0Tm9kZSgpO1xuICAgIGNvbnN0IGZvY3VzTm9kZSA9IHNlbGVjdGlvbi5mb2N1cy5nZXROb2RlKCk7XG4gICAgcmV0dXJuIHRoaXMuaXNQYXJlbnRPZihhbmNob3JOb2RlKSAmJiB0aGlzLmlzUGFyZW50T2YoZm9jdXNOb2RlKSAmJiB0aGlzLmdldFRleHRDb250ZW50KCkubGVuZ3RoID09PSBzZWxlY3Rpb24uZ2V0VGV4dENvbnRlbnQoKS5sZW5ndGg7XG4gIH1cbiAgaXNQYXJlbnRSZXF1aXJlZCgpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuICBjcmVhdGVQYXJlbnRFbGVtZW50Tm9kZSgpIHtcbiAgICByZXR1cm4gJGNyZWF0ZUxpc3ROb2RlKCdidWxsZXQnKTtcbiAgfVxuICBjYW5NZXJnZVdoZW5FbXB0eSgpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxufVxuZnVuY3Rpb24gJHNldExpc3RJdGVtVGhlbWVDbGFzc05hbWVzKGRvbSwgZWRpdG9yVGhlbWVDbGFzc2VzLCBub2RlKSB7XG4gIGNvbnN0IGNsYXNzZXNUb0FkZCA9IFtdO1xuICBjb25zdCBjbGFzc2VzVG9SZW1vdmUgPSBbXTtcbiAgY29uc3QgbGlzdFRoZW1lID0gZWRpdG9yVGhlbWVDbGFzc2VzLmxpc3Q7XG4gIGNvbnN0IGxpc3RJdGVtQ2xhc3NOYW1lID0gbGlzdFRoZW1lID8gbGlzdFRoZW1lLmxpc3RpdGVtIDogdW5kZWZpbmVkO1xuICBsZXQgbmVzdGVkTGlzdEl0ZW1DbGFzc05hbWU7XG4gIGlmIChsaXN0VGhlbWUgJiYgbGlzdFRoZW1lLm5lc3RlZCkge1xuICAgIG5lc3RlZExpc3RJdGVtQ2xhc3NOYW1lID0gbGlzdFRoZW1lLm5lc3RlZC5saXN0aXRlbTtcbiAgfVxuICBpZiAobGlzdEl0ZW1DbGFzc05hbWUgIT09IHVuZGVmaW5lZCkge1xuICAgIGNsYXNzZXNUb0FkZC5wdXNoKC4uLm5vcm1hbGl6ZUNsYXNzTmFtZXMobGlzdEl0ZW1DbGFzc05hbWUpKTtcbiAgfVxuICBpZiAobGlzdFRoZW1lKSB7XG4gICAgY29uc3QgcGFyZW50Tm9kZSA9IG5vZGUuZ2V0UGFyZW50KCk7XG4gICAgY29uc3QgaXNDaGVja0xpc3QgPSAkaXNMaXN0Tm9kZShwYXJlbnROb2RlKSAmJiBwYXJlbnROb2RlLmdldExpc3RUeXBlKCkgPT09ICdjaGVjayc7XG4gICAgY29uc3QgY2hlY2tlZCA9IG5vZGUuZ2V0Q2hlY2tlZCgpO1xuICAgIGlmICghaXNDaGVja0xpc3QgfHwgY2hlY2tlZCkge1xuICAgICAgY2xhc3Nlc1RvUmVtb3ZlLnB1c2gobGlzdFRoZW1lLmxpc3RpdGVtVW5jaGVja2VkKTtcbiAgICB9XG4gICAgaWYgKCFpc0NoZWNrTGlzdCB8fCAhY2hlY2tlZCkge1xuICAgICAgY2xhc3Nlc1RvUmVtb3ZlLnB1c2gobGlzdFRoZW1lLmxpc3RpdGVtQ2hlY2tlZCk7XG4gICAgfVxuICAgIGlmIChpc0NoZWNrTGlzdCkge1xuICAgICAgY2xhc3Nlc1RvQWRkLnB1c2goY2hlY2tlZCA/IGxpc3RUaGVtZS5saXN0aXRlbUNoZWNrZWQgOiBsaXN0VGhlbWUubGlzdGl0ZW1VbmNoZWNrZWQpO1xuICAgIH1cbiAgfVxuICBpZiAobmVzdGVkTGlzdEl0ZW1DbGFzc05hbWUgIT09IHVuZGVmaW5lZCkge1xuICAgIGNvbnN0IG5lc3RlZExpc3RJdGVtQ2xhc3NlcyA9IG5vcm1hbGl6ZUNsYXNzTmFtZXMobmVzdGVkTGlzdEl0ZW1DbGFzc05hbWUpO1xuICAgIGlmIChub2RlLmdldENoaWxkcmVuKCkuc29tZShjaGlsZCA9PiAkaXNMaXN0Tm9kZShjaGlsZCkpKSB7XG4gICAgICBjbGFzc2VzVG9BZGQucHVzaCguLi5uZXN0ZWRMaXN0SXRlbUNsYXNzZXMpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjbGFzc2VzVG9SZW1vdmUucHVzaCguLi5uZXN0ZWRMaXN0SXRlbUNsYXNzZXMpO1xuICAgIH1cbiAgfVxuICBpZiAoY2xhc3Nlc1RvUmVtb3ZlLmxlbmd0aCA+IDApIHtcbiAgICByZW1vdmVDbGFzc05hbWVzRnJvbUVsZW1lbnQoZG9tLCAuLi5jbGFzc2VzVG9SZW1vdmUpO1xuICB9XG4gIGlmIChjbGFzc2VzVG9BZGQubGVuZ3RoID4gMCkge1xuICAgIGFkZENsYXNzTmFtZXNUb0VsZW1lbnQoZG9tLCAuLi5jbGFzc2VzVG9BZGQpO1xuICB9XG59XG5mdW5jdGlvbiB1cGRhdGVMaXN0SXRlbUNoZWNrZWQoZG9tLCBsaXN0SXRlbU5vZGUsIHByZXZMaXN0SXRlbU5vZGUpIHtcbiAgY29uc3QgcGFyZW50ID0gbGlzdEl0ZW1Ob2RlLmdldFBhcmVudCgpO1xuICBjb25zdCBpc0NoZWNrYm94ID0gJGlzTGlzdE5vZGUocGFyZW50KSAmJiBwYXJlbnQuZ2V0TGlzdFR5cGUoKSA9PT0gJ2NoZWNrJyAmJlxuICAvLyBPbmx5IGFkZCBhdHRyaWJ1dGVzIGZvciBsZWFmIGxpc3QgaXRlbXNcbiAgISRpc0xpc3ROb2RlKGxpc3RJdGVtTm9kZS5nZXRGaXJzdENoaWxkKCkpO1xuICBpZiAoIWlzQ2hlY2tib3gpIHtcbiAgICBkb20ucmVtb3ZlQXR0cmlidXRlKCdyb2xlJyk7XG4gICAgZG9tLnJlbW92ZUF0dHJpYnV0ZSgndGFiSW5kZXgnKTtcbiAgICBkb20ucmVtb3ZlQXR0cmlidXRlKCdhcmlhLWNoZWNrZWQnKTtcbiAgfSBlbHNlIHtcbiAgICBkb20uc2V0QXR0cmlidXRlKCdyb2xlJywgJ2NoZWNrYm94Jyk7XG4gICAgZG9tLnNldEF0dHJpYnV0ZSgndGFiSW5kZXgnLCAnLTEnKTtcbiAgICBpZiAoIXByZXZMaXN0SXRlbU5vZGUgfHwgbGlzdEl0ZW1Ob2RlLl9fY2hlY2tlZCAhPT0gcHJldkxpc3RJdGVtTm9kZS5fX2NoZWNrZWQpIHtcbiAgICAgIGRvbS5zZXRBdHRyaWJ1dGUoJ2FyaWEtY2hlY2tlZCcsIGxpc3RJdGVtTm9kZS5nZXRDaGVja2VkKCkgPyAndHJ1ZScgOiAnZmFsc2UnKTtcbiAgICB9XG4gIH1cbn1cbmZ1bmN0aW9uICRjb252ZXJ0TGlzdEl0ZW1FbGVtZW50KGRvbU5vZGUpIHtcbiAgY29uc3QgaXNHaXRIdWJDaGVja0xpc3QgPSBkb21Ob2RlLmNsYXNzTGlzdC5jb250YWlucygndGFzay1saXN0LWl0ZW0nKTtcbiAgaWYgKGlzR2l0SHViQ2hlY2tMaXN0KSB7XG4gICAgZm9yIChjb25zdCBjaGlsZCBvZiBkb21Ob2RlLmNoaWxkcmVuKSB7XG4gICAgICBpZiAoY2hpbGQudGFnTmFtZSA9PT0gJ0lOUFVUJykge1xuICAgICAgICByZXR1cm4gJGNvbnZlcnRDaGVja2JveElucHV0KGNoaWxkKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgY29uc3QgaXNKb3BsaW5DaGVja0xpc3QgPSBkb21Ob2RlLmNsYXNzTGlzdC5jb250YWlucygnam9wbGluLWNoZWNrYm94Jyk7XG4gIGlmIChpc0pvcGxpbkNoZWNrTGlzdCkge1xuICAgIGZvciAoY29uc3QgY2hpbGQgb2YgZG9tTm9kZS5jaGlsZHJlbikge1xuICAgICAgaWYgKGNoaWxkLmNsYXNzTGlzdC5jb250YWlucygnY2hlY2tib3gtd3JhcHBlcicpICYmIGNoaWxkLmNoaWxkcmVuLmxlbmd0aCA+IDAgJiYgY2hpbGQuY2hpbGRyZW5bMF0udGFnTmFtZSA9PT0gJ0lOUFVUJykge1xuICAgICAgICByZXR1cm4gJGNvbnZlcnRDaGVja2JveElucHV0KGNoaWxkLmNoaWxkcmVuWzBdKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgY29uc3QgYXJpYUNoZWNrZWRBdHRyID0gZG9tTm9kZS5nZXRBdHRyaWJ1dGUoJ2FyaWEtY2hlY2tlZCcpO1xuICBjb25zdCBjaGVja2VkID0gYXJpYUNoZWNrZWRBdHRyID09PSAndHJ1ZScgPyB0cnVlIDogYXJpYUNoZWNrZWRBdHRyID09PSAnZmFsc2UnID8gZmFsc2UgOiB1bmRlZmluZWQ7XG4gIHJldHVybiB7XG4gICAgbm9kZTogJGNyZWF0ZUxpc3RJdGVtTm9kZShjaGVja2VkKVxuICB9O1xufVxuZnVuY3Rpb24gJGNvbnZlcnRDaGVja2JveElucHV0KGRvbU5vZGUpIHtcbiAgY29uc3QgaXNDaGVja2JveElucHV0ID0gZG9tTm9kZS5nZXRBdHRyaWJ1dGUoJ3R5cGUnKSA9PT0gJ2NoZWNrYm94JztcbiAgaWYgKCFpc0NoZWNrYm94SW5wdXQpIHtcbiAgICByZXR1cm4ge1xuICAgICAgbm9kZTogbnVsbFxuICAgIH07XG4gIH1cbiAgY29uc3QgY2hlY2tlZCA9IGRvbU5vZGUuaGFzQXR0cmlidXRlKCdjaGVja2VkJyk7XG4gIHJldHVybiB7XG4gICAgbm9kZTogJGNyZWF0ZUxpc3RJdGVtTm9kZShjaGVja2VkKVxuICB9O1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgTGlzdCBJdGVtIG5vZGUsIHBhc3NpbmcgdHJ1ZS9mYWxzZSB3aWxsIGNvbnZlcnQgaXQgdG8gYSBjaGVja2JveCBpbnB1dC5cbiAqIEBwYXJhbSBjaGVja2VkIC0gSXMgdGhlIExpc3QgSXRlbSBhIGNoZWNrYm94IGFuZCwgaWYgc28sIGlzIGl0IGNoZWNrZWQ/IHVuZGVmaW5lZC9udWxsOiBub3QgYSBjaGVja2JveCwgdHJ1ZS9mYWxzZSBpcyBhIGNoZWNrYm94IGFuZCBjaGVja2VkL3VuY2hlY2tlZCwgcmVzcGVjdGl2ZWx5LlxuICogQHJldHVybnMgVGhlIG5ldyBMaXN0IEl0ZW0uXG4gKi9cbmZ1bmN0aW9uICRjcmVhdGVMaXN0SXRlbU5vZGUoY2hlY2tlZCkge1xuICByZXR1cm4gJGFwcGx5Tm9kZVJlcGxhY2VtZW50KG5ldyBMaXN0SXRlbU5vZGUodW5kZWZpbmVkLCBjaGVja2VkKSk7XG59XG5cbi8qKlxuICogQ2hlY2tzIHRvIHNlZSBpZiB0aGUgbm9kZSBpcyBhIExpc3RJdGVtTm9kZS5cbiAqIEBwYXJhbSBub2RlIC0gVGhlIG5vZGUgdG8gYmUgY2hlY2tlZC5cbiAqIEByZXR1cm5zIHRydWUgaWYgdGhlIG5vZGUgaXMgYSBMaXN0SXRlbU5vZGUsIGZhbHNlIG90aGVyd2lzZS5cbiAqL1xuZnVuY3Rpb24gJGlzTGlzdEl0ZW1Ob2RlKG5vZGUpIHtcbiAgcmV0dXJuIG5vZGUgaW5zdGFuY2VvZiBMaXN0SXRlbU5vZGU7XG59XG5cbi8qKlxuICogQ29weXJpZ2h0IChjKSBNZXRhIFBsYXRmb3JtcywgSW5jLiBhbmQgYWZmaWxpYXRlcy5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqXG4gKi9cblxuLyoqIEBub0luaGVyaXREb2MgKi9cbmNsYXNzIExpc3ROb2RlIGV4dGVuZHMgRWxlbWVudE5vZGUge1xuICAvKiogQGludGVybmFsICovXG4gIF9fdGFnO1xuICAvKiogQGludGVybmFsICovXG4gIF9fc3RhcnQ7XG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgX19saXN0VHlwZTtcblxuICAvKiogQGludGVybmFsICovXG4gICRjb25maWcoKSB7XG4gICAgcmV0dXJuIHRoaXMuY29uZmlnKCdsaXN0Jywge1xuICAgICAgJHRyYW5zZm9ybTogbm9kZSA9PiB7XG4gICAgICAgIG1lcmdlTmV4dFNpYmxpbmdMaXN0SWZTYW1lVHlwZShub2RlKTtcbiAgICAgICAgdXBkYXRlQ2hpbGRyZW5MaXN0SXRlbVZhbHVlKG5vZGUpO1xuICAgICAgfSxcbiAgICAgIGV4dGVuZHM6IEVsZW1lbnROb2RlLFxuICAgICAgaW1wb3J0RE9NOiBidWlsZEltcG9ydE1hcCh7XG4gICAgICAgIG9sOiAoKSA9PiAoe1xuICAgICAgICAgIGNvbnZlcnNpb246ICRjb252ZXJ0TGlzdE5vZGUsXG4gICAgICAgICAgcHJpb3JpdHk6IDBcbiAgICAgICAgfSksXG4gICAgICAgIHVsOiAoKSA9PiAoe1xuICAgICAgICAgIGNvbnZlcnNpb246ICRjb252ZXJ0TGlzdE5vZGUsXG4gICAgICAgICAgcHJpb3JpdHk6IDBcbiAgICAgICAgfSlcbiAgICAgIH0pXG4gICAgfSk7XG4gIH1cbiAgY29uc3RydWN0b3IobGlzdFR5cGUgPSAnbnVtYmVyJywgc3RhcnQgPSAxLCBrZXkpIHtcbiAgICBzdXBlcihrZXkpO1xuICAgIGNvbnN0IF9saXN0VHlwZSA9IFRBR19UT19MSVNUX1RZUEVbbGlzdFR5cGVdIHx8IGxpc3RUeXBlO1xuICAgIHRoaXMuX19saXN0VHlwZSA9IF9saXN0VHlwZTtcbiAgICB0aGlzLl9fdGFnID0gX2xpc3RUeXBlID09PSAnbnVtYmVyJyA/ICdvbCcgOiAndWwnO1xuICAgIHRoaXMuX19zdGFydCA9IHN0YXJ0O1xuICB9XG4gIGFmdGVyQ2xvbmVGcm9tKHByZXZOb2RlKSB7XG4gICAgc3VwZXIuYWZ0ZXJDbG9uZUZyb20ocHJldk5vZGUpO1xuICAgIHRoaXMuX19saXN0VHlwZSA9IHByZXZOb2RlLl9fbGlzdFR5cGU7XG4gICAgdGhpcy5fX3RhZyA9IHByZXZOb2RlLl9fdGFnO1xuICAgIHRoaXMuX19zdGFydCA9IHByZXZOb2RlLl9fc3RhcnQ7XG4gIH1cbiAgZ2V0VGFnKCkge1xuICAgIHJldHVybiB0aGlzLmdldExhdGVzdCgpLl9fdGFnO1xuICB9XG4gIHNldExpc3RUeXBlKHR5cGUpIHtcbiAgICBjb25zdCB3cml0YWJsZSA9IHRoaXMuZ2V0V3JpdGFibGUoKTtcbiAgICB3cml0YWJsZS5fX2xpc3RUeXBlID0gdHlwZTtcbiAgICB3cml0YWJsZS5fX3RhZyA9IHR5cGUgPT09ICdudW1iZXInID8gJ29sJyA6ICd1bCc7XG4gICAgcmV0dXJuIHdyaXRhYmxlO1xuICB9XG4gIGdldExpc3RUeXBlKCkge1xuICAgIHJldHVybiB0aGlzLmdldExhdGVzdCgpLl9fbGlzdFR5cGU7XG4gIH1cbiAgZ2V0U3RhcnQoKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0TGF0ZXN0KCkuX19zdGFydDtcbiAgfVxuICBzZXRTdGFydChzdGFydCkge1xuICAgIGNvbnN0IHNlbGYgPSB0aGlzLmdldFdyaXRhYmxlKCk7XG4gICAgc2VsZi5fX3N0YXJ0ID0gc3RhcnQ7XG4gICAgcmV0dXJuIHNlbGY7XG4gIH1cblxuICAvLyBWaWV3XG5cbiAgY3JlYXRlRE9NKGNvbmZpZywgX2VkaXRvcikge1xuICAgIGNvbnN0IHRhZyA9IHRoaXMuX190YWc7XG4gICAgY29uc3QgZG9tID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCh0YWcpO1xuICAgIGlmICh0aGlzLl9fc3RhcnQgIT09IDEpIHtcbiAgICAgIGRvbS5zZXRBdHRyaWJ1dGUoJ3N0YXJ0JywgU3RyaW5nKHRoaXMuX19zdGFydCkpO1xuICAgIH1cbiAgICAvLyBAdHMtZXhwZWN0LWVycm9yIEludGVybmFsIGZpZWxkLlxuICAgIGRvbS5fX2xleGljYWxMaXN0VHlwZSA9IHRoaXMuX19saXN0VHlwZTtcbiAgICAkc2V0TGlzdFRoZW1lQ2xhc3NOYW1lcyhkb20sIGNvbmZpZy50aGVtZSwgdGhpcyk7XG4gICAgcmV0dXJuIGRvbTtcbiAgfVxuICB1cGRhdGVET00ocHJldk5vZGUsIGRvbSwgY29uZmlnKSB7XG4gICAgaWYgKHByZXZOb2RlLl9fdGFnICE9PSB0aGlzLl9fdGFnIHx8IHByZXZOb2RlLl9fbGlzdFR5cGUgIT09IHRoaXMuX19saXN0VHlwZSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgICRzZXRMaXN0VGhlbWVDbGFzc05hbWVzKGRvbSwgY29uZmlnLnRoZW1lLCB0aGlzKTtcbiAgICBpZiAocHJldk5vZGUuX19zdGFydCAhPT0gdGhpcy5fX3N0YXJ0KSB7XG4gICAgICBkb20uc2V0QXR0cmlidXRlKCdzdGFydCcsIFN0cmluZyh0aGlzLl9fc3RhcnQpKTtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHVwZGF0ZUZyb21KU09OKHNlcmlhbGl6ZWROb2RlKSB7XG4gICAgcmV0dXJuIHN1cGVyLnVwZGF0ZUZyb21KU09OKHNlcmlhbGl6ZWROb2RlKS5zZXRMaXN0VHlwZShzZXJpYWxpemVkTm9kZS5saXN0VHlwZSkuc2V0U3RhcnQoc2VyaWFsaXplZE5vZGUuc3RhcnQpO1xuICB9XG4gIGV4cG9ydERPTShlZGl0b3IpIHtcbiAgICBjb25zdCBlbGVtZW50ID0gdGhpcy5jcmVhdGVET00oZWRpdG9yLl9jb25maWcsIGVkaXRvcik7XG4gICAgaWYgKGlzSFRNTEVsZW1lbnQoZWxlbWVudCkpIHtcbiAgICAgIGlmICh0aGlzLl9fc3RhcnQgIT09IDEpIHtcbiAgICAgICAgZWxlbWVudC5zZXRBdHRyaWJ1dGUoJ3N0YXJ0JywgU3RyaW5nKHRoaXMuX19zdGFydCkpO1xuICAgICAgfVxuICAgICAgaWYgKHRoaXMuX19saXN0VHlwZSA9PT0gJ2NoZWNrJykge1xuICAgICAgICBlbGVtZW50LnNldEF0dHJpYnV0ZSgnX19sZXhpY2FsTGlzdFR5cGUnLCAnY2hlY2snKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIGVsZW1lbnRcbiAgICB9O1xuICB9XG4gIGV4cG9ydEpTT04oKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLnN1cGVyLmV4cG9ydEpTT04oKSxcbiAgICAgIGxpc3RUeXBlOiB0aGlzLmdldExpc3RUeXBlKCksXG4gICAgICBzdGFydDogdGhpcy5nZXRTdGFydCgpLFxuICAgICAgdGFnOiB0aGlzLmdldFRhZygpXG4gICAgfTtcbiAgfVxuICBjYW5CZUVtcHR5KCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBjYW5JbmRlbnQoKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHNwbGljZShzdGFydCwgZGVsZXRlQ291bnQsIG5vZGVzVG9JbnNlcnQpIHtcbiAgICBsZXQgbGlzdEl0ZW1Ob2Rlc1RvSW5zZXJ0ID0gbm9kZXNUb0luc2VydDtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG5vZGVzVG9JbnNlcnQubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IG5vZGUgPSBub2Rlc1RvSW5zZXJ0W2ldO1xuICAgICAgaWYgKCEkaXNMaXN0SXRlbU5vZGUobm9kZSkpIHtcbiAgICAgICAgaWYgKGxpc3RJdGVtTm9kZXNUb0luc2VydCA9PT0gbm9kZXNUb0luc2VydCkge1xuICAgICAgICAgIGxpc3RJdGVtTm9kZXNUb0luc2VydCA9IFsuLi5ub2Rlc1RvSW5zZXJ0XTtcbiAgICAgICAgfVxuICAgICAgICBsaXN0SXRlbU5vZGVzVG9JbnNlcnRbaV0gPSAkY3JlYXRlTGlzdEl0ZW1Ob2RlKCkuYXBwZW5kKCRpc0VsZW1lbnROb2RlKG5vZGUpICYmICEoJGlzTGlzdE5vZGUobm9kZSkgfHwgbm9kZS5pc0lubGluZSgpKSA/ICRjcmVhdGVUZXh0Tm9kZShub2RlLmdldFRleHRDb250ZW50KCkpIDogbm9kZSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBzdXBlci5zcGxpY2Uoc3RhcnQsIGRlbGV0ZUNvdW50LCBsaXN0SXRlbU5vZGVzVG9JbnNlcnQpO1xuICB9XG4gIGV4dHJhY3RXaXRoQ2hpbGQoY2hpbGQpIHtcbiAgICByZXR1cm4gJGlzTGlzdEl0ZW1Ob2RlKGNoaWxkKTtcbiAgfVxufVxuZnVuY3Rpb24gJHNldExpc3RUaGVtZUNsYXNzTmFtZXMoZG9tLCBlZGl0b3JUaGVtZUNsYXNzZXMsIG5vZGUpIHtcbiAgY29uc3QgY2xhc3Nlc1RvQWRkID0gW107XG4gIGNvbnN0IGNsYXNzZXNUb1JlbW92ZSA9IFtdO1xuICBjb25zdCBsaXN0VGhlbWUgPSBlZGl0b3JUaGVtZUNsYXNzZXMubGlzdDtcbiAgaWYgKGxpc3RUaGVtZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgY29uc3QgbGlzdExldmVsc0NsYXNzTmFtZXMgPSBsaXN0VGhlbWVbYCR7bm9kZS5fX3RhZ31EZXB0aGBdIHx8IFtdO1xuICAgIGNvbnN0IGxpc3REZXB0aCA9ICRnZXRMaXN0RGVwdGgobm9kZSkgLSAxO1xuICAgIGNvbnN0IG5vcm1hbGl6ZWRMaXN0RGVwdGggPSBsaXN0RGVwdGggJSBsaXN0TGV2ZWxzQ2xhc3NOYW1lcy5sZW5ndGg7XG4gICAgY29uc3QgbGlzdExldmVsQ2xhc3NOYW1lID0gbGlzdExldmVsc0NsYXNzTmFtZXNbbm9ybWFsaXplZExpc3REZXB0aF07XG4gICAgY29uc3QgbGlzdENsYXNzTmFtZSA9IGxpc3RUaGVtZVtub2RlLl9fdGFnXTtcbiAgICBsZXQgbmVzdGVkTGlzdENsYXNzTmFtZTtcbiAgICBjb25zdCBuZXN0ZWRMaXN0VGhlbWUgPSBsaXN0VGhlbWUubmVzdGVkO1xuICAgIGNvbnN0IGNoZWNrbGlzdENsYXNzTmFtZSA9IGxpc3RUaGVtZS5jaGVja2xpc3Q7XG4gICAgaWYgKG5lc3RlZExpc3RUaGVtZSAhPT0gdW5kZWZpbmVkICYmIG5lc3RlZExpc3RUaGVtZS5saXN0KSB7XG4gICAgICBuZXN0ZWRMaXN0Q2xhc3NOYW1lID0gbmVzdGVkTGlzdFRoZW1lLmxpc3Q7XG4gICAgfVxuICAgIGlmIChsaXN0Q2xhc3NOYW1lICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGNsYXNzZXNUb0FkZC5wdXNoKGxpc3RDbGFzc05hbWUpO1xuICAgIH1cbiAgICBpZiAoY2hlY2tsaXN0Q2xhc3NOYW1lICE9PSB1bmRlZmluZWQgJiYgbm9kZS5fX2xpc3RUeXBlID09PSAnY2hlY2snKSB7XG4gICAgICBjbGFzc2VzVG9BZGQucHVzaChjaGVja2xpc3RDbGFzc05hbWUpO1xuICAgIH1cbiAgICBpZiAobGlzdExldmVsQ2xhc3NOYW1lICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGNsYXNzZXNUb0FkZC5wdXNoKC4uLm5vcm1hbGl6ZUNsYXNzTmFtZXMobGlzdExldmVsQ2xhc3NOYW1lKSk7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3RMZXZlbHNDbGFzc05hbWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmIChpICE9PSBub3JtYWxpemVkTGlzdERlcHRoKSB7XG4gICAgICAgICAgY2xhc3Nlc1RvUmVtb3ZlLnB1c2gobm9kZS5fX3RhZyArIGkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChuZXN0ZWRMaXN0Q2xhc3NOYW1lICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGNvbnN0IG5lc3RlZExpc3RJdGVtQ2xhc3NlcyA9IG5vcm1hbGl6ZUNsYXNzTmFtZXMobmVzdGVkTGlzdENsYXNzTmFtZSk7XG4gICAgICBpZiAobGlzdERlcHRoID4gMSkge1xuICAgICAgICBjbGFzc2VzVG9BZGQucHVzaCguLi5uZXN0ZWRMaXN0SXRlbUNsYXNzZXMpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY2xhc3Nlc1RvUmVtb3ZlLnB1c2goLi4ubmVzdGVkTGlzdEl0ZW1DbGFzc2VzKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgaWYgKGNsYXNzZXNUb1JlbW92ZS5sZW5ndGggPiAwKSB7XG4gICAgcmVtb3ZlQ2xhc3NOYW1lc0Zyb21FbGVtZW50KGRvbSwgLi4uY2xhc3Nlc1RvUmVtb3ZlKTtcbiAgfVxuICBpZiAoY2xhc3Nlc1RvQWRkLmxlbmd0aCA+IDApIHtcbiAgICBhZGRDbGFzc05hbWVzVG9FbGVtZW50KGRvbSwgLi4uY2xhc3Nlc1RvQWRkKTtcbiAgfVxufVxuXG4vKlxuICogVGhpcyBmdW5jdGlvbiBub3JtYWxpemVzIHRoZSBjaGlsZHJlbiBvZiBhIExpc3ROb2RlIGFmdGVyIHRoZSBjb252ZXJzaW9uIGZyb20gSFRNTCxcbiAqIGVuc3VyaW5nIHRoYXQgdGhleSBhcmUgYWxsIExpc3RJdGVtTm9kZXMgYW5kIGNvbnRhaW4gZWl0aGVyIGEgc2luZ2xlIG5lc3RlZCBMaXN0Tm9kZVxuICogb3Igc29tZSBvdGhlciBpbmxpbmUgY29udGVudC5cbiAqL1xuZnVuY3Rpb24gJG5vcm1hbGl6ZUNoaWxkcmVuKG5vZGVzKSB7XG4gIGNvbnN0IG5vcm1hbGl6ZWRMaXN0SXRlbXMgPSBbXTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBub2Rlcy5sZW5ndGg7IGkrKykge1xuICAgIGNvbnN0IG5vZGUgPSBub2Rlc1tpXTtcbiAgICBpZiAoJGlzTGlzdEl0ZW1Ob2RlKG5vZGUpKSB7XG4gICAgICBub3JtYWxpemVkTGlzdEl0ZW1zLnB1c2gobm9kZSk7XG4gICAgICBjb25zdCBjaGlsZHJlbiA9IG5vZGUuZ2V0Q2hpbGRyZW4oKTtcbiAgICAgIGlmIChjaGlsZHJlbi5sZW5ndGggPiAxKSB7XG4gICAgICAgIGNoaWxkcmVuLmZvckVhY2goY2hpbGQgPT4ge1xuICAgICAgICAgIGlmICgkaXNMaXN0Tm9kZShjaGlsZCkpIHtcbiAgICAgICAgICAgIG5vcm1hbGl6ZWRMaXN0SXRlbXMucHVzaCgkd3JhcEluTGlzdEl0ZW0oY2hpbGQpKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBub3JtYWxpemVkTGlzdEl0ZW1zLnB1c2goJHdyYXBJbkxpc3RJdGVtKG5vZGUpKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG5vcm1hbGl6ZWRMaXN0SXRlbXM7XG59XG5mdW5jdGlvbiBpc0RvbUNoZWNrbGlzdChkb21Ob2RlKSB7XG4gIGlmIChkb21Ob2RlLmdldEF0dHJpYnV0ZSgnX19sZXhpY2FsbGlzdHR5cGUnKSA9PT0gJ2NoZWNrJyB8fFxuICAvLyBpcyBnaXRodWIgY2hlY2tsaXN0XG4gIGRvbU5vZGUuY2xhc3NMaXN0LmNvbnRhaW5zKCdjb250YWlucy10YXNrLWxpc3QnKSB8fFxuICAvLyBpcyBqb3BsaW4gY2hlY2tsaXN0XG4gIGRvbU5vZGUuZ2V0QXR0cmlidXRlKCdkYXRhLWlzLWNoZWNrbGlzdCcpID09PSAnMScpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuICAvLyBpZiBjaGlsZHJlbiBhcmUgY2hlY2tsaXN0IGl0ZW1zLCB0aGUgbm9kZSBpcyBhIGNoZWNrbGlzdCB1bC4gQXBwbGljYWJsZSBmb3IgZ29vZ2xlZG9jIGNoZWNrbGlzdCBwYXN0aW5nLlxuICBmb3IgKGNvbnN0IGNoaWxkIG9mIGRvbU5vZGUuY2hpbGROb2Rlcykge1xuICAgIGlmIChpc0hUTUxFbGVtZW50KGNoaWxkKSAmJiBjaGlsZC5oYXNBdHRyaWJ1dGUoJ2FyaWEtY2hlY2tlZCcpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGZhbHNlO1xufVxuZnVuY3Rpb24gJGNvbnZlcnRMaXN0Tm9kZShkb21Ob2RlKSB7XG4gIGNvbnN0IG5vZGVOYW1lID0gZG9tTm9kZS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpO1xuICBsZXQgbm9kZSA9IG51bGw7XG4gIGlmIChub2RlTmFtZSA9PT0gJ29sJykge1xuICAgIC8vIEB0cy1pZ25vcmVcbiAgICBjb25zdCBzdGFydCA9IGRvbU5vZGUuc3RhcnQ7XG4gICAgbm9kZSA9ICRjcmVhdGVMaXN0Tm9kZSgnbnVtYmVyJywgc3RhcnQpO1xuICB9IGVsc2UgaWYgKG5vZGVOYW1lID09PSAndWwnKSB7XG4gICAgaWYgKGlzRG9tQ2hlY2tsaXN0KGRvbU5vZGUpKSB7XG4gICAgICBub2RlID0gJGNyZWF0ZUxpc3ROb2RlKCdjaGVjaycpO1xuICAgIH0gZWxzZSB7XG4gICAgICBub2RlID0gJGNyZWF0ZUxpc3ROb2RlKCdidWxsZXQnKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHtcbiAgICBhZnRlcjogJG5vcm1hbGl6ZUNoaWxkcmVuLFxuICAgIG5vZGVcbiAgfTtcbn1cbmNvbnN0IFRBR19UT19MSVNUX1RZUEUgPSB7XG4gIG9sOiAnbnVtYmVyJyxcbiAgdWw6ICdidWxsZXQnXG59O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBMaXN0Tm9kZSBvZiBsaXN0VHlwZS5cbiAqIEBwYXJhbSBsaXN0VHlwZSAtIFRoZSB0eXBlIG9mIGxpc3QgdG8gYmUgY3JlYXRlZC4gQ2FuIGJlICdudW1iZXInLCAnYnVsbGV0Jywgb3IgJ2NoZWNrJy5cbiAqIEBwYXJhbSBzdGFydCAtIFdoZXJlIGFuIG9yZGVyZWQgbGlzdCBzdGFydHMgaXRzIGNvdW50LCBzdGFydCA9IDEgaWYgbGVmdCB1bmRlZmluZWQuXG4gKiBAcmV0dXJucyBUaGUgbmV3IExpc3ROb2RlXG4gKi9cbmZ1bmN0aW9uICRjcmVhdGVMaXN0Tm9kZShsaXN0VHlwZSA9ICdudW1iZXInLCBzdGFydCA9IDEpIHtcbiAgcmV0dXJuICRhcHBseU5vZGVSZXBsYWNlbWVudChuZXcgTGlzdE5vZGUobGlzdFR5cGUsIHN0YXJ0KSk7XG59XG5cbi8qKlxuICogQ2hlY2tzIHRvIHNlZSBpZiB0aGUgbm9kZSBpcyBhIExpc3ROb2RlLlxuICogQHBhcmFtIG5vZGUgLSBUaGUgbm9kZSB0byBiZSBjaGVja2VkLlxuICogQHJldHVybnMgdHJ1ZSBpZiB0aGUgbm9kZSBpcyBhIExpc3ROb2RlLCBmYWxzZSBvdGhlcndpc2UuXG4gKi9cbmZ1bmN0aW9uICRpc0xpc3ROb2RlKG5vZGUpIHtcbiAgcmV0dXJuIG5vZGUgaW5zdGFuY2VvZiBMaXN0Tm9kZTtcbn1cblxuLyoqXG4gKiBDb3B5cmlnaHQgKGMpIE1ldGEgUGxhdGZvcm1zLCBJbmMuIGFuZCBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqL1xuXG5jb25zdCBJTlNFUlRfQ0hFQ0tfTElTVF9DT01NQU5EID0gY3JlYXRlQ29tbWFuZCgnSU5TRVJUX0NIRUNLX0xJU1RfQ09NTUFORCcpO1xuXG4vKipcbiAqIFJlZ2lzdGVycyB0aGUgY2hlY2tsaXN0IHBsdWdpbiB3aXRoIHRoZSBlZGl0b3IuXG4gKiBAcGFyYW0gZWRpdG9yIFRoZSBMZXhpY2FsRWRpdG9yIGluc3RhbmNlLlxuICogQHBhcmFtIG9wdGlvbnMgT3B0aW9uYWwgY29uZmlndXJhdGlvbi5cbiAqICAgLSBkaXNhYmxlVGFrZUZvY3VzT25DbGljazogSWYgdHJ1ZSwgY2xpY2tpbmcgYSBjaGVja2xpc3QgaXRlbSB3aWxsIG5vdCBmb2N1cyB0aGUgZWRpdG9yICh1c2VmdWwgZm9yIG1vYmlsZSkuXG4gKi9cbmZ1bmN0aW9uIHJlZ2lzdGVyQ2hlY2tMaXN0KGVkaXRvciwgb3B0aW9ucykge1xuICBjb25zdCBkaXNhYmxlVGFrZUZvY3VzT25DbGljayA9IG9wdGlvbnMgJiYgb3B0aW9ucy5kaXNhYmxlVGFrZUZvY3VzT25DbGljayB8fCBmYWxzZTtcbiAgY29uc3QgY29uZmlnSGFuZGxlQ2xpY2sgPSBldmVudCA9PiB7XG4gICAgaGFuZGxlQ2xpY2soZXZlbnQsIGRpc2FibGVUYWtlRm9jdXNPbkNsaWNrKTtcbiAgfTtcbiAgY29uc3QgY29uZmlnSGFuZGxlU2VsZWN0RGVmYXVsdHMgPSBldmVudCA9PiB7XG4gICAgaGFuZGxlU2VsZWN0RGVmYXVsdHMoZXZlbnQsIGRpc2FibGVUYWtlRm9jdXNPbkNsaWNrKTtcbiAgfTtcbiAgcmV0dXJuIG1lcmdlUmVnaXN0ZXIoZWRpdG9yLnJlZ2lzdGVyQ29tbWFuZChJTlNFUlRfQ0hFQ0tfTElTVF9DT01NQU5ELCAoKSA9PiB7XG4gICAgJGluc2VydExpc3QoJ2NoZWNrJyk7XG4gICAgcmV0dXJuIHRydWU7XG4gIH0sIENPTU1BTkRfUFJJT1JJVFlfTE9XKSwgZWRpdG9yLnJlZ2lzdGVyQ29tbWFuZChLRVlfQVJST1dfRE9XTl9DT01NQU5ELCBldmVudCA9PiB7XG4gICAgcmV0dXJuIGhhbmRsZUFycm93VXBPckRvd24oZXZlbnQsIGVkaXRvciwgZmFsc2UpO1xuICB9LCBDT01NQU5EX1BSSU9SSVRZX0xPVyksIGVkaXRvci5yZWdpc3RlckNvbW1hbmQoS0VZX0FSUk9XX1VQX0NPTU1BTkQsIGV2ZW50ID0+IHtcbiAgICByZXR1cm4gaGFuZGxlQXJyb3dVcE9yRG93bihldmVudCwgZWRpdG9yLCB0cnVlKTtcbiAgfSwgQ09NTUFORF9QUklPUklUWV9MT1cpLCBlZGl0b3IucmVnaXN0ZXJDb21tYW5kKEtFWV9FU0NBUEVfQ09NTUFORCwgKCkgPT4ge1xuICAgIGNvbnN0IGFjdGl2ZUl0ZW0gPSBnZXRBY3RpdmVDaGVja0xpc3RJdGVtKCk7XG4gICAgaWYgKGFjdGl2ZUl0ZW0gIT0gbnVsbCkge1xuICAgICAgY29uc3Qgcm9vdEVsZW1lbnQgPSBlZGl0b3IuZ2V0Um9vdEVsZW1lbnQoKTtcbiAgICAgIGlmIChyb290RWxlbWVudCAhPSBudWxsKSB7XG4gICAgICAgIHJvb3RFbGVtZW50LmZvY3VzKCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9LCBDT01NQU5EX1BSSU9SSVRZX0xPVyksIGVkaXRvci5yZWdpc3RlckNvbW1hbmQoS0VZX1NQQUNFX0NPTU1BTkQsIGV2ZW50ID0+IHtcbiAgICBjb25zdCBhY3RpdmVJdGVtID0gZ2V0QWN0aXZlQ2hlY2tMaXN0SXRlbSgpO1xuICAgIGlmIChhY3RpdmVJdGVtICE9IG51bGwgJiYgZWRpdG9yLmlzRWRpdGFibGUoKSkge1xuICAgICAgZWRpdG9yLnVwZGF0ZSgoKSA9PiB7XG4gICAgICAgIGNvbnN0IGxpc3RJdGVtTm9kZSA9ICRnZXROZWFyZXN0Tm9kZUZyb21ET01Ob2RlKGFjdGl2ZUl0ZW0pO1xuICAgICAgICBpZiAoJGlzTGlzdEl0ZW1Ob2RlKGxpc3RJdGVtTm9kZSkpIHtcbiAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgIGxpc3RJdGVtTm9kZS50b2dnbGVDaGVja2VkKCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfSwgQ09NTUFORF9QUklPUklUWV9MT1cpLCBlZGl0b3IucmVnaXN0ZXJDb21tYW5kKEtFWV9BUlJPV19MRUZUX0NPTU1BTkQsIGV2ZW50ID0+IHtcbiAgICByZXR1cm4gZWRpdG9yLmdldEVkaXRvclN0YXRlKCkucmVhZCgoKSA9PiB7XG4gICAgICBjb25zdCBzZWxlY3Rpb24gPSAkZ2V0U2VsZWN0aW9uKCk7XG4gICAgICBpZiAoJGlzUmFuZ2VTZWxlY3Rpb24oc2VsZWN0aW9uKSAmJiBzZWxlY3Rpb24uaXNDb2xsYXBzZWQoKSkge1xuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgYW5jaG9yXG4gICAgICAgIH0gPSBzZWxlY3Rpb247XG4gICAgICAgIGNvbnN0IGlzRWxlbWVudCA9IGFuY2hvci50eXBlID09PSAnZWxlbWVudCc7XG4gICAgICAgIGlmIChpc0VsZW1lbnQgfHwgYW5jaG9yLm9mZnNldCA9PT0gMCkge1xuICAgICAgICAgIGNvbnN0IGFuY2hvck5vZGUgPSBhbmNob3IuZ2V0Tm9kZSgpO1xuICAgICAgICAgIGNvbnN0IGVsZW1lbnROb2RlID0gJGZpbmRNYXRjaGluZ1BhcmVudChhbmNob3JOb2RlLCBub2RlID0+ICRpc0VsZW1lbnROb2RlKG5vZGUpICYmICFub2RlLmlzSW5saW5lKCkpO1xuICAgICAgICAgIGlmICgkaXNMaXN0SXRlbU5vZGUoZWxlbWVudE5vZGUpKSB7XG4gICAgICAgICAgICBjb25zdCBwYXJlbnQgPSBlbGVtZW50Tm9kZS5nZXRQYXJlbnQoKTtcbiAgICAgICAgICAgIGlmICgkaXNMaXN0Tm9kZShwYXJlbnQpICYmIHBhcmVudC5nZXRMaXN0VHlwZSgpID09PSAnY2hlY2snICYmIChpc0VsZW1lbnQgfHwgZWxlbWVudE5vZGUuZ2V0Rmlyc3REZXNjZW5kYW50KCkgPT09IGFuY2hvck5vZGUpKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGRvbU5vZGUgPSBlZGl0b3IuZ2V0RWxlbWVudEJ5S2V5KGVsZW1lbnROb2RlLl9fa2V5KTtcbiAgICAgICAgICAgICAgaWYgKGRvbU5vZGUgIT0gbnVsbCAmJiBkb2N1bWVudC5hY3RpdmVFbGVtZW50ICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgZG9tTm9kZS5mb2N1cygpO1xuICAgICAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9KTtcbiAgfSwgQ09NTUFORF9QUklPUklUWV9MT1cpLCBlZGl0b3IucmVnaXN0ZXJSb290TGlzdGVuZXIoKHJvb3RFbGVtZW50LCBwcmV2RWxlbWVudCkgPT4ge1xuICAgIGlmIChyb290RWxlbWVudCAhPT0gbnVsbCkge1xuICAgICAgcm9vdEVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCBjb25maWdIYW5kbGVDbGljayk7XG4gICAgICAvLyBVc2UgY2FwdHVyZSBzbyB3ZSBydW4gYmVmb3JlIG90aGVyIGxpc3RlbmVycyB0aGF0IG1pZ2h0IG1vdmUgZm9jdXMuXG4gICAgICByb290RWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdwb2ludGVyZG93bicsIGNvbmZpZ0hhbmRsZVNlbGVjdERlZmF1bHRzLCB7XG4gICAgICAgIGNhcHR1cmU6IHRydWVcbiAgICAgIH0pO1xuICAgICAgLy8gU29tZSBicm93c2VycyAvIGludGVncmF0aW9ucyBzdGlsbCBnZW5lcmF0ZSBtb3VzZWRvd24gZXZlbnRzOyBoYW5kbGUgdGhlbSB0b28uXG4gICAgICByb290RWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCBjb25maWdIYW5kbGVTZWxlY3REZWZhdWx0cywge1xuICAgICAgICBjYXB0dXJlOiB0cnVlXG4gICAgICB9KTtcbiAgICAgIC8vIEludGVyY2VwdCB0b3VjaHN0YXJ0IHRvIHN0b3AgdGhlIG1vYmlsZSBicm93c2VyIGZyb20gcGxhY2luZyB0aGUgY2FyZXRcbiAgICAgIC8vIGFuZCBvcGVuaW5nIHRoZSBrZXlib2FyZCB3aGVuIHRhcHBpbmcgdGhlIGNoZWNrbGlzdCBtYXJrZXIuXG4gICAgICByb290RWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCd0b3VjaHN0YXJ0JywgY29uZmlnSGFuZGxlU2VsZWN0RGVmYXVsdHMsIHtcbiAgICAgICAgY2FwdHVyZTogdHJ1ZSxcbiAgICAgICAgcGFzc2l2ZTogZmFsc2VcbiAgICAgIH0pO1xuICAgIH1cbiAgICBpZiAocHJldkVsZW1lbnQgIT09IG51bGwpIHtcbiAgICAgIHByZXZFbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgY29uZmlnSGFuZGxlQ2xpY2spO1xuICAgICAgcHJldkVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigncG9pbnRlcmRvd24nLCBjb25maWdIYW5kbGVTZWxlY3REZWZhdWx0cywge1xuICAgICAgICBjYXB0dXJlOiB0cnVlXG4gICAgICB9KTtcbiAgICAgIHByZXZFbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIGNvbmZpZ0hhbmRsZVNlbGVjdERlZmF1bHRzLCB7XG4gICAgICAgIGNhcHR1cmU6IHRydWVcbiAgICAgIH0pO1xuICAgICAgcHJldkVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2hzdGFydCcsIGNvbmZpZ0hhbmRsZVNlbGVjdERlZmF1bHRzLCB7XG4gICAgICAgIGNhcHR1cmU6IHRydWVcbiAgICAgIH0pO1xuICAgIH1cbiAgfSkpO1xufVxuZnVuY3Rpb24gaGFuZGxlQ2hlY2tJdGVtRXZlbnQoZXZlbnQsIGNhbGxiYWNrKSB7XG4gIGNvbnN0IHRhcmdldCA9IGV2ZW50LnRhcmdldDtcbiAgaWYgKCFpc0hUTUxFbGVtZW50KHRhcmdldCkpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICAvLyBJZ25vcmUgY2xpY2tzIG9uIExJIHRoYXQgaGF2ZSBuZXN0ZWQgbGlzdHNcbiAgY29uc3QgZmlyc3RDaGlsZCA9IHRhcmdldC5maXJzdENoaWxkO1xuICBpZiAoaXNIVE1MRWxlbWVudChmaXJzdENoaWxkKSAmJiAoZmlyc3RDaGlsZC50YWdOYW1lID09PSAnVUwnIHx8IGZpcnN0Q2hpbGQudGFnTmFtZSA9PT0gJ09MJykpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgY29uc3QgcGFyZW50Tm9kZSA9IHRhcmdldC5wYXJlbnROb2RlO1xuXG4gIC8vIEB0cy1pZ25vcmUgaW50ZXJuYWwgZmllbGRcbiAgaWYgKCFwYXJlbnROb2RlIHx8IHBhcmVudE5vZGUuX19sZXhpY2FsTGlzdFR5cGUgIT09ICdjaGVjaycpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgbGV0IGNsaWVudFggPSBudWxsO1xuICBsZXQgcG9pbnRlclR5cGUgPSBudWxsO1xuICBpZiAoJ2NsaWVudFgnIGluIGV2ZW50KSB7XG4gICAgY2xpZW50WCA9IGV2ZW50LmNsaWVudFg7XG4gIH0gZWxzZSBpZiAoJ3RvdWNoZXMnIGluIGV2ZW50KSB7XG4gICAgY29uc3QgdG91Y2hlcyA9IGV2ZW50LnRvdWNoZXM7XG4gICAgaWYgKHRvdWNoZXMubGVuZ3RoID4gMCkge1xuICAgICAgY2xpZW50WCA9IHRvdWNoZXNbMF0uY2xpZW50WDtcbiAgICAgIHBvaW50ZXJUeXBlID0gJ3RvdWNoJztcbiAgICB9XG4gIH1cblxuICAvLyBJZiB3ZSBjb3VsZG4ndCByZXNvbHZlIGEgY2xpZW50WCAodW5leHBlY3RlZCBpbnB1dCksIGJhaWwgb3V0LlxuICBpZiAoY2xpZW50WCA9PSBudWxsKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIGNvbnN0IHJlY3QgPSB0YXJnZXQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gIGNvbnN0IHpvb20gPSBjYWxjdWxhdGVab29tTGV2ZWwodGFyZ2V0KTtcbiAgY29uc3QgY2xpZW50WEluUGl4ZWxzID0gY2xpZW50WCAvIHpvb207XG5cbiAgLy8gVXNlIGdldENvbXB1dGVkU3R5bGUgaWYgYXZhaWxhYmxlLCBvdGhlcndpc2UgZmFsbGJhY2sgdG8gMHB4IHdpZHRoXG4gIGNvbnN0IGJlZm9yZVN0eWxlcyA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlID8gd2luZG93LmdldENvbXB1dGVkU3R5bGUodGFyZ2V0LCAnOjpiZWZvcmUnKSA6IHtcbiAgICB3aWR0aDogJzBweCdcbiAgfTtcbiAgY29uc3QgYmVmb3JlV2lkdGhJblBpeGVscyA9IHBhcnNlRmxvYXQoYmVmb3JlU3R5bGVzLndpZHRoKTtcblxuICAvLyBNYWtlIGNsaWNrIGFyZWEgc2xpZ2h0bHkgbGFyZ2VyIGZvciB0b3VjaCBkZXZpY2VzIHRvIGltcHJvdmUgYWNjZXNzaWJpbGl0eVxuICAvLyBEZXRlcm1pbmUgd2hldGhlciB0aGlzIGlzIGEgdG91Y2ggZXZlbnQ7IHNvbWUgZW52aXJvbm1lbnRzIG1heSBzdXBwbHlcbiAgLy8gcG9pbnRlclR5cGUgb24gUG9pbnRlckV2ZW50IHdoaWxlIHRvdWNoIGV2ZW50cyB1c2UgdGhlIGB0b3VjaGVzYCBBUEkgYWJvdmUuXG4gIGNvbnN0IGlzVG91Y2hFdmVudCA9IHBvaW50ZXJUeXBlID09PSAndG91Y2gnIHx8IGV2ZW50LnBvaW50ZXJUeXBlID09PSAndG91Y2gnO1xuICBjb25zdCBjbGlja0FyZWFQYWRkaW5nID0gaXNUb3VjaEV2ZW50ID8gMzIgOiAwOyAvLyBBZGQgMzJweCBwYWRkaW5nIGZvciB0b3VjaCBldmVudHNcblxuICBpZiAodGFyZ2V0LmRpciA9PT0gJ3J0bCcgPyBjbGllbnRYSW5QaXhlbHMgPCByZWN0LnJpZ2h0ICsgY2xpY2tBcmVhUGFkZGluZyAmJiBjbGllbnRYSW5QaXhlbHMgPiByZWN0LnJpZ2h0IC0gYmVmb3JlV2lkdGhJblBpeGVscyAtIGNsaWNrQXJlYVBhZGRpbmcgOiBjbGllbnRYSW5QaXhlbHMgPiByZWN0LmxlZnQgLSBjbGlja0FyZWFQYWRkaW5nICYmIGNsaWVudFhJblBpeGVscyA8IHJlY3QubGVmdCArIGJlZm9yZVdpZHRoSW5QaXhlbHMgKyBjbGlja0FyZWFQYWRkaW5nKSB7XG4gICAgY2FsbGJhY2soKTtcbiAgfVxufVxuZnVuY3Rpb24gaGFuZGxlQ2xpY2soZXZlbnQsIGRpc2FibGVGb2N1c09uQ2xpY2spIHtcbiAgaGFuZGxlQ2hlY2tJdGVtRXZlbnQoZXZlbnQsICgpID0+IHtcbiAgICBpZiAoaXNIVE1MRWxlbWVudChldmVudC50YXJnZXQpKSB7XG4gICAgICBjb25zdCBkb21Ob2RlID0gZXZlbnQudGFyZ2V0O1xuICAgICAgY29uc3QgZWRpdG9yID0gZ2V0TmVhcmVzdEVkaXRvckZyb21ET01Ob2RlKGRvbU5vZGUpO1xuICAgICAgaWYgKGVkaXRvciAhPSBudWxsICYmIGVkaXRvci5pc0VkaXRhYmxlKCkpIHtcbiAgICAgICAgZWRpdG9yLnVwZGF0ZSgoKSA9PiB7XG4gICAgICAgICAgY29uc3Qgbm9kZSA9ICRnZXROZWFyZXN0Tm9kZUZyb21ET01Ob2RlKGRvbU5vZGUpO1xuICAgICAgICAgIGlmICgkaXNMaXN0SXRlbU5vZGUobm9kZSkpIHtcbiAgICAgICAgICAgIGlmIChkaXNhYmxlRm9jdXNPbkNsaWNrKSB7XG4gICAgICAgICAgICAgICRhZGRVcGRhdGVUYWcoU0tJUF9TRUxFQ1RJT05fRk9DVVNfVEFHKTtcbiAgICAgICAgICAgICAgJGFkZFVwZGF0ZVRhZyhTS0lQX0RPTV9TRUxFQ1RJT05fVEFHKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGRvbU5vZGUuZm9jdXMoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG5vZGUudG9nZ2xlQ2hlY2tlZCgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuICB9KTtcbn1cblxuLyoqXG4gKiBQcmV2ZW50cyBkZWZhdWx0IGZvY3VzIHN3aXRjaCBiZWhhdmlvclxuICpcbiAqIEBwYXJhbSBldmVudCBtaWdodCBiZSBvZiB0eXBlIFBvaW50ZXJFdmVudCwgTW91c2VFdmVudCwgb3IgVG91Y2hFdmVudCwgaGVuY2UgdGhlIGdlbmVyaWMgRXZlbnQgdHlwZVxuICpcbiAqL1xuZnVuY3Rpb24gaGFuZGxlU2VsZWN0RGVmYXVsdHMoZXZlbnQsIGRpc2FibGVUYWtlRm9jdXNPbkNsaWNrKSB7XG4gIGhhbmRsZUNoZWNrSXRlbUV2ZW50KGV2ZW50LCAoKSA9PiB7XG4gICAgLy8gUHJldmVudHMgY2FyZXQgbW92aW5nIHdoZW4gY2xpY2tpbmcgb24gY2hlY2sgbWFyay5cbiAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIGlmIChkaXNhYmxlVGFrZUZvY3VzT25DbGljaykge1xuICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgfVxuICB9KTtcbn1cbmZ1bmN0aW9uIGdldEFjdGl2ZUNoZWNrTGlzdEl0ZW0oKSB7XG4gIGNvbnN0IGFjdGl2ZUVsZW1lbnQgPSBkb2N1bWVudC5hY3RpdmVFbGVtZW50O1xuICByZXR1cm4gaXNIVE1MRWxlbWVudChhY3RpdmVFbGVtZW50KSAmJiBhY3RpdmVFbGVtZW50LnRhZ05hbWUgPT09ICdMSScgJiYgYWN0aXZlRWxlbWVudC5wYXJlbnROb2RlICE9IG51bGwgJiZcbiAgLy8gQHRzLWlnbm9yZSBpbnRlcm5hbCBmaWVsZFxuICBhY3RpdmVFbGVtZW50LnBhcmVudE5vZGUuX19sZXhpY2FsTGlzdFR5cGUgPT09ICdjaGVjaycgPyBhY3RpdmVFbGVtZW50IDogbnVsbDtcbn1cbmZ1bmN0aW9uIGZpbmRDaGVja0xpc3RJdGVtU2libGluZyhub2RlLCBiYWNrd2FyZCkge1xuICBsZXQgc2libGluZyA9IGJhY2t3YXJkID8gbm9kZS5nZXRQcmV2aW91c1NpYmxpbmcoKSA6IG5vZGUuZ2V0TmV4dFNpYmxpbmcoKTtcbiAgbGV0IHBhcmVudCA9IG5vZGU7XG5cbiAgLy8gR29pbmcgdXAgaW4gYSB0cmVlIHRvIGdldCBub24tbnVsbCBzaWJsaW5nXG4gIHdoaWxlIChzaWJsaW5nID09IG51bGwgJiYgJGlzTGlzdEl0ZW1Ob2RlKHBhcmVudCkpIHtcbiAgICAvLyBHZXQgbGkgLT4gcGFyZW50IHVsL29sIC0+IHBhcmVudCBsaVxuICAgIHBhcmVudCA9IHBhcmVudC5nZXRQYXJlbnRPclRocm93KCkuZ2V0UGFyZW50KCk7XG4gICAgaWYgKHBhcmVudCAhPSBudWxsKSB7XG4gICAgICBzaWJsaW5nID0gYmFja3dhcmQgPyBwYXJlbnQuZ2V0UHJldmlvdXNTaWJsaW5nKCkgOiBwYXJlbnQuZ2V0TmV4dFNpYmxpbmcoKTtcbiAgICB9XG4gIH1cblxuICAvLyBHb2luZyBkb3duIGluIGEgdHJlZSB0byBnZXQgZmlyc3Qgbm9uLW5lc3RlZCBsaXN0IGl0ZW1cbiAgd2hpbGUgKCRpc0xpc3RJdGVtTm9kZShzaWJsaW5nKSkge1xuICAgIGNvbnN0IGZpcnN0Q2hpbGQgPSBiYWNrd2FyZCA/IHNpYmxpbmcuZ2V0TGFzdENoaWxkKCkgOiBzaWJsaW5nLmdldEZpcnN0Q2hpbGQoKTtcbiAgICBpZiAoISRpc0xpc3ROb2RlKGZpcnN0Q2hpbGQpKSB7XG4gICAgICByZXR1cm4gc2libGluZztcbiAgICB9XG4gICAgc2libGluZyA9IGJhY2t3YXJkID8gZmlyc3RDaGlsZC5nZXRMYXN0Q2hpbGQoKSA6IGZpcnN0Q2hpbGQuZ2V0Rmlyc3RDaGlsZCgpO1xuICB9XG4gIHJldHVybiBudWxsO1xufVxuZnVuY3Rpb24gaGFuZGxlQXJyb3dVcE9yRG93bihldmVudCwgZWRpdG9yLCBiYWNrd2FyZCkge1xuICBjb25zdCBhY3RpdmVJdGVtID0gZ2V0QWN0aXZlQ2hlY2tMaXN0SXRlbSgpO1xuICBpZiAoYWN0aXZlSXRlbSAhPSBudWxsKSB7XG4gICAgZWRpdG9yLnVwZGF0ZSgoKSA9PiB7XG4gICAgICBjb25zdCBsaXN0SXRlbSA9ICRnZXROZWFyZXN0Tm9kZUZyb21ET01Ob2RlKGFjdGl2ZUl0ZW0pO1xuICAgICAgaWYgKCEkaXNMaXN0SXRlbU5vZGUobGlzdEl0ZW0pKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGNvbnN0IG5leHRMaXN0SXRlbSA9IGZpbmRDaGVja0xpc3RJdGVtU2libGluZyhsaXN0SXRlbSwgYmFja3dhcmQpO1xuICAgICAgaWYgKG5leHRMaXN0SXRlbSAhPSBudWxsKSB7XG4gICAgICAgIG5leHRMaXN0SXRlbS5zZWxlY3RTdGFydCgpO1xuICAgICAgICBjb25zdCBkb20gPSBlZGl0b3IuZ2V0RWxlbWVudEJ5S2V5KG5leHRMaXN0SXRlbS5fX2tleSk7XG4gICAgICAgIGlmIChkb20gIT0gbnVsbCkge1xuICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICBkb20uZm9jdXMoKTtcbiAgICAgICAgICB9LCAwKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICB9XG4gIHJldHVybiBmYWxzZTtcbn1cblxuLyoqXG4gKiBDb3B5cmlnaHQgKGMpIE1ldGEgUGxhdGZvcm1zLCBJbmMuIGFuZCBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqL1xuXG5jb25zdCBVUERBVEVfTElTVF9TVEFSVF9DT01NQU5EID0gY3JlYXRlQ29tbWFuZCgnVVBEQVRFX0xJU1RfU1RBUlRfQ09NTUFORCcpO1xuY29uc3QgSU5TRVJUX1VOT1JERVJFRF9MSVNUX0NPTU1BTkQgPSBjcmVhdGVDb21tYW5kKCdJTlNFUlRfVU5PUkRFUkVEX0xJU1RfQ09NTUFORCcpO1xuY29uc3QgSU5TRVJUX09SREVSRURfTElTVF9DT01NQU5EID0gY3JlYXRlQ29tbWFuZCgnSU5TRVJUX09SREVSRURfTElTVF9DT01NQU5EJyk7XG5jb25zdCBSRU1PVkVfTElTVF9DT01NQU5EID0gY3JlYXRlQ29tbWFuZCgnUkVNT1ZFX0xJU1RfQ09NTUFORCcpO1xuZnVuY3Rpb24gcmVnaXN0ZXJMaXN0KGVkaXRvciwgb3B0aW9ucykge1xuICBjb25zdCByZW1vdmVMaXN0ZW5lciA9IG1lcmdlUmVnaXN0ZXIoZWRpdG9yLnJlZ2lzdGVyQ29tbWFuZChJTlNFUlRfT1JERVJFRF9MSVNUX0NPTU1BTkQsICgpID0+IHtcbiAgICAkaW5zZXJ0TGlzdCgnbnVtYmVyJyk7XG4gICAgcmV0dXJuIHRydWU7XG4gIH0sIENPTU1BTkRfUFJJT1JJVFlfTE9XKSwgZWRpdG9yLnJlZ2lzdGVyQ29tbWFuZChVUERBVEVfTElTVF9TVEFSVF9DT01NQU5ELCBwYXlsb2FkID0+IHtcbiAgICBjb25zdCB7XG4gICAgICBsaXN0Tm9kZUtleSxcbiAgICAgIG5ld1N0YXJ0XG4gICAgfSA9IHBheWxvYWQ7XG4gICAgY29uc3QgbGlzdE5vZGUgPSAkZ2V0Tm9kZUJ5S2V5KGxpc3ROb2RlS2V5KTtcbiAgICBpZiAoISRpc0xpc3ROb2RlKGxpc3ROb2RlKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBpZiAobGlzdE5vZGUuZ2V0TGlzdFR5cGUoKSA9PT0gJ251bWJlcicpIHtcbiAgICAgIGxpc3ROb2RlLnNldFN0YXJ0KG5ld1N0YXJ0KTtcbiAgICAgIHVwZGF0ZUNoaWxkcmVuTGlzdEl0ZW1WYWx1ZShsaXN0Tm9kZSk7XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9LCBDT01NQU5EX1BSSU9SSVRZX0xPVyksIGVkaXRvci5yZWdpc3RlckNvbW1hbmQoSU5TRVJUX1VOT1JERVJFRF9MSVNUX0NPTU1BTkQsICgpID0+IHtcbiAgICAkaW5zZXJ0TGlzdCgnYnVsbGV0Jyk7XG4gICAgcmV0dXJuIHRydWU7XG4gIH0sIENPTU1BTkRfUFJJT1JJVFlfTE9XKSwgZWRpdG9yLnJlZ2lzdGVyQ29tbWFuZChSRU1PVkVfTElTVF9DT01NQU5ELCAoKSA9PiB7XG4gICAgJHJlbW92ZUxpc3QoKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSwgQ09NTUFORF9QUklPUklUWV9MT1cpLCBlZGl0b3IucmVnaXN0ZXJDb21tYW5kKElOU0VSVF9QQVJBR1JBUEhfQ09NTUFORCwgKCkgPT4ge1xuICAgIGNvbnN0IHNob3VsZFJlc3RvcmUgPSBvcHRpb25zICYmIG9wdGlvbnMucmVzdG9yZU51bWJlcmluZztcbiAgICByZXR1cm4gJGhhbmRsZUxpc3RJbnNlcnRQYXJhZ3JhcGgoISFzaG91bGRSZXN0b3JlKTtcbiAgfSwgQ09NTUFORF9QUklPUklUWV9MT1cpLCBlZGl0b3IucmVnaXN0ZXJOb2RlVHJhbnNmb3JtKExpc3RJdGVtTm9kZSwgbm9kZSA9PiB7XG4gICAgY29uc3QgZmlyc3RDaGlsZCA9IG5vZGUuZ2V0Rmlyc3RDaGlsZCgpO1xuICAgIGlmIChmaXJzdENoaWxkKSB7XG4gICAgICBpZiAoJGlzVGV4dE5vZGUoZmlyc3RDaGlsZCkpIHtcbiAgICAgICAgY29uc3Qgc3R5bGUgPSBmaXJzdENoaWxkLmdldFN0eWxlKCk7XG4gICAgICAgIGNvbnN0IGZvcm1hdCA9IGZpcnN0Q2hpbGQuZ2V0Rm9ybWF0KCk7XG4gICAgICAgIGlmIChub2RlLmdldFRleHRTdHlsZSgpICE9PSBzdHlsZSkge1xuICAgICAgICAgIG5vZGUuc2V0VGV4dFN0eWxlKHN0eWxlKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobm9kZS5nZXRUZXh0Rm9ybWF0KCkgIT09IGZvcm1hdCkge1xuICAgICAgICAgIG5vZGUuc2V0VGV4dEZvcm1hdChmb3JtYXQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIElmIGl0J3MgZW1wdHksIGNoZWNrIHRoZSBzZWxlY3Rpb25cbiAgICAgIGNvbnN0IHNlbGVjdGlvbiA9ICRnZXRTZWxlY3Rpb24oKTtcbiAgICAgIGlmICgkaXNSYW5nZVNlbGVjdGlvbihzZWxlY3Rpb24pICYmIChzZWxlY3Rpb24uc3R5bGUgIT09IG5vZGUuZ2V0VGV4dFN0eWxlKCkgfHwgc2VsZWN0aW9uLmZvcm1hdCAhPT0gbm9kZS5nZXRUZXh0Rm9ybWF0KCkpICYmIHNlbGVjdGlvbi5pc0NvbGxhcHNlZCgpICYmIG5vZGUuaXMoc2VsZWN0aW9uLmFuY2hvci5nZXROb2RlKCkpKSB7XG4gICAgICAgIG5vZGUuc2V0VGV4dFN0eWxlKHNlbGVjdGlvbi5zdHlsZSkuc2V0VGV4dEZvcm1hdChzZWxlY3Rpb24uZm9ybWF0KTtcbiAgICAgIH1cbiAgICB9XG4gIH0pLCBlZGl0b3IucmVnaXN0ZXJOb2RlVHJhbnNmb3JtKFRleHROb2RlLCBub2RlID0+IHtcbiAgICBjb25zdCBsaXN0SXRlbVBhcmVudE5vZGUgPSBub2RlLmdldFBhcmVudCgpO1xuICAgIGlmICgkaXNMaXN0SXRlbU5vZGUobGlzdEl0ZW1QYXJlbnROb2RlKSAmJiBub2RlLmlzKGxpc3RJdGVtUGFyZW50Tm9kZS5nZXRGaXJzdENoaWxkKCkpKSB7XG4gICAgICBjb25zdCBzdHlsZSA9IG5vZGUuZ2V0U3R5bGUoKTtcbiAgICAgIGNvbnN0IGZvcm1hdCA9IG5vZGUuZ2V0Rm9ybWF0KCk7XG4gICAgICBpZiAoc3R5bGUgIT09IGxpc3RJdGVtUGFyZW50Tm9kZS5nZXRUZXh0U3R5bGUoKSB8fCBmb3JtYXQgIT09IGxpc3RJdGVtUGFyZW50Tm9kZS5nZXRUZXh0Rm9ybWF0KCkpIHtcbiAgICAgICAgbGlzdEl0ZW1QYXJlbnROb2RlLnNldFRleHRTdHlsZShzdHlsZSkuc2V0VGV4dEZvcm1hdChmb3JtYXQpO1xuICAgICAgfVxuICAgIH1cbiAgfSkpO1xuICByZXR1cm4gcmVtb3ZlTGlzdGVuZXI7XG59XG5mdW5jdGlvbiByZWdpc3Rlckxpc3RTdHJpY3RJbmRlbnRUcmFuc2Zvcm0oZWRpdG9yKSB7XG4gIGNvbnN0ICRmb3JtYXRMaXN0SW5kZW50U3RyaWN0ID0gbGlzdEl0ZW1Ob2RlID0+IHtcbiAgICBjb25zdCBsaXN0Tm9kZSA9IGxpc3RJdGVtTm9kZS5nZXRQYXJlbnQoKTtcbiAgICBpZiAoJGlzTGlzdE5vZGUobGlzdEl0ZW1Ob2RlLmdldEZpcnN0Q2hpbGQoKSkgfHwgISRpc0xpc3ROb2RlKGxpc3ROb2RlKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBzdGFydGluZ0xpc3RJdGVtTm9kZSA9ICRmaW5kTWF0Y2hpbmdQYXJlbnQobGlzdEl0ZW1Ob2RlLCBub2RlID0+ICRpc0xpc3RJdGVtTm9kZShub2RlKSAmJiAkaXNMaXN0Tm9kZShub2RlLmdldFBhcmVudCgpKSAmJiAkaXNMaXN0SXRlbU5vZGUobm9kZS5nZXRQcmV2aW91c1NpYmxpbmcoKSkpO1xuICAgIGlmIChzdGFydGluZ0xpc3RJdGVtTm9kZSA9PT0gbnVsbCAmJiBsaXN0SXRlbU5vZGUuZ2V0SW5kZW50KCkgPiAwKSB7XG4gICAgICBsaXN0SXRlbU5vZGUuc2V0SW5kZW50KDApO1xuICAgIH0gZWxzZSBpZiAoJGlzTGlzdEl0ZW1Ob2RlKHN0YXJ0aW5nTGlzdEl0ZW1Ob2RlKSkge1xuICAgICAgY29uc3QgcHJldkxpc3RJdGVtTm9kZSA9IHN0YXJ0aW5nTGlzdEl0ZW1Ob2RlLmdldFByZXZpb3VzU2libGluZygpO1xuICAgICAgaWYgKCRpc0xpc3RJdGVtTm9kZShwcmV2TGlzdEl0ZW1Ob2RlKSkge1xuICAgICAgICBjb25zdCBlbmRMaXN0SXRlbU5vZGUgPSAkZmluZENoaWxkcmVuRW5kTGlzdEl0ZW1Ob2RlKHByZXZMaXN0SXRlbU5vZGUpO1xuICAgICAgICBjb25zdCBlbmRMaXN0Tm9kZSA9IGVuZExpc3RJdGVtTm9kZS5nZXRQYXJlbnQoKTtcbiAgICAgICAgaWYgKCRpc0xpc3ROb2RlKGVuZExpc3ROb2RlKSkge1xuICAgICAgICAgIGNvbnN0IHByZXZEZXB0aCA9ICRnZXRMaXN0RGVwdGgoZW5kTGlzdE5vZGUpO1xuICAgICAgICAgIGNvbnN0IGRlcHRoID0gJGdldExpc3REZXB0aChsaXN0Tm9kZSk7XG4gICAgICAgICAgaWYgKHByZXZEZXB0aCArIDEgPCBkZXB0aCkge1xuICAgICAgICAgICAgbGlzdEl0ZW1Ob2RlLnNldEluZGVudChwcmV2RGVwdGgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfTtcbiAgY29uc3QgJHByb2Nlc3NMaXN0V2l0aFN0cmljdEluZGVudCA9IGxpc3ROb2RlID0+IHtcbiAgICBjb25zdCBxdWV1ZSA9IFtsaXN0Tm9kZV07XG4gICAgd2hpbGUgKHF1ZXVlLmxlbmd0aCA+IDApIHtcbiAgICAgIGNvbnN0IG5vZGUgPSBxdWV1ZS5zaGlmdCgpO1xuICAgICAgaWYgKCEkaXNMaXN0Tm9kZShub2RlKSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGZvciAoY29uc3QgY2hpbGQgb2Ygbm9kZS5nZXRDaGlsZHJlbigpKSB7XG4gICAgICAgIGlmICgkaXNMaXN0SXRlbU5vZGUoY2hpbGQpKSB7XG4gICAgICAgICAgJGZvcm1hdExpc3RJbmRlbnRTdHJpY3QoY2hpbGQpO1xuICAgICAgICAgIGNvbnN0IGZpcnN0Q2hpbGQgPSBjaGlsZC5nZXRGaXJzdENoaWxkKCk7XG4gICAgICAgICAgaWYgKCRpc0xpc3ROb2RlKGZpcnN0Q2hpbGQpKSB7XG4gICAgICAgICAgICBxdWV1ZS5wdXNoKGZpcnN0Q2hpbGQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfTtcbiAgcmV0dXJuIGVkaXRvci5yZWdpc3Rlck5vZGVUcmFuc2Zvcm0oTGlzdE5vZGUsICRwcm9jZXNzTGlzdFdpdGhTdHJpY3RJbmRlbnQpO1xufVxuZnVuY3Rpb24gJGZpbmRDaGlsZHJlbkVuZExpc3RJdGVtTm9kZShsaXN0SXRlbU5vZGUpIHtcbiAgbGV0IGN1cnJlbnQgPSBsaXN0SXRlbU5vZGU7XG4gIGxldCBmaXJzdENoaWxkID0gY3VycmVudC5nZXRGaXJzdENoaWxkKCk7XG4gIHdoaWxlICgkaXNMaXN0Tm9kZShmaXJzdENoaWxkKSkge1xuICAgIGNvbnN0IGxhc3RDaGlsZCA9IGZpcnN0Q2hpbGQuZ2V0TGFzdENoaWxkKCk7XG4gICAgaWYgKCRpc0xpc3RJdGVtTm9kZShsYXN0Q2hpbGQpKSB7XG4gICAgICBjdXJyZW50ID0gbGFzdENoaWxkO1xuICAgICAgZmlyc3RDaGlsZCA9IGN1cnJlbnQuZ2V0Rmlyc3RDaGlsZCgpO1xuICAgIH0gZWxzZSB7XG4gICAgICBicmVhaztcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGN1cnJlbnQ7XG59XG5cbi8qKlxuICogQGRlcHJlY2F0ZWQgdXNlIHtAbGluayAkaW5zZXJ0TGlzdH0gZnJvbSBhbiB1cGRhdGUgb3IgY29tbWFuZCBsaXN0ZW5lci5cbiAqXG4gKiBJbnNlcnRzIGEgbmV3IExpc3ROb2RlLiBJZiB0aGUgc2VsZWN0aW9uJ3MgYW5jaG9yIG5vZGUgaXMgYW4gZW1wdHkgTGlzdEl0ZW1Ob2RlIGFuZCBpcyBhIGNoaWxkIG9mXG4gKiB0aGUgcm9vdC9zaGFkb3cgcm9vdCwgaXQgd2lsbCByZXBsYWNlIHRoZSBMaXN0SXRlbU5vZGUgd2l0aCBhIExpc3ROb2RlIGFuZCB0aGUgb2xkIExpc3RJdGVtTm9kZS5cbiAqIE90aGVyd2lzZSBpdCB3aWxsIHJlcGxhY2UgaXRzIHBhcmVudCB3aXRoIGEgbmV3IExpc3ROb2RlIGFuZCByZS1pbnNlcnQgdGhlIExpc3RJdGVtTm9kZSBhbmQgYW55IHByZXZpb3VzIGNoaWxkcmVuLlxuICogSWYgdGhlIHNlbGVjdGlvbidzIGFuY2hvciBub2RlIGlzIG5vdCBhbiBlbXB0eSBMaXN0SXRlbU5vZGUsIGl0IHdpbGwgYWRkIGEgbmV3IExpc3ROb2RlIG9yIG1lcmdlIGFuIGV4aXN0aW5nIExpc3ROb2RlLFxuICogdW5sZXNzIHRoZSB0aGUgbm9kZSBpcyBhIGxlYWYgbm9kZSwgaW4gd2hpY2ggY2FzZSBpdCB3aWxsIGF0dGVtcHQgdG8gZmluZCBhIExpc3ROb2RlIHVwIHRoZSBicmFuY2ggYW5kIHJlcGxhY2UgaXQgd2l0aFxuICogYSBuZXcgTGlzdE5vZGUsIG9yIGNyZWF0ZSBhIG5ldyBMaXN0Tm9kZSBhdCB0aGUgbmVhcmVzdCByb290L3NoYWRvdyByb290LlxuICogQHBhcmFtIGVkaXRvciAtIFRoZSBsZXhpY2FsIGVkaXRvci5cbiAqIEBwYXJhbSBsaXN0VHlwZSAtIFRoZSB0eXBlIG9mIGxpc3QsIFwibnVtYmVyXCIgfCBcImJ1bGxldFwiIHwgXCJjaGVja1wiLlxuICovXG5mdW5jdGlvbiBpbnNlcnRMaXN0KGVkaXRvciwgbGlzdFR5cGUpIHtcbiAgZWRpdG9yLnVwZGF0ZSgoKSA9PiAkaW5zZXJ0TGlzdChsaXN0VHlwZSkpO1xufVxuXG4vKipcbiAqIEBkZXByZWNhdGVkIHVzZSB7QGxpbmsgJHJlbW92ZUxpc3R9IGZyb20gYW4gdXBkYXRlIG9yIGNvbW1hbmQgbGlzdGVuZXIuXG4gKlxuICogU2VhcmNoZXMgZm9yIHRoZSBuZWFyZXN0IGFuY2VzdHJhbCBMaXN0Tm9kZSBhbmQgcmVtb3ZlcyBpdC4gSWYgc2VsZWN0aW9uIGlzIGFuIGVtcHR5IExpc3RJdGVtTm9kZVxuICogaXQgd2lsbCByZW1vdmUgdGhlIHdob2xlIGxpc3QsIGluY2x1ZGluZyB0aGUgTGlzdEl0ZW1Ob2RlLiBGb3IgZWFjaCBMaXN0SXRlbU5vZGUgaW4gdGhlIExpc3ROb2RlLFxuICogcmVtb3ZlTGlzdCB3aWxsIGFsc28gZ2VuZXJhdGUgbmV3IFBhcmFncmFwaE5vZGVzIGluIHRoZSByZW1vdmVkIExpc3ROb2RlJ3MgcGxhY2UuIEFueSBjaGlsZCBub2RlXG4gKiBpbnNpZGUgYSBMaXN0SXRlbU5vZGUgd2lsbCBiZSBhcHBlbmRlZCB0byB0aGUgbmV3IFBhcmFncmFwaE5vZGVzLlxuICogQHBhcmFtIGVkaXRvciAtIFRoZSBsZXhpY2FsIGVkaXRvci5cbiAqL1xuZnVuY3Rpb24gcmVtb3ZlTGlzdChlZGl0b3IpIHtcbiAgZWRpdG9yLnVwZGF0ZSgoKSA9PiAkcmVtb3ZlTGlzdCgpKTtcbn1cbi8qKlxuICogQ29uZmlndXJlcyB7QGxpbmsgTGlzdE5vZGV9LCB7QGxpbmsgTGlzdEl0ZW1Ob2RlfSBhbmQgcmVnaXN0ZXJzXG4gKiB0aGUgc3RyaWN0IGluZGVudCB0cmFuc2Zvcm0gaWYgYGhhc1N0cmljdEluZGVudGAgaXMgdHJ1ZSAoZGVmYXVsdCBmYWxzZSkuXG4gKi9cbmNvbnN0IExpc3RFeHRlbnNpb24gPSBkZWZpbmVFeHRlbnNpb24oe1xuICBidWlsZChlZGl0b3IsIGNvbmZpZywgc3RhdGUpIHtcbiAgICByZXR1cm4gbmFtZWRTaWduYWxzKGNvbmZpZyk7XG4gIH0sXG4gIGNvbmZpZzogc2FmZUNhc3Qoe1xuICAgIGhhc1N0cmljdEluZGVudDogZmFsc2UsXG4gICAgc2hvdWxkUHJlc2VydmVOdW1iZXJpbmc6IGZhbHNlXG4gIH0pLFxuICBuYW1lOiAnQGxleGljYWwvbGlzdC9MaXN0JyxcbiAgbm9kZXM6ICgpID0+IFtMaXN0Tm9kZSwgTGlzdEl0ZW1Ob2RlXSxcbiAgcmVnaXN0ZXIoZWRpdG9yLCBjb25maWcsIHN0YXRlKSB7XG4gICAgY29uc3Qgc3RvcmVzID0gc3RhdGUuZ2V0T3V0cHV0KCk7XG4gICAgcmV0dXJuIG1lcmdlUmVnaXN0ZXIoZWZmZWN0KCgpID0+IHtcbiAgICAgIHJldHVybiByZWdpc3Rlckxpc3QoZWRpdG9yLCB7XG4gICAgICAgIHJlc3RvcmVOdW1iZXJpbmc6IHN0b3Jlcy5zaG91bGRQcmVzZXJ2ZU51bWJlcmluZy52YWx1ZVxuICAgICAgfSk7XG4gICAgfSksIGVmZmVjdCgoKSA9PiBzdG9yZXMuaGFzU3RyaWN0SW5kZW50LnZhbHVlID8gcmVnaXN0ZXJMaXN0U3RyaWN0SW5kZW50VHJhbnNmb3JtKGVkaXRvcikgOiB1bmRlZmluZWQpKTtcbiAgfVxufSk7XG4vKipcbiAqIFJlZ2lzdGVycyBjaGVja2xpc3QgZnVuY3Rpb25hbGl0eSBmb3Ige0BsaW5rIExpc3ROb2RlfSBhbmRcbiAqIHtAbGluayBMaXN0SXRlbU5vZGV9IHdpdGggYVxuICoge0BsaW5rIElOU0VSVF9DSEVDS19MSVNUX0NPTU1BTkR9IGxpc3RlbmVyIGFuZFxuICogdGhlIGV4cGVjdGVkIGtleWJvYXJkIGFuZCBtb3VzZSBpbnRlcmFjdGlvbnMgZm9yXG4gKiBjaGVja2JveGVzLlxuICovXG5jb25zdCBDaGVja0xpc3RFeHRlbnNpb24gPSBkZWZpbmVFeHRlbnNpb24oe1xuICBjb25maWc6IHNhZmVDYXN0KHtcbiAgICBkaXNhYmxlVGFrZUZvY3VzT25DbGljazogZmFsc2VcbiAgfSksXG4gIGRlcGVuZGVuY2llczogW0xpc3RFeHRlbnNpb25dLFxuICBuYW1lOiAnQGxleGljYWwvbGlzdC9DaGVja0xpc3QnLFxuICByZWdpc3RlcjogcmVnaXN0ZXJDaGVja0xpc3Rcbn0pO1xuXG5leHBvcnQgeyAkY3JlYXRlTGlzdEl0ZW1Ob2RlLCAkY3JlYXRlTGlzdE5vZGUsICRnZXRMaXN0RGVwdGgsICRoYW5kbGVMaXN0SW5zZXJ0UGFyYWdyYXBoLCAkaW5zZXJ0TGlzdCwgJGlzTGlzdEl0ZW1Ob2RlLCAkaXNMaXN0Tm9kZSwgJHJlbW92ZUxpc3QsIENoZWNrTGlzdEV4dGVuc2lvbiwgSU5TRVJUX0NIRUNLX0xJU1RfQ09NTUFORCwgSU5TRVJUX09SREVSRURfTElTVF9DT01NQU5ELCBJTlNFUlRfVU5PUkRFUkVEX0xJU1RfQ09NTUFORCwgTGlzdEV4dGVuc2lvbiwgTGlzdEl0ZW1Ob2RlLCBMaXN0Tm9kZSwgUkVNT1ZFX0xJU1RfQ09NTUFORCwgVVBEQVRFX0xJU1RfU1RBUlRfQ09NTUFORCwgaW5zZXJ0TGlzdCwgcmVnaXN0ZXJDaGVja0xpc3QsIHJlZ2lzdGVyTGlzdCwgcmVnaXN0ZXJMaXN0U3RyaWN0SW5kZW50VHJhbnNmb3JtLCByZW1vdmVMaXN0IH07XG4iXSwibmFtZXMiOltdLCJpZ25vcmVMaXN0IjpbMF0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///(rsc)/./node_modules/.pnpm/@lexical+list@0.41.0/node_modules/@lexical/list/LexicalList.dev.mjs\n");
|
|
|
|
/***/ })
|
|
|
|
};
|
|
; |