timhor / obsidian-editor-shortcuts

Obsidian plugin to add keyboard shortcuts commonly found in code editors such as Visual Studio Code (vscode) or Sublime Text
MIT License
356 stars 25 forks source link

[Feature Request] Expand selection Up / Down / Left / Right #81

Open Mikestriken opened 3 months ago

Mikestriken commented 3 months ago

VSCode allows users to adjust the following:



Please add these key bindings as well!

I use alt + j / k /l / i as my arrow keys alt + o / u as word part left / right

and then just by pressing shift while using any of the above I move the cursor and select what's in between.

Mikestriken commented 3 months ago

I used generative AI (and referenced some of abrahamneben's code in his fork) to implement my feature request. The following was added to your code: Note: I used the source code of your last stable release to implement my code. in actions.ts:

export const select1LinesUp = (
  editor: Editor, 
  selection: EditorSelection
) => {
  let newHead: EditorPosition = {
    line: selection.head.line - 1,
    ch: selection.head.ch
  };

  // Ensure the new head position is within the bounds of the line
  if (newHead.line >= 0) {
    const lineAboveLength = editor.getLine(newHead.line).length;
    if (newHead.ch > lineAboveLength) {
      newHead.ch = lineAboveLength;
    }
  } else {
    // Prevent moving the head above the first line
    newHead.line = 0;
    newHead.ch = 0;
  }

  return { anchor: selection.anchor, head: newHead };
};

export const select1LinesDown = (
  editor: Editor, 
  selection: EditorSelection
) => {
  let newHead: EditorPosition = {
    line: selection.head.line + 1,
    ch: selection.head.ch
  };

  // Ensure the new head position is within the bounds of the line
  if (newHead.line < editor.lineCount()) {
    const lineBelowLength = editor.getLine(newHead.line).length;
    if (newHead.ch > lineBelowLength) {
      newHead.ch = 0;
    }
  } else {
    // Prevent moving the head below the last line
    newHead.line = editor.lineCount() - 1;
    newHead.ch = editor.getLine(newHead.line).length;
  }

  return { anchor: selection.anchor, head: newHead };
};

export const select1CharLeft = (
  _editor: Editor, 
  selection: EditorSelection
) => {
    const new_hd: EditorPosition = {
      line:selection.head.line, 
      ch:selection.head.ch-1
    };

    return { anchor: selection.anchor, head: new_hd };
};

export const select1CharRight = (
  _editor: Editor, 
  selection: EditorSelection
) => {
    const new_hd: EditorPosition = {
      line:selection.head.line, 
      ch:selection.head.ch+1
    };

    return { anchor: selection.anchor, head: new_hd };
};

// Define a reusable variable for punctuation characters
const punctuationChars = /[\s.,!?;:-_]/;

export const select1WordLeft = (
  editor: Editor,
  selection: EditorSelection
) => {
  const { anchor, head } = selection;  // Destructure the anchor and head positions from the selection
  const line = editor.getLine(head.line);  // Get the text of the line where the head is currently located
  let newHead = { ...head };  // Create a new position object for the head to track the updated cursor position

  // Handle the case where the cursor is at the beginning of the line and needs to move to the previous line
  if (head.ch === 0 && head.line > 0) {
    newHead.line--;  // Move up one line
    newHead.ch = editor.getLine(newHead.line).length;  // Set the cursor to the end of the previous line
  } else {
    // Move left to the end of the next word or punctuation group
    let ch = head.ch;
    if (ch > 0 && !/[\s]/.test(line[ch-1]) && !punctuationChars.test(line[ch-1])) {
      // If the character is part of a word, move left until the end of the word is found
      while (ch > 0 && !/[\s]/.test(line[ch-1]) && !punctuationChars.test(line[ch-1])) ch--;
    } else if (ch > 0 && punctuationChars.test(line[ch-1])) {
      // If the character is a punctuation mark, move left until the end of the punctuation group is found
      while (ch > 0 && punctuationChars.test(line[ch-1])) ch--;
    } else {
      ch--;  // If none of the above, simply move one character to the left
    }
    newHead.ch = ch;  // Update the head position with the new character position
  }

  // Adjust selection based on direction
  if (editor.posToOffset(newHead) < editor.posToOffset(anchor)) {
    // If the new head position is before the anchor, expand the selection to the left
    return { anchor, head: newHead };
  } else if (editor.posToOffset(newHead) > editor.posToOffset(anchor) && head.ch !== anchor.ch) {
    // If the new head position is after the anchor and the selection is non-collapsed, shrink the selection from the right
    return { anchor, head: newHead };
  } else {
    // If neither condition is met, maintain the current selection
    return { anchor: newHead, head: anchor };
  }
};

export const select1WordRight = (
  editor: Editor,
  selection: EditorSelection
) => {
  const { anchor, head } = selection;
  const line = editor.getLine(head.line);
  let newHead = { ...head };

  // Handle moving across lines
  if (head.ch === line.length && head.line < editor.lineCount() - 1) {
    newHead.line++;
    newHead.ch = 0;
  } else {
    // Move right to the end of the next word or punctuation group
    let ch = head.ch;
    if (ch < line.length && !/[\s]/.test(line[ch]) && !punctuationChars.test(line[ch])) {
      while (ch < line.length && !/[\s]/.test(line[ch]) && !punctuationChars.test(line[ch])) ch++;
    } else if (ch < line.length && punctuationChars.test(line[ch])) {
      while (ch < line.length && punctuationChars.test(line[ch])) ch++;
    } else {
      ch++;
    }
    newHead.ch = ch;
  }

  // Determine if we should shrink or expand the selection
  if (editor.posToOffset(newHead) > editor.posToOffset(head)) {
    // Shrink the selection from the left
    return { anchor, head: newHead };
  } else {
    // Expand the selection to the right
    return { anchor: newHead, head: anchor };
  }
};

in main.ts

import {
  // ...
  select1LinesUp,
  select1LinesDown,
  select1CharLeft,
  select1CharRight,
  select1WordLeft,
  select1WordRight,
  // ...
} from './actions';
 // ...
export default class CodeEditorShortcuts extends Plugin {
  settings: PluginSettings;
  async onload() {
    await this.loadSettings();
     // ... 
    this.addCommand({
      id: 'select1LinesUp',
      name: 'Select 1 lines up',
      editorCallback: (editor) => withMultipleSelections(editor, select1LinesUp),
    });

    this.addCommand({
      id: 'select1LinesDown',
      name: 'Select 1 lines Down',
      editorCallback: (editor) => withMultipleSelections(editor, select1LinesDown),
    });

    this.addCommand({
      id: 'select1CharLeft',
      name: 'Select 1 character left',
      editorCallback: (editor) => withMultipleSelections(editor, select1CharLeft),
    });

    this.addCommand({
      id: 'select1CharRight',
      name: 'Select 1 character right',
      editorCallback: (editor) => withMultipleSelections(editor, select1CharRight),
    });

    this.addCommand({
      id: 'select1WordLeft',
      name: 'Select 1 word left',
      editorCallback: (editor) => withMultipleSelections(editor, select1WordLeft),
    });

    this.addCommand({
      id: 'select1WordRight',
      name: 'Select 1 word right',
      editorCallback: (editor) => withMultipleSelections(editor, select1WordRight),
    });
    // ...
}

Known Bugs:

Additional Feature I would like implemented, word part detection;

IE: camelCase = 2 words not 1.

Mikestriken commented 3 months ago
Here is the compiled main.js code: ```js var __create = Object.create; var __defProp = Object.defineProperty; var __defProps = Object.defineProperties; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropDescs = Object.getOwnPropertyDescriptors; var __getOwnPropNames = Object.getOwnPropertyNames; var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) { if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]); } return a; }; var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); var __markAsModule = (target) => __defProp(target, "__esModule", { value: true }); var __export = (target, all) => { __markAsModule(target); for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __reExport = (target, module2, desc) => { if (module2 && typeof module2 === "object" || typeof module2 === "function") { for (let key of __getOwnPropNames(module2)) if (!__hasOwnProp.call(target, key) && key !== "default") __defProp(target, key, { get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable }); } return target; }; var __toModule = (module2) => { return __reExport(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", module2 && module2.__esModule && "default" in module2 ? { get: () => module2.default, enumerable: true } : { value: module2, enumerable: true })), module2); }; var __async = (__this, __arguments, generator) => { return new Promise((resolve, reject) => { var fulfilled = (value) => { try { step(generator.next(value)); } catch (e) { reject(e); } }; var rejected = (value) => { try { step(generator.throw(value)); } catch (e) { reject(e); } }; var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected); step((generator = generator.apply(__this, __arguments)).next()); }); }; // src/main.ts __export(exports, { default: () => CodeEditorShortcuts }); var import_obsidian3 = __toModule(require("obsidian")); // src/constants.ts var CASE; (function(CASE2) { CASE2["UPPER"] = "upper"; CASE2["LOWER"] = "lower"; CASE2["TITLE"] = "title"; CASE2["NEXT"] = "next"; })(CASE || (CASE = {})); var LOWERCASE_ARTICLES = ["the", "a", "an"]; var SEARCH_DIRECTION; (function(SEARCH_DIRECTION2) { SEARCH_DIRECTION2["FORWARD"] = "forward"; SEARCH_DIRECTION2["BACKWARD"] = "backward"; })(SEARCH_DIRECTION || (SEARCH_DIRECTION = {})); var MATCHING_BRACKETS = { "[": "]", "(": ")", "{": "}" }; var MATCHING_QUOTES = { "'": "'", '"': '"', "`": "`" }; var MATCHING_QUOTES_BRACKETS = __spreadValues(__spreadValues({}, MATCHING_QUOTES), MATCHING_BRACKETS); var CODE_EDITOR; (function(CODE_EDITOR2) { CODE_EDITOR2["SUBLIME"] = "sublime"; CODE_EDITOR2["VSCODE"] = "vscode"; })(CODE_EDITOR || (CODE_EDITOR = {})); var MODIFIER_KEYS = [ "Control", "Shift", "Alt", "Meta", "CapsLock", "Fn" ]; var LIST_CHARACTER_REGEX = /^\s*(-|\+|\*|\d+\.|>) (\[.\] )?/; // src/state.ts var SettingsState = { autoInsertListPrefix: true }; // src/utils.ts var defaultMultipleSelectionOptions = { repeatSameLineActions: true }; var withMultipleSelectionsNew = (editor, callback, options = defaultMultipleSelectionOptions) => { const selections = editor.listSelections(); let selectionIndexesToProcess; const newSelections = []; const changes = []; if (!options.repeatSameLineActions) { const seenLines = []; selectionIndexesToProcess = selections.reduce((indexes, currSelection, currIndex) => { const currentLine = currSelection.head.line; if (!seenLines.includes(currentLine)) { seenLines.push(currentLine); indexes.push(currIndex); } return indexes; }, []); } for (let i = 0; i < selections.length; i++) { if (selectionIndexesToProcess && !selectionIndexesToProcess.includes(i)) { continue; } const { changes: newChanges, newSelection } = callback(editor, selections[i], __spreadProps(__spreadValues({}, options.args), { iteration: i })); changes.push(...newChanges); if (options.combineSameLineSelections) { const existingSameLineSelection = newSelections.find((selection) => selection.from.line === newSelection.from.line); if (existingSameLineSelection) { existingSameLineSelection.from.ch = 0; continue; } } newSelections.push(newSelection); } editor.transaction({ changes, selections: newSelections }); }; var withMultipleSelections = (editor, callback, options = defaultMultipleSelectionOptions) => { const { cm } = editor; const selections = editor.listSelections(); let selectionIndexesToProcess; let newSelections = []; if (!options.repeatSameLineActions) { const seenLines = []; selectionIndexesToProcess = selections.reduce((indexes, currSelection, currIndex) => { const currentLine = currSelection.head.line; if (!seenLines.includes(currentLine)) { seenLines.push(currentLine); indexes.push(currIndex); } return indexes; }, []); } const applyCallbackOnSelections = () => { for (let i = 0; i < selections.length; i++) { if (selectionIndexesToProcess && !selectionIndexesToProcess.includes(i)) { continue; } const selection = editor.listSelections()[i]; if (selection) { const newSelection = callback(editor, selection, options.args); newSelections.push(newSelection); } } if (options.customSelectionHandler) { newSelections = options.customSelectionHandler(newSelections); } editor.setSelections(newSelections); }; if (cm && cm.operation) { cm.operation(applyCallbackOnSelections); } else { console.debug("cm object not found, operations will not be buffered"); applyCallbackOnSelections(); } }; var iterateCodeMirrorDivs = (callback) => { let codeMirrors; codeMirrors = document.querySelectorAll(".cm-content"); if (codeMirrors.length === 0) { codeMirrors = document.querySelectorAll(".CodeMirror"); } codeMirrors.forEach(callback); }; var getLineStartPos = (line) => ({ line, ch: 0 }); var getLineEndPos = (line, editor) => ({ line, ch: editor.getLine(line).length }); var getSelectionBoundaries = (selection) => { let { anchor: from, head: to } = selection; if (from.line > to.line) { [from, to] = [to, from]; } if (from.line === to.line && from.ch > to.ch) { [from, to] = [to, from]; } return { from, to, hasTrailingNewline: to.line > from.line && to.ch === 0 }; }; var getLeadingWhitespace = (lineContent) => { const indentation = lineContent.match(/^\s+/); return indentation ? indentation[0] : ""; }; var isLetterCharacter = (char) => /\p{L}\p{M}*/u.test(char); var isDigit = (char) => /\d/.test(char); var isLetterOrDigit = (char) => isLetterCharacter(char) || isDigit(char); var wordRangeAtPos = (pos, lineContent) => { let start = pos.ch; let end = pos.ch; while (start > 0 && isLetterOrDigit(lineContent.charAt(start - 1))) { start--; } while (end < lineContent.length && isLetterOrDigit(lineContent.charAt(end))) { end++; } return { anchor: { line: pos.line, ch: start }, head: { line: pos.line, ch: end } }; }; var findPosOfNextCharacter = ({ editor, startPos, checkCharacter, searchDirection }) => { let { line, ch } = startPos; let lineContent = editor.getLine(line); let matchFound = false; let matchedChar; if (searchDirection === SEARCH_DIRECTION.BACKWARD) { while (line >= 0) { const char = lineContent.charAt(Math.max(ch - 1, 0)); matchFound = checkCharacter(char); if (matchFound) { matchedChar = char; break; } ch--; if (ch <= 0) { line--; if (line >= 0) { lineContent = editor.getLine(line); ch = lineContent.length; } } } } else { while (line < editor.lineCount()) { const char = lineContent.charAt(ch); matchFound = checkCharacter(char); if (matchFound) { matchedChar = char; break; } ch++; if (ch >= lineContent.length) { line++; lineContent = editor.getLine(line); ch = 0; } } } return matchFound ? { match: matchedChar, pos: { line, ch } } : null; }; var hasSameSelectionContent = (editor, selections) => new Set(selections.map((selection) => { const { from, to } = getSelectionBoundaries(selection); return editor.getRange(from, to); })).size === 1; var getSearchText = ({ editor, allSelections, autoExpand }) => { const singleSearchText = hasSameSelectionContent(editor, allSelections); const firstSelection = allSelections[0]; const { from, to } = getSelectionBoundaries(firstSelection); let searchText = editor.getRange(from, to); if (searchText.length === 0 && autoExpand) { const wordRange = wordRangeAtPos(from, editor.getLine(from.line)); searchText = editor.getRange(wordRange.anchor, wordRange.head); } return { searchText, singleSearchText }; }; var escapeRegex = (input) => input.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); var withWordBoundaries = (input) => `(?<=\\W|^)${input}(?=\\W|$)`; var findAllMatches = ({ searchText, searchWithinWords, documentContent }) => { const escapedSearchText = escapeRegex(searchText); const searchExpression = new RegExp(searchWithinWords ? escapedSearchText : withWordBoundaries(escapedSearchText), "g"); return Array.from(documentContent.matchAll(searchExpression)); }; var findNextMatchPosition = ({ editor, latestMatchPos, searchText, searchWithinWords, documentContent }) => { const latestMatchOffset = editor.posToOffset(latestMatchPos); const matches = findAllMatches({ searchText, searchWithinWords, documentContent }); let nextMatch = null; for (const match of matches) { if (match.index > latestMatchOffset) { nextMatch = { anchor: editor.offsetToPos(match.index), head: editor.offsetToPos(match.index + searchText.length) }; break; } } if (!nextMatch) { const selectionIndexes = editor.listSelections().map((selection) => { const { from } = getSelectionBoundaries(selection); return editor.posToOffset(from); }); for (const match of matches) { if (!selectionIndexes.includes(match.index)) { nextMatch = { anchor: editor.offsetToPos(match.index), head: editor.offsetToPos(match.index + searchText.length) }; break; } } } return nextMatch; }; var findAllMatchPositions = ({ editor, searchText, searchWithinWords, documentContent }) => { const matches = findAllMatches({ searchText, searchWithinWords, documentContent }); const matchPositions = []; for (const match of matches) { matchPositions.push({ anchor: editor.offsetToPos(match.index), head: editor.offsetToPos(match.index + searchText.length) }); } return matchPositions; }; var toTitleCase = (selectedText) => { return selectedText.split(/(\s+)/).map((word, index, allWords) => { if (index > 0 && index < allWords.length - 1 && LOWERCASE_ARTICLES.includes(word.toLowerCase())) { return word.toLowerCase(); } return word.charAt(0).toUpperCase() + word.substring(1).toLowerCase(); }).join(""); }; var getNextCase = (selectedText) => { const textUpper = selectedText.toUpperCase(); const textLower = selectedText.toLowerCase(); const textTitle = toTitleCase(selectedText); switch (selectedText) { case textUpper: { return textLower; } case textLower: { return textTitle; } case textTitle: { return textUpper; } default: { return textUpper; } } }; var isNumeric = (input) => input.length > 0 && !isNaN(+input); var getNextListPrefix = (text, direction) => { const listChars = text.match(LIST_CHARACTER_REGEX); if (listChars && listChars.length > 0) { let prefix = listChars[0].trimStart(); const isEmptyListItem = prefix === listChars.input.trimStart(); if (isEmptyListItem) { return null; } if (isNumeric(prefix) && direction === "after") { prefix = +prefix + 1 + ". "; } if (prefix.startsWith("- [") && !prefix.includes("[ ]")) { prefix = "- [ ] "; } return prefix; } return ""; }; var formatRemainingListPrefixes = (editor, fromLine, indentation) => { const changes = []; for (let i = fromLine; i < editor.lineCount(); i++) { const contentsOfCurrentLine = editor.getLine(i); const listPrefixRegex = new RegExp(`^${indentation}\\d+\\.`); const lineStartsWithNumberPrefix = listPrefixRegex.test(contentsOfCurrentLine); if (!lineStartsWithNumberPrefix) { break; } const replacementContent = contentsOfCurrentLine.replace(/\d+\./, (match) => +match + 1 + "."); changes.push({ from: { line: i, ch: 0 }, to: { line: i, ch: contentsOfCurrentLine.length }, text: replacementContent }); } if (changes.length > 0) { editor.transaction({ changes }); } }; var toggleVaultConfig = (app, setting) => { const value = app.vault.getConfig(setting); setVaultConfig(app, setting, !value); }; var setVaultConfig = (app, setting, value) => { app.vault.setConfig(setting, value); }; // src/actions.ts var insertLineAbove = (editor, selection, args) => { const { line } = selection.head; const startOfCurrentLine = getLineStartPos(line); const contentsOfCurrentLine = editor.getLine(line); const indentation = getLeadingWhitespace(contentsOfCurrentLine); let listPrefix = ""; if (SettingsState.autoInsertListPrefix && line > 0 && editor.getLine(line - 1).trim().length > 0) { listPrefix = getNextListPrefix(contentsOfCurrentLine, "before"); if (isNumeric(listPrefix)) { formatRemainingListPrefixes(editor, line, indentation); } } const changes = [ { from: startOfCurrentLine, text: indentation + listPrefix + "\n" } ]; const newSelection = { from: __spreadProps(__spreadValues({}, startOfCurrentLine), { line: startOfCurrentLine.line + args.iteration, ch: indentation.length + listPrefix.length }) }; return { changes, newSelection }; }; var insertLineBelow = (editor, selection, args) => { const { line } = selection.head; const startOfCurrentLine = getLineStartPos(line); const endOfCurrentLine = getLineEndPos(line, editor); const contentsOfCurrentLine = editor.getLine(line); const indentation = getLeadingWhitespace(contentsOfCurrentLine); let listPrefix = ""; if (SettingsState.autoInsertListPrefix) { listPrefix = getNextListPrefix(contentsOfCurrentLine, "after"); if (listPrefix === null) { const changes2 = [ { from: startOfCurrentLine, to: endOfCurrentLine, text: "" } ]; const newSelection2 = { from: { line, ch: 0 } }; return { changes: changes2, newSelection: newSelection2 }; } if (isNumeric(listPrefix)) { formatRemainingListPrefixes(editor, line + 1, indentation); } } const changes = [ { from: endOfCurrentLine, text: "\n" + indentation + listPrefix } ]; const newSelection = { from: { line: line + 1 + args.iteration, ch: indentation.length + listPrefix.length } }; return { changes, newSelection }; }; var numLinesDeleted = 0; var deleteLine = (editor, selection, args) => { const { from, to, hasTrailingNewline } = getSelectionBoundaries(selection); if (to.line === editor.lastLine()) { const previousLine = Math.max(0, from.line - 1); const endOfPreviousLine = getLineEndPos(previousLine, editor); const changes2 = [ { from: from.line === 0 ? getLineStartPos(0) : endOfPreviousLine, to: to.ch === 0 ? getLineStartPos(to.line) : getLineEndPos(to.line, editor), text: "" } ]; const newSelection2 = { from: { line: previousLine, ch: Math.min(from.ch, endOfPreviousLine.ch) } }; return { changes: changes2, newSelection: newSelection2 }; } if (args.iteration === 0) { numLinesDeleted = 0; } const toLine = hasTrailingNewline ? to.line - 1 : to.line; const endOfNextLine = getLineEndPos(toLine + 1, editor); const changes = [ { from: getLineStartPos(from.line), to: getLineStartPos(toLine + 1), text: "" } ]; const newSelection = { from: { line: from.line - numLinesDeleted, ch: Math.min(to.ch, endOfNextLine.ch) } }; numLinesDeleted += toLine - from.line + 1; return { changes, newSelection }; }; var deleteToStartOfLine = (editor, selection) => { const pos = selection.head; let startPos = getLineStartPos(pos.line); if (pos.line === 0 && pos.ch === 0) { return selection; } if (pos.line === startPos.line && pos.ch === startPos.ch) { startPos = getLineEndPos(pos.line - 1, editor); } editor.replaceRange("", startPos, pos); return { anchor: startPos }; }; var deleteToEndOfLine = (editor, selection) => { const pos = selection.head; let endPos = getLineEndPos(pos.line, editor); if (pos.line === endPos.line && pos.ch === endPos.ch) { endPos = getLineStartPos(pos.line + 1); } editor.replaceRange("", pos, endPos); return { anchor: pos }; }; var joinLines = (editor, selection) => { var _a, _b; const { from, to } = getSelectionBoundaries(selection); const { line } = from; let endOfCurrentLine = getLineEndPos(line, editor); const joinRangeLimit = Math.max(to.line - line, 1); const selectionLength = editor.posToOffset(to) - editor.posToOffset(from); let trimmedChars = ""; for (let i = 0; i < joinRangeLimit; i++) { if (line === editor.lineCount() - 1) { break; } endOfCurrentLine = getLineEndPos(line, editor); const endOfNextLine = getLineEndPos(line + 1, editor); const contentsOfCurrentLine = editor.getLine(line); const contentsOfNextLine = editor.getLine(line + 1); const charsToTrim = (_a = contentsOfNextLine.match(LIST_CHARACTER_REGEX)) != null ? _a : []; trimmedChars += (_b = charsToTrim[0]) != null ? _b : ""; const newContentsOfNextLine = contentsOfNextLine.replace(LIST_CHARACTER_REGEX, ""); if (newContentsOfNextLine.length > 0 && contentsOfCurrentLine.charAt(endOfCurrentLine.ch - 1) !== " ") { editor.replaceRange(" " + newContentsOfNextLine, endOfCurrentLine, endOfNextLine); } else { editor.replaceRange(newContentsOfNextLine, endOfCurrentLine, endOfNextLine); } } if (selectionLength === 0) { return { anchor: endOfCurrentLine }; } return { anchor: from, head: { line: from.line, ch: from.ch + selectionLength - trimmedChars.length } }; }; var copyLine = (editor, selection, direction) => { const { from, to, hasTrailingNewline } = getSelectionBoundaries(selection); const fromLineStart = getLineStartPos(from.line); const toLine = hasTrailingNewline ? to.line - 1 : to.line; const toLineEnd = getLineEndPos(toLine, editor); const contentsOfSelectedLines = editor.getRange(fromLineStart, toLineEnd); if (direction === "up") { editor.replaceRange("\n" + contentsOfSelectedLines, toLineEnd); return selection; } else { editor.replaceRange(contentsOfSelectedLines + "\n", fromLineStart); const linesSelected = to.line - from.line + 1; return { anchor: { line: toLine + 1, ch: from.ch }, head: { line: toLine + linesSelected, ch: to.ch } }; } }; var isManualSelection = true; var setIsManualSelection = (value) => { isManualSelection = value; }; var isProgrammaticSelectionChange = false; var setIsProgrammaticSelectionChange = (value) => { isProgrammaticSelectionChange = value; }; var selectWordOrNextOccurrence = (editor) => { setIsProgrammaticSelectionChange(true); const allSelections = editor.listSelections(); const { searchText, singleSearchText } = getSearchText({ editor, allSelections, autoExpand: false }); if (searchText.length > 0 && singleSearchText) { const { from: latestMatchPos } = getSelectionBoundaries(allSelections[allSelections.length - 1]); const nextMatch = findNextMatchPosition({ editor, latestMatchPos, searchText, searchWithinWords: isManualSelection, documentContent: editor.getValue() }); const newSelections = nextMatch ? allSelections.concat(nextMatch) : allSelections; editor.setSelections(newSelections); const lastSelection = newSelections[newSelections.length - 1]; editor.scrollIntoView(getSelectionBoundaries(lastSelection)); } else { const newSelections = []; for (const selection of allSelections) { const { from, to } = getSelectionBoundaries(selection); if (from.line !== to.line || from.ch !== to.ch) { newSelections.push(selection); } else { newSelections.push(wordRangeAtPos(from, editor.getLine(from.line))); setIsManualSelection(false); } } editor.setSelections(newSelections); } }; var selectAllOccurrences = (editor) => { const allSelections = editor.listSelections(); const { searchText, singleSearchText } = getSearchText({ editor, allSelections, autoExpand: true }); if (!singleSearchText) { return; } const matches = findAllMatchPositions({ editor, searchText, searchWithinWords: true, documentContent: editor.getValue() }); editor.setSelections(matches); }; var selectLine = (_editor, selection) => { const { from, to } = getSelectionBoundaries(selection); const startOfCurrentLine = getLineStartPos(from.line); const startOfNextLine = getLineStartPos(to.line + 1); return { anchor: startOfCurrentLine, head: startOfNextLine }; }; var addCursorsToSelectionEnds = (editor, emulate = CODE_EDITOR.VSCODE) => { if (editor.listSelections().length !== 1) { return; } const selection = editor.listSelections()[0]; const { from, to, hasTrailingNewline } = getSelectionBoundaries(selection); const newSelections = []; const toLine = hasTrailingNewline ? to.line - 1 : to.line; for (let line = from.line; line <= toLine; line++) { const head = line === to.line ? to : getLineEndPos(line, editor); let anchor; if (emulate === CODE_EDITOR.VSCODE) { anchor = head; } else { anchor = line === from.line ? from : getLineStartPos(line); } newSelections.push({ anchor, head }); } editor.setSelections(newSelections); }; var goToLineBoundary = (editor, selection, boundary) => { const { from, to } = getSelectionBoundaries(selection); if (boundary === "start") { return { anchor: getLineStartPos(from.line) }; } else { return { anchor: getLineEndPos(to.line, editor) }; } }; var navigateLine = (editor, selection, position) => { const pos = selection.head; let line; let ch; if (position === "prev") { line = Math.max(pos.line - 1, 0); const endOfLine = getLineEndPos(line, editor); ch = Math.min(pos.ch, endOfLine.ch); } if (position === "next") { line = Math.min(pos.line + 1, editor.lineCount() - 1); const endOfLine = getLineEndPos(line, editor); ch = Math.min(pos.ch, endOfLine.ch); } if (position === "first") { line = 0; ch = 0; } if (position === "last") { line = editor.lineCount() - 1; const endOfLine = getLineEndPos(line, editor); ch = endOfLine.ch; } return { anchor: { line, ch } }; }; var moveCursor = (editor, direction) => { switch (direction) { case "up": editor.exec("goUp"); break; case "down": editor.exec("goDown"); break; case "left": editor.exec("goLeft"); break; case "right": editor.exec("goRight"); break; } }; var select1LinesUp = (editor, selection) => { let newHead = { line: selection.head.line - 1, ch: selection.head.ch }; if (newHead.line >= 0) { const lineAboveLength = editor.getLine(newHead.line).length; if (newHead.ch > lineAboveLength) { newHead.ch = lineAboveLength; } } else { newHead.line = 0; newHead.ch = 0; } return { anchor: selection.anchor, head: newHead }; }; var select1LinesDown = (editor, selection) => { let newHead = { line: selection.head.line + 1, ch: selection.head.ch }; if (newHead.line < editor.lineCount()) { const lineBelowLength = editor.getLine(newHead.line).length; if (newHead.ch > lineBelowLength) { newHead.ch = 0; } } else { newHead.line = editor.lineCount() - 1; newHead.ch = editor.getLine(newHead.line).length; } return { anchor: selection.anchor, head: newHead }; }; var select1CharLeft = (_editor, selection) => { const new_hd = { line: selection.head.line, ch: selection.head.ch - 1 }; return { anchor: selection.anchor, head: new_hd }; }; var select1CharRight = (_editor, selection) => { const new_hd = { line: selection.head.line, ch: selection.head.ch + 1 }; return { anchor: selection.anchor, head: new_hd }; }; var punctuationChars = /[\s.,!?;:-_]/; var select1WordLeft = (editor, selection) => { const { anchor, head } = selection; const line = editor.getLine(head.line); let newHead = __spreadValues({}, head); if (head.ch === 0 && head.line > 0) { newHead.line--; newHead.ch = editor.getLine(newHead.line).length; } else { let ch = head.ch; if (ch > 0 && !/[\s]/.test(line[ch - 1]) && !punctuationChars.test(line[ch - 1])) { while (ch > 0 && !/[\s]/.test(line[ch - 1]) && !punctuationChars.test(line[ch - 1])) ch--; } else if (ch > 0 && punctuationChars.test(line[ch - 1])) { while (ch > 0 && punctuationChars.test(line[ch - 1])) ch--; } else { ch--; } newHead.ch = ch; } if (editor.posToOffset(newHead) < editor.posToOffset(anchor)) { return { anchor, head: newHead }; } else if (editor.posToOffset(newHead) > editor.posToOffset(anchor) && head.ch !== anchor.ch) { return { anchor, head: newHead }; } else { return { anchor: newHead, head: anchor }; } }; var select1WordRight = (editor, selection) => { const { anchor, head } = selection; const line = editor.getLine(head.line); let newHead = __spreadValues({}, head); if (head.ch === line.length && head.line < editor.lineCount() - 1) { newHead.line++; newHead.ch = 0; } else { let ch = head.ch; if (ch < line.length && !/[\s]/.test(line[ch]) && !punctuationChars.test(line[ch])) { while (ch < line.length && !/[\s]/.test(line[ch]) && !punctuationChars.test(line[ch])) ch++; } else if (ch < line.length && punctuationChars.test(line[ch])) { while (ch < line.length && punctuationChars.test(line[ch])) ch++; } else { ch++; } newHead.ch = ch; } if (editor.posToOffset(newHead) > editor.posToOffset(head)) { return { anchor, head: newHead }; } else { return { anchor: newHead, head: anchor }; } }; var moveWord = (editor, direction) => { switch (direction) { case "left": editor.exec("goWordLeft"); break; case "right": editor.exec("goWordRight"); break; } }; var transformCase = (editor, selection, caseType) => { let { from, to } = getSelectionBoundaries(selection); let selectedText = editor.getRange(from, to); if (selectedText.length === 0) { const pos = selection.head; const { anchor, head } = wordRangeAtPos(pos, editor.getLine(pos.line)); [from, to] = [anchor, head]; selectedText = editor.getRange(anchor, head); } let replacementText = selectedText; switch (caseType) { case CASE.UPPER: { replacementText = selectedText.toUpperCase(); break; } case CASE.LOWER: { replacementText = selectedText.toLowerCase(); break; } case CASE.TITLE: { replacementText = toTitleCase(selectedText); break; } case CASE.NEXT: { replacementText = getNextCase(selectedText); break; } } editor.replaceRange(replacementText, from, to); return selection; }; var expandSelection = ({ editor, selection, openingCharacterCheck, matchingCharacterMap }) => { let { anchor, head } = selection; if (anchor.line >= head.line && anchor.ch > anchor.ch) { [anchor, head] = [head, anchor]; } const newAnchor = findPosOfNextCharacter({ editor, startPos: anchor, checkCharacter: openingCharacterCheck, searchDirection: SEARCH_DIRECTION.BACKWARD }); if (!newAnchor) { return selection; } const newHead = findPosOfNextCharacter({ editor, startPos: head, checkCharacter: (char) => char === matchingCharacterMap[newAnchor.match], searchDirection: SEARCH_DIRECTION.FORWARD }); if (!newHead) { return selection; } return { anchor: newAnchor.pos, head: newHead.pos }; }; var expandSelectionToBrackets = (editor, selection) => expandSelection({ editor, selection, openingCharacterCheck: (char) => /[([{]/.test(char), matchingCharacterMap: MATCHING_BRACKETS }); var expandSelectionToQuotes = (editor, selection) => expandSelection({ editor, selection, openingCharacterCheck: (char) => /['"`]/.test(char), matchingCharacterMap: MATCHING_QUOTES }); var expandSelectionToQuotesOrBrackets = (editor) => { const selections = editor.listSelections(); const newSelection = expandSelection({ editor, selection: selections[0], openingCharacterCheck: (char) => /['"`([{]/.test(char), matchingCharacterMap: MATCHING_QUOTES_BRACKETS }); editor.setSelections([...selections, newSelection]); }; var insertCursor = (editor, lineOffset) => { const selections = editor.listSelections(); const newSelections = []; for (const selection of selections) { const { line, ch } = selection.head; if (line === 0 && lineOffset < 0 || line === editor.lastLine() && lineOffset > 0) { break; } const targetLineLength = editor.getLine(line + lineOffset).length; newSelections.push({ anchor: { line: selection.anchor.line + lineOffset, ch: Math.min(selection.anchor.ch, targetLineLength) }, head: { line: line + lineOffset, ch: Math.min(ch, targetLineLength) } }); } editor.setSelections([...editor.listSelections(), ...newSelections]); }; var insertCursorAbove = (editor) => insertCursor(editor, -1); var insertCursorBelow = (editor) => insertCursor(editor, 1); var goToHeading = (app, editor, boundary) => { const file = app.metadataCache.getFileCache(app.workspace.getActiveFile()); if (!file.headings || file.headings.length === 0) { return; } const { line } = editor.getCursor("from"); let prevHeadingLine = 0; let nextHeadingLine = editor.lastLine(); file.headings.forEach(({ position }) => { const { end: headingPos } = position; if (line > headingPos.line && headingPos.line > prevHeadingLine) { prevHeadingLine = headingPos.line; } if (line < headingPos.line && headingPos.line < nextHeadingLine) { nextHeadingLine = headingPos.line; } }); editor.setSelection(boundary === "prev" ? getLineEndPos(prevHeadingLine, editor) : getLineEndPos(nextHeadingLine, editor)); }; // src/settings.ts var import_obsidian = __toModule(require("obsidian")); var DEFAULT_SETTINGS = { autoInsertListPrefix: true }; var SettingTab = class extends import_obsidian.PluginSettingTab { constructor(app, plugin) { super(app, plugin); this.plugin = plugin; } display() { const { containerEl } = this; containerEl.empty(); containerEl.createEl("h2", { text: "Code Editor Shortcuts" }); const listPrefixSetting = new import_obsidian.Setting(containerEl).setName("Auto insert list prefix").setDesc("Automatically insert list prefix when inserting a line above or below").addToggle((toggle) => toggle.setValue(this.plugin.settings.autoInsertListPrefix).onChange((value) => __async(this, null, function* () { this.plugin.settings.autoInsertListPrefix = value; yield this.plugin.saveSettings(); }))); new import_obsidian.Setting(containerEl).setName("Reset defaults").addButton((btn) => { btn.setButtonText("Reset").onClick(() => __async(this, null, function* () { this.plugin.settings = __spreadValues({}, DEFAULT_SETTINGS); listPrefixSetting.components[0].setValue(DEFAULT_SETTINGS.autoInsertListPrefix); yield this.plugin.saveSettings(); })); }); } }; // src/modals.ts var import_obsidian2 = __toModule(require("obsidian")); var GoToLineModal = class extends import_obsidian2.SuggestModal { constructor(app, lineCount, onSubmit) { super(app); this.lineCount = lineCount; this.onSubmit = onSubmit; const PROMPT_TEXT = `Enter a line number between 1 and ${lineCount}`; this.limit = 1; this.setPlaceholder(PROMPT_TEXT); this.emptyStateText = PROMPT_TEXT; } getSuggestions(line) { const lineNumber = parseInt(line); if (line.length > 0 && lineNumber > 0 && lineNumber <= this.lineCount) { return [line]; } return []; } renderSuggestion(line, el) { el.createEl("div", { text: line }); } onChooseSuggestion(line) { this.onSubmit(parseInt(line) - 1); } }; // src/main.ts var CodeEditorShortcuts = class extends import_obsidian3.Plugin { onload() { return __async(this, null, function* () { yield this.loadSettings(); this.addCommand({ id: "insertLineAbove", name: "Insert line above", hotkeys: [ { modifiers: ["Mod", "Shift"], key: "Enter" } ], editorCallback: (editor) => withMultipleSelectionsNew(editor, insertLineAbove) }); this.addCommand({ id: "insertLineBelow", name: "Insert line below", hotkeys: [ { modifiers: ["Mod"], key: "Enter" } ], editorCallback: (editor) => withMultipleSelectionsNew(editor, insertLineBelow) }); this.addCommand({ id: "deleteLine", name: "Delete line", hotkeys: [ { modifiers: ["Mod", "Shift"], key: "K" } ], editorCallback: (editor) => withMultipleSelectionsNew(editor, deleteLine, __spreadProps(__spreadValues({}, defaultMultipleSelectionOptions), { combineSameLineSelections: true })) }); this.addCommand({ id: "deleteToStartOfLine", name: "Delete to start of line", editorCallback: (editor) => withMultipleSelections(editor, deleteToStartOfLine) }); this.addCommand({ id: "deleteToEndOfLine", name: "Delete to end of line", editorCallback: (editor) => withMultipleSelections(editor, deleteToEndOfLine) }); this.addCommand({ id: "joinLines", name: "Join lines", hotkeys: [ { modifiers: ["Mod"], key: "J" } ], editorCallback: (editor) => withMultipleSelections(editor, joinLines, __spreadProps(__spreadValues({}, defaultMultipleSelectionOptions), { repeatSameLineActions: false })) }); this.addCommand({ id: "duplicateLine", name: "Duplicate line", hotkeys: [ { modifiers: ["Mod", "Shift"], key: "D" } ], editorCallback: (editor) => withMultipleSelections(editor, copyLine, __spreadProps(__spreadValues({}, defaultMultipleSelectionOptions), { args: "down" })) }); this.addCommand({ id: "copyLineUp", name: "Copy line up", hotkeys: [ { modifiers: ["Alt", "Shift"], key: "ArrowUp" } ], editorCallback: (editor) => withMultipleSelections(editor, copyLine, __spreadProps(__spreadValues({}, defaultMultipleSelectionOptions), { args: "up" })) }); this.addCommand({ id: "copyLineDown", name: "Copy line down", hotkeys: [ { modifiers: ["Alt", "Shift"], key: "ArrowDown" } ], editorCallback: (editor) => withMultipleSelections(editor, copyLine, __spreadProps(__spreadValues({}, defaultMultipleSelectionOptions), { args: "down" })) }); this.addCommand({ id: "selectWordOrNextOccurrence", name: "Select word or next occurrence", hotkeys: [ { modifiers: ["Mod"], key: "D" } ], editorCallback: (editor) => selectWordOrNextOccurrence(editor) }); this.addCommand({ id: "selectAllOccurrences", name: "Select all occurrences", hotkeys: [ { modifiers: ["Mod", "Shift"], key: "L" } ], editorCallback: (editor) => selectAllOccurrences(editor) }); this.addCommand({ id: "selectLine", name: "Select line", hotkeys: [ { modifiers: ["Mod"], key: "L" } ], editorCallback: (editor) => withMultipleSelections(editor, selectLine) }); this.addCommand({ id: "addCursorsToSelectionEnds", name: "Add cursors to selection ends", hotkeys: [ { modifiers: ["Alt", "Shift"], key: "I" } ], editorCallback: (editor) => addCursorsToSelectionEnds(editor) }); this.addCommand({ id: "goToLineStart", name: "Go to start of line", editorCallback: (editor) => withMultipleSelections(editor, goToLineBoundary, __spreadProps(__spreadValues({}, defaultMultipleSelectionOptions), { args: "start" })) }); this.addCommand({ id: "goToLineEnd", name: "Go to end of line", editorCallback: (editor) => withMultipleSelections(editor, goToLineBoundary, __spreadProps(__spreadValues({}, defaultMultipleSelectionOptions), { args: "end" })) }); this.addCommand({ id: "goToNextLine", name: "Go to next line", editorCallback: (editor) => withMultipleSelections(editor, navigateLine, __spreadProps(__spreadValues({}, defaultMultipleSelectionOptions), { args: "next" })) }); this.addCommand({ id: "goToPrevLine", name: "Go to previous line", editorCallback: (editor) => withMultipleSelections(editor, navigateLine, __spreadProps(__spreadValues({}, defaultMultipleSelectionOptions), { args: "prev" })) }); this.addCommand({ id: "goToFirstLine", name: "Go to first line", editorCallback: (editor) => withMultipleSelections(editor, navigateLine, __spreadProps(__spreadValues({}, defaultMultipleSelectionOptions), { args: "first" })) }); this.addCommand({ id: "goToLastLine", name: "Go to last line", editorCallback: (editor) => withMultipleSelections(editor, navigateLine, __spreadProps(__spreadValues({}, defaultMultipleSelectionOptions), { args: "last" })) }); this.addCommand({ id: "goToLineNumber", name: "Go to line number", editorCallback: (editor) => { const lineCount = editor.lineCount(); const onSubmit = (line) => editor.setCursor({ line, ch: 0 }); new GoToLineModal(this.app, lineCount, onSubmit).open(); } }); this.addCommand({ id: "goToNextChar", name: "Move cursor forward", editorCallback: (editor) => moveCursor(editor, "right") }); this.addCommand({ id: "goToPrevChar", name: "Move cursor backward", editorCallback: (editor) => moveCursor(editor, "left") }); this.addCommand({ id: "moveCursorUp", name: "Move cursor up", editorCallback: (editor) => moveCursor(editor, "up") }); this.addCommand({ id: "moveCursorDown", name: "Move cursor down", editorCallback: (editor) => moveCursor(editor, "down") }); this.addCommand({ id: "select1LinesUp", name: "Select 1 lines up", editorCallback: (editor) => withMultipleSelections(editor, select1LinesUp) }); this.addCommand({ id: "select1LinesDown", name: "Select 1 lines Down", editorCallback: (editor) => withMultipleSelections(editor, select1LinesDown) }); this.addCommand({ id: "select1CharLeft", name: "Select 1 character left", editorCallback: (editor) => withMultipleSelections(editor, select1CharLeft) }); this.addCommand({ id: "select1CharRight", name: "Select 1 character right", editorCallback: (editor) => withMultipleSelections(editor, select1CharRight) }); this.addCommand({ id: "select1WordLeft", name: "Select 1 word left", editorCallback: (editor) => withMultipleSelections(editor, select1WordLeft) }); this.addCommand({ id: "select1WordRight", name: "Select 1 word right", editorCallback: (editor) => withMultipleSelections(editor, select1WordRight) }); this.addCommand({ id: "goToPreviousWord", name: "Go to previous word", editorCallback: (editor) => moveWord(editor, "left") }); this.addCommand({ id: "goToNextWord", name: "Go to next word", editorCallback: (editor) => moveWord(editor, "right") }); this.addCommand({ id: "transformToUppercase", name: "Transform selection to uppercase", editorCallback: (editor) => withMultipleSelections(editor, transformCase, __spreadProps(__spreadValues({}, defaultMultipleSelectionOptions), { args: CASE.UPPER })) }); this.addCommand({ id: "transformToLowercase", name: "Transform selection to lowercase", editorCallback: (editor) => withMultipleSelections(editor, transformCase, __spreadProps(__spreadValues({}, defaultMultipleSelectionOptions), { args: CASE.LOWER })) }); this.addCommand({ id: "transformToTitlecase", name: "Transform selection to title case", editorCallback: (editor) => withMultipleSelections(editor, transformCase, __spreadProps(__spreadValues({}, defaultMultipleSelectionOptions), { args: CASE.TITLE })) }); this.addCommand({ id: "toggleCase", name: "Toggle case of selection", editorCallback: (editor) => withMultipleSelections(editor, transformCase, __spreadProps(__spreadValues({}, defaultMultipleSelectionOptions), { args: CASE.NEXT })) }); this.addCommand({ id: "expandSelectionToBrackets", name: "Expand selection to brackets", editorCallback: (editor) => withMultipleSelections(editor, expandSelectionToBrackets) }); this.addCommand({ id: "expandSelectionToQuotes", name: "Expand selection to quotes", editorCallback: (editor) => withMultipleSelections(editor, expandSelectionToQuotes) }); this.addCommand({ id: "expandSelectionToQuotesOrBrackets", name: "Expand selection to quotes or brackets", editorCallback: (editor) => expandSelectionToQuotesOrBrackets(editor) }); this.addCommand({ id: "insertCursorAbove", name: "Insert cursor above", editorCallback: (editor) => insertCursorAbove(editor) }); this.addCommand({ id: "insertCursorBelow", name: "Insert cursor below", editorCallback: (editor) => insertCursorBelow(editor) }); this.addCommand({ id: "goToNextHeading", name: "Go to next heading", editorCallback: (editor) => goToHeading(this.app, editor, "next") }); this.addCommand({ id: "goToPrevHeading", name: "Go to previous heading", editorCallback: (editor) => goToHeading(this.app, editor, "prev") }); this.addCommand({ id: "toggle-line-numbers", name: "Toggle line numbers", callback: () => toggleVaultConfig(this.app, "showLineNumber") }); this.addCommand({ id: "indent-using-tabs", name: "Indent using tabs", callback: () => setVaultConfig(this.app, "useTab", true) }); this.addCommand({ id: "indent-using-spaces", name: "Indent using spaces", callback: () => setVaultConfig(this.app, "useTab", false) }); this.addCommand({ id: "undo", name: "Undo", editorCallback: (editor) => editor.undo() }); this.addCommand({ id: "redo", name: "Redo", editorCallback: (editor) => editor.redo() }); this.registerSelectionChangeListeners(); this.addSettingTab(new SettingTab(this.app, this)); }); } registerSelectionChangeListeners() { this.app.workspace.onLayoutReady(() => { const handleSelectionChange = (evt) => { if (evt instanceof KeyboardEvent && MODIFIER_KEYS.includes(evt.key)) { return; } if (!isProgrammaticSelectionChange) { setIsManualSelection(true); } setIsProgrammaticSelectionChange(false); }; iterateCodeMirrorDivs((cm) => { this.registerDomEvent(cm, "keydown", handleSelectionChange); this.registerDomEvent(cm, "click", handleSelectionChange); this.registerDomEvent(cm, "dblclick", handleSelectionChange); }); }); } loadSettings() { return __async(this, null, function* () { const savedSettings = yield this.loadData(); this.settings = __spreadValues(__spreadValues({}, DEFAULT_SETTINGS), savedSettings); SettingsState.autoInsertListPrefix = this.settings.autoInsertListPrefix; }); } saveSettings() { return __async(this, null, function* () { yield this.saveData(this.settings); SettingsState.autoInsertListPrefix = this.settings.autoInsertListPrefix; }); } }; //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsic3JjL21haW4udHMiLCAic3JjL2NvbnN0YW50cy50cyIsICJzcmMvc3RhdGUudHMiLCAic3JjL3V0aWxzLnRzIiwgInNyYy9hY3Rpb25zLnRzIiwgInNyYy9zZXR0aW5ncy50cyIsICJzcmMvbW9kYWxzLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyJpbXBvcnQgeyBQbHVnaW4gfSBmcm9tICdvYnNpZGlhbic7XG5pbXBvcnQge1xuICBhZGRDdXJzb3JzVG9TZWxlY3Rpb25FbmRzLFxuICBjb3B5TGluZSxcbiAgZGVsZXRlTGluZSxcbiAgZGVsZXRlVG9TdGFydE9mTGluZSxcbiAgZGVsZXRlVG9FbmRPZkxpbmUsXG4gIGV4cGFuZFNlbGVjdGlvblRvQnJhY2tldHMsXG4gIGV4cGFuZFNlbGVjdGlvblRvUXVvdGVzLFxuICBleHBhbmRTZWxlY3Rpb25Ub1F1b3Rlc09yQnJhY2tldHMsXG4gIGdvVG9IZWFkaW5nLFxuICBnb1RvTGluZUJvdW5kYXJ5LFxuICBpbnNlcnRMaW5lQWJvdmUsXG4gIGluc2VydExpbmVCZWxvdyxcbiAgam9pbkxpbmVzLFxuICBtb3ZlQ3Vyc29yLFxuICBzZWxlY3QxTGluZXNVcCxcbiAgc2VsZWN0MUxpbmVzRG93bixcbiAgc2VsZWN0MUNoYXJMZWZ0LFxuICBzZWxlY3QxQ2hhclJpZ2h0LFxuICBzZWxlY3QxV29yZExlZnQsXG4gIHNlbGVjdDFXb3JkUmlnaHQsXG4gIG5hdmlnYXRlTGluZSxcbiAgaXNQcm9ncmFtbWF0aWNTZWxlY3Rpb25DaGFuZ2UsXG4gIHNlbGVjdEFsbE9jY3VycmVuY2VzLFxuICBzZWxlY3RMaW5lLFxuICBzZWxlY3RXb3JkT3JOZXh0T2NjdXJyZW5jZSxcbiAgc2V0SXNNYW51YWxTZWxlY3Rpb24sXG4gIHNldElzUHJvZ3JhbW1hdGljU2VsZWN0aW9uQ2hhbmdlLFxuICB0cmFuc2Zvcm1DYXNlLFxuICBpbnNlcnRDdXJzb3JBYm92ZSxcbiAgaW5zZXJ0Q3Vyc29yQmVsb3csXG4gIG1vdmVXb3JkLFxufSBmcm9tICcuL2FjdGlvbnMnO1xuaW1wb3J0IHtcbiAgZGVmYXVsdE11bHRpcGxlU2VsZWN0aW9uT3B0aW9ucyxcbiAgaXRlcmF0ZUNvZGVNaXJyb3JEaXZzLFxuICBzZXRWYXVsdENvbmZpZyxcbiAgdG9nZ2xlVmF1bHRDb25maWcsXG4gIHdpdGhNdWx0aXBsZVNlbGVjdGlvbnMsXG4gIHdpdGhNdWx0aXBsZVNlbGVjdGlvbnNOZXcsXG59IGZyb20gJy4vdXRpbHMnO1xuaW1wb3J0IHsgQ0FTRSwgTU9ESUZJRVJfS0VZUyB9IGZyb20gJy4vY29uc3RhbnRzJztcbmltcG9ydCB7IFNldHRpbmdUYWIsIERFRkFVTFRfU0VUVElOR1MsIFBsdWdpblNldHRpbmdzIH0gZnJvbSAnLi9zZXR0aW5ncyc7XG5pbXBvcnQgeyBTZXR0aW5nc1N0YXRlIH0gZnJvbSAnLi9zdGF0ZSc7XG5pbXBvcnQgeyBHb1RvTGluZU1vZGFsIH0gZnJvbSAnLi9tb2RhbHMnO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBDb2RlRWRpdG9yU2hvcnRjdXRzIGV4dGVuZHMgUGx1Z2luIHtcbiAgc2V0dGluZ3M6IFBsdWdpblNldHRpbmdzO1xuXG4gIGFzeW5jIG9ubG9hZCgpIHtcbiAgICBhd2FpdCB0aGlzLmxvYWRTZXR0aW5ncygpO1xuXG4gICAgdGhpcy5hZGRDb21tYW5kKHtcbiAgICAgIGlkOiAnaW5zZXJ0TGluZUFib3ZlJyxcbiAgICAgIG5hbWU6ICdJbnNlcnQgbGluZSBhYm92ZScsXG4gICAgICBob3RrZXlzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBtb2RpZmllcnM6IFsnTW9kJywgJ1NoaWZ0J10sXG4gICAgICAgICAga2V5OiAnRW50ZXInLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICAgIGVkaXRvckNhbGxiYWNrOiAoZWRpdG9yKSA9PlxuICAgICAgICB3aXRoTXVsdGlwbGVTZWxlY3Rpb25zTmV3KGVkaXRvciwgaW5zZXJ0TGluZUFib3ZlKSxcbiAgICB9KTtcblxuICAgIHRoaXMuYWRkQ29tbWFuZCh7XG4gICAgICBpZDogJ2luc2VydExpbmVCZWxvdycsXG4gICAgICBuYW1lOiAnSW5zZXJ0IGxpbmUgYmVsb3cnLFxuICAgICAgaG90a2V5czogW1xuICAgICAgICB7XG4gICAgICAgICAgbW9kaWZpZXJzOiBbJ01vZCddLFxuICAgICAgICAgIGtleTogJ0VudGVyJyxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgICBlZGl0b3JDYWxsYmFjazogKGVkaXRvcikgPT5cbiAgICAgICAgd2l0aE11bHRpcGxlU2VsZWN0aW9uc05ldyhlZGl0b3IsIGluc2VydExpbmVCZWxvdyksXG4gICAgfSk7XG5cbiAgICB0aGlzLmFkZENvbW1hbmQoe1xuICAgICAgaWQ6ICdkZWxldGVMaW5lJyxcbiAgICAgIG5hbWU6ICdEZWxldGUgbGluZScsXG4gICAgICBob3RrZXlzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBtb2RpZmllcnM6IFsnTW9kJywgJ1NoaWZ0J10sXG4gICAgICAgICAga2V5OiAnSycsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgICAgZWRpdG9yQ2FsbGJhY2s6IChlZGl0b3IpID0+XG4gICAgICAgIHdpdGhNdWx0aXBsZVNlbGVjdGlvbnNOZXcoZWRpdG9yLCBkZWxldGVMaW5lLCB7XG4gICAgICAgICAgLi4uZGVmYXVsdE11bHRpcGxlU2VsZWN0aW9uT3B0aW9ucyxcbiAgICAgICAgICBjb21iaW5lU2FtZUxpbmVTZWxlY3Rpb25zOiB0cnVlLFxuICAgICAgICB9KSxcbiAgICB9KTtcblxuICAgIHRoaXMuYWRkQ29tbWFuZCh7XG4gICAgICBpZDogJ2RlbGV0ZVRvU3RhcnRPZkxpbmUnLFxuICAgICAgbmFtZTogJ0RlbGV0ZSB0byBzdGFydCBvZiBsaW5lJyxcbiAgICAgIGVkaXRvckNhbGxiYWNrOiAoZWRpdG9yKSA9PlxuICAgICAgICB3aXRoTXVsdGlwbGVTZWxlY3Rpb25zKGVkaXRvciwgZGVsZXRlVG9TdGFydE9mTGluZSksXG4gICAgfSk7XG5cbiAgICB0aGlzLmFkZENvbW1hbmQoe1xuICAgICAgaWQ6ICdkZWxldGVUb0VuZE9mTGluZScsXG4gICAgICBuYW1lOiAnRGVsZXRlIHRvIGVuZCBvZiBsaW5lJyxcbiAgICAgIGVkaXRvckNhbGxiYWNrOiAoZWRpdG9yKSA9PlxuICAgICAgICB3aXRoTXVsdGlwbGVTZWxlY3Rpb25zKGVkaXRvciwgZGVsZXRlVG9FbmRPZkxpbmUpLFxuICAgIH0pO1xuXG4gICAgdGhpcy5hZGRDb21tYW5kKHtcbiAgICAgIGlkOiAnam9pbkxpbmVzJyxcbiAgICAgIG5hbWU6ICdKb2luIGxpbmVzJyxcbiAgICAgIGhvdGtleXM6IFtcbiAgICAgICAge1xuICAgICAgICAgIG1vZGlmaWVyczogWydNb2QnXSxcbiAgICAgICAgICBrZXk6ICdKJyxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgICBlZGl0b3JDYWxsYmFjazogKGVkaXRvcikgPT5cbiAgICAgICAgd2l0aE11bHRpcGxlU2VsZWN0aW9ucyhlZGl0b3IsIGpvaW5MaW5lcywge1xuICAgICAgICAgIC4uLmRlZmF1bHRNdWx0aXBsZVNlbGVjdGlvbk9wdGlvbnMsXG4gICAgICAgICAgcmVwZWF0U2FtZUxpbmVBY3Rpb25zOiBmYWxzZSxcbiAgICAgICAgfSksXG4gICAgfSk7XG5cbiAgICB0aGlzLmFkZENvbW1hbmQoe1xuICAgICAgaWQ6ICdkdXBsaWNhdGVMaW5lJyxcbiAgICAgIG5hbWU6ICdEdXBsaWNhdGUgbGluZScsXG4gICAgICBob3RrZXlzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBtb2RpZmllcnM6IFsnTW9kJywgJ1NoaWZ0J10sXG4gICAgICAgICAga2V5OiAnRCcsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgICAgZWRpdG9yQ2FsbGJhY2s6IChlZGl0b3IpID0+XG4gICAgICAgIHdpdGhNdWx0aXBsZVNlbGVjdGlvbnMoZWRpdG9yLCBjb3B5TGluZSwge1xuICAgICAgICAgIC4uLmRlZmF1bHRNdWx0aXBsZVNlbGVjdGlvbk9wdGlvbnMsXG4gICAgICAgICAgYXJnczogJ2Rvd24nLFxuICAgICAgICB9KSxcbiAgICB9KTtcblxuICAgIHRoaXMuYWRkQ29tbWFuZCh7XG4gICAgICBpZDogJ2NvcHlMaW5lVXAnLFxuICAgICAgbmFtZTogJ0NvcHkgbGluZSB1cCcsXG4gICAgICBob3RrZXlzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBtb2RpZmllcnM6IFsnQWx0JywgJ1NoaWZ0J10sXG4gICAgICAgICAga2V5OiAnQXJyb3dVcCcsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgICAgZWRpdG9yQ2FsbGJhY2s6IChlZGl0b3IpID0+XG4gICAgICAgIHdpdGhNdWx0aXBsZVNlbGVjdGlvbnMoZWRpdG9yLCBjb3B5TGluZSwge1xuICAgICAgICAgIC4uLmRlZmF1bHRNdWx0aXBsZVNlbGVjdGlvbk9wdGlvbnMsXG4gICAgICAgICAgYXJnczogJ3VwJyxcbiAgICAgICAgfSksXG4gICAgfSk7XG5cbiAgICB0aGlzLmFkZENvbW1hbmQoe1xuICAgICAgaWQ6ICdjb3B5TGluZURvd24nLFxuICAgICAgbmFtZTogJ0NvcHkgbGluZSBkb3duJyxcbiAgICAgIGhvdGtleXM6IFtcbiAgICAgICAge1xuICAgICAgICAgIG1vZGlmaWVyczogWydBbHQnLCAnU2hpZnQnXSxcbiAgICAgICAgICBrZXk6ICdBcnJvd0Rvd24nLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICAgIGVkaXRvckNhbGxiYWNrOiAoZWRpdG9yKSA9PlxuICAgICAgICB3aXRoTXVsdGlwbGVTZWxlY3Rpb25zKGVkaXRvciwgY29weUxpbmUsIHtcbiAgICAgICAgICAuLi5kZWZhdWx0TXVsdGlwbGVTZWxlY3Rpb25PcHRpb25zLFxuICAgICAgICAgIGFyZ3M6ICdkb3duJyxcbiAgICAgICAgfSksXG4gICAgfSk7XG5cbiAgICB0aGlzLmFkZENvbW1hbmQoe1xuICAgICAgaWQ6ICdzZWxlY3RXb3JkT3JOZXh0T2NjdXJyZW5jZScsXG4gICAgICBuYW1lOiAnU2VsZWN0IHdvcmQgb3IgbmV4dCBvY2N1cnJlbmNlJyxcbiAgICAgIGhvdGtleXM6IFtcbiAgICAgICAge1xuICAgICAgICAgIG1vZGlmaWVyczogWydNb2QnXSxcbiAgICAgICAgICBrZXk6ICdEJyxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgICBlZGl0b3JDYWxsYmFjazogKGVkaXRvcikgPT4gc2VsZWN0V29yZE9yTmV4dE9jY3VycmVuY2UoZWRpdG9yKSxcbiAgICB9KTtcblxuICAgIHRoaXMuYWRkQ29tbWFuZCh7XG4gICAgICBpZDogJ3NlbGVjdEFsbE9jY3VycmVuY2VzJyxcbiAgICAgIG5hbWU6ICdTZWxlY3QgYWxsIG9jY3VycmVuY2VzJyxcbiAgICAgIGhvdGtleXM6IFtcbiAgICAgICAge1xuICAgICAgICAgIG1vZGlmaWVyczogWydNb2QnLCAnU2hpZnQnXSxcbiAgICAgICAgICBrZXk6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgICBlZGl0b3JDYWxsYmFjazogKGVkaXRvcikgPT4gc2VsZWN0QWxsT2NjdXJyZW5jZXMoZWRpdG9yKSxcbiAgICB9KTtcblxuICAgIHRoaXMuYWRkQ29tbWFuZCh7XG4gICAgICBpZDogJ3NlbGVjdExpbmUnLFxuICAgICAgbmFtZTogJ1NlbGVjdCBsaW5lJyxcbiAgICAgIGhvdGtleXM6IFtcbiAgICAgICAge1xuICAgICAgICAgIG1vZGlmaWVyczogWydNb2QnXSxcbiAgICAgICAgICBrZXk6ICdMJyxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgICBlZGl0b3JDYWxsYmFjazogKGVkaXRvcikgPT4gd2l0aE11bHRpcGxlU2VsZWN0aW9ucyhlZGl0b3IsIHNlbGVjdExpbmUpLFxuICAgIH0pO1xuXG4gICAgdGhpcy5hZGRDb21tYW5kKHtcbiAgICAgIGlkOiAnYWRkQ3Vyc29yc1RvU2VsZWN0aW9uRW5kcycsXG4gICAgICBuYW1lOiAnQWRkIGN1cnNvcnMgdG8gc2VsZWN0aW9uIGVuZHMnLFxuICAgICAgaG90a2V5czogW1xuICAgICAgICB7XG4gICAgICAgICAgbW9kaWZpZXJzOiBbJ0FsdCcsICdTaGlmdCddLFxuICAgICAgICAgIGtleTogJ0knLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICAgIGVkaXRvckNhbGxiYWNrOiAoZWRpdG9yKSA9PiBhZGRDdXJzb3JzVG9TZWxlY3Rpb25FbmRzKGVkaXRvciksXG4gICAgfSk7XG5cbiAgICB0aGlzLmFkZENvbW1hbmQoe1xuICAgICAgaWQ6ICdnb1RvTGluZVN0YXJ0JyxcbiAgICAgIG5hbWU6ICdHbyB0byBzdGFydCBvZiBsaW5lJyxcbiAgICAgIGVkaXRvckNhbGxiYWNrOiAoZWRpdG9yKSA9PlxuICAgICAgICB3aXRoTXVsdGlwbGVTZWxlY3Rpb25zKGVkaXRvciwgZ29Ub0xpbmVCb3VuZGFyeSwge1xuICAgICAgICAgIC4uLmRlZmF1bHRNdWx0aXBsZVNlbGVjdGlvbk9wdGlvbnMsXG4gICAgICAgICAgYXJnczogJ3N0YXJ0JyxcbiAgICAgICAgfSksXG4gICAgfSk7XG5cbiAgICB0aGlzLmFkZENvbW1hbmQoe1xuICAgICAgaWQ6ICdnb1RvTGluZUVuZCcsXG4gICAgICBuYW1lOiAnR28gdG8gZW5kIG9mIGxpbmUnLFxuICAgICAgZWRpdG9yQ2FsbGJhY2s6IChlZGl0b3IpID0+XG4gICAgICAgIHdpdGhNdWx0aXBsZVNlbGVjdGlvbnMoZWRpdG9yLCBnb1RvTGluZUJvdW5kYXJ5LCB7XG4gICAgICAgICAgLi4uZGVmYXVsdE11bHRpcGxlU2VsZWN0aW9uT3B0aW9ucyxcbiAgICAgICAgICBhcmdzOiAnZW5kJyxcbiAgICAgICAgfSksXG4gICAgfSk7XG5cbiAgICB0aGlzLmFkZENvbW1hbmQoe1xuICAgICAgaWQ6ICdnb1RvTmV4dExpbmUnLFxuICAgICAgbmFtZTogJ0dvIHRvIG5leHQgbGluZScsXG4gICAgICBlZGl0b3JDYWxsYmFjazogKGVkaXRvcikgPT5cbiAgICAgICAgd2l0aE11bHRpcGxlU2VsZWN0aW9ucyhlZGl0b3IsIG5hdmlnYXRlTGluZSwge1xuICAgICAgICAgIC4uLmRlZmF1bHRNdWx0aXBsZVNlbGVjdGlvbk9wdGlvbnMsXG4gICAgICAgICAgYXJnczogJ25leHQnLFxuICAgICAgICB9KSxcbiAgICB9KTtcblxuICAgIHRoaXMuYWRkQ29tbWFuZCh7XG4gICAgICBpZDogJ2dvVG9QcmV2TGluZScsXG4gICAgICBuYW1lOiAnR28gdG8gcHJldmlvdXMgbGluZScsXG4gICAgICBlZGl0b3JDYWxsYmFjazogKGVkaXRvcikgPT5cbiAgICAgICAgd2l0aE11bHRpcGxlU2VsZWN0aW9ucyhlZGl0b3IsIG5hdmlnYXRlTGluZSwge1xuICAgICAgICAgIC4uLmRlZmF1bHRNdWx0aXBsZVNlbGVjdGlvbk9wdGlvbnMsXG4gICAgICAgICAgYXJnczogJ3ByZXYnLFxuICAgICAgICB9KSxcbiAgICB9KTtcblxuICAgIHRoaXMuYWRkQ29tbWFuZCh7XG4gICAgICBpZDogJ2dvVG9GaXJzdExpbmUnLFxuICAgICAgbmFtZTogJ0dvIHRvIGZpcnN0IGxpbmUnLFxuICAgICAgZWRpdG9yQ2FsbGJhY2s6IChlZGl0b3IpID0+XG4gICAgICAgIHdpdGhNdWx0aXBsZVNlbGVjdGlvbnMoZWRpdG9yLCBuYXZpZ2F0ZUxpbmUsIHtcbiAgICAgICAgICAuLi5kZWZhdWx0TXVsdGlwbGVTZWxlY3Rpb25PcHRpb25zLFxuICAgICAgICAgIGFyZ3M6ICdmaXJzdCcsXG4gICAgICAgIH0pLFxuICAgIH0pO1xuXG4gICAgdGhpcy5hZGRDb21tYW5kKHtcbiAgICAgIGlkOiAnZ29Ub0xhc3RMaW5lJyxcbiAgICAgIG5hbWU6ICdHbyB0byBsYXN0IGxpbmUnLFxuICAgICAgZWRpdG9yQ2FsbGJhY2s6IChlZGl0b3IpID0+XG4gICAgICAgIHdpdGhNdWx0aXBsZVNlbGVjdGlvbnMoZWRpdG9yLCBuYXZpZ2F0ZUxpbmUsIHtcbiAgICAgICAgICAuLi5kZWZhdWx0TXVsdGlwbGVTZWxlY3Rpb25PcHRpb25zLFxuICAgICAgICAgIGFyZ3M6ICdsYXN0JyxcbiAgICAgICAgfSksXG4gICAgfSk7XG5cbiAgICB0aGlzLmFkZENvbW1hbmQoe1xuICAgICAgaWQ6ICdnb1RvTGluZU51bWJlcicsXG4gICAgICBuYW1lOiAnR28gdG8gbGluZSBudW1iZXInLFxuICAgICAgZWRpdG9yQ2FsbGJhY2s6IChlZGl0b3IpID0+IHtcbiAgICAgICAgY29uc3QgbGluZUNvdW50ID0gZWRpdG9yLmxpbmVDb3VudCgpO1xuICAgICAgICBjb25zdCBvblN1Ym1pdCA9IChsaW5lOiBudW1iZXIpID0+IGVkaXRvci5zZXRDdXJzb3IoeyBsaW5lLCBjaDogMCB9KTtcbiAgICAgICAgbmV3IEdvVG9MaW5lTW9kYWwodGhpcy5hcHAsIGxpbmVDb3VudCwgb25TdWJtaXQpLm9wZW4oKTtcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICB0aGlzLmFkZENvbW1hbmQoe1xuICAgICAgaWQ6ICdnb1RvTmV4dENoYXInLFxuICAgICAgbmFtZTogJ01vdmUgY3Vyc29yIGZvcndhcmQnLFxuICAgICAgZWRpdG9yQ2FsbGJhY2s6IChlZGl0b3IpID0+IG1vdmVDdXJzb3IoZWRpdG9yLCAncmlnaHQnKSxcbiAgICB9KTtcblxuICAgIHRoaXMuYWRkQ29tbWFuZCh7XG4gICAgICBpZDogJ2dvVG9QcmV2Q2hhcicsXG4gICAgICBuYW1lOiAnTW92ZSBjdXJzb3IgYmFja3dhcmQnLFxuICAgICAgZWRpdG9yQ2FsbGJhY2s6IChlZGl0b3IpID0+IG1vdmVDdXJzb3IoZWRpdG9yLCAnbGVmdCcpLFxuICAgIH0pO1xuXG4gICAgdGhpcy5hZGRDb21tYW5kKHtcbiAgICAgIGlkOiAnbW92ZUN1cnNvclVwJyxcbiAgICAgIG5hbWU6ICdNb3ZlIGN1cnNvciB1cCcsXG4gICAgICBlZGl0b3JDYWxsYmFjazogKGVkaXRvcikgPT4gbW92ZUN1cnNvcihlZGl0b3IsICd1cCcpLFxuICAgIH0pO1xuXG4gICAgdGhpcy5hZGRDb21tYW5kKHtcbiAgICAgIGlkOiAnbW92ZUN1cnNvckRvd24nLFxuICAgICAgbmFtZTogJ01vdmUgY3Vyc29yIGRvd24nLFxuICAgICAgZWRpdG9yQ2FsbGJhY2s6IChlZGl0b3IpID0+IG1vdmVDdXJzb3IoZWRpdG9yLCAnZG93bicpLFxuICAgIH0pO1xuXG4gICAgLy8gVGVzdCBvdGhlciBjb2RlXG4gICAgdGhpcy5hZGRDb21tYW5kKHtcbiAgICAgIGlkOiAnc2VsZWN0MUxpbmVzVXAnLFxuICAgICAgbmFtZTogJ1NlbGVjdCAxIGxpbmVzIHVwJyxcbiAgICAgIGVkaXRvckNhbGxiYWNrOiAoZWRpdG9yKSA9PiB3aXRoTXVsdGlwbGVTZWxlY3Rpb25zKGVkaXRvciwgc2VsZWN0MUxpbmVzVXApLFxuICAgIH0pO1xuICAgIFxuICAgIHRoaXMuYWRkQ29tbWFuZCh7XG4gICAgICBpZDogJ3NlbGVjdDFMaW5lc0Rvd24nLFxuICAgICAgbmFtZTogJ1NlbGVjdCAxIGxpbmVzIERvd24nLFxuICAgICAgZWRpdG9yQ2FsbGJhY2s6IChlZGl0b3IpID0+IHdpdGhNdWx0aXBsZVNlbGVjdGlvbnMoZWRpdG9yLCBzZWxlY3QxTGluZXNEb3duKSxcbiAgICB9KTtcblxuICAgIHRoaXMuYWRkQ29tbWFuZCh7XG4gICAgICBpZDogJ3NlbGVjdDFDaGFyTGVmdCcsXG4gICAgICBuYW1lOiAnU2VsZWN0IDEgY2hhcmFjdGVyIGxlZnQnLFxuICAgICAgZWRpdG9yQ2FsbGJhY2s6IChlZGl0b3IpID0+IHdpdGhNdWx0aXBsZVNlbGVjdGlvbnMoZWRpdG9yLCBzZWxlY3QxQ2hhckxlZnQpLFxuICAgIH0pO1xuXG4gICAgdGhpcy5hZGRDb21tYW5kKHtcbiAgICAgIGlkOiAnc2VsZWN0MUNoYXJSaWdodCcsXG4gICAgICBuYW1lOiAnU2VsZWN0IDEgY2hhcmFjdGVyIHJpZ2h0JyxcbiAgICAgIGVkaXRvckNhbGxiYWNrOiAoZWRpdG9yKSA9PiB3aXRoTXVsdGlwbGVTZWxlY3Rpb25zKGVkaXRvciwgc2VsZWN0MUNoYXJSaWdodCksXG4gICAgfSk7XG5cbiAgICB0aGlzLmFkZENvbW1hbmQoe1xuICAgICAgaWQ6ICdzZWxlY3QxV29yZExlZnQnLFxuICAgICAgbmFtZTogJ1NlbGVjdCAxIHdvcmQgbGVmdCcsXG4gICAgICBlZGl0b3JDYWxsYmFjazogKGVkaXRvcikgPT4gd2l0aE11bHRpcGxlU2VsZWN0aW9ucyhlZGl0b3IsIHNlbGVjdDFXb3JkTGVmdCksXG4gICAgfSk7XG5cbiAgICB0aGlzLmFkZENvbW1hbmQoe1xuICAgICAgaWQ6ICdzZWxlY3QxV29yZFJpZ2h0JyxcbiAgICAgIG5hbWU6ICdTZWxlY3QgMSB3b3JkIHJpZ2h0JyxcbiAgICAgIGVkaXRvckNhbGxiYWNrOiAoZWRpdG9yKSA9PiB3aXRoTXVsdGlwbGVTZWxlY3Rpb25zKGVkaXRvciwgc2VsZWN0MVdvcmRSaWdodCksXG4gICAgfSk7XG5cbiAgICB0aGlzLmFkZENvbW1hbmQoe1xuICAgICAgaWQ6ICdnb1RvUHJldmlvdXNXb3JkJyxcbiAgICAgIG5hbWU6ICdHbyB0byBwcmV2aW91cyB3b3JkJyxcbiAgICAgIGVkaXRvckNhbGxiYWNrOiAoZWRpdG9yKSA9PiBtb3ZlV29yZChlZGl0b3IsICdsZWZ0JyksXG4gICAgfSk7XG5cbiAgICB0aGlzLmFkZENvbW1hbmQoe1xuICAgICAgaWQ6ICdnb1RvTmV4dFdvcmQnLFxuICAgICAgbmFtZTogJ0dvIHRvIG5leHQgd29yZCcsXG4gICAgICBlZGl0b3JDYWxsYmFjazogKGVkaXRvcikgPT4gbW92ZVdvcmQoZWRpdG9yLCAncmlnaHQnKSxcbiAgICB9KTtcblxuICAgIHRoaXMuYWRkQ29tbWFuZCh7XG4gICAgICBpZDogJ3RyYW5zZm9ybVRvVXBwZXJjYXNlJyxcbiAgICAgIG5hbWU6ICdUcmFuc2Zvcm0gc2VsZWN0aW9uIHRvIHVwcGVyY2FzZScsXG4gICAgICBlZGl0b3JDYWxsYmFjazogKGVkaXRvcikgPT5cbiAgICAgICAgd2l0aE11bHRpcGxlU2VsZWN0aW9ucyhlZGl0b3IsIHRyYW5zZm9ybUNhc2UsIHtcbiAgICAgICAgICAuLi5kZWZhdWx0TXVsdGlwbGVTZWxlY3Rpb25PcHRpb25zLFxuICAgICAgICAgIGFyZ3M6IENBU0UuVVBQRVIsXG4gICAgICAgIH0pLFxuICAgIH0pO1xuXG4gICAgdGhpcy5hZGRDb21tYW5kKHtcbiAgICAgIGlkOiAndHJhbnNmb3JtVG9Mb3dlcmNhc2UnLFxuICAgICAgbmFtZTogJ1RyYW5zZm9ybSBzZWxlY3Rpb24gdG8gbG93ZXJjYXNlJyxcbiAgICAgIGVkaXRvckNhbGxiYWNrOiAoZWRpdG9yKSA9PlxuICAgICAgICB3aXRoTXVsdGlwbGVTZWxlY3Rpb25zKGVkaXRvciwgdHJhbnNmb3JtQ2FzZSwge1xuICAgICAgICAgIC4uLmRlZmF1bHRNdWx0aXBsZVNlbGVjdGlvbk9wdGlvbnMsXG4gICAgICAgICAgYXJnczogQ0FTRS5MT1dFUixcbiAgICAgICAgfSksXG4gICAgfSk7XG5cbiAgICB0aGlzLmFkZENvbW1hbmQoe1xuICAgICAgaWQ6ICd0cmFuc2Zvcm1Ub1RpdGxlY2FzZScsXG4gICAgICBuYW1lOiAnVHJhbnNmb3JtIHNlbGVjdGlvbiB0byB0aXRsZSBjYXNlJyxcbiAgICAgIGVkaXRvckNhbGxiYWNrOiAoZWRpdG9yKSA9PlxuICAgICAgICB3aXRoTXVsdGlwbGVTZWxlY3Rpb25zKGVkaXRvciwgdHJhbnNmb3JtQ2FzZSwge1xuICAgICAgICAgIC4uLmRlZmF1bHRNdWx0aXBsZVNlbGVjdGlvbk9wdGlvbnMsXG4gICAgICAgICAgYXJnczogQ0FTRS5USVRMRSxcbiAgICAgICAgfSksXG4gICAgfSk7XG5cbiAgICB0aGlzLmFkZENvbW1hbmQoe1xuICAgICAgaWQ6ICd0b2dnbGVDYXNlJyxcbiAgICAgIG5hbWU6ICdUb2dnbGUgY2FzZSBvZiBzZWxlY3Rpb24nLFxuICAgICAgZWRpdG9yQ2FsbGJhY2s6IChlZGl0b3IpID0+XG4gICAgICAgIHdpdGhNdWx0aXBsZVNlbGVjdGlvbnMoZWRpdG9yLCB0cmFuc2Zvcm1DYXNlLCB7XG4gICAgICAgICAgLi4uZGVmYXVsdE11bHRpcGxlU2VsZWN0aW9uT3B0aW9ucyxcbiAgICAgICAgICBhcmdzOiBDQVNFLk5FWFQsXG4gICAgICAgIH0pLFxuICAgIH0pO1xuXG4gICAgdGhpcy5hZGRDb21tYW5kKHtcbiAgICAgIGlkOiAnZXhwYW5kU2VsZWN0aW9uVG9CcmFja2V0cycsXG4gICAgICBuYW1lOiAnRXhwYW5kIHNlbGVjdGlvbiB0byBicmFja2V0cycsXG4gICAgICBlZGl0b3JDYWxsYmFjazogKGVkaXRvcikgPT5cbiAgICAgICAgd2l0aE11bHRpcGxlU2VsZWN0aW9ucyhlZGl0b3IsIGV4cGFuZFNlbGVjdGlvblRvQnJhY2tldHMpLFxuICAgIH0pO1xuXG4gICAgdGhpcy5hZGRDb21tYW5kKHtcbiAgICAgIGlkOiAnZXhwYW5kU2VsZWN0aW9uVG9RdW90ZXMnLFxuICAgICAgbmFtZTogJ0V4cGFuZCBzZWxlY3Rpb24gdG8gcXVvdGVzJyxcbiAgICAgIGVkaXRvckNhbGxiYWNrOiAoZWRpdG9yKSA9PlxuICAgICAgICB3aXRoTXVsdGlwbGVTZWxlY3Rpb25zKGVkaXRvciwgZXhwYW5kU2VsZWN0aW9uVG9RdW90ZXMpLFxuICAgIH0pO1xuXG4gICAgdGhpcy5hZGRDb21tYW5kKHtcbiAgICAgIGlkOiAnZXhwYW5kU2VsZWN0aW9uVG9RdW90ZXNPckJyYWNrZXRzJyxcbiAgICAgIG5hbWU6ICdFeHBhbmQgc2VsZWN0aW9uIHRvIHF1b3RlcyBvciBicmFja2V0cycsXG4gICAgICBlZGl0b3JDYWxsYmFjazogKGVkaXRvcikgPT4gZXhwYW5kU2VsZWN0aW9uVG9RdW90ZXNPckJyYWNrZXRzKGVkaXRvciksXG4gICAgfSk7XG5cbiAgICB0aGlzLmFkZENvbW1hbmQoe1xuICAgICAgaWQ6ICdpbnNlcnRDdXJzb3JBYm92ZScsXG4gICAgICBuYW1lOiAnSW5zZXJ0IGN1cnNvciBhYm92ZScsXG4gICAgICBlZGl0b3JDYWxsYmFjazogKGVkaXRvcikgPT4gaW5zZXJ0Q3Vyc29yQWJvdmUoZWRpdG9yKSxcbiAgICB9KTtcblxuICAgIHRoaXMuYWRkQ29tbWFuZCh7XG4gICAgICBpZDogJ2luc2VydEN1cnNvckJlbG93JyxcbiAgICAgIG5hbWU6ICdJbnNlcnQgY3Vyc29yIGJlbG93JyxcbiAgICAgIGVkaXRvckNhbGxiYWNrOiAoZWRpdG9yKSA9PiBpbnNlcnRDdXJzb3JCZWxvdyhlZGl0b3IpLFxuICAgIH0pO1xuXG4gICAgdGhpcy5hZGRDb21tYW5kKHtcbiAgICAgIGlkOiAnZ29Ub05leHRIZWFkaW5nJyxcbiAgICAgIG5hbWU6ICdHbyB0byBuZXh0IGhlYWRpbmcnLFxuICAgICAgZWRpdG9yQ2FsbGJhY2s6IChlZGl0b3IpID0+IGdvVG9IZWFkaW5nKHRoaXMuYXBwLCBlZGl0b3IsICduZXh0JyksXG4gICAgfSk7XG5cbiAgICB0aGlzLmFkZENvbW1hbmQoe1xuICAgICAgaWQ6ICdnb1RvUHJldkhlYWRpbmcnLFxuICAgICAgbmFtZTogJ0dvIHRvIHByZXZpb3VzIGhlYWRpbmcnLFxuICAgICAgZWRpdG9yQ2FsbGJhY2s6IChlZGl0b3IpID0+IGdvVG9IZWFkaW5nKHRoaXMuYXBwLCBlZGl0b3IsICdwcmV2JyksXG4gICAgfSk7XG5cbiAgICB0aGlzLmFkZENvbW1hbmQoe1xuICAgICAgaWQ6ICd0b2dnbGUtbGluZS1udW1iZXJzJyxcbiAgICAgIG5hbWU6ICdUb2dnbGUgbGluZSBudW1iZXJzJyxcbiAgICAgIGNhbGxiYWNrOiAoKSA9PiB0b2dnbGVWYXVsdENvbmZpZyh0aGlzLmFwcCwgJ3Nob3dMaW5lTnVtYmVyJyksXG4gICAgfSk7XG5cbiAgICB0aGlzLmFkZENvbW1hbmQoe1xuICAgICAgaWQ6ICdpbmRlbnQtdXNpbmctdGFicycsXG4gICAgICBuYW1lOiAnSW5kZW50IHVzaW5nIHRhYnMnLFxuICAgICAgY2FsbGJhY2s6ICgpID0+IHNldFZhdWx0Q29uZmlnKHRoaXMuYXBwLCAndXNlVGFiJywgdHJ1ZSksXG4gICAgfSk7XG5cbiAgICB0aGlzLmFkZENvbW1hbmQoe1xuICAgICAgaWQ6ICdpbmRlbnQtdXNpbmctc3BhY2VzJyxcbiAgICAgIG5hbWU6ICdJbmRlbnQgdXNpbmcgc3BhY2VzJyxcbiAgICAgIGNhbGxiYWNrOiAoKSA9PiBzZXRWYXVsdENvbmZpZyh0aGlzLmFwcCwgJ3VzZVRhYicsIGZhbHNlKSxcbiAgICB9KTtcblxuICAgIHRoaXMuYWRkQ29tbWFuZCh7XG4gICAgICBpZDogJ3VuZG8nLFxuICAgICAgbmFtZTogJ1VuZG8nLFxuICAgICAgZWRpdG9yQ2FsbGJhY2s6IChlZGl0b3IpID0+IGVkaXRvci51bmRvKCksXG4gICAgfSk7XG5cbiAgICB0aGlzLmFkZENvbW1hbmQoe1xuICAgICAgaWQ6ICdyZWRvJyxcbiAgICAgIG5hbWU6ICdSZWRvJyxcbiAgICAgIGVkaXRvckNhbGxiYWNrOiAoZWRpdG9yKSA9PiBlZGl0b3IucmVkbygpLFxuICAgIH0pO1xuXG4gICAgdGhpcy5yZWdpc3RlclNlbGVjdGlvbkNoYW5nZUxpc3RlbmVycygpO1xuXG4gICAgdGhpcy5hZGRTZXR0aW5nVGFiKG5ldyBTZXR0aW5nVGFiKHRoaXMuYXBwLCB0aGlzKSk7XG4gIH1cblxuICBwcml2YXRlIHJlZ2lzdGVyU2VsZWN0aW9uQ2hhbmdlTGlzdGVuZXJzKCkge1xuICAgIHRoaXMuYXBwLndvcmtzcGFjZS5vbkxheW91dFJlYWR5KCgpID0+IHtcbiAgICAgIC8vIENoYW5nZSBoYW5kbGVyIGZvciBzZWxlY3RXb3JkT3JOZXh0T2NjdXJyZW5jZVxuICAgICAgY29uc3QgaGFuZGxlU2VsZWN0aW9uQ2hhbmdlID0gKGV2dDogRXZlbnQpID0+IHtcbiAgICAgICAgaWYgKGV2dCBpbnN0YW5jZW9mIEtleWJvYXJkRXZlbnQgJiYgTU9ESUZJRVJfS0VZUy5pbmNsdWRlcyhldnQua2V5KSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWlzUHJvZ3JhbW1hdGljU2VsZWN0aW9uQ2hhbmdlKSB7XG4gICAgICAgICAgc2V0SXNNYW51YWxTZWxlY3Rpb24odHJ1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgc2V0SXNQcm9ncmFtbWF0aWNTZWxlY3Rpb25DaGFuZ2UoZmFsc2UpO1xuICAgICAgfTtcbiAgICAgIGl0ZXJhdGVDb2RlTWlycm9yRGl2cygoY206IEhUTUxFbGVtZW50KSA9PiB7XG4gICAgICAgIHRoaXMucmVnaXN0ZXJEb21FdmVudChjbSwgJ2tleWRvd24nLCBoYW5kbGVTZWxlY3Rpb25DaGFuZ2UpO1xuICAgICAgICB0aGlzLnJlZ2lzdGVyRG9tRXZlbnQoY20sICdjbGljaycsIGhhbmRsZVNlbGVjdGlvbkNoYW5nZSk7XG4gICAgICAgIHRoaXMucmVnaXN0ZXJEb21FdmVudChjbSwgJ2RibGNsaWNrJywgaGFuZGxlU2VsZWN0aW9uQ2hhbmdlKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgYXN5bmMgbG9hZFNldHRpbmdzKCkge1xuICAgIGNvbnN0IHNhdmVkU2V0dGluZ3MgPSBhd2FpdCB0aGlzLmxvYWREYXRhKCk7XG4gICAgdGhpcy5zZXR0aW5ncyA9IHtcbiAgICAgIC4uLkRFRkFVTFRfU0VUVElOR1MsXG4gICAgICAuLi5zYXZlZFNldHRpbmdzLFxuICAgIH07XG4gICAgU2V0dGluZ3NTdGF0ZS5hdXRvSW5zZXJ0TGlzdFByZWZpeCA9IHRoaXMuc2V0dGluZ3MuYXV0b0luc2VydExpc3RQcmVmaXg7XG4gIH1cblxuICBhc3luYyBzYXZlU2V0dGluZ3MoKSB7XG4gICAgYXdhaXQgdGhpcy5zYXZlRGF0YSh0aGlzLnNldHRpbmdzKTtcbiAgICBTZXR0aW5nc1N0YXRlLmF1dG9JbnNlcnRMaXN0UHJlZml4ID0gdGhpcy5zZXR0aW5ncy5hdXRvSW5zZXJ0TGlzdFByZWZpeDtcbiAgfVxufVxuIiwgImV4cG9ydCBlbnVtIENBU0Uge1xuICBVUFBFUiA9ICd1cHBlcicsXG4gIExPV0VSID0gJ2xvd2VyJyxcbiAgVElUTEUgPSAndGl0bGUnLFxuICBORVhUID0gJ25leHQnLFxufVxuXG5leHBvcnQgY29uc3QgTE9XRVJDQVNFX0FSVElDTEVTID0gWyd0aGUnLCAnYScsICdhbiddO1xuXG5leHBvcnQgZW51bSBTRUFSQ0hfRElSRUNUSU9OIHtcbiAgRk9SV0FSRCA9ICdmb3J3YXJkJyxcbiAgQkFDS1dBUkQgPSAnYmFja3dhcmQnLFxufVxuXG5leHBvcnQgdHlwZSBNYXRjaGluZ0NoYXJhY3Rlck1hcCA9IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH07XG5cbmV4cG9ydCBjb25zdCBNQVRDSElOR19CUkFDS0VUUzogTWF0Y2hpbmdDaGFyYWN0ZXJNYXAgPSB7XG4gICdbJzogJ10nLFxuICAnKCc6ICcpJyxcbiAgJ3snOiAnfScsXG59O1xuXG5leHBvcnQgY29uc3QgTUFUQ0hJTkdfUVVPVEVTOiBNYXRjaGluZ0NoYXJhY3Rlck1hcCA9IHtcbiAgXCInXCI6IFwiJ1wiLFxuICAnXCInOiAnXCInLFxuICAnYCc6ICdgJyxcbn07XG5cbmV4cG9ydCBjb25zdCBNQVRDSElOR19RVU9URVNfQlJBQ0tFVFM6IE1hdGNoaW5nQ2hhcmFjdGVyTWFwID0ge1xuICAuLi5NQVRDSElOR19RVU9URVMsXG4gIC4uLk1BVENISU5HX0JSQUNLRVRTLFxufTtcblxuZXhwb3J0IGVudW0gQ09ERV9FRElUT1Ige1xuICBTVUJMSU1FID0gJ3N1YmxpbWUnLFxuICBWU0NPREUgPSAndnNjb2RlJyxcbn1cblxuZXhwb3J0IGNvbnN0IE1PRElGSUVSX0tFWVMgPSBbXG4gICdDb250cm9sJyxcbiAgJ1NoaWZ0JyxcbiAgJ0FsdCcsXG4gICdNZXRhJyxcbiAgJ0NhcHNMb2NrJyxcbiAgJ0ZuJyxcbl07XG5cbi8qKlxuICogQ2FwdHVyZXMgdGhlIHByZWZpeCAoaW5jbHVkaW5nIHNwYWNlKSBmb3IgYnVsbGV0IGxpc3RzLCBudW1iZXJlZCBsaXN0c1xuICogYW5kIGNoZWNrbGlzdHNcbiAqL1xuZXhwb3J0IGNvbnN0IExJU1RfQ0hBUkFDVEVSX1JFR0VYID0gL15cXHMqKC18XFwrfFxcKnxcXGQrXFwufD4pIChcXFsuXFxdICk/LztcbiIsICJ0eXBlIENvZGVFZGl0b3JTaG9ydGN1dHNTdGF0ZSA9IHtcbiAgYXV0b0luc2VydExpc3RQcmVmaXg6IGJvb2xlYW47XG59O1xuXG4vKipcbiAqIFNpbXBsZSBzdGF0ZSBvYmplY3QgdXNlZCB0byBob2xkIGluZm9ybWF0aW9uIGZyb20gc2F2ZWQgc2V0dGluZ3MgKGFjY2Vzc2libGVcbiAqIGFueXdoZXJlIGl0J3MgaW1wb3J0ZWQgd2l0aG91dCBuZWVkaW5nIHRvIHRocmVhZCBpdCBkb3duIHRvIGRlcGVuZGVudFxuICogZnVuY3Rpb25zIGFzIGFuIGFyZ3VtZW50KVxuICovXG5leHBvcnQgY29uc3QgU2V0dGluZ3NTdGF0ZTogQ29kZUVkaXRvclNob3J0Y3V0c1N0YXRlID0ge1xuICBhdXRvSW5zZXJ0TGlzdFByZWZpeDogdHJ1ZSxcbn07XG4iLCAiaW1wb3J0IHtcbiAgQXBwLFxuICBFZGl0b3IsXG4gIEVkaXRvckNoYW5nZSxcbiAgRWRpdG9yUmFuZ2VPckNhcmV0LFxuICBFZGl0b3JQb3NpdGlvbixcbiAgRWRpdG9yU2VsZWN0aW9uLFxuICBFZGl0b3JTZWxlY3Rpb25PckNhcmV0LFxufSBmcm9tICdvYnNpZGlhbic7XG5pbXBvcnQge1xuICBTRUFSQ0hfRElSRUNUSU9OLFxuICBMT1dFUkNBU0VfQVJUSUNMRVMsXG4gIExJU1RfQ0hBUkFDVEVSX1JFR0VYLFxufSBmcm9tICcuL2NvbnN0YW50cyc7XG5pbXBvcnQgeyBDdXN0b21TZWxlY3Rpb25IYW5kbGVyIH0gZnJvbSAnLi9jdXN0b20tc2VsZWN0aW9uLWhhbmRsZXJzJztcblxudHlwZSBFZGl0b3JBY3Rpb25DYWxsYmFja05ldyA9IChcbiAgZWRpdG9yOiBFZGl0b3IsXG4gIHNlbGVjdGlvbjogRWRpdG9yU2VsZWN0aW9uLFxuICBhcmdzOiBhbnksXG4pID0+IHsgY2hhbmdlczogRWRpdG9yQ2hhbmdlW107IG5ld1NlbGVjdGlvbjogRWRpdG9yUmFuZ2VPckNhcmV0IH07XG5cbnR5cGUgRWRpdG9yQWN0aW9uQ2FsbGJhY2sgPSAoXG4gIGVkaXRvcjogRWRpdG9yLFxuICBzZWxlY3Rpb246IEVkaXRvclNlbGVjdGlvbixcbiAgYXJnczogc3RyaW5nLFxuKSA9PiBFZGl0b3JTZWxlY3Rpb25PckNhcmV0O1xuXG50eXBlIE11bHRpcGxlU2VsZWN0aW9uT3B0aW9ucyA9IHtcbiAgLy8gQWRkaXRpb25hbCBpbmZvcm1hdGlvbiB0byBiZSBwYXNzZWQgdG8gdGhlIEVkaXRvckFjdGlvbkNhbGxiYWNrXG4gIGFyZ3M/OiBzdHJpbmc7XG5cbiAgLy8gUGVyZm9ybSBmdXJ0aGVyIHByb2Nlc3Npbmcgb2YgbmV3IHNlbGVjdGlvbnMgYmVmb3JlIHRoZXkgYXJlIHNldFxuICBjdXN0b21TZWxlY3Rpb25IYW5kbGVyPzogQ3VzdG9tU2VsZWN0aW9uSGFuZGxlcjtcblxuICAvLyBXaGV0aGVyIHRoZSBhY3Rpb24gc2hvdWxkIGJlIHJlcGVhdGVkIGZvciBjdXJzb3JzIG9uIHRoZSBzYW1lIGxpbmVcbiAgcmVwZWF0U2FtZUxpbmVBY3Rpb25zPzogYm9vbGVhbjtcbn07XG5cbmV4cG9ydCB0eXBlIEVkaXRvckFjdGlvbkNhbGxiYWNrTmV3QXJncyA9IFJlY29yZDxzdHJpbmcsIGFueT47XG5cbnR5cGUgTXVsdGlwbGVTZWxlY3Rpb25PcHRpb25zTmV3ID0ge1xuICAvLyBBZGRpdGlvbmFsIGluZm9ybWF0aW9uIHRvIGJlIHBhc3NlZCB0byB0aGUgRWRpdG9yQWN0aW9uQ2FsbGJhY2tcbiAgYXJncz86IEVkaXRvckFjdGlvbkNhbGxiYWNrTmV3QXJncztcblxuICAvLyBXaGV0aGVyIHRoZSBhY3Rpb24gc2hvdWxkIGJlIHJlcGVhdGVkIGZvciBjdXJzb3JzIG9uIHRoZSBzYW1lIGxpbmVcbiAgcmVwZWF0U2FtZUxpbmVBY3Rpb25zPzogYm9vbGVhbjtcblxuICAvLyBXaGV0aGVyIHRvIGNvbWJpbmUgY3Vyc29ycyBvbiB0aGUgc2FtZSBsaW5lIGFmdGVyIHRoZSBvcGVyYXRpb24gaGFzXG4gIC8vIGZpbmlzaGVkICh0aGUgY3Vyc29yIHdpdGggYSBzbWFsbGVyIGxpbmUgbnVtYmVyIHRha2VzIHByZWNlZGVuY2UpXG4gIGNvbWJpbmVTYW1lTGluZVNlbGVjdGlvbnM/OiBib29sZWFuO1xufTtcblxuZXhwb3J0IGNvbnN0IGRlZmF1bHRNdWx0aXBsZVNlbGVjdGlvbk9wdGlvbnMgPSB7IHJlcGVhdFNhbWVMaW5lQWN0aW9uczogdHJ1ZSB9O1xuXG5leHBvcnQgY29uc3Qgd2l0aE11bHRpcGxlU2VsZWN0aW9uc05ldyA9IChcbiAgZWRpdG9yOiBFZGl0b3IsXG4gIGNhbGxiYWNrOiBFZGl0b3JBY3Rpb25DYWxsYmFja05ldyxcbiAgb3B0aW9uczogTXVsdGlwbGVTZWxlY3Rpb25PcHRpb25zTmV3ID0gZGVmYXVsdE11bHRpcGxlU2VsZWN0aW9uT3B0aW9ucyxcbikgPT4ge1xuICBjb25zdCBzZWxlY3Rpb25zID0gZWRpdG9yLmxpc3RTZWxlY3Rpb25zKCk7XG4gIGxldCBzZWxlY3Rpb25JbmRleGVzVG9Qcm9jZXNzOiBudW1iZXJbXTtcbiAgY29uc3QgbmV3U2VsZWN0aW9uczogRWRpdG9yUmFuZ2VPckNhcmV0W10gPSBbXTtcbiAgY29uc3QgY2hhbmdlczogRWRpdG9yQ2hhbmdlW10gPSBbXTtcblxuICBpZiAoIW9wdGlvbnMucmVwZWF0U2FtZUxpbmVBY3Rpb25zKSB7XG4gICAgY29uc3Qgc2VlbkxpbmVzOiBudW1iZXJbXSA9IFtdO1xuICAgIHNlbGVjdGlvbkluZGV4ZXNUb1Byb2Nlc3MgPSBzZWxlY3Rpb25zLnJlZHVjZShcbiAgICAgIChpbmRleGVzLCBjdXJyU2VsZWN0aW9uLCBjdXJySW5kZXgpID0+IHtcbiAgICAgICAgY29uc3QgY3VycmVudExpbmUgPSBjdXJyU2VsZWN0aW9uLmhlYWQubGluZTtcbiAgICAgICAgaWYgKCFzZWVuTGluZXMuaW5jbHVkZXMoY3VycmVudExpbmUpKSB7XG4gICAgICAgICAgc2VlbkxpbmVzLnB1c2goY3VycmVudExpbmUpO1xuICAgICAgICAgIGluZGV4ZXMucHVzaChjdXJySW5kZXgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBpbmRleGVzO1xuICAgICAgfSxcbiAgICAgIFtdLFxuICAgICk7XG4gIH1cblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHNlbGVjdGlvbnMubGVuZ3RoOyBpKyspIHtcbiAgICAvLyBDb250cm9sbGVkIGJ5IHJlcGVhdFNhbWVMaW5lQWN0aW9uc1xuICAgIGlmIChzZWxlY3Rpb25JbmRleGVzVG9Qcm9jZXNzICYmICFzZWxlY3Rpb25JbmRleGVzVG9Qcm9jZXNzLmluY2x1ZGVzKGkpKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBjb25zdCB7IGNoYW5nZXM6IG5ld0NoYW5nZXMsIG5ld1NlbGVjdGlvbiB9ID0gY2FsbGJhY2soXG4gICAgICBlZGl0b3IsXG4gICAgICBzZWxlY3Rpb25zW2ldLFxuICAgICAge1xuICAgICAgICAuLi5vcHRpb25zLmFyZ3MsXG4gICAgICAgIGl0ZXJhdGlvbjogaSxcbiAgICAgIH0sXG4gICAgKTtcbiAgICBjaGFuZ2VzLnB1c2goLi4ubmV3Q2hhbmdlcyk7XG5cbiAgICBpZiAob3B0aW9ucy5jb21iaW5lU2FtZUxpbmVTZWxlY3Rpb25zKSB7XG4gICAgICBjb25zdCBleGlzdGluZ1NhbWVMaW5lU2VsZWN0aW9uID0gbmV3U2VsZWN0aW9ucy5maW5kKFxuICAgICAgICAoc2VsZWN0aW9uKSA9PiBzZWxlY3Rpb24uZnJvbS5saW5lID09PSBuZXdTZWxlY3Rpb24uZnJvbS5saW5lLFxuICAgICAgKTtcbiAgICAgIC8vIEdlbmVyYWxseSBvbmx5IGhhcHBlbnMgd2hlbiBkZWxldGluZyBjb25zZWN1dGl2ZSBsaW5lcyB1c2luZyBzZXBhcmF0ZSBjdXJzb3JzXG4gICAgICBpZiAoZXhpc3RpbmdTYW1lTGluZVNlbGVjdGlvbikge1xuICAgICAgICAvLyBSZXNldCB0byAwIGFzIGBjaGAgd2lsbCBvdGhlcndpc2UgZXhjZWVkIHRoZSBsaW5lIGxlbmd0aFxuICAgICAgICBleGlzdGluZ1NhbWVMaW5lU2VsZWN0aW9uLmZyb20uY2ggPSAwO1xuICAgICAgICAvLyBTa2lwIGFkZGluZyBhIG5ldyBzZWxlY3Rpb24gd2l0aCB0aGUgc2FtZSBsaW5lIG51bWJlclxuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBuZXdTZWxlY3Rpb25zLnB1c2gobmV3U2VsZWN0aW9uKTtcbiAgfVxuXG4gIGVkaXRvci50cmFuc2FjdGlvbih7XG4gICAgY2hhbmdlcyxcbiAgICBzZWxlY3Rpb25zOiBuZXdTZWxlY3Rpb25zLFxuICB9KTtcbn07XG5cbmV4cG9ydCBjb25zdCB3aXRoTXVsdGlwbGVTZWxlY3Rpb25zID0gKFxuICBlZGl0b3I6IEVkaXRvcixcbiAgY2FsbGJhY2s6IEVkaXRvckFjdGlvbkNhbGxiYWNrLFxuICBvcHRpb25zOiBNdWx0aXBsZVNlbGVjdGlvbk9wdGlvbnMgPSBkZWZhdWx0TXVsdGlwbGVTZWxlY3Rpb25PcHRpb25zLFxuKSA9PiB7XG4gIC8vIEB0cy1leHBlY3QtZXJyb3I6IE9ic2lkaWFuJ3MgRWRpdG9yIGludGVyZmFjZSBkb2VzIG5vdCBleHBsaWNpdGx5XG4gIC8vIGluY2x1ZGUgdGhlIENvZGVNaXJyb3IgY20gb2JqZWN0LCBidXQgaXQgaXMgdGhlcmUgd2hlbiB1c2luZyB0aGVcbiAgLy8gbGVnYWN5IGVkaXRvclxuICBjb25zdCB7IGNtIH0gPSBlZGl0b3I7XG5cbiAgY29uc3Qgc2VsZWN0aW9ucyA9IGVkaXRvci5saXN0U2VsZWN0aW9ucygpO1xuICBsZXQgc2VsZWN0aW9uSW5kZXhlc1RvUHJvY2VzczogbnVtYmVyW107XG4gIGxldCBuZXdTZWxlY3Rpb25zOiBFZGl0b3JTZWxlY3Rpb25PckNhcmV0W10gPSBbXTtcblxuICBpZiAoIW9wdGlvbnMucmVwZWF0U2FtZUxpbmVBY3Rpb25zKSB7XG4gICAgY29uc3Qgc2VlbkxpbmVzOiBudW1iZXJbXSA9IFtdO1xuICAgIHNlbGVjdGlvbkluZGV4ZXNUb1Byb2Nlc3MgPSBzZWxlY3Rpb25zLnJlZHVjZShcbiAgICAgIChpbmRleGVzLCBjdXJyU2VsZWN0aW9uLCBjdXJySW5kZXgpID0+IHtcbiAgICAgICAgY29uc3QgY3VycmVudExpbmUgPSBjdXJyU2VsZWN0aW9uLmhlYWQubGluZTtcbiAgICAgICAgaWYgKCFzZWVuTGluZXMuaW5jbHVkZXMoY3VycmVudExpbmUpKSB7XG4gICAgICAgICAgc2VlbkxpbmVzLnB1c2goY3VycmVudExpbmUpO1xuICAgICAgICAgIGluZGV4ZXMucHVzaChjdXJySW5kZXgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBpbmRleGVzO1xuICAgICAgfSxcbiAgICAgIFtdLFxuICAgICk7XG4gIH1cblxuICBjb25zdCBhcHBseUNhbGxiYWNrT25TZWxlY3Rpb25zID0gKCkgPT4ge1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2VsZWN0aW9ucy5sZW5ndGg7IGkrKykge1xuICAgICAgLy8gQ29udHJvbGxlZCBieSByZXBlYXRTYW1lTGluZUFjdGlvbnNcbiAgICAgIGlmIChzZWxlY3Rpb25JbmRleGVzVG9Qcm9jZXNzICYmICFzZWxlY3Rpb25JbmRleGVzVG9Qcm9jZXNzLmluY2x1ZGVzKGkpKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICAvLyBDYW4ndCByZXVzZSBzZWxlY3Rpb25zIHZhcmlhYmxlIGFzIHBvc2l0aW9ucyBtYXkgY2hhbmdlIG9uIGVhY2ggaXRlcmF0aW9uXG4gICAgICBjb25zdCBzZWxlY3Rpb24gPSBlZGl0b3IubGlzdFNlbGVjdGlvbnMoKVtpXTtcblxuICAgICAgLy8gU2VsZWN0aW9ucyBtYXkgZGlzYXBwZWFyIChlLmcuIHJ1bm5pbmcgZGVsZXRlIGxpbmUgZm9yIHR3byBjdXJzb3JzIG9uIHRoZSBzYW1lIGxpbmUpXG4gICAgICBpZiAoc2VsZWN0aW9uKSB7XG4gICAgICAgIGNvbnN0IG5ld1NlbGVjdGlvbiA9IGNhbGxiYWNrKGVkaXRvciwgc2VsZWN0aW9uLCBvcHRpb25zLmFyZ3MpO1xuICAgICAgICBuZXdTZWxlY3Rpb25zLnB1c2gobmV3U2VsZWN0aW9uKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAob3B0aW9ucy5jdXN0b21TZWxlY3Rpb25IYW5kbGVyKSB7XG4gICAgICBuZXdTZWxlY3Rpb25zID0gb3B0aW9ucy5jdXN0b21TZWxlY3Rpb25IYW5kbGVyKG5ld1NlbGVjdGlvbnMpO1xuICAgIH1cbiAgICBlZGl0b3Iuc2V0U2VsZWN0aW9ucyhuZXdTZWxlY3Rpb25zKTtcbiAgfTtcblxuICBpZiAoY20gJiYgY20ub3BlcmF0aW9uKSB7XG4gICAgLy8gR3JvdXAgYWxsIHRoZSB1cGRhdGVzIGludG8gb25lIGF0b21pYyBvcGVyYXRpb24gKHNvIHVuZG8vcmVkbyB3b3JrIGFzIGV4cGVjdGVkKVxuICAgIGNtLm9wZXJhdGlvbihhcHBseUNhbGxiYWNrT25TZWxlY3Rpb25zKTtcbiAgfSBlbHNlIHtcbiAgICAvLyBTYWZlIGZhbGxiYWNrIGlmIGNtIGRvZXNuJ3QgZXhpc3QgKHNvIHVuZG8vcmVkbyB3aWxsIHN0ZXAgdGhyb3VnaCBlYWNoIGNoYW5nZSlcbiAgICBjb25zb2xlLmRlYnVnKCdjbSBvYmplY3Qgbm90IGZvdW5kLCBvcGVyYXRpb25zIHdpbGwgbm90IGJlIGJ1ZmZlcmVkJyk7XG4gICAgYXBwbHlDYWxsYmFja09uU2VsZWN0aW9ucygpO1xuICB9XG59O1xuXG4vKipcbiAqIEV4ZWN1dGVzIHRoZSBzdXBwbGllZCBjYWxsYmFjayBmb3IgZWFjaCB0b3AtbGV2ZWwgQ29kZU1pcnJvciBkaXYgZWxlbWVudCBpbiB0aGVcbiAqIERPTS4gVGhpcyBpcyBhbiBpbnRlcmltIHV0aWwgbWFkZSB0byB3b3JrIHdpdGggYm90aCBDTTUgYW5kIENNNiBhcyBPYnNpZGlhbidzXG4gKiBgaXRlcmF0ZUNvZGVNaXJyb3JzYCBtZXRob2Qgb25seSB3b3JrcyB3aXRoIENNNS5cbiAqL1xuZXhwb3J0IGNvbnN0IGl0ZXJhdGVDb2RlTWlycm9yRGl2cyA9IChjYWxsYmFjazogKGNtOiBIVE1MRWxlbWVudCkgPT4gYW55KSA9PiB7XG4gIGxldCBjb2RlTWlycm9yczogTm9kZUxpc3RPZjxIVE1MRWxlbWVudD47XG4gIGNvZGVNaXJyb3JzID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnLmNtLWNvbnRlbnQnKTsgLy8gQ002XG4gIGlmIChjb2RlTWlycm9ycy5sZW5ndGggPT09IDApIHtcbiAgICBjb2RlTWlycm9ycyA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJy5Db2RlTWlycm9yJyk7IC8vIENNNVxuICB9XG4gIGNvZGVNaXJyb3JzLmZvckVhY2goY2FsbGJhY2spO1xufTtcblxuZXhwb3J0IGNvbnN0IGdldExpbmVTdGFydFBvcyA9IChsaW5lOiBudW1iZXIpOiBFZGl0b3JQb3NpdGlvbiA9PiAoe1xuICBsaW5lLFxuICBjaDogMCxcbn0pO1xuXG5leHBvcnQgY29uc3QgZ2V0TGluZUVuZFBvcyA9IChcbiAgbGluZTogbnVtYmVyLFxuICBlZGl0b3I6IEVkaXRvcixcbik6IEVkaXRvclBvc2l0aW9uID0+ICh7XG4gIGxpbmUsXG4gIGNoOiBlZGl0b3IuZ2V0TGluZShsaW5lKS5sZW5ndGgsXG59KTtcblxuZXhwb3J0IGNvbnN0IGdldFNlbGVjdGlvbkJvdW5kYXJpZXMgPSAoc2VsZWN0aW9uOiBFZGl0b3JTZWxlY3Rpb24pID0+IHtcbiAgbGV0IHsgYW5jaG9yOiBmcm9tLCBoZWFkOiB0byB9ID0gc2VsZWN0aW9uO1xuXG4gIC8vIEluIGNhc2UgdXNlciBzZWxlY3RzIHVwd2FyZHNcbiAgaWYgKGZyb20ubGluZSA+IHRvLmxpbmUpIHtcbiAgICBbZnJvbSwgdG9dID0gW3RvLCBmcm9tXTtcbiAgfVxuXG4gIC8vIEluIGNhc2UgdXNlciBzZWxlY3RzIGJhY2t3YXJkcyBvbiB0aGUgc2FtZSBsaW5lXG4gIGlmIChmcm9tLmxpbmUgPT09IHRvLmxpbmUgJiYgZnJvbS5jaCA+IHRvLmNoKSB7XG4gICAgW2Zyb20sIHRvXSA9IFt0bywgZnJvbV07XG4gIH1cblxuICByZXR1cm4geyBmcm9tLCB0bywgaGFzVHJhaWxpbmdOZXdsaW5lOiB0by5saW5lID4gZnJvbS5saW5lICYmIHRvLmNoID09PSAwIH07XG59O1xuXG5leHBvcnQgY29uc3QgZ2V0TGVhZGluZ1doaXRlc3BhY2UgPSAobGluZUNvbnRlbnQ6IHN0cmluZykgPT4ge1xuICBjb25zdCBpbmRlbnRhdGlvbiA9IGxpbmVDb250ZW50Lm1hdGNoKC9eXFxzKy8pO1xuICByZXR1cm4gaW5kZW50YXRpb24gPyBpbmRlbnRhdGlvblswXSA6ICcnO1xufTtcblxuLy8gTWF0Y2ggYW55IGNoYXJhY3RlciBmcm9tIGFueSBsYW5ndWFnZTogaHR0cHM6Ly93d3cucmVndWxhci1leHByZXNzaW9ucy5pbmZvL3VuaWNvZGUuaHRtbFxuY29uc3QgaXNMZXR0ZXJDaGFyYWN0ZXIgPSAoY2hhcjogc3RyaW5nKSA9PiAvXFxwe0x9XFxwe019Ki91LnRlc3QoY2hhcik7XG5cbmNvbnN0IGlzRGlnaXQgPSAoY2hhcjogc3RyaW5nKSA9PiAvXFxkLy50ZXN0KGNoYXIpO1xuXG5jb25zdCBpc0xldHRlck9yRGlnaXQgPSAoY2hhcjogc3RyaW5nKSA9PlxuICBpc0xldHRlckNoYXJhY3RlcihjaGFyKSB8fCBpc0RpZ2l0KGNoYXIpO1xuXG5leHBvcnQgY29uc3Qgd29yZFJhbmdlQXRQb3MgPSAoXG4gIHBvczogRWRpdG9yUG9zaXRpb24sXG4gIGxpbmVDb250ZW50OiBzdHJpbmcsXG4pOiB7IGFuY2hvcjogRWRpdG9yUG9zaXRpb247IGhlYWQ6IEVkaXRvclBvc2l0aW9uIH0gPT4ge1xuICBsZXQgc3RhcnQgPSBwb3MuY2g7XG4gIGxldCBlbmQgPSBwb3MuY2g7XG4gIHdoaWxlIChzdGFydCA+IDAgJiYgaXNMZXR0ZXJPckRpZ2l0KGxpbmVDb250ZW50LmNoYXJBdChzdGFydCAtIDEpKSkge1xuICAgIHN0YXJ0LS07XG4gIH1cbiAgd2hpbGUgKGVuZCA8IGxpbmVDb250ZW50Lmxlbmd0aCAmJiBpc0xldHRlck9yRGlnaXQobGluZUNvbnRlbnQuY2hhckF0KGVuZCkpKSB7XG4gICAgZW5kKys7XG4gIH1cbiAgcmV0dXJuIHtcbiAgICBhbmNob3I6IHtcbiAgICAgIGxpbmU6IHBvcy5saW5lLFxuICAgICAgY2g6IHN0YXJ0LFxuICAgIH0sXG4gICAgaGVhZDoge1xuICAgICAgbGluZTogcG9zLmxpbmUsXG4gICAgICBjaDogZW5kLFxuICAgIH0sXG4gIH07XG59O1xuXG5leHBvcnQgdHlwZSBDaGVja0NoYXJhY3RlciA9IChjaGFyOiBzdHJpbmcpID0+IGJvb2xlYW47XG5cbmV4cG9ydCBjb25zdCBmaW5kUG9zT2ZOZXh0Q2hhcmFjdGVyID0gKHtcbiAgZWRpdG9yLFxuICBzdGFydFBvcyxcbiAgY2hlY2tDaGFyYWN0ZXIsXG4gIHNlYXJjaERpcmVjdGlvbixcbn06IHtcbiAgZWRpdG9yOiBFZGl0b3I7XG4gIHN0YXJ0UG9zOiBFZGl0b3JQb3NpdGlvbjtcbiAgY2hlY2tDaGFyYWN0ZXI6IENoZWNrQ2hhcmFjdGVyO1xuICBzZWFyY2hEaXJlY3Rpb246IFNFQVJDSF9ESVJFQ1RJT047XG59KSA9PiB7XG4gIGxldCB7IGxpbmUsIGNoIH0gPSBzdGFydFBvcztcbiAgbGV0IGxpbmVDb250ZW50ID0gZWRpdG9yLmdldExpbmUobGluZSk7XG4gIGxldCBtYXRjaEZvdW5kID0gZmFsc2U7XG4gIGxldCBtYXRjaGVkQ2hhcjogc3RyaW5nO1xuXG4gIGlmIChzZWFyY2hEaXJlY3Rpb24gPT09IFNFQVJDSF9ESVJFQ1RJT04uQkFDS1dBUkQpIHtcbiAgICB3aGlsZSAobGluZSA+PSAwKSB7XG4gICAgICAvLyBjaCB3aWxsIGluaXRpYWxseSBiZSAwIGlmIHNlYXJjaGluZyBmcm9tIHN0YXJ0IG9mIGxpbmVcbiAgICAgIGNvbnN0IGNoYXIgPSBsaW5lQ29udGVudC5jaGFyQXQoTWF0aC5tYXgoY2ggLSAxLCAwKSk7XG4gICAgICBtYXRjaEZvdW5kID0gY2hlY2tDaGFyYWN0ZXIoY2hhcik7XG4gICAgICBpZiAobWF0Y2hGb3VuZCkge1xuICAgICAgICBtYXRjaGVkQ2hhciA9IGNoYXI7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgY2gtLTtcbiAgICAgIC8vIGluY2x1c2l2ZSBiZWNhdXNlIChjaCAtIDEpIG1lYW5zIHRoZSBmaXJzdCBjaGFyYWN0ZXIgd2lsbCBhbHJlYWR5XG4gICAgICAvLyBoYXZlIGJlZW4gY2hlY2tlZFxuICAgICAgaWYgKGNoIDw9IDApIHtcbiAgICAgICAgbGluZS0tO1xuICAgICAgICBpZiAobGluZSA+PSAwKSB7XG4gICAgICAgICAgbGluZUNvbnRlbnQgPSBlZGl0b3IuZ2V0TGluZShsaW5lKTtcbiAgICAgICAgICBjaCA9IGxpbmVDb250ZW50Lmxlbmd0aDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICB3aGlsZSAobGluZSA8IGVkaXRvci5saW5lQ291bnQoKSkge1xuICAgICAgY29uc3QgY2hhciA9IGxpbmVDb250ZW50LmNoYXJBdChjaCk7XG4gICAgICBtYXRjaEZvdW5kID0gY2hlY2tDaGFyYWN0ZXIoY2hhcik7XG4gICAgICBpZiAobWF0Y2hGb3VuZCkge1xuICAgICAgICBtYXRjaGVkQ2hhciA9IGNoYXI7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgY2grKztcbiAgICAgIGlmIChjaCA+PSBsaW5lQ29udGVudC5sZW5ndGgpIHtcbiAgICAgICAgbGluZSsrO1xuICAgICAgICBsaW5lQ29udGVudCA9IGVkaXRvci5nZXRMaW5lKGxpbmUpO1xuICAgICAgICBjaCA9IDA7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG1hdGNoRm91bmRcbiAgICA/IHtcbiAgICAgICAgbWF0Y2g6IG1hdGNoZWRDaGFyLFxuICAgICAgICBwb3M6IHtcbiAgICAgICAgICBsaW5lLFxuICAgICAgICAgIGNoLFxuICAgICAgICB9LFxuICAgICAgfVxuICAgIDogbnVsbDtcbn07XG5cbmV4cG9ydCBjb25zdCBoYXNTYW1lU2VsZWN0aW9uQ29udGVudCA9IChcbiAgZWRpdG9yOiBFZGl0b3IsXG4gIHNlbGVjdGlvbnM6IEVkaXRvclNlbGVjdGlvbltdLFxuKSA9PlxuICBuZXcgU2V0KFxuICAgIHNlbGVjdGlvbnMubWFwKChzZWxlY3Rpb24pID0+IHtcbiAgICAgIGNvbnN0IHsgZnJvbSwgdG8gfSA9IGdldFNlbGVjdGlvbkJvdW5kYXJpZXMoc2VsZWN0aW9uKTtcbiAgICAgIHJldHVybiBlZGl0b3IuZ2V0UmFuZ2UoZnJvbSwgdG8pO1xuICAgIH0pLFxuICApLnNpemUgPT09IDE7XG5cbmV4cG9ydCBjb25zdCBnZXRTZWFyY2hUZXh0ID0gKHtcbiAgZWRpdG9yLFxuICBhbGxTZWxlY3Rpb25zLFxuICBhdXRvRXhwYW5kLFxufToge1xuICBlZGl0b3I6IEVkaXRvcjtcbiAgYWxsU2VsZWN0aW9uczogRWRpdG9yU2VsZWN0aW9uW107XG4gIGF1dG9FeHBhbmQ6IGJvb2xlYW47XG59KSA9PiB7XG4gIC8vIERvbid0IHNlYXJjaCBpZiBtdWx0aXBsZSBzZWxlY3Rpb24gY29udGVudHMgYXJlIG5vdCBpZGVudGljYWxcbiAgY29uc3Qgc2luZ2xlU2VhcmNoVGV4dCA9IGhhc1NhbWVTZWxlY3Rpb25Db250ZW50KGVkaXRvciwgYWxsU2VsZWN0aW9ucyk7XG4gIGNvbnN0IGZpcnN0U2VsZWN0aW9uID0gYWxsU2VsZWN0aW9uc1swXTtcbiAgY29uc3QgeyBmcm9tLCB0byB9ID0gZ2V0U2VsZWN0aW9uQm91bmRhcmllcyhmaXJzdFNlbGVjdGlvbik7XG4gIGxldCBzZWFyY2hUZXh0ID0gZWRpdG9yLmdldFJhbmdlKGZyb20sIHRvKTtcbiAgaWYgKHNlYXJjaFRleHQubGVuZ3RoID09PSAwICYmIGF1dG9FeHBhbmQpIHtcbiAgICBjb25zdCB3b3JkUmFuZ2UgPSB3b3JkUmFuZ2VBdFBvcyhmcm9tLCBlZGl0b3IuZ2V0TGluZShmcm9tLmxpbmUpKTtcbiAgICBzZWFyY2hUZXh0ID0gZWRpdG9yLmdldFJhbmdlKHdvcmRSYW5nZS5hbmNob3IsIHdvcmRSYW5nZS5oZWFkKTtcbiAgfVxuICByZXR1cm4ge1xuICAgIHNlYXJjaFRleHQsXG4gICAgc2luZ2xlU2VhcmNoVGV4dCxcbiAgfTtcbn07XG5cbi8qKlxuICogRXNjYXBlcyBhbnkgc3BlY2lhbCByZWdleCBjaGFyYWN0ZXJzIGluIHRoZSBnaXZlbiBzdHJpbmcuXG4gKlxuICogQWRhcHRlZCBmcm9tIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvR3VpZGUvUmVndWxhcl9FeHByZXNzaW9ucyNlc2NhcGluZ1xuICovXG5jb25zdCBlc2NhcGVSZWdleCA9IChpbnB1dDogc3RyaW5nKSA9PlxuICBpbnB1dC5yZXBsYWNlKC9bLiorP14ke30oKXxbXFxdXFxcXF0vZywgJ1xcXFwkJicpOyAvLyAkJiBtZWFucyB0aGUgd2hvbGUgbWF0Y2hlZCBzdHJpbmdcblxuLyoqXG4gKiBDb25zdHJ1Y3RzIGEgY3VzdG9tIHJlZ2V4IHF1ZXJ5IHdpdGggd29yZCBib3VuZGFyaWVzIGJlY2F1c2UgaW4gYFxcYmAgaW4gSlMgZG9lc24ndFxuICogbWF0Y2ggd29yZCBib3VuZGFyaWVzIGZvciB1bmljb2RlIGNoYXJhY3RlcnMsIGV2ZW4gd2l0aCB0aGUgdW5pY29kZSBmbGFnIG9uLlxuICpcbiAqIEFkYXB0ZWQgZnJvbSBodHRwczovL3NoaWJhMTAxNC5tZWRpdW0uY29tL3JlZ2V4LXdvcmQtYm91bmRhcmllcy13aXRoLXVuaWNvZGUtMjA3Nzk0ZjZlN2VkLlxuICovXG5jb25zdCB3aXRoV29yZEJvdW5kYXJpZXMgPSAoaW5wdXQ6IHN0cmluZykgPT4gYCg/PD1cXFxcV3xeKSR7aW5wdXR9KD89XFxcXFd8JClgO1xuXG5leHBvcnQgY29uc3QgZmluZEFsbE1hdGNoZXMgPSAoe1xuICBzZWFyY2hUZXh0LFxuICBzZWFyY2hXaXRoaW5Xb3JkcyxcbiAgZG9jdW1lbnRDb250ZW50LFxufToge1xuICBzZWFyY2hUZXh0OiBzdHJpbmc7XG4gIHNlYXJjaFdpdGhpbldvcmRzOiBib29sZWFuO1xuICBkb2N1bWVudENvbnRlbnQ6IHN0cmluZztcbn0pID0+IHtcbiAgY29uc3QgZXNjYXBlZFNlYXJjaFRleHQgPSBlc2NhcGVSZWdleChzZWFyY2hUZXh0KTtcbiAgY29uc3Qgc2VhcmNoRXhwcmVzc2lvbiA9IG5ldyBSZWdFeHAoXG4gICAgc2VhcmNoV2l0aGluV29yZHNcbiAgICAgID8gZXNjYXBlZFNlYXJjaFRleHRcbiAgICAgIDogd2l0aFdvcmRCb3VuZGFyaWVzKGVzY2FwZWRTZWFyY2hUZXh0KSxcbiAgICAnZycsXG4gICk7XG4gIHJldHVybiBBcnJheS5mcm9tKGRvY3VtZW50Q29udGVudC5tYXRjaEFsbChzZWFyY2hFeHByZXNzaW9uKSk7XG59O1xuXG5leHBvcnQgY29uc3QgZmluZE5leHRNYXRjaFBvc2l0aW9uID0gKHtcbiAgZWRpdG9yLFxuICBsYXRlc3RNYXRjaFBvcyxcbiAgc2VhcmNoVGV4dCxcbiAgc2VhcmNoV2l0aGluV29yZHMsXG4gIGRvY3VtZW50Q29udGVudCxcbn06IHtcbiAgZWRpdG9yOiBFZGl0b3I7XG4gIGxhdGVzdE1hdGNoUG9zOiBFZGl0b3JQb3NpdGlvbjtcbiAgc2VhcmNoVGV4dDogc3RyaW5nO1xuICBzZWFyY2hXaXRoaW5Xb3JkczogYm9vbGVhbjtcbiAgZG9jdW1lbnRDb250ZW50OiBzdHJpbmc7XG59KSA9PiB7XG4gIGNvbnN0IGxhdGVzdE1hdGNoT2Zmc2V0ID0gZWRpdG9yLnBvc1RvT2Zmc2V0KGxhdGVzdE1hdGNoUG9zKTtcbiAgY29uc3QgbWF0Y2hlcyA9IGZpbmRBbGxNYXRjaGVzKHtcbiAgICBzZWFyY2hUZXh0LFxuICAgIHNlYXJjaFdpdGhpbldvcmRzLFxuICAgIGRvY3VtZW50Q29udGVudCxcbiAgfSk7XG4gIGxldCBuZXh0TWF0Y2g6IEVkaXRvclNlbGVjdGlvbiB8IG51bGwgPSBudWxsO1xuXG4gIGZvciAoY29uc3QgbWF0Y2ggb2YgbWF0Y2hlcykge1xuICAgIGlmIChtYXRjaC5pbmRleCA+IGxhdGVzdE1hdGNoT2Zmc2V0KSB7XG4gICAgICBuZXh0TWF0Y2ggPSB7XG4gICAgICAgIGFuY2hvcjogZWRpdG9yLm9mZnNldFRvUG9zKG1hdGNoLmluZGV4KSxcbiAgICAgICAgaGVhZDogZWRpdG9yLm9mZnNldFRvUG9zKG1hdGNoLmluZGV4ICsgc2VhcmNoVGV4dC5sZW5ndGgpLFxuICAgICAgfTtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuICAvLyBDaXJjbGUgYmFjayB0byBzZWFyY2ggZnJvbSB0aGUgdG9wXG4gIGlmICghbmV4dE1hdGNoKSB7XG4gICAgY29uc3Qgc2VsZWN0aW9uSW5kZXhlcyA9IGVkaXRvci5saXN0U2VsZWN0aW9ucygpLm1hcCgoc2VsZWN0aW9uKSA9PiB7XG4gICAgICBjb25zdCB7IGZyb20gfSA9IGdldFNlbGVjdGlvbkJvdW5kYXJpZXMoc2VsZWN0aW9uKTtcbiAgICAgIHJldHVybiBlZGl0b3IucG9zVG9PZmZzZXQoZnJvbSk7XG4gICAgfSk7XG4gICAgZm9yIChjb25zdCBtYXRjaCBvZiBtYXRjaGVzKSB7XG4gICAgICBpZiAoIXNlbGVjdGlvbkluZGV4ZXMuaW5jbHVkZXMobWF0Y2guaW5kZXgpKSB7XG4gICAgICAgIG5leHRNYXRjaCA9IHtcbiAgICAgICAgICBhbmNob3I6IGVkaXRvci5vZmZzZXRUb1BvcyhtYXRjaC5pbmRleCksXG4gICAgICAgICAgaGVhZDogZWRpdG9yLm9mZnNldFRvUG9zKG1hdGNoLmluZGV4ICsgc2VhcmNoVGV4dC5sZW5ndGgpLFxuICAgICAgICB9O1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gbmV4dE1hdGNoO1xufTtcblxuZXhwb3J0IGNvbnN0IGZpbmRBbGxNYXRjaFBvc2l0aW9ucyA9ICh7XG4gIGVkaXRvcixcbiAgc2VhcmNoVGV4dCxcbiAgc2VhcmNoV2l0aGluV29yZHMsXG4gIGRvY3VtZW50Q29udGVudCxcbn06IHtcbiAgZWRpdG9yOiBFZGl0b3I7XG4gIHNlYXJjaFRleHQ6IHN0cmluZztcbiAgc2VhcmNoV2l0aGluV29yZHM6IGJvb2xlYW47XG4gIGRvY3VtZW50Q29udGVudDogc3RyaW5nO1xufSkgPT4ge1xuICBjb25zdCBtYXRjaGVzID0gZmluZEFsbE1hdGNoZXMoe1xuICAgIHNlYXJjaFRleHQsXG4gICAgc2VhcmNoV2l0aGluV29yZHMsXG4gICAgZG9jdW1lbnRDb250ZW50LFxuICB9KTtcbiAgY29uc3QgbWF0Y2hQb3NpdGlvbnMgPSBbXTtcbiAgZm9yIChjb25zdCBtYXRjaCBvZiBtYXRjaGVzKSB7XG4gICAgbWF0Y2hQb3NpdGlvbnMucHVzaCh7XG4gICAgICBhbmNob3I6IGVkaXRvci5vZmZzZXRUb1BvcyhtYXRjaC5pbmRleCksXG4gICAgICBoZWFkOiBlZGl0b3Iub2Zmc2V0VG9Qb3MobWF0Y2guaW5kZXggKyBzZWFyY2hUZXh0Lmxlbmd0aCksXG4gICAgfSk7XG4gIH1cbiAgcmV0dXJuIG1hdGNoUG9zaXRpb25zO1xufTtcblxuZXhwb3J0IGNvbnN0IHRvVGl0bGVDYXNlID0gKHNlbGVjdGVkVGV4dDogc3RyaW5nKSA9PiB7XG4gIC8vIHVzZSBjYXB0dXJlIGdyb3VwIHRvIGpvaW4gd2l0aCB0aGUgc2FtZSBzZXBhcmF0b3IgdXNlZCB0byBzcGxpdFxuICByZXR1cm4gc2VsZWN0ZWRUZXh0XG4gICAgLnNwbGl0KC8oXFxzKykvKVxuICAgIC5tYXAoKHdvcmQsIGluZGV4LCBhbGxXb3JkcykgPT4ge1xuICAgICAgaWYgKFxuICAgICAgICBpbmRleCA+IDAgJiZcbiAgICAgICAgaW5kZXggPCBhbGxXb3Jkcy5sZW5ndGggLSAxICYmXG4gICAgICAgIExPV0VSQ0FTRV9BUlRJQ0xFUy5pbmNsdWRlcyh3b3JkLnRvTG93ZXJDYXNlKCkpXG4gICAgICApIHtcbiAgICAgICAgcmV0dXJuIHdvcmQudG9Mb3dlckNhc2UoKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB3b3JkLmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsgd29yZC5zdWJzdHJpbmcoMSkudG9Mb3dlckNhc2UoKTtcbiAgICB9KVxuICAgIC5qb2luKCcnKTtcbn07XG5cbmV4cG9ydCBjb25zdCBnZXROZXh0Q2FzZSA9IChzZWxlY3RlZFRleHQ6IHN0cmluZyk6IHN0cmluZyA9PiB7XG4gIGNvbnN0IHRleHRVcHBlciA9IHNlbGVjdGVkVGV4dC50b1VwcGVyQ2FzZSgpO1xuICBjb25zdCB0ZXh0TG93ZXIgPSBzZWxlY3RlZFRleHQudG9Mb3dlckNhc2UoKTtcbiAgY29uc3QgdGV4dFRpdGxlID0gdG9UaXRsZUNhc2Uoc2VsZWN0ZWRUZXh0KTtcblxuICBzd2l0Y2ggKHNlbGVjdGVkVGV4dCkge1xuICAgIGNhc2UgdGV4dFVwcGVyOiB7XG4gICAgICByZXR1cm4gdGV4dExvd2VyO1xuICAgIH1cbiAgICBjYXNlIHRleHRMb3dlcjoge1xuICAgICAgcmV0dXJuIHRleHRUaXRsZTtcbiAgICB9XG4gICAgY2FzZSB0ZXh0VGl0bGU6IHtcbiAgICAgIHJldHVybiB0ZXh0VXBwZXI7XG4gICAgfVxuICAgIGRlZmF1bHQ6IHtcbiAgICAgIHJldHVybiB0ZXh0VXBwZXI7XG4gICAgfVxuICB9XG59O1xuXG4vKipcbiAqIENoZWNrcyBpZiBhbiBpbnB1dCBzdHJpbmcgaXMgbnVtZXJpYy5cbiAqXG4gKiBBZGFwdGVkIGZyb20gaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9hLzYwNTQ4MTE5XG4gKi9cbmV4cG9ydCBjb25zdCBpc051bWVyaWMgPSAoaW5wdXQ6IHN0cmluZykgPT4gaW5wdXQubGVuZ3RoID4gMCAmJiAhaXNOYU4oK2lucHV0KTtcblxuLyoqXG4gKiBEZXRlcm1pbmVzIHRoZSBuZXh0IG1hcmtkb3duIGxpc3QgY2hhcmFjdGVyIHByZWZpeCBmb3IgYSBnaXZlbiBsaW5lLlxuICpcbiAqIElmIGl0J3MgYW4gb3JkZXJlZCBsaXN0IGFuZCBkaXJlY3Rpb24gaXMgYGFmdGVyYCwgdGhlIHByZWZpeCB3aWxsIGJlXG4gKiBpbmNyZW1lbnRlZCBieSAxLlxuICpcbiAqIElmIGl0J3MgYSBjaGVja2xpc3QsIHRoZSBuZXdseSBpbnNlcnRlZCBjaGVja2JveCB3aWxsIGFsd2F5cyBiZSB1bnRpY2tlZC5cbiAqXG4gKiBJZiB0aGUgY3VycmVudCBsaXN0IGl0ZW0gaXMgZW1wdHksIHRoaXMgd2lsbCBiZSBpbmRpY2F0ZWQgYnkgYSBgbnVsbGAgcHJlZml4LlxuICovXG5leHBvcnQgY29uc3QgZ2V0TmV4dExpc3RQcmVmaXggPSAoXG4gIHRleHQ6IHN0cmluZyxcbiAgZGlyZWN0aW9uOiAnYmVmb3JlJyB8ICdhZnRlcicsXG4pOiBzdHJpbmcgfCBudWxsID0+IHtcbiAgY29uc3QgbGlzdENoYXJzID0gdGV4dC5tYXRjaChMSVNUX0NIQVJBQ1RFUl9SRUdFWCk7XG4gIGlmIChsaXN0Q2hhcnMgJiYgbGlzdENoYXJzLmxlbmd0aCA+IDApIHtcbiAgICBsZXQgcHJlZml4ID0gbGlzdENoYXJzWzBdLnRyaW1TdGFydCgpO1xuICAgIGNvbnN0IGlzRW1wdHlMaXN0SXRlbSA9IHByZWZpeCA9PT0gbGlzdENoYXJzLmlucHV0LnRyaW1TdGFydCgpO1xuICAgIGlmIChpc0VtcHR5TGlzdEl0ZW0pIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBpZiAoaXNOdW1lcmljKHByZWZpeCkgJiYgZGlyZWN0aW9uID09PSAnYWZ0ZXInKSB7XG4gICAgICBwcmVmaXggPSArcHJlZml4ICsgMSArICcuICc7XG4gICAgfVxuICAgIGlmIChwcmVmaXguc3RhcnRzV2l0aCgnLSBbJykgJiYgIXByZWZpeC5pbmNsdWRlcygnWyBdJykpIHtcbiAgICAgIHByZWZpeCA9ICctIFsgXSAnO1xuICAgIH1cbiAgICByZXR1cm4gcHJlZml4O1xuICB9XG4gIHJldHVybiAnJztcbn07XG5cbmV4cG9ydCBjb25zdCBmb3JtYXRSZW1haW5pbmdMaXN0UHJlZml4ZXMgPSAoXG4gIGVkaXRvcjogRWRpdG9yLFxuICBmcm9tTGluZTogbnVtYmVyLFxuICBpbmRlbnRhdGlvbjogc3RyaW5nLFxuKSA9PiB7XG4gIGNvbnN0IGNoYW5nZXM6IEVkaXRvckNoYW5nZVtdID0gW107XG5cbiAgZm9yIChsZXQgaSA9IGZyb21MaW5lOyBpIDwgZWRpdG9yLmxpbmVDb3VudCgpOyBpKyspIHtcbiAgICBjb25zdCBjb250ZW50c09mQ3VycmVudExpbmUgPSBlZGl0b3IuZ2V0TGluZShpKTtcbiAgICAvLyBPbmx5IHByZWZpeGVzIGF0IHRoZSBzYW1lIGluZGVudGF0aW9uIGxldmVsIHNob3VsZCBiZSB1cGRhdGVkXG4gICAgY29uc3QgbGlzdFByZWZpeFJlZ2V4ID0gbmV3IFJlZ0V4cChgXiR7aW5kZW50YXRpb259XFxcXGQrXFxcXC5gKTtcbiAgICBjb25zdCBsaW5lU3RhcnRzV2l0aE51bWJlclByZWZpeCA9IGxpc3RQcmVmaXhSZWdleC50ZXN0KFxuICAgICAgY29udGVudHNPZkN1cnJlbnRMaW5lLFxuICAgICk7XG4gICAgaWYgKCFsaW5lU3RhcnRzV2l0aE51bWJlclByZWZpeCkge1xuICAgICAgYnJlYWs7XG4gICAgfVxuICAgIGNvbnN0IHJlcGxhY2VtZW50Q29udGVudCA9IGNvbnRlbnRzT2ZDdXJyZW50TGluZS5yZXBsYWNlKFxuICAgICAgL1xcZCtcXC4vLFxuICAgICAgKG1hdGNoKSA9PiArbWF0Y2ggKyAxICsgJy4nLFxuICAgICk7XG4gICAgY2hhbmdlcy5wdXNoKHtcbiAgICAgIGZyb206IHsgbGluZTogaSwgY2g6IDAgfSxcbiAgICAgIHRvOiB7IGxpbmU6IGksIGNoOiBjb250ZW50c09mQ3VycmVudExpbmUubGVuZ3RoIH0sXG4gICAgICB0ZXh0OiByZXBsYWNlbWVudENvbnRlbnQsXG4gICAgfSk7XG4gIH1cblxuICBpZiAoY2hhbmdlcy5sZW5ndGggPiAwKSB7XG4gICAgZWRpdG9yLnRyYW5zYWN0aW9uKHsgY2hhbmdlcyB9KTtcbiAgfVxufTtcblxudHlwZSBWYXVsdENvbmZpZ1NldHRpbmcgPSAnc2hvd0xpbmVOdW1iZXInIHwgJ3VzZVRhYic7XG5cbmV4cG9ydCBjb25zdCB0b2dnbGVWYXVsdENvbmZpZyA9IChhcHA6IEFwcCwgc2V0dGluZzogVmF1bHRDb25maWdTZXR0aW5nKSA9PiB7XG4gIC8vIEB0cy1leHBlY3QtZXJyb3IgLSBnZXRDb25maWcgaXMgbm90IGluIHRoZSBwdWJsaWMgQVBJXG4gIGNvbnN0IHZhbHVlID0gYXBwLnZhdWx0LmdldENvbmZpZyhzZXR0aW5nKTtcbiAgc2V0VmF1bHRDb25maWcoYXBwLCBzZXR0aW5nLCAhdmFsdWUpO1xufTtcblxuZXhwb3J0IGNvbnN0IHNldFZhdWx0Q29uZmlnID0gKFxuICBhcHA6IEFwcCxcbiAgc2V0dGluZzogVmF1bHRDb25maWdTZXR0aW5nLFxuICB2YWx1ZTogYm9vbGVhbixcbikgPT4ge1xuICAvLyBAdHMtZXhwZWN0LWVycm9yIC0gc2V0Q29uZmlnIGlzIG5vdCBpbiB0aGUgcHVibGljIEFQSVxuICBhcHAudmF1bHQuc2V0Q29uZmlnKHNldHRpbmcsIHZhbHVlKTtcbn07XG4iLCAiaW1wb3J0IHR5cGUge1xuICBBcHAsXG4gIEVkaXRvcixcbiAgRWRpdG9yQ2hhbmdlLFxuICBFZGl0b3JQb3NpdGlvbixcbiAgRWRpdG9yU2VsZWN0aW9uLFxufSBmcm9tICdvYnNpZGlhbic7XG5pbXBvcnQge1xuICBDQVNFLFxuICBTRUFSQ0hfRElSRUNUSU9OLFxuICBNQVRDSElOR19CUkFDS0VUUyxcbiAgTUFUQ0hJTkdfUVVPVEVTLFxuICBNQVRDSElOR19RVU9URVNfQlJBQ0tFVFMsXG4gIE1hdGNoaW5nQ2hhcmFjdGVyTWFwLFxuICBDT0RFX0VESVRPUixcbiAgTElTVF9DSEFSQUNURVJfUkVHRVgsXG59IGZyb20gJy4vY29uc3RhbnRzJztcbmltcG9ydCB7IFNldHRpbmdzU3RhdGUgfSBmcm9tICcuL3N0YXRlJztcbmltcG9ydCB7XG4gIENoZWNrQ2hhcmFjdGVyLFxuICBFZGl0b3JBY3Rpb25DYWxsYmFja05ld0FyZ3MsXG4gIGZpbmRBbGxNYXRjaFBvc2l0aW9ucyxcbiAgZmluZE5leHRNYXRjaFBvc2l0aW9uLFxuICBmaW5kUG9zT2ZOZXh0Q2hhcmFjdGVyLFxuICBmb3JtYXRSZW1haW5pbmdMaXN0UHJlZml4ZXMsXG4gIGdldExlYWRpbmdXaGl0ZXNwYWNlLFxuICBnZXRMaW5lRW5kUG9zLFxuICBnZXRMaW5lU3RhcnRQb3MsXG4gIGdldE5leHRDYXNlLFxuICB0b1RpdGxlQ2FzZSxcbiAgZ2V0U2VsZWN0aW9uQm91bmRhcmllcyxcbiAgd29yZFJhbmdlQXRQb3MsXG4gIGdldFNlYXJjaFRleHQsXG4gIGdldE5leHRMaXN0UHJlZml4LFxuICBpc051bWVyaWMsXG59IGZyb20gJy4vdXRpbHMnO1xuXG5leHBvcnQgY29uc3QgaW5zZXJ0TGluZUFib3ZlID0gKFxuICBlZGl0b3I6IEVkaXRvcixcbiAgc2VsZWN0aW9uOiBFZGl0b3JTZWxlY3Rpb24sXG4gIGFyZ3M6IEVkaXRvckFjdGlvbkNhbGxiYWNrTmV3QXJncyxcbikgPT4ge1xuICBjb25zdCB7IGxpbmUgfSA9IHNlbGVjdGlvbi5oZWFkO1xuICBjb25zdCBzdGFydE9mQ3VycmVudExpbmUgPSBnZXRMaW5lU3RhcnRQb3MobGluZSk7XG5cbiAgY29uc3QgY29udGVudHNPZkN1cnJlbnRMaW5lID0gZWRpdG9yLmdldExpbmUobGluZSk7XG4gIGNvbnN0IGluZGVudGF0aW9uID0gZ2V0TGVhZGluZ1doaXRlc3BhY2UoY29udGVudHNPZkN1cnJlbnRMaW5lKTtcblxuICBsZXQgbGlzdFByZWZpeCA9ICcnO1xuICBpZiAoXG4gICAgU2V0dGluZ3NTdGF0ZS5hdXRvSW5zZXJ0TGlzdFByZWZpeCAmJlxuICAgIGxpbmUgPiAwICYmXG4gICAgLy8gSWYgaW5zaWRlIGEgbGlzdCwgb25seSBpbnNlcnQgcHJlZml4IGlmIHdpdGhpbiB0aGUgc2FtZSBsaXN0XG4gICAgZWRpdG9yLmdldExpbmUobGluZSAtIDEpLnRyaW0oKS5sZW5ndGggPiAwXG4gICkge1xuICAgIGxpc3RQcmVmaXggPSBnZXROZXh0TGlzdFByZWZpeChjb250ZW50c09mQ3VycmVudExpbmUsICdiZWZvcmUnKTtcbiAgICBpZiAoaXNOdW1lcmljKGxpc3RQcmVmaXgpKSB7XG4gICAgICBmb3JtYXRSZW1haW5pbmdMaXN0UHJlZml4ZXMoZWRpdG9yLCBsaW5lLCBpbmRlbnRhdGlvbik7XG4gICAgfVxuICB9XG5cbiAgY29uc3QgY2hhbmdlczogRWRpdG9yQ2hhbmdlW10gPSBbXG4gICAgeyBmcm9tOiBzdGFydE9mQ3VycmVudExpbmUsIHRleHQ6IGluZGVudGF0aW9uICsgbGlzdFByZWZpeCArICdcXG4nIH0sXG4gIF07XG4gIGNvbnN0IG5ld1NlbGVjdGlvbiA9IHtcbiAgICBmcm9tOiB7XG4gICAgICAuLi5zdGFydE9mQ3VycmVudExpbmUsXG4gICAgICAvLyBPZmZzZXQgYnkgaXRlcmF0aW9uXG4gICAgICBsaW5lOiBzdGFydE9mQ3VycmVudExpbmUubGluZSArIGFyZ3MuaXRlcmF0aW9uLFxuICAgICAgY2g6IGluZGVudGF0aW9uLmxlbmd0aCArIGxpc3RQcmVmaXgubGVuZ3RoLFxuICAgIH0sXG4gIH07XG4gIHJldHVybiB7XG4gICAgY2hhbmdlcyxcbiAgICBuZXdTZWxlY3Rpb24sXG4gIH07XG59O1xuXG5leHBvcnQgY29uc3QgaW5zZXJ0TGluZUJlbG93ID0gKFxuICBlZGl0b3I6IEVkaXRvcixcbiAgc2VsZWN0aW9uOiBFZGl0b3JTZWxlY3Rpb24sXG4gIGFyZ3M6IEVkaXRvckFjdGlvbkNhbGxiYWNrTmV3QXJncyxcbikgPT4ge1xuICBjb25zdCB7IGxpbmUgfSA9IHNlbGVjdGlvbi5oZWFkO1xuICBjb25zdCBzdGFydE9mQ3VycmVudExpbmUgPSBnZXRMaW5lU3RhcnRQb3MobGluZSk7XG4gIGNvbnN0IGVuZE9mQ3VycmVudExpbmUgPSBnZXRMaW5lRW5kUG9zKGxpbmUsIGVkaXRvcik7XG5cbiAgY29uc3QgY29udGVudHNPZkN1cnJlbnRMaW5lID0gZWRpdG9yLmdldExpbmUobGluZSk7XG4gIGNvbnN0IGluZGVudGF0aW9uID0gZ2V0TGVhZGluZ1doaXRlc3BhY2UoY29udGVudHNPZkN1cnJlbnRMaW5lKTtcblxuICBsZXQgbGlzdFByZWZpeCA9ICcnO1xuICBpZiAoU2V0dGluZ3NTdGF0ZS5hdXRvSW5zZXJ0TGlzdFByZWZpeCkge1xuICAgIGxpc3RQcmVmaXggPSBnZXROZXh0TGlzdFByZWZpeChjb250ZW50c09mQ3VycmVudExpbmUsICdhZnRlcicpO1xuXG4gICAgLy8gUGVyZm9ybWluZyB0aGlzIGFjdGlvbiBvbiBhbiBlbXB0eSBsaXN0IGl0ZW0gc2hvdWxkIGRlbGV0ZSBpdFxuICAgIGlmIChsaXN0UHJlZml4ID09PSBudWxsKSB7XG4gICAgICBjb25zdCBjaGFuZ2VzOiBFZGl0b3JDaGFuZ2VbXSA9IFtcbiAgICAgICAgeyBmcm9tOiBzdGFydE9mQ3VycmVudExpbmUsIHRvOiBlbmRPZkN1cnJlbnRMaW5lLCB0ZXh0OiAnJyB9LFxuICAgICAgXTtcbiAgICAgIGNvbnN0IG5ld1NlbGVjdGlvbiA9IHtcbiAgICAgICAgZnJvbToge1xuICAgICAgICAgIGxpbmUsXG4gICAgICAgICAgY2g6IDAsXG4gICAgICAgIH0sXG4gICAgICB9O1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY2hhbmdlcyxcbiAgICAgICAgbmV3U2VsZWN0aW9uLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICBpZiAoaXNOdW1lcmljKGxpc3RQcmVmaXgpKSB7XG4gICAgICBmb3JtYXRSZW1haW5pbmdMaXN0UHJlZml4ZXMoZWRpdG9yLCBsaW5lICsgMSwgaW5kZW50YXRpb24pO1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IGNoYW5nZXM6IEVkaXRvckNoYW5nZVtdID0gW1xuICAgIHsgZnJvbTogZW5kT2ZDdXJyZW50TGluZSwgdGV4dDogJ1xcbicgKyBpbmRlbnRhdGlvbiArIGxpc3RQcmVmaXggfSxcbiAgXTtcbiAgY29uc3QgbmV3U2VsZWN0aW9uID0ge1xuICAgIGZyb206IHtcbiAgICAgIC8vIE9mZnNldCBieSBpdGVyYXRpb25cbiAgICAgIGxpbmU6IGxpbmUgKyAxICsgYXJncy5pdGVyYXRpb24sXG4gICAgICBjaDogaW5kZW50YXRpb24ubGVuZ3RoICsgbGlzdFByZWZpeC5sZW5ndGgsXG4gICAgfSxcbiAgfTtcbiAgcmV0dXJuIHtcbiAgICBjaGFuZ2VzLFxuICAgIG5ld1NlbGVjdGlvbixcbiAgfTtcbn07XG5cbi8vIE5vdGU6IGRvbid0IHVzZSB0aGUgYnVpbHQtaW4gZXhlYyBtZXRob2QgZm9yICdkZWxldGVMaW5lJyBhcyB0aGVyZSBpcyBhIGJ1Z1xuLy8gd2hlcmUgcnVubmluZyBpdCBvbiBhIGxpbmUgdGhhdCBpcyBsb25nIGVub3VnaCB0byBiZSB3cmFwcGVkIHdpbGwgZm9jdXMgb25cbi8vIHRoZSBwcmV2aW91cyBsaW5lIGluc3RlYWQgb2YgdGhlIG5leHQgbGluZSBhZnRlciBkZWxldGlvblxubGV0IG51bUxpbmVzRGVsZXRlZCA9IDA7XG5leHBvcnQgY29uc3QgZGVsZXRlTGluZSA9IChcbiAgZWRpdG9yOiBFZGl0b3IsXG4gIHNlbGVjdGlvbjogRWRpdG9yU2VsZWN0aW9uLFxuICBhcmdzOiBFZGl0b3JBY3Rpb25DYWxsYmFja05ld0FyZ3MsXG4pID0+IHtcbiAgY29uc3QgeyBmcm9tLCB0bywgaGFzVHJhaWxpbmdOZXdsaW5lIH0gPSBnZXRTZWxlY3Rpb25Cb3VuZGFyaWVzKHNlbGVjdGlvbik7XG5cbiAgaWYgKHRvLmxpbmUgPT09IGVkaXRvci5sYXN0TGluZSgpKSB7XG4gICAgLy8gVGhlcmUgaXMgbm8gJ25leHQgbGluZScgd2hlbiBjdXJzb3IgaXMgb24gdGhlIGxhc3QgbGluZVxuICAgIGNvbnN0IHByZXZpb3VzTGluZSA9IE1hdGgubWF4KDAsIGZyb20ubGluZSAtIDEpO1xuICAgIGNvbnN0IGVuZE9mUHJldmlvdXNMaW5lID0gZ2V0TGluZUVuZFBvcyhwcmV2aW91c0xpbmUsIGVkaXRvcik7XG4gICAgY29uc3QgY2hhbmdlczogRWRpdG9yQ2hhbmdlW10gPSBbXG4gICAgICB7XG4gICAgICAgIGZyb206IGZyb20ubGluZSA9PT0gMCA/IGdldExpbmVTdGFydFBvcygwKSA6IGVuZE9mUHJldmlvdXNMaW5lLFxuICAgICAgICB0bzpcbiAgICAgICAgICAvLyBFeGNsdWRlIGxpbmUgc3RhcnRpbmcgYXQgdHJhaWxpbmcgbmV3bGluZSBhdCBlbmQgb2YgZG9jdW1lbnQgZnJvbSBiZWluZyBkZWxldGVkXG4gICAgICAgICAgdG8uY2ggPT09IDBcbiAgICAgICAgICAgID8gZ2V0TGluZVN0YXJ0UG9zKHRvLmxpbmUpXG4gICAgICAgICAgICA6IGdldExpbmVFbmRQb3ModG8ubGluZSwgZWRpdG9yKSxcbiAgICAgICAgdGV4dDogJycsXG4gICAgICB9LFxuICAgIF07XG4gICAgY29uc3QgbmV3U2VsZWN0aW9uID0ge1xuICAgICAgZnJvbToge1xuICAgICAgICBsaW5lOiBwcmV2aW91c0xpbmUsXG4gICAgICAgIGNoOiBNYXRoLm1pbihmcm9tLmNoLCBlbmRPZlByZXZpb3VzTGluZS5jaCksXG4gICAgICB9LFxuICAgIH07XG4gICAgcmV0dXJuIHtcbiAgICAgIGNoYW5nZXMsXG4gICAgICBuZXdTZWxlY3Rpb24sXG4gICAgfTtcbiAgfVxuXG4gIC8vIFJlc2V0IG9mZnNldCBhdCB0aGUgc3RhcnQgb2YgYSBuZXcgYnVsayBkZWxldGUgb3BlcmF0aW9uXG4gIGlmIChhcmdzLml0ZXJhdGlvbiA9PT0gMCkge1xuICAgIG51bUxpbmVzRGVsZXRlZCA9IDA7XG4gIH1cbiAgLy8gRXhjbHVkZSBsaW5lIHN0YXJ0aW5nIGF0IHRyYWlsaW5nIG5ld2xpbmUgZnJvbSBiZWluZyBkZWxldGVkXG4gIGNvbnN0IHRvTGluZSA9IGhhc1RyYWlsaW5nTmV3bGluZSA/IHRvLmxpbmUgLSAxIDogdG8ubGluZTtcbiAgY29uc3QgZW5kT2ZOZXh0TGluZSA9IGdldExpbmVFbmRQb3ModG9MaW5lICsgMSwgZWRpdG9yKTtcbiAgY29uc3QgY2hhbmdlczogRWRpdG9yQ2hhbmdlW10gPSBbXG4gICAge1xuICAgICAgZnJvbTogZ2V0TGluZVN0YXJ0UG9zKGZyb20ubGluZSksXG4gICAgICB0bzogZ2V0TGluZVN0YXJ0UG9zKHRvTGluZSArIDEpLFxuICAgICAgdGV4dDogJycsXG4gICAgfSxcbiAgXTtcbiAgY29uc3QgbmV3U2VsZWN0aW9uID0ge1xuICAgIGZyb206IHtcbiAgICAgIC8vIE9mZnNldCBieSB0aGUgbnVtYmVyIG9mIGxpbmVzIGRlbGV0ZWQgaW4gYWxsIHByZXZpb3VzIGl0ZXJhdGlvbnNcbiAgICAgIGxpbmU6IGZyb20ubGluZSAtIG51bUxpbmVzRGVsZXRlZCxcbiAgICAgIGNoOiBNYXRoLm1pbih0by5jaCwgZW5kT2ZOZXh0TGluZS5jaCksXG4gICAgfSxcbiAgfTtcbiAgLy8gVGhpcyBuZWVkcyB0byBiZSBjYWxjdWxhdGVkIGFmdGVyIHNldHRpbmcgdGhlIG5ldyBzZWxlY3Rpb24gYXMgaXQgb25seVxuICAvLyBhcHBsaWVzIGZvciBzdWJzZXF1ZW50IGl0ZXJhdGlvbnNcbiAgbnVtTGluZXNEZWxldGVkICs9IHRvTGluZSAtIGZyb20ubGluZSArIDE7XG4gIHJldHVybiB7XG4gICAgY2hhbmdlcyxcbiAgICBuZXdTZWxlY3Rpb24sXG4gIH07XG59O1xuXG5leHBvcnQgY29uc3QgZGVsZXRlVG9TdGFydE9mTGluZSA9IChcbiAgZWRpdG9yOiBFZGl0b3IsXG4gIHNlbGVjdGlvbjogRWRpdG9yU2VsZWN0aW9uLFxuKSA9PiB7XG4gIGNvbnN0IHBvcyA9IHNlbGVjdGlvbi5oZWFkO1xuICBsZXQgc3RhcnRQb3MgPSBnZXRMaW5lU3RhcnRQb3MocG9zLmxpbmUpO1xuXG4gIGlmIChwb3MubGluZSA9PT0gMCAmJiBwb3MuY2ggPT09IDApIHtcbiAgICAvLyBXZSdyZSBhdCB0aGUgc3RhcnQgb2YgdGhlIGRvY3VtZW50IHNvIGRvIG5vdGhpbmdcbiAgICByZXR1cm4gc2VsZWN0aW9uO1xuICB9XG5cbiAgaWYgKHBvcy5saW5lID09PSBzdGFydFBvcy5saW5lICYmIHBvcy5jaCA9PT0gc3RhcnRQb3MuY2gpIHtcbiAgICAvLyBXZSdyZSBhdCB0aGUgc3RhcnQgb2YgdGhlIGxpbmUgc28gZGVsZXRlIHRoZSBwcmVjZWRpbmcgbmV3bGluZVxuICAgIHN0YXJ0UG9zID0gZ2V0TGluZUVuZFBvcyhwb3MubGluZSAtIDEsIGVkaXRvcik7XG4gIH1cblxuICBlZGl0b3IucmVwbGFjZVJhbmdlKCcnLCBzdGFydFBvcywgcG9zKTtcbiAgcmV0dXJuIHtcbiAgICBhbmNob3I6IHN0YXJ0UG9zLFxuICB9O1xufTtcblxuZXhwb3J0IGNvbnN0IGRlbGV0ZVRvRW5kT2ZMaW5lID0gKFxuICBlZGl0b3I6IEVkaXRvcixcbiAgc2VsZWN0aW9uOiBFZGl0b3JTZWxlY3Rpb24sXG4pID0+IHtcbiAgY29uc3QgcG9zID0gc2VsZWN0aW9uLmhlYWQ7XG4gIGxldCBlbmRQb3MgPSBnZXRMaW5lRW5kUG9zKHBvcy5saW5lLCBlZGl0b3IpO1xuXG4gIGlmIChwb3MubGluZSA9PT0gZW5kUG9zLmxpbmUgJiYgcG9zLmNoID09PSBlbmRQb3MuY2gpIHtcbiAgICAvLyBXZSdyZSBhdCB0aGUgZW5kIG9mIHRoZSBsaW5lIHNvIGRlbGV0ZSBqdXN0IHRoZSBuZXdsaW5lXG4gICAgZW5kUG9zID0gZ2V0TGluZVN0YXJ0UG9zKHBvcy5saW5lICsgMSk7XG4gIH1cblxuICBlZGl0b3IucmVwbGFjZVJhbmdlKCcnLCBwb3MsIGVuZFBvcyk7XG4gIHJldHVybiB7XG4gICAgYW5jaG9yOiBwb3MsXG4gIH07XG59O1xuXG5leHBvcnQgY29uc3Qgam9pbkxpbmVzID0gKGVkaXRvcjogRWRpdG9yLCBzZWxlY3Rpb246IEVkaXRvclNlbGVjdGlvbikgPT4ge1xuICBjb25zdCB7IGZyb20sIHRvIH0gPSBnZXRTZWxlY3Rpb25Cb3VuZGFyaWVzKHNlbGVjdGlvbik7XG4gIGNvbnN0IHsgbGluZSB9ID0gZnJvbTtcblxuICBsZXQgZW5kT2ZDdXJyZW50TGluZSA9IGdldExpbmVFbmRQb3MobGluZSwgZWRpdG9yKTtcbiAgY29uc3Qgam9pblJhbmdlTGltaXQgPSBNYXRoLm1heCh0by5saW5lIC0gbGluZSwgMSk7XG4gIGNvbnN0IHNlbGVjdGlvbkxlbmd0aCA9IGVkaXRvci5wb3NUb09mZnNldCh0bykgLSBlZGl0b3IucG9zVG9PZmZzZXQoZnJvbSk7XG4gIGxldCB0cmltbWVkQ2hhcnMgPSAnJztcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGpvaW5SYW5nZUxpbWl0OyBpKyspIHtcbiAgICBpZiAobGluZSA9PT0gZWRpdG9yLmxpbmVDb3VudCgpIC0gMSkge1xuICAgICAgYnJlYWs7XG4gICAgfVxuICAgIGVuZE9mQ3VycmVudExpbmUgPSBnZXRMaW5lRW5kUG9zKGxpbmUsIGVkaXRvcik7XG4gICAgY29uc3QgZW5kT2ZOZXh0TGluZSA9IGdldExpbmVFbmRQb3MobGluZSArIDEsIGVkaXRvcik7XG4gICAgY29uc3QgY29udGVudHNPZkN1cnJlbnRMaW5lID0gZWRpdG9yLmdldExpbmUobGluZSk7XG4gICAgY29uc3QgY29udGVudHNPZk5leHRMaW5lID0gZWRpdG9yLmdldExpbmUobGluZSArIDEpO1xuXG4gICAgY29uc3QgY2hhcnNUb1RyaW0gPSBjb250ZW50c09mTmV4dExpbmUubWF0Y2goTElTVF9DSEFSQUNURVJfUkVHRVgpID8/IFtdO1xuICAgIHRyaW1tZWRDaGFycyArPSBjaGFyc1RvVHJpbVswXSA/PyAnJztcblxuICAgIGNvbnN0IG5ld0NvbnRlbnRzT2ZOZXh0TGluZSA9IGNvbnRlbnRzT2ZOZXh0TGluZS5yZXBsYWNlKFxuICAgICAgTElTVF9DSEFSQUNURVJfUkVHRVgsXG4gICAgICAnJyxcbiAgICApO1xuICAgIGlmIChcbiAgICAgIG5ld0NvbnRlbnRzT2ZOZXh0TGluZS5sZW5ndGggPiAwICYmXG4gICAgICBjb250ZW50c09mQ3VycmVudExpbmUuY2hhckF0KGVuZE9mQ3VycmVudExpbmUuY2ggLSAxKSAhPT0gJyAnXG4gICAgKSB7XG4gICAgICBlZGl0b3IucmVwbGFjZVJhbmdlKFxuICAgICAgICAnICcgKyBuZXdDb250ZW50c09mTmV4dExpbmUsXG4gICAgICAgIGVuZE9mQ3VycmVudExpbmUsXG4gICAgICAgIGVuZE9mTmV4dExpbmUsXG4gICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICBlZGl0b3IucmVwbGFjZVJhbmdlKFxuICAgICAgICBuZXdDb250ZW50c09mTmV4dExpbmUsXG4gICAgICAgIGVuZE9mQ3VycmVudExpbmUsXG4gICAgICAgIGVuZE9mTmV4dExpbmUsXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIGlmIChzZWxlY3Rpb25MZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4ge1xuICAgICAgYW5jaG9yOiBlbmRPZkN1cnJlbnRMaW5lLFxuICAgIH07XG4gIH1cbiAgcmV0dXJuIHtcbiAgICBhbmNob3I6IGZyb20sXG4gICAgaGVhZDoge1xuICAgICAgbGluZTogZnJvbS5saW5lLFxuICAgICAgY2g6IGZyb20uY2ggKyBzZWxlY3Rpb25MZW5ndGggLSB0cmltbWVkQ2hhcnMubGVuZ3RoLFxuICAgIH0sXG4gIH07XG59O1xuXG5leHBvcnQgY29uc3QgY29weUxpbmUgPSAoXG4gIGVkaXRvcjogRWRpdG9yLFxuICBzZWxlY3Rpb246IEVkaXRvclNlbGVjdGlvbixcbiAgZGlyZWN0aW9uOiAndXAnIHwgJ2Rvd24nLFxuKSA9PiB7XG4gIGNvbnN0IHsgZnJvbSwgdG8sIGhhc1RyYWlsaW5nTmV3bGluZSB9ID0gZ2V0U2VsZWN0aW9uQm91bmRhcmllcyhzZWxlY3Rpb24pO1xuICBjb25zdCBmcm9tTGluZVN0YXJ0ID0gZ2V0TGluZVN0YXJ0UG9zKGZyb20ubGluZSk7XG4gIC8vIEV4Y2x1ZGUgbGluZSBzdGFydGluZyBhdCB0cmFpbGluZyBuZXdsaW5lIGZyb20gYmVpbmcgZHVwbGljYXRlZFxuICBjb25zdCB0b0xpbmUgPSBoYXNUcmFpbGluZ05ld2xpbmUgPyB0by5saW5lIC0gMSA6IHRvLmxpbmU7XG4gIGNvbnN0IHRvTGluZUVuZCA9IGdldExpbmVFbmRQb3ModG9MaW5lLCBlZGl0b3IpO1xuICBjb25zdCBjb250ZW50c09mU2VsZWN0ZWRMaW5lcyA9IGVkaXRvci5nZXRSYW5nZShmcm9tTGluZVN0YXJ0LCB0b0xpbmVFbmQpO1xuICBpZiAoZGlyZWN0aW9uID09PSAndXAnKSB7XG4gICAgZWRpdG9yLnJlcGxhY2VSYW5nZSgnXFxuJyArIGNvbnRlbnRzT2ZTZWxlY3RlZExpbmVzLCB0b0xpbmVFbmQpO1xuICAgIHJldHVybiBzZWxlY3Rpb247XG4gIH0gZWxzZSB7XG4gICAgZWRpdG9yLnJlcGxhY2VSYW5nZShjb250ZW50c09mU2VsZWN0ZWRMaW5lcyArICdcXG4nLCBmcm9tTGluZVN0YXJ0KTtcbiAgICAvLyBUaGlzIHVzZXMgYHRvLmxpbmVgIGluc3RlYWQgb2YgYHRvTGluZWAgdG8gYXZvaWQgYSBkb3VibGUgYWRqdXN0bWVudFxuICAgIGNvbnN0IGxpbmVzU2VsZWN0ZWQgPSB0by5saW5lIC0gZnJvbS5saW5lICsgMTtcbiAgICByZXR1cm4ge1xuICAgICAgYW5jaG9yOiB7IGxpbmU6IHRvTGluZSArIDEsIGNoOiBmcm9tLmNoIH0sXG4gICAgICBoZWFkOiB7IGxpbmU6IHRvTGluZSArIGxpbmVzU2VsZWN0ZWQsIGNoOiB0by5jaCB9LFxuICAgIH07XG4gIH1cbn07XG5cbi8qXG5Qcm9wZXJ0aWVzIHVzZWQgdG8gZGlzdGluZ3Vpc2ggYmV0d2VlbiBzZWxlY3Rpb25zIHRoYXQgYXJlIHByb2dyYW1tYXRpY1xuKGV4cGFuZGluZyBmcm9tIGEgY3Vyc29yIHNlbGVjdGlvbikgdnMuIG1hbnVhbCAodXNpbmcgYSBtb3VzZSAvIFNoaWZ0ICsgYXJyb3dcbmtleXMpLiBUaGlzIGNvbnRyb2xzIHRoZSBtYXRjaCBiZWhhdmlvdXIgZm9yIHNlbGVjdFdvcmRPck5leHRPY2N1cnJlbmNlLlxuKi9cbmxldCBpc01hbnVhbFNlbGVjdGlvbiA9IHRydWU7XG5leHBvcnQgY29uc3Qgc2V0SXNNYW51YWxTZWxlY3Rpb24gPSAodmFsdWU6IGJvb2xlYW4pID0+IHtcbiAgaXNNYW51YWxTZWxlY3Rpb24gPSB2YWx1ZTtcbn07XG5leHBvcnQgbGV0IGlzUHJvZ3JhbW1hdGljU2VsZWN0aW9uQ2hhbmdlID0gZmFsc2U7XG5leHBvcnQgY29uc3Qgc2V0SXNQcm9ncmFtbWF0aWNTZWxlY3Rpb25DaGFuZ2UgPSAodmFsdWU6IGJvb2xlYW4pID0+IHtcbiAgaXNQcm9ncmFtbWF0aWNTZWxlY3Rpb25DaGFuZ2UgPSB2YWx1ZTtcbn07XG5cbmV4cG9ydCBjb25zdCBzZWxlY3RXb3JkT3JOZXh0T2NjdXJyZW5jZSA9IChlZGl0b3I6IEVkaXRvcikgPT4ge1xuICBzZXRJc1Byb2dyYW1tYXRpY1NlbGVjdGlvbkNoYW5nZSh0cnVlKTtcbiAgY29uc3QgYWxsU2VsZWN0aW9ucyA9IGVkaXRvci5saXN0U2VsZWN0aW9ucygpO1xuICBjb25zdCB7IHNlYXJjaFRleHQsIHNpbmdsZVNlYXJjaFRleHQgfSA9IGdldFNlYXJjaFRleHQoe1xuICAgIGVkaXRvcixcbiAgICBhbGxTZWxlY3Rpb25zLFxuICAgIGF1dG9FeHBhbmQ6IGZhbHNlLFxuICB9KTtcblxuICBpZiAoc2VhcmNoVGV4dC5sZW5ndGggPiAwICYmIHNpbmdsZVNlYXJjaFRleHQpIHtcbiAgICBjb25zdCB7IGZyb206IGxhdGVzdE1hdGNoUG9zIH0gPSBnZXRTZWxlY3Rpb25Cb3VuZGFyaWVzKFxuICAgICAgYWxsU2VsZWN0aW9uc1thbGxTZWxlY3Rpb25zLmxlbmd0aCAtIDFdLFxuICAgICk7XG4gICAgY29uc3QgbmV4dE1hdGNoID0gZmluZE5leHRNYXRjaFBvc2l0aW9uKHtcbiAgICAgIGVkaXRvcixcbiAgICAgIGxhdGVzdE1hdGNoUG9zLFxuICAgICAgc2VhcmNoVGV4dCxcbiAgICAgIHNlYXJjaFdpdGhpbldvcmRzOiBpc01hbnVhbFNlbGVjdGlvbixcbiAgICAgIGRvY3VtZW50Q29udGVudDogZWRpdG9yLmdldFZhbHVlKCksXG4gICAgfSk7XG4gICAgY29uc3QgbmV3U2VsZWN0aW9ucyA9IG5leHRNYXRjaFxuICAgICAgPyBhbGxTZWxlY3Rpb25zLmNvbmNhdChuZXh0TWF0Y2gpXG4gICAgICA6IGFsbFNlbGVjdGlvbnM7XG4gICAgZWRpdG9yLnNldFNlbGVjdGlvbnMobmV3U2VsZWN0aW9ucyk7XG4gICAgY29uc3QgbGFzdFNlbGVjdGlvbiA9IG5ld1NlbGVjdGlvbnNbbmV3U2VsZWN0aW9ucy5sZW5ndGggLSAxXTtcbiAgICBlZGl0b3Iuc2Nyb2xsSW50b1ZpZXcoZ2V0U2VsZWN0aW9uQm91bmRhcmllcyhsYXN0U2VsZWN0aW9uKSk7XG4gIH0gZWxzZSB7XG4gICAgY29uc3QgbmV3U2VsZWN0aW9ucyA9IFtdO1xuICAgIGZvciAoY29uc3Qgc2VsZWN0aW9uIG9mIGFsbFNlbGVjdGlvbnMpIHtcbiAgICAgIGNvbnN0IHsgZnJvbSwgdG8gfSA9IGdldFNlbGVjdGlvbkJvdW5kYXJpZXMoc2VsZWN0aW9uKTtcbiAgICAgIC8vIERvbid0IG1vZGlmeSBleGlzdGluZyByYW5nZSBzZWxlY3Rpb25zXG4gICAgICBpZiAoZnJvbS5saW5lICE9PSB0by5saW5lIHx8IGZyb20uY2ggIT09IHRvLmNoKSB7XG4gICAgICAgIG5ld1NlbGVjdGlvbnMucHVzaChzZWxlY3Rpb24pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbmV3U2VsZWN0aW9ucy5wdXNoKHdvcmRSYW5nZUF0UG9zKGZyb20sIGVkaXRvci5nZXRMaW5lKGZyb20ubGluZSkpKTtcbiAgICAgICAgc2V0SXNNYW51YWxTZWxlY3Rpb24oZmFsc2UpO1xuICAgICAgfVxuICAgIH1cbiAgICBlZGl0b3Iuc2V0U2VsZWN0aW9ucyhuZXdTZWxlY3Rpb25zKTtcbiAgfVxufTtcblxuZXhwb3J0IGNvbnN0IHNlbGVjdEFsbE9jY3VycmVuY2VzID0gKGVkaXRvcjogRWRpdG9yKSA9PiB7XG4gIGNvbnN0IGFsbFNlbGVjdGlvbnMgPSBlZGl0b3IubGlzdFNlbGVjdGlvbnMoKTtcbiAgY29uc3QgeyBzZWFyY2hUZXh0LCBzaW5nbGVTZWFyY2hUZXh0IH0gPSBnZXRTZWFyY2hUZXh0KHtcbiAgICBlZGl0b3IsXG4gICAgYWxsU2VsZWN0aW9ucyxcbiAgICBhdXRvRXhwYW5kOiB0cnVlLFxuICB9KTtcbiAgaWYgKCFzaW5nbGVTZWFyY2hUZXh0KSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIGNvbnN0IG1hdGNoZXMgPSBmaW5kQWxsTWF0Y2hQb3NpdGlvbnMoe1xuICAgIGVkaXRvcixcbiAgICBzZWFyY2hUZXh0LFxuICAgIHNlYXJjaFdpdGhpbldvcmRzOiB0cnVlLFxuICAgIGRvY3VtZW50Q29udGVudDogZWRpdG9yLmdldFZhbHVlKCksXG4gIH0pO1xuICBlZGl0b3Iuc2V0U2VsZWN0aW9ucyhtYXRjaGVzKTtcbn07XG5cbmV4cG9ydCBjb25zdCBzZWxlY3RMaW5lID0gKF9lZGl0b3I6IEVkaXRvciwgc2VsZWN0aW9uOiBFZGl0b3JTZWxlY3Rpb24pID0+IHtcbiAgY29uc3QgeyBmcm9tLCB0byB9ID0gZ2V0U2VsZWN0aW9uQm91bmRhcmllcyhzZWxlY3Rpb24pO1xuICBjb25zdCBzdGFydE9mQ3VycmVudExpbmUgPSBnZXRMaW5lU3RhcnRQb3MoZnJvbS5saW5lKTtcbiAgLy8gaWYgYSBsaW5lIGlzIGFscmVhZHkgc2VsZWN0ZWQsIGV4cGFuZCB0aGUgc2VsZWN0aW9uIHRvIHRoZSBuZXh0IGxpbmVcbiAgY29uc3Qgc3RhcnRPZk5leHRMaW5lID0gZ2V0TGluZVN0YXJ0UG9zKHRvLmxpbmUgKyAxKTtcbiAgcmV0dXJuIHsgYW5jaG9yOiBzdGFydE9mQ3VycmVudExpbmUsIGhlYWQ6IHN0YXJ0T2ZOZXh0TGluZSB9O1xufTtcblxuZXhwb3J0IGNvbnN0IGFkZEN1cnNvcnNUb1NlbGVjdGlvbkVuZHMgPSAoXG4gIGVkaXRvcjogRWRpdG9yLFxuICBlbXVsYXRlOiBDT0RFX0VESVRPUiA9IENPREVfRURJVE9SLlZTQ09ERSxcbikgPT4ge1xuICAvLyBPbmx5IGFwcGx5IHRoZSBhY3Rpb24gaWYgdGhlcmUgaXMgZXhhY3RseSBvbmUgc2VsZWN0aW9uXG4gIGlmIChlZGl0b3IubGlzdFNlbGVjdGlvbnMoKS5sZW5ndGggIT09IDEpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgY29uc3Qgc2VsZWN0aW9uID0gZWRpdG9yLmxpc3RTZWxlY3Rpb25zKClbMF07XG4gIGNvbnN0IHsgZnJvbSwgdG8sIGhhc1RyYWlsaW5nTmV3bGluZSB9ID0gZ2V0U2VsZWN0aW9uQm91bmRhcmllcyhzZWxlY3Rpb24pO1xuICBjb25zdCBuZXdTZWxlY3Rpb25zID0gW107XG4gIC8vIEV4Y2x1ZGUgbGluZSBzdGFydGluZyBhdCB0cmFpbGluZyBuZXdsaW5lIGZyb20gaGF2aW5nIGN1cnNvciBhZGRlZFxuICBjb25zdCB0b0xpbmUgPSBoYXNUcmFpbGluZ05ld2xpbmUgPyB0by5saW5lIC0gMSA6IHRvLmxpbmU7XG4gIGZvciAobGV0IGxpbmUgPSBmcm9tLmxpbmU7IGxpbmUgPD0gdG9MaW5lOyBsaW5lKyspIHtcbiAgICBjb25zdCBoZWFkID0gbGluZSA9PT0gdG8ubGluZSA/IHRvIDogZ2V0TGluZUVuZFBvcyhsaW5lLCBlZGl0b3IpO1xuICAgIGxldCBhbmNob3I6IEVkaXRvclBvc2l0aW9uO1xuICAgIGlmIChlbXVsYXRlID09PSBDT0RFX0VESVRPUi5WU0NPREUpIHtcbiAgICAgIGFuY2hvciA9IGhlYWQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIGFuY2hvciA9IGxpbmUgPT09IGZyb20ubGluZSA/IGZyb20gOiBnZXRMaW5lU3RhcnRQb3MobGluZSk7XG4gICAgfVxuICAgIG5ld1NlbGVjdGlvbnMucHVzaCh7XG4gICAgICBhbmNob3IsXG4gICAgICBoZWFkLFxuICAgIH0pO1xuICB9XG4gIGVkaXRvci5zZXRTZWxlY3Rpb25zKG5ld1NlbGVjdGlvbnMpO1xufTtcblxuZXhwb3J0IGNvbnN0IGdvVG9MaW5lQm91bmRhcnkgPSAoXG4gIGVkaXRvcjogRWRpdG9yLFxuICBzZWxlY3Rpb246IEVkaXRvclNlbGVjdGlvbixcbiAgYm91bmRhcnk6ICdzdGFydCcgfCAnZW5kJyxcbikgPT4ge1xuICBjb25zdCB7IGZyb20sIHRvIH0gPSBnZXRTZWxlY3Rpb25Cb3VuZGFyaWVzKHNlbGVjdGlvbik7XG4gIGlmIChib3VuZGFyeSA9PT0gJ3N0YXJ0Jykge1xuICAgIHJldHVybiB7IGFuY2hvcjogZ2V0TGluZVN0YXJ0UG9zKGZyb20ubGluZSkgfTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4geyBhbmNob3I6IGdldExpbmVFbmRQb3ModG8ubGluZSwgZWRpdG9yKSB9O1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgbmF2aWdhdGVMaW5lID0gKFxuICBlZGl0b3I6IEVkaXRvcixcbiAgc2VsZWN0aW9uOiBFZGl0b3JTZWxlY3Rpb24sXG4gIHBvc2l0aW9uOiAnbmV4dCcgfCAncHJldicgfCAnZmlyc3QnIHwgJ2xhc3QnLFxuKSA9PiB7XG4gIGNvbnN0IHBvcyA9IHNlbGVjdGlvbi5oZWFkO1xuICBsZXQgbGluZTogbnVtYmVyO1xuICBsZXQgY2g6IG51bWJlcjtcblxuICBpZiAocG9zaXRpb24gPT09ICdwcmV2Jykge1xuICAgIGxpbmUgPSBNYXRoLm1heChwb3MubGluZSAtIDEsIDApO1xuICAgIGNvbnN0IGVuZE9mTGluZSA9IGdldExpbmVFbmRQb3MobGluZSwgZWRpdG9yKTtcbiAgICBjaCA9IE1hdGgubWluKHBvcy5jaCwgZW5kT2ZMaW5lLmNoKTtcbiAgfVxuICBpZiAocG9zaXRpb24gPT09ICduZXh0Jykge1xuICAgIGxpbmUgPSBNYXRoLm1pbihwb3MubGluZSArIDEsIGVkaXRvci5saW5lQ291bnQoKSAtIDEpO1xuICAgIGNvbnN0IGVuZE9mTGluZSA9IGdldExpbmVFbmRQb3MobGluZSwgZWRpdG9yKTtcbiAgICBjaCA9IE1hdGgubWluKHBvcy5jaCwgZW5kT2ZMaW5lLmNoKTtcbiAgfVxuICBpZiAocG9zaXRpb24gPT09ICdmaXJzdCcpIHtcbiAgICBsaW5lID0gMDtcbiAgICBjaCA9IDA7XG4gIH1cbiAgaWYgKHBvc2l0aW9uID09PSAnbGFzdCcpIHtcbiAgICBsaW5lID0gZWRpdG9yLmxpbmVDb3VudCgpIC0gMTtcbiAgICBjb25zdCBlbmRPZkxpbmUgPSBnZXRMaW5lRW5kUG9zKGxpbmUsIGVkaXRvcik7XG4gICAgY2ggPSBlbmRPZkxpbmUuY2g7XG4gIH1cblxuICByZXR1cm4geyBhbmNob3I6IHsgbGluZSwgY2ggfSB9O1xufTtcblxuZXhwb3J0IGNvbnN0IG1vdmVDdXJzb3IgPSAoXG4gIGVkaXRvcjogRWRpdG9yLFxuICBkaXJlY3Rpb246ICd1cCcgfCAnZG93bicgfCAnbGVmdCcgfCAncmlnaHQnLFxuKSA9PiB7XG4gIHN3aXRjaCAoZGlyZWN0aW9uKSB7XG4gICAgY2FzZSAndXAnOlxuICAgICAgZWRpdG9yLmV4ZWMoJ2dvVXAnKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ2Rvd24nOlxuICAgICAgZWRpdG9yLmV4ZWMoJ2dvRG93bicpO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnbGVmdCc6XG4gICAgICBlZGl0b3IuZXhlYygnZ29MZWZ0Jyk7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdyaWdodCc6XG4gICAgICBlZGl0b3IuZXhlYygnZ29SaWdodCcpO1xuICAgICAgYnJlYWs7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBzZWxlY3QxTGluZXNVcCA9IChcbiAgZWRpdG9yOiBFZGl0b3IsIFxuICBzZWxlY3Rpb246IEVkaXRvclNlbGVjdGlvblxuKSA9PiB7XG4gIGxldCBuZXdIZWFkOiBFZGl0b3JQb3NpdGlvbiA9IHtcbiAgICBsaW5lOiBzZWxlY3Rpb24uaGVhZC5saW5lIC0gMSxcbiAgICBjaDogc2VsZWN0aW9uLmhlYWQuY2hcbiAgfTtcblxuICAvLyBFbnN1cmUgdGhlIG5ldyBoZWFkIHBvc2l0aW9uIGlzIHdpdGhpbiB0aGUgYm91bmRzIG9mIHRoZSBsaW5lXG4gIGlmIChuZXdIZWFkLmxpbmUgPj0gMCkge1xuICAgIGNvbnN0IGxpbmVBYm92ZUxlbmd0aCA9IGVkaXRvci5nZXRMaW5lKG5ld0hlYWQubGluZSkubGVuZ3RoO1xuICAgIGlmIChuZXdIZWFkLmNoID4gbGluZUFib3ZlTGVuZ3RoKSB7XG4gICAgICBuZXdIZWFkLmNoID0gbGluZUFib3ZlTGVuZ3RoO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICAvLyBQcmV2ZW50IG1vdmluZyB0aGUgaGVhZCBhYm92ZSB0aGUgZmlyc3QgbGluZVxuICAgIG5ld0hlYWQubGluZSA9IDA7XG4gICAgbmV3SGVhZC5jaCA9IDA7XG4gIH1cblxuICByZXR1cm4geyBhbmNob3I6IHNlbGVjdGlvbi5hbmNob3IsIGhlYWQ6IG5ld0hlYWQgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBzZWxlY3QxTGluZXNEb3duID0gKFxuICBlZGl0b3I6IEVkaXRvciwgXG4gIHNlbGVjdGlvbjogRWRpdG9yU2VsZWN0aW9uXG4pID0+IHtcbiAgbGV0IG5ld0hlYWQ6IEVkaXRvclBvc2l0aW9uID0ge1xuICAgIGxpbmU6IHNlbGVjdGlvbi5oZWFkLmxpbmUgKyAxLFxuICAgIGNoOiBzZWxlY3Rpb24uaGVhZC5jaFxuICB9O1xuXG4gIC8vIEVuc3VyZSB0aGUgbmV3IGhlYWQgcG9zaXRpb24gaXMgd2l0aGluIHRoZSBib3VuZHMgb2YgdGhlIGxpbmVcbiAgaWYgKG5ld0hlYWQubGluZSA8IGVkaXRvci5saW5lQ291bnQoKSkge1xuICAgIGNvbnN0IGxpbmVCZWxvd0xlbmd0aCA9IGVkaXRvci5nZXRMaW5lKG5ld0hlYWQubGluZSkubGVuZ3RoO1xuICAgIGlmIChuZXdIZWFkLmNoID4gbGluZUJlbG93TGVuZ3RoKSB7XG4gICAgICBuZXdIZWFkLmNoID0gMDtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgLy8gUHJldmVudCBtb3ZpbmcgdGhlIGhlYWQgYmVsb3cgdGhlIGxhc3QgbGluZVxuICAgIG5ld0hlYWQubGluZSA9IGVkaXRvci5saW5lQ291bnQoKSAtIDE7XG4gICAgbmV3SGVhZC5jaCA9IGVkaXRvci5nZXRMaW5lKG5ld0hlYWQubGluZSkubGVuZ3RoO1xuICB9XG5cbiAgcmV0dXJuIHsgYW5jaG9yOiBzZWxlY3Rpb24uYW5jaG9yLCBoZWFkOiBuZXdIZWFkIH07XG59O1xuXG5leHBvcnQgY29uc3Qgc2VsZWN0MUNoYXJMZWZ0ID0gKFxuICBfZWRpdG9yOiBFZGl0b3IsIFxuICBzZWxlY3Rpb246IEVkaXRvclNlbGVjdGlvblxuKSA9PiB7XG4gICAgY29uc3QgbmV3X2hkOiBFZGl0b3JQb3NpdGlvbiA9IHtcbiAgICAgIGxpbmU6c2VsZWN0aW9uLmhlYWQubGluZSwgXG4gICAgICBjaDpzZWxlY3Rpb24uaGVhZC5jaC0xXG4gICAgfTtcblxuICAgIHJldHVybiB7IGFuY2hvcjogc2VsZWN0aW9uLmFuY2hvciwgaGVhZDogbmV3X2hkIH07XG59O1xuXG5leHBvcnQgY29uc3Qgc2VsZWN0MUNoYXJSaWdodCA9IChcbiAgX2VkaXRvcjogRWRpdG9yLCBcbiAgc2VsZWN0aW9uOiBFZGl0b3JTZWxlY3Rpb25cbikgPT4ge1xuICAgIGNvbnN0IG5ld19oZDogRWRpdG9yUG9zaXRpb24gPSB7XG4gICAgICBsaW5lOnNlbGVjdGlvbi5oZWFkLmxpbmUsIFxuICAgICAgY2g6c2VsZWN0aW9uLmhlYWQuY2grMVxuICAgIH07XG5cbiAgICByZXR1cm4geyBhbmNob3I6IHNlbGVjdGlvbi5hbmNob3IsIGhlYWQ6IG5ld19oZCB9O1xufTtcblxuLy8gRGVmaW5lIGEgcmV1c2FibGUgdmFyaWFibGUgZm9yIHB1bmN0dWF0aW9uIGNoYXJhY3RlcnNcbmNvbnN0IHB1bmN0dWF0aW9uQ2hhcnMgPSAvW1xccy4sIT87Oi1fXS87XG5cbmV4cG9ydCBjb25zdCBzZWxlY3QxV29yZExlZnQgPSAoXG4gIGVkaXRvcjogRWRpdG9yLFxuICBzZWxlY3Rpb246IEVkaXRvclNlbGVjdGlvblxuKSA9PiB7XG4gIGNvbnN0IHsgYW5jaG9yLCBoZWFkIH0gPSBzZWxlY3Rpb247ICAvLyBEZXN0cnVjdHVyZSB0aGUgYW5jaG9yIGFuZCBoZWFkIHBvc2l0aW9ucyBmcm9tIHRoZSBzZWxlY3Rpb25cbiAgY29uc3QgbGluZSA9IGVkaXRvci5nZXRMaW5lKGhlYWQubGluZSk7ICAvLyBHZXQgdGhlIHRleHQgb2YgdGhlIGxpbmUgd2hlcmUgdGhlIGhlYWQgaXMgY3VycmVudGx5IGxvY2F0ZWRcbiAgbGV0IG5ld0hlYWQgPSB7IC4uLmhlYWQgfTsgIC8vIENyZWF0ZSBhIG5ldyBwb3NpdGlvbiBvYmplY3QgZm9yIHRoZSBoZWFkIHRvIHRyYWNrIHRoZSB1cGRhdGVkIGN1cnNvciBwb3NpdGlvblxuXG4gIC8vIEhhbmRsZSB0aGUgY2FzZSB3aGVyZSB0aGUgY3Vyc29yIGlzIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIGxpbmUgYW5kIG5lZWRzIHRvIG1vdmUgdG8gdGhlIHByZXZpb3VzIGxpbmVcbiAgaWYgKGhlYWQuY2ggPT09IDAgJiYgaGVhZC5saW5lID4gMCkge1xuICAgIG5ld0hlYWQubGluZS0tOyAgLy8gTW92ZSB1cCBvbmUgbGluZVxuICAgIG5ld0hlYWQuY2ggPSBlZGl0b3IuZ2V0TGluZShuZXdIZWFkLmxpbmUpLmxlbmd0aDsgIC8vIFNldCB0aGUgY3Vyc29yIHRvIHRoZSBlbmQgb2YgdGhlIHByZXZpb3VzIGxpbmVcbiAgfSBlbHNlIHtcbiAgICAvLyBNb3ZlIGxlZnQgdG8gdGhlIGVuZCBvZiB0aGUgbmV4dCB3b3JkIG9yIHB1bmN0dWF0aW9uIGdyb3VwXG4gICAgbGV0IGNoID0gaGVhZC5jaDtcbiAgICBpZiAoY2ggPiAwICYmICEvW1xcc10vLnRlc3QobGluZVtjaC0xXSkgJiYgIXB1bmN0dWF0aW9uQ2hhcnMudGVzdChsaW5lW2NoLTFdKSkge1xuICAgICAgLy8gSWYgdGhlIGNoYXJhY3RlciBpcyBwYXJ0IG9mIGEgd29yZCwgbW92ZSBsZWZ0IHVudGlsIHRoZSBlbmQgb2YgdGhlIHdvcmQgaXMgZm91bmRcbiAgICAgIHdoaWxlIChjaCA+IDAgJiYgIS9bXFxzXS8udGVzdChsaW5lW2NoLTFdKSAmJiAhcHVuY3R1YXRpb25DaGFycy50ZXN0KGxpbmVbY2gtMV0pKSBjaC0tO1xuICAgIH0gZWxzZSBpZiAoY2ggPiAwICYmIHB1bmN0dWF0aW9uQ2hhcnMudGVzdChsaW5lW2NoLTFdKSkge1xuICAgICAgLy8gSWYgdGhlIGNoYXJhY3RlciBpcyBhIHB1bmN0dWF0aW9uIG1hcmssIG1vdmUgbGVmdCB1bnRpbCB0aGUgZW5kIG9mIHRoZSBwdW5jdHVhdGlvbiBncm91cCBpcyBmb3VuZFxuICAgICAgd2hpbGUgKGNoID4gMCAmJiBwdW5jdHVhdGlvbkNoYXJzLnRlc3QobGluZVtjaC0xXSkpIGNoLS07XG4gICAgfSBlbHNlIHtcbiAgICAgIGNoLS07ICAvLyBJZiBub25lIG9mIHRoZSBhYm92ZSwgc2ltcGx5IG1vdmUgb25lIGNoYXJhY3RlciB0byB0aGUgbGVmdFxuICAgIH1cbiAgICBuZXdIZWFkLmNoID0gY2g7ICAvLyBVcGRhdGUgdGhlIGhlYWQgcG9zaXRpb24gd2l0aCB0aGUgbmV3IGNoYXJhY3RlciBwb3NpdGlvblxuICB9XG5cbiAgLy8gQWRqdXN0IHNlbGVjdGlvbiBiYXNlZCBvbiBkaXJlY3Rpb25cbiAgaWYgKGVkaXRvci5wb3NUb09mZnNldChuZXdIZWFkKSA8IGVkaXRvci5wb3NUb09mZnNldChhbmNob3IpKSB7XG4gICAgLy8gSWYgdGhlIG5ldyBoZWFkIHBvc2l0aW9uIGlzIGJlZm9yZSB0aGUgYW5jaG9yLCBleHBhbmQgdGhlIHNlbGVjdGlvbiB0byB0aGUgbGVmdFxuICAgIHJldHVybiB7IGFuY2hvciwgaGVhZDogbmV3SGVhZCB9O1xuICB9IGVsc2UgaWYgKGVkaXRvci5wb3NUb09mZnNldChuZXdIZWFkKSA+IGVkaXRvci5wb3NUb09mZnNldChhbmNob3IpICYmIGhlYWQuY2ggIT09IGFuY2hvci5jaCkge1xuICAgIC8vIElmIHRoZSBuZXcgaGVhZCBwb3NpdGlvbiBpcyBhZnRlciB0aGUgYW5jaG9yIGFuZCB0aGUgc2VsZWN0aW9uIGlzIG5vbi1jb2xsYXBzZWQsIHNocmluayB0aGUgc2VsZWN0aW9uIGZyb20gdGhlIHJpZ2h0XG4gICAgcmV0dXJuIHsgYW5jaG9yLCBoZWFkOiBuZXdIZWFkIH07XG4gIH0gZWxzZSB7XG4gICAgLy8gSWYgbmVpdGhlciBjb25kaXRpb24gaXMgbWV0LCBtYWludGFpbiB0aGUgY3VycmVudCBzZWxlY3Rpb25cbiAgICByZXR1cm4geyBhbmNob3I6IG5ld0hlYWQsIGhlYWQ6IGFuY2hvciB9O1xuICB9XG59O1xuXG5leHBvcnQgY29uc3Qgc2VsZWN0MVdvcmRSaWdodCA9IChcbiAgZWRpdG9yOiBFZGl0b3IsXG4gIHNlbGVjdGlvbjogRWRpdG9yU2VsZWN0aW9uXG4pID0+IHtcbiAgY29uc3QgeyBhbmNob3IsIGhlYWQgfSA9IHNlbGVjdGlvbjtcbiAgY29uc3QgbGluZSA9IGVkaXRvci5nZXRMaW5lKGhlYWQubGluZSk7XG4gIGxldCBuZXdIZWFkID0geyAuLi5oZWFkIH07XG5cbiAgLy8gSGFuZGxlIG1vdmluZyBhY3Jvc3MgbGluZXNcbiAgaWYgKGhlYWQuY2ggPT09IGxpbmUubGVuZ3RoICYmIGhlYWQubGluZSA8IGVkaXRvci5saW5lQ291bnQoKSAtIDEpIHtcbiAgICBuZXdIZWFkLmxpbmUrKztcbiAgICBuZXdIZWFkLmNoID0gMDtcbiAgfSBlbHNlIHtcbiAgICAvLyBNb3ZlIHJpZ2h0IHRvIHRoZSBlbmQgb2YgdGhlIG5leHQgd29yZCBvciBwdW5jdHVhdGlvbiBncm91cFxuICAgIGxldCBjaCA9IGhlYWQuY2g7XG4gICAgaWYgKGNoIDwgbGluZS5sZW5ndGggJiYgIS9bXFxzXS8udGVzdChsaW5lW2NoXSkgJiYgIXB1bmN0dWF0aW9uQ2hhcnMudGVzdChsaW5lW2NoXSkpIHtcbiAgICAgIHdoaWxlIChjaCA8IGxpbmUubGVuZ3RoICYmICEvW1xcc10vLnRlc3QobGluZVtjaF0pICYmICFwdW5jdHVhdGlvbkNoYXJzLnRlc3QobGluZVtjaF0pKSBjaCsrO1xuICAgIH0gZWxzZSBpZiAoY2ggPCBsaW5lLmxlbmd0aCAmJiBwdW5jdHVhdGlvbkNoYXJzLnRlc3QobGluZVtjaF0pKSB7XG4gICAgICB3aGlsZSAoY2ggPCBsaW5lLmxlbmd0aCAmJiBwdW5jdHVhdGlvbkNoYXJzLnRlc3QobGluZVtjaF0pKSBjaCsrO1xuICAgIH0gZWxzZSB7XG4gICAgICBjaCsrO1xuICAgIH1cbiAgICBuZXdIZWFkLmNoID0gY2g7XG4gIH1cblxuICAvLyBEZXRlcm1pbmUgaWYgd2Ugc2hvdWxkIHNocmluayBvciBleHBhbmQgdGhlIHNlbGVjdGlvblxuICBpZiAoZWRpdG9yLnBvc1RvT2Zmc2V0KG5ld0hlYWQpID4gZWRpdG9yLnBvc1RvT2Zmc2V0KGhlYWQpKSB7XG4gICAgLy8gU2hyaW5rIHRoZSBzZWxlY3Rpb24gZnJvbSB0aGUgbGVmdFxuICAgIHJldHVybiB7IGFuY2hvciwgaGVhZDogbmV3SGVhZCB9O1xuICB9IGVsc2Uge1xuICAgIC8vIEV4cGFuZCB0aGUgc2VsZWN0aW9uIHRvIHRoZSByaWdodFxuICAgIHJldHVybiB7IGFuY2hvcjogbmV3SGVhZCwgaGVhZDogYW5jaG9yIH07XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBtb3ZlV29yZCA9IChlZGl0b3I6IEVkaXRvciwgZGlyZWN0aW9uOiAnbGVmdCcgfCAncmlnaHQnKSA9PiB7XG4gIHN3aXRjaCAoZGlyZWN0aW9uKSB7XG4gICAgY2FzZSAnbGVmdCc6XG4gICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIC0gY29tbWFuZCBub3QgZGVmaW5lZCBpbiBPYnNpZGlhbiBBUElcbiAgICAgIGVkaXRvci5leGVjKCdnb1dvcmRMZWZ0Jyk7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdyaWdodCc6XG4gICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIC0gY29tbWFuZCBub3QgZGVmaW5lZCBpbiBPYnNpZGlhbiBBUElcbiAgICAgIGVkaXRvci5leGVjKCdnb1dvcmRSaWdodCcpO1xuICAgICAgYnJlYWs7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCB0cmFuc2Zvcm1DYXNlID0gKFxuICBlZGl0b3I6IEVkaXRvcixcbiAgc2VsZWN0aW9uOiBFZGl0b3JTZWxlY3Rpb24sXG4gIGNhc2VUeXBlOiBDQVNFLFxuKSA9PiB7XG4gIGxldCB7IGZyb20sIHRvIH0gPSBnZXRTZWxlY3Rpb25Cb3VuZGFyaWVzKHNlbGVjdGlvbik7XG4gIGxldCBzZWxlY3RlZFRleHQgPSBlZGl0b3IuZ2V0UmFuZ2UoZnJvbSwgdG8pO1xuXG4gIC8vIGFwcGx5IHRyYW5zZm9ybSBvbiB3b3JkIGF0IGN1cnNvciBpZiBub3RoaW5nIGlzIHNlbGVjdGVkXG4gIGlmIChzZWxlY3RlZFRleHQubGVuZ3RoID09PSAwKSB7XG4gICAgY29uc3QgcG9zID0gc2VsZWN0aW9uLmhlYWQ7XG4gICAgY29uc3QgeyBhbmNob3IsIGhlYWQgfSA9IHdvcmRSYW5nZUF0UG9zKHBvcywgZWRpdG9yLmdldExpbmUocG9zLmxpbmUpKTtcbiAgICBbZnJvbSwgdG9dID0gW2FuY2hvciwgaGVhZF07XG4gICAgc2VsZWN0ZWRUZXh0ID0gZWRpdG9yLmdldFJhbmdlKGFuY2hvciwgaGVhZCk7XG4gIH1cblxuICBsZXQgcmVwbGFjZW1lbnRUZXh0ID0gc2VsZWN0ZWRUZXh0O1xuXG4gIHN3aXRjaCAoY2FzZVR5cGUpIHtcbiAgICBjYXNlIENBU0UuVVBQRVI6IHtcbiAgICAgIHJlcGxhY2VtZW50VGV4dCA9IHNlbGVjdGVkVGV4dC50b1VwcGVyQ2FzZSgpO1xuICAgICAgYnJlYWs7XG4gICAgfVxuICAgIGNhc2UgQ0FTRS5MT1dFUjoge1xuICAgICAgcmVwbGFjZW1lbnRUZXh0ID0gc2VsZWN0ZWRUZXh0LnRvTG93ZXJDYXNlKCk7XG4gICAgICBicmVhaztcbiAgICB9XG4gICAgY2FzZSBDQVNFLlRJVExFOiB7XG4gICAgICByZXBsYWNlbWVudFRleHQgPSB0b1RpdGxlQ2FzZShzZWxlY3RlZFRleHQpO1xuICAgICAgYnJlYWs7XG4gICAgfVxuICAgIGNhc2UgQ0FTRS5ORVhUOiB7XG4gICAgICByZXBsYWNlbWVudFRleHQgPSBnZXROZXh0Q2FzZShzZWxlY3RlZFRleHQpO1xuICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgZWRpdG9yLnJlcGxhY2VSYW5nZShyZXBsYWNlbWVudFRleHQsIGZyb20sIHRvKTtcblxuICByZXR1cm4gc2VsZWN0aW9uO1xufTtcblxuY29uc3QgZXhwYW5kU2VsZWN0aW9uID0gKHtcbiAgZWRpdG9yLFxuICBzZWxlY3Rpb24sXG4gIG9wZW5pbmdDaGFyYWN0ZXJDaGVjayxcbiAgbWF0Y2hpbmdDaGFyYWN0ZXJNYXAsXG59OiB7XG4gIGVkaXRvcjogRWRpdG9yO1xuICBzZWxlY3Rpb246IEVkaXRvclNlbGVjdGlvbjtcbiAgb3BlbmluZ0NoYXJhY3RlckNoZWNrOiBDaGVja0NoYXJhY3RlcjtcbiAgbWF0Y2hpbmdDaGFyYWN0ZXJNYXA6IE1hdGNoaW5nQ2hhcmFjdGVyTWFwO1xufSkgPT4ge1xuICBsZXQgeyBhbmNob3IsIGhlYWQgfSA9IHNlbGVjdGlvbjtcblxuICAvLyBpbiBjYXNlIHVzZXIgc2VsZWN0cyB1cHdhcmRzXG4gIGlmIChhbmNob3IubGluZSA+PSBoZWFkLmxpbmUgJiYgYW5jaG9yLmNoID4gYW5jaG9yLmNoKSB7XG4gICAgW2FuY2hvciwgaGVhZF0gPSBbaGVhZCwgYW5jaG9yXTtcbiAgfVxuXG4gIGNvbnN0IG5ld0FuY2hvciA9IGZpbmRQb3NPZk5leHRDaGFyYWN0ZXIoe1xuICAgIGVkaXRvcixcbiAgICBzdGFydFBvczogYW5jaG9yLFxuICAgIGNoZWNrQ2hhcmFjdGVyOiBvcGVuaW5nQ2hhcmFjdGVyQ2hlY2ssXG4gICAgc2VhcmNoRGlyZWN0aW9uOiBTRUFSQ0hfRElSRUNUSU9OLkJBQ0tXQVJELFxuICB9KTtcbiAgaWYgKCFuZXdBbmNob3IpIHtcbiAgICByZXR1cm4gc2VsZWN0aW9uO1xuICB9XG5cbiAgY29uc3QgbmV3SGVhZCA9IGZpbmRQb3NPZk5leHRDaGFyYWN0ZXIoe1xuICAgIGVkaXRvcixcbiAgICBzdGFydFBvczogaGVhZCxcbiAgICBjaGVja0NoYXJhY3RlcjogKGNoYXI6IHN0cmluZykgPT5cbiAgICAgIGNoYXIgPT09IG1hdGNoaW5nQ2hhcmFjdGVyTWFwW25ld0FuY2hvci5tYXRjaF0sXG4gICAgc2VhcmNoRGlyZWN0aW9uOiBTRUFSQ0hfRElSRUNUSU9OLkZPUldBUkQsXG4gIH0pO1xuICBpZiAoIW5ld0hlYWQpIHtcbiAgICByZXR1cm4gc2VsZWN0aW9uO1xuICB9XG5cbiAgcmV0dXJuIHsgYW5jaG9yOiBuZXdBbmNob3IucG9zLCBoZWFkOiBuZXdIZWFkLnBvcyB9O1xufTtcblxuZXhwb3J0IGNvbnN0IGV4cGFuZFNlbGVjdGlvblRvQnJhY2tldHMgPSAoXG4gIGVkaXRvcjogRWRpdG9yLFxuICBzZWxlY3Rpb246IEVkaXRvclNlbGVjdGlvbixcbikgPT5cbiAgZXhwYW5kU2VsZWN0aW9uKHtcbiAgICBlZGl0b3IsXG4gICAgc2VsZWN0aW9uLFxuICAgIG9wZW5pbmdDaGFyYWN0ZXJDaGVjazogKGNoYXI6IHN0cmluZykgPT4gL1soW3tdLy50ZXN0KGNoYXIpLFxuICAgIG1hdGNoaW5nQ2hhcmFjdGVyTWFwOiBNQVRDSElOR19CUkFDS0VUUyxcbiAgfSk7XG5cbmV4cG9ydCBjb25zdCBleHBhbmRTZWxlY3Rpb25Ub1F1b3RlcyA9IChcbiAgZWRpdG9yOiBFZGl0b3IsXG4gIHNlbGVjdGlvbjogRWRpdG9yU2VsZWN0aW9uLFxuKSA9PlxuICBleHBhbmRTZWxlY3Rpb24oe1xuICAgIGVkaXRvcixcbiAgICBzZWxlY3Rpb24sXG4gICAgb3BlbmluZ0NoYXJhY3RlckNoZWNrOiAoY2hhcjogc3RyaW5nKSA9PiAvWydcImBdLy50ZXN0KGNoYXIpLFxuICAgIG1hdGNoaW5nQ2hhcmFjdGVyTWFwOiBNQVRDSElOR19RVU9URVMsXG4gIH0pO1xuXG5leHBvcnQgY29uc3QgZXhwYW5kU2VsZWN0aW9uVG9RdW90ZXNPckJyYWNrZXRzID0gKGVkaXRvcjogRWRpdG9yKSA9PiB7XG4gIGNvbnN0IHNlbGVjdGlvbnMgPSBlZGl0b3IubGlzdFNlbGVjdGlvbnMoKTtcbiAgY29uc3QgbmV3U2VsZWN0aW9uID0gZXhwYW5kU2VsZWN0aW9uKHtcbiAgICBlZGl0b3IsXG4gICAgc2VsZWN0aW9uOiBzZWxlY3Rpb25zWzBdLFxuICAgIG9wZW5pbmdDaGFyYWN0ZXJDaGVjazogKGNoYXI6IHN0cmluZykgPT4gL1snXCJgKFt7XS8udGVzdChjaGFyKSxcbiAgICBtYXRjaGluZ0NoYXJhY3Rlck1hcDogTUFUQ0hJTkdfUVVPVEVTX0JSQUNLRVRTLFxuICB9KTtcbiAgZWRpdG9yLnNldFNlbGVjdGlvbnMoWy4uLnNlbGVjdGlvbnMsIG5ld1NlbGVjdGlvbl0pO1xufTtcblxuY29uc3QgaW5zZXJ0Q3Vyc29yID0gKGVkaXRvcjogRWRpdG9yLCBsaW5lT2Zmc2V0OiBudW1iZXIpID0+IHtcbiAgY29uc3Qgc2VsZWN0aW9ucyA9IGVkaXRvci5saXN0U2VsZWN0aW9ucygpO1xuICBjb25zdCBuZXdTZWxlY3Rpb25zID0gW107XG4gIGZvciAoY29uc3Qgc2VsZWN0aW9uIG9mIHNlbGVjdGlvbnMpIHtcbiAgICBjb25zdCB7IGxpbmUsIGNoIH0gPSBzZWxlY3Rpb24uaGVhZDtcbiAgICBpZiAoXG4gICAgICAobGluZSA9PT0gMCAmJiBsaW5lT2Zmc2V0IDwgMCkgfHxcbiAgICAgIChsaW5lID09PSBlZGl0b3IubGFzdExpbmUoKSAmJiBsaW5lT2Zmc2V0ID4gMClcbiAgICApIHtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgICBjb25zdCB0YXJnZXRMaW5lTGVuZ3RoID0gZWRpdG9yLmdldExpbmUobGluZSArIGxpbmVPZmZzZXQpLmxlbmd0aDtcbiAgICBuZXdTZWxlY3Rpb25zLnB1c2goe1xuICAgICAgYW5jaG9yOiB7XG4gICAgICAgIGxpbmU6IHNlbGVjdGlvbi5hbmNob3IubGluZSArIGxpbmVPZmZzZXQsXG4gICAgICAgIGNoOiBNYXRoLm1pbihzZWxlY3Rpb24uYW5jaG9yLmNoLCB0YXJnZXRMaW5lTGVuZ3RoKSxcbiAgICAgIH0sXG4gICAgICBoZWFkOiB7XG4gICAgICAgIGxpbmU6IGxpbmUgKyBsaW5lT2Zmc2V0LFxuICAgICAgICBjaDogTWF0aC5taW4oY2gsIHRhcmdldExpbmVMZW5ndGgpLFxuICAgICAgfSxcbiAgICB9KTtcbiAgfVxuICBlZGl0b3Iuc2V0U2VsZWN0aW9ucyhbLi4uZWRpdG9yLmxpc3RTZWxlY3Rpb25zKCksIC4uLm5ld1NlbGVjdGlvbnNdKTtcbn07XG5cbmV4cG9ydCBjb25zdCBpbnNlcnRDdXJzb3JBYm92ZSA9IChlZGl0b3I6IEVkaXRvcikgPT4gaW5zZXJ0Q3Vyc29yKGVkaXRvciwgLTEpO1xuXG5leHBvcnQgY29uc3QgaW5zZXJ0Q3Vyc29yQmVsb3cgPSAoZWRpdG9yOiBFZGl0b3IpID0+IGluc2VydEN1cnNvcihlZGl0b3IsIDEpO1xuXG5leHBvcnQgY29uc3QgZ29Ub0hlYWRpbmcgPSAoXG4gIGFwcDogQXBwLFxuICBlZGl0b3I6IEVkaXRvcixcbiAgYm91bmRhcnk6ICdwcmV2JyB8ICduZXh0JyxcbikgPT4ge1xuICBjb25zdCBmaWxlID0gYXBwLm1ldGFkYXRhQ2FjaGUuZ2V0RmlsZUNhY2hlKGFwcC53b3Jrc3BhY2UuZ2V0QWN0aXZlRmlsZSgpKTtcbiAgaWYgKCFmaWxlLmhlYWRpbmdzIHx8IGZpbGUuaGVhZGluZ3MubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY29uc3QgeyBsaW5lIH0gPSBlZGl0b3IuZ2V0Q3Vyc29yKCdmcm9tJyk7XG4gIGxldCBwcmV2SGVhZGluZ0xpbmUgPSAwO1xuICBsZXQgbmV4dEhlYWRpbmdMaW5lID0gZWRpdG9yLmxhc3RMaW5lKCk7XG5cbiAgZmlsZS5oZWFkaW5ncy5mb3JFYWNoKCh7IHBvc2l0aW9uIH0pID0+IHtcbiAgICBjb25zdCB7IGVuZDogaGVhZGluZ1BvcyB9ID0gcG9zaXRpb247XG4gICAgaWYgKGxpbmUgPiBoZWFkaW5nUG9zLmxpbmUgJiYgaGVhZGluZ1Bvcy5saW5lID4gcHJldkhlYWRpbmdMaW5lKSB7XG4gICAgICBwcmV2SGVhZGluZ0xpbmUgPSBoZWFkaW5nUG9zLmxpbmU7XG4gICAgfVxuICAgIGlmIChsaW5lIDwgaGVhZGluZ1Bvcy5saW5lICYmIGhlYWRpbmdQb3MubGluZSA8IG5leHRIZWFkaW5nTGluZSkge1xuICAgICAgbmV4dEhlYWRpbmdMaW5lID0gaGVhZGluZ1Bvcy5saW5lO1xuICAgIH1cbiAgfSk7XG5cbiAgZWRpdG9yLnNldFNlbGVjdGlvbihcbiAgICBib3VuZGFyeSA9PT0gJ3ByZXYnXG4gICAgICA/IGdldExpbmVFbmRQb3MocHJldkhlYWRpbmdMaW5lLCBlZGl0b3IpXG4gICAgICA6IGdldExpbmVFbmRQb3MobmV4dEhlYWRpbmdMaW5lLCBlZGl0b3IpLFxuICApO1xufTtcbiIsICJpbXBvcnQgeyBQbHVnaW5TZXR0aW5nVGFiLCBBcHAsIFNldHRpbmcsIFRvZ2dsZUNvbXBvbmVudCB9IGZyb20gJ29ic2lkaWFuJztcbmltcG9ydCBDb2RlRWRpdG9yU2hvcnRjdXRzIGZyb20gJy4vbWFpbic7XG5cbmV4cG9ydCBpbnRlcmZhY2UgUGx1Z2luU2V0dGluZ3Mge1xuICBhdXRvSW5zZXJ0TGlzdFByZWZpeDogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGNvbnN0IERFRkFVTFRfU0VUVElOR1M6IFBsdWdpblNldHRpbmdzID0ge1xuICBhdXRvSW5zZXJ0TGlzdFByZWZpeDogdHJ1ZSxcbn07XG5cbmV4cG9ydCBjbGFzcyBTZXR0aW5nVGFiIGV4dGVuZHMgUGx1Z2luU2V0dGluZ1RhYiB7XG4gIHBsdWdpbjogQ29kZUVkaXRvclNob3J0Y3V0cztcblxuICBjb25zdHJ1Y3RvcihhcHA6IEFwcCwgcGx1Z2luOiBDb2RlRWRpdG9yU2hvcnRjdXRzKSB7XG4gICAgc3VwZXIoYXBwLCBwbHVnaW4pO1xuICAgIHRoaXMucGx1Z2luID0gcGx1Z2luO1xuICB9XG5cbiAgZGlzcGxheSgpIHtcbiAgICBjb25zdCB7IGNvbnRhaW5lckVsIH0gPSB0aGlzO1xuXG4gICAgY29udGFpbmVyRWwuZW1wdHkoKTtcblxuICAgIGNvbnRhaW5lckVsLmNyZWF0ZUVsKCdoMicsIHsgdGV4dDogJ0NvZGUgRWRpdG9yIFNob3J0Y3V0cycgfSk7XG5cbiAgICBjb25zdCBsaXN0UHJlZml4U2V0dGluZyA9IG5ldyBTZXR0aW5nKGNvbnRhaW5lckVsKVxuICAgICAgLnNldE5hbWUoJ0F1dG8gaW5zZXJ0IGxpc3QgcHJlZml4JylcbiAgICAgIC5zZXREZXNjKFxuICAgICAgICAnQXV0b21hdGljYWxseSBpbnNlcnQgbGlzdCBwcmVmaXggd2hlbiBpbnNlcnRpbmcgYSBsaW5lIGFib3ZlIG9yIGJlbG93JyxcbiAgICAgIClcbiAgICAgIC5hZGRUb2dnbGUoKHRvZ2dsZSkgPT5cbiAgICAgICAgdG9nZ2xlXG4gICAgICAgICAgLnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLmF1dG9JbnNlcnRMaXN0UHJlZml4KVxuICAgICAgICAgIC5vbkNoYW5nZShhc3luYyAodmFsdWUpID0+IHtcbiAgICAgICAgICAgIHRoaXMucGx1Z2luLnNldHRpbmdzLmF1dG9JbnNlcnRMaXN0UHJlZml4ID0gdmFsdWU7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcbiAgICAgICAgICB9KSxcbiAgICAgICk7XG5cbiAgICBuZXcgU2V0dGluZyhjb250YWluZXJFbCkuc2V0TmFtZSgnUmVzZXQgZGVmYXVsdHMnKS5hZGRCdXR0b24oKGJ0bikgPT4ge1xuICAgICAgYnRuLnNldEJ1dHRvblRleHQoJ1Jlc2V0Jykub25DbGljayhhc3luYyAoKSA9PiB7XG4gICAgICAgIHRoaXMucGx1Z2luLnNldHRpbmdzID0geyAuLi5ERUZBVUxUX1NFVFRJTkdTIH07XG4gICAgICAgIChsaXN0UHJlZml4U2V0dGluZy5jb21wb25lbnRzWzBdIGFzIFRvZ2dsZUNvbXBvbmVudCkuc2V0VmFsdWUoXG4gICAgICAgICAgREVGQVVMVF9TRVRUSU5HUy5hdXRvSW5zZXJ0TGlzdFByZWZpeCxcbiAgICAgICAgKTtcbiAgICAgICAgYXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxufVxuIiwgImltcG9ydCB7IEFwcCwgU3VnZ2VzdE1vZGFsIH0gZnJvbSAnb2JzaWRpYW4nO1xuXG5leHBvcnQgY2xhc3MgR29Ub0xpbmVNb2RhbCBleHRlbmRzIFN1Z2dlc3RNb2RhbDxzdHJpbmc+IHtcbiAgcHJpdmF0ZSBsaW5lQ291bnQ7XG4gIHByaXZhdGUgb25TdWJtaXQ7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgYXBwOiBBcHAsXG4gICAgbGluZUNvdW50OiBudW1iZXIsXG4gICAgb25TdWJtaXQ6IChsaW5lTnVtYmVyOiBudW1iZXIpID0+IHZvaWQsXG4gICkge1xuICAgIHN1cGVyKGFwcCk7XG4gICAgdGhpcy5saW5lQ291bnQgPSBsaW5lQ291bnQ7XG4gICAgdGhpcy5vblN1Ym1pdCA9IG9uU3VibWl0O1xuXG4gICAgY29uc3QgUFJPTVBUX1RFWFQgPSBgRW50ZXIgYSBsaW5lIG51bWJlciBiZXR3ZWVuIDEgYW5kICR7bGluZUNvdW50fWA7XG4gICAgdGhpcy5saW1pdCA9IDE7XG4gICAgdGhpcy5zZXRQbGFjZWhvbGRlcihQUk9NUFRfVEVYVCk7XG4gICAgdGhpcy5lbXB0eVN0YXRlVGV4dCA9IFBST01QVF9URVhUO1xuICB9XG5cbiAgZ2V0U3VnZ2VzdGlvbnMobGluZTogc3RyaW5nKTogc3RyaW5nW10ge1xuICAgIGNvbnN0IGxpbmVOdW1iZXIgPSBwYXJzZUludChsaW5lKTtcbiAgICBpZiAobGluZS5sZW5ndGggPiAwICYmIGxpbmVOdW1iZXIgPiAwICYmIGxpbmVOdW1iZXIgPD0gdGhpcy5saW5lQ291bnQpIHtcbiAgICAgIHJldHVybiBbbGluZV07XG4gICAgfVxuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIHJlbmRlclN1Z2dlc3Rpb24obGluZTogc3RyaW5nLCBlbDogSFRNTEVsZW1lbnQpIHtcbiAgICBlbC5jcmVhdGVFbCgnZGl2JywgeyB0ZXh0OiBsaW5lIH0pO1xuICB9XG5cbiAgb25DaG9vc2VTdWdnZXN0aW9uKGxpbmU6IHN0cmluZykge1xuICAgIC8vIFN1YnRyYWN0IDEgYXMgbGluZSBudW1iZXJzIGFyZSB6ZXJvLWluZGV4ZWRcbiAgICB0aGlzLm9uU3VibWl0KHBhcnNlSW50KGxpbmUpIC0gMSk7XG4gIH1cbn1cbiJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFBQTtBQUFBO0FBQUEsdUJBQXVCOzs7QUNBaEIsSUFBSztBQUFMLFVBQUssT0FBTDtBQUNMLG1CQUFRO0FBQ1IsbUJBQVE7QUFDUixtQkFBUTtBQUNSLGtCQUFPO0FBQUEsR0FKRztBQU9MLElBQU0scUJBQXFCLENBQUMsT0FBTyxLQUFLO0FBRXhDLElBQUs7QUFBTCxVQUFLLG1CQUFMO0FBQ0wsaUNBQVU7QUFDVixrQ0FBVztBQUFBLEdBRkQ7QUFPTCxJQUFNLG9CQUEwQztBQUFBLEVBQ3JELEtBQUs7QUFB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