From 008f7d9f19710e3b9979eff688ec57ab663acb98 Mon Sep 17 00:00:00 2001 From: KemoNine Date: Fri, 22 Nov 2024 10:53:13 -0500 Subject: [PATCH] cleanup and update installed plugins --- .obsidian/community-plugins.json | 2 - .obsidian/core-plugins.json | 47 +- .../plugins/attachment-management/main.js | 2076 --- .../attachment-management/manifest.json | 10 - .../plugins/attachment-management/styles.css | 15 - .../plugins/dashboard-navigator/data.json | 9 +- .obsidian/plugins/dashboard-navigator/main.js | 1510 +- .../plugins/dashboard-navigator/manifest.json | 2 +- .../plugins/dashboard-navigator/styles.css | 285 +- .obsidian/plugins/line-arrange/main.js | 141 - .obsidian/plugins/line-arrange/manifest.json | 10 - .obsidian/plugins/litegallery/main.js | 214 - .obsidian/plugins/litegallery/manifest.json | 10 - .obsidian/plugins/litegallery/styles.css | 111 - .../plugins/multi-column-markdown/main.js | 6555 ------- .../multi-column-markdown/manifest.json | 11 - .../plugins/multi-column-markdown/styles.css | 249 - .../plugins/obsidian-advanced-uri/main.js | 4 +- .../obsidian-advanced-uri/manifest.json | 2 +- .../obsidian-sort-and-permute-lines/main.js | 392 - .../manifest.json | 10 - .../plugins/table-editor-obsidian/data.json | 6 - .../plugins/table-editor-obsidian/main.js | 14109 ---------------- .../table-editor-obsidian/manifest.json | 17 - .../plugins/table-editor-obsidian/styles.css | 78 - .obsidian/plugins/tag-page-md/data.json | 9 - .obsidian/plugins/tag-page-md/main.js | 525 - .obsidian/plugins/tag-page-md/manifest.json | 11 - .obsidian/plugins/tag-page-md/styles.css | 29 - .obsidian/workspace.json | 79 +- 30 files changed, 1420 insertions(+), 25108 deletions(-) delete mode 100644 .obsidian/plugins/attachment-management/main.js delete mode 100644 .obsidian/plugins/attachment-management/manifest.json delete mode 100644 .obsidian/plugins/attachment-management/styles.css delete mode 100644 .obsidian/plugins/line-arrange/main.js delete mode 100644 .obsidian/plugins/line-arrange/manifest.json delete mode 100644 .obsidian/plugins/litegallery/main.js delete mode 100644 .obsidian/plugins/litegallery/manifest.json delete mode 100644 .obsidian/plugins/litegallery/styles.css delete mode 100644 .obsidian/plugins/multi-column-markdown/main.js delete mode 100644 .obsidian/plugins/multi-column-markdown/manifest.json delete mode 100644 .obsidian/plugins/multi-column-markdown/styles.css delete mode 100644 .obsidian/plugins/obsidian-sort-and-permute-lines/main.js delete mode 100644 .obsidian/plugins/obsidian-sort-and-permute-lines/manifest.json delete mode 100644 .obsidian/plugins/table-editor-obsidian/data.json delete mode 100644 .obsidian/plugins/table-editor-obsidian/main.js delete mode 100644 .obsidian/plugins/table-editor-obsidian/manifest.json delete mode 100644 .obsidian/plugins/table-editor-obsidian/styles.css delete mode 100644 .obsidian/plugins/tag-page-md/data.json delete mode 100644 .obsidian/plugins/tag-page-md/main.js delete mode 100644 .obsidian/plugins/tag-page-md/manifest.json delete mode 100644 .obsidian/plugins/tag-page-md/styles.css diff --git a/.obsidian/community-plugins.json b/.obsidian/community-plugins.json index b2b5b6b..079fd26 100644 --- a/.obsidian/community-plugins.json +++ b/.obsidian/community-plugins.json @@ -4,11 +4,9 @@ "note-gallery", "smart-random-note", "tag-word-cloud", - "obsidian-sort-and-permute-lines", "dashboard-navigator", "automatic-table-of-contents", "obsidian-advanced-uri", - "table-editor-obsidian", "folder-notes", "waypoint" ] \ No newline at end of file diff --git a/.obsidian/core-plugins.json b/.obsidian/core-plugins.json index edc2ff5..f2483b2 100644 --- a/.obsidian/core-plugins.json +++ b/.obsidian/core-plugins.json @@ -1,17 +1,30 @@ -[ - "file-explorer", - "global-search", - "graph", - "backlink", - "canvas", - "outgoing-link", - "tag-pane", - "properties", - "page-preview", - "command-palette", - "editor-status", - "bookmarks", - "zk-prefixer", - "outline", - "file-recovery" -] \ No newline at end of file +{ + "file-explorer": true, + "global-search": true, + "switcher": false, + "graph": true, + "backlink": true, + "canvas": true, + "outgoing-link": true, + "tag-pane": true, + "properties": true, + "page-preview": true, + "daily-notes": false, + "templates": false, + "note-composer": false, + "command-palette": true, + "slash-command": false, + "editor-status": true, + "bookmarks": true, + "markdown-importer": false, + "zk-prefixer": true, + "random-note": false, + "outline": true, + "word-count": false, + "slides": false, + "audio-recorder": false, + "workspaces": false, + "file-recovery": true, + "publish": false, + "sync": false +} \ No newline at end of file diff --git a/.obsidian/plugins/attachment-management/main.js b/.obsidian/plugins/attachment-management/main.js deleted file mode 100644 index f071ea4..0000000 --- a/.obsidian/plugins/attachment-management/main.js +++ /dev/null @@ -1,2076 +0,0 @@ -/* -THIS IS A GENERATED/BUNDLED FILE BY ESBUILD -if you want to view the source, please visit the github repository of this plugin -*/ - -var __defProp = Object.defineProperty; -var __getOwnPropDesc = Object.getOwnPropertyDescriptor; -var __getOwnPropNames = Object.getOwnPropertyNames; -var __hasOwnProp = Object.prototype.hasOwnProperty; -var __export = (target, all) => { - for (var name in all) - __defProp(target, name, { get: all[name], enumerable: true }); -}; -var __copyProps = (to, from, except, desc) => { - if (from && typeof from === "object" || typeof from === "function") { - for (let key of __getOwnPropNames(from)) - if (!__hasOwnProp.call(to, key) && key !== except) - __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); - } - return to; -}; -var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); - -// src/main.ts -var main_exports = {}; -__export(main_exports, { - default: () => AttachmentManagementPlugin -}); -module.exports = __toCommonJS(main_exports); -var import_obsidian11 = require("obsidian"); - -// src/settings/settings.ts -var import_obsidian3 = require("obsidian"); - -// src/lib/constant.ts -var SETTINGS_VARIABLES_DATES = "${date}"; -var SETTINGS_VARIABLES_NOTEPATH = "${notepath}"; -var SETTINGS_VARIABLES_NOTENAME = "${notename}"; -var SETTINGS_VARIABLES_NOTEPARENT = "${parent}"; -var SETTINGS_VARIABLES_ORIGINALNAME = "${originalname}"; -var SETTINGS_VARIABLES_MD5 = "${md5}"; -var SETTINGS_ROOT_OBSFOLDER = "obsFolder"; -var SETTINGS_ROOT_INFOLDER = "inFolderBelow"; -var SETTINGS_ROOT_NEXTTONOTE = "nextToNote"; - -// src/model/extensionOverride.ts -var import_obsidian2 = require("obsidian"); - -// src/utils.ts -var import_obsidian = require("obsidian"); - -// node_modules/ts-md5/dist/esm/md5.js -var Md5 = class { - constructor() { - this._dataLength = 0; - this._bufferLength = 0; - this._state = new Int32Array(4); - this._buffer = new ArrayBuffer(68); - this._buffer8 = new Uint8Array(this._buffer, 0, 68); - this._buffer32 = new Uint32Array(this._buffer, 0, 17); - this.start(); - } - static hashStr(str, raw = false) { - return this.onePassHasher.start().appendStr(str).end(raw); - } - static hashAsciiStr(str, raw = false) { - return this.onePassHasher.start().appendAsciiStr(str).end(raw); - } - static _hex(x) { - const hc = Md5.hexChars; - const ho = Md5.hexOut; - let n; - let offset; - let j; - let i; - for (i = 0; i < 4; i += 1) { - offset = i * 8; - n = x[i]; - for (j = 0; j < 8; j += 2) { - ho[offset + 1 + j] = hc.charAt(n & 15); - n >>>= 4; - ho[offset + 0 + j] = hc.charAt(n & 15); - n >>>= 4; - } - } - return ho.join(""); - } - static _md5cycle(x, k) { - let a = x[0]; - let b = x[1]; - let c = x[2]; - let d = x[3]; - a += (b & c | ~b & d) + k[0] - 680876936 | 0; - a = (a << 7 | a >>> 25) + b | 0; - d += (a & b | ~a & c) + k[1] - 389564586 | 0; - d = (d << 12 | d >>> 20) + a | 0; - c += (d & a | ~d & b) + k[2] + 606105819 | 0; - c = (c << 17 | c >>> 15) + d | 0; - b += (c & d | ~c & a) + k[3] - 1044525330 | 0; - b = (b << 22 | b >>> 10) + c | 0; - a += (b & c | ~b & d) + k[4] - 176418897 | 0; - a = (a << 7 | a >>> 25) + b | 0; - d += (a & b | ~a & c) + k[5] + 1200080426 | 0; - d = (d << 12 | d >>> 20) + a | 0; - c += (d & a | ~d & b) + k[6] - 1473231341 | 0; - c = (c << 17 | c >>> 15) + d | 0; - b += (c & d | ~c & a) + k[7] - 45705983 | 0; - b = (b << 22 | b >>> 10) + c | 0; - a += (b & c | ~b & d) + k[8] + 1770035416 | 0; - a = (a << 7 | a >>> 25) + b | 0; - d += (a & b | ~a & c) + k[9] - 1958414417 | 0; - d = (d << 12 | d >>> 20) + a | 0; - c += (d & a | ~d & b) + k[10] - 42063 | 0; - c = (c << 17 | c >>> 15) + d | 0; - b += (c & d | ~c & a) + k[11] - 1990404162 | 0; - b = (b << 22 | b >>> 10) + c | 0; - a += (b & c | ~b & d) + k[12] + 1804603682 | 0; - a = (a << 7 | a >>> 25) + b | 0; - d += (a & b | ~a & c) + k[13] - 40341101 | 0; - d = (d << 12 | d >>> 20) + a | 0; - c += (d & a | ~d & b) + k[14] - 1502002290 | 0; - c = (c << 17 | c >>> 15) + d | 0; - b += (c & d | ~c & a) + k[15] + 1236535329 | 0; - b = (b << 22 | b >>> 10) + c | 0; - a += (b & d | c & ~d) + k[1] - 165796510 | 0; - a = (a << 5 | a >>> 27) + b | 0; - d += (a & c | b & ~c) + k[6] - 1069501632 | 0; - d = (d << 9 | d >>> 23) + a | 0; - c += (d & b | a & ~b) + k[11] + 643717713 | 0; - c = (c << 14 | c >>> 18) + d | 0; - b += (c & a | d & ~a) + k[0] - 373897302 | 0; - b = (b << 20 | b >>> 12) + c | 0; - a += (b & d | c & ~d) + k[5] - 701558691 | 0; - a = (a << 5 | a >>> 27) + b | 0; - d += (a & c | b & ~c) + k[10] + 38016083 | 0; - d = (d << 9 | d >>> 23) + a | 0; - c += (d & b | a & ~b) + k[15] - 660478335 | 0; - c = (c << 14 | c >>> 18) + d | 0; - b += (c & a | d & ~a) + k[4] - 405537848 | 0; - b = (b << 20 | b >>> 12) + c | 0; - a += (b & d | c & ~d) + k[9] + 568446438 | 0; - a = (a << 5 | a >>> 27) + b | 0; - d += (a & c | b & ~c) + k[14] - 1019803690 | 0; - d = (d << 9 | d >>> 23) + a | 0; - c += (d & b | a & ~b) + k[3] - 187363961 | 0; - c = (c << 14 | c >>> 18) + d | 0; - b += (c & a | d & ~a) + k[8] + 1163531501 | 0; - b = (b << 20 | b >>> 12) + c | 0; - a += (b & d | c & ~d) + k[13] - 1444681467 | 0; - a = (a << 5 | a >>> 27) + b | 0; - d += (a & c | b & ~c) + k[2] - 51403784 | 0; - d = (d << 9 | d >>> 23) + a | 0; - c += (d & b | a & ~b) + k[7] + 1735328473 | 0; - c = (c << 14 | c >>> 18) + d | 0; - b += (c & a | d & ~a) + k[12] - 1926607734 | 0; - b = (b << 20 | b >>> 12) + c | 0; - a += (b ^ c ^ d) + k[5] - 378558 | 0; - a = (a << 4 | a >>> 28) + b | 0; - d += (a ^ b ^ c) + k[8] - 2022574463 | 0; - d = (d << 11 | d >>> 21) + a | 0; - c += (d ^ a ^ b) + k[11] + 1839030562 | 0; - c = (c << 16 | c >>> 16) + d | 0; - b += (c ^ d ^ a) + k[14] - 35309556 | 0; - b = (b << 23 | b >>> 9) + c | 0; - a += (b ^ c ^ d) + k[1] - 1530992060 | 0; - a = (a << 4 | a >>> 28) + b | 0; - d += (a ^ b ^ c) + k[4] + 1272893353 | 0; - d = (d << 11 | d >>> 21) + a | 0; - c += (d ^ a ^ b) + k[7] - 155497632 | 0; - c = (c << 16 | c >>> 16) + d | 0; - b += (c ^ d ^ a) + k[10] - 1094730640 | 0; - b = (b << 23 | b >>> 9) + c | 0; - a += (b ^ c ^ d) + k[13] + 681279174 | 0; - a = (a << 4 | a >>> 28) + b | 0; - d += (a ^ b ^ c) + k[0] - 358537222 | 0; - d = (d << 11 | d >>> 21) + a | 0; - c += (d ^ a ^ b) + k[3] - 722521979 | 0; - c = (c << 16 | c >>> 16) + d | 0; - b += (c ^ d ^ a) + k[6] + 76029189 | 0; - b = (b << 23 | b >>> 9) + c | 0; - a += (b ^ c ^ d) + k[9] - 640364487 | 0; - a = (a << 4 | a >>> 28) + b | 0; - d += (a ^ b ^ c) + k[12] - 421815835 | 0; - d = (d << 11 | d >>> 21) + a | 0; - c += (d ^ a ^ b) + k[15] + 530742520 | 0; - c = (c << 16 | c >>> 16) + d | 0; - b += (c ^ d ^ a) + k[2] - 995338651 | 0; - b = (b << 23 | b >>> 9) + c | 0; - a += (c ^ (b | ~d)) + k[0] - 198630844 | 0; - a = (a << 6 | a >>> 26) + b | 0; - d += (b ^ (a | ~c)) + k[7] + 1126891415 | 0; - d = (d << 10 | d >>> 22) + a | 0; - c += (a ^ (d | ~b)) + k[14] - 1416354905 | 0; - c = (c << 15 | c >>> 17) + d | 0; - b += (d ^ (c | ~a)) + k[5] - 57434055 | 0; - b = (b << 21 | b >>> 11) + c | 0; - a += (c ^ (b | ~d)) + k[12] + 1700485571 | 0; - a = (a << 6 | a >>> 26) + b | 0; - d += (b ^ (a | ~c)) + k[3] - 1894986606 | 0; - d = (d << 10 | d >>> 22) + a | 0; - c += (a ^ (d | ~b)) + k[10] - 1051523 | 0; - c = (c << 15 | c >>> 17) + d | 0; - b += (d ^ (c | ~a)) + k[1] - 2054922799 | 0; - b = (b << 21 | b >>> 11) + c | 0; - a += (c ^ (b | ~d)) + k[8] + 1873313359 | 0; - a = (a << 6 | a >>> 26) + b | 0; - d += (b ^ (a | ~c)) + k[15] - 30611744 | 0; - d = (d << 10 | d >>> 22) + a | 0; - c += (a ^ (d | ~b)) + k[6] - 1560198380 | 0; - c = (c << 15 | c >>> 17) + d | 0; - b += (d ^ (c | ~a)) + k[13] + 1309151649 | 0; - b = (b << 21 | b >>> 11) + c | 0; - a += (c ^ (b | ~d)) + k[4] - 145523070 | 0; - a = (a << 6 | a >>> 26) + b | 0; - d += (b ^ (a | ~c)) + k[11] - 1120210379 | 0; - d = (d << 10 | d >>> 22) + a | 0; - c += (a ^ (d | ~b)) + k[2] + 718787259 | 0; - c = (c << 15 | c >>> 17) + d | 0; - b += (d ^ (c | ~a)) + k[9] - 343485551 | 0; - b = (b << 21 | b >>> 11) + c | 0; - x[0] = a + x[0] | 0; - x[1] = b + x[1] | 0; - x[2] = c + x[2] | 0; - x[3] = d + x[3] | 0; - } - /** - * Initialise buffer to be hashed - */ - start() { - this._dataLength = 0; - this._bufferLength = 0; - this._state.set(Md5.stateIdentity); - return this; - } - // Char to code point to to array conversion: - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/charCodeAt - // #Example.3A_Fixing_charCodeAt_to_handle_non-Basic-Multilingual-Plane_characters_if_their_presence_earlier_in_the_string_is_unknown - /** - * Append a UTF-8 string to the hash buffer - * @param str String to append - */ - appendStr(str) { - const buf8 = this._buffer8; - const buf32 = this._buffer32; - let bufLen = this._bufferLength; - let code; - let i; - for (i = 0; i < str.length; i += 1) { - code = str.charCodeAt(i); - if (code < 128) { - buf8[bufLen++] = code; - } else if (code < 2048) { - buf8[bufLen++] = (code >>> 6) + 192; - buf8[bufLen++] = code & 63 | 128; - } else if (code < 55296 || code > 56319) { - buf8[bufLen++] = (code >>> 12) + 224; - buf8[bufLen++] = code >>> 6 & 63 | 128; - buf8[bufLen++] = code & 63 | 128; - } else { - code = (code - 55296) * 1024 + (str.charCodeAt(++i) - 56320) + 65536; - if (code > 1114111) { - throw new Error("Unicode standard supports code points up to U+10FFFF"); - } - buf8[bufLen++] = (code >>> 18) + 240; - buf8[bufLen++] = code >>> 12 & 63 | 128; - buf8[bufLen++] = code >>> 6 & 63 | 128; - buf8[bufLen++] = code & 63 | 128; - } - if (bufLen >= 64) { - this._dataLength += 64; - Md5._md5cycle(this._state, buf32); - bufLen -= 64; - buf32[0] = buf32[16]; - } - } - this._bufferLength = bufLen; - return this; - } - /** - * Append an ASCII string to the hash buffer - * @param str String to append - */ - appendAsciiStr(str) { - const buf8 = this._buffer8; - const buf32 = this._buffer32; - let bufLen = this._bufferLength; - let i; - let j = 0; - for (; ; ) { - i = Math.min(str.length - j, 64 - bufLen); - while (i--) { - buf8[bufLen++] = str.charCodeAt(j++); - } - if (bufLen < 64) { - break; - } - this._dataLength += 64; - Md5._md5cycle(this._state, buf32); - bufLen = 0; - } - this._bufferLength = bufLen; - return this; - } - /** - * Append a byte array to the hash buffer - * @param input array to append - */ - appendByteArray(input) { - const buf8 = this._buffer8; - const buf32 = this._buffer32; - let bufLen = this._bufferLength; - let i; - let j = 0; - for (; ; ) { - i = Math.min(input.length - j, 64 - bufLen); - while (i--) { - buf8[bufLen++] = input[j++]; - } - if (bufLen < 64) { - break; - } - this._dataLength += 64; - Md5._md5cycle(this._state, buf32); - bufLen = 0; - } - this._bufferLength = bufLen; - return this; - } - /** - * Get the state of the hash buffer - */ - getState() { - const s = this._state; - return { - buffer: String.fromCharCode.apply(null, Array.from(this._buffer8)), - buflen: this._bufferLength, - length: this._dataLength, - state: [s[0], s[1], s[2], s[3]] - }; - } - /** - * Override the current state of the hash buffer - * @param state New hash buffer state - */ - setState(state) { - const buf = state.buffer; - const x = state.state; - const s = this._state; - let i; - this._dataLength = state.length; - this._bufferLength = state.buflen; - s[0] = x[0]; - s[1] = x[1]; - s[2] = x[2]; - s[3] = x[3]; - for (i = 0; i < buf.length; i += 1) { - this._buffer8[i] = buf.charCodeAt(i); - } - } - /** - * Hash the current state of the hash buffer and return the result - * @param raw Whether to return the value as an `Int32Array` - */ - end(raw = false) { - const bufLen = this._bufferLength; - const buf8 = this._buffer8; - const buf32 = this._buffer32; - const i = (bufLen >> 2) + 1; - this._dataLength += bufLen; - const dataBitsLen = this._dataLength * 8; - buf8[bufLen] = 128; - buf8[bufLen + 1] = buf8[bufLen + 2] = buf8[bufLen + 3] = 0; - buf32.set(Md5.buffer32Identity.subarray(i), i); - if (bufLen > 55) { - Md5._md5cycle(this._state, buf32); - buf32.set(Md5.buffer32Identity); - } - if (dataBitsLen <= 4294967295) { - buf32[14] = dataBitsLen; - } else { - const matches = dataBitsLen.toString(16).match(/(.*?)(.{0,8})$/); - if (matches === null) { - return; - } - const lo = parseInt(matches[2], 16); - const hi = parseInt(matches[1], 16) || 0; - buf32[14] = lo; - buf32[15] = hi; - } - Md5._md5cycle(this._state, buf32); - return raw ? this._state : Md5._hex(this._state); - } -}; -Md5.stateIdentity = new Int32Array([1732584193, -271733879, -1732584194, 271733878]); -Md5.buffer32Identity = new Int32Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); -Md5.hexChars = "0123456789abcdef"; -Md5.hexOut = []; -Md5.onePassHasher = new Md5(); -if (Md5.hashStr("hello") !== "5d41402abc4b2a76b9719d911017c592") { - throw new Error("Md5 self test failed."); -} - -// src/utils.ts -var PASTED_IMAGE_PREFIX = "Pasted image "; -var ImageExtensionRegex = /^(jpe?g|png|gif|svg|bmp|eps|webp)$/i; -function isMarkdownFile(extension) { - return extension === "md"; -} -function isCanvasFile(extension) { - return extension === "canvas"; -} -function isPastedImage(file) { - if (file instanceof import_obsidian.TFile) { - if (file.name.startsWith(PASTED_IMAGE_PREFIX)) { - return true; - } - } - return false; -} -function isImage(extension) { - const match = extension.match(ImageExtensionRegex); - if (match !== null) { - return true; - } - return false; -} -function stripPaths(src, dst) { - if (src === dst) { - return { stripedSrc: src, stripedDst: dst }; - } - const srcParts = src.split("/"); - const dstParts = dst.split("/"); - if (srcParts.length !== dstParts.length) { - return { stripedSrc: src, stripedDst: dst }; - } - for (let i = 0; i < srcParts.length; i++) { - const srcPart = srcParts[i]; - const dstPart = dstParts[i]; - if (srcPart !== dstPart) { - return { - stripedSrc: srcParts.slice(0, i + 1).join("/"), - stripedDst: dstParts.slice(0, i + 1).join("/") - }; - } - } - return { stripedSrc: "", stripedDst: "" }; -} -function matchExtension(extension, pattern) { - if (!pattern || pattern === "") - return false; - return new RegExp(pattern).test(extension); -} -function isAttachment(settings, filePath) { - let file = null; - if (filePath instanceof import_obsidian.TAbstractFile) { - file = filePath; - } else { - file = this.app.vault.getAbstractFileByPath(filePath); - } - if (file === null || !(file instanceof import_obsidian.TFile)) { - return false; - } - if (isMarkdownFile(file.extension) || isCanvasFile(file.extension)) { - return false; - } - return !matchExtension(file.extension, settings.excludeExtensionPattern); -} -async function md5sum(adapter, file) { - const md5 = new Md5(); - if (!adapter.exists(file.path, true)) { - return ""; - } - const content = await adapter.readBinary(file.path); - md5.appendByteArray(new Uint8Array(content)); - const ret = md5.end(); - return ret.toUpperCase(); -} -function validateExtensionEntry(setting, plugin) { - const wrongIndex = []; - if (setting.extensionOverride !== void 0) { - const extOverride = setting.extensionOverride; - if (extOverride.some((ext) => ext.extension === "")) { - wrongIndex.push({ type: "empty", index: extOverride.findIndex((ext) => ext.extension === "") }); - } - const duplicate = extOverride.map((ext) => ext.extension).filter((value, index, self) => self.indexOf(value) !== index); - if (duplicate.length > 0) { - duplicate.forEach((dupli) => { - wrongIndex.push({ type: "duplicate", index: extOverride.findIndex((ext) => dupli === ext.extension) }); - }); - } - const markdown = extOverride.filter((ext) => ext.extension === "md"); - if (markdown.length > 0) { - wrongIndex.push({ type: "md", index: extOverride.findIndex((ext) => ext.extension === "md") }); - } - const canvas = extOverride.filter((ext) => ext.extension === "canvas"); - if (canvas.length > 0) { - wrongIndex.push({ type: "canvas", index: extOverride.findIndex((ext) => ext.extension === "canvas") }); - } - const excludedFromSettings = plugin.excludeExtensionPattern.split("|"); - const excluded = extOverride.filter((ext) => excludedFromSettings.includes(ext.extension)); - if (excluded.length > 0) { - wrongIndex.push({ - type: "excluded", - index: extOverride.findIndex((ext) => excludedFromSettings.includes(ext.extension)) - }); - } - } - return wrongIndex; -} -function generateErrorExtensionMessage(type) { - if (type === "canvas") { - new import_obsidian.Notice("Canvas is not supported as an extension override."); - } else if (type === "md") { - new import_obsidian.Notice("Markdown is not supported as an extension override."); - } else if (type === "empty") { - new import_obsidian.Notice("Extension override cannot be empty."); - } else if (type === "duplicate") { - new import_obsidian.Notice("Duplicate extension override."); - } else if (type === "excluded") { - new import_obsidian.Notice("Extension override cannot be an excluded extension."); - } -} - -// src/lib/log.ts -var DEBUG = false; -if (DEBUG) - console.log("DEBUG is enabled"); -function debugLog(...args) { - if (DEBUG) { - console.log(new Date().toISOString().slice(11, 23), ...args); - } -} - -// src/model/extensionOverride.ts -function getExtensionOverrideSetting(extension, settings) { - if (settings.extensionOverride === void 0 || settings.extensionOverride.length === 0) { - return { extSetting: void 0 }; - } - for (let i = 0; i < settings.extensionOverride.length; i++) { - if (matchExtension(extension, settings.extensionOverride[i].extension)) { - debugLog( - "getExtensionOverrideSetting - ", - settings.extensionOverride[i].extension, - settings.extensionOverride[i] - ); - return { extSetting: settings.extensionOverride[i] }; - } - } - return { extSetting: void 0 }; -} -var OverrideExtensionModal = class extends import_obsidian2.Modal { - constructor(plugin, settings, onSubmit) { - super(plugin.app); - this.plugin = plugin; - this.settings = settings; - this.onSubmit = onSubmit; - } - displaySw(cont) { - cont.findAll(".setting-item").forEach((el) => { - var _a; - if ((_a = el.getAttr("class")) == null ? void 0 : _a.includes("override_root_folder_set")) { - if (this.settings.saveAttE === "obsFolder") { - el.hide(); - } else { - el.show(); - } - } - }); - } - onOpen() { - const { contentEl } = this; - contentEl.empty(); - contentEl.createEl("h3", { - text: `Extension settings for ${this.settings.extension}` - }); - new import_obsidian2.Setting(contentEl).setName("Root path to save attachment").setDesc("Select root path of attachment").addDropdown( - (text) => text.addOption(`${SETTINGS_ROOT_OBSFOLDER}`, "Copy Obsidian settings").addOption(`${SETTINGS_ROOT_INFOLDER}`, "In the folder specified below").addOption(`${SETTINGS_ROOT_NEXTTONOTE}`, "Next to note in folder specified below").setValue(this.settings.saveAttE).onChange(async (value) => { - this.settings.saveAttE = value; - this.displaySw(contentEl); - this.onOpen(); - }) - ); - if (this.settings.saveAttE !== "obsFolder") { - new import_obsidian2.Setting(contentEl).setName("Root folder").setClass("override_root_folder_set").addText( - (text) => text.setPlaceholder(DEFAULT_SETTINGS.attachPath.attachmentRoot).setValue(this.settings.attachmentRoot).onChange(async (value) => { - this.settings.attachmentRoot = value; - }) - ); - } - new import_obsidian2.Setting(contentEl).setName("Attachment path").setDesc( - `Path of attachment in root folder, available variables ${SETTINGS_VARIABLES_NOTEPATH}, ${SETTINGS_VARIABLES_NOTENAME} and ${SETTINGS_VARIABLES_NOTEPARENT}` - ).addText( - (text) => text.setPlaceholder(DEFAULT_SETTINGS.attachPath.attachmentPath).setValue(this.settings.attachmentPath).onChange(async (value) => { - this.settings.attachmentPath = value; - }) - ); - new import_obsidian2.Setting(contentEl).setName("Attachment format").setDesc( - `Define how to name the attachment file, available variables ${SETTINGS_VARIABLES_DATES}, ${SETTINGS_VARIABLES_NOTENAME}, ${SETTINGS_VARIABLES_MD5} and ${SETTINGS_VARIABLES_ORIGINALNAME}.` - ).addText( - (text) => text.setPlaceholder(DEFAULT_SETTINGS.attachPath.attachFormat).setValue(this.settings.attachFormat).onChange(async (value) => { - this.settings.attachFormat = value; - }) - ); - new import_obsidian2.Setting(contentEl).addButton( - (button) => button.setButtonText("Save").onClick(async () => { - this.onSubmit(this.settings); - this.close(); - }) - ); - } - onClose() { - const { contentEl } = this; - contentEl.empty(); - } -}; - -// src/settings/settings.ts -var DEFAULT_SETTINGS = { - attachPath: { - attachmentRoot: "", - saveAttE: `${SETTINGS_ROOT_OBSFOLDER}`, - attachmentPath: `${SETTINGS_VARIABLES_NOTEPATH}/${SETTINGS_VARIABLES_NOTENAME}`, - attachFormat: `IMG-${SETTINGS_VARIABLES_DATES}`, - type: "GLOBAL" /* GLOBAL */ - }, - dateFormat: "YYYYMMDDHHmmssSSS", - excludeExtensionPattern: "", - autoRenameAttachment: true, - excludedPaths: "", - excludePathsArray: [], - excludeSubpaths: false, - originalNameStorage: [], - overridePath: {}, - disableNotification: false -}; -var SettingTab = class extends import_obsidian3.PluginSettingTab { - constructor(app2, plugin) { - super(app2, plugin); - this.plugin = plugin; - } - displaySw(cont) { - cont.findAll(".setting-item").forEach((el) => { - var _a; - if ((_a = el.getAttr("class")) == null ? void 0 : _a.includes("root_folder_set")) { - if (this.plugin.settings.attachPath.saveAttE === "obsFolder") { - el.hide(); - } else { - el.show(); - } - } - }); - } - splitPath(path2) { - const splitted = path2.split(";"); - const rets = []; - for (const s of splitted) { - rets.push(s.trim()); - } - return { splittedPaths: rets }; - } - display() { - const { containerEl } = this; - containerEl.empty(); - new import_obsidian3.Setting(containerEl).setName("Root path to save attachment").setDesc("Select root path of attachment").addDropdown( - (text) => text.addOption(`${SETTINGS_ROOT_OBSFOLDER}`, "Copy Obsidian settings").addOption(`${SETTINGS_ROOT_INFOLDER}`, "In the folder specified below").addOption(`${SETTINGS_ROOT_NEXTTONOTE}`, "Next to note in folder specified below").setValue(this.plugin.settings.attachPath.saveAttE).onChange(async (value) => { - this.plugin.settings.attachPath.saveAttE = value; - this.displaySw(containerEl); - await this.plugin.saveSettings(); - }) - ); - new import_obsidian3.Setting(containerEl).setName("Root folder").setDesc("Root folder of new attachment").setClass("root_folder_set").addText( - (text) => text.setPlaceholder(DEFAULT_SETTINGS.attachPath.attachmentRoot).setValue(this.plugin.settings.attachPath.attachmentRoot).onChange(async (value) => { - debugLog("setting - attachment root:" + value); - this.plugin.settings.attachPath.attachmentRoot = value; - await this.plugin.saveSettings(); - }) - ); - new import_obsidian3.Setting(containerEl).setName("Attachment path").setDesc( - `Path of attachment in root folder, available variables ${SETTINGS_VARIABLES_NOTEPATH}, ${SETTINGS_VARIABLES_NOTENAME}, ${SETTINGS_VARIABLES_NOTEPARENT}` - ).addText( - (text) => text.setPlaceholder(DEFAULT_SETTINGS.attachPath.attachmentPath).setValue(this.plugin.settings.attachPath.attachmentPath).onChange(async (value) => { - debugLog("setting - attachment path:" + value); - this.plugin.settings.attachPath.attachmentPath = value; - await this.plugin.saveSettings(); - }) - ); - new import_obsidian3.Setting(containerEl).setName("Attachment format").setDesc( - `Define how to name the attachment file, available variables ${SETTINGS_VARIABLES_DATES}, ${SETTINGS_VARIABLES_NOTENAME}, ${SETTINGS_VARIABLES_MD5} and ${SETTINGS_VARIABLES_ORIGINALNAME}.` - ).addText( - (text) => text.setPlaceholder(DEFAULT_SETTINGS.attachPath.attachFormat).setValue(this.plugin.settings.attachPath.attachFormat).onChange(async (value) => { - debugLog("setting - attachment format:" + value); - this.plugin.settings.attachPath.attachFormat = value; - await this.plugin.saveSettings(); - }) - ); - new import_obsidian3.Setting(containerEl).setName("Date format").setDesc( - createFragment((frag) => { - frag.appendText("Moment date format to use "); - frag.createEl("a", { - href: "https://momentjscom.readthedocs.io/en/latest/moment/04-displaying/01-format", - text: "Moment format options" - }); - }) - ).addMomentFormat((component) => { - component.setPlaceholder(DEFAULT_SETTINGS.dateFormat).setValue(this.plugin.settings.dateFormat).onChange(async (value) => { - debugLog("setting - date format:" + value); - this.plugin.settings.dateFormat = value; - await this.plugin.saveSettings(); - }); - }); - new import_obsidian3.Setting(containerEl).setName("Automatically rename attachment").setDesc( - "Automatically rename the attachment folder/filename when you rename the folder/filename where the corresponding md/canvas file be placed." - ).addToggle( - (toggle) => toggle.setValue(this.plugin.settings.autoRenameAttachment).onChange(async (value) => { - debugLog("setting - automatically rename attachment folder:" + value); - this.plugin.settings.autoRenameAttachment = value; - await this.plugin.saveSettings(); - }) - ); - new import_obsidian3.Setting(containerEl).setName("Extension override").setDesc("Using the extension override if you want to autorename the attachment with a specific extension (e.g. pdf or zip).").addButton((btn) => { - btn.setButtonText("Add extension overrides").onClick(async () => { - if (this.plugin.settings.attachPath.extensionOverride === void 0) { - this.plugin.settings.attachPath.extensionOverride = []; - } - this.plugin.settings.attachPath.extensionOverride.push({ - extension: "", - attachmentRoot: this.plugin.settings.attachPath.attachmentRoot, - saveAttE: this.plugin.settings.attachPath.saveAttE, - attachmentPath: this.plugin.settings.attachPath.attachmentPath, - attachFormat: this.plugin.settings.attachPath.attachFormat - }); - await this.plugin.saveSettings(); - this.display(); - }); - }); - if (this.plugin.settings.attachPath.extensionOverride !== void 0) { - this.plugin.settings.attachPath.extensionOverride.forEach((ext) => { - new import_obsidian3.Setting(containerEl).setName("Extension").setDesc("Extension to override").setClass("override_extension_set").addText( - (text) => text.setPlaceholder("pdf|docx?").setValue(ext.extension).onChange(async (value) => { - ext.extension = value; - }) - ).addButton((btn) => { - btn.setIcon("trash").setTooltip("Remove extension override").onClick(async () => { - var _a, _b, _c; - const index = (_b = (_a = this.plugin.settings.attachPath.extensionOverride) == null ? void 0 : _a.indexOf(ext)) != null ? _b : -1; - (_c = this.plugin.settings.attachPath.extensionOverride) == null ? void 0 : _c.splice(index, 1); - await this.plugin.saveSettings(); - this.display(); - }); - }).addButton((btn) => { - btn.setIcon("pencil").setTooltip("Edit extension override").onClick(async () => { - new OverrideExtensionModal(this.plugin, ext, (result) => { - ext = result; - }).open(); - }); - }).addButton((btn) => { - btn.setIcon("check").setTooltip("Save extension override").onClick(async () => { - const wrongIndex = validateExtensionEntry(this.plugin.settings.attachPath, this.plugin.settings); - if (wrongIndex.length > 0) { - for (const i of wrongIndex) { - const resIndex = i.index < 0 ? 0 : i.index; - const wrongSetting = containerEl.getElementsByClassName("override_extension_set")[resIndex]; - wrongSetting.getElementsByTagName("input")[0].style.border = "1px solid var(--color-red)"; - generateErrorExtensionMessage(i.type); - } - return; - } - await this.plugin.saveSettings(); - this.display(); - new import_obsidian3.Notice("Saved extension override"); - }); - }); - }); - } - new import_obsidian3.Setting(containerEl).setName("Exclude extension pattern").setDesc(`Regex pattern to exclude certain extensions from being handled.`).addText( - (text) => text.setPlaceholder("pdf|docx?|xlsx?|pptx?|zip|rar").setValue(this.plugin.settings.excludeExtensionPattern).onChange(async (value) => { - this.plugin.settings.excludeExtensionPattern = value; - await this.plugin.saveSettings(); - }) - ); - new import_obsidian3.Setting(containerEl).setName("Excluded paths").setDesc( - `Provide the full path of the folder names (case sensitive and without leading slash '/') divided by semicolon (;) to be excluded from renaming.` - ).addTextArea((component) => { - component.setValue(this.plugin.settings.excludedPaths).onChange(async (value) => { - this.plugin.settings.excludedPaths = value; - const { splittedPaths } = this.splitPath(value); - this.plugin.settings.excludePathsArray = splittedPaths; - debugLog("setting - excluded paths:" + value, splittedPaths); - await this.plugin.saveSettings(); - }); - }); - new import_obsidian3.Setting(containerEl).setName("Exclude subpaths").setDesc("Turn on this option if you want to also exclude all subfolders of the folder paths provided above.").addToggle( - (toggle) => toggle.setValue(this.plugin.settings.excludeSubpaths).onChange(async (value) => { - debugLog("setting - excluded subpaths:" + value); - this.plugin.settings.excludeSubpaths = value; - await this.plugin.saveSettings(); - }) - ); - this.displaySw(containerEl); - } -}; - -// src/model/override.ts -var import_obsidian4 = require("obsidian"); -var OverrideModal = class extends import_obsidian4.Modal { - constructor(plugin, file, setting) { - super(plugin.app); - this.plugin = plugin; - this.file = file; - this.setting = setting; - } - displaySw(cont) { - cont.findAll(".setting-item").forEach((el) => { - var _a; - if ((_a = el.getAttr("class")) == null ? void 0 : _a.includes("override_root_folder_set")) { - if (this.setting.saveAttE === "obsFolder") { - el.hide(); - } else { - el.show(); - } - } - }); - } - onOpen() { - const { contentEl } = this; - contentEl.empty(); - contentEl.createEl("h3", { - text: "Overriding Settings" - }); - new import_obsidian4.Setting(contentEl).setName("Root path to save attachment").setDesc("Select root path of attachment").addDropdown( - (text) => text.addOption(`${SETTINGS_ROOT_OBSFOLDER}`, "Copy Obsidian settings").addOption(`${SETTINGS_ROOT_INFOLDER}`, "In the folder specified below").addOption(`${SETTINGS_ROOT_NEXTTONOTE}`, "Next to note in folder specified below").setValue(this.setting.saveAttE).onChange(async (value) => { - this.setting.saveAttE = value; - this.displaySw(contentEl); - }) - ); - new import_obsidian4.Setting(contentEl).setName("Root folder").setClass("override_root_folder_set").addText( - (text) => text.setPlaceholder(DEFAULT_SETTINGS.attachPath.attachmentRoot).setValue(this.setting.attachmentRoot).onChange(async (value) => { - debugLog("override - attachment root:" + value); - this.setting.attachmentRoot = value; - }) - ); - new import_obsidian4.Setting(contentEl).setName("Attachment path").setDesc( - `Path of attachment in root folder, available variables ${SETTINGS_VARIABLES_NOTEPATH}, ${SETTINGS_VARIABLES_NOTENAME} and ${SETTINGS_VARIABLES_NOTEPARENT}` - ).addText( - (text) => text.setPlaceholder(DEFAULT_SETTINGS.attachPath.attachmentPath).setValue(this.setting.attachmentPath).onChange(async (value) => { - debugLog("override - attachment path:" + value); - this.setting.attachmentPath = value; - }) - ); - new import_obsidian4.Setting(contentEl).setName("Attachment format").setDesc( - `Define how to name the attachment file, available variables ${SETTINGS_VARIABLES_DATES}, ${SETTINGS_VARIABLES_NOTENAME}, ${SETTINGS_VARIABLES_MD5} and ${SETTINGS_VARIABLES_ORIGINALNAME}.` - ).addText( - (text) => text.setPlaceholder(DEFAULT_SETTINGS.attachPath.attachFormat).setValue(this.setting.attachFormat).onChange(async (value) => { - debugLog("override - attachment format:" + value); - this.setting.attachFormat = value; - }) - ); - new import_obsidian4.Setting(contentEl).addButton((btn) => { - btn.setButtonText("Add extension overrides").onClick(async () => { - if (this.setting.extensionOverride === void 0) { - this.setting.extensionOverride = []; - } - this.setting.extensionOverride.push({ - extension: "", - saveAttE: this.setting.saveAttE, - attachmentRoot: this.setting.attachmentRoot, - attachmentPath: this.setting.attachmentPath, - attachFormat: this.setting.attachFormat - }); - this.onOpen(); - }); - }); - if (this.setting.extensionOverride !== void 0) { - this.setting.extensionOverride.forEach((ext) => { - new import_obsidian4.Setting(contentEl).setName("Extension").setDesc("Extension to override").setClass("override_extension_set").addText( - (text) => text.setPlaceholder("pdf").setValue(ext.extension).onChange(async (value) => { - ext.extension = value; - }) - ).addButton((btn) => { - btn.setIcon("trash").onClick(async () => { - var _a, _b, _c; - const index = (_b = (_a = this.setting.extensionOverride) == null ? void 0 : _a.indexOf(ext)) != null ? _b : -1; - (_c = this.setting.extensionOverride) == null ? void 0 : _c.splice(index, 1); - this.onOpen(); - }); - }).addButton((btn) => { - btn.setIcon("pencil").onClick(async () => { - new OverrideExtensionModal(this.plugin, ext, (result) => { - ext = result; - }).open(); - }); - }); - }); - } - new import_obsidian4.Setting(contentEl).addButton((btn) => { - btn.setButtonText("Reset").onClick(async () => { - this.setting = this.plugin.settings.attachPath; - delete this.plugin.settings.overridePath[this.file.path]; - await this.plugin.saveSettings(); - await this.plugin.loadSettings(); - new import_obsidian4.Notice(`Reset attachment setting of ${this.file.path}`); - this.close(); - }); - }).addButton( - (btn) => btn.setButtonText("Submit").setCta().onClick(async () => { - if (this.file instanceof import_obsidian4.TFile) { - this.setting.type = "FILE" /* FILE */; - } else if (this.file instanceof import_obsidian4.TFolder) { - this.setting.type = "FOLDER" /* FOLDER */; - } - this.plugin.settings.overridePath[this.file.path] = this.setting; - await this.plugin.saveSettings(); - debugLog("override - overriding settings:", this.file.path, this.setting); - new import_obsidian4.Notice(`Overridden attachment setting of ${this.file.path}`); - this.close(); - }) - ); - this.displaySw(contentEl); - } - onClose() { - const { contentEl } = this; - contentEl.empty(); - } -}; - -// src/model/confirm.ts -var import_obsidian9 = require("obsidian"); - -// src/arrange.ts -var import_obsidian8 = require("obsidian"); - -// src/lib/path.ts -var path = { - // Credit: [@creationix/path.js](https://gist.github.com/creationix/7435851) - join(...partSegments) { - let parts = []; - for (let i = 0, l = partSegments.length; i < l; i++) { - parts = parts.concat(partSegments[i].split("/")); - } - const newParts = []; - for (let i = 0, l = parts.length; i < l; i++) { - const part = parts[i]; - if (!part || part === ".") - continue; - if (part === "..") - newParts.pop(); - else - newParts.push(part); - } - if (parts[0] === "") - newParts.unshift(""); - return newParts.join("/"); - }, - // A simple function to get the dirname of a path - // Trailing slashes are ignored. Leading slash is preserved. - dirname(filepath) { - return this.join(filepath, ".."); - }, - // returns the last part of a path, e.g. 'foo.jpg' - basename(filepath, extension = "") { - const sp = filepath.split("/"); - const filename = sp[sp.length - 1]; - if (extension !== "") { - return filename.slice(0, filename.length - extension.length - 1); - } - return sp[sp.length - 1]; - }, - // return extension without dot, e.g. 'jpg' - extname(filepath) { - const positions = [...filepath.matchAll(new RegExp("\\.", "gi"))].map((a) => a.index); - const idx = positions[positions.length - 1]; - if (idx === void 0) { - return ""; - } - return filepath.slice(idx + 1); - } -}; - -// src/override.ts -var import_obsidian5 = require("obsidian"); -function getOverrideSetting(settings, file, oldPath = "") { - if (Object.keys(settings.overridePath).length === 0) { - return { settingPath: "", setting: settings.attachPath }; - } - const candidates = {}; - let fileType; - let filePath; - fileType = file instanceof import_obsidian5.TFile; - fileType = !(file instanceof import_obsidian5.TFolder); - if (oldPath === "") { - filePath = file.path; - } else { - filePath = oldPath; - } - for (const overridePath of Object.keys(settings.overridePath)) { - const overrideSetting = settings.overridePath[overridePath]; - if (fileType) { - if (overridePath === filePath && overrideSetting.type === "FILE" /* FILE */) { - return { settingPath: overridePath, setting: overrideSetting }; - } else if (filePath.startsWith(overridePath) && filePath.charAt(overridePath.length) === "/" && overrideSetting.type === "FOLDER" /* FOLDER */) { - candidates[overridePath] = overrideSetting; - } - } else { - if (overridePath === filePath && overrideSetting.type === "FOLDER" /* FOLDER */) { - return { settingPath: overridePath, setting: overrideSetting }; - } else if (filePath.startsWith(overridePath) && filePath.charAt(overridePath.length) === "/" && overrideSetting.type === "FOLDER" /* FOLDER */) { - candidates[overridePath] = overrideSetting; - } - } - } - if (Object.keys(candidates).length === 0) { - return { settingPath: "", setting: settings.attachPath }; - } - const sortedK = Object.keys(candidates).sort( - (a, b) => a.split("/").length > b.split("/").length ? -1 : a.split("/").length < b.split("/").length ? 1 : 0 - ); - debugLog("getOverrideSetting - sortedK:", sortedK); - for (const k of sortedK) { - if (filePath.startsWith(k)) { - return { settingPath: k, setting: candidates[k] }; - } - } - return { settingPath: "", setting: settings.attachPath }; -} -function getRenameOverrideSetting(settings, file, oldPath) { - if (Object.keys(settings.overridePath).length === 0) { - return { settingPath: "", setting: settings.attachPath }; - } - const { settingPath: np, setting: ns } = getOverrideSetting(settings, file); - const { settingPath: op, setting: os } = getOverrideSetting(settings, file, oldPath); - if (ns.type === "GLOBAL" /* GLOBAL */) { - return { settingPath: op, setting: os }; - } - if (os.type === "GLOBAL" /* GLOBAL */) { - return { settingPath: np, setting: ns }; - } - if (ns.type === "FILE" /* FILE */ && os.type === "FILE" /* FILE */) { - debugLog("getRenameOverrideSetting - both file type setting", np, op); - return { settingPath: "", setting: settings.attachPath }; - } - if (ns.type === "FILE" /* FILE */ && os.type === "FOLDER" /* FOLDER */) { - return { settingPath: np, setting: ns }; - } else if (ns.type === "FOLDER" /* FOLDER */ && os.type === "FILE" /* FILE */) { - return { settingPath: op, setting: os }; - } - if (ns.type === "FOLDER" /* FOLDER */ && os.type === "FOLDER" /* FOLDER */) { - const l = np.split("/").length; - const r = op.split("/").length; - if (l > r) { - return { settingPath: np, setting: ns }; - } else if (l < r) { - return { settingPath: op, setting: os }; - } else if (l === r) { - return { settingPath: "", setting: os }; - } - } - return { settingPath: "", setting: settings.attachPath }; -} -function updateOverrideSetting(settings, file, oldPath) { - const keys = Object.keys(settings.overridePath); - if (keys.length === 0 || file.path === oldPath) { - return; - } - const { settingPath, setting } = getOverrideSetting(settings, file, oldPath); - const copySetting = Object.assign({}, setting); - if (file.path === settingPath) { - return; - } - if (oldPath === settingPath) { - settings.overridePath[file.path] = copySetting; - delete settings.overridePath[settingPath]; - return; - } else { - const { stripedSrc, stripedDst } = stripPaths(oldPath, file.path); - if (stripedSrc === settingPath) { - settings.overridePath[stripedDst] = copySetting; - delete settings.overridePath[settingPath]; - return; - } - } -} -function deleteOverrideSetting(settings, file) { - const keys = Object.keys(settings.overridePath); - for (const key of keys) { - if (file.path === key) { - delete settings.overridePath[key]; - return true; - } - } - return false; -} - -// src/lib/linkDetector.ts -var getAllLinkMatchesInFile = async (mdFile, app2, fileText) => { - const linkMatches = []; - if (fileText === void 0) { - fileText = await app2.vault.read(mdFile); - } - const wikiRegex = /\[\[.*?\]\]/g; - const wikiMatches = fileText.match(wikiRegex); - if (wikiMatches) { - const fileRegex = /(?<=\[\[).*?(?=(\]|\|))/; - for (const wikiMatch of wikiMatches) { - if (matchIsWikiTransclusion(wikiMatch)) { - const fileName = getTransclusionFileName(wikiMatch); - const file = app2.metadataCache.getFirstLinkpathDest(fileName, mdFile.path); - if (fileName !== "") { - const linkMatch = { - type: "wikiTransclusion", - match: wikiMatch, - linkText: file ? file.path : fileName, - sourceFilePath: mdFile.path - }; - linkMatches.push(linkMatch); - continue; - } - } - const fileMatch = wikiMatch.match(fileRegex); - if (fileMatch) { - if (fileMatch[0].startsWith("http")) - continue; - const file = app2.metadataCache.getFirstLinkpathDest(fileMatch[0], mdFile.path); - const linkMatch = { - type: "wiki", - match: wikiMatch, - linkText: file ? file.path : fileMatch[0], - sourceFilePath: mdFile.path - }; - linkMatches.push(linkMatch); - } - } - } - const markdownRegex = /\[(^$|.*?)\]\((.*?)\)/g; - const markdownMatches = fileText.match(markdownRegex); - if (markdownMatches) { - const fileRegex = /(?<=\().*(?=\))/; - for (const markdownMatch of markdownMatches) { - if (matchIsMdTransclusion(markdownMatch)) { - const fileName = getTransclusionFileName(markdownMatch); - const file = app2.metadataCache.getFirstLinkpathDest(fileName, mdFile.path); - if (fileName !== "") { - const linkMatch = { - type: "mdTransclusion", - match: markdownMatch, - linkText: file ? file.path : fileName, - sourceFilePath: mdFile.path - }; - linkMatches.push(linkMatch); - continue; - } - } - const fileMatch = markdownMatch.match(fileRegex); - if (fileMatch) { - if (fileMatch[0].startsWith("http")) - continue; - const file = app2.metadataCache.getFirstLinkpathDest(fileMatch[0], mdFile.path); - const linkMatch = { - type: "markdown", - match: markdownMatch, - linkText: file ? file.path : fileMatch[0], - sourceFilePath: mdFile.path - }; - linkMatches.push(linkMatch); - } - } - } - return linkMatches; -}; -var wikiTransclusionRegex = /\[\[(.*?)#.*?\]\]/; -var wikiTransclusionFileNameRegex = /(?<=\[\[)(.*)(?=#)/; -var mdTransclusionRegex = /\[.*?]\((.*?)#.*?\)/; -var mdTransclusionFileNameRegex = /(?<=\]\()(.*)(?=#)/; -var matchIsWikiTransclusion = (match) => { - return wikiTransclusionRegex.test(match); -}; -var matchIsMdTransclusion = (match) => { - return mdTransclusionRegex.test(match); -}; -var getTransclusionFileName = (match) => { - const isWiki = wikiTransclusionRegex.test(match); - const isMd = mdTransclusionRegex.test(match); - if (isWiki || isMd) { - const fileNameMatch = match.match(isWiki ? wikiTransclusionFileNameRegex : mdTransclusionFileNameRegex); - if (fileNameMatch) - return fileNameMatch[0]; - } - return ""; -}; - -// src/lib/deduplicate.ts -function escapeRegExp(s) { - return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); -} -async function deduplicateNewName(newName, file) { - const dir = file.path; - const listed = await this.app.vault.adapter.list(dir); - debugLog("deduplicateNewName - sibling files", listed); - const newNameExt = path.extname(newName), newNameStem = newName.slice(0, newName.length - newNameExt.length - 1), newNameStemEscaped = escapeRegExp(newNameStem), delimiter = "-", delimiterEscaped = escapeRegExp(delimiter); - const dupNameRegex = new RegExp( - `^(?${newNameStemEscaped})${delimiterEscaped}(?\\d{1,3})\\.${newNameExt}$` - ); - debugLog("dupNameRegex", dupNameRegex); - const dupNameNumbers = []; - let isNewNameExist = false; - for (let sibling of listed.files) { - sibling = path.basename(sibling); - if (sibling == newName) { - isNewNameExist = true; - continue; - } - const m = dupNameRegex.exec(sibling); - if (!m || m.groups === void 0) - continue; - dupNameNumbers.push(parseInt(m.groups.number)); - } - if (isNewNameExist) { - const newNumber = dupNameNumbers.length > 0 ? Math.max(...dupNameNumbers) + 1 : 1; - newName = `${newNameStem}${delimiter}${newNumber}.${newNameExt}`; - } - return { - name: newName, - basename: newName.slice(0, newName.length - newNameExt.length - 1), - extension: newNameExt - }; -} - -// src/settings/metadata.ts -var import_obsidian7 = require("obsidian"); - -// src/commons.ts -var import_obsidian6 = require("obsidian"); -function getActiveFile(app2) { - const view = getActiveView(app2); - if (view == null) { - return void 0; - } else if (view.file == null) { - return void 0; - } else { - return view.file; - } -} -function getActiveView(app2) { - return app2.workspace.getActiveViewOfType(import_obsidian6.TextFileView); -} -function getRootPath(notePath, setting) { - let root; - const obsmediadir = app.vault.getConfig("attachmentFolderPath"); - switch (setting.saveAttE) { - case `${SETTINGS_ROOT_INFOLDER}`: - root = path.join(setting.attachmentRoot); - break; - case `${SETTINGS_ROOT_NEXTTONOTE}`: - root = path.join(notePath, setting.attachmentRoot.replace("./", "")); - break; - default: - if (obsmediadir === "/") { - root = obsmediadir; - } else if (obsmediadir === "./") { - root = path.join(notePath); - } else if (obsmediadir.match(/\.\/.+/g) !== null) { - root = path.join(notePath, obsmediadir.replace("./", "")); - } else { - root = obsmediadir; - } - } - return root === "/" ? root : (0, import_obsidian6.normalizePath)(root); -} -async function checkEmptyFolder(adapter, path2) { - const exist = await adapter.exists(path2, true); - if (!exist) { - return true; - } - const data = await adapter.list(path2); - if (data.files.length > 0) { - return false; - } - if (data.folders.length > 0) { - for (let i = 0; i < data.folders.length; i++) { - return checkEmptyFolder(adapter, data.folders[i]); - } - } - return true; -} - -// src/settings/metadata.ts -var Metadata = class { - constructor(path2, name, basename, extension, parentPath, parentName, attachmentFile) { - /** parent path of file */ - this.parentPath = ""; - /** parent path basename of file */ - this.parentName = ""; - this.path = path2; - this.name = name; - this.basename = basename; - this.extension = extension; - this.parentPath = parentPath; - this.parentName = parentName; - this.attachmentFile = attachmentFile; - } - /** - * Returns a formatted attachment file name according to the provided settings. - * - * @param {AttachmentPathSettings} setting - attachment path settings object - * @param {string} dateFormat - format string for date and time - * @param {string} originalName - name of the original attachment - * @param {string} [linkName] - optional name for the attachment link - * @return {string} the formatted attachment file name - */ - async getAttachFileName(setting, dateFormat, originalName, adapter, linkName) { - const dateTime = window.moment().format(dateFormat); - let md5 = ""; - let attachFormat = ""; - if (this.attachmentFile !== void 0) { - md5 = await md5sum(adapter, this.attachmentFile); - const { extSetting } = getExtensionOverrideSetting(this.attachmentFile.extension, setting); - if (extSetting !== void 0) { - attachFormat = extSetting.attachFormat; - } else { - attachFormat = setting.attachFormat; - } - } - if (attachFormat.includes(SETTINGS_VARIABLES_ORIGINALNAME)) { - if (originalName === "" && linkName != void 0) { - return linkName; - } else { - return attachFormat.replace(`${SETTINGS_VARIABLES_DATES}`, dateTime).replace(`${SETTINGS_VARIABLES_NOTENAME}`, this.basename).replace(`${SETTINGS_VARIABLES_ORIGINALNAME}`, originalName).replace(`${SETTINGS_VARIABLES_MD5}`, md5); - } - } - return attachFormat.replace(`${SETTINGS_VARIABLES_DATES}`, dateTime).replace(`${SETTINGS_VARIABLES_NOTENAME}`, this.basename).replace(`${SETTINGS_VARIABLES_MD5}`, md5); - } - /** - * Returns the attachment path based on the given AttachmentPathSettings object. - * - * @param {AttachmentPathSettings} setting - An object containing the attachment path settings. - * @return {string} The normalized attachment path. - */ - getAttachmentPath(setting, dateFormat) { - const dateTime = window.moment().format(dateFormat); - let root = ""; - let attachPath = ""; - if (this.attachmentFile !== void 0) { - const { extSetting } = getExtensionOverrideSetting(this.attachmentFile.extension, setting); - if (extSetting !== void 0) { - root = getRootPath(this.parentPath, extSetting); - attachPath = path.join( - root, - extSetting.attachmentPath.replace(`${SETTINGS_VARIABLES_NOTEPATH}`, this.parentPath).replace(`${SETTINGS_VARIABLES_NOTENAME}`, this.basename).replace(`${SETTINGS_VARIABLES_NOTEPARENT}`, this.parentName).replace(`${SETTINGS_VARIABLES_DATES}`, dateTime) - ); - return (0, import_obsidian7.normalizePath)(attachPath); - } - } - root = getRootPath(this.parentPath, setting); - debugLog("getAttachmentPath - root", root); - attachPath = path.join( - root, - setting.attachmentPath.replace(`${SETTINGS_VARIABLES_NOTEPATH}`, this.parentPath).replace(`${SETTINGS_VARIABLES_NOTENAME}`, this.basename).replace(`${SETTINGS_VARIABLES_NOTEPARENT}`, this.parentName).replace(`${SETTINGS_VARIABLES_DATES}`, dateTime) - ); - return (0, import_obsidian7.normalizePath)(attachPath); - } -}; -function getMetadata(file, attach) { - const parentPath = path.dirname(file); - const parentName = path.basename(parentPath); - const name = path.basename(file); - const extension = path.extname(file); - const basename = path.basename(file, extension); - return new Metadata(file, name, basename, extension, parentPath, parentName, attach); -} - -// src/exclude.ts -function isExcluded(path2, settings) { - debugLog("excludePathsArray: ", settings.excludePathsArray); - for (const excludedPath of settings.excludePathsArray) { - if (excludedPath.length === 0) { - continue; - } - if (settings.excludeSubpaths && path2.startsWith(excludedPath)) { - debugLog("isExcluded: ", path2); - return true; - } else { - if (path2 === excludedPath) { - return true; - } - } - } - return false; -} - -// src/lib/originalStorage.ts -function containOriginalNameVariable(setting, ext) { - const { extSetting } = getExtensionOverrideSetting(ext, setting); - if (extSetting !== void 0 && extSetting.attachFormat.contains(SETTINGS_VARIABLES_ORIGINALNAME) || setting.attachFormat.contains(SETTINGS_VARIABLES_ORIGINALNAME)) { - return true; - } - return false; -} -function saveOriginalName(settings, setting, ext, data) { - if (settings.originalNameStorage === void 0) { - settings.originalNameStorage = []; - } - if (containOriginalNameVariable(setting, ext)) { - settings.originalNameStorage.filter((n) => n.md5 == data.md5).forEach((n) => settings.originalNameStorage.remove(n)); - settings.originalNameStorage.push(data); - } -} -function loadOriginalName(settings, setting, ext, md5) { - if (containOriginalNameVariable(setting, ext)) { - const first = settings.originalNameStorage.find((data) => data.md5 === md5); - const last = settings.originalNameStorage.reverse().find((data) => data.md5 === md5); - if (first === void 0 || last == void 0) { - return void 0; - } - if (first.md5 === last.md5 && first.n === last.n) { - return last; - } else if (first.md5 === last.md5 && first.n !== last.n) { - settings.originalNameStorage.remove(first); - return last; - } - } - return void 0; -} - -// src/arrange.ts -var bannerRegex = /!\[\[(.*?)\]\]/i; -var ArrangeHandler = class { - constructor(settings, app2, plugin) { - this.settings = settings; - this.app = app2; - this.plugin = plugin; - } - /** - * Rearranges attachments that are linked by markdown or canvas. - * Only rearranges attachments if autoRenameAttachment is enabled in settings. - * - * @param {RearrangeType} type - The type of attachments to rearrange. - * @param {TFile} file - The file to which the attachments are linked (optional), if the type was "file", thi should be provided. - * @param {string} oldPath - The old path of the file (optional), used for rename event. - */ - async rearrangeAttachment(type, file, oldPath) { - var _a; - if (!this.settings.autoRenameAttachment) { - debugLog("rearrangeAttachment - autoRenameAttachment not enable"); - return; - } - const attachments = await this.getAttachmentsInVault(this.settings, type, file, oldPath); - debugLog("rearrangeAttachment - attachments:", Object.keys(attachments).length, Object.entries(attachments)); - for (const obNote of Object.keys(attachments)) { - const innerFile = this.app.vault.getAbstractFileByPath(obNote); - if (!(innerFile instanceof import_obsidian8.TFile) || isAttachment(this.settings, innerFile)) { - debugLog(`rearrangeAttachment - ${obNote} not exists or is attachment, skipped`); - continue; - } - const { setting } = getOverrideSetting(this.settings, innerFile); - if (attachments[obNote].size == 0) { - continue; - } - const md = getMetadata(obNote); - const attachPath = md.getAttachmentPath(setting, this.settings.dateFormat); - if (!await this.app.vault.adapter.exists(attachPath, true)) { - if (oldPath != void 0 && await this.app.vault.adapter.exists(attachPath, false)) { - const mdOld = getMetadata(oldPath); - const attachPathOld = mdOld.getAttachmentPath(setting, this.settings.dateFormat); - this.app.vault.adapter.rename(attachPathOld, attachPath); - } else { - await this.app.vault.adapter.mkdir(attachPath); - } - } - for (let link of attachments[obNote]) { - try { - link = decodeURI(link); - } catch (err) { - console.log(`Invalid link: ${link}, err: ${err}`); - continue; - } - debugLog(`rearrangeAttachment - article: ${obNote} links: ${link}`); - const linkFile = this.app.vault.getAbstractFileByPath(link); - if (linkFile === null || !(linkFile instanceof import_obsidian8.TFile)) { - debugLog(`${link} not exists, skipped`); - continue; - } - const metadata = getMetadata(obNote, linkFile); - const md5 = await md5sum(this.app.vault.adapter, linkFile); - const originalName = loadOriginalName(this.settings, setting, linkFile.extension, md5); - debugLog("rearrangeAttachment - original name:", originalName); - let attachName = ""; - if (containOriginalNameVariable(setting, linkFile.extension)) { - attachName = await metadata.getAttachFileName( - setting, - this.settings.dateFormat, - (_a = originalName == null ? void 0 : originalName.n) != null ? _a : "", - this.app.vault.adapter, - path.basename(link, path.extname(link)) - ); - } else { - attachName = await metadata.getAttachFileName( - setting, - this.settings.dateFormat, - path.basename(link, path.extname(link)), - this.app.vault.adapter - ); - } - if (attachPath == path.dirname(link) && attachName === path.basename(link, path.extname(link))) { - continue; - } - const attachPathFile = this.app.vault.getAbstractFileByPath(attachPath); - if (attachPathFile === null || !(attachPathFile instanceof import_obsidian8.TFolder)) { - debugLog(`${attachPath} not exists, skipped`); - continue; - } - const { name } = await deduplicateNewName(attachName + "." + path.extname(link), attachPathFile); - debugLog("rearrangeAttachment - deduplicated name:", name); - await this.app.fileManager.renameFile(linkFile, path.join(attachPath, name)); - } - } - } - /** - * Retrieves the attachments in the vault based on the specified settings and type. - * If a file is provided, only attachments related to that file will be returned. - * - * @param {AttachmentManagementPluginSettings} settings - The settings for the attachment management plugin. - * @param {RearrangeType} type - The type of attachments to retrieve. - * @param {TFile} [file] - The file to filter attachments by. Optional. - * @return {Promise>>} - A promise that resolves to a record of attachments, where each key is a file name and each value is a set of associated attachment names. - */ - async getAttachmentsInVault(settings, type, file, oldPath) { - let attachmentsRecord = {}; - attachmentsRecord = await this.getAttachmentsInVaultByLinks(settings, type, file, oldPath); - return attachmentsRecord; - } - /** - * Modified from https://github.com/ozntel/oz-clear-unused-images-obsidian/blob/master/src/util.ts#LL48C21-L48C21 - * Retrieves a record of attachments in the vault based on the given settings and type. - * - * @param {AttachmentManagementPluginSettings} settings - The settings for the attachment management plugin. - * @param {RearrangeType} type - The type of attachments to retrieve. - * @param {TFile} file - The file to retrieve attachments for (optional). - * @return {Promise>>} - A promise that resolves to a record of attachments. - */ - async getAttachmentsInVaultByLinks(settings, type, file, oldPath) { - const attachmentsRecord = {}; - let resolvedLinks = {}; - let allFiles = []; - if (type == 1 /* LINKS */) { - resolvedLinks = this.app.metadataCache.resolvedLinks; - allFiles = this.app.vault.getFiles(); - } else if (type == 0 /* ACTIVE */) { - const file2 = getActiveFile(this.app); - if (file2) { - if (file2.parent && isExcluded(file2.parent.path, this.settings) || isAttachment(this.settings, file2)) { - allFiles = []; - new import_obsidian8.Notice(`${file2.path} was excluded, skipped`); - } else { - debugLog("getAttachmentsInVaultByLinks - active:", file2.path); - allFiles = [file2]; - if (this.app.metadataCache.resolvedLinks[file2.path]) { - resolvedLinks[file2.path] = this.app.metadataCache.resolvedLinks[file2.path]; - } - debugLog("getAttachmentsInVaultByLinks - resolvedLinks:", resolvedLinks); - } - } - } else if (type == 2 /* FILE */ && file != void 0) { - if (file.parent && isExcluded(file.parent.path, this.settings) || isAttachment(this.settings, file)) { - allFiles = []; - new import_obsidian8.Notice(`${file.path} was excluded, skipped`); - } else { - debugLog("getAttachmentsInVaultByLinks - file:", file.path); - allFiles = [file]; - const rlinks = this.app.metadataCache.resolvedLinks[file.path]; - if (rlinks) { - debugLog("getAttachmentsInVaultByLinks - rlinks:", rlinks); - resolvedLinks[file.path] = rlinks; - } else if (oldPath) { - debugLog("getAttachmentsInVaultByLinks - oldPath:", oldPath); - resolvedLinks[file.path] = this.app.metadataCache.resolvedLinks[oldPath]; - } - debugLog("getAttachmentsInVaultByLinks - resolvedLinks:", resolvedLinks); - } - } - debugLog("getAttachmentsInVaultByLinks - allFiles:", allFiles.length, allFiles); - if (resolvedLinks) { - for (const [mdFile, links] of Object.entries(resolvedLinks)) { - const attachmentsSet = /* @__PURE__ */ new Set(); - if (links) { - for (const [filePath] of Object.entries(links)) { - if (isAttachment(settings, filePath)) { - this.addToSet(attachmentsSet, filePath); - } - } - this.addToRecord(attachmentsRecord, mdFile, attachmentsSet); - } - } - } - for (let i = 0; i < allFiles.length; i++) { - const obsFile = allFiles[i]; - const attachmentsSet = /* @__PURE__ */ new Set(); - if (obsFile.parent && isExcluded(obsFile.parent.path, this.settings)) { - continue; - } - if (isMarkdownFile(obsFile.extension)) { - const fileCache = this.app.metadataCache.getFileCache(obsFile); - if (fileCache === null) { - continue; - } - if (fileCache.frontmatter) { - const frontmatter = fileCache.frontmatter; - for (const k of Object.keys(frontmatter)) { - if (typeof frontmatter[k] === "string") { - const formatMatch = frontmatter[k].match(bannerRegex); - if (formatMatch && formatMatch[1]) { - const fileName = formatMatch[1]; - const file2 = this.app.metadataCache.getFirstLinkpathDest(fileName, obsFile.path); - if (file2 && isAttachment(settings, file2.path)) { - this.addToSet(attachmentsSet, file2.path); - } - } - } - } - } - const linkMatches = await getAllLinkMatchesInFile(obsFile, app); - for (const linkMatch of linkMatches) { - if (isAttachment(settings, linkMatch.linkText)) { - this.addToSet(attachmentsSet, linkMatch.linkText); - } - } - } else if (isCanvasFile(obsFile.extension)) { - const fileRead = await this.app.vault.cachedRead(obsFile); - if (!fileRead || fileRead.length === 0) { - continue; - } - let canvasData; - try { - canvasData = JSON.parse(fileRead); - } catch (e) { - debugLog("getAttachmentsInVaultByLinks - parse canvas data error", e); - continue; - } - if (canvasData.nodes && canvasData.nodes.length > 0) { - for (const node of canvasData.nodes) { - if (node.type === "file") { - if (isAttachment(settings, node.file)) { - this.addToSet(attachmentsSet, node.file); - } - } else if (node.type == "text") { - const linkMatches = await getAllLinkMatchesInFile(obsFile, app, node.text); - for (const linkMatch of linkMatches) { - if (isAttachment(settings, linkMatch.linkText)) { - this.addToSet(attachmentsSet, linkMatch.linkText); - } - } - } - } - } - } - this.addToRecord(attachmentsRecord, obsFile.path, attachmentsSet); - } - return attachmentsRecord; - } - addToRecord(record, key, value) { - if (record[key] === void 0) { - record[key] = value; - return; - } - const valueSet = record[key]; - for (const val of value) { - this.addToSet(valueSet, val); - } - record[key] = valueSet; - } - addToSet(setObj, value) { - if (!setObj.has(value)) { - setObj.add(value); - } - } - needToRename(settings, attachPath, attachName, noteName, link) { - const linkPath = path.dirname(link); - const linkName = path.basename(link, path.extname(link)); - if (linkName.length !== attachName.length) { - return true; - } - if (attachPath !== linkPath) { - return true; - } else { - if (settings.attachFormat.includes(SETTINGS_VARIABLES_NOTENAME) && !linkName.includes(noteName)) { - return true; - } - const noNoteNameAttachFormat = settings.attachFormat.split(SETTINGS_VARIABLES_NOTENAME); - if (settings.attachFormat.includes(SETTINGS_VARIABLES_DATES)) { - for (const formatPart in noNoteNameAttachFormat) { - const splited = formatPart.split(SETTINGS_VARIABLES_DATES); - for (const part in splited) { - if (!linkName.includes(part)) { - return true; - } - } - } - } - } - return false; - } -}; - -// src/model/confirm.ts -var ConfirmModal = class extends import_obsidian9.Modal { - constructor(plugin) { - super(plugin.app); - this.plugin = plugin; - } - onOpen() { - const { contentEl } = this; - contentEl.empty(); - contentEl.createEl("h3", { - text: "Tips" - }); - contentEl.createSpan("", (el) => { - el.innerText = "This operation is irreversible and experimental. Please backup your vault first!"; - }); - new import_obsidian9.Setting(contentEl).addButton((btn) => { - btn.setButtonText("Cancel").setCta().onClick(() => { - this.close(); - }); - }).addButton( - (btn) => btn.setButtonText("Continue").onClick(async () => { - new ArrangeHandler(this.plugin.settings, this.plugin.app, this.plugin).rearrangeAttachment(1 /* LINKS */).finally(() => { - new import_obsidian9.Notice("Arrange completed"); - this.close(); - }); - }) - ); - } - onClose() { - const { contentEl } = this; - contentEl.empty(); - } -}; - -// src/create.ts -var import_obsidian10 = require("obsidian"); -var CreateHandler = class { - constructor(plugin, settings) { - this.plugin = plugin; - this.app = this.plugin.app; - this.settings = settings; - } - /** - * Post-processing of created attachment file (for paste and drop event). - * @param attach - the attachment file to process - * @param source - the notes file that linked to attach - * @returns - none - */ - processAttach(attach, source) { - if (source.parent && isExcluded(source.parent.path, this.settings)) { - debugLog("processAttach - not a file or exclude path:", source.path); - new import_obsidian10.Notice(`${source.path} was excluded, skipped`); - return; - } - const { setting } = getOverrideSetting(this.settings, source); - const { extSetting } = getExtensionOverrideSetting(attach.extension, setting); - debugLog("processAttach - file.extension:", attach.extension); - if (extSetting === void 0 && !isImage(attach.extension) && !isPastedImage(attach)) { - debugLog("renameFiles - no handle extension:", attach.extension); - return; - } - const metadata = getMetadata(source.path, attach); - debugLog("processAttach - metadata:", metadata); - const attachPath = metadata.getAttachmentPath(setting, this.settings.dateFormat); - metadata.getAttachFileName(setting, this.settings.dateFormat, attach.basename, this.app.vault.adapter).then((attachName) => { - attachName = attachName + "." + attach.extension; - this.app.vault.adapter.exists(attachPath, true).then(async (exists) => { - if (!exists) { - await this.app.vault.adapter.mkdir(attachPath); - debugLog("processAttach - create path:", attachPath); - } - }).finally(() => { - const attachPathFolder = this.app.vault.getAbstractFileByPath(attachPath); - deduplicateNewName(attachName, attachPathFolder).then(({ name }) => { - debugLog("processAttach - new path of file:", path.join(attachPath, name)); - this.renameCreateFile(attach, attachPath, name, source); - }); - }); - }); - } - /** - * Rename the file specified by `@param file`, and update the link of the file if specified updateLink - * @param attach - file to rename - * @param attachPath - where to the renamed file will be move to - * @param attachName - name of the renamed file - * @param source - associated active file - * @returns - none - */ - renameCreateFile(attach, attachPath, attachName, source) { - const dst = (0, import_obsidian10.normalizePath)(path.join(attachPath, attachName)); - debugLog("renameFile - ", attach.path, " to ", dst); - const original = attach.basename; - const name = attach.name; - this.app.fileManager.renameFile(attach, dst).then(() => { - new import_obsidian10.Notice(`Renamed ${name} to ${attachName}.`); - }).finally(() => { - const { setting } = getOverrideSetting(this.settings, source); - md5sum(this.app.vault.adapter, attach).then((md5) => { - saveOriginalName(this.settings, setting, attach.extension, { - n: original, - md5 - }); - this.plugin.saveData(this.settings); - }); - }); - } -}; - -// src/main.ts -var AttachmentManagementPlugin = class extends import_obsidian11.Plugin { - constructor() { - super(...arguments); - this.createdQueue = []; - } - async onload() { - await this.loadSettings(); - console.log(`Plugin loading: ${this.manifest.name} v.${this.manifest.version}`); - this.app.workspace.onLayoutReady(() => { - this.initCommands(); - this.registerEvent( - this.app.workspace.on("file-menu", async (menu, file) => { - if (file.parent && isExcluded(file.parent.path, this.settings) || isAttachment(this.settings, file)) { - return; - } - menu.addItem((item) => { - item.setTitle("Overriding attachment setting").setIcon("image-plus").onClick(async () => { - const { setting } = getOverrideSetting(this.settings, file); - const fileSetting = Object.assign({}, setting); - this.overrideConfiguration(file, fileSetting); - }); - }); - }) - ); - this.registerEvent( - this.app.vault.on("create", async (file) => { - debugLog("on create event - file:", file.path); - if (!(file instanceof import_obsidian11.TFile)) { - return; - } - const curentTime = new Date().getTime(); - const timeGapMs = curentTime - file.stat.mtime; - const timeGapCs = curentTime - file.stat.ctime; - if (timeGapMs > 1e3 || timeGapCs > 1e3 || isMarkdownFile(file.extension) || isCanvasFile(file.extension)) { - return; - } - if (matchExtension(file.extension, this.settings.excludeExtensionPattern)) { - debugLog("create - excluded file by extension", file); - return; - } - this.createdQueue.push(file); - }) - ); - this.registerEvent( - this.app.vault.on("modify", (file) => { - debugLog("on modify event - create queue:", this.createdQueue); - if (this.createdQueue.length < 1 || !(file instanceof import_obsidian11.TFile)) { - return; - } - debugLog("on modify event - file:", file.path); - this.app.vault.adapter.process(file.path, (pdata) => { - const f = this.createdQueue.first(); - if (f != void 0) { - this.app.vault.adapter.exists(f.path, true).then((exist) => { - if (exist) { - const processor = new CreateHandler(this, this.settings); - const link = this.app.fileManager.generateMarkdownLink(f, file.path); - if (file.extension == "md" && pdata.indexOf(link) != -1 || file.extension == "canvas" && pdata.indexOf(f.path) != -1) { - this.createdQueue.remove(f); - processor.processAttach(f, file); - } - } else { - debugLog("on modify event - file does not exist:", f.path); - this.createdQueue.remove(f); - } - }); - } - return pdata; - }); - }) - ); - this.registerEvent( - // when trigger a rename event on folder, for each file/folder in this renamed folder (include itself) will trigger this event - this.app.vault.on("rename", async (file, oldPath) => { - debugLog("on rename event - new path and old path:", file.path, oldPath); - const { setting } = getRenameOverrideSetting(this.settings, file, oldPath); - debugLog("rename - using settings:", setting); - if (setting.type === "FOLDER" /* FOLDER */ || setting.type === "FILE" /* FILE */) { - updateOverrideSetting(this.settings, file, oldPath); - this.saveSettings(); - } - debugLog("rename - updated settings:", setting); - if (!this.settings.autoRenameAttachment) { - debugLog("rename - auto rename not enabled:", this.settings.autoRenameAttachment); - return; - } - if (file instanceof import_obsidian11.TFile) { - if (file.parent && isExcluded(file.parent.path, this.settings)) { - debugLog("rename - exclude path:", file.parent.path); - new import_obsidian11.Notice(`${file.path} was excluded`); - return; - } - if (isAttachment(this.settings, file)) { - debugLog("rename - not processing rename on attachment:", file.path); - return; - } - await new ArrangeHandler(this.settings, this.app, this).rearrangeAttachment( - 2 /* FILE */, - file, - oldPath - ); - const oldMetadata = getMetadata(oldPath); - const oldAttachPath = oldMetadata.getAttachmentPath(setting, this.settings.dateFormat); - this.app.vault.adapter.exists(oldAttachPath, true).then((exists) => { - if (exists) { - checkEmptyFolder(this.app.vault.adapter, oldAttachPath).then((empty) => { - if (empty) { - this.app.vault.adapter.rmdir(oldAttachPath, true); - } - }); - } - }); - } else if (file instanceof import_obsidian11.TFolder) { - return; - } - }) - ); - this.registerEvent( - this.app.vault.on("delete", async (file) => { - debugLog("on delete event - file path:", file.path); - if (file.parent && isExcluded(file.parent.path, this.settings) || isAttachment(this.settings, file)) { - debugLog("delete - exclude path or the file is an attachment:", file.path); - return; - } - if (deleteOverrideSetting(this.settings, file)) { - await this.saveSettings(); - new import_obsidian11.Notice("Removed override setting of " + file.path); - } - if (file instanceof import_obsidian11.TFile) { - const oldMetadata = getMetadata(file.path); - const { setting } = getOverrideSetting(this.settings, file); - const oldAttachPath = oldMetadata.getAttachmentPath(setting, this.settings.dateFormat); - this.app.vault.adapter.exists(oldAttachPath, true).then((exists) => { - if (exists) { - checkEmptyFolder(this.app.vault.adapter, oldAttachPath).then((empty) => { - if (empty) { - this.app.vault.adapter.rmdir(oldAttachPath, true); - } - }); - } - }); - } - }) - ); - this.addSettingTab(new SettingTab(this.app, this)); - }); - } - async overrideConfiguration(file, setting) { - new OverrideModal(this, file, setting).open(); - } - /** - * Initializes and registers the plugin's commands - * This method is responsible for setting up the user interface by adding various commands. - * These commands include settings overrides, resetting settings, clearing unused original name storage, - * and rearranging attachments. - * - * Note: The actual implementation of each command is not included in this method and needs to be - * defined separately asynchronously. - * - * Warning: Make sure you have checked for errors while implementing the functionality of each command. - */ - initCommands() { - this.addCommand({ - id: "attachment-management-rearrange-all-links", - name: "Rearrange all linked attachments", - callback: async () => { - new ConfirmModal(this).open(); - } - }); - this.addCommand({ - id: "attachment-management-rearrange-active-links", - name: "Rearrange linked attachments", - callback: async () => { - new ArrangeHandler(this.settings, this.app, this).rearrangeAttachment(0 /* ACTIVE */).finally(() => { - new import_obsidian11.Notice("Arrange completed"); - }); - } - }); - this.addCommand({ - id: "attachment-management-override-setting", - name: "Overriding setting", - checkCallback: (checking) => { - const file = getActiveFile(this.app); - if (file) { - if (isAttachment(this.settings, file)) { - return true; - } - if (!checking) { - if (file.parent && isExcluded(file.parent.path, this.settings)) { - new import_obsidian11.Notice(`${file.path} was excluded`); - return true; - } - const { setting } = getOverrideSetting(this.settings, file); - const fileSetting = Object.assign({}, setting); - this.overrideConfiguration(file, fileSetting); - } - return true; - } - return false; - } - }); - this.addCommand({ - id: "attachment-management-reset-override-setting", - name: "Reset override setting", - checkCallback: (checking) => { - const file = getActiveFile(this.app); - if (file) { - if (isAttachment(this.settings, file)) { - return true; - } - if (!checking) { - if (file.parent && isExcluded(file.parent.path, this.settings)) { - new import_obsidian11.Notice(`${file.path} was excluded`); - return true; - } - delete this.settings.overridePath[file.path]; - this.saveSettings().finally(() => { - new import_obsidian11.Notice(`Reset attachment setting of ${file.path}`); - }); - } - return true; - } - return false; - } - }); - this.addCommand({ - id: "attachment-management-clear-unused-originalname-storage", - name: "Clear unused original name storage", - callback: async () => { - const attachments = await new ArrangeHandler(this.settings, this.app, this).getAttachmentsInVault( - this.settings, - 1 /* LINKS */ - ); - const storages = []; - for (const attachs of Object.values(attachments)) { - for (const attach of attachs) { - const link = decodeURI(attach); - const linkFile = this.app.vault.getAbstractFileByPath(link); - if (linkFile !== null && linkFile instanceof import_obsidian11.TFile) { - md5sum(this.app.vault.adapter, linkFile).then((md5) => { - const ret = this.settings.originalNameStorage.find((data) => data.md5 === md5); - if (ret) { - storages.filter((n) => n.md5 == md5).forEach((n) => storages.remove(n)); - storages.push(ret); - } - }); - } - } - } - debugLog("clearUnusedOriginalNameStorage - storage:", storages); - this.settings.originalNameStorage = storages; - this.saveSettings(); - } - }); - } - async loadSettings() { - this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData()); - } - async saveSettings() { - await this.saveData(this.settings); - } - async onunload() { - console.log("unloading attachment management."); - this.createdQueue = []; - } -}; diff --git a/.obsidian/plugins/attachment-management/manifest.json b/.obsidian/plugins/attachment-management/manifest.json deleted file mode 100644 index cae6cf0..0000000 --- a/.obsidian/plugins/attachment-management/manifest.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "id": "attachment-management", - "name": "Attachment Management", - "version": "0.9.16", - "description": "Customize your attachment path of notes independently with variables and auto rename it on change.", - "author": "trganda", - "authorUrl": "https://github.com/trganda", - "fundingUrl": "https://paypal.me/trganda", - "isDesktopOnly": false -} diff --git a/.obsidian/plugins/attachment-management/styles.css b/.obsidian/plugins/attachment-management/styles.css deleted file mode 100644 index e30a878..0000000 --- a/.obsidian/plugins/attachment-management/styles.css +++ /dev/null @@ -1,15 +0,0 @@ -/* - -This CSS file will be included with your plugin, and -available in the app when your plugin is enabled. - -If your plugin does not need CSS, delete this file. - -*/ -.attach_management_sub_setting { - padding-left: 2em; -} -.attach_management_sub_setting + .attach_management_sub_setting { - padding-left: 0; - margin-left: 2em; -} diff --git a/.obsidian/plugins/dashboard-navigator/data.json b/.obsidian/plugins/dashboard-navigator/data.json index ff86f51..632daa5 100644 --- a/.obsidian/plugins/dashboard-navigator/data.json +++ b/.obsidian/plugins/dashboard-navigator/data.json @@ -14,5 +14,12 @@ "color_audios": "#bfbf00", "color_pdf": "#00a300", "color_other": "#828282", - "colored_files": false + "colored_files": false, + "hide_ext": false, + "hide_path": false, + "hide_size": false, + "hide_date": false, + "hide_tags": false, + "hide_frontmatter": false, + "hide_columns": [] } \ No newline at end of file diff --git a/.obsidian/plugins/dashboard-navigator/main.js b/.obsidian/plugins/dashboard-navigator/main.js index be5f7a3..ad8c078 100644 --- a/.obsidian/plugins/dashboard-navigator/main.js +++ b/.obsidian/plugins/dashboard-navigator/main.js @@ -42,7 +42,7 @@ var DNSettingTab = class extends import_obsidian.PluginSettingTab { containerEl.empty(); new import_obsidian.Setting(containerEl).setName("Open dashboard navigator").addButton((btn) => { btn.setButtonText("Open").setTooltip("Open dashboard navigator").onClick((evt) => { - this.plugin._DN_MODAL.open(); + this.plugin.DN_MODAL.open(); }); }); new import_obsidian.Setting(containerEl).setName("Default view").setDesc("Select view when opening window").addDropdown((sel) => { @@ -51,7 +51,7 @@ var DNSettingTab = class extends import_obsidian.PluginSettingTab { sel.addOption("2", "Navigator"); sel.onChange(async (val) => { this.plugin.settings.default_view = parseInt(val); - this.plugin._DN_MODAL.default_view = this.plugin.settings.default_view; + this.plugin.DN_MODAL.default_view = this.plugin.settings.default_view; await this.plugin.saveSettings(); }), sel.setValue(this.plugin.settings.default_view.toString()); }).addExtraButton((btn) => { @@ -60,7 +60,7 @@ var DNSettingTab = class extends import_obsidian.PluginSettingTab { btn.onClick(() => { this.dropdownDefaultView.setValue(DEFAULT_SETTINGS.default_view.toString()); this.plugin.settings.default_view = DEFAULT_SETTINGS.default_view; - this.plugin._DN_MODAL.default_view = this.plugin.settings.default_view; + this.plugin.DN_MODAL.default_view = this.plugin.settings.default_view; this.plugin.saveSettings(); }); }); @@ -72,7 +72,7 @@ var DNSettingTab = class extends import_obsidian.PluginSettingTab { sel.addOption("dn-tbl-bordered", "Bordered"); sel.onChange(async (val) => { this.plugin.settings.selected_table_layout = val; - this.plugin._DN_MODAL.selected_table_layout = this.plugin.settings.selected_table_layout; + this.plugin.DN_MODAL.selected_table_layout = this.plugin.settings.selected_table_layout; await this.plugin.saveSettings(); }), sel.setValue(this.plugin.settings.selected_table_layout.toString()); }).addExtraButton((btn) => { @@ -81,7 +81,7 @@ var DNSettingTab = class extends import_obsidian.PluginSettingTab { btn.onClick(() => { this.dropdownTableLayout.setValue(DEFAULT_SETTINGS.selected_table_layout.toString()); this.plugin.settings.selected_table_layout = DEFAULT_SETTINGS.selected_table_layout; - this.plugin._DN_MODAL.selected_table_layout = this.plugin.settings.selected_table_layout; + this.plugin.DN_MODAL.selected_table_layout = this.plugin.settings.selected_table_layout; this.plugin.saveSettings(); }); }); @@ -95,7 +95,7 @@ var DNSettingTab = class extends import_obsidian.PluginSettingTab { sel.addOption("DD/MM/YYYY", "DD/MM/YYYY"); sel.onChange(async (val) => { this.plugin.settings.date_format = val; - this.plugin._DN_MODAL.date_format = this.plugin.settings.date_format; + this.plugin.DN_MODAL.date_format = this.plugin.settings.date_format; await this.plugin.saveSettings(); }), sel.setValue(this.plugin.settings.date_format.toString()); }).addExtraButton((btn) => { @@ -104,7 +104,7 @@ var DNSettingTab = class extends import_obsidian.PluginSettingTab { btn.onClick(() => { this.dropdownDateFormat.setValue(DEFAULT_SETTINGS.date_format.toString()); this.plugin.settings.date_format = DEFAULT_SETTINGS.date_format; - this.plugin._DN_MODAL.date_format = this.plugin.settings.date_format; + this.plugin.DN_MODAL.date_format = this.plugin.settings.date_format; this.plugin.saveSettings(); }); }); @@ -143,7 +143,7 @@ var DNSettingTab = class extends import_obsidian.PluginSettingTab { sel.addOption("100", "100"); sel.onChange(async (val) => { this.plugin.settings.files_per_page = parseInt(val); - this.plugin._DN_MODAL.files_per_page = this.plugin.settings.files_per_page; + this.plugin.DN_MODAL.files_per_page = this.plugin.settings.files_per_page; await this.plugin.saveSettings(); }), sel.setValue(this.plugin.settings.files_per_page.toString()); }).addExtraButton((btn) => { @@ -152,7 +152,7 @@ var DNSettingTab = class extends import_obsidian.PluginSettingTab { btn.onClick(() => { this.dropdownFilesPerPage.setValue(DEFAULT_SETTINGS.files_per_page.toString()); this.plugin.settings.files_per_page = DEFAULT_SETTINGS.files_per_page; - this.plugin._DN_MODAL.files_per_page = this.plugin.settings.files_per_page; + this.plugin.DN_MODAL.files_per_page = this.plugin.settings.files_per_page; this.plugin.saveSettings(); }); }); @@ -164,7 +164,7 @@ var DNSettingTab = class extends import_obsidian.PluginSettingTab { sel.addOption("10", "10"); sel.onChange(async (val) => { this.plugin.settings.num_recent_files = parseInt(val); - this.plugin._DN_MODAL.num_recent_files = this.plugin.settings.num_recent_files; + this.plugin.DN_MODAL.num_recent_files = this.plugin.settings.num_recent_files; await this.plugin.saveSettings(); }), sel.setValue(this.plugin.settings.num_recent_files.toString()); }).addExtraButton((btn) => { @@ -173,7 +173,109 @@ var DNSettingTab = class extends import_obsidian.PluginSettingTab { btn.onClick(() => { this.dropdownRecentFiles.setValue(DEFAULT_SETTINGS.num_recent_files.toString()); this.plugin.settings.num_recent_files = DEFAULT_SETTINGS.num_recent_files; - this.plugin._DN_MODAL.num_recent_files = this.plugin.settings.num_recent_files; + this.plugin.DN_MODAL.num_recent_files = this.plugin.settings.num_recent_files; + this.plugin.saveSettings(); + }); + }); + new import_obsidian.Setting(containerEl).setName("Hide column: Ext").setDesc("Navigator: Hide file extension column").addToggle((toggle) => { + this.toggleHideExtColumn = toggle; + toggle.setValue(this.plugin.settings.hide_ext).onChange(async (val) => { + this.plugin.settings.hide_ext = val; + this.plugin.dnUpdateHideColumn("ext", val); + await this.plugin.saveSettings(); + }); + }).addExtraButton((btn) => { + btn.setIcon("rotate-ccw"); + btn.setTooltip("Restore default"); + btn.onClick(() => { + this.toggleHideExtColumn.setValue(DEFAULT_SETTINGS.hide_ext); + this.plugin.settings.hide_ext = DEFAULT_SETTINGS.hide_ext; + this.plugin.dnUpdateHideColumn("ext", DEFAULT_SETTINGS.hide_ext); + this.plugin.saveSettings(); + }); + }); + new import_obsidian.Setting(containerEl).setName("Hide column: Path").setDesc("Navigator: Hide path column").addToggle((toggle) => { + this.toggleHidePathColumn = toggle; + toggle.setValue(this.plugin.settings.hide_path).onChange(async (val) => { + this.plugin.settings.hide_path = val; + this.plugin.dnUpdateHideColumn("path", val); + await this.plugin.saveSettings(); + }); + }).addExtraButton((btn) => { + btn.setIcon("rotate-ccw"); + btn.setTooltip("Restore default"); + btn.onClick(() => { + this.toggleHidePathColumn.setValue(DEFAULT_SETTINGS.hide_path); + this.plugin.settings.hide_path = DEFAULT_SETTINGS.hide_path; + this.plugin.dnUpdateHideColumn("path", DEFAULT_SETTINGS.hide_path); + this.plugin.saveSettings(); + }); + }); + new import_obsidian.Setting(containerEl).setName("Hide column: Size").setDesc("Navigator: Hide size column").addToggle((toggle) => { + this.toggleHideSizeColumn = toggle; + toggle.setValue(this.plugin.settings.hide_size).onChange(async (val) => { + this.plugin.settings.hide_size = val; + this.plugin.dnUpdateHideColumn("size", val); + await this.plugin.saveSettings(); + }); + }).addExtraButton((btn) => { + btn.setIcon("rotate-ccw"); + btn.setTooltip("Restore default"); + btn.onClick(() => { + this.toggleHideSizeColumn.setValue(DEFAULT_SETTINGS.hide_size); + this.plugin.settings.hide_size = DEFAULT_SETTINGS.hide_size; + this.plugin.dnUpdateHideColumn("size", DEFAULT_SETTINGS.hide_size); + this.plugin.saveSettings(); + }); + }); + new import_obsidian.Setting(containerEl).setName("Hide column: Date").setDesc("Navigator: Hide date column").addToggle((toggle) => { + this.toggleHideDateColumn = toggle; + toggle.setValue(this.plugin.settings.hide_date).onChange(async (val) => { + this.plugin.settings.hide_date = val; + this.plugin.dnUpdateHideColumn("date", val); + await this.plugin.saveSettings(); + }); + }).addExtraButton((btn) => { + btn.setIcon("rotate-ccw"); + btn.setTooltip("Restore default"); + btn.onClick(() => { + this.toggleHideDateColumn.setValue(DEFAULT_SETTINGS.hide_date); + this.plugin.settings.hide_date = DEFAULT_SETTINGS.hide_date; + this.plugin.dnUpdateHideColumn("date", DEFAULT_SETTINGS.hide_date); + this.plugin.saveSettings(); + }); + }); + new import_obsidian.Setting(containerEl).setName("Hide column: Tags").setDesc("Navigator: Hide tags column").addToggle((toggle) => { + this.toggleHideTagsColumn = toggle; + toggle.setValue(this.plugin.settings.hide_tags).onChange(async (val) => { + this.plugin.settings.hide_tags = val; + this.plugin.dnUpdateHideColumn("tags", val); + await this.plugin.saveSettings(); + }); + }).addExtraButton((btn) => { + btn.setIcon("rotate-ccw"); + btn.setTooltip("Restore default"); + btn.onClick(() => { + this.toggleHideTagsColumn.setValue(DEFAULT_SETTINGS.hide_tags); + this.plugin.settings.hide_tags = DEFAULT_SETTINGS.hide_tags; + this.plugin.dnUpdateHideColumn("tags", DEFAULT_SETTINGS.hide_tags); + this.plugin.saveSettings(); + }); + }); + new import_obsidian.Setting(containerEl).setName("Hide column: Frontmatter").setDesc("Navigator: Hide frontmatter properties column").addToggle((toggle) => { + this.toggleHideFrontmatterColumn = toggle; + toggle.setValue(this.plugin.settings.hide_frontmatter).onChange(async (val) => { + this.plugin.settings.hide_frontmatter = val; + this.plugin.dnUpdateHideColumn("frontmatter", val); + await this.plugin.saveSettings(); + }); + }).addExtraButton((btn) => { + btn.setIcon("rotate-ccw"); + btn.setTooltip("Restore default"); + btn.onClick(() => { + this.toggleHideFrontmatterColumn.setValue(DEFAULT_SETTINGS.hide_frontmatter); + this.plugin.settings.hide_frontmatter = DEFAULT_SETTINGS.hide_frontmatter; + this.plugin.dnUpdateHideColumn("frontmatter", DEFAULT_SETTINGS.hide_frontmatter); this.plugin.saveSettings(); }); }); @@ -181,7 +283,7 @@ var DNSettingTab = class extends import_obsidian.PluginSettingTab { this.textExcludedExtensions = text; text.setPlaceholder("File extensions to exclude").setValue(this.plugin.settings.excluded_ext).onChange(async (val) => { this.plugin.settings.excluded_ext = val; - this.plugin._DN_MODAL.excluded_extensions = this.plugin.dnGetExcludedExtensions(val); + this.plugin.DN_MODAL.excluded_extensions = this.plugin.dnGetExcludedExtensions(val); await this.plugin.saveSettings(); }); }).addExtraButton((btn) => { @@ -190,7 +292,7 @@ var DNSettingTab = class extends import_obsidian.PluginSettingTab { btn.onClick(() => { this.textExcludedExtensions.setValue(""); this.plugin.settings.excluded_ext = ""; - this.plugin._DN_MODAL.excluded_extensions = []; + this.plugin.DN_MODAL.excluded_extensions = []; this.plugin.saveSettings(); }); }); @@ -198,7 +300,7 @@ var DNSettingTab = class extends import_obsidian.PluginSettingTab { this.textExcludedFolders = text; text.setPlaceholder("Folder paths to exclude").setValue(this.plugin.settings.excluded_path).onChange(async (val) => { this.plugin.settings.excluded_path = val; - this.plugin._DN_MODAL.excluded_folders = this.plugin.dnGetExcludedFolders(val); + this.plugin.DN_MODAL.excluded_folders = this.plugin.dnGetExcludedFolders(val); await this.plugin.saveSettings(); }); }).addExtraButton((btn) => { @@ -207,7 +309,7 @@ var DNSettingTab = class extends import_obsidian.PluginSettingTab { btn.onClick(() => { this.textExcludedFolders.setValue(""); this.plugin.settings.excluded_path = ""; - this.plugin._DN_MODAL.excluded_folders = []; + this.plugin.DN_MODAL.excluded_folders = []; this.plugin.saveSettings(); }); }); @@ -215,8 +317,8 @@ var DNSettingTab = class extends import_obsidian.PluginSettingTab { this.toggleColoredFiles = toggle; toggle.setValue(this.plugin.settings.colored_files).onChange(async (val) => { this.plugin.settings.colored_files = val; - this.plugin._DN_MODAL.colored_files = val; - this.plugin._DN_MODAL.dnToggleColoredFiles(); + this.plugin.DN_MODAL.colored_files = val; + this.plugin.DN_MODAL.dnToggleColoredFiles(); await this.plugin.saveSettings(); }); }).addExtraButton((btn) => { @@ -225,8 +327,8 @@ var DNSettingTab = class extends import_obsidian.PluginSettingTab { btn.onClick(() => { this.toggleColoredFiles.setValue(DEFAULT_SETTINGS.colored_files); this.plugin.settings.colored_files = DEFAULT_SETTINGS.colored_files; - this.plugin._DN_MODAL.colored_files = DEFAULT_SETTINGS.colored_files; - this.plugin._DN_MODAL.dnToggleColoredFiles(); + this.plugin.DN_MODAL.colored_files = DEFAULT_SETTINGS.colored_files; + this.plugin.DN_MODAL.dnToggleColoredFiles(); this.plugin.saveSettings(); }); }); @@ -234,8 +336,8 @@ var DNSettingTab = class extends import_obsidian.PluginSettingTab { this.colorCompNotes = color; color.setValue(this.plugin.settings.color_notes).onChange(async (val) => { this.plugin.settings.color_notes = val; - this.plugin._DN_MODAL.color_notes = val; - this.plugin._DN_MODAL.dnSetCustomColors(); + this.plugin.DN_MODAL.color_notes = val; + this.plugin.DN_MODAL.dnSetCustomColors(); await this.plugin.saveSettings(); }); }).addExtraButton((btn) => { @@ -244,8 +346,8 @@ var DNSettingTab = class extends import_obsidian.PluginSettingTab { btn.onClick(() => { this.colorCompNotes.setValue(DEFAULT_SETTINGS.color_notes); this.plugin.settings.color_notes = DEFAULT_SETTINGS.color_notes; - this.plugin._DN_MODAL.color_notes = DEFAULT_SETTINGS.color_notes; - this.plugin._DN_MODAL.dnSetCustomColors(); + this.plugin.DN_MODAL.color_notes = DEFAULT_SETTINGS.color_notes; + this.plugin.DN_MODAL.dnSetCustomColors(); this.plugin.saveSettings(); }); }); @@ -253,8 +355,8 @@ var DNSettingTab = class extends import_obsidian.PluginSettingTab { this.colorCompCanvas = color; color.setValue(this.plugin.settings.color_canvas).onChange(async (val) => { this.plugin.settings.color_canvas = val; - this.plugin._DN_MODAL.color_canvas = val; - this.plugin._DN_MODAL.dnSetCustomColors(); + this.plugin.DN_MODAL.color_canvas = val; + this.plugin.DN_MODAL.dnSetCustomColors(); await this.plugin.saveSettings(); }); }).addExtraButton((btn) => { @@ -263,8 +365,8 @@ var DNSettingTab = class extends import_obsidian.PluginSettingTab { btn.onClick(() => { this.colorCompCanvas.setValue(DEFAULT_SETTINGS.color_canvas); this.plugin.settings.color_canvas = DEFAULT_SETTINGS.color_canvas; - this.plugin._DN_MODAL.color_canvas = DEFAULT_SETTINGS.color_canvas; - this.plugin._DN_MODAL.dnSetCustomColors(); + this.plugin.DN_MODAL.color_canvas = DEFAULT_SETTINGS.color_canvas; + this.plugin.DN_MODAL.dnSetCustomColors(); this.plugin.saveSettings(); }); }); @@ -272,8 +374,8 @@ var DNSettingTab = class extends import_obsidian.PluginSettingTab { this.colorCompImages = color; color.setValue(this.plugin.settings.color_images).onChange(async (val) => { this.plugin.settings.color_images = val; - this.plugin._DN_MODAL.color_images = val; - this.plugin._DN_MODAL.dnSetCustomColors(); + this.plugin.DN_MODAL.color_images = val; + this.plugin.DN_MODAL.dnSetCustomColors(); await this.plugin.saveSettings(); }); }).addExtraButton((btn) => { @@ -282,8 +384,8 @@ var DNSettingTab = class extends import_obsidian.PluginSettingTab { btn.onClick(() => { this.colorCompImages.setValue(DEFAULT_SETTINGS.color_images); this.plugin.settings.color_images = DEFAULT_SETTINGS.color_images; - this.plugin._DN_MODAL.color_images = DEFAULT_SETTINGS.color_images; - this.plugin._DN_MODAL.dnSetCustomColors(); + this.plugin.DN_MODAL.color_images = DEFAULT_SETTINGS.color_images; + this.plugin.DN_MODAL.dnSetCustomColors(); this.plugin.saveSettings(); }); }); @@ -291,8 +393,8 @@ var DNSettingTab = class extends import_obsidian.PluginSettingTab { this.colorCompVideos = color; color.setValue(this.plugin.settings.color_videos).onChange(async (val) => { this.plugin.settings.color_videos = val; - this.plugin._DN_MODAL.color_videos = val; - this.plugin._DN_MODAL.dnSetCustomColors(); + this.plugin.DN_MODAL.color_videos = val; + this.plugin.DN_MODAL.dnSetCustomColors(); await this.plugin.saveSettings(); }); }).addExtraButton((btn) => { @@ -301,8 +403,8 @@ var DNSettingTab = class extends import_obsidian.PluginSettingTab { btn.onClick(() => { this.colorCompVideos.setValue(DEFAULT_SETTINGS.color_videos); this.plugin.settings.color_videos = DEFAULT_SETTINGS.color_videos; - this.plugin._DN_MODAL.color_videos = DEFAULT_SETTINGS.color_videos; - this.plugin._DN_MODAL.dnSetCustomColors(); + this.plugin.DN_MODAL.color_videos = DEFAULT_SETTINGS.color_videos; + this.plugin.DN_MODAL.dnSetCustomColors(); this.plugin.saveSettings(); }); }); @@ -310,8 +412,8 @@ var DNSettingTab = class extends import_obsidian.PluginSettingTab { this.colorCompAudios = color; color.setValue(this.plugin.settings.color_audios).onChange(async (val) => { this.plugin.settings.color_audios = val; - this.plugin._DN_MODAL.color_audios = val; - this.plugin._DN_MODAL.dnSetCustomColors(); + this.plugin.DN_MODAL.color_audios = val; + this.plugin.DN_MODAL.dnSetCustomColors(); await this.plugin.saveSettings(); }); }).addExtraButton((btn) => { @@ -320,8 +422,8 @@ var DNSettingTab = class extends import_obsidian.PluginSettingTab { btn.onClick(() => { this.colorCompAudios.setValue(DEFAULT_SETTINGS.color_audios); this.plugin.settings.color_audios = DEFAULT_SETTINGS.color_audios; - this.plugin._DN_MODAL.color_audios = DEFAULT_SETTINGS.color_audios; - this.plugin._DN_MODAL.dnSetCustomColors(); + this.plugin.DN_MODAL.color_audios = DEFAULT_SETTINGS.color_audios; + this.plugin.DN_MODAL.dnSetCustomColors(); this.plugin.saveSettings(); }); }); @@ -329,8 +431,8 @@ var DNSettingTab = class extends import_obsidian.PluginSettingTab { this.colorCompPdf = color; color.setValue(this.plugin.settings.color_pdf).onChange(async (val) => { this.plugin.settings.color_pdf = val; - this.plugin._DN_MODAL.color_pdf = val; - this.plugin._DN_MODAL.dnSetCustomColors(); + this.plugin.DN_MODAL.color_pdf = val; + this.plugin.DN_MODAL.dnSetCustomColors(); await this.plugin.saveSettings(); }); }).addExtraButton((btn) => { @@ -339,8 +441,8 @@ var DNSettingTab = class extends import_obsidian.PluginSettingTab { btn.onClick(() => { this.colorCompPdf.setValue(DEFAULT_SETTINGS.color_pdf); this.plugin.settings.color_pdf = DEFAULT_SETTINGS.color_pdf; - this.plugin._DN_MODAL.color_pdf = DEFAULT_SETTINGS.color_pdf; - this.plugin._DN_MODAL.dnSetCustomColors(); + this.plugin.DN_MODAL.color_pdf = DEFAULT_SETTINGS.color_pdf; + this.plugin.DN_MODAL.dnSetCustomColors(); this.plugin.saveSettings(); }); }); @@ -348,8 +450,8 @@ var DNSettingTab = class extends import_obsidian.PluginSettingTab { this.colorCompOther = color; color.setValue(this.plugin.settings.color_other).onChange(async (val) => { this.plugin.settings.color_other = val; - this.plugin._DN_MODAL.color_other = val; - this.plugin._DN_MODAL.dnSetCustomColors(); + this.plugin.DN_MODAL.color_other = val; + this.plugin.DN_MODAL.dnSetCustomColors(); await this.plugin.saveSettings(); }); }).addExtraButton((btn) => { @@ -358,8 +460,8 @@ var DNSettingTab = class extends import_obsidian.PluginSettingTab { btn.onClick(() => { this.colorCompOther.setValue(DEFAULT_SETTINGS.color_other); this.plugin.settings.color_other = DEFAULT_SETTINGS.color_other; - this.plugin._DN_MODAL.color_other = DEFAULT_SETTINGS.color_other; - this.plugin._DN_MODAL.dnSetCustomColors(); + this.plugin.DN_MODAL.color_other = DEFAULT_SETTINGS.color_other; + this.plugin.DN_MODAL.dnSetCustomColors(); this.plugin.saveSettings(); }); }); @@ -380,16 +482,66 @@ function formatFileSize(fileSize) { function getFolderStructure(folder) { const folders = folder.split("/").slice(0, -1); if (folders.length === 0) { - return "/"; + return "//"; } return "/" + folders.join("/"); } +function formatFileSizeKBMB(total_bytes) { + if (total_bytes < 1024) { + return ""; + } else if (total_bytes < 1048576) { + return ` (${(total_bytes / 1024).toFixed(2)} KB)`; + } else { + return ` (${(total_bytes / (1024 * 1024)).toFixed(2)} MB)`; + } +} -// src/utils/piechart.ts +// src/utils/tags.ts +function getTagsPerFile(file) { + var _a, _b; + const cur_file = this.app.vault.getAbstractFileByPath(file.path); + if (cur_file !== null) { + const tags = (_a = this.app.metadataCache.getFileCache(file)) == null ? void 0 : _a.tags; + const frontmatter_tags = (_b = this.app.metadataCache.getFileCache(file)) == null ? void 0 : _b.frontmatter; + const arrTags = []; + if (tags) { + for (let i = 0, len = tags.length; i < len; i++) { + if (arrTags.indexOf(tags[i].tag) < 0) { + arrTags.push(tags[i].tag); + } + } + } + if (frontmatter_tags !== void 0 && frontmatter_tags.tags) { + for (let i = 0, len = frontmatter_tags.tags.length; i < len; i++) { + if (arrTags.indexOf(frontmatter_tags.tags[i]) < 0) { + arrTags.push("#" + frontmatter_tags.tags[i]); + } + } + } + return arrTags.join(" "); + } else { + return ""; + } +} +function getPropsPerFile(file) { + const fileProperties = []; + const cache = this.app.metadataCache.getFileCache(file); + if (cache == null ? void 0 : cache.frontmatter) { + for (const [key, value] of Object.entries(cache.frontmatter)) { + fileProperties.push(`'${key}: ${value}'`); + } + } + return fileProperties.join(" \n"); +} + +// src/utils/dnpiechart.ts var DNPieChart = class { constructor(canvas, margin = 10, fontSize = 12, legendWidth = 50, labelColor = "#828282") { this._canvas = canvas; - this._ctx = canvas.getContext("2d"); + const ctx = canvas.getContext("2d"); + if (ctx) { + this._ctx = ctx; + } this._data = []; this._margin = margin; this._fontSize = fontSize; @@ -439,6 +591,37 @@ var DNPieChart = class { } }; +// src/utils/dntablemanager.ts +var DNTableManager = class { + constructor(tbl) { + this.table = document.querySelector(tbl); + } + getCells() { + return this.table.querySelectorAll("td, th"); + } + hideColumns(columnNames) { + const cells = this.getCells(); + if (columnNames.length === 0) { + for (let i = 0; i < cells.length; i++) { + cells[i].classList.remove("dn-hidden"); + } + } else { + for (let i = 0; i < cells.length; i++) { + const colIndex = i % 7; + const columnName = this.getColumnNames()[colIndex]; + if (columnNames.includes(columnName)) { + cells[i].classList.add("dn-hidden"); + } else { + cells[i].classList.remove("dn-hidden"); + } + } + } + } + getColumnNames() { + return ["name", "ext", "path", "size", "date", "tags", "frontmatter"]; + } +}; + // src/dn.ts var import_obsidian3 = require("obsidian"); var DNModal = class extends import_obsidian2.Modal { @@ -465,6 +648,8 @@ var DNModal = class extends import_obsidian2.Modal { this.color_pdf = "#00a300"; this.color_other = "#828282"; this.colored_files = false; + // Hide columns + this.hide_columns = []; this.dnHandleIntersection = (entries) => { entries.forEach((entry) => { if (!entry.isIntersecting) { @@ -479,20 +664,34 @@ var DNModal = class extends import_obsidian2.Modal { async onOpen() { var _a; const { contentEl } = this; + this._previewComponent = new import_obsidian2.Component(); + this._hoverDiv = this.contentEl.createEl("div", { cls: "dn-preview" }); + await this.updateModalData(); + const leaf = (_a = this.app.workspace) == null ? void 0 : _a.getMostRecentLeaf(); + if (leaf !== null) { + this._leaf = leaf; + } + this.dnCreateMainUI(contentEl); + this.dnSetView(this.default_view); + this.dnSetSelectLayoutValue(this.selected_table_layout); + this.dnSetSelectSortValue(this.selected_sort_value); + this.dnToggleColoredFiles(); + this._isDraggingPreview = false; + this._hoverDivLeft = ""; + this._hoverDivTop = ""; + } + async updateModalData() { this._files = []; this._folders = []; - this._notes = []; this._recent = []; + this._last_opened = []; + this._notes = []; this._images = []; this._canvas = []; this._audios = []; this._videos = []; this._pdf = []; this._other = []; - const leaf = (_a = this.app.workspace) == null ? void 0 : _a.getMostRecentLeaf(); - if (leaf !== null) { - this._leaf = leaf; - } const dnFilesAndFolders = this.app.vault.getAllLoadedFiles(); for (const absF of dnFilesAndFolders) { if (absF instanceof import_obsidian2.TFile) { @@ -501,37 +700,21 @@ var DNModal = class extends import_obsidian2.Modal { this._folders.push(absF); } } - this._filtered_files = this._files.filter( + this._files_excluded_filters = this._files.filter( (file) => { return !this.excluded_extensions.includes(file.extension.toLowerCase()) && !this.excluded_folders.some((folder) => file.path.startsWith(folder)); } ); - this._files = this._filtered_files; - await this.dnOrganizeFiles({ arr: this._filtered_files }); - this._recent = await this.dnGetRecentFiles(this._filtered_files); - this.dnCreateMainUI(contentEl); - this.dnSetView(this.default_view); - this.dnSetSelectLayoutValue(this.selected_table_layout); - this.dnSetSelectSortValue(this.selected_sort_value); - this.dnToggleColoredFiles(); - } - dnSetCustomColors() { - document.body.style.setProperty("--dn-notes-color", this.color_notes); - document.body.style.setProperty("--dn-images-color", this.color_images); - document.body.style.setProperty("--dn-canvas-color", this.color_canvas); - document.body.style.setProperty("--dn-videos-color", this.color_videos); - document.body.style.setProperty("--dn-audios-color", this.color_audios); - document.body.style.setProperty("--dn-pdfs-color", this.color_pdf); - document.body.style.setProperty("--dn-other-color", this.color_other); - } - dnToggleColoredFiles() { - const dnMainContainer = document.getElementById("dn-container"); - if (this.colored_files) { - dnMainContainer == null ? void 0 : dnMainContainer.classList.add("dn-colored-files"); - } else { - dnMainContainer == null ? void 0 : dnMainContainer.classList.remove("dn-colored-files"); - } - this.dnSetCustomColors(); + this._files_results = this._files_excluded_filters; + await this.dnOrganizeFiles({ arr: this._files_excluded_filters }); + this._recent = await this.dnGetRecentFiles(this._files_excluded_filters); + const arrStrLastOpened = this.app.workspace.getLastOpenFiles(); + arrStrLastOpened.forEach(async (file) => { + const f_temp = await this.app.vault.getAbstractFileByPath(file); + if (f_temp instanceof import_obsidian2.TFile) { + this._last_opened.push(f_temp); + } + }); } async dnCreateMainUI(el) { const mainContainer = el.createEl("div", { cls: "dn-container" }); @@ -546,7 +729,7 @@ var DNModal = class extends import_obsidian2.Modal { }); this._BTN_NAVIGATOR = leftTopNav.createEl("button", { text: "Navigator" }); this._BTN_NAVIGATOR.onClickEvent((evt) => { - this.dnSearchVault(this._INPUT_SEARCH.value); + this.dnModalSearchVault(this._INPUT_SEARCH.value); this.dnSetView(2); }); this.labelLayout = rightTopNav.createEl("span", { @@ -576,27 +759,30 @@ var DNModal = class extends import_obsidian2.Modal { this._SELECT_SORT.addEventListener("change", () => { this.dnSortColumnWithSelect(); }); - const option1 = this._SELECT_SORT.createEl("option", { text: "File name (A to Z)", value: "name-asc" }); - const option2 = this._SELECT_SORT.createEl("option", { text: "File name (Z to A)", value: "name-desc" }); - const option3 = this._SELECT_SORT.createEl("option", { text: "Path (A to Z)", value: "path-asc" }); - const option4 = this._SELECT_SORT.createEl("option", { text: "Path (Z to A)", value: "path-desc" }); - const option5 = this._SELECT_SORT.createEl("option", { text: "File size (smallest to largest)", value: "size-asc" }); - const option6 = this._SELECT_SORT.createEl("option", { text: "File size (largest to smallest)", value: "size-desc" }); - const option7 = this._SELECT_SORT.createEl("option", { text: "Date/time (oldest to newest)", value: "modified-asc" }); - const option8 = this._SELECT_SORT.createEl("option", { text: "Date/time (newest to oldest)", value: "modified-desc" }); + this._SELECT_SORT.createEl("option", { text: "Name (A to Z)", value: "name-asc" }); + this._SELECT_SORT.createEl("option", { text: "Name (Z to A)", value: "name-desc" }); + this._SELECT_SORT.createEl("option", { text: "Extension (A to Z)", value: "ext-asc" }); + this._SELECT_SORT.createEl("option", { text: "Extension (Z to A)", value: "ext-desc" }); + this._SELECT_SORT.createEl("option", { text: "Path (A to Z)", value: "path-asc" }); + this._SELECT_SORT.createEl("option", { text: "Path (Z to A)", value: "path-desc" }); + this._SELECT_SORT.createEl("option", { text: "Size (smallest to largest)", value: "size-asc" }); + this._SELECT_SORT.createEl("option", { text: "Size (largest to smallest)", value: "size-desc" }); + this._SELECT_SORT.createEl("option", { text: "Date/time (oldest to newest)", value: "modified-asc" }); + this._SELECT_SORT.createEl("option", { text: "Date/time (newest to oldest)", value: "modified-desc" }); this._VIEW_DASHBOARD = mainContainer.createEl("div", { cls: "dn-flex" }); this._VIEW_NAVIGATOR = mainContainer.createEl("div", { cls: "dn-display-none" }); this._divSearchResults = this._VIEW_NAVIGATOR.createEl("div", { cls: "dn-div-table" }); - this.dnShowSearchResults({ f: this._filtered_files, el: this._divSearchResults, leaf: this._leaf }); + this.dnShowModalSearchResults({ f: this._files_results, el: this._divSearchResults, leaf: this._leaf }); const divVaultStats = this._VIEW_DASHBOARD.createEl("div"); divVaultStats.setAttribute("id", "dn-vault-stats"); const divVaultGraph = this._VIEW_DASHBOARD.createEl("div"); divVaultGraph.setAttribute("id", "dn-vault-graph"); + const divLastOpenedFiles = this._VIEW_DASHBOARD.createEl("div"); + divLastOpenedFiles.setAttribute("id", "dn-last-opened-files"); const divRecentFiles = this._VIEW_DASHBOARD.createEl("div"); divRecentFiles.setAttribute("id", "dn-recent-files"); const divRecentNotes = this._VIEW_DASHBOARD.createEl("div"); divRecentNotes.setAttribute("id", "dn-recent-notes"); - ; const divCanvas = this._VIEW_DASHBOARD.createEl("div"); divCanvas.setAttribute("id", "dn-canvas"); const divImages = this._VIEW_DASHBOARD.createEl("div"); @@ -609,7 +795,7 @@ var DNModal = class extends import_obsidian2.Modal { divPDFs.setAttribute("id", "dn-pdfs"); const divOther = this._VIEW_DASHBOARD.createEl("div"); divOther.setAttribute("id", "dn-other"); - const btnNotes = await this.dnCreateBtn( + await this.dnCreateBtn( divVaultStats, "dn-btn-notes", "Notes", @@ -617,15 +803,15 @@ var DNModal = class extends import_obsidian2.Modal { this._divSearchResults, this._leaf ); - const btnCanvas = await this.dnCreateBtn( + await this.dnCreateBtn( divVaultStats, "dn-btn-canvas", - "Canvas", + "Canvases", this._canvas, this._divSearchResults, this._leaf ); - const btnImages = await this.dnCreateBtn( + await this.dnCreateBtn( divVaultStats, "dn-btn-images", "Images", @@ -633,7 +819,7 @@ var DNModal = class extends import_obsidian2.Modal { this._divSearchResults, this._leaf ); - const btnAudios = await this.dnCreateBtn( + await this.dnCreateBtn( divVaultStats, "dn-btn-audios", "Audios", @@ -641,7 +827,7 @@ var DNModal = class extends import_obsidian2.Modal { this._divSearchResults, this._leaf ); - const btnVideos = await this.dnCreateBtn( + await this.dnCreateBtn( divVaultStats, "dn-btn-videos", "Videos", @@ -649,15 +835,15 @@ var DNModal = class extends import_obsidian2.Modal { this._divSearchResults, this._leaf ); - const btnPDF = await this.dnCreateBtn( + await this.dnCreateBtn( divVaultStats, "dn-btn-pdf", - "PDF", + "PDFs", this._pdf, this._divSearchResults, this._leaf ); - const btnOther = await this.dnCreateBtn( + await this.dnCreateBtn( divVaultStats, "dn-btn-other", "Other", @@ -679,11 +865,12 @@ var DNModal = class extends import_obsidian2.Modal { pieChart1.addData(this._other.length, this.color_other, "Other"); pieChart1.draw(); const divStatsFrame = divVaultGraph.createEl("div", { cls: "dn-stats-files-folders" }); - divStatsFrame.createEl("div", { cls: "dn-stats-files", text: "Files: " + this._filtered_files.length }); + divStatsFrame.createEl("div", { cls: "dn-stats-files", text: "Files: " + this._files_excluded_filters.length }); divStatsFrame.createEl("div", { cls: "dn-stats-folders", text: "Folders: " + this._folders.length }); + await this.dnCreateRecentFiles("Recently opened", divLastOpenedFiles, this._last_opened, this.num_recent_files); await this.dnCreateRecentFiles("Recent files", divRecentFiles, this._recent, this.num_recent_files); await this.dnCreateRecentFiles("Recent notes", divRecentNotes, this._notes, this.num_recent_files); - await this.dnCreateRecentFiles("Recent canvas", divCanvas, this._canvas, this.num_recent_files); + await this.dnCreateRecentFiles("Recent canvases", divCanvas, this._canvas, this.num_recent_files); await this.dnCreateRecentFiles("Recent images", divImages, this._images, this.num_recent_files); await this.dnCreateRecentFiles("Recent audios", divAudios, this._audios, this.num_recent_files); await this.dnCreateRecentFiles("Recent videos", divVideos, this._videos, this.num_recent_files); @@ -691,109 +878,105 @@ var DNModal = class extends import_obsidian2.Modal { await this.dnCreateRecentFiles("Recent other files", divOther, this._other, this.num_recent_files); } async dnCreateBtn(elDiv, btnId, btnTitle, btnCategoryFiles, displayEl, leaf) { - let btn = elDiv.createEl("div", { cls: "dn-btn-stats" }); + const btn = elDiv.createEl("div", { cls: "dn-btn-stats" }); btn.setAttribute("id", btnId); btn.createEl("span", { cls: "dn-btn-stats-label", text: btnTitle }); btn.createEl("span", { cls: "dn-btn-stats-icon" }); btn.createEl("span", { cls: "dn-btn-stats-number", text: btnCategoryFiles.length.toString() }); btn.onClickEvent((evt) => { - this._filtered_files = btnCategoryFiles; - this._selected_category = " (" + btnTitle + ")"; - this.dnSortFilteredFiles(false); - this.dnShowSearchResults({ f: btnCategoryFiles, el: displayEl, leaf }); - this.dnSetView(2); + this._files_results = btnCategoryFiles; + this._INPUT_SEARCH.value = "@" + btnTitle.toLocaleLowerCase() + " "; + this.dnModalSearchVault(this._INPUT_SEARCH.value); + this._INPUT_SEARCH.focus(); }); return btn; } - async dnCreateRecentFiles(title, divF, files, num_files) { - if (files.length === 0) { - divF.createEl("h3", { cls: "dn-subtitles", text: title }); - divF.createEl("p", { cls: "dn-no-results-found", text: "No files found." }); - divF.classList.add("dn-display-none"); - } else { - divF.createEl("h3", { cls: "dn-subtitles", text: title }); - const sortedFiles = await this.dnGetRecentFiles(files); - sortedFiles.forEach((sfile) => { - divF.createEl("a", { cls: this.dnSetFileIconClass(sfile.extension), text: sfile.basename, title: sfile.path }).onClickEvent((evt) => { - if (sfile !== null) { - this.dnOpenFileAlt(sfile, evt); - } - }); - if (sfile.extension !== "md") { - divF.createEl("span", { cls: "nav-file-tag", text: sfile.extension }); - } - divF.createEl("br"); - }); - } - } dnCreateInputSearch(el) { const searchContainer = el.createEl("div", { cls: "dn-search-input-container" }); this._INPUT_SEARCH = searchContainer.createEl("input", { type: "search", placeholder: "Search..." }); this._INPUT_SEARCH.setAttribute("id", "dn-input-filter"); this._INPUT_SEARCH.spellcheck = false; this._INPUT_SEARCH.focus(); - const clearInputSearch = searchContainer.createEl("div", { cls: "search-input-clear-button" }).onClickEvent((evt) => { + searchContainer.createEl("div", { cls: "search-input-clear-button" }).onClickEvent((evt) => { this._INPUT_SEARCH.value = ""; this._INPUT_SEARCH.focus(); - this.dnSearchVault(this._INPUT_SEARCH.value); + this.dnModalSearchVault(this._INPUT_SEARCH.value); }); - this._INPUT_SEARCH.addEventListener("input", (0, import_obsidian2.debounce)(() => this.dnSearchVault(this._INPUT_SEARCH.value), 300, true)); + this._INPUT_SEARCH.addEventListener("input", (0, import_obsidian2.debounce)(() => this.dnModalSearchVault(this._INPUT_SEARCH.value), 300, true)); } - async dnSearchVault(val) { + async dnModalSearchVault(val) { + this.dnSetView(2); + const search_raw_vals = /!(?:"(?:\\"|[^"])*"|'(?:\\'|[^'])*')|"(?:\\"|[^"])*"|'(?:\\'|[^'])*'|\S+/g; + let searchParams = val.toLowerCase().trim().match(search_raw_vals); + if (!searchParams) { + return this.searchAction("", this._files_excluded_filters); + } + searchParams = searchParams.map((param) => { + if (param.startsWith('"') && param.endsWith('"')) { + return param.slice(1, -1); + } else if (param.startsWith("'") && param.endsWith("'")) { + return param.slice(1, -1); + } else if (param.startsWith(".")) { + return "\\" + param + "$"; + } else { + return param; + } + }); + const firstParam = searchParams[0]; + await this.searchAction(firstParam, this._files_excluded_filters); + const remainingParams = searchParams.slice(1); + remainingParams.every(async (p) => { + await this.searchAction(p, this._files_results); + }); + } + // Search + async searchAction(val, files) { let rExp; + const isExcludeSearch = val.startsWith("!") && val.length >= 2; + let excludeParam = isExcludeSearch ? val.slice(1) : val; + if (excludeParam.startsWith('"') && excludeParam.endsWith('"')) { + excludeParam = excludeParam.slice(1, -1); + } else if (excludeParam.startsWith("'") && excludeParam.endsWith("'")) { + excludeParam = excludeParam.slice(1, -1); + } try { - rExp = new RegExp(val.toLowerCase(), "iu"); + if (isExcludeSearch) { + rExp = new RegExp("", "iu"); + } else { + if (val === "!") { + rExp = new RegExp("", "iu"); + } else { + rExp = new RegExp(val.toLowerCase(), "iu"); + } + } } catch (error) { return; } - this.dnSetView(2); const isDateSearch = val.startsWith("@"); - if (isDateSearch) { + if (this._INPUT_SEARCH.value.includes("@")) { this._INPUT_SEARCH.classList.add("dn-input-datesearch"); } else { this._INPUT_SEARCH.classList.remove("dn-input-datesearch"); } - this._filtered_files = this._files.filter( - (file) => { - if (isDateSearch) { - let mtime = (0, import_obsidian3.moment)(file.stat.mtime); - const dateSearch = val.slice(1).toLowerCase().split(" "); - switch (dateSearch[0]) { - case "day": - case "today": - return mtime.isSame((0, import_obsidian3.moment)(), "day"); - case "day-1": - case "yesterday": - return mtime.isSame((0, import_obsidian3.moment)().subtract(1, "days"), "day"); - case "day-2": - return mtime.isSame((0, import_obsidian3.moment)().subtract(2, "days"), "day"); - case "day-3": - return mtime.isSame((0, import_obsidian3.moment)().subtract(3, "days"), "day"); - case "day-4": - return mtime.isSame((0, import_obsidian3.moment)().subtract(4, "days"), "day"); - case "day-5": - return mtime.isSame((0, import_obsidian3.moment)().subtract(5, "days"), "day"); - case "day-6": - return mtime.isSame((0, import_obsidian3.moment)().subtract(6, "days"), "day"); - case "day-7": - return mtime.isSame((0, import_obsidian3.moment)().subtract(7, "days"), "day"); - case "week": - return mtime.isBetween((0, import_obsidian3.moment)().subtract(7, "days"), (0, import_obsidian3.moment)(), "day", "[]"); - case "month": - return mtime.isSame((0, import_obsidian3.moment)(), "month"); - case "year": - return mtime.isSame((0, import_obsidian3.moment)(), "year"); - default: - return false; + if (isExcludeSearch) { + this._files_results = files.filter((file) => { + const isMatch = file.name.toLowerCase().includes(excludeParam) || getFolderStructure(file.path).toLowerCase().includes(excludeParam) || (0, import_obsidian3.moment)(file.stat.mtime).format(this.date_format).toLowerCase().includes(excludeParam) || getTagsPerFile(file).toLowerCase().includes(excludeParam) || getPropsPerFile(file).toLowerCase().includes(excludeParam); + return isExcludeSearch ? !isMatch : isMatch; + }); + } else { + this._files_results = files.filter( + (file) => { + if (isDateSearch) { + const dateSearch = val.slice(1).toLowerCase().split(" "); + return this.dnHandleSpecialSearch(dateSearch[0], file); + } else { + return this.dnHandleNormalSearch(rExp, file); } - } else { - return rExp.test(file.name.toLowerCase()) || rExp.test(getFolderStructure(file.path).toLowerCase()) || rExp.test((0, import_obsidian3.moment)(file.stat.mtime).format(this.date_format)) || rExp.test(this.dnGetTagsPerFile(file).toLowerCase()); } - } - ); - this._selected_category = ""; + ); + } this.dnSortFilteredFiles(false); - await this.dnShowSearchResults({ f: this._filtered_files, el: this._divSearchResults, leaf: this._leaf }); + await this.dnShowModalSearchResults({ f: this._files_results, el: this._divSearchResults, leaf: this._leaf }); const tbody = document.getElementById("dn-table-results"); if (tbody !== null) { const tr = tbody.getElementsByTagName("tr"); @@ -816,10 +999,156 @@ var DNModal = class extends import_obsidian2.Modal { } } } + async dnShowModalSearchResults({ f, el, leaf, currentPage = 1 }) { + el.empty(); + const paginationContainer = this._divSearchResults.createEl("div", { cls: "dn-pagination" }); + const table = el.createEl("table", { cls: this.selected_table_layout }); + table.setAttribute("id", "dn-table"); + const thead = table.createEl("thead"); + const tr = thead.createEl("tr"); + this._th1 = tr.createEl("th", { text: "Name" }); + this._th2 = tr.createEl("th", { text: "Ext" }); + this._th3 = tr.createEl("th", { text: "Path" }); + this._th4 = tr.createEl("th", { text: "Size" }); + this._th5 = tr.createEl("th", { text: "Date" }); + this._th6 = tr.createEl("th", { text: "Tags" }); + this._th7 = tr.createEl("th", { text: "Frontmatter" }); + this._th1.addEventListener("dblclick", () => this.dnAlternateSortColumn("name")); + this._th2.addEventListener("dblclick", () => this.dnAlternateSortColumn("ext")); + this._th3.addEventListener("dblclick", () => this.dnAlternateSortColumn("path")); + this._th4.addEventListener("dblclick", () => this.dnAlternateSortColumn("size")); + this._th5.addEventListener("dblclick", () => this.dnAlternateSortColumn("modified")); + const tbody = table.createEl("tbody"); + tbody.setAttribute("id", "dn-table-results"); + if (f.length > 0) { + if (this.intersectionObserver) { + this.intersectionObserver.disconnect(); + } + this._total_pages = Math.ceil(f.length / this.files_per_page); + const paginatedData = f.slice((currentPage - 1) * this.files_per_page, currentPage * this.files_per_page); + paginatedData.forEach(async (file) => { + const tr2 = tbody.createEl("tr"); + tr2.addEventListener("contextmenu", (evt) => { + this.dnHandleClick(evt, file); + }); + tr2.addEventListener("click", (evt) => { + this.dnHandleClick(evt, file); + }); + tr2.addEventListener("dblclick", (evt) => { + this.dnHandleDblClick(evt, file); + }); + tr2.addEventListener("mouseover", async (evt) => { + this.dnHandleHoverPreview(evt, file); + }); + this.intersectionObserver.observe(tr2); + tr2.removeEventListener("mouseover", async (evt) => { + this.dnHandleHoverPreview(evt, file); + }); + const td1 = tr2.createEl("td"); + td1.createEl("a", { cls: this.dnSetFileIconClass(file.extension), text: file.name }).onClickEvent((evt) => { + if (leaf !== null && file !== null) { + this.dnOpenFileAlt(file, evt); + } + }); + const fExt = file.extension; + const fSize = formatFileSize(file.stat.size); + const fMTime = (0, import_obsidian3.moment)(file.stat.mtime).format(this.date_format); + const fCTime = (0, import_obsidian3.moment)(file.stat.ctime).format(this.date_format); + const td2 = tr2.createEl("td"); + td2.createEl("a", { cls: "dn-ext", text: fExt, title: fExt }).onClickEvent((evt) => { + if (evt.button === 2) { + evt.preventDefault(); + } else { + this._INPUT_SEARCH.value = "." + fExt; + this.dnModalSearchVault(this._INPUT_SEARCH.value); + } + }); + const td3 = tr2.createEl("td"); + const folder_path = getFolderStructure(file.path); + td3.createEl("a", { cls: "dn-folder-path", text: folder_path, title: file.path }).onClickEvent((evt) => { + if (evt.button === 2) { + evt.preventDefault(); + } else { + this._INPUT_SEARCH.value = folder_path; + this.dnModalSearchVault(this._INPUT_SEARCH.value + "$"); + } + }); + tr2.createEl("td", { text: fSize, title: fSize + " bytes" }); + tr2.createEl("td", { text: fMTime, title: fCTime + " - Created\n" + fMTime + " - Modified" }); + const tags_per_file = getTagsPerFile(file); + const props_per_file = getPropsPerFile(file); + const td6 = tr2.createEl("td", { title: tags_per_file }); + const fTags = tags_per_file.split(" "); + fTags.forEach((tag) => { + td6.createEl("a", { cls: "dn-tag", text: tag }).onClickEvent((evt) => { + if (evt.button === 2) { + evt.preventDefault(); + } else { + this._INPUT_SEARCH.value = tag; + this.dnModalSearchVault(this._INPUT_SEARCH.value); + } + }); + }); + const td7 = tr2.createEl("td", { title: props_per_file }); + const fProps = props_per_file.split("\n"); + fProps.forEach((prop) => { + td7.createEl("a", { cls: "dn-tag", text: prop }).onClickEvent((evt) => { + if (evt.button === 2) { + evt.preventDefault(); + } else { + this._INPUT_SEARCH.value = prop; + this.dnModalSearchVault(this._INPUT_SEARCH.value); + } + }); + }); + }); + paginationContainer.empty(); + paginationContainer.createEl("div", { cls: "dn-pagination-total-results", text: `File(s): ${f.length} ` }); + const rightPagDiv = paginationContainer.createEl("div", { cls: "dn-pagination-current-page", text: `Page ${currentPage} of ${this._total_pages} ` }); + const btnPrev = rightPagDiv.createEl("button", { cls: "dn-btn-prev", text: "\u25C0", title: "Previous" }); + if (currentPage === 1) { + btnPrev.disabled = true; + } else { + btnPrev.disabled = false; + } + btnPrev.addEventListener("click", () => { + if (currentPage > 1) { + this.dnShowModalSearchResults({ f, el, leaf, currentPage: currentPage - 1 }); + } + }); + const btnNext = rightPagDiv.createEl("button", { cls: "dn-btn-next", text: "\u25B6", title: "Next" }); + if (currentPage === this._total_pages) { + btnNext.disabled = true; + } else { + btnNext.disabled = false; + } + btnNext.addEventListener("click", () => { + if (currentPage < this._total_pages) { + this.dnShowModalSearchResults({ f, el, leaf, currentPage: currentPage + 1 }); + } + }); + this.dnUpdateSortIndicators( + this._sort_column, + this._sort_order, + this._th1, + this._th2, + this._th3, + this._th4, + this._th5 + ); + const dnTableManager = new DNTableManager("#dn-table"); + dnTableManager.hideColumns(this.hide_columns); + } else { + tr.empty(); + paginationContainer.createEl("div", { cls: "dn-pagination-total-results", text: `File(s): 0 ` }); + this._divSearchResults.createEl("p", { cls: "dn-no-results-found", text: "No files found." }); + } + } async dnSortFilteredFiles(toggle) { switch (this._sort_column) { case "name": case "path": + case "ext": this.dnSortColumnString(this._sort_column, this._sort_order, toggle); break; case "size": @@ -837,6 +1166,7 @@ var DNModal = class extends import_obsidian2.Modal { switch (this._sort_column) { case "name": case "path": + case "ext": this.dnSortColumnString(this._sort_column, this._sort_order, false); break; case "size": @@ -844,7 +1174,7 @@ var DNModal = class extends import_obsidian2.Modal { this.dnSortColumnNumber(this._sort_column, this._sort_order, false); break; } - this.dnShowSearchResults({ f: this._filtered_files, el: this._divSearchResults, leaf: this._leaf }); + this.dnShowModalSearchResults({ f: this._files_results, el: this._divSearchResults, leaf: this._leaf }); } } dnIsValidSort(val) { @@ -853,6 +1183,8 @@ var DNModal = class extends import_obsidian2.Modal { "name-desc", "path-asc", "path-desc", + "ext-asc", + "ext-desc", "size-asc", "size-desc", "modified-asc", @@ -870,106 +1202,6 @@ var DNModal = class extends import_obsidian2.Modal { return false; } } - async dnShowSearchResults({ f, el, leaf, currentPage = 1 }) { - el.empty(); - const paginationContainer = this._divSearchResults.createEl("div", { cls: "dn-pagination" }); - const table = el.createEl("table", { cls: this.selected_table_layout }); - table.setAttribute("id", "dn-table"); - const thead = table.createEl("thead"); - const tr = thead.createEl("tr"); - this._th1 = tr.createEl("th", { text: "Name" }); - this._th2 = tr.createEl("th", { text: "Path" }); - this._th3 = tr.createEl("th", { text: "Size" }); - this._th4 = tr.createEl("th", { text: "Date" }); - this._th5 = tr.createEl("th", { text: "Tags" }); - this._th1.addEventListener("dblclick", () => this.dnAlternateSortColumn("name")); - this._th2.addEventListener("dblclick", () => this.dnAlternateSortColumn("path")); - this._th3.addEventListener("dblclick", () => this.dnAlternateSortColumn("size")); - this._th4.addEventListener("dblclick", () => this.dnAlternateSortColumn("modified")); - const tbody = table.createEl("tbody"); - tbody.setAttribute("id", "dn-table-results"); - if (f.length > 0) { - if (this.intersectionObserver) { - this.intersectionObserver.disconnect(); - } - this._total_pages = Math.ceil(f.length / this.files_per_page); - const paginatedData = f.slice((currentPage - 1) * this.files_per_page, currentPage * this.files_per_page); - paginatedData.forEach(async (file) => { - let tr2 = tbody.createEl("tr"); - tr2.addEventListener("contextmenu", (evt) => { - this.dnHandleClick(evt, file); - }); - tr2.addEventListener("click", (evt) => { - this.dnHandleClick(evt, file); - }); - tr2.addEventListener("dblclick", (evt) => { - this.dnHandleDblClick(evt, file); - }); - this.intersectionObserver.observe(tr2); - let td1 = tr2.createEl("td"); - let td1Link = td1.createEl("a", { cls: this.dnSetFileIconClass(file.extension), text: file.name }).onClickEvent((evt) => { - if (leaf !== null && file !== null) { - this.dnOpenFileAlt(file, evt); - } - }); - let fSize = formatFileSize(file.stat.size); - let fMTime = (0, import_obsidian3.moment)(file.stat.mtime).format(this.date_format); - let td2 = tr2.createEl("td"); - let folder_path = getFolderStructure(file.path); - let td2_path = td2.createEl("a", { cls: "dn-folder-path", text: folder_path, title: file.path }).onClickEvent((evt) => { - this._INPUT_SEARCH.value = folder_path; - this.dnSearchVault(this._INPUT_SEARCH.value + "$"); - }); - let td3 = tr2.createEl("td", { text: fSize, title: fSize + " bytes" }); - let td4 = tr2.createEl("td", { text: fMTime, title: fMTime }); - let tags_per_file = this.dnGetTagsPerFile(file); - let td5 = tr2.createEl("td", { title: tags_per_file }); - let fTags = tags_per_file.split(" "); - fTags.forEach((tag) => { - td5.createEl("a", { cls: "dn-tag", text: tag }).onClickEvent((evt) => { - this._INPUT_SEARCH.value = tag; - this.dnSearchVault(this._INPUT_SEARCH.value); - }); - }); - }); - paginationContainer.empty(); - const resultsCount = paginationContainer.createEl("span", { cls: "dn-pagination-total-results", text: `File(s): ${f.length}` + this._selected_category }); - const currentPageIndicator = paginationContainer.createEl("span", { cls: "dn-pagination-current-page", text: `Page ${currentPage} of ${this._total_pages}` }); - const btnPrev = paginationContainer.createEl("button", { cls: "dn-btn-prev", text: "\u25C0", title: "Previous" }); - if (currentPage === 1) { - btnPrev.disabled = true; - } else { - btnPrev.disabled = false; - } - btnPrev.addEventListener("click", () => { - if (currentPage > 1) { - this.dnShowSearchResults({ f, el, leaf, currentPage: currentPage - 1 }); - } - }); - const btnNext = paginationContainer.createEl("button", { cls: "dn-btn-next", text: "\u25B6", title: "Next" }); - if (currentPage === this._total_pages) { - btnNext.disabled = true; - } else { - btnNext.disabled = false; - } - btnNext.addEventListener("click", () => { - if (currentPage < this._total_pages) { - this.dnShowSearchResults({ f, el, leaf, currentPage: currentPage + 1 }); - } - }); - this.dnUpdateSortIndicators( - this._sort_column, - this._sort_order, - this._th1, - this._th2, - this._th3, - this._th4 - ); - } else { - tr.empty(); - this._divSearchResults.createEl("p", { cls: "dn-no-results-found", text: "No files found." }); - } - } dnAlternateSortColumn(colName) { switch (colName) { case "name": @@ -978,6 +1210,9 @@ var DNModal = class extends import_obsidian2.Modal { case "path": this.dnSortColumnString("path", this._sort_order, true); break; + case "ext": + this.dnSortColumnString("ext", this._sort_order, true); + break; case "size": this.dnSortColumnNumber("size", this._sort_order, true); break; @@ -985,59 +1220,37 @@ var DNModal = class extends import_obsidian2.Modal { this.dnSortColumnNumber("modified", this._sort_order, true); break; } - this.dnShowSearchResults({ f: this._filtered_files, el: this._divSearchResults, leaf: this._leaf }); + this.dnShowModalSearchResults({ f: this._files_results, el: this._divSearchResults, leaf: this._leaf }); } - dnGetTagsPerFile(file) { - var _a, _b; - const cur_file = this.app.vault.getAbstractFileByPath(file.path); - if (cur_file !== null) { - const tags = (_a = this.app.metadataCache.getFileCache(file)) == null ? void 0 : _a.tags; - const frontmatter_tags = (_b = this.app.metadataCache.getFileCache(file)) == null ? void 0 : _b.frontmatter; - const arrTags = []; - if (tags) { - for (let i = 0, len = tags.length; i < len; i++) { - if (arrTags.indexOf(tags[i].tag) < 0) { - arrTags.push(tags[i].tag); - } - } - } - if (frontmatter_tags !== void 0 && frontmatter_tags.tags) { - for (let i = 0, len = frontmatter_tags.tags.length; i < len; i++) { - if (arrTags.indexOf(frontmatter_tags.tags[i]) < 0) { - arrTags.push("#" + frontmatter_tags.tags[i]); - } - } - } - return arrTags.join(" "); - } else { - return ""; - } - } - dnUpdateSortIndicators(activeColumn, sortOrder, col1, col2, col3, col4) { + dnUpdateSortIndicators(activeColumn, sortOrder, col1, col2, col3, col4, col5) { col1.classList.remove("sort-active", "sort-asc", "sort-desc"); col2.classList.remove("sort-active", "sort-asc", "sort-desc"); col3.classList.remove("sort-active", "sort-asc", "sort-desc"); col4.classList.remove("sort-active", "sort-asc", "sort-desc"); - let activeThCell = col4; + col5.classList.remove("sort-active", "sort-asc", "sort-desc"); + let activeThCell = col5; switch (activeColumn) { case "name": activeThCell = col1; break; - case "path": + case "ext": activeThCell = col2; break; - case "size": + case "path": activeThCell = col3; break; - case "modified": + case "size": activeThCell = col4; break; + case "modified": + activeThCell = col5; + break; } activeThCell.classList.add("sort-active"); activeThCell.classList.add(sortOrder === "asc" ? "sort-asc" : "sort-desc"); } dnSortColumnString(sortColumn, sortOrder, toggleSortOrder) { - const supportedColumns = ["name", "path"]; + const supportedColumns = ["name", "path", "ext"]; if (!supportedColumns.includes(sortColumn)) { return; } @@ -1052,17 +1265,23 @@ var DNModal = class extends import_obsidian2.Modal { } const sortValue = sortColumn + "-" + this._sort_order; this.dnSetSelectSortValue(sortValue); - this._filtered_files.sort((fileA, fileB) => { + this._files_results.sort((fileA, fileB) => { let sortA; let sortB; + let folderStructureA; + let folderStructureB; switch (sortColumn) { case "name": sortA = fileA.name.toLowerCase(); sortB = fileB.name.toLowerCase(); break; + case "ext": + sortA = fileA.extension.toLowerCase(); + sortB = fileB.extension.toLowerCase(); + break; case "path": - const folderStructureA = getFolderStructure(fileA.path); - const folderStructureB = getFolderStructure(fileB.path); + folderStructureA = getFolderStructure(fileA.path); + folderStructureB = getFolderStructure(fileB.path); sortA = folderStructureA.toLowerCase(); sortB = folderStructureB.toLowerCase(); break; @@ -1095,7 +1314,7 @@ var DNModal = class extends import_obsidian2.Modal { } const sortValue = sortColumn + "-" + this._sort_order; this.dnSetSelectSortValue(sortValue); - this._filtered_files.sort((fileA, fileB) => { + this._files_results.sort((fileA, fileB) => { let sortA = 0; let sortB = 0; switch (sortColumn) { @@ -1121,6 +1340,38 @@ var DNModal = class extends import_obsidian2.Modal { const arrRecentFiles = files; return arrRecentFiles.sort((a, b) => b.stat.mtime - a.stat.mtime).slice(0, this.num_recent_files); } + async dnCreateRecentFiles(title, divF, files, num_files) { + if (files.length === 0) { + divF.createEl("h3", { cls: "dn-subtitles", text: title }); + divF.createEl("p", { cls: "dn-no-results-found", text: "No files found." }); + divF.classList.add("dn-display-none"); + } else { + divF.createEl("h3", { cls: "dn-subtitles", text: title }); + let sortedFiles = []; + if (title === "Recently opened") { + sortedFiles = files.slice(0, this.num_recent_files); + } else { + sortedFiles = await this.dnGetRecentFiles(files); + } + sortedFiles.forEach((sfile) => { + const aLink = divF.createEl("a", { + cls: this.dnSetFileIconClass(sfile.extension), + text: sfile.basename, + title: sfile.path + }); + aLink.onClickEvent((evt) => { + if (sfile !== null) { + this.dnOpenFileAlt(sfile, evt); + } + }); + if (sfile.extension !== "md") { + divF.createEl("span", { cls: "nav-file-tag", text: sfile.extension }); + } + divF.createEl("br"); + aLink.addEventListener("mouseover", (evt) => this.dnHandleHoverPreview(evt, sfile)); + }); + } + } async dnOrganizeFiles({ arr }) { const arrNotes = []; const arrImages = []; @@ -1131,21 +1382,36 @@ var DNModal = class extends import_obsidian2.Modal { const arrOther = []; const extensions = { "md": arrNotes, - "png": arrImages, - "jpg": arrImages, - "webp": arrImages, - "ico": arrImages, + // Images + "avif": arrImages, "bmp": arrImages, "gif": arrImages, + "ico": arrImages, + "jpeg": arrImages, + "jpg": arrImages, + "png": arrImages, + "raw": arrImages, + "svg": arrImages, "tif": arrImages, "tiff": arrImages, - "raw": arrImages, + "webp": arrImages, + // Audios + "aac": arrAudios, + "aif": arrAudios, + "aifc": arrAudios, + "aiff": arrAudios, + "flac": arrAudios, + "m4a": arrAudios, "mp3": arrAudios, - "wav": arrAudios, "ogg": arrAudios, + "wav": arrAudios, "webm": arrAudios, - "mp4": arrVideos, + // Videos "avi": arrVideos, + "mov": arrVideos, + "mkv": arrVideos, + "mp4": arrVideos, + // PDF and other formats "pdf": arrPDFs, "canvas": arrCanvas }; @@ -1170,21 +1436,36 @@ var DNModal = class extends import_obsidian2.Modal { const file_extension = ext.toLowerCase(); const extensions = { "md": "note", - "png": "image", - "jpg": "image", - "webp": "image", - "ico": "image", + // Images + "avif": "image", "bmp": "image", "gif": "image", + "ico": "image", + "jpeg": "image", + "jpg": "image", + "png": "image", + "raw": "image", + "svg": "image", "tif": "image", "tiff": "image", - "raw": "image", + "webp": "image", + // Audios + "aac": "audio", + "aif": "audio", + "aifc": "audio", + "aiff": "audio", + "flac": "audio", + "m4a": "audio", "mp3": "audio", - "wav": "audio", "ogg": "audio", + "wav": "audio", "webm": "audio", - "mp4": "video", + // Videos "avi": "video", + "mov": "video", + "mkv": "video", + "mp4": "video", + // PDF and other formats "pdf": "pdf", "canvas": "canvas" }; @@ -1194,6 +1475,25 @@ var DNModal = class extends import_obsidian2.Modal { return "dn-f-other"; } } + // Custom Colors + dnSetCustomColors() { + document.body.style.setProperty("--dn-notes-color", this.color_notes); + document.body.style.setProperty("--dn-images-color", this.color_images); + document.body.style.setProperty("--dn-canvas-color", this.color_canvas); + document.body.style.setProperty("--dn-videos-color", this.color_videos); + document.body.style.setProperty("--dn-audios-color", this.color_audios); + document.body.style.setProperty("--dn-pdfs-color", this.color_pdf); + document.body.style.setProperty("--dn-other-color", this.color_other); + } + dnToggleColoredFiles() { + const dnMainContainer = document.getElementById("dn-container"); + if (this.colored_files) { + dnMainContainer == null ? void 0 : dnMainContainer.classList.add("dn-colored-files"); + } else { + dnMainContainer == null ? void 0 : dnMainContainer.classList.remove("dn-colored-files"); + } + this.dnSetCustomColors(); + } dnSetView(view) { const divElements = [this._VIEW_DASHBOARD, this._VIEW_NAVIGATOR]; const topNavBtns = [this._BTN_DASHBOARD, this._BTN_NAVIGATOR]; @@ -1246,47 +1546,6 @@ var DNModal = class extends import_obsidian2.Modal { this.dnSelectTableLayout(); } } - dnOpenFileAlt(f, evt) { - if (!evt || typeof evt !== "object" || !(f instanceof import_obsidian2.TFile)) { - return; - } - try { - if (evt.button === 0 && (evt.ctrlKey || evt.metaKey)) { - this.app.workspace.getLeaf("tab").openFile(f); - } else if (evt.button === 1) { - this.app.workspace.getLeaf("tab").openFile(f); - } else if (evt.button === 0) { - this.dnOpenFile(f); - } else if (evt.button === 2 && !(evt.target instanceof HTMLTableCellElement)) { - evt.preventDefault(); - this.dnGenerateContextMenu(evt, f); - } - } catch (er) { - return; - } - } - dnOpenFile(file) { - this.app.workspace.getLeaf(false).openFile(file); - this.close(); - } - dnHandleClick(evt, file) { - if (!evt || typeof evt !== "object" || !(file instanceof import_obsidian2.TFile)) { - return; - } - this.dnSelectTableRow(evt); - if (evt.button === 2) { - evt.preventDefault(); - this.dnGenerateContextMenu(evt, file); - } - } - dnHandleDblClick(evt, file) { - if (!evt || typeof evt !== "object" || !(file instanceof import_obsidian2.TFile)) { - return; - } - evt.preventDefault(); - this.dnSelectTableRow(evt); - this.dnOpenFile(file); - } dnSelectTableLayout() { const val = this._SELECT_TABLE_LAYOUT.value; if (this._TABLE_LAYOUTS.includes(val)) { @@ -1334,75 +1593,411 @@ var DNModal = class extends import_obsidian2.Modal { }) ); this._DN_CTX_MENU.addSeparator(); + this._DN_CTX_MENU.addItem( + (item) => item.setTitle("Show preview").setIcon("eye").onClick((evt2) => { + this.dnShowPreviewFile(evt2, file); + }) + ); + this._DN_CTX_MENU.addSeparator(); + this._DN_CTX_MENU.addItem( + (item) => item.setTitle("Frontmatter").setIcon("text").onClick(() => { + const fpModal = new import_obsidian2.Modal(this.app); + fpModal.contentEl.setAttribute("class", "dn-frontmatter-modal"); + fpModal.contentEl.createEl("h4", { text: "Frontmatter" }); + const rowName = fpModal.contentEl.createEl("div", { cls: "dn-property-row" }); + rowName.createEl("div", { text: "Name: ", cls: "dn-property-name-sm" }); + rowName.createEl("div", { text: file.name, cls: "dn-property-value" }); + const rowPath = fpModal.contentEl.createEl("div", { cls: "dn-property-row" }); + rowPath.createEl("div", { text: "Path: ", cls: "dn-property-name-sm" }); + rowPath.createEl("div", { text: getFolderStructure(file.path), cls: "dn-property-value" }); + fpModal.contentEl.createEl("br"); + fpModal.contentEl.createEl("span", { text: "Frontmatter: ", cls: "dn-properties" }); + fpModal.contentEl.createEl("br"); + const frontmatterDiv = fpModal.contentEl.createEl("div", { cls: "dn-properties-frontmatter-modal" }); + frontmatterDiv.setAttribute("contenteditable", "true"); + frontmatterDiv.setAttribute("spellcheck", "false"); + const curProps = getPropsPerFile(file); + if (curProps) { + const prop = curProps.split(" \n"); + for (let i = 0, len = prop.length; i < len; i++) { + frontmatterDiv.createEl("a", { text: prop[i], cls: "dn-fproperties" }).onClickEvent((evt2) => { + if (evt2.button === 2) { + evt2.preventDefault(); + } else { + fpModal.close(); + this._INPUT_SEARCH.value = prop[i]; + this.dnModalSearchVault(this._INPUT_SEARCH.value); + } + }); + frontmatterDiv.createEl("br"); + } + } else { + frontmatterDiv.createEl("span", { text: "No frontmatter" }); + } + fpModal.contentEl.createEl("br"); + const divBottom = fpModal.contentEl.createEl("div", { cls: "dn-div-bottom-properties" }); + const btnPropsOpen = divBottom.createEl("button", { text: "Open", cls: "dn-btn-properties-open-file" }); + btnPropsOpen.onClickEvent(() => { + fpModal.close(); + this.dnOpenFile(file); + }); + const btnCloseProps = divBottom.createEl("button", { text: "Close", cls: "dn-btn-properties-close" }); + btnCloseProps.onClickEvent(() => { + fpModal.close(); + }); + fpModal.open(); + frontmatterDiv.blur(); + }) + ); this._DN_CTX_MENU.addItem( (item) => item.setTitle("File properties").setIcon("file-cog").onClick(() => { const mdFileProps = new import_obsidian2.Modal(this.app); - mdFileProps.contentEl.createEl("h4", { text: "Properties" }); - const propFileName = mdFileProps.contentEl.createEl("div"); - propFileName.createEl("span", { text: "File name: ", cls: "dn-properties" }); - propFileName.createEl("span", { text: file.basename }); + mdFileProps.contentEl.setAttribute("class", "dn-properties-modal"); + mdFileProps.contentEl.createEl("h4", { text: "File properties" }); + const rowName = mdFileProps.contentEl.createEl("div", { cls: "dn-property-row" }); + rowName.createEl("div", { text: "Name: ", cls: "dn-property-name" }); + rowName.createEl("div", { text: file.name, cls: "dn-property-value" }); + const rowExt = mdFileProps.contentEl.createEl("div", { cls: "dn-property-row" }); + rowExt.createEl("div", { text: "Extension: ", cls: "dn-property-name" }); + const rowExtValue = rowExt.createEl("div", { cls: "dn-property-value" }); + rowExtValue.createEl("span", { text: file.extension, cls: "nav-file-tag" }); + const rowPath = mdFileProps.contentEl.createEl("div", { cls: "dn-property-row" }); + rowPath.createEl("div", { text: "Path: ", cls: "dn-property-name" }); + rowPath.createEl("div", { text: getFolderStructure(file.path), cls: "dn-property-value" }); mdFileProps.contentEl.createEl("br"); - const propFileExt = mdFileProps.contentEl.createEl("div"); - propFileExt.createEl("span", { text: "Extension: ", cls: "dn-properties" }); - propFileExt.createEl("span", { text: file.extension, cls: "nav-file-tag" }); + const rowSize = mdFileProps.contentEl.createEl("div", { cls: "dn-property-row" }); + rowSize.createEl("div", { text: "Size: ", cls: "dn-property-name" }); + rowSize.createEl("div", { text: formatFileSize(file.stat.size) + " bytes" + formatFileSizeKBMB(file.stat.size) }); mdFileProps.contentEl.createEl("br"); - const propFilePath = mdFileProps.contentEl.createEl("div"); - propFilePath.createEl("span", { text: "Path: ", cls: "dn-properties" }); - propFilePath.createEl("span", { text: getFolderStructure(file.path) }); + const rowDateCreated = mdFileProps.contentEl.createEl("div", { cls: "dn-property-row" }); + rowDateCreated.createEl("div", { text: "Created: ", cls: "dn-property-name" }); + rowDateCreated.createEl("div", { text: (0, import_obsidian3.moment)(file.stat.ctime).format(this.date_format) }); + const rowDateModified = mdFileProps.contentEl.createEl("div", { cls: "dn-property-row" }); + rowDateModified.createEl("div", { text: "Modified: ", cls: "dn-property-name" }); + rowDateModified.createEl("div", { text: (0, import_obsidian3.moment)(file.stat.mtime).format(this.date_format) }); mdFileProps.contentEl.createEl("br"); - const propFileSize = mdFileProps.contentEl.createEl("div"); - propFileSize.createEl("span", { text: "Size: ", cls: "dn-properties" }); - propFileSize.createEl("span", { text: formatFileSize(file.stat.size) + " bytes" }); - mdFileProps.contentEl.createEl("br"); - const propDateCreated = mdFileProps.contentEl.createEl("div"); - propDateCreated.createEl("span", { text: "Created: ", cls: "dn-properties" }); - propDateCreated.createEl("span", { text: (0, import_obsidian3.moment)(file.stat.ctime).format(this.date_format) }); - mdFileProps.contentEl.createEl("br"); - const propDateModified = mdFileProps.contentEl.createEl("div"); - propDateModified.createEl("span", { text: "Modified: ", cls: "dn-properties" }); - propDateModified.createEl("span", { text: (0, import_obsidian3.moment)(file.stat.mtime).format(this.date_format) }); - mdFileProps.contentEl.createEl("br"); - const propTags = mdFileProps.contentEl.createEl("div"); - const curTags = this.dnGetTagsPerFile(file); - propTags.createEl("span", { text: "Tag(s): ", cls: "dn-properties" }); + const rowTags = mdFileProps.contentEl.createEl("div", { cls: "dn-property-row" }); + rowTags.createEl("div", { text: "Tag(s): ", cls: "dn-property-name" }); + const propTags = rowTags.createEl("div"); + const curTags = getTagsPerFile(file); if (curTags) { const tags = curTags.split(" "); for (let i = 0, len = tags.length; i < len; i++) { propTags.createEl("a", { text: tags[i], cls: "dn-tag" }).onClickEvent((evt2) => { - mdFileProps.close(); - this._INPUT_SEARCH.value = tags[i]; - this.dnSearchVault(this._INPUT_SEARCH.value); + if (evt2.button === 2) { + evt2.preventDefault(); + } else { + mdFileProps.close(); + this._INPUT_SEARCH.value = tags[i]; + this.dnModalSearchVault(this._INPUT_SEARCH.value); + } }); } - ; } else { propTags.createEl("span", { text: "No tags" }); } mdFileProps.contentEl.createEl("br"); - mdFileProps.contentEl.createEl("hr"); + mdFileProps.contentEl.createEl("span", { text: "Frontmatter: ", cls: "dn-properties" }); + mdFileProps.contentEl.createEl("br"); + const frontmatterProps = mdFileProps.contentEl.createEl("div", { cls: "dn-properties-frontmatter" }); + frontmatterProps.setAttribute("contenteditable", "true"); + frontmatterProps.setAttribute("spellcheck", "false"); + const curProps = getPropsPerFile(file); + if (curProps) { + const prop = curProps.split(" \n"); + for (let i = 0, len = prop.length; i < len; i++) { + frontmatterProps.createEl("a", { text: prop[i], cls: "dn-fproperties" }).onClickEvent((evt2) => { + if (evt2.button === 2) { + evt2.preventDefault(); + } else { + mdFileProps.close(); + this._INPUT_SEARCH.value = prop[i]; + this.dnModalSearchVault(this._INPUT_SEARCH.value); + } + }); + frontmatterProps.createEl("br"); + } + } else { + frontmatterProps.createEl("span", { text: "No frontmatter" }); + } + mdFileProps.contentEl.createEl("br"); const divBottom = mdFileProps.contentEl.createEl("div", { cls: "dn-div-bottom-properties" }); - const btnCloseProps = divBottom.createEl("button", { text: "Ok", cls: "dn-btn-close-properties" }); + const btnPropsOpen = divBottom.createEl("button", { text: "Open", cls: "dn-btn-properties-open-file" }); + btnPropsOpen.onClickEvent(() => { + mdFileProps.close(); + this.dnOpenFile(file); + }); + const btnCloseProps = divBottom.createEl("button", { text: "Close", cls: "dn-btn-properties-close" }); btnCloseProps.onClickEvent(() => { mdFileProps.close(); }); mdFileProps.open(); + frontmatterProps.blur(); }) ); this._DN_CTX_MENU.showAtMouseEvent(evt); } + dnHandleClick(evt, file) { + if (!evt || typeof evt !== "object" || !(file instanceof import_obsidian2.TFile)) { + return; + } + this.dnSelectTableRow(evt); + if (evt.button === 2) { + evt.preventDefault(); + this.dnGenerateContextMenu(evt, file); + } + } + dnHandleDblClick(evt, file) { + if (!evt || typeof evt !== "object" || !(file instanceof import_obsidian2.TFile)) { + return; + } + evt.preventDefault(); + this.dnSelectTableRow(evt); + this.dnOpenFile(file); + } + dnHandleHoverPreview(evt, file) { + evt.stopImmediatePropagation(); + if (evt.ctrlKey || evt.metaKey) { + this.dnShowPreviewFile(evt, file); + } + } + dnShowPreviewFile(evt, file) { + this._hoverDiv.empty(); + const topBar = this._hoverDiv.createEl("div", { cls: "dn-preview-top-bar" }); + const btnClosePreview = topBar.createEl("div", { cls: "modal-close-button" }); + btnClosePreview.onClickEvent((evt2) => { + evt2.stopPropagation(); + this.dnHidePreview(); + }); + const previewTop = topBar.createEl("div", "dn-preview-titlebar"); + const divPreviewName = previewTop.createEl("div", { cls: "dn-property-row" }); + divPreviewName.createEl("div", { text: "Name: ", cls: "dn-property-name-sm" }); + divPreviewName.createEl("div", { text: file.name, cls: "dn-property-value" }); + const divPreviewPath = previewTop.createEl("div", { cls: "dn-property-row" }); + divPreviewPath.createEl("div", { text: "Path: ", cls: "dn-property-name-sm" }); + divPreviewPath.createEl("div", { text: getFolderStructure(file.path), cls: "dn-property-value" }); + const divButtons = topBar.createEl("div", { cls: "dn-div-top-preview-btns" }); + const btnPreviewOpenFile = divButtons.createEl("button", { text: "Open", cls: "dn-btn-properties-open-file" }); + btnPreviewOpenFile.onClickEvent(() => { + this.dnHidePreview(); + this.close(); + this.dnOpenFile(file); + }); + const btnPreviewOpenFileNewTab = divButtons.createEl("button", { text: "Open in new tab", cls: "dn-btn-properties-open-file" }); + btnPreviewOpenFileNewTab.onClickEvent(() => { + this.dnHidePreview(); + this.close(); + this.app.workspace.getLeaf("tab").openFile(file); + }); + const btnPreviewOpenFileNewWindow = divButtons.createEl("button", { text: "Open in new window", cls: "dn-btn-properties-open-file" }); + btnPreviewOpenFileNewWindow.onClickEvent(() => { + this.dnHidePreview(); + this.app.workspace.getLeaf("window").openFile(file); + }); + this._hoverRender = this._hoverDiv.createEl("div", { cls: "dn-pr-content" }); + import_obsidian2.MarkdownRenderer.render( + this.app, + "![[" + file.path + "]]", + this._hoverRender, + file.path, + this._previewComponent + ); + this._hoverRender.addEventListener("mousedown", (evt2) => { + evt2.stopPropagation(); + }); + previewTop.addEventListener("mousedown", (evt2) => this.dnHoverDragOnMouseDown(evt2)); + this._hoverDiv.addEventListener("mousemove", (evt2) => this.dnHoverDragOnMouseMove(evt2)); + this._hoverDiv.addEventListener("mouseup", (evt2) => this.dnHoverDragOnMouseUp(evt2)); + this._hoverDiv.style.display = "block"; + const screenWidth = window.innerWidth; + const screenHeight = window.innerHeight; + const divW = this._hoverDiv.offsetWidth; + const divH = this._hoverDiv.offsetHeight; + if (this._hoverDivLeft === "") { + this._hoverDiv.style.left = ((screenWidth - divW) / 2).toString() + "px"; + this._hoverDiv.style.top = ((screenHeight - divH) / 2).toString() + "px"; + } + previewTop.removeEventListener("mousedown", (evt2) => this.dnHoverDragOnMouseDown(evt2)); + this._hoverRender.removeEventListener("mousedown", (evt2) => { + evt2.stopPropagation(); + }); + } + dnHidePreview() { + this._isDraggingPreview = false; + this._hoverDiv.style.display = "none"; + this._hoverDiv.empty(); + } + dnHandleNormalSearch(rExp, file) { + return rExp.test(file.name.toLowerCase()) || rExp.test(getFolderStructure(file.path).toLowerCase()) || rExp.test((0, import_obsidian3.moment)(file.stat.mtime).format(this.date_format)) || rExp.test(getTagsPerFile(file).toLowerCase()) || rExp.test(getPropsPerFile(file).toLowerCase()); + } + dnHandleSpecialSearch(search, file) { + const mtime = (0, import_obsidian3.moment)(file.stat.mtime); + switch (search) { + case "d": + case "day": + case "today": + return mtime.isSame((0, import_obsidian3.moment)(), "day"); + case "d-1": + case "day-1": + case "yesterday": + return mtime.isBetween((0, import_obsidian3.moment)().subtract(1, "days"), (0, import_obsidian3.moment)(), "day", "[]"); + case "d-2": + case "day-2": + return mtime.isBetween((0, import_obsidian3.moment)().subtract(2, "days"), (0, import_obsidian3.moment)(), "day", "[]"); + case "d-3": + case "day-3": + return mtime.isBetween((0, import_obsidian3.moment)().subtract(3, "days"), (0, import_obsidian3.moment)(), "day", "[]"); + case "d-4": + case "day-4": + return mtime.isBetween((0, import_obsidian3.moment)().subtract(4, "days"), (0, import_obsidian3.moment)(), "day", "[]"); + case "d-5": + case "day-5": + return mtime.isBetween((0, import_obsidian3.moment)().subtract(5, "days"), (0, import_obsidian3.moment)(), "day", "[]"); + case "d-6": + case "day-6": + return mtime.isBetween((0, import_obsidian3.moment)().subtract(6, "days"), (0, import_obsidian3.moment)(), "day", "[]"); + case "d-7": + case "day-7": + case "w": + case "week": + return mtime.isBetween((0, import_obsidian3.moment)().subtract(7, "days"), (0, import_obsidian3.moment)(), "day", "[]"); + case "m": + case "month": + return mtime.isSame((0, import_obsidian3.moment)(), "month"); + case "m-1": + case "month-1": + return mtime.isBetween((0, import_obsidian3.moment)().subtract(1, "month"), (0, import_obsidian3.moment)(), "month", "[]"); + case "m-2": + case "month-2": + return mtime.isBetween((0, import_obsidian3.moment)().subtract(2, "month"), (0, import_obsidian3.moment)(), "month", "[]"); + case "m-3": + case "month-3": + return mtime.isBetween((0, import_obsidian3.moment)().subtract(3, "month"), (0, import_obsidian3.moment)(), "month", "[]"); + case "m-4": + case "month-4": + return mtime.isBetween((0, import_obsidian3.moment)().subtract(4, "month"), (0, import_obsidian3.moment)(), "month", "[]"); + case "m-5": + case "month-5": + return mtime.isBetween((0, import_obsidian3.moment)().subtract(5, "month"), (0, import_obsidian3.moment)(), "month", "[]"); + case "m-6": + case "month-6": + return mtime.isBetween((0, import_obsidian3.moment)().subtract(6, "month"), (0, import_obsidian3.moment)(), "month", "[]"); + case "m-7": + case "month-7": + return mtime.isBetween((0, import_obsidian3.moment)().subtract(7, "month"), (0, import_obsidian3.moment)(), "month", "[]"); + case "m-8": + case "month-8": + return mtime.isBetween((0, import_obsidian3.moment)().subtract(8, "month"), (0, import_obsidian3.moment)(), "month", "[]"); + case "m-9": + case "month-9": + return mtime.isBetween((0, import_obsidian3.moment)().subtract(9, "month"), (0, import_obsidian3.moment)(), "month", "[]"); + case "m-10": + case "month-10": + return mtime.isBetween((0, import_obsidian3.moment)().subtract(10, "month"), (0, import_obsidian3.moment)(), "month", "[]"); + case "m-11": + case "month-11": + return mtime.isBetween((0, import_obsidian3.moment)().subtract(11, "month"), (0, import_obsidian3.moment)(), "month", "[]"); + case "m-12": + case "month-12": + return mtime.isBetween((0, import_obsidian3.moment)().subtract(12, "month"), (0, import_obsidian3.moment)(), "month", "[]"); + case "y": + case "year": + return mtime.isSame((0, import_obsidian3.moment)(), "year"); + case "n": + case "notes": + return this._notes.includes(file); + case "c": + case "canvases": + case "canvas": + return this._canvas.includes(file); + case "i": + case "images": + return this._images.includes(file); + case "a": + case "audios": + return this._audios.includes(file); + case "v": + case "videos": + return this._videos.includes(file); + case "p": + case "pdf": + case "pdfs": + return this._pdf.includes(file); + case "o": + case "other": + case "others": + return this._other.includes(file); + default: + return false; + } + } + dnOpenFileAlt(f, evt) { + if (!evt || typeof evt !== "object" || !(f instanceof import_obsidian2.TFile)) { + return; + } + try { + if (evt.button === 0 && (evt.ctrlKey || evt.metaKey)) { + this.app.workspace.getLeaf("tab").openFile(f); + } else if (evt.button === 1) { + this.app.workspace.getLeaf("tab").openFile(f); + } else if (evt.button === 0) { + this.dnOpenFile(f); + } else if (evt.button === 2 && !(evt.target instanceof HTMLTableCellElement)) { + evt.preventDefault(); + this.dnGenerateContextMenu(evt, f); + } + } catch (er) { + return; + } + } + dnOpenFile(file) { + this.app.workspace.getLeaf(false).openFile(file); + this.close(); + } + dnHoverDragOnMouseDown(evt) { + evt.stopPropagation(); + this._isDraggingPreview = true; + this.initialX = evt.screenX - this._hoverDiv.offsetLeft; + this.initialY = evt.screenY - this._hoverDiv.offsetTop; + this.previousX = evt.screenX; + this.previousY = evt.screenY; + } + dnHoverDragOnMouseMove(evt) { + evt.stopPropagation(); + if (this._isDraggingPreview) { + const newX = evt.screenX - this.initialX; + const newY = evt.screenY - this.initialY; + if (Math.abs(evt.screenX - this.previousX) > 5 || Math.abs(evt.screenY - this.previousY) > 5) { + this._hoverDiv.style.left = newX + "px"; + this._hoverDiv.style.top = newY + "px"; + this.previousX = evt.screenX; + this.previousY = evt.screenY; + } + this._hoverDivLeft = newX + "px"; + this._hoverDivTop = newY + "px"; + } + } + dnHoverDragOnMouseUp(evt) { + evt.stopPropagation(); + this._isDraggingPreview = false; + } onClose() { const { contentEl } = this; contentEl.empty(); + this._previewComponent.unload(); if (this._INPUT_SEARCH && this._INPUT_SEARCH.removeEventListener) { - this._INPUT_SEARCH.removeEventListener("input", (0, import_obsidian2.debounce)(() => this.dnSearchVault(this._INPUT_SEARCH.value), 300, true)); + this._INPUT_SEARCH.removeEventListener("input", (0, import_obsidian2.debounce)(() => this.dnModalSearchVault(this._INPUT_SEARCH.value), 300, true)); } this._th1.removeEventListener("dblclick", () => this.dnAlternateSortColumn("name")); - this._th2.removeEventListener("dblclick", () => this.dnAlternateSortColumn("path")); - this._th3.removeEventListener("dblclick", () => this.dnAlternateSortColumn("size")); - this._th4.removeEventListener("dblclick", () => this.dnAlternateSortColumn("modified")); + this._th2.removeEventListener("dblclick", () => this.dnAlternateSortColumn("ext")); + this._th3.removeEventListener("dblclick", () => this.dnAlternateSortColumn("path")); + this._th4.removeEventListener("dblclick", () => this.dnAlternateSortColumn("size")); + this._th5.removeEventListener("dblclick", () => this.dnAlternateSortColumn("modified")); this._SELECT_SORT.removeEventListener("change", () => { this.dnSortColumnWithSelect(); }); + this._hoverDiv.removeEventListener("mousemove", (evt) => this.dnHoverDragOnMouseMove(evt)); + this._hoverDiv.removeEventListener("mouseup", (evt) => this.dnHoverDragOnMouseUp(evt)); if (this.intersectionObserver) { this.intersectionObserver.disconnect(); } @@ -1426,58 +2021,92 @@ var DEFAULT_SETTINGS = { color_audios: "#bfbf00", color_pdf: "#00a300", color_other: "#828282", - colored_files: false + colored_files: false, + hide_ext: false, + hide_path: false, + hide_size: false, + hide_date: false, + hide_tags: false, + hide_frontmatter: false, + hide_columns: [] }; var DNPlugin = class extends import_obsidian4.Plugin { async onload() { await this.loadSettings(); - this._DN_MODAL = new DNModal(this.app); - this._DN_MODAL.default_view = this.settings.default_view; - this._DN_MODAL.date_format = this.settings.date_format; - this._DN_MODAL.num_recent_files = this.settings.num_recent_files; - this._DN_MODAL.files_per_page = this.settings.files_per_page; - this._DN_MODAL.selected_table_layout = this.settings.selected_table_layout; - this._DN_MODAL.excluded_extensions = this.dnGetExcludedExtensions(this.settings.excluded_ext); - this._DN_MODAL.excluded_folders = this.dnGetExcludedFolders(this.settings.excluded_path); + this.DN_MODAL = new DNModal(this.app); + this.DN_MODAL.default_view = this.settings.default_view; + this.DN_MODAL.date_format = this.settings.date_format; + this.DN_MODAL.num_recent_files = this.settings.num_recent_files; + this.DN_MODAL.files_per_page = this.settings.files_per_page; + this.DN_MODAL.selected_table_layout = this.settings.selected_table_layout; + this.DN_MODAL.excluded_extensions = this.dnGetExcludedExtensions(this.settings.excluded_ext); + this.DN_MODAL.excluded_folders = this.dnGetExcludedFolders(this.settings.excluded_path); this.dnSetFontSize(this.settings.font_size); - this._DN_MODAL.colored_files = this.settings.colored_files; - this._DN_MODAL.color_notes = this.settings.color_notes; - this._DN_MODAL.color_canvas = this.settings.color_canvas; - this._DN_MODAL.color_images = this.settings.color_images; - this._DN_MODAL.color_videos = this.settings.color_videos; - this._DN_MODAL.color_audios = this.settings.color_audios; - this._DN_MODAL.color_pdf = this.settings.color_pdf; - this._DN_MODAL.color_other = this.settings.color_other; + this.DN_MODAL.colored_files = this.settings.colored_files; + this.DN_MODAL.color_notes = this.settings.color_notes; + this.DN_MODAL.color_canvas = this.settings.color_canvas; + this.DN_MODAL.color_images = this.settings.color_images; + this.DN_MODAL.color_videos = this.settings.color_videos; + this.DN_MODAL.color_audios = this.settings.color_audios; + this.DN_MODAL.color_pdf = this.settings.color_pdf; + this.DN_MODAL.color_other = this.settings.color_other; + this.DN_MODAL.hide_columns = this.dnSetHiddenColumns(this.settings.hide_columns); this.addRibbonIcon("gauge", "Open dashboard navigator", (evt) => { - this._DN_MODAL.default_view = this.settings.default_view; - this._DN_MODAL.open(); - }); - this.addCommand({ - id: "activate", - name: "Open", - callback: () => { - this._DN_MODAL.default_view = this.settings.default_view; - this._DN_MODAL.open(); - } + this.DN_MODAL.default_view = this.settings.default_view; + this.DN_MODAL.open(); }); this.addCommand({ id: "dashboard", name: "Open dashboard", callback: () => { - this._DN_MODAL.default_view = 1; - this._DN_MODAL.open(); + this.DN_MODAL.default_view = 1; + this.DN_MODAL.open(); } }); this.addCommand({ id: "navigator", name: "Open navigator", callback: () => { - this._DN_MODAL.default_view = 2; - this._DN_MODAL.open(); + this.DN_MODAL.default_view = 2; + this.DN_MODAL.open(); } }); this.addSettingTab(new DNSettingTab(this.app, this)); } + dnSetFontSize(val) { + if (val >= 12 || val <= 24) { + document.body.style.setProperty("--dn-font-size", val.toString() + "px"); + } + } + dnSetHiddenColumns(arrCols) { + const allowedCols = ["ext", "path", "size", "date", "tags", "frontmatter"]; + arrCols = arrCols.filter((col) => allowedCols.includes(col)); + if (arrCols.length <= 6 && arrCols.some((col) => ["ext", "path", "size", "date", "tags", "frontmatter"].includes(col))) { + return arrCols; + } else { + this.settings.hide_columns = []; + this.settings.hide_ext = false; + this.settings.hide_path = false; + this.settings.hide_size = false; + this.settings.hide_date = false; + this.settings.hide_tags = false; + this.settings.hide_frontmatter = false; + this.saveSettings(); + return []; + } + } + dnUpdateHideColumn(col, val) { + const allowedCols = ["ext", "path", "size", "date", "tags", "frontmatter"]; + if (allowedCols.includes(col) && val === true) { + if (!this.settings.hide_columns.includes(col)) { + this.settings.hide_columns.push(col); + this.DN_MODAL.hide_columns = this.settings.hide_columns; + } + } else { + this.settings.hide_columns = this.settings.hide_columns.filter((c) => c !== col); + this.DN_MODAL.hide_columns = this.settings.hide_columns; + } + } dnGetExcludedFolders(foldersString) { if (foldersString === "") { return []; @@ -1485,13 +2114,6 @@ var DNPlugin = class extends import_obsidian4.Plugin { const folders = foldersString.split(",").map((folder) => folder.trim()); return folders.map((folder) => folder.replace(/^\/|\/$|\.\./g, "")).filter((folder) => folder !== ""); } - dnSetFontSize(val) { - if (val >= 12 || val <= 24) { - const styles = getComputedStyle(document.body); - const fontSize = styles.getPropertyValue("--dn-font-size"); - document.body.style.setProperty("--dn-font-size", val.toString() + "px"); - } - } dnGetExcludedExtensions(excluded_ext) { if (excluded_ext === "") { return []; @@ -1511,4 +2133,6 @@ var DNPlugin = class extends import_obsidian4.Plugin { await this.saveData(this.settings); } }; -//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsic3JjL21haW4udHMiLCAic3JjL3NldHRpbmdzLnRzIiwgInNyYy9kbi50cyIsICJzcmMvdXRpbHMvZm9ybWF0LnRzIiwgInNyYy91dGlscy9waWVjaGFydC50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiaW1wb3J0IHsgUGx1Z2luIH0gZnJvbSAnb2JzaWRpYW4nO1xuaW1wb3J0IHsgRE5TZXR0aW5nVGFiIH0gZnJvbSAnLi9zZXR0aW5ncyc7XG5pbXBvcnQgeyBETk1vZGFsIH0gZnJvbSAnLi9kbic7XG5cbmludGVyZmFjZSBETlNldHRpbmdzIHtcblx0ZGVmYXVsdF92aWV3OiBudW1iZXI7XG5cdGZvbnRfc2l6ZTogbnVtYmVyO1xuXHRzZWxlY3RlZF90YWJsZV9sYXlvdXQ6IHN0cmluZztcblx0ZGF0ZV9mb3JtYXQ6IHN0cmluZztcblx0ZmlsZXNfcGVyX3BhZ2U6IG51bWJlcjtcblx0bnVtX3JlY2VudF9maWxlczogbnVtYmVyO1xuXHRleGNsdWRlZF9leHQ6IHN0cmluZztcblx0ZXhjbHVkZWRfcGF0aDogc3RyaW5nO1xuXHRjb2xvcl9ub3Rlczogc3RyaW5nO1xuXHRjb2xvcl9jYW52YXM6IHN0cmluZztcblx0Y29sb3JfaW1hZ2VzOiBzdHJpbmc7XG5cdGNvbG9yX3ZpZGVvczogc3RyaW5nO1xuXHRjb2xvcl9hdWRpb3M6IHN0cmluZztcblx0Y29sb3JfcGRmOiBzdHJpbmc7XG5cdGNvbG9yX290aGVyOiBzdHJpbmc7XG5cdGNvbG9yZWRfZmlsZXM6IGJvb2xlYW47XG59XG5cbmV4cG9ydCBjb25zdCBERUZBVUxUX1NFVFRJTkdTOiBETlNldHRpbmdzID0ge1xuXHRkZWZhdWx0X3ZpZXc6IDEsXG5cdGZvbnRfc2l6ZTogMTYsXG5cdHNlbGVjdGVkX3RhYmxlX2xheW91dDogJ2RuLXRibC1kZWZhdWx0Jyxcblx0ZGF0ZV9mb3JtYXQ6ICdZWVlZLU1NLUREIEhIOm1tJyxcblx0ZmlsZXNfcGVyX3BhZ2U6IDIwLFxuXHRudW1fcmVjZW50X2ZpbGVzOiA1LFxuXHRleGNsdWRlZF9leHQ6ICcnLFxuXHRleGNsdWRlZF9wYXRoOiAnJyxcblx0Y29sb3Jfbm90ZXM6ICcjYmY0OGZmJyxcblx0Y29sb3JfaW1hZ2VzOiAnIzAwN2ZmZicsXG5cdGNvbG9yX2NhbnZhczogJyNmZjdmMjgnLFxuXHRjb2xvcl92aWRlb3M6ICcjZDM0ODQ4Jyxcblx0Y29sb3JfYXVkaW9zOiAnI2JmYmYwMCcsXG5cdGNvbG9yX3BkZjogJyMwMGEzMDAnLFxuXHRjb2xvcl9vdGhlcjogJyM4MjgyODInLFxuXHRjb2xvcmVkX2ZpbGVzOiBmYWxzZVxufVxuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBETlBsdWdpbiBleHRlbmRzIFBsdWdpbiB7XG5cblx0X0ROX01PREFMOiBETk1vZGFsO1xuXG5cdHNldHRpbmdzOiBETlNldHRpbmdzO1xuXG5cdGFzeW5jIG9ubG9hZCgpIHtcblxuXHRcdGF3YWl0IHRoaXMubG9hZFNldHRpbmdzKCk7XG5cblx0XHR0aGlzLl9ETl9NT0RBTCA9IG5ldyBETk1vZGFsKHRoaXMuYXBwKTtcblxuXHRcdC8vIFNldCBtb2RhbCBzZXR0aW5nc1xuXHRcdHRoaXMuX0ROX01PREFMLmRlZmF1bHRfdmlldyA9IHRoaXMuc2V0dGluZ3MuZGVmYXVsdF92aWV3O1xuXHRcdHRoaXMuX0ROX01PREFMLmRhdGVfZm9ybWF0ID0gdGhpcy5zZXR0aW5ncy5kYXRlX2Zvcm1hdDtcblx0XHR0aGlzLl9ETl9NT0RBTC5udW1fcmVjZW50X2ZpbGVzID0gdGhpcy5zZXR0aW5ncy5udW1fcmVjZW50X2ZpbGVzO1xuXHRcdHRoaXMuX0ROX01PREFMLmZpbGVzX3Blcl9wYWdlID0gdGhpcy5zZXR0aW5ncy5maWxlc19wZXJfcGFnZTtcblx0XHR0aGlzLl9ETl9NT0RBTC5zZWxlY3RlZF90YWJsZV9sYXlvdXQgPSB0aGlzLnNldHRpbmdzLnNlbGVjdGVkX3RhYmxlX2xheW91dDtcblx0XHR0aGlzLl9ETl9NT0RBTC5leGNsdWRlZF9leHRlbnNpb25zID0gdGhpcy5kbkdldEV4Y2x1ZGVkRXh0ZW5zaW9ucyh0aGlzLnNldHRpbmdzLmV4Y2x1ZGVkX2V4dCk7XG5cdFx0dGhpcy5fRE5fTU9EQUwuZXhjbHVkZWRfZm9sZGVycyA9IHRoaXMuZG5HZXRFeGNsdWRlZEZvbGRlcnModGhpcy5zZXR0aW5ncy5leGNsdWRlZF9wYXRoKTtcblx0XHR0aGlzLmRuU2V0Rm9udFNpemUodGhpcy5zZXR0aW5ncy5mb250X3NpemUpO1xuXHRcdC8vIFNldCBjb2xvcnNcblx0XHR0aGlzLl9ETl9NT0RBTC5jb2xvcmVkX2ZpbGVzID0gdGhpcy5zZXR0aW5ncy5jb2xvcmVkX2ZpbGVzO1xuXHRcdHRoaXMuX0ROX01PREFMLmNvbG9yX25vdGVzID0gdGhpcy5zZXR0aW5ncy5jb2xvcl9ub3Rlcztcblx0XHR0aGlzLl9ETl9NT0RBTC5jb2xvcl9jYW52YXMgPSB0aGlzLnNldHRpbmdzLmNvbG9yX2NhbnZhcztcblx0XHR0aGlzLl9ETl9NT0RBTC5jb2xvcl9pbWFnZXMgPSB0aGlzLnNldHRpbmdzLmNvbG9yX2ltYWdlcztcblx0XHR0aGlzLl9ETl9NT0RBTC5jb2xvcl92aWRlb3MgPSB0aGlzLnNldHRpbmdzLmNvbG9yX3ZpZGVvcztcblx0XHR0aGlzLl9ETl9NT0RBTC5jb2xvcl9hdWRpb3MgPSB0aGlzLnNldHRpbmdzLmNvbG9yX2F1ZGlvcztcblx0XHR0aGlzLl9ETl9NT0RBTC5jb2xvcl9wZGYgPSB0aGlzLnNldHRpbmdzLmNvbG9yX3BkZjtcblx0XHR0aGlzLl9ETl9NT0RBTC5jb2xvcl9vdGhlciA9IHRoaXMuc2V0dGluZ3MuY29sb3Jfb3RoZXI7XG5cblx0XHR0aGlzLmFkZFJpYmJvbkljb24oJ2dhdWdlJywgJ09wZW4gZGFzaGJvYXJkIG5hdmlnYXRvcicsIChldnQ6IE1vdXNlRXZlbnQpID0+IHtcblx0XHRcdHRoaXMuX0ROX01PREFMLmRlZmF1bHRfdmlldyA9IHRoaXMuc2V0dGluZ3MuZGVmYXVsdF92aWV3O1xuXHRcdFx0dGhpcy5fRE5fTU9EQUwub3BlbigpO1xuXHRcdH0pO1xuXG5cblx0XHR0aGlzLmFkZENvbW1hbmQoe1xuXHRcdFx0aWQ6ICdhY3RpdmF0ZScsXG5cdFx0XHRuYW1lOiAnT3BlbicsXG5cdFx0XHRjYWxsYmFjazogKCkgPT4ge1xuXHRcdFx0XHR0aGlzLl9ETl9NT0RBTC5kZWZhdWx0X3ZpZXcgPSB0aGlzLnNldHRpbmdzLmRlZmF1bHRfdmlldztcblx0XHRcdFx0dGhpcy5fRE5fTU9EQUwub3BlbigpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXG5cdFx0dGhpcy5hZGRDb21tYW5kKHtcblx0XHRcdGlkOiAnZGFzaGJvYXJkJyxcblx0XHRcdG5hbWU6ICdPcGVuIGRhc2hib2FyZCcsXG5cdFx0XHRjYWxsYmFjazogKCkgPT4ge1xuXHRcdFx0XHR0aGlzLl9ETl9NT0RBTC5kZWZhdWx0X3ZpZXcgPSAxO1xuXHRcdFx0XHR0aGlzLl9ETl9NT0RBTC5vcGVuKCk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cblx0XHR0aGlzLmFkZENvbW1hbmQoe1xuXHRcdFx0aWQ6ICduYXZpZ2F0b3InLFxuXHRcdFx0bmFtZTogJ09wZW4gbmF2aWdhdG9yJyxcblx0XHRcdGNhbGxiYWNrOiAoKSA9PiB7XG5cdFx0XHRcdHRoaXMuX0ROX01PREFMLmRlZmF1bHRfdmlldyA9IDI7XG5cdFx0XHRcdHRoaXMuX0ROX01PREFMLm9wZW4oKTtcblx0XHRcdH1cblx0XHR9KTtcblxuXHRcdHRoaXMuYWRkU2V0dGluZ1RhYihuZXcgRE5TZXR0aW5nVGFiKHRoaXMuYXBwLCB0aGlzKSk7XG5cblx0fVxuXG5cdGRuR2V0RXhjbHVkZWRGb2xkZXJzKGZvbGRlcnNTdHJpbmc6IHN0cmluZyk6IHN0cmluZ1tdIHtcblx0XHRpZiAoZm9sZGVyc1N0cmluZyA9PT0gJycpIHtcblx0XHRcdHJldHVybiBbXTtcblx0XHR9XG5cblx0XHRjb25zdCBmb2xkZXJzID0gZm9sZGVyc1N0cmluZy5zcGxpdCgnLCcpLm1hcChmb2xkZXIgPT4gZm9sZGVyLnRyaW0oKSk7XG5cblx0XHRyZXR1cm4gZm9sZGVycy5tYXAoZm9sZGVyID0+IGZvbGRlci5yZXBsYWNlKC9eXFwvfFxcLyR8XFwuXFwuL2csICcnKSkuZmlsdGVyKGZvbGRlciA9PiBmb2xkZXIgIT09ICcnKTtcblx0fVxuXG5cdGRuU2V0Rm9udFNpemUodmFsOiBudW1iZXIpIHtcblx0XHRpZiAodmFsID49IDEyIHx8IHZhbCA8PSAyNCkge1xuXHRcdFx0Y29uc3Qgc3R5bGVzID0gZ2V0Q29tcHV0ZWRTdHlsZShkb2N1bWVudC5ib2R5KTtcblx0XHRcdGNvbnN0IGZvbnRTaXplID0gc3R5bGVzLmdldFByb3BlcnR5VmFsdWUoJy0tZG4tZm9udC1zaXplJyk7XG5cdFx0XHRkb2N1bWVudC5ib2R5LnN0eWxlLnNldFByb3BlcnR5KCctLWRuLWZvbnQtc2l6ZScsIHZhbC50b1N0cmluZygpICsgJ3B4Jyk7XG5cdFx0fVxuXHR9XG5cblx0ZG5HZXRFeGNsdWRlZEV4dGVuc2lvbnMoZXhjbHVkZWRfZXh0OiBzdHJpbmcpOiBzdHJpbmdbXSB7XG5cdFx0aWYgKGV4Y2x1ZGVkX2V4dCA9PT0gJycpIHtcblx0XHRcdHJldHVybiBbXTtcblx0XHR9XG5cblx0XHRyZXR1cm4gZXhjbHVkZWRfZXh0LnNwbGl0KCcsJykubWFwKGV4dGVuc2lvbiA9PiBleHRlbnNpb24udHJpbSgpKTtcblx0fVxuXG5cdG9udW5sb2FkKCkge1xuXG5cdH1cblxuXHRhc3luYyBsb2FkU2V0dGluZ3MoKSB7XG5cdFx0dGhpcy5zZXR0aW5ncyA9IE9iamVjdC5hc3NpZ24oXG5cdFx0XHR7fSxcblx0XHRcdERFRkFVTFRfU0VUVElOR1MsXG5cdFx0XHRhd2FpdCB0aGlzLmxvYWREYXRhKCkpO1xuXHR9XG5cblx0YXN5bmMgc2F2ZVNldHRpbmdzKCkge1xuXHRcdGF3YWl0IHRoaXMuc2F2ZURhdGEodGhpcy5zZXR0aW5ncyk7XG5cdH1cbn1cblxuXG5cbiIsICJpbXBvcnQgeyBBcHAsIENvbG9yQ29tcG9uZW50LCBEcm9wZG93bkNvbXBvbmVudCwgUGx1Z2luU2V0dGluZ1RhYiwgU2V0dGluZywgU2xpZGVyQ29tcG9uZW50LCBUZXh0Q29tcG9uZW50LCBUb2dnbGVDb21wb25lbnQgfSBmcm9tICdvYnNpZGlhbic7XG5pbXBvcnQgRE5QbHVnaW4gZnJvbSAnLi9tYWluJztcbmltcG9ydCB7IERFRkFVTFRfU0VUVElOR1MgfSBmcm9tICcuL21haW4nO1xuXG5leHBvcnQgY2xhc3MgRE5TZXR0aW5nVGFiIGV4dGVuZHMgUGx1Z2luU2V0dGluZ1RhYiB7XG5cbiAgICBwbHVnaW46IEROUGx1Z2luO1xuICAgIGRyb3Bkb3duRGF0ZUZvcm1hdDogRHJvcGRvd25Db21wb25lbnQ7XG4gICAgZHJvcGRvd25GaWxlc1BlclBhZ2U6IERyb3Bkb3duQ29tcG9uZW50O1xuICAgIGRyb3Bkb3duRGVmYXVsdFZpZXc6IERyb3Bkb3duQ29tcG9uZW50O1xuICAgIGRyb3Bkb3duVGFibGVMYXlvdXQ6IERyb3Bkb3duQ29tcG9uZW50O1xuICAgIGRyb3Bkb3duUmVjZW50RmlsZXM6IERyb3Bkb3duQ29tcG9uZW50O1xuICAgIHNsaWRlckZvbnRTaXplOiBTbGlkZXJDb21wb25lbnQ7XG4gICAgdGV4dEV4Y2x1ZGVkRXh0ZW5zaW9uczogVGV4dENvbXBvbmVudDtcbiAgICB0ZXh0RXhjbHVkZWRGb2xkZXJzOiBUZXh0Q29tcG9uZW50O1xuICAgIGNvbG9yQ29tcE5vdGVzOiBDb2xvckNvbXBvbmVudDtcbiAgICBjb2xvckNvbXBDYW52YXM6IENvbG9yQ29tcG9uZW50O1xuICAgIGNvbG9yQ29tcEltYWdlczogQ29sb3JDb21wb25lbnQ7XG4gICAgY29sb3JDb21wVmlkZW9zOiBDb2xvckNvbXBvbmVudDtcbiAgICBjb2xvckNvbXBBdWRpb3M6IENvbG9yQ29tcG9uZW50O1xuICAgIGNvbG9yQ29tcFBkZjogQ29sb3JDb21wb25lbnQ7XG4gICAgY29sb3JDb21wT3RoZXI6IENvbG9yQ29tcG9uZW50O1xuICAgIHRvZ2dsZUNvbG9yZWRGaWxlczogVG9nZ2xlQ29tcG9uZW50O1xuXG4gICAgY29uc3RydWN0b3IoYXBwOiBBcHAsIHBsdWdpbjogRE5QbHVnaW4pIHtcbiAgICAgICAgc3VwZXIoYXBwLCBwbHVnaW4pO1xuICAgICAgICB0aGlzLnBsdWdpbiA9IHBsdWdpbjtcbiAgICB9XG5cbiAgICBkaXNwbGF5KCk6IHZvaWQge1xuICAgICAgICBjb25zdCB7IGNvbnRhaW5lckVsIH0gPSB0aGlzO1xuXG4gICAgICAgIGNvbnRhaW5lckVsLmVtcHR5KCk7XG5cbiAgICAgICAgbmV3IFNldHRpbmcoY29udGFpbmVyRWwpXG4gICAgICAgICAgICAuc2V0TmFtZSgnT3BlbiBkYXNoYm9hcmQgbmF2aWdhdG9yJylcbiAgICAgICAgICAgIC5hZGRCdXR0b24oKGJ0bikgPT4ge1xuICAgICAgICAgICAgICAgIGJ0bi5zZXRCdXR0b25UZXh0KCdPcGVuJylcbiAgICAgICAgICAgICAgICAgICAgLnNldFRvb2x0aXAoJ09wZW4gZGFzaGJvYXJkIG5hdmlnYXRvcicpXG4gICAgICAgICAgICAgICAgICAgIC5vbkNsaWNrKChldnQ6IE1vdXNlRXZlbnQpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLl9ETl9NT0RBTC5vcGVuKCk7XG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAvLyBEZWZhdWx0IEROIHZpZXc6IERhc2hib2FyZCBvciBOYXZpZ2F0b3JcbiAgICAgICAgbmV3IFNldHRpbmcoY29udGFpbmVyRWwpXG4gICAgICAgICAgICAuc2V0TmFtZSgnRGVmYXVsdCB2aWV3JylcbiAgICAgICAgICAgIC5zZXREZXNjKCdTZWxlY3QgdmlldyB3aGVuIG9wZW5pbmcgd2luZG93JylcbiAgICAgICAgICAgIC5hZGREcm9wZG93bihzZWwgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuZHJvcGRvd25EZWZhdWx0VmlldyA9IHNlbDtcbiAgICAgICAgICAgICAgICBzZWwuYWRkT3B0aW9uKCcxJywgJ0Rhc2hib2FyZCcpO1xuICAgICAgICAgICAgICAgIHNlbC5hZGRPcHRpb24oJzInLCAnTmF2aWdhdG9yJyk7XG4gICAgICAgICAgICAgICAgc2VsLm9uQ2hhbmdlKGFzeW5jICh2YWw6IHN0cmluZykgPT4ge1xuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLnNldHRpbmdzLmRlZmF1bHRfdmlldyA9IHBhcnNlSW50KHZhbCk7XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uX0ROX01PREFMLmRlZmF1bHRfdmlldyA9IHRoaXMucGx1Z2luLnNldHRpbmdzLmRlZmF1bHRfdmlldztcblxuICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICAgICAgc2VsLnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLmRlZmF1bHRfdmlldy50b1N0cmluZygpKTtcbiAgICAgICAgICAgIH0pLmFkZEV4dHJhQnV0dG9uKChidG4pID0+IHtcbiAgICAgICAgICAgICAgICBidG4uc2V0SWNvbigncm90YXRlLWNjdycpO1xuICAgICAgICAgICAgICAgIGJ0bi5zZXRUb29sdGlwKCdSZXN0b3JlIGRlZmF1bHQnKVxuICAgICAgICAgICAgICAgIGJ0bi5vbkNsaWNrKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kcm9wZG93bkRlZmF1bHRWaWV3LnNldFZhbHVlKERFRkFVTFRfU0VUVElOR1MuZGVmYXVsdF92aWV3LnRvU3RyaW5nKCkpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnBsdWdpbi5zZXR0aW5ncy5kZWZhdWx0X3ZpZXcgPSBERUZBVUxUX1NFVFRJTkdTLmRlZmF1bHRfdmlldztcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uX0ROX01PREFMLmRlZmF1bHRfdmlldyA9IHRoaXMucGx1Z2luLnNldHRpbmdzLmRlZmF1bHRfdmlldztcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAvLyBUYWJsZSBsYXlvdXRcbiAgICAgICAgbmV3IFNldHRpbmcoY29udGFpbmVyRWwpXG4gICAgICAgICAgICAuc2V0TmFtZSgnTmF2aWdhdG9yIHRhYmxlIGxheW91dCcpXG4gICAgICAgICAgICAuc2V0RGVzYygnU2VsZWN0IHRhYmxlIHJlc3VsdHMgbGF5b3V0JylcbiAgICAgICAgICAgIC5hZGREcm9wZG93bihzZWwgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuZHJvcGRvd25UYWJsZUxheW91dCA9IHNlbDtcbiAgICAgICAgICAgICAgICBzZWwuYWRkT3B0aW9uKCdkbi10YmwtZGVmYXVsdCcsICdEZWZhdWx0Jyk7XG4gICAgICAgICAgICAgICAgc2VsLmFkZE9wdGlvbignZG4tdGJsLXJvdycsICdSb3cgc3RyaXBlZCcpO1xuICAgICAgICAgICAgICAgIHNlbC5hZGRPcHRpb24oJ2RuLXRibC1jb2x1bW4nLCAnQ29sdW1uIHN0cmlwZWQnKTtcbiAgICAgICAgICAgICAgICBzZWwuYWRkT3B0aW9uKCdkbi10YmwtYm9yZGVyZWQnLCAnQm9yZGVyZWQnKTtcbiAgICAgICAgICAgICAgICBzZWwub25DaGFuZ2UoYXN5bmMgKHZhbDogc3RyaW5nKSA9PiB7XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uc2V0dGluZ3Muc2VsZWN0ZWRfdGFibGVfbGF5b3V0ID0gdmFsO1xuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLl9ETl9NT0RBTC5zZWxlY3RlZF90YWJsZV9sYXlvdXQgPSB0aGlzLnBsdWdpbi5zZXR0aW5ncy5zZWxlY3RlZF90YWJsZV9sYXlvdXQ7XG5cbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XG4gICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgICAgIHNlbC5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy5zZWxlY3RlZF90YWJsZV9sYXlvdXQudG9TdHJpbmcoKSk7XG4gICAgICAgICAgICB9KS5hZGRFeHRyYUJ1dHRvbigoYnRuKSA9PiB7XG4gICAgICAgICAgICAgICAgYnRuLnNldEljb24oJ3JvdGF0ZS1jY3cnKTtcbiAgICAgICAgICAgICAgICBidG4uc2V0VG9vbHRpcCgnUmVzdG9yZSBkZWZhdWx0JylcbiAgICAgICAgICAgICAgICBidG4ub25DbGljaygoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZHJvcGRvd25UYWJsZUxheW91dC5zZXRWYWx1ZShERUZBVUxUX1NFVFRJTkdTLnNlbGVjdGVkX3RhYmxlX2xheW91dC50b1N0cmluZygpKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uc2V0dGluZ3Muc2VsZWN0ZWRfdGFibGVfbGF5b3V0ID0gREVGQVVMVF9TRVRUSU5HUy5zZWxlY3RlZF90YWJsZV9sYXlvdXQ7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLl9ETl9NT0RBTC5zZWxlY3RlZF90YWJsZV9sYXlvdXQgPSB0aGlzLnBsdWdpbi5zZXR0aW5ncy5zZWxlY3RlZF90YWJsZV9sYXlvdXQ7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gRGF0ZSBmb3JtYXRcbiAgICAgICAgbmV3IFNldHRpbmcoY29udGFpbmVyRWwpXG4gICAgICAgICAgICAuc2V0TmFtZSgnRGF0ZSBmb3JtYXQnKVxuICAgICAgICAgICAgLnNldERlc2MoJ1NlbGVjdCBkYXRlIGZvcm1hdCcpXG4gICAgICAgICAgICAuYWRkRHJvcGRvd24oc2VsID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmRyb3Bkb3duRGF0ZUZvcm1hdCA9IHNlbDtcbiAgICAgICAgICAgICAgICBzZWwuYWRkT3B0aW9uKCdZWVlZLU1NLUREIEhIOm1tOnNzJywgJ1lZWVktTU0tREQgSEg6bW06c3MnKTtcbiAgICAgICAgICAgICAgICBzZWwuYWRkT3B0aW9uKCdZWVlZLU1NLUREIEhIOm1tJywgJ1lZWVktTU0tREQgSEg6bW0nKTtcbiAgICAgICAgICAgICAgICBzZWwuYWRkT3B0aW9uKCdZWVlZLU1NLUREJywgJ1lZWVktTU0tREQnKTtcbiAgICAgICAgICAgICAgICBzZWwuYWRkT3B0aW9uKCdERC9NTS9ZWVlZIEhIOm1tOnNzJywgJ0REL01NL1lZWVkgSEg6bW06c3MnKTtcbiAgICAgICAgICAgICAgICBzZWwuYWRkT3B0aW9uKCdERC9NTS9ZWVlZIEhIOm1tJywgJ0REL01NL1lZWVkgSEg6bW0nKTtcbiAgICAgICAgICAgICAgICBzZWwuYWRkT3B0aW9uKCdERC9NTS9ZWVlZJywgJ0REL01NL1lZWVknKTtcbiAgICAgICAgICAgICAgICBzZWwub25DaGFuZ2UoYXN5bmMgKHZhbDogc3RyaW5nKSA9PiB7XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uc2V0dGluZ3MuZGF0ZV9mb3JtYXQgPSB2YWw7XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uX0ROX01PREFMLmRhdGVfZm9ybWF0ID0gdGhpcy5wbHVnaW4uc2V0dGluZ3MuZGF0ZV9mb3JtYXQ7XG5cbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XG4gICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgICAgIHNlbC5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy5kYXRlX2Zvcm1hdC50b1N0cmluZygpKTtcbiAgICAgICAgICAgIH0pLmFkZEV4dHJhQnV0dG9uKChidG4pID0+IHtcbiAgICAgICAgICAgICAgICBidG4uc2V0SWNvbigncm90YXRlLWNjdycpO1xuICAgICAgICAgICAgICAgIGJ0bi5zZXRUb29sdGlwKCdSZXN0b3JlIGRlZmF1bHQnKVxuICAgICAgICAgICAgICAgIGJ0bi5vbkNsaWNrKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kcm9wZG93bkRhdGVGb3JtYXQuc2V0VmFsdWUoREVGQVVMVF9TRVRUSU5HUy5kYXRlX2Zvcm1hdC50b1N0cmluZygpKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uc2V0dGluZ3MuZGF0ZV9mb3JtYXQgPSBERUZBVUxUX1NFVFRJTkdTLmRhdGVfZm9ybWF0O1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnBsdWdpbi5fRE5fTU9EQUwuZGF0ZV9mb3JtYXQgPSB0aGlzLnBsdWdpbi5zZXR0aW5ncy5kYXRlX2Zvcm1hdDtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAvLyBGb250IHNpemVcbiAgICAgICAgbmV3IFNldHRpbmcoY29udGFpbmVyRWwpXG4gICAgICAgICAgICAuc2V0TmFtZSgnRm9udCBzaXplJylcbiAgICAgICAgICAgIC5zZXREZXNjKCdTZWxlY3QgZm9udCBzaXplIGluIHBpeGVscyBmb3IgcmVzdWx0cyBhbmQgbGlua3MnKVxuICAgICAgICAgICAgLmFkZFNsaWRlcigoc2xpKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5zbGlkZXJGb250U2l6ZSA9IHNsaTtcbiAgICAgICAgICAgICAgICBsZXQgc2xpZGVyX3ZhbDogbnVtYmVyO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnBsdWdpbi5zZXR0aW5ncy5mb250X3NpemUpIHtcbiAgICAgICAgICAgICAgICAgICAgc2xpZGVyX3ZhbCA9IHRoaXMucGx1Z2luLnNldHRpbmdzLmZvbnRfc2l6ZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBzbGlkZXJfdmFsID0gREVGQVVMVF9TRVRUSU5HUy5mb250X3NpemU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHNsaS5zZXREeW5hbWljVG9vbHRpcCgpO1xuICAgICAgICAgICAgICAgIHNsaS5zZXRMaW1pdHMoMTIsIDI0LCAxKTtcbiAgICAgICAgICAgICAgICBzbGkuc2V0VmFsdWUoc2xpZGVyX3ZhbCk7XG4gICAgICAgICAgICAgICAgc2xpLm9uQ2hhbmdlKCh2YWw6IG51bWJlcikgPT4ge1xuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLnNldHRpbmdzLmZvbnRfc2l6ZSA9IHZhbDtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uZG5TZXRGb250U2l6ZSh2YWwpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgfSkuYWRkRXh0cmFCdXR0b24oKGJ0bikgPT4ge1xuICAgICAgICAgICAgICAgIGJ0bi5zZXRJY29uKCdyb3RhdGUtY2N3Jyk7XG4gICAgICAgICAgICAgICAgYnRuLnNldFRvb2x0aXAoJ1Jlc3RvcmUgZGVmYXVsdCcpXG4gICAgICAgICAgICAgICAgYnRuLm9uQ2xpY2soKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNsaWRlckZvbnRTaXplLnNldFZhbHVlKERFRkFVTFRfU0VUVElOR1MuZm9udF9zaXplKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uc2V0dGluZ3MuZm9udF9zaXplID0gREVGQVVMVF9TRVRUSU5HUy5mb250X3NpemU7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLmRuU2V0Rm9udFNpemUodGhpcy5wbHVnaW4uc2V0dGluZ3MuZm9udF9zaXplKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAvLyBSZXN1bHRzL2ZpbGVzIHBlciBwYWdlXG4gICAgICAgIG5ldyBTZXR0aW5nKGNvbnRhaW5lckVsKVxuICAgICAgICAgICAgLnNldE5hbWUoJ0ZpbGVzIHBlciBwYWdlJylcbiAgICAgICAgICAgIC5zZXREZXNjKCdOdW1iZXIgb2YgcmVzdWx0cyBwZXIgcGFnZScpXG4gICAgICAgICAgICAuYWRkRHJvcGRvd24oc2VsID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmRyb3Bkb3duRmlsZXNQZXJQYWdlID0gc2VsO1xuICAgICAgICAgICAgICAgIHNlbC5hZGRPcHRpb24oJzEwJywgJzEwJyk7XG4gICAgICAgICAgICAgICAgc2VsLmFkZE9wdGlvbignMjAnLCAnMjAnKTtcbiAgICAgICAgICAgICAgICBzZWwuYWRkT3B0aW9uKCczMCcsICczMCcpO1xuICAgICAgICAgICAgICAgIHNlbC5hZGRPcHRpb24oJzUwJywgJzUwJyk7XG4gICAgICAgICAgICAgICAgc2VsLmFkZE9wdGlvbignMTAwJywgJzEwMCcpO1xuICAgICAgICAgICAgICAgIHNlbC5vbkNoYW5nZShhc3luYyAodmFsOiBzdHJpbmcpID0+IHtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLnBsdWdpbi5zZXR0aW5ncy5maWxlc19wZXJfcGFnZSA9IHBhcnNlSW50KHZhbCk7XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uX0ROX01PREFMLmZpbGVzX3Blcl9wYWdlID0gdGhpcy5wbHVnaW4uc2V0dGluZ3MuZmlsZXNfcGVyX3BhZ2U7XG5cbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XG4gICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgICAgIHNlbC5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy5maWxlc19wZXJfcGFnZS50b1N0cmluZygpKTtcbiAgICAgICAgICAgIH0pLmFkZEV4dHJhQnV0dG9uKChidG4pID0+IHtcbiAgICAgICAgICAgICAgICBidG4uc2V0SWNvbigncm90YXRlLWNjdycpO1xuICAgICAgICAgICAgICAgIGJ0bi5zZXRUb29sdGlwKCdSZXN0b3JlIGRlZmF1bHQnKVxuICAgICAgICAgICAgICAgIGJ0bi5vbkNsaWNrKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kcm9wZG93bkZpbGVzUGVyUGFnZS5zZXRWYWx1ZShERUZBVUxUX1NFVFRJTkdTLmZpbGVzX3Blcl9wYWdlLnRvU3RyaW5nKCkpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnBsdWdpbi5zZXR0aW5ncy5maWxlc19wZXJfcGFnZSA9IERFRkFVTFRfU0VUVElOR1MuZmlsZXNfcGVyX3BhZ2U7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLl9ETl9NT0RBTC5maWxlc19wZXJfcGFnZSA9IHRoaXMucGx1Z2luLnNldHRpbmdzLmZpbGVzX3Blcl9wYWdlO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgIC8vIFJlY2VudCBmaWxlcyBieSB0eXBlXG4gICAgICAgIG5ldyBTZXR0aW5nKGNvbnRhaW5lckVsKVxuICAgICAgICAgICAgLnNldE5hbWUoJ1JlY2VudCBmaWxlcycpXG4gICAgICAgICAgICAuc2V0RGVzYygnTnVtYmVyIG9mIHJlY2VudCBmaWxlcyBwZXIgY2F0ZWdvcnknKVxuICAgICAgICAgICAgLmFkZERyb3Bkb3duKHNlbCA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5kcm9wZG93blJlY2VudEZpbGVzID0gc2VsO1xuICAgICAgICAgICAgICAgIHNlbC5hZGRPcHRpb24oJzMnLCAnMycpO1xuICAgICAgICAgICAgICAgIHNlbC5hZGRPcHRpb24oJzQnLCAnNCcpO1xuICAgICAgICAgICAgICAgIHNlbC5hZGRPcHRpb24oJzUnLCAnNScpO1xuICAgICAgICAgICAgICAgIHNlbC5hZGRPcHRpb24oJzEwJywgJzEwJyk7XG4gICAgICAgICAgICAgICAgc2VsLm9uQ2hhbmdlKGFzeW5jICh2YWw6IHN0cmluZykgPT4ge1xuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLnNldHRpbmdzLm51bV9yZWNlbnRfZmlsZXMgPSBwYXJzZUludCh2YWwpO1xuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLl9ETl9NT0RBTC5udW1fcmVjZW50X2ZpbGVzID0gdGhpcy5wbHVnaW4uc2V0dGluZ3MubnVtX3JlY2VudF9maWxlcztcblxuICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICAgICAgc2VsLnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLm51bV9yZWNlbnRfZmlsZXMudG9TdHJpbmcoKSk7XG4gICAgICAgICAgICB9KS5hZGRFeHRyYUJ1dHRvbigoYnRuKSA9PiB7XG4gICAgICAgICAgICAgICAgYnRuLnNldEljb24oJ3JvdGF0ZS1jY3cnKTtcbiAgICAgICAgICAgICAgICBidG4uc2V0VG9vbHRpcCgnUmVzdG9yZSBkZWZhdWx0JylcbiAgICAgICAgICAgICAgICBidG4ub25DbGljaygoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZHJvcGRvd25SZWNlbnRGaWxlcy5zZXRWYWx1ZShERUZBVUxUX1NFVFRJTkdTLm51bV9yZWNlbnRfZmlsZXMudG9TdHJpbmcoKSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLnNldHRpbmdzLm51bV9yZWNlbnRfZmlsZXMgPSBERUZBVUxUX1NFVFRJTkdTLm51bV9yZWNlbnRfZmlsZXM7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLl9ETl9NT0RBTC5udW1fcmVjZW50X2ZpbGVzID0gdGhpcy5wbHVnaW4uc2V0dGluZ3MubnVtX3JlY2VudF9maWxlcztcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAvLyBFeGNsdWRlZCBmaWxlIGV4dGVuc2lvbnNcbiAgICAgICAgbmV3IFNldHRpbmcoY29udGFpbmVyRWwpXG4gICAgICAgICAgICAuc2V0TmFtZSgnRXhjbHVkZWQgZmlsZSBleHRlbnNpb25zJylcbiAgICAgICAgICAgIC5zZXREZXNjKCdGaWxlIGV4dGVuc2lvbnMgdG8gZXhjbHVkZSwgc2VwYXJhdGVkIGJ5IGNvbW1hcycpXG4gICAgICAgICAgICAuYWRkVGV4dCgodGV4dCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMudGV4dEV4Y2x1ZGVkRXh0ZW5zaW9ucyA9IHRleHQ7XG4gICAgICAgICAgICAgICAgdGV4dFxuICAgICAgICAgICAgICAgICAgICAuc2V0UGxhY2Vob2xkZXIoXCJGaWxlIGV4dGVuc2lvbnMgdG8gZXhjbHVkZVwiKVxuICAgICAgICAgICAgICAgICAgICAuc2V0VmFsdWUodGhpcy5wbHVnaW4uc2V0dGluZ3MuZXhjbHVkZWRfZXh0KVxuICAgICAgICAgICAgICAgICAgICAub25DaGFuZ2UoYXN5bmMgKHZhbCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uc2V0dGluZ3MuZXhjbHVkZWRfZXh0ID0gdmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uX0ROX01PREFMLmV4Y2x1ZGVkX2V4dGVuc2lvbnMgPSB0aGlzLnBsdWdpbi5kbkdldEV4Y2x1ZGVkRXh0ZW5zaW9ucyh2YWwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB9KS5hZGRFeHRyYUJ1dHRvbigoYnRuKSA9PiB7XG4gICAgICAgICAgICAgICAgYnRuLnNldEljb24oJ3JvdGF0ZS1jY3cnKTtcbiAgICAgICAgICAgICAgICBidG4uc2V0VG9vbHRpcCgnUmVzdG9yZSBkZWZhdWx0JylcbiAgICAgICAgICAgICAgICBidG4ub25DbGljaygoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudGV4dEV4Y2x1ZGVkRXh0ZW5zaW9ucy5zZXRWYWx1ZSgnJyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLnNldHRpbmdzLmV4Y2x1ZGVkX2V4dCA9ICcnO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnBsdWdpbi5fRE5fTU9EQUwuZXhjbHVkZWRfZXh0ZW5zaW9ucyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgIC8vIEV4Y2x1ZGVkIGZvbGRlcnNcbiAgICAgICAgbmV3IFNldHRpbmcoY29udGFpbmVyRWwpXG4gICAgICAgICAgICAuc2V0TmFtZSgnRXhjbHVkZWQgZm9sZGVycycpXG4gICAgICAgICAgICAuc2V0RGVzYygnTGlzdCBvZiBmb2xkZXIgcGF0aHMgdG8gZXhjbHVkZSwgc2VwYXJhdGVkIGJ5IGNvbW1hcycpXG4gICAgICAgICAgICAuYWRkVGV4dCgodGV4dCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMudGV4dEV4Y2x1ZGVkRm9sZGVycyA9IHRleHQ7XG4gICAgICAgICAgICAgICAgdGV4dFxuICAgICAgICAgICAgICAgICAgICAuc2V0UGxhY2Vob2xkZXIoXCJGb2xkZXIgcGF0aHMgdG8gZXhjbHVkZVwiKVxuICAgICAgICAgICAgICAgICAgICAuc2V0VmFsdWUodGhpcy5wbHVnaW4uc2V0dGluZ3MuZXhjbHVkZWRfcGF0aClcbiAgICAgICAgICAgICAgICAgICAgLm9uQ2hhbmdlKGFzeW5jICh2YWwpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLnNldHRpbmdzLmV4Y2x1ZGVkX3BhdGggPSB2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBsdWdpbi5fRE5fTU9EQUwuZXhjbHVkZWRfZm9sZGVycyA9IHRoaXMucGx1Z2luLmRuR2V0RXhjbHVkZWRGb2xkZXJzKHZhbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIH0pLmFkZEV4dHJhQnV0dG9uKChidG4pID0+IHtcbiAgICAgICAgICAgICAgICBidG4uc2V0SWNvbigncm90YXRlLWNjdycpO1xuICAgICAgICAgICAgICAgIGJ0bi5zZXRUb29sdGlwKCdSZXN0b3JlIGRlZmF1bHQnKVxuICAgICAgICAgICAgICAgIGJ0bi5vbkNsaWNrKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy50ZXh0RXhjbHVkZWRGb2xkZXJzLnNldFZhbHVlKCcnKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uc2V0dGluZ3MuZXhjbHVkZWRfcGF0aCA9ICcnO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnBsdWdpbi5fRE5fTU9EQUwuZXhjbHVkZWRfZm9sZGVycyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgIC8vIFRvZ2dsZSBjb2xvcmVkIGZpbGVzXG4gICAgICAgIG5ldyBTZXR0aW5nKGNvbnRhaW5lckVsKVxuICAgICAgICAgICAgLnNldE5hbWUoJ1RvZ2dsZSBjb2xvcmVkIGZpbGVzJylcbiAgICAgICAgICAgIC5zZXREZXNjKCdUdXJuIG9uL29mZiBjb2xvcmVkIGZpbGVzJylcbiAgICAgICAgICAgIC5hZGRUb2dnbGUoKHRvZ2dsZSkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMudG9nZ2xlQ29sb3JlZEZpbGVzID0gdG9nZ2xlO1xuICAgICAgICAgICAgICAgIHRvZ2dsZVxuICAgICAgICAgICAgICAgICAgICAuc2V0VmFsdWUodGhpcy5wbHVnaW4uc2V0dGluZ3MuY29sb3JlZF9maWxlcylcbiAgICAgICAgICAgICAgICAgICAgLm9uQ2hhbmdlKGFzeW5jICh2YWwpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLnNldHRpbmdzLmNvbG9yZWRfZmlsZXMgPSB2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBsdWdpbi5fRE5fTU9EQUwuY29sb3JlZF9maWxlcyA9IHZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLl9ETl9NT0RBTC5kblRvZ2dsZUNvbG9yZWRGaWxlcygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB9KS5hZGRFeHRyYUJ1dHRvbigoYnRuKSA9PiB7XG4gICAgICAgICAgICAgICAgYnRuLnNldEljb24oJ3JvdGF0ZS1jY3cnKTtcbiAgICAgICAgICAgICAgICBidG4uc2V0VG9vbHRpcCgnUmVzdG9yZSBkZWZhdWx0JylcbiAgICAgICAgICAgICAgICBidG4ub25DbGljaygoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudG9nZ2xlQ29sb3JlZEZpbGVzLnNldFZhbHVlKERFRkFVTFRfU0VUVElOR1MuY29sb3JlZF9maWxlcyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLnNldHRpbmdzLmNvbG9yZWRfZmlsZXMgPSBERUZBVUxUX1NFVFRJTkdTLmNvbG9yZWRfZmlsZXM7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLl9ETl9NT0RBTC5jb2xvcmVkX2ZpbGVzID0gREVGQVVMVF9TRVRUSU5HUy5jb2xvcmVkX2ZpbGVzO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnBsdWdpbi5fRE5fTU9EQUwuZG5Ub2dnbGVDb2xvcmVkRmlsZXMoKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAvLyAxIENvbG9yIC0+IE5vdGVzXG4gICAgICAgIG5ldyBTZXR0aW5nKGNvbnRhaW5lckVsKVxuICAgICAgICAgICAgLnNldE5hbWUoJ0NvbG9yOiBOb3RlcycpXG4gICAgICAgICAgICAuc2V0RGVzYygnQ29sb3Igb2Ygbm90ZXMnKVxuICAgICAgICAgICAgLmFkZENvbG9yUGlja2VyKChjb2xvcikgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuY29sb3JDb21wTm90ZXMgPSBjb2xvcjtcbiAgICAgICAgICAgICAgICBjb2xvclxuICAgICAgICAgICAgICAgICAgICAuc2V0VmFsdWUodGhpcy5wbHVnaW4uc2V0dGluZ3MuY29sb3Jfbm90ZXMpXG4gICAgICAgICAgICAgICAgICAgIC5vbkNoYW5nZShhc3luYyAodmFsKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBsdWdpbi5zZXR0aW5ncy5jb2xvcl9ub3RlcyA9IHZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLl9ETl9NT0RBTC5jb2xvcl9ub3RlcyA9IHZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLl9ETl9NT0RBTC5kblNldEN1c3RvbUNvbG9ycygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB9KS5hZGRFeHRyYUJ1dHRvbigoYnRuKSA9PiB7XG4gICAgICAgICAgICAgICAgYnRuLnNldEljb24oJ3JvdGF0ZS1jY3cnKTtcbiAgICAgICAgICAgICAgICBidG4uc2V0VG9vbHRpcCgnUmVzdG9yZSBkZWZhdWx0JylcbiAgICAgICAgICAgICAgICBidG4ub25DbGljaygoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29sb3JDb21wTm90ZXMuc2V0VmFsdWUoREVGQVVMVF9TRVRUSU5HUy5jb2xvcl9ub3Rlcyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLnNldHRpbmdzLmNvbG9yX25vdGVzID0gREVGQVVMVF9TRVRUSU5HUy5jb2xvcl9ub3RlcztcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uX0ROX01PREFMLmNvbG9yX25vdGVzID0gREVGQVVMVF9TRVRUSU5HUy5jb2xvcl9ub3RlcztcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uX0ROX01PREFMLmRuU2V0Q3VzdG9tQ29sb3JzKCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gMiBDb2xvciAtPiBDYW52YXNcbiAgICAgICAgbmV3IFNldHRpbmcoY29udGFpbmVyRWwpXG4gICAgICAgICAgICAuc2V0TmFtZSgnQ29sb3I6IENhbnZhcycpXG4gICAgICAgICAgICAuc2V0RGVzYygnQ29sb3Igb2YgY2FudmFzJylcbiAgICAgICAgICAgIC5hZGRDb2xvclBpY2tlcigoY29sb3IpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbG9yQ29tcENhbnZhcyA9IGNvbG9yO1xuICAgICAgICAgICAgICAgIGNvbG9yXG4gICAgICAgICAgICAgICAgICAgIC5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy5jb2xvcl9jYW52YXMpXG4gICAgICAgICAgICAgICAgICAgIC5vbkNoYW5nZShhc3luYyAodmFsKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBsdWdpbi5zZXR0aW5ncy5jb2xvcl9jYW52YXMgPSB2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBsdWdpbi5fRE5fTU9EQUwuY29sb3JfY2FudmFzID0gdmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uX0ROX01PREFMLmRuU2V0Q3VzdG9tQ29sb3JzKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xuICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgfSkuYWRkRXh0cmFCdXR0b24oKGJ0bikgPT4ge1xuICAgICAgICAgICAgICAgIGJ0bi5zZXRJY29uKCdyb3RhdGUtY2N3Jyk7XG4gICAgICAgICAgICAgICAgYnRuLnNldFRvb2x0aXAoJ1Jlc3RvcmUgZGVmYXVsdCcpXG4gICAgICAgICAgICAgICAgYnRuLm9uQ2xpY2soKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbG9yQ29tcENhbnZhcy5zZXRWYWx1ZShERUZBVUxUX1NFVFRJTkdTLmNvbG9yX2NhbnZhcyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLnNldHRpbmdzLmNvbG9yX2NhbnZhcyA9IERFRkFVTFRfU0VUVElOR1MuY29sb3JfY2FudmFzO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnBsdWdpbi5fRE5fTU9EQUwuY29sb3JfY2FudmFzID0gREVGQVVMVF9TRVRUSU5HUy5jb2xvcl9jYW52YXM7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLl9ETl9NT0RBTC5kblNldEN1c3RvbUNvbG9ycygpO1xuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gMyBDb2xvciAtPiBJbWFnZXNcbiAgICAgICAgbmV3IFNldHRpbmcoY29udGFpbmVyRWwpXG4gICAgICAgICAgICAuc2V0TmFtZSgnQ29sb3I6IEltYWdlcycpXG4gICAgICAgICAgICAuc2V0RGVzYygnQ29sb3Igb2YgaW1hZ2VzJylcbiAgICAgICAgICAgIC5hZGRDb2xvclBpY2tlcigoY29sb3IpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbG9yQ29tcEltYWdlcyA9IGNvbG9yO1xuICAgICAgICAgICAgICAgIGNvbG9yXG4gICAgICAgICAgICAgICAgICAgIC5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy5jb2xvcl9pbWFnZXMpXG4gICAgICAgICAgICAgICAgICAgIC5vbkNoYW5nZShhc3luYyAodmFsKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBsdWdpbi5zZXR0aW5ncy5jb2xvcl9pbWFnZXMgPSB2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBsdWdpbi5fRE5fTU9EQUwuY29sb3JfaW1hZ2VzID0gdmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uX0ROX01PREFMLmRuU2V0Q3VzdG9tQ29sb3JzKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xuICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgfSkuYWRkRXh0cmFCdXR0b24oKGJ0bikgPT4ge1xuICAgICAgICAgICAgICAgIGJ0bi5zZXRJY29uKCdyb3RhdGUtY2N3Jyk7XG4gICAgICAgICAgICAgICAgYnRuLnNldFRvb2x0aXAoJ1Jlc3RvcmUgZGVmYXVsdCcpXG4gICAgICAgICAgICAgICAgYnRuLm9uQ2xpY2soKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbG9yQ29tcEltYWdlcy5zZXRWYWx1ZShERUZBVUxUX1NFVFRJTkdTLmNvbG9yX2ltYWdlcyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLnNldHRpbmdzLmNvbG9yX2ltYWdlcyA9IERFRkFVTFRfU0VUVElOR1MuY29sb3JfaW1hZ2VzO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnBsdWdpbi5fRE5fTU9EQUwuY29sb3JfaW1hZ2VzID0gREVGQVVMVF9TRVRUSU5HUy5jb2xvcl9pbWFnZXM7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLl9ETl9NT0RBTC5kblNldEN1c3RvbUNvbG9ycygpO1xuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gNCBDb2xvciAtPiBWaWRlb3NcbiAgICAgICAgbmV3IFNldHRpbmcoY29udGFpbmVyRWwpXG4gICAgICAgICAgICAuc2V0TmFtZSgnQ29sb3I6IFZpZGVvcycpXG4gICAgICAgICAgICAuc2V0RGVzYygnQ29sb3Igb2YgdmlkZW9zJylcbiAgICAgICAgICAgIC5hZGRDb2xvclBpY2tlcigoY29sb3IpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbG9yQ29tcFZpZGVvcyA9IGNvbG9yO1xuICAgICAgICAgICAgICAgIGNvbG9yXG4gICAgICAgICAgICAgICAgICAgIC5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy5jb2xvcl92aWRlb3MpXG4gICAgICAgICAgICAgICAgICAgIC5vbkNoYW5nZShhc3luYyAodmFsKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBsdWdpbi5zZXR0aW5ncy5jb2xvcl92aWRlb3MgPSB2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBsdWdpbi5fRE5fTU9EQUwuY29sb3JfdmlkZW9zID0gdmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uX0ROX01PREFMLmRuU2V0Q3VzdG9tQ29sb3JzKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xuICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgfSkuYWRkRXh0cmFCdXR0b24oKGJ0bikgPT4ge1xuICAgICAgICAgICAgICAgIGJ0bi5zZXRJY29uKCdyb3RhdGUtY2N3Jyk7XG4gICAgICAgICAgICAgICAgYnRuLnNldFRvb2x0aXAoJ1Jlc3RvcmUgZGVmYXVsdCcpXG4gICAgICAgICAgICAgICAgYnRuLm9uQ2xpY2soKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbG9yQ29tcFZpZGVvcy5zZXRWYWx1ZShERUZBVUxUX1NFVFRJTkdTLmNvbG9yX3ZpZGVvcyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLnNldHRpbmdzLmNvbG9yX3ZpZGVvcyA9IERFRkFVTFRfU0VUVElOR1MuY29sb3JfdmlkZW9zO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnBsdWdpbi5fRE5fTU9EQUwuY29sb3JfdmlkZW9zID0gREVGQVVMVF9TRVRUSU5HUy5jb2xvcl92aWRlb3M7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLl9ETl9NT0RBTC5kblNldEN1c3RvbUNvbG9ycygpO1xuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gNSBDb2xvciAtPiBBdWRpb3NcbiAgICAgICAgbmV3IFNldHRpbmcoY29udGFpbmVyRWwpXG4gICAgICAgICAgICAuc2V0TmFtZSgnQ29sb3I6IEF1ZGlvcycpXG4gICAgICAgICAgICAuc2V0RGVzYygnQ29sb3Igb2YgYXVkaW9zJylcbiAgICAgICAgICAgIC5hZGRDb2xvclBpY2tlcigoY29sb3IpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbG9yQ29tcEF1ZGlvcyA9IGNvbG9yO1xuICAgICAgICAgICAgICAgIGNvbG9yXG4gICAgICAgICAgICAgICAgICAgIC5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy5jb2xvcl9hdWRpb3MpXG4gICAgICAgICAgICAgICAgICAgIC5vbkNoYW5nZShhc3luYyAodmFsKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBsdWdpbi5zZXR0aW5ncy5jb2xvcl9hdWRpb3MgPSB2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBsdWdpbi5fRE5fTU9EQUwuY29sb3JfYXVkaW9zID0gdmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uX0ROX01PREFMLmRuU2V0Q3VzdG9tQ29sb3JzKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xuICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgfSkuYWRkRXh0cmFCdXR0b24oKGJ0bikgPT4ge1xuICAgICAgICAgICAgICAgIGJ0bi5zZXRJY29uKCdyb3RhdGUtY2N3Jyk7XG4gICAgICAgICAgICAgICAgYnRuLnNldFRvb2x0aXAoJ1Jlc3RvcmUgZGVmYXVsdCcpXG4gICAgICAgICAgICAgICAgYnRuLm9uQ2xpY2soKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbG9yQ29tcEF1ZGlvcy5zZXRWYWx1ZShERUZBVUxUX1NFVFRJTkdTLmNvbG9yX2F1ZGlvcyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLnNldHRpbmdzLmNvbG9yX2F1ZGlvcyA9IERFRkFVTFRfU0VUVElOR1MuY29sb3JfYXVkaW9zO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnBsdWdpbi5fRE5fTU9EQUwuY29sb3JfYXVkaW9zID0gREVGQVVMVF9TRVRUSU5HUy5jb2xvcl9hdWRpb3M7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLl9ETl9NT0RBTC5kblNldEN1c3RvbUNvbG9ycygpO1xuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gNiBDb2xvciAtPiBQREZcbiAgICAgICAgbmV3IFNldHRpbmcoY29udGFpbmVyRWwpXG4gICAgICAgICAgICAuc2V0TmFtZSgnQ29sb3I6IFBERicpXG4gICAgICAgICAgICAuc2V0RGVzYygnQ29sb3Igb2YgUERGIGZpbGVzJylcbiAgICAgICAgICAgIC5hZGRDb2xvclBpY2tlcigoY29sb3IpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbG9yQ29tcFBkZiA9IGNvbG9yO1xuICAgICAgICAgICAgICAgIGNvbG9yXG4gICAgICAgICAgICAgICAgICAgIC5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy5jb2xvcl9wZGYpXG4gICAgICAgICAgICAgICAgICAgIC5vbkNoYW5nZShhc3luYyAodmFsKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBsdWdpbi5zZXR0aW5ncy5jb2xvcl9wZGYgPSB2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBsdWdpbi5fRE5fTU9EQUwuY29sb3JfcGRmID0gdmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uX0ROX01PREFMLmRuU2V0Q3VzdG9tQ29sb3JzKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xuICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgfSkuYWRkRXh0cmFCdXR0b24oKGJ0bikgPT4ge1xuICAgICAgICAgICAgICAgIGJ0bi5zZXRJY29uKCdyb3RhdGUtY2N3Jyk7XG4gICAgICAgICAgICAgICAgYnRuLnNldFRvb2x0aXAoJ1Jlc3RvcmUgZGVmYXVsdCcpXG4gICAgICAgICAgICAgICAgYnRuLm9uQ2xpY2soKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbG9yQ29tcFBkZi5zZXRWYWx1ZShERUZBVUxUX1NFVFRJTkdTLmNvbG9yX3BkZik7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLnNldHRpbmdzLmNvbG9yX3BkZiA9IERFRkFVTFRfU0VUVElOR1MuY29sb3JfcGRmO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnBsdWdpbi5fRE5fTU9EQUwuY29sb3JfcGRmID0gREVGQVVMVF9TRVRUSU5HUy5jb2xvcl9wZGY7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLl9ETl9NT0RBTC5kblNldEN1c3RvbUNvbG9ycygpO1xuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gNyBDb2xvciAtPiBPdGhlciBmaWxlc1xuICAgICAgICBuZXcgU2V0dGluZyhjb250YWluZXJFbClcbiAgICAgICAgICAgIC5zZXROYW1lKCdDb2xvcjogT3RoZXIgZmlsZXMnKVxuICAgICAgICAgICAgLnNldERlc2MoJ0NvbG9yIG9mIG90aGVyIGZpbGVzJylcbiAgICAgICAgICAgIC5hZGRDb2xvclBpY2tlcigoY29sb3IpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbG9yQ29tcE90aGVyID0gY29sb3I7XG4gICAgICAgICAgICAgICAgY29sb3JcbiAgICAgICAgICAgICAgICAgICAgLnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLmNvbG9yX290aGVyKVxuICAgICAgICAgICAgICAgICAgICAub25DaGFuZ2UoYXN5bmMgKHZhbCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uc2V0dGluZ3MuY29sb3Jfb3RoZXIgPSB2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBsdWdpbi5fRE5fTU9EQUwuY29sb3Jfb3RoZXIgPSB2YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBsdWdpbi5fRE5fTU9EQUwuZG5TZXRDdXN0b21Db2xvcnMoKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB9KS5hZGRFeHRyYUJ1dHRvbigoYnRuKSA9PiB7XG4gICAgICAgICAgICAgICAgYnRuLnNldEljb24oJ3JvdGF0ZS1jY3cnKTtcbiAgICAgICAgICAgICAgICBidG4uc2V0VG9vbHRpcCgnUmVzdG9yZSBkZWZhdWx0JylcbiAgICAgICAgICAgICAgICBidG4ub25DbGljaygoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29sb3JDb21wT3RoZXIuc2V0VmFsdWUoREVGQVVMVF9TRVRUSU5HUy5jb2xvcl9vdGhlcik7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLnNldHRpbmdzLmNvbG9yX290aGVyID0gREVGQVVMVF9TRVRUSU5HUy5jb2xvcl9vdGhlcjtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uX0ROX01PREFMLmNvbG9yX290aGVyID0gREVGQVVMVF9TRVRUSU5HUy5jb2xvcl9vdGhlcjtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uX0ROX01PREFMLmRuU2V0Q3VzdG9tQ29sb3JzKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcblxuICAgIH1cbn1cbiIsICJpbXBvcnQgeyBBcHAsIGRlYm91bmNlLCBNZW51LCBNb2RhbCwgVEFic3RyYWN0RmlsZSwgVEZpbGUsIFRGb2xkZXIsIFdvcmtzcGFjZUxlYWYgfSBmcm9tICdvYnNpZGlhbic7XG5pbXBvcnQgeyBmb3JtYXRGaWxlU2l6ZSwgZ2V0Rm9sZGVyU3RydWN0dXJlIH0gZnJvbSAnLi91dGlscy9mb3JtYXQnO1xuaW1wb3J0IHsgRE5QaWVDaGFydCB9IGZyb20gJy4vdXRpbHMvcGllY2hhcnQnO1xuaW1wb3J0IHsgbW9tZW50IH0gZnJvbSAnb2JzaWRpYW4nO1xuXG5leHBvcnQgY2xhc3MgRE5Nb2RhbCBleHRlbmRzIE1vZGFsIHtcblx0cHJpdmF0ZSBfZmlsZXM6IFRGaWxlW107XG5cdHByaXZhdGUgX2ZvbGRlcnM6IFRGb2xkZXJbXTtcblx0cHJpdmF0ZSBfbm90ZXM6IFRGaWxlW107XG5cdHByaXZhdGUgX3JlY2VudDogVEZpbGVbXTtcblx0cHJpdmF0ZSBfaW1hZ2VzOiBURmlsZVtdO1xuXHRwcml2YXRlIF9jYW52YXM6IFRGaWxlW107XG5cdHByaXZhdGUgX2F1ZGlvczogVEZpbGVbXTtcblx0cHJpdmF0ZSBfdmlkZW9zOiBURmlsZVtdO1xuXHRwcml2YXRlIF9wZGY6IFRGaWxlW107XG5cdHByaXZhdGUgX290aGVyOiBURmlsZVtdO1xuXHRwcml2YXRlIF9CVE5fREFTSEJPQVJEOiBIVE1MQnV0dG9uRWxlbWVudDtcblx0cHJpdmF0ZSBfQlROX05BVklHQVRPUjogSFRNTEJ1dHRvbkVsZW1lbnQ7XG5cdHByaXZhdGUgX1ZJRVdfREFTSEJPQVJEOiBIVE1MRWxlbWVudDtcblx0cHJpdmF0ZSBfVklFV19OQVZJR0FUT1I6IEhUTUxFbGVtZW50O1xuXHRwcml2YXRlIF9JTlBVVF9TRUFSQ0g6IEhUTUxJbnB1dEVsZW1lbnQ7XG5cdHByaXZhdGUgX2RpdlNlYXJjaFJlc3VsdHM6IEhUTUxEaXZFbGVtZW50O1xuXHRwcml2YXRlIF9sZWFmOiBXb3Jrc3BhY2VMZWFmO1xuXHRwcml2YXRlIF9maWx0ZXJlZF9maWxlczogVEZpbGVbXTtcblx0cHJpdmF0ZSBfc29ydF9vcmRlcjogc3RyaW5nID0gJ2Rlc2MnO1xuXHRwcml2YXRlIF9zb3J0X2NvbHVtbjogc3RyaW5nID0gJ21vZGlmaWVkJztcblx0cHJpdmF0ZSBfdGgxOiBIVE1MVGFibGVDZWxsRWxlbWVudDtcblx0cHJpdmF0ZSBfdGgyOiBIVE1MVGFibGVDZWxsRWxlbWVudDtcblx0cHJpdmF0ZSBfdGgzOiBIVE1MVGFibGVDZWxsRWxlbWVudDtcblx0cHJpdmF0ZSBfdGg0OiBIVE1MVGFibGVDZWxsRWxlbWVudDtcblx0cHJpdmF0ZSBfdGg1OiBIVE1MVGFibGVDZWxsRWxlbWVudDtcblx0cHJpdmF0ZSBfdG90YWxfcGFnZXM6IG51bWJlcjtcblxuXHRwcml2YXRlIF9TRUxFQ1RfU09SVDogSFRNTFNlbGVjdEVsZW1lbnQ7XG5cdHByaXZhdGUgX1NFTEVDVF9UQUJMRV9MQVlPVVQ6IEhUTUxTZWxlY3RFbGVtZW50O1xuXG5cdHByaXZhdGUgX3NlbGVjdGVkX2NhdGVnb3J5OiBzdHJpbmcgPSAnJztcblx0cHJpdmF0ZSBfVEFCTEVfTEFZT1VUUzogc3RyaW5nW10gPSBbJ2RuLXRibC1kZWZhdWx0JywgJ2RuLXRibC1yb3cnLCAnZG4tdGJsLWNvbHVtbicsICdkbi10YmwtYm9yZGVyZWQnXTtcblx0c2VsZWN0ZWRfdGFibGVfbGF5b3V0OiBzdHJpbmcgPSAnZG4tdGJsLWRlZmF1bHQnO1xuXHRzZWxlY3RlZF9zb3J0X3ZhbHVlOiBzdHJpbmcgPSAnbW9kaWZpZWQtZGVzYyc7XG5cblx0bnVtX3JlY2VudF9maWxlczogbnVtYmVyID0gNTtcblx0ZmlsZXNfcGVyX3BhZ2U6IG51bWJlciA9IDIwO1xuXHRkYXRlX2Zvcm1hdDogc3RyaW5nID0gJ1lZWVktTU0tREQgSEg6bW0nO1xuXHRkZWZhdWx0X3ZpZXc6IG51bWJlciA9IDE7XG5cdGV4Y2x1ZGVkX2V4dGVuc2lvbnM6IHN0cmluZ1tdID0gW107XG5cdGV4Y2x1ZGVkX2ZvbGRlcnM6IHN0cmluZ1tdID0gW107XG5cdC8vIEZpbGUgY29sb3JzXG5cdGNvbG9yX25vdGVzOiBzdHJpbmcgPSAnI2JmNDhmZic7XG5cdGNvbG9yX2ltYWdlczogc3RyaW5nID0gJyMwMDdmZmYnO1xuXHRjb2xvcl9jYW52YXM6IHN0cmluZyA9ICcjZmY3ZjI4Jztcblx0Y29sb3JfdmlkZW9zOiBzdHJpbmcgPSAnI2QzNDg0OCc7XG5cdGNvbG9yX2F1ZGlvczogc3RyaW5nID0gJyNiZmJmMDAnO1xuXHRjb2xvcl9wZGY6IHN0cmluZyA9ICcjMDBhMzAwJztcblx0Y29sb3Jfb3RoZXI6IHN0cmluZyA9ICcjODI4MjgyJztcblx0Y29sb3JlZF9maWxlczogYm9vbGVhbiA9IGZhbHNlO1xuXG5cdGxhYmVsTGF5b3V0OiBIVE1MU3BhbkVsZW1lbnQ7XG5cdGxhYmVsU29ydDogSFRNTFNwYW5FbGVtZW50O1xuXHRwcml2YXRlIHJlYWRvbmx5IGludGVyc2VjdGlvbk9ic2VydmVyOiBJbnRlcnNlY3Rpb25PYnNlcnZlcjtcblx0cHJpdmF0ZSBfRE5fQ1RYX01FTlU6IE1lbnU7XG5cblx0Y29uc3RydWN0b3IoYXBwOiBBcHApIHtcblx0XHRzdXBlcihhcHApO1xuXHRcdHRoaXMuaW50ZXJzZWN0aW9uT2JzZXJ2ZXIgPSBuZXcgSW50ZXJzZWN0aW9uT2JzZXJ2ZXIodGhpcy5kbkhhbmRsZUludGVyc2VjdGlvbik7XG5cdH1cblxuXHRhc3luYyBvbk9wZW4oKSB7XG5cblx0XHRjb25zdCB7IGNvbnRlbnRFbCB9ID0gdGhpcztcblxuXHRcdHRoaXMuX2ZpbGVzID0gW107XG5cdFx0dGhpcy5fZm9sZGVycyA9IFtdO1xuXHRcdHRoaXMuX25vdGVzID0gW107XG5cdFx0dGhpcy5fcmVjZW50ID0gW107XG5cdFx0dGhpcy5faW1hZ2VzID0gW107XG5cdFx0dGhpcy5fY2FudmFzID0gW107XG5cdFx0dGhpcy5fYXVkaW9zID0gW107XG5cdFx0dGhpcy5fdmlkZW9zID0gW107XG5cdFx0dGhpcy5fcGRmID0gW107XG5cdFx0dGhpcy5fb3RoZXIgPSBbXTtcblxuXHRcdGNvbnN0IGxlYWYgPSB0aGlzLmFwcC53b3Jrc3BhY2U/LmdldE1vc3RSZWNlbnRMZWFmKCk7XG5cdFx0aWYgKGxlYWYgIT09IG51bGwpIHtcblx0XHRcdHRoaXMuX2xlYWYgPSBsZWFmO1xuXHRcdH1cblxuXHRcdGNvbnN0IGRuRmlsZXNBbmRGb2xkZXJzOiBUQWJzdHJhY3RGaWxlW10gPSB0aGlzLmFwcC52YXVsdC5nZXRBbGxMb2FkZWRGaWxlcygpO1xuXHRcdGZvciAoY29uc3QgYWJzRiBvZiBkbkZpbGVzQW5kRm9sZGVycykge1xuXHRcdFx0aWYgKGFic0YgaW5zdGFuY2VvZiBURmlsZSkge1xuXHRcdFx0XHR0aGlzLl9maWxlcy5wdXNoKGFic0YpO1xuXHRcdFx0fSBlbHNlIGlmICgoYWJzRiBpbnN0YW5jZW9mIFRGb2xkZXIpICYmICghYWJzRi5pc1Jvb3QoKSkpIHtcblx0XHRcdFx0dGhpcy5fZm9sZGVycy5wdXNoKGFic0YpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHRoaXMuX2ZpbHRlcmVkX2ZpbGVzID0gdGhpcy5fZmlsZXMuZmlsdGVyKFxuXHRcdFx0KGZpbGUpID0+IHtcblx0XHRcdFx0cmV0dXJuICF0aGlzLmV4Y2x1ZGVkX2V4dGVuc2lvbnMuaW5jbHVkZXMoZmlsZS5leHRlbnNpb24udG9Mb3dlckNhc2UoKSlcblx0XHRcdFx0XHQmJiAhdGhpcy5leGNsdWRlZF9mb2xkZXJzLnNvbWUoZm9sZGVyID0+IGZpbGUucGF0aC5zdGFydHNXaXRoKGZvbGRlcikpO1xuXHRcdFx0fVxuXHRcdCk7XG5cblx0XHR0aGlzLl9maWxlcyA9IHRoaXMuX2ZpbHRlcmVkX2ZpbGVzO1xuXG5cdFx0YXdhaXQgdGhpcy5kbk9yZ2FuaXplRmlsZXMoeyBhcnI6IHRoaXMuX2ZpbHRlcmVkX2ZpbGVzIH0pO1xuXG5cdFx0dGhpcy5fcmVjZW50ID0gYXdhaXQgdGhpcy5kbkdldFJlY2VudEZpbGVzKHRoaXMuX2ZpbHRlcmVkX2ZpbGVzKTtcblxuXHRcdHRoaXMuZG5DcmVhdGVNYWluVUkoY29udGVudEVsKTtcblxuXHRcdHRoaXMuZG5TZXRWaWV3KHRoaXMuZGVmYXVsdF92aWV3KTtcblx0XHR0aGlzLmRuU2V0U2VsZWN0TGF5b3V0VmFsdWUodGhpcy5zZWxlY3RlZF90YWJsZV9sYXlvdXQpO1xuXHRcdHRoaXMuZG5TZXRTZWxlY3RTb3J0VmFsdWUodGhpcy5zZWxlY3RlZF9zb3J0X3ZhbHVlKTtcblxuXHRcdHRoaXMuZG5Ub2dnbGVDb2xvcmVkRmlsZXMoKTtcblx0fVxuXG5cdGRuU2V0Q3VzdG9tQ29sb3JzKCk6IHZvaWQge1xuXHRcdGRvY3VtZW50LmJvZHkuc3R5bGUuc2V0UHJvcGVydHkoJy0tZG4tbm90ZXMtY29sb3InLCB0aGlzLmNvbG9yX25vdGVzKTtcblx0XHRkb2N1bWVudC5ib2R5LnN0eWxlLnNldFByb3BlcnR5KCctLWRuLWltYWdlcy1jb2xvcicsIHRoaXMuY29sb3JfaW1hZ2VzKTtcblx0XHRkb2N1bWVudC5ib2R5LnN0eWxlLnNldFByb3BlcnR5KCctLWRuLWNhbnZhcy1jb2xvcicsIHRoaXMuY29sb3JfY2FudmFzKTtcblx0XHRkb2N1bWVudC5ib2R5LnN0eWxlLnNldFByb3BlcnR5KCctLWRuLXZpZGVvcy1jb2xvcicsIHRoaXMuY29sb3JfdmlkZW9zKTtcblx0XHRkb2N1bWVudC5ib2R5LnN0eWxlLnNldFByb3BlcnR5KCctLWRuLWF1ZGlvcy1jb2xvcicsIHRoaXMuY29sb3JfYXVkaW9zKTtcblx0XHRkb2N1bWVudC5ib2R5LnN0eWxlLnNldFByb3BlcnR5KCctLWRuLXBkZnMtY29sb3InLCB0aGlzLmNvbG9yX3BkZik7XG5cdFx0ZG9jdW1lbnQuYm9keS5zdHlsZS5zZXRQcm9wZXJ0eSgnLS1kbi1vdGhlci1jb2xvcicsIHRoaXMuY29sb3Jfb3RoZXIpO1xuXHR9XG5cblx0ZG5Ub2dnbGVDb2xvcmVkRmlsZXMoKTogdm9pZCB7XG5cdFx0Y29uc3QgZG5NYWluQ29udGFpbmVyID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoXCJkbi1jb250YWluZXJcIik7XG5cdFx0aWYgKHRoaXMuY29sb3JlZF9maWxlcykge1xuXHRcdFx0ZG5NYWluQ29udGFpbmVyPy5jbGFzc0xpc3QuYWRkKCdkbi1jb2xvcmVkLWZpbGVzJyk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGRuTWFpbkNvbnRhaW5lcj8uY2xhc3NMaXN0LnJlbW92ZSgnZG4tY29sb3JlZC1maWxlcycpO1xuXHRcdH1cblx0XHR0aGlzLmRuU2V0Q3VzdG9tQ29sb3JzKCk7XG5cdH1cblxuXHRhc3luYyBkbkNyZWF0ZU1haW5VSShlbDogSFRNTEVsZW1lbnQpIHtcblxuXHRcdGNvbnN0IG1haW5Db250YWluZXIgPSBlbC5jcmVhdGVFbCgnZGl2JywgeyBjbHM6ICdkbi1jb250YWluZXInIH0pO1xuXHRcdG1haW5Db250YWluZXIuc2V0QXR0cmlidXRlKCdpZCcsICdkbi1jb250YWluZXInKTtcblx0XHQvLyBUb3AgTmF2aWdhdGlvblxuXHRcdHRoaXMuZG5DcmVhdGVJbnB1dFNlYXJjaChtYWluQ29udGFpbmVyKTtcblxuXHRcdGNvbnN0IHRvcE5hdiA9IG1haW5Db250YWluZXIuY3JlYXRlRWwoJ2RpdicsIHsgY2xzOiAnZG4tdG9wLW5hdicgfSk7XG5cblx0XHRjb25zdCBsZWZ0VG9wTmF2ID0gdG9wTmF2LmNyZWF0ZUVsKCdkaXYnKTtcblx0XHRjb25zdCByaWdodFRvcE5hdiA9IHRvcE5hdi5jcmVhdGVFbCgnZGl2Jyk7XG5cblx0XHR0aGlzLl9CVE5fREFTSEJPQVJEID0gbGVmdFRvcE5hdi5jcmVhdGVFbCgnYnV0dG9uJywgeyB0ZXh0OiAnRGFzaGJvYXJkJywgY2xzOiAnbW9kLWN0YScgfSk7XG5cdFx0dGhpcy5fQlROX0RBU0hCT0FSRC5vbkNsaWNrRXZlbnQoKGV2dDogTW91c2VFdmVudCkgPT4ge1xuXHRcdFx0dGhpcy5kblNldFZpZXcoMSk7XG5cdFx0fSk7XG5cblx0XHR0aGlzLl9CVE5fTkFWSUdBVE9SID0gbGVmdFRvcE5hdi5jcmVhdGVFbCgnYnV0dG9uJywgeyB0ZXh0OiAnTmF2aWdhdG9yJyB9KTtcblx0XHR0aGlzLl9CVE5fTkFWSUdBVE9SLm9uQ2xpY2tFdmVudCgoZXZ0OiBNb3VzZUV2ZW50KSA9PiB7XG5cdFx0XHR0aGlzLmRuU2VhcmNoVmF1bHQodGhpcy5fSU5QVVRfU0VBUkNILnZhbHVlKTtcblx0XHRcdHRoaXMuZG5TZXRWaWV3KDIpO1xuXHRcdH0pO1xuXG5cdFx0Ly8gU2VsZWN0IHRhYmxlIGxheW91dFxuXG5cdFx0dGhpcy5sYWJlbExheW91dCA9IHJpZ2h0VG9wTmF2LmNyZWF0ZUVsKCdzcGFuJywge1xuXHRcdFx0dGV4dDogJ0xheW91dDonLCBjbHM6ICdkbi10YmwtbGFiZWwnXG5cdFx0fSk7XG5cblx0XHR0aGlzLmxhYmVsTGF5b3V0LnNldEF0dHJpYnV0ZSgnaWQnLCAnZG4tbGFiZWwtbGF5b3V0Jyk7XG5cblx0XHR0aGlzLl9TRUxFQ1RfVEFCTEVfTEFZT1VUID0gcmlnaHRUb3BOYXYuY3JlYXRlRWwoJ3NlbGVjdCcsIHtcblx0XHRcdGNsczogJ2Ryb3Bkb3duIHRibC1zZWxlY3QnXG5cdFx0fSk7XG5cdFx0dGhpcy5fU0VMRUNUX1RBQkxFX0xBWU9VVC5jcmVhdGVFbCgnb3B0aW9uJywgeyB0ZXh0OiAnRGVmYXVsdCcsIHZhbHVlOiAnZG4tdGJsLWRlZmF1bHQnIH0pO1xuXHRcdHRoaXMuX1NFTEVDVF9UQUJMRV9MQVlPVVQuY3JlYXRlRWwoJ29wdGlvbicsIHsgdGV4dDogJ1JvdyBzdHJpcGVkJywgdmFsdWU6ICdkbi10Ymwtcm93JyB9KTtcblx0XHR0aGlzLl9TRUxFQ1RfVEFCTEVfTEFZT1VULmNyZWF0ZUVsKCdvcHRpb24nLCB7IHRleHQ6ICdDb2x1bW4gc3RyaXBlZCcsIHZhbHVlOiAnZG4tdGJsLWNvbHVtbicgfSk7XG5cdFx0dGhpcy5fU0VMRUNUX1RBQkxFX0xBWU9VVC5jcmVhdGVFbCgnb3B0aW9uJywgeyB0ZXh0OiAnQm9yZGVyZWQnLCB2YWx1ZTogJ2RuLXRibC1ib3JkZXJlZCcgfSk7XG5cdFx0dGhpcy5fU0VMRUNUX1RBQkxFX0xBWU9VVC5hZGRFdmVudExpc3RlbmVyKCdjaGFuZ2UnLCAoKSA9PiB7IHRoaXMuZG5TZWxlY3RUYWJsZUxheW91dCgpOyB9KTtcblxuXHRcdC8vIFNlbGVjdCBzb3J0XG5cblx0XHR0aGlzLmxhYmVsU29ydCA9IHJpZ2h0VG9wTmF2LmNyZWF0ZUVsKCdzcGFuJywge1xuXHRcdFx0dGV4dDogJ1NvcnQgYnk6JywgY2xzOiAnZG4tdGJsLWxhYmVsJ1xuXHRcdH0pO1xuXG5cdFx0dGhpcy5sYWJlbFNvcnQuc2V0QXR0cmlidXRlKCdpZCcsICdkbi1sYWJlbC1zb3J0Jyk7XG5cblx0XHR0aGlzLl9TRUxFQ1RfU09SVCA9IHJpZ2h0VG9wTmF2LmNyZWF0ZUVsKCdzZWxlY3QnLCB7XG5cdFx0XHRjbHM6ICdkcm9wZG93bidcblx0XHR9KTtcblx0XHR0aGlzLl9TRUxFQ1RfU09SVC5zZXRBdHRyaWJ1dGUoJ2lkJywgJ2RuLXNlbGVjdC1zb3J0Jyk7XG5cblx0XHR0aGlzLl9TRUxFQ1RfU09SVC5hZGRFdmVudExpc3RlbmVyKCdjaGFuZ2UnLCAoKSA9PiB7IHRoaXMuZG5Tb3J0Q29sdW1uV2l0aFNlbGVjdCgpOyB9KTtcblxuXHRcdGNvbnN0IG9wdGlvbjEgPSB0aGlzLl9TRUxFQ1RfU09SVC5jcmVhdGVFbCgnb3B0aW9uJywgeyB0ZXh0OiAnRmlsZSBuYW1lIChBIHRvIFopJywgdmFsdWU6ICduYW1lLWFzYycgfSk7XG5cdFx0Y29uc3Qgb3B0aW9uMiA9IHRoaXMuX1NFTEVDVF9TT1JULmNyZWF0ZUVsKCdvcHRpb24nLCB7IHRleHQ6ICdGaWxlIG5hbWUgKFogdG8gQSknLCB2YWx1ZTogJ25hbWUtZGVzYycgfSk7XG5cdFx0Y29uc3Qgb3B0aW9uMyA9IHRoaXMuX1NFTEVDVF9TT1JULmNyZWF0ZUVsKCdvcHRpb24nLCB7IHRleHQ6ICdQYXRoIChBIHRvIFopJywgdmFsdWU6ICdwYXRoLWFzYycgfSk7XG5cdFx0Y29uc3Qgb3B0aW9uNCA9IHRoaXMuX1NFTEVDVF9TT1JULmNyZWF0ZUVsKCdvcHRpb24nLCB7IHRleHQ6ICdQYXRoIChaIHRvIEEpJywgdmFsdWU6ICdwYXRoLWRlc2MnIH0pO1xuXHRcdGNvbnN0IG9wdGlvbjUgPSB0aGlzLl9TRUxFQ1RfU09SVC5jcmVhdGVFbCgnb3B0aW9uJywgeyB0ZXh0OiAnRmlsZSBzaXplIChzbWFsbGVzdCB0byBsYXJnZXN0KScsIHZhbHVlOiAnc2l6ZS1hc2MnIH0pO1xuXHRcdGNvbnN0IG9wdGlvbjYgPSB0aGlzLl9TRUxFQ1RfU09SVC5jcmVhdGVFbCgnb3B0aW9uJywgeyB0ZXh0OiAnRmlsZSBzaXplIChsYXJnZXN0IHRvIHNtYWxsZXN0KScsIHZhbHVlOiAnc2l6ZS1kZXNjJyB9KTtcblx0XHRjb25zdCBvcHRpb243ID0gdGhpcy5fU0VMRUNUX1NPUlQuY3JlYXRlRWwoJ29wdGlvbicsIHsgdGV4dDogJ0RhdGUvdGltZSAob2xkZXN0IHRvIG5ld2VzdCknLCB2YWx1ZTogJ21vZGlmaWVkLWFzYycgfSk7XG5cdFx0Y29uc3Qgb3B0aW9uOCA9IHRoaXMuX1NFTEVDVF9TT1JULmNyZWF0ZUVsKCdvcHRpb24nLCB7IHRleHQ6ICdEYXRlL3RpbWUgKG5ld2VzdCB0byBvbGRlc3QpJywgdmFsdWU6ICdtb2RpZmllZC1kZXNjJyB9KTtcblxuXG5cdFx0Ly8gQ29udGFpbmVyc1xuXHRcdHRoaXMuX1ZJRVdfREFTSEJPQVJEID0gbWFpbkNvbnRhaW5lci5jcmVhdGVFbCgnZGl2JywgeyBjbHM6ICdkbi1mbGV4JyB9KTtcblxuXHRcdHRoaXMuX1ZJRVdfTkFWSUdBVE9SID0gbWFpbkNvbnRhaW5lci5jcmVhdGVFbCgnZGl2JywgeyBjbHM6ICdkbi1kaXNwbGF5LW5vbmUnIH0pO1xuXG5cdFx0dGhpcy5fZGl2U2VhcmNoUmVzdWx0cyA9IHRoaXMuX1ZJRVdfTkFWSUdBVE9SLmNyZWF0ZUVsKCdkaXYnLCB7IGNsczogJ2RuLWRpdi10YWJsZScgfSk7XG5cblx0XHR0aGlzLmRuU2hvd1NlYXJjaFJlc3VsdHMoeyBmOiB0aGlzLl9maWx0ZXJlZF9maWxlcywgZWw6IHRoaXMuX2RpdlNlYXJjaFJlc3VsdHMsIGxlYWY6IHRoaXMuX2xlYWYgfSlcblxuXHRcdC8vIFZhdWx0IFN0YXRzIGNvbnRhaW5lclxuXHRcdGNvbnN0IGRpdlZhdWx0U3RhdHMgPSB0aGlzLl9WSUVXX0RBU0hCT0FSRC5jcmVhdGVFbCgnZGl2Jyk7XG5cdFx0ZGl2VmF1bHRTdGF0cy5zZXRBdHRyaWJ1dGUoJ2lkJywgJ2RuLXZhdWx0LXN0YXRzJyk7XG5cblx0XHRjb25zdCBkaXZWYXVsdEdyYXBoID0gdGhpcy5fVklFV19EQVNIQk9BUkQuY3JlYXRlRWwoJ2RpdicpO1xuXHRcdGRpdlZhdWx0R3JhcGguc2V0QXR0cmlidXRlKCdpZCcsICdkbi12YXVsdC1ncmFwaCcpO1xuXG5cdFx0Y29uc3QgZGl2UmVjZW50RmlsZXMgPSB0aGlzLl9WSUVXX0RBU0hCT0FSRC5jcmVhdGVFbCgnZGl2Jyk7XG5cdFx0ZGl2UmVjZW50RmlsZXMuc2V0QXR0cmlidXRlKCdpZCcsICdkbi1yZWNlbnQtZmlsZXMnKTtcblxuXHRcdGNvbnN0IGRpdlJlY2VudE5vdGVzID0gdGhpcy5fVklFV19EQVNIQk9BUkQuY3JlYXRlRWwoJ2RpdicpO1xuXHRcdGRpdlJlY2VudE5vdGVzLnNldEF0dHJpYnV0ZSgnaWQnLCAnZG4tcmVjZW50LW5vdGVzJyk7O1xuXG5cdFx0Y29uc3QgZGl2Q2FudmFzID0gdGhpcy5fVklFV19EQVNIQk9BUkQuY3JlYXRlRWwoJ2RpdicpO1xuXHRcdGRpdkNhbnZhcy5zZXRBdHRyaWJ1dGUoJ2lkJywgJ2RuLWNhbnZhcycpO1xuXG5cdFx0Y29uc3QgZGl2SW1hZ2VzID0gdGhpcy5fVklFV19EQVNIQk9BUkQuY3JlYXRlRWwoJ2RpdicpO1xuXHRcdGRpdkltYWdlcy5zZXRBdHRyaWJ1dGUoJ2lkJywgJ2RuLWltYWdlcycpO1xuXG5cdFx0Y29uc3QgZGl2QXVkaW9zID0gdGhpcy5fVklFV19EQVNIQk9BUkQuY3JlYXRlRWwoJ2RpdicpO1xuXHRcdGRpdkF1ZGlvcy5zZXRBdHRyaWJ1dGUoJ2lkJywgJ2RuLWF1ZGlvcycpO1xuXG5cdFx0Y29uc3QgZGl2VmlkZW9zID0gdGhpcy5fVklFV19EQVNIQk9BUkQuY3JlYXRlRWwoJ2RpdicpO1xuXHRcdGRpdlZpZGVvcy5zZXRBdHRyaWJ1dGUoJ2lkJywgJ2RuLXZpZGVvcycpO1xuXG5cdFx0Y29uc3QgZGl2UERGcyA9IHRoaXMuX1ZJRVdfREFTSEJPQVJELmNyZWF0ZUVsKCdkaXYnKTtcblx0XHRkaXZQREZzLnNldEF0dHJpYnV0ZSgnaWQnLCAnZG4tcGRmcycpO1xuXG5cdFx0Y29uc3QgZGl2T3RoZXIgPSB0aGlzLl9WSUVXX0RBU0hCT0FSRC5jcmVhdGVFbCgnZGl2Jyk7XG5cdFx0ZGl2T3RoZXIuc2V0QXR0cmlidXRlKCdpZCcsICdkbi1vdGhlcicpO1xuXG5cdFx0Ly8gVmF1bHQgU3RhdHNcblxuXHRcdGNvbnN0IGJ0bk5vdGVzID0gYXdhaXQgdGhpcy5kbkNyZWF0ZUJ0bihkaXZWYXVsdFN0YXRzLFxuXHRcdFx0J2RuLWJ0bi1ub3RlcycsXG5cdFx0XHQnTm90ZXMnLFxuXHRcdFx0dGhpcy5fbm90ZXMsXG5cdFx0XHR0aGlzLl9kaXZTZWFyY2hSZXN1bHRzLFxuXHRcdFx0dGhpcy5fbGVhZik7XG5cblxuXHRcdGNvbnN0IGJ0bkNhbnZhcyA9IGF3YWl0IHRoaXMuZG5DcmVhdGVCdG4oZGl2VmF1bHRTdGF0cyxcblx0XHRcdCdkbi1idG4tY2FudmFzJyxcblx0XHRcdCdDYW52YXMnLFxuXHRcdFx0dGhpcy5fY2FudmFzLFxuXHRcdFx0dGhpcy5fZGl2U2VhcmNoUmVzdWx0cyxcblx0XHRcdHRoaXMuX2xlYWYpO1xuXG5cdFx0Y29uc3QgYnRuSW1hZ2VzID0gYXdhaXQgdGhpcy5kbkNyZWF0ZUJ0bihkaXZWYXVsdFN0YXRzLFxuXHRcdFx0J2RuLWJ0bi1pbWFnZXMnLFxuXHRcdFx0J0ltYWdlcycsXG5cdFx0XHR0aGlzLl9pbWFnZXMsXG5cdFx0XHR0aGlzLl9kaXZTZWFyY2hSZXN1bHRzLFxuXHRcdFx0dGhpcy5fbGVhZik7XG5cblx0XHRjb25zdCBidG5BdWRpb3MgPSBhd2FpdCB0aGlzLmRuQ3JlYXRlQnRuKGRpdlZhdWx0U3RhdHMsXG5cdFx0XHQnZG4tYnRuLWF1ZGlvcycsXG5cdFx0XHQnQXVkaW9zJyxcblx0XHRcdHRoaXMuX2F1ZGlvcyxcblx0XHRcdHRoaXMuX2RpdlNlYXJjaFJlc3VsdHMsXG5cdFx0XHR0aGlzLl9sZWFmKTtcblxuXHRcdGNvbnN0IGJ0blZpZGVvcyA9IGF3YWl0IHRoaXMuZG5DcmVhdGVCdG4oZGl2VmF1bHRTdGF0cyxcblx0XHRcdCdkbi1idG4tdmlkZW9zJyxcblx0XHRcdCdWaWRlb3MnLFxuXHRcdFx0dGhpcy5fdmlkZW9zLFxuXHRcdFx0dGhpcy5fZGl2U2VhcmNoUmVzdWx0cyxcblx0XHRcdHRoaXMuX2xlYWYpO1xuXG5cdFx0Y29uc3QgYnRuUERGID0gYXdhaXQgdGhpcy5kbkNyZWF0ZUJ0bihkaXZWYXVsdFN0YXRzLFxuXHRcdFx0J2RuLWJ0bi1wZGYnLFxuXHRcdFx0J1BERicsXG5cdFx0XHR0aGlzLl9wZGYsXG5cdFx0XHR0aGlzLl9kaXZTZWFyY2hSZXN1bHRzLFxuXHRcdFx0dGhpcy5fbGVhZik7XG5cblx0XHRjb25zdCBidG5PdGhlciA9IGF3YWl0IHRoaXMuZG5DcmVhdGVCdG4oZGl2VmF1bHRTdGF0cyxcblx0XHRcdCdkbi1idG4tb3RoZXInLFxuXHRcdFx0J090aGVyJyxcblx0XHRcdHRoaXMuX290aGVyLFxuXHRcdFx0dGhpcy5fZGl2U2VhcmNoUmVzdWx0cyxcblx0XHRcdHRoaXMuX2xlYWYpO1xuXG5cdFx0Ly8gUGllIGNoYXJ0XG5cdFx0Y29uc3QgY2FudmFzUGllQ2hhcnQxID0gZGl2VmF1bHRHcmFwaC5jcmVhdGVFbCgnY2FudmFzJyk7XG5cdFx0Y2FudmFzUGllQ2hhcnQxLnNldEF0dHJpYnV0ZSgnaWQnLCAnZGFzaGJvYXJkLWNhbnZhcycpO1xuXG5cdFx0Y29uc3Qgc3R5bGVzID0gZ2V0Q29tcHV0ZWRTdHlsZShkb2N1bWVudC5ib2R5KTtcblxuXHRcdGNvbnN0IGxhYmVsQ29sb3IgPSBzdHlsZXMuZ2V0UHJvcGVydHlWYWx1ZSgnLS10ZXh0LW11dGVkJyk7XG5cblx0XHRjb25zdCBwaWVDaGFydDEgPSBuZXcgRE5QaWVDaGFydChjYW52YXNQaWVDaGFydDEsIDEwLCAxMiwgNTAsIGxhYmVsQ29sb3IpO1xuXG5cdFx0cGllQ2hhcnQxLmFkZERhdGEodGhpcy5fbm90ZXMubGVuZ3RoLCB0aGlzLmNvbG9yX25vdGVzLCAnTm90ZXMnKTtcblx0XHRwaWVDaGFydDEuYWRkRGF0YSh0aGlzLl9pbWFnZXMubGVuZ3RoLCB0aGlzLmNvbG9yX2ltYWdlcywgJ0ltYWdlcycpO1xuXHRcdHBpZUNoYXJ0MS5hZGREYXRhKHRoaXMuX2NhbnZhcy5sZW5ndGgsIHRoaXMuY29sb3JfY2FudmFzLCAnQ2FudmFzJyk7XG5cdFx0cGllQ2hhcnQxLmFkZERhdGEodGhpcy5fdmlkZW9zLmxlbmd0aCwgdGhpcy5jb2xvcl92aWRlb3MsICdWaWRlb3MnKTtcblx0XHRwaWVDaGFydDEuYWRkRGF0YSh0aGlzLl9hdWRpb3MubGVuZ3RoLCB0aGlzLmNvbG9yX2F1ZGlvcywgJ0F1ZGlvcycpO1xuXHRcdHBpZUNoYXJ0MS5hZGREYXRhKHRoaXMuX3BkZi5sZW5ndGgsIHRoaXMuY29sb3JfcGRmLCAnUERGJyk7XG5cdFx0cGllQ2hhcnQxLmFkZERhdGEodGhpcy5fb3RoZXIubGVuZ3RoLCB0aGlzLmNvbG9yX290aGVyLCAnT3RoZXInKTtcblx0XHRwaWVDaGFydDEuZHJhdygpO1xuXG5cdFx0Ly8gVG90YWwgZmlsZXNcblx0XHRjb25zdCBkaXZTdGF0c0ZyYW1lID0gZGl2VmF1bHRHcmFwaC5jcmVhdGVFbCgnZGl2JywgeyBjbHM6ICdkbi1zdGF0cy1maWxlcy1mb2xkZXJzJyB9KTtcblxuXHRcdGRpdlN0YXRzRnJhbWUuY3JlYXRlRWwoJ2RpdicsIHsgY2xzOiAnZG4tc3RhdHMtZmlsZXMnLCB0ZXh0OiAnRmlsZXM6ICcgKyB0aGlzLl9maWx0ZXJlZF9maWxlcy5sZW5ndGggfSk7XG5cblx0XHQvLyBUb3RhbCBmb2xkZXJzXG5cblx0XHRkaXZTdGF0c0ZyYW1lLmNyZWF0ZUVsKCdkaXYnLCB7IGNsczogJ2RuLXN0YXRzLWZvbGRlcnMnLCB0ZXh0OiAnRm9sZGVyczogJyArIHRoaXMuX2ZvbGRlcnMubGVuZ3RoIH0pO1xuXG5cdFx0Ly8gUmVjZW50IGZpbGVzIGJ5IHR5cGUvY2F0ZWdvcnlcblxuXHRcdGF3YWl0IHRoaXMuZG5DcmVhdGVSZWNlbnRGaWxlcygnUmVjZW50IGZpbGVzJywgZGl2UmVjZW50RmlsZXMsIHRoaXMuX3JlY2VudCwgdGhpcy5udW1fcmVjZW50X2ZpbGVzKTtcblx0XHRhd2FpdCB0aGlzLmRuQ3JlYXRlUmVjZW50RmlsZXMoJ1JlY2VudCBub3RlcycsIGRpdlJlY2VudE5vdGVzLCB0aGlzLl9ub3RlcywgdGhpcy5udW1fcmVjZW50X2ZpbGVzKTtcblx0XHRhd2FpdCB0aGlzLmRuQ3JlYXRlUmVjZW50RmlsZXMoJ1JlY2VudCBjYW52YXMnLCBkaXZDYW52YXMsIHRoaXMuX2NhbnZhcywgdGhpcy5udW1fcmVjZW50X2ZpbGVzKTtcblx0XHRhd2FpdCB0aGlzLmRuQ3JlYXRlUmVjZW50RmlsZXMoJ1JlY2VudCBpbWFnZXMnLCBkaXZJbWFnZXMsIHRoaXMuX2ltYWdlcywgdGhpcy5udW1fcmVjZW50X2ZpbGVzKTtcblx0XHRhd2FpdCB0aGlzLmRuQ3JlYXRlUmVjZW50RmlsZXMoJ1JlY2VudCBhdWRpb3MnLCBkaXZBdWRpb3MsIHRoaXMuX2F1ZGlvcywgdGhpcy5udW1fcmVjZW50X2ZpbGVzKTtcblx0XHRhd2FpdCB0aGlzLmRuQ3JlYXRlUmVjZW50RmlsZXMoJ1JlY2VudCB2aWRlb3MnLCBkaXZWaWRlb3MsIHRoaXMuX3ZpZGVvcywgdGhpcy5udW1fcmVjZW50X2ZpbGVzKTtcblx0XHRhd2FpdCB0aGlzLmRuQ3JlYXRlUmVjZW50RmlsZXMoJ1JlY2VudCBQREZzJywgZGl2UERGcywgdGhpcy5fcGRmLCB0aGlzLm51bV9yZWNlbnRfZmlsZXMpO1xuXHRcdGF3YWl0IHRoaXMuZG5DcmVhdGVSZWNlbnRGaWxlcygnUmVjZW50IG90aGVyIGZpbGVzJywgZGl2T3RoZXIsIHRoaXMuX290aGVyLCB0aGlzLm51bV9yZWNlbnRfZmlsZXMpO1xuXHR9XG5cblx0YXN5bmMgZG5DcmVhdGVCdG4oZWxEaXY6IEhUTUxFbGVtZW50LFxuXHRcdGJ0bklkOiBzdHJpbmcsXG5cdFx0YnRuVGl0bGU6IHN0cmluZyxcblx0XHRidG5DYXRlZ29yeUZpbGVzOiBURmlsZVtdLFxuXHRcdGRpc3BsYXlFbDogSFRNTEVsZW1lbnQsXG5cdFx0bGVhZjogV29ya3NwYWNlTGVhZikge1xuXG5cdFx0bGV0IGJ0biA9IGVsRGl2LmNyZWF0ZUVsKCdkaXYnLCB7IGNsczogJ2RuLWJ0bi1zdGF0cycgfSk7XG5cblx0XHRidG4uc2V0QXR0cmlidXRlKCdpZCcsIGJ0bklkKVxuXHRcdGJ0bi5jcmVhdGVFbCgnc3BhbicsIHsgY2xzOiAnZG4tYnRuLXN0YXRzLWxhYmVsJywgdGV4dDogYnRuVGl0bGUgfSk7XG5cdFx0YnRuLmNyZWF0ZUVsKCdzcGFuJywgeyBjbHM6ICdkbi1idG4tc3RhdHMtaWNvbicgfSk7XG5cdFx0YnRuLmNyZWF0ZUVsKCdzcGFuJywgeyBjbHM6ICdkbi1idG4tc3RhdHMtbnVtYmVyJywgdGV4dDogYnRuQ2F0ZWdvcnlGaWxlcy5sZW5ndGgudG9TdHJpbmcoKSB9KTtcblx0XHRidG4ub25DbGlja0V2ZW50KChldnQ6IE1vdXNlRXZlbnQpID0+IHtcblx0XHRcdHRoaXMuX2ZpbHRlcmVkX2ZpbGVzID0gYnRuQ2F0ZWdvcnlGaWxlcztcblx0XHRcdHRoaXMuX3NlbGVjdGVkX2NhdGVnb3J5ID0gJyAoJyArIGJ0blRpdGxlICsgJyknO1xuXHRcdFx0dGhpcy5kblNvcnRGaWx0ZXJlZEZpbGVzKGZhbHNlKTtcblx0XHRcdHRoaXMuZG5TaG93U2VhcmNoUmVzdWx0cyh7IGY6IGJ0bkNhdGVnb3J5RmlsZXMsIGVsOiBkaXNwbGF5RWwsIGxlYWYgfSk7XG5cdFx0XHR0aGlzLmRuU2V0VmlldygyKTtcblx0XHR9KTtcblxuXHRcdHJldHVybiBidG47XG5cdH1cblxuXHRhc3luYyBkbkNyZWF0ZVJlY2VudEZpbGVzKHRpdGxlOiBzdHJpbmcsIGRpdkY6IEhUTUxEaXZFbGVtZW50LCBmaWxlczogVEZpbGVbXSwgbnVtX2ZpbGVzOiBudW1iZXIpIHtcblx0XHRpZiAoZmlsZXMubGVuZ3RoID09PSAwKSB7XG5cdFx0XHRkaXZGLmNyZWF0ZUVsKCdoMycsIHsgY2xzOiAnZG4tc3VidGl0bGVzJywgdGV4dDogdGl0bGUgfSk7XG5cdFx0XHRkaXZGLmNyZWF0ZUVsKCdwJywgeyBjbHM6ICdkbi1uby1yZXN1bHRzLWZvdW5kJywgdGV4dDogJ05vIGZpbGVzIGZvdW5kLicgfSk7XG5cdFx0XHRkaXZGLmNsYXNzTGlzdC5hZGQoJ2RuLWRpc3BsYXktbm9uZScpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRkaXZGLmNyZWF0ZUVsKCdoMycsIHsgY2xzOiAnZG4tc3VidGl0bGVzJywgdGV4dDogdGl0bGUgfSk7XG5cdFx0XHRjb25zdCBzb3J0ZWRGaWxlcyA9IGF3YWl0IHRoaXMuZG5HZXRSZWNlbnRGaWxlcyhmaWxlcyk7XG5cdFx0XHRzb3J0ZWRGaWxlcy5mb3JFYWNoKHNmaWxlID0+IHtcblx0XHRcdFx0ZGl2Ri5jcmVhdGVFbCgnYScsIHsgY2xzOiB0aGlzLmRuU2V0RmlsZUljb25DbGFzcyhzZmlsZS5leHRlbnNpb24pLCB0ZXh0OiBzZmlsZS5iYXNlbmFtZSwgdGl0bGU6IHNmaWxlLnBhdGggfSkub25DbGlja0V2ZW50KChldnQ6IE1vdXNlRXZlbnQpID0+IHtcblx0XHRcdFx0XHRpZiAoc2ZpbGUgIT09IG51bGwpIHtcblx0XHRcdFx0XHRcdHRoaXMuZG5PcGVuRmlsZUFsdChzZmlsZSwgZXZ0KTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0pO1xuXHRcdFx0XHRpZiAoc2ZpbGUuZXh0ZW5zaW9uICE9PSAnbWQnKSB7XG5cdFx0XHRcdFx0ZGl2Ri5jcmVhdGVFbCgnc3BhbicsIHsgY2xzOiAnbmF2LWZpbGUtdGFnJywgdGV4dDogc2ZpbGUuZXh0ZW5zaW9uIH0pXG5cdFx0XHRcdH1cblxuXHRcdFx0XHRkaXZGLmNyZWF0ZUVsKCdicicpO1xuXHRcdFx0fSk7XG5cdFx0fVxuXHR9XG5cblxuXHRkbkNyZWF0ZUlucHV0U2VhcmNoKGVsOiBIVE1MRWxlbWVudCk6IHZvaWQge1xuXHRcdGNvbnN0IHNlYXJjaENvbnRhaW5lciA9IGVsLmNyZWF0ZUVsKCdkaXYnLCB7IGNsczogJ2RuLXNlYXJjaC1pbnB1dC1jb250YWluZXInIH0pO1xuXHRcdHRoaXMuX0lOUFVUX1NFQVJDSCA9IHNlYXJjaENvbnRhaW5lci5jcmVhdGVFbCgnaW5wdXQnLCB7IHR5cGU6ICdzZWFyY2gnLCBwbGFjZWhvbGRlcjogJ1NlYXJjaC4uLicgfSk7XG5cdFx0dGhpcy5fSU5QVVRfU0VBUkNILnNldEF0dHJpYnV0ZSgnaWQnLCAnZG4taW5wdXQtZmlsdGVyJyk7XG5cdFx0dGhpcy5fSU5QVVRfU0VBUkNILnNwZWxsY2hlY2sgPSBmYWxzZTtcblx0XHR0aGlzLl9JTlBVVF9TRUFSQ0guZm9jdXMoKTtcblx0XHRjb25zdCBjbGVhcklucHV0U2VhcmNoID0gc2VhcmNoQ29udGFpbmVyLmNyZWF0ZUVsKCdkaXYnLCB7IGNsczogJ3NlYXJjaC1pbnB1dC1jbGVhci1idXR0b24nIH0pLm9uQ2xpY2tFdmVudCgoZXZ0OiBNb3VzZUV2ZW50KSA9PiB7XG5cdFx0XHR0aGlzLl9JTlBVVF9TRUFSQ0gudmFsdWUgPSAnJztcblx0XHRcdHRoaXMuX0lOUFVUX1NFQVJDSC5mb2N1cygpO1xuXHRcdFx0dGhpcy5kblNlYXJjaFZhdWx0KHRoaXMuX0lOUFVUX1NFQVJDSC52YWx1ZSk7XG5cdFx0fSk7XG5cdFx0Ly8gS2V5dXAgZXZlbnQgbGlzdGVuZXIgd2l0aCBkZWJvdW5jZVxuXHRcdHRoaXMuX0lOUFVUX1NFQVJDSC5hZGRFdmVudExpc3RlbmVyKCdpbnB1dCcsIGRlYm91bmNlKCgpID0+IHRoaXMuZG5TZWFyY2hWYXVsdCh0aGlzLl9JTlBVVF9TRUFSQ0gudmFsdWUpLCAzMDAsIHRydWUpKTtcblx0fVxuXG5cdGFzeW5jIGRuU2VhcmNoVmF1bHQodmFsOiBzdHJpbmcpIHtcblx0XHRsZXQgckV4cDtcblx0XHR0cnkge1xuXHRcdFx0ckV4cCA9IG5ldyBSZWdFeHAodmFsLnRvTG93ZXJDYXNlKCksICdpdScpO1xuXG5cdFx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHR0aGlzLmRuU2V0VmlldygyKTtcblxuXHRcdGNvbnN0IGlzRGF0ZVNlYXJjaCA9IHZhbC5zdGFydHNXaXRoKCdAJyk7XG5cblx0XHRpZiAoaXNEYXRlU2VhcmNoKSB7XG5cdFx0XHR0aGlzLl9JTlBVVF9TRUFSQ0guY2xhc3NMaXN0LmFkZCgnZG4taW5wdXQtZGF0ZXNlYXJjaCcpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLl9JTlBVVF9TRUFSQ0guY2xhc3NMaXN0LnJlbW92ZSgnZG4taW5wdXQtZGF0ZXNlYXJjaCcpO1xuXHRcdH1cblxuXHRcdHRoaXMuX2ZpbHRlcmVkX2ZpbGVzID0gdGhpcy5fZmlsZXMuZmlsdGVyKFxuXHRcdFx0ZmlsZSA9PiB7XG5cdFx0XHRcdGlmIChpc0RhdGVTZWFyY2gpIHtcblxuXHRcdFx0XHRcdGxldCBtdGltZSA9IG1vbWVudChmaWxlLnN0YXQubXRpbWUpO1xuXHRcdFx0XHRcdGNvbnN0IGRhdGVTZWFyY2ggPSB2YWwuc2xpY2UoMSkudG9Mb3dlckNhc2UoKS5zcGxpdCgnICcpO1xuXG5cdFx0XHRcdFx0c3dpdGNoIChkYXRlU2VhcmNoWzBdKSB7XG5cdFx0XHRcdFx0XHRjYXNlICdkYXknOlxuXHRcdFx0XHRcdFx0Y2FzZSAndG9kYXknOlxuXHRcdFx0XHRcdFx0XHRyZXR1cm4gbXRpbWUuaXNTYW1lKG1vbWVudCgpLCAnZGF5Jyk7XG5cdFx0XHRcdFx0XHRjYXNlICdkYXktMSc6XG5cdFx0XHRcdFx0XHRjYXNlICd5ZXN0ZXJkYXknOlxuXHRcdFx0XHRcdFx0XHRyZXR1cm4gbXRpbWUuaXNTYW1lKG1vbWVudCgpLnN1YnRyYWN0KDEsICdkYXlzJyksICdkYXknKTtcblx0XHRcdFx0XHRcdGNhc2UgJ2RheS0yJzpcblx0XHRcdFx0XHRcdFx0cmV0dXJuIG10aW1lLmlzU2FtZShtb21lbnQoKS5zdWJ0cmFjdCgyLCAnZGF5cycpLCAnZGF5Jyk7XG5cdFx0XHRcdFx0XHRjYXNlICdkYXktMyc6XG5cdFx0XHRcdFx0XHRcdHJldHVybiBtdGltZS5pc1NhbWUobW9tZW50KCkuc3VidHJhY3QoMywgJ2RheXMnKSwgJ2RheScpO1xuXHRcdFx0XHRcdFx0Y2FzZSAnZGF5LTQnOlxuXHRcdFx0XHRcdFx0XHRyZXR1cm4gbXRpbWUuaXNTYW1lKG1vbWVudCgpLnN1YnRyYWN0KDQsICdkYXlzJyksICdkYXknKTtcblx0XHRcdFx0XHRcdGNhc2UgJ2RheS01Jzpcblx0XHRcdFx0XHRcdFx0cmV0dXJuIG10aW1lLmlzU2FtZShtb21lbnQoKS5zdWJ0cmFjdCg1LCAnZGF5cycpLCAnZGF5Jyk7XG5cdFx0XHRcdFx0XHRjYXNlICdkYXktNic6XG5cdFx0XHRcdFx0XHRcdHJldHVybiBtdGltZS5pc1NhbWUobW9tZW50KCkuc3VidHJhY3QoNiwgJ2RheXMnKSwgJ2RheScpO1xuXHRcdFx0XHRcdFx0Y2FzZSAnZGF5LTcnOlxuXHRcdFx0XHRcdFx0XHRyZXR1cm4gbXRpbWUuaXNTYW1lKG1vbWVudCgpLnN1YnRyYWN0KDcsICdkYXlzJyksICdkYXknKTtcblx0XHRcdFx0XHRcdGNhc2UgJ3dlZWsnOlxuXHRcdFx0XHRcdFx0XHRyZXR1cm4gbXRpbWUuaXNCZXR3ZWVuKG1vbWVudCgpLnN1YnRyYWN0KDcsICdkYXlzJyksIG1vbWVudCgpLCAnZGF5JywgJ1tdJyk7XG5cdFx0XHRcdFx0XHRjYXNlICdtb250aCc6XG5cdFx0XHRcdFx0XHRcdHJldHVybiBtdGltZS5pc1NhbWUobW9tZW50KCksICdtb250aCcpO1xuXHRcdFx0XHRcdFx0Y2FzZSAneWVhcic6XG5cdFx0XHRcdFx0XHRcdHJldHVybiBtdGltZS5pc1NhbWUobW9tZW50KCksICd5ZWFyJyk7XG5cdFx0XHRcdFx0XHRkZWZhdWx0OlxuXHRcdFx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHJldHVybiByRXhwLnRlc3QoZmlsZS5uYW1lLnRvTG93ZXJDYXNlKCkpXG5cdFx0XHRcdFx0XHR8fCByRXhwLnRlc3QoZ2V0Rm9sZGVyU3RydWN0dXJlKGZpbGUucGF0aCkudG9Mb3dlckNhc2UoKSlcblx0XHRcdFx0XHRcdHx8IHJFeHAudGVzdChtb21lbnQoZmlsZS5zdGF0Lm10aW1lKS5mb3JtYXQodGhpcy5kYXRlX2Zvcm1hdCkpXG5cdFx0XHRcdFx0XHR8fCByRXhwLnRlc3QodGhpcy5kbkdldFRhZ3NQZXJGaWxlKGZpbGUpLnRvTG93ZXJDYXNlKCkpO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblxuXHRcdHRoaXMuX3NlbGVjdGVkX2NhdGVnb3J5ID0gJyc7XG5cblx0XHR0aGlzLmRuU29ydEZpbHRlcmVkRmlsZXMoZmFsc2UpO1xuXG5cdFx0YXdhaXQgdGhpcy5kblNob3dTZWFyY2hSZXN1bHRzKHsgZjogdGhpcy5fZmlsdGVyZWRfZmlsZXMsIGVsOiB0aGlzLl9kaXZTZWFyY2hSZXN1bHRzLCBsZWFmOiB0aGlzLl9sZWFmIH0pO1xuXG5cdFx0Y29uc3QgdGJvZHkgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZG4tdGFibGUtcmVzdWx0cycpIGFzIEhUTUxUYWJsZVNlY3Rpb25FbGVtZW50O1xuXG5cdFx0aWYgKHRib2R5ICE9PSBudWxsKSB7XG5cdFx0XHRjb25zdCB0ciA9IHRib2R5LmdldEVsZW1lbnRzQnlUYWdOYW1lKCd0cicpIGFzIEhUTUxDb2xsZWN0aW9uT2Y8SFRNTFRhYmxlUm93RWxlbWVudD47XG5cblx0XHRcdGZvciAobGV0IGkgPSAwLCBsZW4gPSB0ci5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuXHRcdFx0XHRjb25zdCBhbGxUZHMgPSB0cltpXS5xdWVyeVNlbGVjdG9yQWxsKCd0ZCcpIGFzIE5vZGVMaXN0T2Y8SFRNTFRhYmxlQ2VsbEVsZW1lbnQ+O1xuXG5cdFx0XHRcdGxldCBpc1Jlc3VsdCA9IGZhbHNlO1xuXG5cdFx0XHRcdGZvciAobGV0IGogPSAwOyBqIDwgYWxsVGRzLmxlbmd0aDsgaisrKSB7XG5cdFx0XHRcdFx0Y29uc3QgdGQgPSBhbGxUZHNbal07XG5cdFx0XHRcdFx0Y29uc3QgdGRWYWwgPSB0ZC5pbm5lclRleHQudG9Mb3dlckNhc2UoKTtcblx0XHRcdFx0XHRpZiAockV4cC50ZXN0KHRkVmFsKSB8fCBpc0RhdGVTZWFyY2gpIHtcblx0XHRcdFx0XHRcdGlzUmVzdWx0ID0gdHJ1ZTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmIChpc1Jlc3VsdCkge1xuXHRcdFx0XHRcdHRyW2ldLmNsYXNzTGlzdC5yZW1vdmUoJ2RuLWRpc3BsYXktbm9uZScpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHRyW2ldLmNsYXNzTGlzdC5hZGQoJ2RuLWRpc3BsYXktbm9uZScpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0YXN5bmMgZG5Tb3J0RmlsdGVyZWRGaWxlcyh0b2dnbGU6IGJvb2xlYW4pIHtcblx0XHRzd2l0Y2ggKHRoaXMuX3NvcnRfY29sdW1uKSB7XG5cdFx0XHRjYXNlICduYW1lJzpcblx0XHRcdGNhc2UgJ3BhdGgnOlxuXHRcdFx0XHR0aGlzLmRuU29ydENvbHVtblN0cmluZyh0aGlzLl9zb3J0X2NvbHVtbiwgdGhpcy5fc29ydF9vcmRlciwgdG9nZ2xlKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdzaXplJzpcblx0XHRcdGNhc2UgJ21vZGlmaWVkJzpcblx0XHRcdFx0dGhpcy5kblNvcnRDb2x1bW5OdW1iZXIodGhpcy5fc29ydF9jb2x1bW4sIHRoaXMuX3NvcnRfb3JkZXIsIHRvZ2dsZSk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdH1cblx0fVxuXG5cdGRuU29ydENvbHVtbldpdGhTZWxlY3QoKTogdm9pZCB7XG5cdFx0Y29uc3QgdmFsID0gdGhpcy5fU0VMRUNUX1NPUlQudmFsdWU7XG5cdFx0aWYgKHRoaXMuZG5Jc1ZhbGlkU29ydCh2YWwpKSB7XG5cdFx0XHRjb25zdCBzZWxTb3J0ID0gdmFsLnNwbGl0KCctJyk7XG5cdFx0XHR0aGlzLl9zb3J0X2NvbHVtbiA9IHNlbFNvcnRbMF07XG5cdFx0XHR0aGlzLl9zb3J0X29yZGVyID0gc2VsU29ydFsxXTtcblxuXHRcdFx0c3dpdGNoICh0aGlzLl9zb3J0X2NvbHVtbikge1xuXHRcdFx0XHRjYXNlICduYW1lJzpcblx0XHRcdFx0Y2FzZSAncGF0aCc6XG5cdFx0XHRcdFx0dGhpcy5kblNvcnRDb2x1bW5TdHJpbmcodGhpcy5fc29ydF9jb2x1bW4sIHRoaXMuX3NvcnRfb3JkZXIsIGZhbHNlKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSAnc2l6ZSc6XG5cdFx0XHRcdGNhc2UgJ21vZGlmaWVkJzpcblx0XHRcdFx0XHR0aGlzLmRuU29ydENvbHVtbk51bWJlcih0aGlzLl9zb3J0X2NvbHVtbiwgdGhpcy5fc29ydF9vcmRlciwgZmFsc2UpO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXG5cdFx0XHR0aGlzLmRuU2hvd1NlYXJjaFJlc3VsdHMoeyBmOiB0aGlzLl9maWx0ZXJlZF9maWxlcywgZWw6IHRoaXMuX2RpdlNlYXJjaFJlc3VsdHMsIGxlYWY6IHRoaXMuX2xlYWYgfSk7XG5cblx0XHR9XG5cdH1cblxuXHRkbklzVmFsaWRTb3J0KHZhbDogc3RyaW5nKTogYm9vbGVhbiB7XG5cdFx0aWYgKFsnbmFtZS1hc2MnLCAnbmFtZS1kZXNjJywgJ3BhdGgtYXNjJywgJ3BhdGgtZGVzYycsXG5cdFx0XHQnc2l6ZS1hc2MnLCAnc2l6ZS1kZXNjJywgJ21vZGlmaWVkLWFzYycsICdtb2RpZmllZC1kZXNjJ10uaW5jbHVkZXModmFsKSkge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cdH1cblxuXHRkbklzVmFsaWRMYXlvdXQodmFsOiBzdHJpbmcpOiBib29sZWFuIHtcblx0XHRpZiAodGhpcy5fVEFCTEVfTEFZT1VUUy5pbmNsdWRlcyh2YWwpKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblx0fVxuXG5cdGFzeW5jIGRuU2hvd1NlYXJjaFJlc3VsdHMoeyBmLCBlbCwgbGVhZiwgY3VycmVudFBhZ2UgPSAxIH06IHsgZjogVEZpbGVbXTsgZWw6IEhUTUxFbGVtZW50OyBsZWFmOiBXb3Jrc3BhY2VMZWFmOyBjdXJyZW50UGFnZT86IG51bWJlciB9KTogUHJvbWlzZTx2b2lkPiB7XG5cblx0XHRlbC5lbXB0eSgpO1xuXG5cdFx0Y29uc3QgcGFnaW5hdGlvbkNvbnRhaW5lciA9IHRoaXMuX2RpdlNlYXJjaFJlc3VsdHMuY3JlYXRlRWwoJ2RpdicsIHsgY2xzOiAnZG4tcGFnaW5hdGlvbicgfSk7XG5cdFx0Y29uc3QgdGFibGUgPSBlbC5jcmVhdGVFbCgndGFibGUnLCB7IGNsczogdGhpcy5zZWxlY3RlZF90YWJsZV9sYXlvdXQgfSk7XG5cdFx0dGFibGUuc2V0QXR0cmlidXRlKCdpZCcsICdkbi10YWJsZScpO1xuXG5cdFx0Y29uc3QgdGhlYWQgPSB0YWJsZS5jcmVhdGVFbCgndGhlYWQnKTtcblx0XHRjb25zdCB0ciA9IHRoZWFkLmNyZWF0ZUVsKCd0cicpO1xuXHRcdHRoaXMuX3RoMSA9IHRyLmNyZWF0ZUVsKCd0aCcsIHsgdGV4dDogJ05hbWUnIH0pO1xuXHRcdHRoaXMuX3RoMiA9IHRyLmNyZWF0ZUVsKCd0aCcsIHsgdGV4dDogJ1BhdGgnIH0pO1xuXHRcdHRoaXMuX3RoMyA9IHRyLmNyZWF0ZUVsKCd0aCcsIHsgdGV4dDogJ1NpemUnIH0pO1xuXHRcdHRoaXMuX3RoNCA9IHRyLmNyZWF0ZUVsKCd0aCcsIHsgdGV4dDogJ0RhdGUnIH0pO1xuXHRcdHRoaXMuX3RoNSA9IHRyLmNyZWF0ZUVsKCd0aCcsIHsgdGV4dDogJ1RhZ3MnIH0pO1xuXG5cdFx0dGhpcy5fdGgxLmFkZEV2ZW50TGlzdGVuZXIoJ2RibGNsaWNrJywgKCkgPT4gdGhpcy5kbkFsdGVybmF0ZVNvcnRDb2x1bW4oJ25hbWUnKSk7XG5cdFx0dGhpcy5fdGgyLmFkZEV2ZW50TGlzdGVuZXIoJ2RibGNsaWNrJywgKCkgPT4gdGhpcy5kbkFsdGVybmF0ZVNvcnRDb2x1bW4oJ3BhdGgnKSk7XG5cdFx0dGhpcy5fdGgzLmFkZEV2ZW50TGlzdGVuZXIoJ2RibGNsaWNrJywgKCkgPT4gdGhpcy5kbkFsdGVybmF0ZVNvcnRDb2x1bW4oJ3NpemUnKSk7XG5cdFx0dGhpcy5fdGg0LmFkZEV2ZW50TGlzdGVuZXIoJ2RibGNsaWNrJywgKCkgPT4gdGhpcy5kbkFsdGVybmF0ZVNvcnRDb2x1bW4oJ21vZGlmaWVkJykpO1xuXHRcdGNvbnN0IHRib2R5ID0gdGFibGUuY3JlYXRlRWwoJ3Rib2R5Jyk7XG5cdFx0dGJvZHkuc2V0QXR0cmlidXRlKCdpZCcsICdkbi10YWJsZS1yZXN1bHRzJyk7XG5cblx0XHRpZiAoZi5sZW5ndGggPiAwKSB7XG5cblx0XHRcdGlmICh0aGlzLmludGVyc2VjdGlvbk9ic2VydmVyKSB7XG5cdFx0XHRcdHRoaXMuaW50ZXJzZWN0aW9uT2JzZXJ2ZXIuZGlzY29ubmVjdCgpO1xuXHRcdFx0fVxuXHRcdFx0Ly8gUGFnaW5hdGlvblxuXHRcdFx0dGhpcy5fdG90YWxfcGFnZXMgPSBNYXRoLmNlaWwoZi5sZW5ndGggLyB0aGlzLmZpbGVzX3Blcl9wYWdlKTtcblx0XHRcdGNvbnN0IHBhZ2luYXRlZERhdGEgPSBmLnNsaWNlKChjdXJyZW50UGFnZSAtIDEpICogdGhpcy5maWxlc19wZXJfcGFnZSwgY3VycmVudFBhZ2UgKiB0aGlzLmZpbGVzX3Blcl9wYWdlKTtcblxuXHRcdFx0cGFnaW5hdGVkRGF0YS5mb3JFYWNoKGFzeW5jIGZpbGUgPT4ge1xuXHRcdFx0XHRsZXQgdHIgPSB0Ym9keS5jcmVhdGVFbCgndHInKTtcblx0XHRcdFx0Ly8gRXZlbnRzXG5cdFx0XHRcdHRyLmFkZEV2ZW50TGlzdGVuZXIoJ2NvbnRleHRtZW51JywgKGV2dDogTW91c2VFdmVudCkgPT4geyB0aGlzLmRuSGFuZGxlQ2xpY2soZXZ0LCBmaWxlKSB9KTtcblx0XHRcdFx0dHIuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCAoZXZ0OiBNb3VzZUV2ZW50KSA9PiB7IHRoaXMuZG5IYW5kbGVDbGljayhldnQsIGZpbGUpIH0pO1xuXHRcdFx0XHR0ci5hZGRFdmVudExpc3RlbmVyKCdkYmxjbGljaycsIChldnQ6IE1vdXNlRXZlbnQpID0+IHsgdGhpcy5kbkhhbmRsZURibENsaWNrKGV2dCwgZmlsZSkgfSk7XG5cblx0XHRcdFx0dGhpcy5pbnRlcnNlY3Rpb25PYnNlcnZlci5vYnNlcnZlKHRyKTtcblxuXHRcdFx0XHRsZXQgdGQxID0gdHIuY3JlYXRlRWwoJ3RkJyk7XG5cdFx0XHRcdGxldCB0ZDFMaW5rID0gdGQxLmNyZWF0ZUVsKCdhJywgeyBjbHM6IHRoaXMuZG5TZXRGaWxlSWNvbkNsYXNzKGZpbGUuZXh0ZW5zaW9uKSwgdGV4dDogZmlsZS5uYW1lIH0pLm9uQ2xpY2tFdmVudCgoZXZ0OiBNb3VzZUV2ZW50KSA9PiB7XG5cdFx0XHRcdFx0aWYgKGxlYWYgIT09IG51bGwgJiYgZmlsZSAhPT0gbnVsbCkge1xuXHRcdFx0XHRcdFx0dGhpcy5kbk9wZW5GaWxlQWx0KGZpbGUsIGV2dCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9KTtcblxuXHRcdFx0XHRsZXQgZlNpemUgPSBmb3JtYXRGaWxlU2l6ZShmaWxlLnN0YXQuc2l6ZSk7XG5cdFx0XHRcdGxldCBmTVRpbWUgPSBtb21lbnQoZmlsZS5zdGF0Lm10aW1lKS5mb3JtYXQodGhpcy5kYXRlX2Zvcm1hdCk7XG5cdFx0XHRcdGxldCB0ZDIgPSB0ci5jcmVhdGVFbCgndGQnKTtcblx0XHRcdFx0bGV0IGZvbGRlcl9wYXRoID0gZ2V0Rm9sZGVyU3RydWN0dXJlKGZpbGUucGF0aCk7XG5cdFx0XHRcdGxldCB0ZDJfcGF0aCA9IHRkMi5jcmVhdGVFbCgnYScsIHsgY2xzOiAnZG4tZm9sZGVyLXBhdGgnLCB0ZXh0OiBmb2xkZXJfcGF0aCwgdGl0bGU6IGZpbGUucGF0aCB9KS5vbkNsaWNrRXZlbnQoKGV2dDogTW91c2VFdmVudCkgPT4ge1xuXHRcdFx0XHRcdHRoaXMuX0lOUFVUX1NFQVJDSC52YWx1ZSA9IGZvbGRlcl9wYXRoO1xuXHRcdFx0XHRcdHRoaXMuZG5TZWFyY2hWYXVsdCh0aGlzLl9JTlBVVF9TRUFSQ0gudmFsdWUgKyAnJCcpO1xuXHRcdFx0XHR9KTtcblxuXHRcdFx0XHRsZXQgdGQzID0gdHIuY3JlYXRlRWwoJ3RkJywgeyB0ZXh0OiBmU2l6ZSwgdGl0bGU6IGZTaXplICsgJyBieXRlcycgfSk7XG5cdFx0XHRcdGxldCB0ZDQgPSB0ci5jcmVhdGVFbCgndGQnLCB7IHRleHQ6IGZNVGltZSwgdGl0bGU6IGZNVGltZSB9KTtcblx0XHRcdFx0bGV0IHRhZ3NfcGVyX2ZpbGUgPSB0aGlzLmRuR2V0VGFnc1BlckZpbGUoZmlsZSk7XG5cdFx0XHRcdGxldCB0ZDUgPSB0ci5jcmVhdGVFbCgndGQnLCB7IHRpdGxlOiB0YWdzX3Blcl9maWxlIH0pO1xuXHRcdFx0XHRsZXQgZlRhZ3MgPSB0YWdzX3Blcl9maWxlLnNwbGl0KCcgJyk7XG5cdFx0XHRcdGZUYWdzLmZvckVhY2goKHRhZykgPT4ge1xuXHRcdFx0XHRcdHRkNS5jcmVhdGVFbCgnYScsIHsgY2xzOiAnZG4tdGFnJywgdGV4dDogdGFnIH0pLm9uQ2xpY2tFdmVudCgoZXZ0OiBNb3VzZUV2ZW50KSA9PiB7XG5cdFx0XHRcdFx0XHR0aGlzLl9JTlBVVF9TRUFSQ0gudmFsdWUgPSB0YWc7XG5cdFx0XHRcdFx0XHR0aGlzLmRuU2VhcmNoVmF1bHQodGhpcy5fSU5QVVRfU0VBUkNILnZhbHVlKTtcblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fSk7XG5cblx0XHRcdH0pO1xuXG5cdFx0XHQvLyBBZGQgcGFnaW5hdGlvblxuXHRcdFx0cGFnaW5hdGlvbkNvbnRhaW5lci5lbXB0eSgpO1xuXHRcdFx0Y29uc3QgcmVzdWx0c0NvdW50ID0gcGFnaW5hdGlvbkNvbnRhaW5lci5jcmVhdGVFbCgnc3BhbicsIHsgY2xzOiAnZG4tcGFnaW5hdGlvbi10b3RhbC1yZXN1bHRzJywgdGV4dDogYEZpbGUocyk6ICR7Zi5sZW5ndGh9YCArIHRoaXMuX3NlbGVjdGVkX2NhdGVnb3J5IH0pO1xuXHRcdFx0Y29uc3QgY3VycmVudFBhZ2VJbmRpY2F0b3IgPSBwYWdpbmF0aW9uQ29udGFpbmVyLmNyZWF0ZUVsKCdzcGFuJywgeyBjbHM6ICdkbi1wYWdpbmF0aW9uLWN1cnJlbnQtcGFnZScsIHRleHQ6IGBQYWdlICR7Y3VycmVudFBhZ2V9IG9mICR7dGhpcy5fdG90YWxfcGFnZXN9YCB9KTtcblxuXHRcdFx0Y29uc3QgYnRuUHJldiA9IHBhZ2luYXRpb25Db250YWluZXIuY3JlYXRlRWwoJ2J1dHRvbicsIHsgY2xzOiAnZG4tYnRuLXByZXYnLCB0ZXh0OiAnXHUyNUMwJywgdGl0bGU6ICdQcmV2aW91cycgfSk7XG5cdFx0XHRpZiAoY3VycmVudFBhZ2UgPT09IDEpIHtcblx0XHRcdFx0YnRuUHJldi5kaXNhYmxlZCA9IHRydWU7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRidG5QcmV2LmRpc2FibGVkID0gZmFsc2U7XG5cdFx0XHR9XG5cdFx0XHRidG5QcmV2LmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgKCkgPT4ge1xuXHRcdFx0XHRpZiAoY3VycmVudFBhZ2UgPiAxKSB7XG5cdFx0XHRcdFx0dGhpcy5kblNob3dTZWFyY2hSZXN1bHRzKHsgZiwgZWwsIGxlYWYsIGN1cnJlbnRQYWdlOiBjdXJyZW50UGFnZSAtIDEgfSk7XG5cdFx0XHRcdH1cblx0XHRcdH0pO1xuXHRcdFx0Y29uc3QgYnRuTmV4dCA9IHBhZ2luYXRpb25Db250YWluZXIuY3JlYXRlRWwoJ2J1dHRvbicsIHsgY2xzOiAnZG4tYnRuLW5leHQnLCB0ZXh0OiAnXHUyNUI2JywgdGl0bGU6ICdOZXh0JyB9KTtcblx0XHRcdGlmIChjdXJyZW50UGFnZSA9PT0gdGhpcy5fdG90YWxfcGFnZXMpIHtcblx0XHRcdFx0YnRuTmV4dC5kaXNhYmxlZCA9IHRydWU7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRidG5OZXh0LmRpc2FibGVkID0gZmFsc2U7XG5cdFx0XHR9XG5cblx0XHRcdGJ0bk5leHQuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCAoKSA9PiB7XG5cdFx0XHRcdGlmIChjdXJyZW50UGFnZSA8IHRoaXMuX3RvdGFsX3BhZ2VzKSB7XG5cdFx0XHRcdFx0dGhpcy5kblNob3dTZWFyY2hSZXN1bHRzKHsgZiwgZWwsIGxlYWYsIGN1cnJlbnRQYWdlOiBjdXJyZW50UGFnZSArIDEgfSk7XG5cdFx0XHRcdH1cblx0XHRcdH0pO1xuXG5cdFx0XHR0aGlzLmRuVXBkYXRlU29ydEluZGljYXRvcnModGhpcy5fc29ydF9jb2x1bW4sXG5cdFx0XHRcdHRoaXMuX3NvcnRfb3JkZXIsXG5cdFx0XHRcdHRoaXMuX3RoMSxcblx0XHRcdFx0dGhpcy5fdGgyLFxuXHRcdFx0XHR0aGlzLl90aDMsXG5cdFx0XHRcdHRoaXMuX3RoNCk7XG5cblx0XHR9IGVsc2Uge1xuXHRcdFx0dHIuZW1wdHkoKTtcblx0XHRcdHRoaXMuX2RpdlNlYXJjaFJlc3VsdHMuY3JlYXRlRWwoJ3AnLCB7IGNsczogJ2RuLW5vLXJlc3VsdHMtZm91bmQnLCB0ZXh0OiAnTm8gZmlsZXMgZm91bmQuJyB9KTtcblx0XHR9XG5cdH1cblxuXHRkbkFsdGVybmF0ZVNvcnRDb2x1bW4oY29sTmFtZTogc3RyaW5nKSB7XG5cdFx0c3dpdGNoIChjb2xOYW1lKSB7XG5cdFx0XHRjYXNlICduYW1lJzpcblx0XHRcdFx0dGhpcy5kblNvcnRDb2x1bW5TdHJpbmcoJ25hbWUnLCB0aGlzLl9zb3J0X29yZGVyLCB0cnVlKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdwYXRoJzpcblx0XHRcdFx0dGhpcy5kblNvcnRDb2x1bW5TdHJpbmcoJ3BhdGgnLCB0aGlzLl9zb3J0X29yZGVyLCB0cnVlKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdzaXplJzpcblx0XHRcdFx0dGhpcy5kblNvcnRDb2x1bW5OdW1iZXIoJ3NpemUnLCB0aGlzLl9zb3J0X29yZGVyLCB0cnVlKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdtb2RpZmllZCc6XG5cdFx0XHRcdHRoaXMuZG5Tb3J0Q29sdW1uTnVtYmVyKCdtb2RpZmllZCcsIHRoaXMuX3NvcnRfb3JkZXIsIHRydWUpO1xuXHRcdFx0XHRicmVhaztcblx0XHR9XG5cdFx0dGhpcy5kblNob3dTZWFyY2hSZXN1bHRzKHsgZjogdGhpcy5fZmlsdGVyZWRfZmlsZXMsIGVsOiB0aGlzLl9kaXZTZWFyY2hSZXN1bHRzLCBsZWFmOiB0aGlzLl9sZWFmIH0pO1xuXHR9XG5cblx0ZG5HZXRUYWdzUGVyRmlsZShmaWxlOiBURmlsZSk6IHN0cmluZyB7XG5cdFx0Y29uc3QgY3VyX2ZpbGUgPSB0aGlzLmFwcC52YXVsdC5nZXRBYnN0cmFjdEZpbGVCeVBhdGgoZmlsZS5wYXRoKTtcblx0XHRpZiAoY3VyX2ZpbGUgIT09IG51bGwpIHtcblxuXHRcdFx0Y29uc3QgdGFncyA9IHRoaXMuYXBwLm1ldGFkYXRhQ2FjaGUuZ2V0RmlsZUNhY2hlKGZpbGUpPy50YWdzO1xuXHRcdFx0Y29uc3QgZnJvbnRtYXR0ZXJfdGFncyA9IHRoaXMuYXBwLm1ldGFkYXRhQ2FjaGUuZ2V0RmlsZUNhY2hlKGZpbGUpPy5mcm9udG1hdHRlcjtcblx0XHRcdGNvbnN0IGFyclRhZ3M6IHN0cmluZ1tdID0gW107XG5cblx0XHRcdGlmICh0YWdzKSB7XG5cdFx0XHRcdGZvciAobGV0IGkgPSAwLCBsZW4gPSB0YWdzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG5cblx0XHRcdFx0XHRpZiAoYXJyVGFncy5pbmRleE9mKHRhZ3NbaV0udGFnKSA8IDApIHtcblx0XHRcdFx0XHRcdGFyclRhZ3MucHVzaCh0YWdzW2ldLnRhZyk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdGlmIChmcm9udG1hdHRlcl90YWdzICE9PSB1bmRlZmluZWQgJiYgZnJvbnRtYXR0ZXJfdGFncy50YWdzKSB7XG5cdFx0XHRcdGZvciAobGV0IGkgPSAwLCBsZW4gPSBmcm9udG1hdHRlcl90YWdzLnRhZ3MubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcblxuXHRcdFx0XHRcdGlmIChhcnJUYWdzLmluZGV4T2YoZnJvbnRtYXR0ZXJfdGFncy50YWdzW2ldKSA8IDApIHtcblx0XHRcdFx0XHRcdGFyclRhZ3MucHVzaCgnIycgKyBmcm9udG1hdHRlcl90YWdzLnRhZ3NbaV0pO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gYXJyVGFncy5qb2luKCcgJyk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJldHVybiAnJztcblx0XHR9XG5cblx0fVxuXG5cdGRuVXBkYXRlU29ydEluZGljYXRvcnMoYWN0aXZlQ29sdW1uOiBzdHJpbmcsIHNvcnRPcmRlcjogc3RyaW5nLCBjb2wxOiBIVE1MVGFibGVDZWxsRWxlbWVudCwgY29sMjogSFRNTFRhYmxlQ2VsbEVsZW1lbnQsIGNvbDM6IEhUTUxUYWJsZUNlbGxFbGVtZW50LCBjb2w0OiBIVE1MVGFibGVDZWxsRWxlbWVudCkge1xuXHRcdGNvbDEuY2xhc3NMaXN0LnJlbW92ZSgnc29ydC1hY3RpdmUnLCAnc29ydC1hc2MnLCAnc29ydC1kZXNjJyk7XG5cdFx0Y29sMi5jbGFzc0xpc3QucmVtb3ZlKCdzb3J0LWFjdGl2ZScsICdzb3J0LWFzYycsICdzb3J0LWRlc2MnKTtcblx0XHRjb2wzLmNsYXNzTGlzdC5yZW1vdmUoJ3NvcnQtYWN0aXZlJywgJ3NvcnQtYXNjJywgJ3NvcnQtZGVzYycpO1xuXHRcdGNvbDQuY2xhc3NMaXN0LnJlbW92ZSgnc29ydC1hY3RpdmUnLCAnc29ydC1hc2MnLCAnc29ydC1kZXNjJyk7XG5cdFx0bGV0IGFjdGl2ZVRoQ2VsbCA9IGNvbDQ7XG5cdFx0c3dpdGNoIChhY3RpdmVDb2x1bW4pIHtcblx0XHRcdGNhc2UgJ25hbWUnOlxuXHRcdFx0XHRhY3RpdmVUaENlbGwgPSBjb2wxO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ3BhdGgnOlxuXHRcdFx0XHRhY3RpdmVUaENlbGwgPSBjb2wyO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ3NpemUnOlxuXHRcdFx0XHRhY3RpdmVUaENlbGwgPSBjb2wzO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgJ21vZGlmaWVkJzpcblx0XHRcdFx0YWN0aXZlVGhDZWxsID0gY29sNDtcblx0XHRcdFx0YnJlYWs7XG5cdFx0fVxuXHRcdGFjdGl2ZVRoQ2VsbC5jbGFzc0xpc3QuYWRkKCdzb3J0LWFjdGl2ZScpO1xuXHRcdGFjdGl2ZVRoQ2VsbC5jbGFzc0xpc3QuYWRkKHNvcnRPcmRlciA9PT0gJ2FzYycgPyAnc29ydC1hc2MnIDogJ3NvcnQtZGVzYycpO1xuXHR9XG5cblx0ZG5Tb3J0Q29sdW1uU3RyaW5nKHNvcnRDb2x1bW46IHN0cmluZywgc29ydE9yZGVyOiBzdHJpbmcsIHRvZ2dsZVNvcnRPcmRlcjogYm9vbGVhbikge1xuXHRcdGNvbnN0IHN1cHBvcnRlZENvbHVtbnMgPSBbJ25hbWUnLCAncGF0aCddO1xuXG5cdFx0aWYgKCFzdXBwb3J0ZWRDb2x1bW5zLmluY2x1ZGVzKHNvcnRDb2x1bW4pKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0aWYgKHRvZ2dsZVNvcnRPcmRlcikge1xuXHRcdFx0aWYgKHRoaXMuX3NvcnRfY29sdW1uID09PSBzb3J0Q29sdW1uKSB7XG5cdFx0XHRcdHNvcnRPcmRlciA9IHNvcnRPcmRlciA9PT0gJ2FzYycgPyAnZGVzYycgOiAnYXNjJztcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHRoaXMuX3NvcnRfY29sdW1uID0gc29ydENvbHVtbjtcblx0XHRcdFx0c29ydE9yZGVyID0gJ2Rlc2MnO1xuXHRcdFx0fVxuXHRcdFx0dGhpcy5fc29ydF9vcmRlciA9IHNvcnRPcmRlcjtcblx0XHR9XG5cblx0XHRjb25zdCBzb3J0VmFsdWUgPSBzb3J0Q29sdW1uICsgJy0nICsgdGhpcy5fc29ydF9vcmRlcjtcblxuXHRcdHRoaXMuZG5TZXRTZWxlY3RTb3J0VmFsdWUoc29ydFZhbHVlKTtcblxuXHRcdHRoaXMuX2ZpbHRlcmVkX2ZpbGVzLnNvcnQoKGZpbGVBOiBURmlsZSwgZmlsZUI6IFRGaWxlKSA9PiB7XG5cdFx0XHRsZXQgc29ydEE6IHN0cmluZztcblx0XHRcdGxldCBzb3J0Qjogc3RyaW5nO1xuXHRcdFx0c3dpdGNoIChzb3J0Q29sdW1uKSB7XG5cdFx0XHRcdGNhc2UgJ25hbWUnOlxuXHRcdFx0XHRcdHNvcnRBID0gZmlsZUEubmFtZS50b0xvd2VyQ2FzZSgpO1xuXHRcdFx0XHRcdHNvcnRCID0gZmlsZUIubmFtZS50b0xvd2VyQ2FzZSgpO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlICdwYXRoJzpcblx0XHRcdFx0XHRjb25zdCBmb2xkZXJTdHJ1Y3R1cmVBID0gZ2V0Rm9sZGVyU3RydWN0dXJlKGZpbGVBLnBhdGgpO1xuXHRcdFx0XHRcdGNvbnN0IGZvbGRlclN0cnVjdHVyZUIgPSBnZXRGb2xkZXJTdHJ1Y3R1cmUoZmlsZUIucGF0aCk7XG5cdFx0XHRcdFx0c29ydEEgPSBmb2xkZXJTdHJ1Y3R1cmVBLnRvTG93ZXJDYXNlKCk7XG5cdFx0XHRcdFx0c29ydEIgPSBmb2xkZXJTdHJ1Y3R1cmVCLnRvTG93ZXJDYXNlKCk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGRlZmF1bHQ6XG5cdFx0XHRcdFx0c29ydEEgPSBmaWxlQS5uYW1lLnRvTG93ZXJDYXNlKCk7XG5cdFx0XHRcdFx0c29ydEIgPSBmaWxlQi5uYW1lLnRvTG93ZXJDYXNlKCk7XG5cdFx0XHR9XG5cblx0XHRcdGlmIChzb3J0T3JkZXIgPT09ICdhc2MnKSB7XG5cdFx0XHRcdHJldHVybiBzb3J0QS5sb2NhbGVDb21wYXJlKHNvcnRCKTtcblx0XHRcdH0gZWxzZSBpZiAoc29ydE9yZGVyID09PSAnZGVzYycpIHtcblx0XHRcdFx0cmV0dXJuIHNvcnRCLmxvY2FsZUNvbXBhcmUoc29ydEEpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cmV0dXJuIHNvcnRBLmxvY2FsZUNvbXBhcmUoc29ydEIpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cblx0ZG5Tb3J0Q29sdW1uTnVtYmVyKHNvcnRDb2x1bW46IHN0cmluZywgc29ydE9yZGVyOiBzdHJpbmcsIHRvZ2dsZVNvcnRPcmRlcjogYm9vbGVhbikge1xuXHRcdGNvbnN0IHN1cHBvcnRlZENvbHVtbnMgPSBbJ3NpemUnLCAnbW9kaWZpZWQnXTtcblxuXHRcdGlmICghc3VwcG9ydGVkQ29sdW1ucy5pbmNsdWRlcyhzb3J0Q29sdW1uKSkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGlmICh0b2dnbGVTb3J0T3JkZXIpIHtcblx0XHRcdGlmICh0aGlzLl9zb3J0X2NvbHVtbiA9PT0gc29ydENvbHVtbikge1xuXHRcdFx0XHRzb3J0T3JkZXIgPSBzb3J0T3JkZXIgPT09ICdhc2MnID8gJ2Rlc2MnIDogJ2FzYyc7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLl9zb3J0X2NvbHVtbiA9IHNvcnRDb2x1bW47XG5cdFx0XHRcdHNvcnRPcmRlciA9ICdkZXNjJztcblx0XHRcdH1cblx0XHRcdHRoaXMuX3NvcnRfb3JkZXIgPSBzb3J0T3JkZXI7XG5cdFx0fVxuXG5cdFx0Y29uc3Qgc29ydFZhbHVlID0gc29ydENvbHVtbiArICctJyArIHRoaXMuX3NvcnRfb3JkZXI7XG5cblx0XHR0aGlzLmRuU2V0U2VsZWN0U29ydFZhbHVlKHNvcnRWYWx1ZSk7XG5cblx0XHR0aGlzLl9maWx0ZXJlZF9maWxlcy5zb3J0KChmaWxlQTogVEZpbGUsIGZpbGVCOiBURmlsZSkgPT4ge1xuXHRcdFx0bGV0IHNvcnRBOiBudW1iZXIgPSAwO1xuXHRcdFx0bGV0IHNvcnRCOiBudW1iZXIgPSAwO1xuXG5cdFx0XHRzd2l0Y2ggKHNvcnRDb2x1bW4pIHtcblx0XHRcdFx0Y2FzZSAnc2l6ZSc6XG5cdFx0XHRcdFx0c29ydEEgPSBmaWxlQS5zdGF0LnNpemU7XG5cdFx0XHRcdFx0c29ydEIgPSBmaWxlQi5zdGF0LnNpemU7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgJ21vZGlmaWVkJzpcblx0XHRcdFx0XHRzb3J0QSA9IGZpbGVBLnN0YXQubXRpbWU7XG5cdFx0XHRcdFx0c29ydEIgPSBmaWxlQi5zdGF0Lm10aW1lO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoc29ydE9yZGVyID09PSAnYXNjJykge1xuXHRcdFx0XHRyZXR1cm4gc29ydEEgLSBzb3J0Qjtcblx0XHRcdH0gZWxzZSBpZiAoc29ydE9yZGVyID09PSAnZGVzYycpIHtcblx0XHRcdFx0cmV0dXJuIHNvcnRCIC0gc29ydEE7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRyZXR1cm4gc29ydEEgLSBzb3J0Qjtcblx0XHRcdH1cblx0XHR9KTtcblx0fVxuXG5cblx0YXN5bmMgZG5HZXRSZWNlbnRGaWxlcyhmaWxlczogVEZpbGVbXSk6IFByb21pc2U8VEZpbGVbXT4ge1xuXHRcdGNvbnN0IGFyclJlY2VudEZpbGVzID0gZmlsZXM7XG5cdFx0cmV0dXJuIGFyclJlY2VudEZpbGVzLnNvcnQoKGEsIGIpID0+IGIuc3RhdC5tdGltZSAtIGEuc3RhdC5tdGltZSkuc2xpY2UoMCwgdGhpcy5udW1fcmVjZW50X2ZpbGVzKTtcblx0fVxuXG5cdGFzeW5jIGRuT3JnYW5pemVGaWxlcyh7IGFyciB9OiB7IGFycjogVEZpbGVbXSB9KTogUHJvbWlzZTx2b2lkPiB7XG5cdFx0Y29uc3QgYXJyTm90ZXM6IFRGaWxlW10gPSBbXTtcblx0XHRjb25zdCBhcnJJbWFnZXM6IFRGaWxlW10gPSBbXTtcblx0XHRjb25zdCBhcnJBdWRpb3M6IFRGaWxlW10gPSBbXTtcblx0XHRjb25zdCBhcnJDYW52YXM6IFRGaWxlW10gPSBbXTtcblx0XHRjb25zdCBhcnJWaWRlb3M6IFRGaWxlW10gPSBbXTtcblx0XHRjb25zdCBhcnJQREZzOiBURmlsZVtdID0gW107XG5cdFx0Y29uc3QgYXJyT3RoZXI6IFRGaWxlW10gPSBbXTtcblxuXHRcdC8vIGZvcm1hdHNcblx0XHRjb25zdCBleHRlbnNpb25zOiBSZWNvcmQ8c3RyaW5nLCBURmlsZVtdPiA9IHtcblx0XHRcdCdtZCc6IGFyck5vdGVzLFxuXHRcdFx0J3BuZyc6IGFyckltYWdlcyxcblx0XHRcdCdqcGcnOiBhcnJJbWFnZXMsXG5cdFx0XHQnd2VicCc6IGFyckltYWdlcyxcblx0XHRcdCdpY28nOiBhcnJJbWFnZXMsXG5cdFx0XHQnYm1wJzogYXJySW1hZ2VzLFxuXHRcdFx0J2dpZic6IGFyckltYWdlcyxcblx0XHRcdCd0aWYnOiBhcnJJbWFnZXMsXG5cdFx0XHQndGlmZic6IGFyckltYWdlcyxcblx0XHRcdCdyYXcnOiBhcnJJbWFnZXMsXG5cdFx0XHQnbXAzJzogYXJyQXVkaW9zLFxuXHRcdFx0J3dhdic6IGFyckF1ZGlvcyxcblx0XHRcdCdvZ2cnOiBhcnJBdWRpb3MsXG5cdFx0XHQnd2VibSc6IGFyckF1ZGlvcyxcblx0XHRcdCdtcDQnOiBhcnJWaWRlb3MsXG5cdFx0XHQnYXZpJzogYXJyVmlkZW9zLFxuXHRcdFx0J3BkZic6IGFyclBERnMsXG5cdFx0XHQnY2FudmFzJzogYXJyQ2FudmFzXG5cdFx0fTtcblxuXHRcdGZvciAobGV0IGkgPSAwLCBsZW4gPSBhcnIubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcblx0XHRcdGNvbnN0IGYgPSBhcnJbaV0uZXh0ZW5zaW9uLnRvTG93ZXJDYXNlKCk7XG5cdFx0XHRjb25zdCB0YXJnZXRBcnIgPSBleHRlbnNpb25zW2ZdO1xuXHRcdFx0aWYgKHRhcmdldEFycikge1xuXHRcdFx0XHR0YXJnZXRBcnIucHVzaChhcnJbaV0pO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0YXJyT3RoZXIucHVzaChhcnJbaV0pO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHRoaXMuX25vdGVzID0gYXJyTm90ZXM7XG5cdFx0dGhpcy5faW1hZ2VzID0gYXJySW1hZ2VzO1xuXHRcdHRoaXMuX2F1ZGlvcyA9IGFyckF1ZGlvcztcblx0XHR0aGlzLl92aWRlb3MgPSBhcnJWaWRlb3M7XG5cdFx0dGhpcy5fcGRmID0gYXJyUERGcztcblx0XHR0aGlzLl9jYW52YXMgPSBhcnJDYW52YXM7XG5cdFx0dGhpcy5fb3RoZXIgPSBhcnJPdGhlcjtcblx0fVxuXG5cdGRuU2V0RmlsZUljb25DbGFzcyhleHQ6IHN0cmluZykge1xuXHRcdGNvbnN0IGZpbGVfZXh0ZW5zaW9uID0gZXh0LnRvTG93ZXJDYXNlKCk7XG5cblx0XHRjb25zdCBleHRlbnNpb25zOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge1xuXHRcdFx0J21kJzogJ25vdGUnLFxuXHRcdFx0J3BuZyc6ICdpbWFnZScsXG5cdFx0XHQnanBnJzogJ2ltYWdlJyxcblx0XHRcdCd3ZWJwJzogJ2ltYWdlJyxcblx0XHRcdCdpY28nOiAnaW1hZ2UnLFxuXHRcdFx0J2JtcCc6ICdpbWFnZScsXG5cdFx0XHQnZ2lmJzogJ2ltYWdlJyxcblx0XHRcdCd0aWYnOiAnaW1hZ2UnLFxuXHRcdFx0J3RpZmYnOiAnaW1hZ2UnLFxuXHRcdFx0J3Jhdyc6ICdpbWFnZScsXG5cdFx0XHQnbXAzJzogJ2F1ZGlvJyxcblx0XHRcdCd3YXYnOiAnYXVkaW8nLFxuXHRcdFx0J29nZyc6ICdhdWRpbycsXG5cdFx0XHQnd2VibSc6ICdhdWRpbycsXG5cdFx0XHQnbXA0JzogJ3ZpZGVvJyxcblx0XHRcdCdhdmknOiAndmlkZW8nLFxuXHRcdFx0J3BkZic6ICdwZGYnLFxuXHRcdFx0J2NhbnZhcyc6ICdjYW52YXMnXG5cdFx0fTtcblxuXHRcdGlmIChmaWxlX2V4dGVuc2lvbiBpbiBleHRlbnNpb25zKSB7XG5cdFx0XHRyZXR1cm4gJ2RuLWYtJyArIGV4dGVuc2lvbnNbZmlsZV9leHRlbnNpb25dO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm4gJ2RuLWYtb3RoZXInO1xuXHRcdH1cblx0fVxuXG5cdGRuU2V0Vmlldyh2aWV3OiBudW1iZXIpOiB2b2lkIHtcblx0XHRjb25zdCBkaXZFbGVtZW50cyA9IFt0aGlzLl9WSUVXX0RBU0hCT0FSRCwgdGhpcy5fVklFV19OQVZJR0FUT1JdO1xuXHRcdGNvbnN0IHRvcE5hdkJ0bnMgPSBbdGhpcy5fQlROX0RBU0hCT0FSRCwgdGhpcy5fQlROX05BVklHQVRPUl07XG5cblx0XHRkaXZFbGVtZW50cy5mb3JFYWNoKGVsID0+IHtcblx0XHRcdGVsLmNsYXNzTGlzdC5hZGQoJ2RuLWRpc3BsYXktbm9uZScpO1xuXHRcdFx0ZWwuY2xhc3NMaXN0LnJlbW92ZSgnZG4tZmxleCcpO1xuXHRcdH0pO1xuXHRcdHRvcE5hdkJ0bnMuZm9yRWFjaChidG4gPT4gYnRuLmNsYXNzTGlzdC5yZW1vdmUoJ21vZC1jdGEnKSk7XG5cblx0XHRzd2l0Y2ggKHZpZXcpIHtcblx0XHRcdGNhc2UgMTpcblx0XHRcdFx0dGhpcy5fVklFV19EQVNIQk9BUkQuY2xhc3NMaXN0LnJlbW92ZSgnZG4tZGlzcGxheS1ub25lJyk7XG5cdFx0XHRcdHRoaXMuX1ZJRVdfREFTSEJPQVJELmNsYXNzTGlzdC5hZGQoJ2RuLWZsZXgnKTtcblx0XHRcdFx0dGhpcy5fQlROX0RBU0hCT0FSRC5jbGFzc0xpc3QuYWRkKCdtb2QtY3RhJyk7XG5cdFx0XHRcdHRoaXMuZG5IaWRlVG9wUmlnaHROYXYoKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlIDI6XG5cdFx0XHRcdHRoaXMuX1ZJRVdfTkFWSUdBVE9SLmNsYXNzTGlzdC5yZW1vdmUoJ2RuLWRpc3BsYXktbm9uZScpO1xuXHRcdFx0XHR0aGlzLl9WSUVXX05BVklHQVRPUi5jbGFzc0xpc3QuYWRkKCdkbi1mbGV4Jyk7XG5cdFx0XHRcdHRoaXMuX0JUTl9OQVZJR0FUT1IuY2xhc3NMaXN0LmFkZCgnbW9kLWN0YScpO1xuXHRcdFx0XHR0aGlzLmRuU2hvd1RvcFJpZ2h0TmF2KCk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0ZGVmYXVsdDpcblx0XHRcdFx0dGhpcy5fVklFV19EQVNIQk9BUkQuY2xhc3NMaXN0LnJlbW92ZSgnZG4tZGlzcGxheS1ub25lJyk7XG5cdFx0XHRcdHRoaXMuX1ZJRVdfREFTSEJPQVJELmNsYXNzTGlzdC5hZGQoJ2RuLWZsZXgnKTtcblx0XHRcdFx0dGhpcy5fQlROX0RBU0hCT0FSRC5jbGFzc0xpc3QuYWRkKCdtb2QtY3RhJyk7XG5cdFx0XHRcdHRoaXMuZG5IaWRlVG9wUmlnaHROYXYoKTtcblx0XHR9XG5cdH1cblxuXHRkblNob3dUb3BSaWdodE5hdigpOiB2b2lkIHtcblx0XHR0aGlzLl9TRUxFQ1RfU09SVC5jbGFzc0xpc3QucmVtb3ZlKCdkbi1kaXNwbGF5LW5vbmUnKTtcblx0XHR0aGlzLl9TRUxFQ1RfVEFCTEVfTEFZT1VULmNsYXNzTGlzdC5yZW1vdmUoJ2RuLWRpc3BsYXktbm9uZScpO1xuXHRcdHRoaXMubGFiZWxMYXlvdXQuY2xhc3NMaXN0LnJlbW92ZSgnZG4tZGlzcGxheS1ub25lJyk7XG5cdFx0dGhpcy5sYWJlbFNvcnQuY2xhc3NMaXN0LnJlbW92ZSgnZG4tZGlzcGxheS1ub25lJyk7XG5cdH1cblxuXHRkbkhpZGVUb3BSaWdodE5hdigpOiB2b2lkIHtcblx0XHR0aGlzLl9TRUxFQ1RfU09SVC5jbGFzc0xpc3QuYWRkKCdkbi1kaXNwbGF5LW5vbmUnKTtcblx0XHR0aGlzLl9TRUxFQ1RfVEFCTEVfTEFZT1VULmNsYXNzTGlzdC5hZGQoJ2RuLWRpc3BsYXktbm9uZScpO1xuXHRcdHRoaXMubGFiZWxMYXlvdXQuY2xhc3NMaXN0LmFkZCgnZG4tZGlzcGxheS1ub25lJyk7XG5cdFx0dGhpcy5sYWJlbFNvcnQuY2xhc3NMaXN0LmFkZCgnZG4tZGlzcGxheS1ub25lJyk7XG5cdH1cblxuXHRkblNldFNlbGVjdFNvcnRWYWx1ZSh2YWw6IHN0cmluZyk6IHZvaWQge1xuXHRcdGlmICh0aGlzLmRuSXNWYWxpZFNvcnQodmFsKSkge1xuXG5cdFx0XHR0aGlzLnNlbGVjdGVkX3NvcnRfdmFsdWUgPSB2YWw7XG5cdFx0XHR0aGlzLl9TRUxFQ1RfU09SVC52YWx1ZSA9IHRoaXMuc2VsZWN0ZWRfc29ydF92YWx1ZTtcblx0XHR9XG5cdH1cblxuXHRkblNldFNlbGVjdExheW91dFZhbHVlKHZhbDogc3RyaW5nKTogdm9pZCB7XG5cdFx0aWYgKHRoaXMuZG5Jc1ZhbGlkTGF5b3V0KHZhbCkpIHtcblxuXHRcdFx0dGhpcy5fU0VMRUNUX1RBQkxFX0xBWU9VVC52YWx1ZSA9IHZhbDtcblx0XHRcdHRoaXMuZG5TZWxlY3RUYWJsZUxheW91dCgpO1xuXHRcdH1cblx0fVxuXG5cdGRuT3BlbkZpbGVBbHQoZjogVEZpbGUsIGV2dDogTW91c2VFdmVudCkge1xuXHRcdGlmICghZXZ0IHx8IHR5cGVvZiBldnQgIT09ICdvYmplY3QnIHx8ICEoZiBpbnN0YW5jZW9mIFRGaWxlKSkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdHRyeSB7XG5cdFx0XHRpZiAoKGV2dC5idXR0b24gPT09IDApICYmIChldnQuY3RybEtleSB8fCBldnQubWV0YUtleSkpIHtcblx0XHRcdFx0dGhpcy5hcHAud29ya3NwYWNlLmdldExlYWYoJ3RhYicpLm9wZW5GaWxlKGYpO1xuXHRcdFx0fSBlbHNlIGlmIChldnQuYnV0dG9uID09PSAxKSB7XG5cdFx0XHRcdHRoaXMuYXBwLndvcmtzcGFjZS5nZXRMZWFmKCd0YWInKS5vcGVuRmlsZShmKTtcblxuXHRcdFx0fSBlbHNlIGlmIChldnQuYnV0dG9uID09PSAwKSB7XG5cdFx0XHRcdHRoaXMuZG5PcGVuRmlsZShmKTtcblx0XHRcdH0gZWxzZSBpZiAoZXZ0LmJ1dHRvbiA9PT0gMiAmJiAhKGV2dC50YXJnZXQgaW5zdGFuY2VvZiBIVE1MVGFibGVDZWxsRWxlbWVudCkpIHtcblx0XHRcdFx0ZXZ0LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRcdHRoaXMuZG5HZW5lcmF0ZUNvbnRleHRNZW51KGV2dCwgZik7XG5cdFx0XHR9XG5cdFx0fSBjYXRjaCAoZXIpIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdH1cblxuXHRkbk9wZW5GaWxlKGZpbGU6IFRGaWxlKSB7XG5cdFx0dGhpcy5hcHAud29ya3NwYWNlLmdldExlYWYoZmFsc2UpLm9wZW5GaWxlKGZpbGUpO1xuXHRcdHRoaXMuY2xvc2UoKTtcblx0fVxuXG5cdHByaXZhdGUgZG5IYW5kbGVDbGljayhldnQ6IE1vdXNlRXZlbnQsIGZpbGU/OiBURmlsZSkge1xuXHRcdGlmICghZXZ0IHx8IHR5cGVvZiBldnQgIT09ICdvYmplY3QnIHx8ICEoZmlsZSBpbnN0YW5jZW9mIFRGaWxlKSkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdHRoaXMuZG5TZWxlY3RUYWJsZVJvdyhldnQpO1xuXHRcdGlmIChldnQuYnV0dG9uID09PSAyKSB7XG5cdFx0XHRldnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdHRoaXMuZG5HZW5lcmF0ZUNvbnRleHRNZW51KGV2dCwgZmlsZSk7XG5cdFx0fVxuXHR9XG5cblx0cHJpdmF0ZSBkbkhhbmRsZURibENsaWNrKGV2dDogTW91c2VFdmVudCwgZmlsZT86IFRGaWxlKSB7XG5cdFx0aWYgKCFldnQgfHwgdHlwZW9mIGV2dCAhPT0gJ29iamVjdCcgfHwgIShmaWxlIGluc3RhbmNlb2YgVEZpbGUpKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0ZXZ0LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0dGhpcy5kblNlbGVjdFRhYmxlUm93KGV2dCk7XG5cdFx0dGhpcy5kbk9wZW5GaWxlKGZpbGUpO1xuXHR9XG5cblx0ZG5TZWxlY3RUYWJsZUxheW91dCgpOiB2b2lkIHtcblx0XHRjb25zdCB2YWwgPSB0aGlzLl9TRUxFQ1RfVEFCTEVfTEFZT1VULnZhbHVlO1xuXG5cdFx0aWYgKHRoaXMuX1RBQkxFX0xBWU9VVFMuaW5jbHVkZXModmFsKSkge1xuXHRcdFx0Y29uc3QgdGJsID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2RuLXRhYmxlJyk7XG5cdFx0XHR0aGlzLl9UQUJMRV9MQVlPVVRTLmZvckVhY2gobGF5b3V0ID0+IHRibD8uY2xhc3NMaXN0LnJlbW92ZShsYXlvdXQpKTtcblx0XHRcdHRibD8uY2xhc3NMaXN0LmFkZCh2YWwpO1xuXHRcdFx0dGhpcy5zZWxlY3RlZF90YWJsZV9sYXlvdXQgPSB2YWw7XG5cdFx0fVxuXHR9XG5cblx0cHJpdmF0ZSBkblNlbGVjdFRhYmxlUm93KGV2dDogTW91c2VFdmVudCkge1xuXHRcdGlmICghZXZ0IHx8IHR5cGVvZiBldnQgIT09ICdvYmplY3QnKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdGlmIChldnQudGFyZ2V0IGluc3RhbmNlb2YgSFRNTFRhYmxlQ2VsbEVsZW1lbnQpIHtcblx0XHRcdGNvbnN0IGFsbFRyID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnI2RuLXRhYmxlIHRyJyk7XG5cdFx0XHRhbGxUci5mb3JFYWNoKHJvdyA9PiByb3cuY2xhc3NMaXN0LnJlbW92ZSgndGJsLXNlbGVjdGVkJykpO1xuXHRcdFx0Y29uc3QgY2xpY2tlZFRyID0gZXZ0LnRhcmdldC5wYXJlbnRFbGVtZW50IGFzIEhUTUxUYWJsZVJvd0VsZW1lbnQ7XG5cdFx0XHRjbGlja2VkVHIuY2xhc3NMaXN0LmFkZCgndGJsLXNlbGVjdGVkJyk7XG5cdFx0fVxuXHR9XG5cblx0cHJpdmF0ZSBkbkdlbmVyYXRlQ29udGV4dE1lbnUoZXZ0OiBNb3VzZUV2ZW50LCBmaWxlOiBURmlsZSkge1xuXHRcdHRoaXMuX0ROX0NUWF9NRU5VID0gbmV3IE1lbnUoKTtcblxuXHRcdHRoaXMuX0ROX0NUWF9NRU5VLmFkZEl0ZW0oKGl0ZW0pID0+XG5cdFx0XHRpdGVtXG5cdFx0XHRcdC5zZXRUaXRsZSgnT3BlbicpXG5cdFx0XHRcdC5zZXRJY29uKCdtb3VzZS1wb2ludGVyLTInKVxuXHRcdFx0XHQub25DbGljaygoKSA9PiB7XG5cdFx0XHRcdFx0dGhpcy5hcHAud29ya3NwYWNlLmdldExlYWYoZmFsc2UpLm9wZW5GaWxlKGZpbGUpO1xuXHRcdFx0XHRcdHRoaXMuY2xvc2UoKTtcblx0XHRcdFx0fSlcblx0XHQpO1xuXG5cdFx0dGhpcy5fRE5fQ1RYX01FTlUuYWRkU2VwYXJhdG9yKCk7XG5cblx0XHR0aGlzLl9ETl9DVFhfTUVOVS5hZGRJdGVtKChpdGVtKSA9PlxuXHRcdFx0aXRlbVxuXHRcdFx0XHQuc2V0VGl0bGUoJ09wZW4gaW4gbmV3IHRhYicpXG5cdFx0XHRcdC5zZXRJY29uKCdmaWxlLXBsdXMnKVxuXHRcdFx0XHQub25DbGljaygoKSA9PiB7XG5cdFx0XHRcdFx0dGhpcy5hcHAud29ya3NwYWNlLmdldExlYWYoJ3RhYicpLm9wZW5GaWxlKGZpbGUpO1xuXHRcdFx0XHRcdHRoaXMuY2xvc2UoKTtcblx0XHRcdFx0fSlcblx0XHQpO1xuXG5cdFx0dGhpcy5fRE5fQ1RYX01FTlUuYWRkSXRlbSgoaXRlbSkgPT5cblx0XHRcdGl0ZW1cblx0XHRcdFx0LnNldFRpdGxlKCdPcGVuIHRvIHRoZSByaWdodCcpXG5cdFx0XHRcdC5zZXRJY29uKCdzZXBhcmF0b3ItdmVydGljYWwnKVxuXHRcdFx0XHQub25DbGljaygoKSA9PiB7XG5cdFx0XHRcdFx0dGhpcy5hcHAud29ya3NwYWNlLmdldExlYWYoJ3NwbGl0Jykub3BlbkZpbGUoZmlsZSk7XG5cdFx0XHRcdFx0dGhpcy5jbG9zZSgpO1xuXHRcdFx0XHR9KVxuXHRcdCk7XG5cblx0XHR0aGlzLl9ETl9DVFhfTUVOVS5hZGRJdGVtKChpdGVtKSA9PlxuXHRcdFx0aXRlbVxuXHRcdFx0XHQuc2V0VGl0bGUoJ09wZW4gaW4gbmV3IHdpbmRvdycpXG5cdFx0XHRcdC5zZXRJY29uKCdwaWN0dXJlLWluLXBpY3R1cmUtMicpXG5cdFx0XHRcdC5vbkNsaWNrKCgpID0+IHtcblx0XHRcdFx0XHR0aGlzLmFwcC53b3Jrc3BhY2UuZ2V0TGVhZignd2luZG93Jykub3BlbkZpbGUoZmlsZSk7XG5cdFx0XHRcdH0pXG5cdFx0KTtcblxuXHRcdHRoaXMuX0ROX0NUWF9NRU5VLmFkZFNlcGFyYXRvcigpO1xuXG5cdFx0dGhpcy5fRE5fQ1RYX01FTlUuYWRkSXRlbSgoaXRlbSkgPT5cblx0XHRcdGl0ZW1cblx0XHRcdFx0LnNldFRpdGxlKCdGaWxlIHByb3BlcnRpZXMnKVxuXHRcdFx0XHQuc2V0SWNvbignZmlsZS1jb2cnKVxuXHRcdFx0XHQub25DbGljaygoKSA9PiB7XG5cdFx0XHRcdFx0Y29uc3QgbWRGaWxlUHJvcHMgPSBuZXcgTW9kYWwodGhpcy5hcHApO1xuXHRcdFx0XHRcdG1kRmlsZVByb3BzLmNvbnRlbnRFbC5jcmVhdGVFbCgnaDQnLCB7IHRleHQ6ICdQcm9wZXJ0aWVzJyB9KTtcblxuXHRcdFx0XHRcdGNvbnN0IHByb3BGaWxlTmFtZSA9IG1kRmlsZVByb3BzLmNvbnRlbnRFbC5jcmVhdGVFbCgnZGl2Jyk7XG5cdFx0XHRcdFx0cHJvcEZpbGVOYW1lLmNyZWF0ZUVsKCdzcGFuJywgeyB0ZXh0OiAnRmlsZSBuYW1lOiAnLCBjbHM6ICdkbi1wcm9wZXJ0aWVzJyB9KTtcblx0XHRcdFx0XHRwcm9wRmlsZU5hbWUuY3JlYXRlRWwoJ3NwYW4nLCB7IHRleHQ6IGZpbGUuYmFzZW5hbWUgfSk7XG5cdFx0XHRcdFx0bWRGaWxlUHJvcHMuY29udGVudEVsLmNyZWF0ZUVsKCdicicpO1xuXG5cdFx0XHRcdFx0Y29uc3QgcHJvcEZpbGVFeHQgPSBtZEZpbGVQcm9wcy5jb250ZW50RWwuY3JlYXRlRWwoJ2RpdicpO1xuXHRcdFx0XHRcdHByb3BGaWxlRXh0LmNyZWF0ZUVsKCdzcGFuJywgeyB0ZXh0OiAnRXh0ZW5zaW9uOiAnLCBjbHM6ICdkbi1wcm9wZXJ0aWVzJyB9KTtcblx0XHRcdFx0XHRwcm9wRmlsZUV4dC5jcmVhdGVFbCgnc3BhbicsIHsgdGV4dDogZmlsZS5leHRlbnNpb24sIGNsczogJ25hdi1maWxlLXRhZycgfSk7XG5cdFx0XHRcdFx0bWRGaWxlUHJvcHMuY29udGVudEVsLmNyZWF0ZUVsKCdicicpO1xuXG5cdFx0XHRcdFx0Y29uc3QgcHJvcEZpbGVQYXRoID0gbWRGaWxlUHJvcHMuY29udGVudEVsLmNyZWF0ZUVsKCdkaXYnKTtcblx0XHRcdFx0XHRwcm9wRmlsZVBhdGguY3JlYXRlRWwoJ3NwYW4nLCB7IHRleHQ6ICdQYXRoOiAnLCBjbHM6ICdkbi1wcm9wZXJ0aWVzJyB9KTtcblx0XHRcdFx0XHRwcm9wRmlsZVBhdGguY3JlYXRlRWwoJ3NwYW4nLCB7IHRleHQ6IGdldEZvbGRlclN0cnVjdHVyZShmaWxlLnBhdGgpIH0pO1xuXHRcdFx0XHRcdG1kRmlsZVByb3BzLmNvbnRlbnRFbC5jcmVhdGVFbCgnYnInKTtcblxuXHRcdFx0XHRcdGNvbnN0IHByb3BGaWxlU2l6ZSA9IG1kRmlsZVByb3BzLmNvbnRlbnRFbC5jcmVhdGVFbCgnZGl2Jyk7XG5cdFx0XHRcdFx0cHJvcEZpbGVTaXplLmNyZWF0ZUVsKCdzcGFuJywgeyB0ZXh0OiAnU2l6ZTogJywgY2xzOiAnZG4tcHJvcGVydGllcycgfSk7XG5cdFx0XHRcdFx0cHJvcEZpbGVTaXplLmNyZWF0ZUVsKCdzcGFuJywgeyB0ZXh0OiBmb3JtYXRGaWxlU2l6ZShmaWxlLnN0YXQuc2l6ZSkgKyAnIGJ5dGVzJyB9KTtcblx0XHRcdFx0XHRtZEZpbGVQcm9wcy5jb250ZW50RWwuY3JlYXRlRWwoJ2JyJyk7XG5cblx0XHRcdFx0XHRjb25zdCBwcm9wRGF0ZUNyZWF0ZWQgPSBtZEZpbGVQcm9wcy5jb250ZW50RWwuY3JlYXRlRWwoJ2RpdicpO1xuXHRcdFx0XHRcdHByb3BEYXRlQ3JlYXRlZC5jcmVhdGVFbCgnc3BhbicsIHsgdGV4dDogJ0NyZWF0ZWQ6ICcsIGNsczogJ2RuLXByb3BlcnRpZXMnIH0pO1xuXHRcdFx0XHRcdHByb3BEYXRlQ3JlYXRlZC5jcmVhdGVFbCgnc3BhbicsIHsgdGV4dDogbW9tZW50KGZpbGUuc3RhdC5jdGltZSkuZm9ybWF0KHRoaXMuZGF0ZV9mb3JtYXQpIH0pO1xuXHRcdFx0XHRcdG1kRmlsZVByb3BzLmNvbnRlbnRFbC5jcmVhdGVFbCgnYnInKTtcblxuXHRcdFx0XHRcdGNvbnN0IHByb3BEYXRlTW9kaWZpZWQgPSBtZEZpbGVQcm9wcy5jb250ZW50RWwuY3JlYXRlRWwoJ2RpdicpO1xuXHRcdFx0XHRcdHByb3BEYXRlTW9kaWZpZWQuY3JlYXRlRWwoJ3NwYW4nLCB7IHRleHQ6ICdNb2RpZmllZDogJywgY2xzOiAnZG4tcHJvcGVydGllcycgfSk7XG5cdFx0XHRcdFx0cHJvcERhdGVNb2RpZmllZC5jcmVhdGVFbCgnc3BhbicsIHsgdGV4dDogbW9tZW50KGZpbGUuc3RhdC5tdGltZSkuZm9ybWF0KHRoaXMuZGF0ZV9mb3JtYXQpIH0pO1xuXHRcdFx0XHRcdG1kRmlsZVByb3BzLmNvbnRlbnRFbC5jcmVhdGVFbCgnYnInKTtcblxuXHRcdFx0XHRcdGNvbnN0IHByb3BUYWdzID0gbWRGaWxlUHJvcHMuY29udGVudEVsLmNyZWF0ZUVsKCdkaXYnKTtcblx0XHRcdFx0XHRjb25zdCBjdXJUYWdzID0gdGhpcy5kbkdldFRhZ3NQZXJGaWxlKGZpbGUpO1xuXHRcdFx0XHRcdHByb3BUYWdzLmNyZWF0ZUVsKCdzcGFuJywgeyB0ZXh0OiAnVGFnKHMpOiAnLCBjbHM6ICdkbi1wcm9wZXJ0aWVzJyB9KTtcblx0XHRcdFx0XHRpZiAoY3VyVGFncykge1xuXHRcdFx0XHRcdFx0Y29uc3QgdGFncyA9IGN1clRhZ3Muc3BsaXQoJyAnKTtcblx0XHRcdFx0XHRcdGZvciAobGV0IGkgPSAwLCBsZW4gPSB0YWdzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG5cdFx0XHRcdFx0XHRcdHByb3BUYWdzLmNyZWF0ZUVsKCdhJywgeyB0ZXh0OiB0YWdzW2ldLCBjbHM6ICdkbi10YWcnIH0pLm9uQ2xpY2tFdmVudCgoZXZ0OiBNb3VzZUV2ZW50KSA9PiB7XG5cdFx0XHRcdFx0XHRcdFx0bWRGaWxlUHJvcHMuY2xvc2UoKTtcblx0XHRcdFx0XHRcdFx0XHR0aGlzLl9JTlBVVF9TRUFSQ0gudmFsdWUgPSB0YWdzW2ldO1xuXHRcdFx0XHRcdFx0XHRcdHRoaXMuZG5TZWFyY2hWYXVsdCh0aGlzLl9JTlBVVF9TRUFSQ0gudmFsdWUpO1xuXHRcdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHRcdH07XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdHByb3BUYWdzLmNyZWF0ZUVsKCdzcGFuJywgeyB0ZXh0OiAnTm8gdGFncycgfSk7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0bWRGaWxlUHJvcHMuY29udGVudEVsLmNyZWF0ZUVsKCdicicpO1xuXG5cblxuXHRcdFx0XHRcdG1kRmlsZVByb3BzLmNvbnRlbnRFbC5jcmVhdGVFbCgnaHInKTtcblxuXHRcdFx0XHRcdGNvbnN0IGRpdkJvdHRvbSA9IG1kRmlsZVByb3BzLmNvbnRlbnRFbC5jcmVhdGVFbCgnZGl2JywgeyBjbHM6ICdkbi1kaXYtYm90dG9tLXByb3BlcnRpZXMnIH0pO1xuXHRcdFx0XHRcdGNvbnN0IGJ0bkNsb3NlUHJvcHMgPSBkaXZCb3R0b20uY3JlYXRlRWwoJ2J1dHRvbicsIHsgdGV4dDogJ09rJywgY2xzOiAnZG4tYnRuLWNsb3NlLXByb3BlcnRpZXMnIH0pO1xuXHRcdFx0XHRcdGJ0bkNsb3NlUHJvcHMub25DbGlja0V2ZW50KCgpID0+IHtcblx0XHRcdFx0XHRcdG1kRmlsZVByb3BzLmNsb3NlKCk7XG5cdFx0XHRcdFx0fSk7XG5cblx0XHRcdFx0XHRtZEZpbGVQcm9wcy5vcGVuKCk7XG5cdFx0XHRcdH0pXG5cdFx0KTtcblxuXHRcdHRoaXMuX0ROX0NUWF9NRU5VLnNob3dBdE1vdXNlRXZlbnQoZXZ0KTtcblx0fVxuXG5cdHByaXZhdGUgZG5IYW5kbGVJbnRlcnNlY3Rpb24gPSAoZW50cmllczogSW50ZXJzZWN0aW9uT2JzZXJ2ZXJFbnRyeVtdKSA9PiB7XG5cdFx0ZW50cmllcy5mb3JFYWNoKGVudHJ5ID0+IHtcblx0XHRcdGlmICghZW50cnkuaXNJbnRlcnNlY3RpbmcpIHtcblx0XHRcdFx0ZW50cnkudGFyZ2V0LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NvbnRleHRtZW51JywgdGhpcy5kbkhhbmRsZUNsaWNrKTtcblx0XHRcdFx0ZW50cnkudGFyZ2V0LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgdGhpcy5kbkhhbmRsZUNsaWNrKTtcblx0XHRcdFx0ZW50cnkudGFyZ2V0LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2RibGNsaWNrJywgdGhpcy5kbkhhbmRsZURibENsaWNrKTtcblx0XHRcdH1cblx0XHR9KTtcblx0fVxuXG5cdG9uQ2xvc2UoKSB7XG5cdFx0Y29uc3QgeyBjb250ZW50RWwgfSA9IHRoaXM7XG5cdFx0Y29udGVudEVsLmVtcHR5KCk7XG5cblx0XHRpZiAodGhpcy5fSU5QVVRfU0VBUkNIICYmIHRoaXMuX0lOUFVUX1NFQVJDSC5yZW1vdmVFdmVudExpc3RlbmVyKSB7XG5cdFx0XHR0aGlzLl9JTlBVVF9TRUFSQ0gucmVtb3ZlRXZlbnRMaXN0ZW5lcignaW5wdXQnLCBkZWJvdW5jZSgoKSA9PiB0aGlzLmRuU2VhcmNoVmF1bHQodGhpcy5fSU5QVVRfU0VBUkNILnZhbHVlKSwgMzAwLCB0cnVlKSk7XG5cdFx0fVxuXHRcdHRoaXMuX3RoMS5yZW1vdmVFdmVudExpc3RlbmVyKCdkYmxjbGljaycsICgpID0+IHRoaXMuZG5BbHRlcm5hdGVTb3J0Q29sdW1uKCduYW1lJykpO1xuXHRcdHRoaXMuX3RoMi5yZW1vdmVFdmVudExpc3RlbmVyKCdkYmxjbGljaycsICgpID0+IHRoaXMuZG5BbHRlcm5hdGVTb3J0Q29sdW1uKCdwYXRoJykpO1xuXHRcdHRoaXMuX3RoMy5yZW1vdmVFdmVudExpc3RlbmVyKCdkYmxjbGljaycsICgpID0+IHRoaXMuZG5BbHRlcm5hdGVTb3J0Q29sdW1uKCdzaXplJykpO1xuXHRcdHRoaXMuX3RoNC5yZW1vdmVFdmVudExpc3RlbmVyKCdkYmxjbGljaycsICgpID0+IHRoaXMuZG5BbHRlcm5hdGVTb3J0Q29sdW1uKCdtb2RpZmllZCcpKTtcblx0XHR0aGlzLl9TRUxFQ1RfU09SVC5yZW1vdmVFdmVudExpc3RlbmVyKCdjaGFuZ2UnLCAoKSA9PiB7IHRoaXMuZG5Tb3J0Q29sdW1uV2l0aFNlbGVjdCgpOyB9KTtcblxuXHRcdGlmICh0aGlzLmludGVyc2VjdGlvbk9ic2VydmVyKSB7XG5cdFx0XHR0aGlzLmludGVyc2VjdGlvbk9ic2VydmVyLmRpc2Nvbm5lY3QoKTtcblx0XHR9XG5cdH1cbn1cbiIsICJleHBvcnQgZnVuY3Rpb24gZm9ybWF0RmlsZVNpemUoZmlsZVNpemU6IG51bWJlcik6IHN0cmluZyB7XG5cdGlmIChmaWxlU2l6ZSA9PT0gMCkge1xuXHRcdHJldHVybiBcIjBcIjtcblx0fVxuXHRjb25zdCBmb3JtYXR0ZWRTaXplID0gZmlsZVNpemUudG9GaXhlZCgwKS5yZXBsYWNlKC9cXEIoPz0oXFxkezN9KSsoPyFcXGQpKS9nLCBcIixcIik7XG5cblx0cmV0dXJuIGZvcm1hdHRlZFNpemU7XG59XG5cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEZvbGRlclN0cnVjdHVyZShmb2xkZXI6IHN0cmluZyk6IHN0cmluZyB7XG5cdGNvbnN0IGZvbGRlcnMgPSBmb2xkZXIuc3BsaXQoXCIvXCIpLnNsaWNlKDAsIC0xKTtcblx0aWYgKGZvbGRlcnMubGVuZ3RoID09PSAwKSB7XG5cdFx0cmV0dXJuIFwiL1wiO1xuXHR9XG5cblx0cmV0dXJuIFwiL1wiICsgZm9sZGVycy5qb2luKFwiL1wiKTtcbn0iLCAiZXhwb3J0IGNsYXNzIEROUGllQ2hhcnQge1xuXHRwcml2YXRlIF9jYW52YXM6IEhUTUxDYW52YXNFbGVtZW50O1xuXHRwcml2YXRlIF9jdHg6IENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRDtcblx0cHJpdmF0ZSBfZGF0YTogeyB2YWx1ZTogbnVtYmVyOyBjb2xvcjogc3RyaW5nOyBsYWJlbDogc3RyaW5nIH1bXTtcblx0cHJpdmF0ZSBfbWFyZ2luOiBudW1iZXI7XG5cdHByaXZhdGUgX2ZvbnRTaXplOiBudW1iZXI7XG5cdHByaXZhdGUgX2xlZ2VuZFdpZHRoOiBudW1iZXI7XG5cdHByaXZhdGUgX2xhYmVsQ29sb3I6IHN0cmluZztcblx0cHJpdmF0ZSBfY1g6IG51bWJlcjtcblx0cHJpdmF0ZSBfY1k6IG51bWJlcjtcblxuXHRjb25zdHJ1Y3RvcihjYW52YXM6IEhUTUxDYW52YXNFbGVtZW50LCBtYXJnaW4gPSAxMCwgZm9udFNpemUgPSAxMiwgbGVnZW5kV2lkdGggPSA1MCwgbGFiZWxDb2xvcjogc3RyaW5nID0gXCIjODI4MjgyXCIpIHtcblx0XHR0aGlzLl9jYW52YXMgPSBjYW52YXM7XG5cdFx0dGhpcy5fY3R4ID0gY2FudmFzLmdldENvbnRleHQoJzJkJykhO1xuXHRcdHRoaXMuX2RhdGEgPSBbXTtcblx0XHR0aGlzLl9tYXJnaW4gPSBtYXJnaW47XG5cdFx0dGhpcy5fZm9udFNpemUgPSBmb250U2l6ZTtcblx0XHR0aGlzLl9sZWdlbmRXaWR0aCA9IGxlZ2VuZFdpZHRoO1xuXHRcdHRoaXMuX2xhYmVsQ29sb3IgPSBsYWJlbENvbG9yO1xuXHR9XG5cblx0YWRkRGF0YSh2YWx1ZTogbnVtYmVyLCBjb2xvcjogc3RyaW5nLCBsYWJlbDogc3RyaW5nKTogdm9pZCB7XG5cdFx0dGhpcy5fZGF0YS5wdXNoKHsgdmFsdWUsIGNvbG9yLCBsYWJlbCB9KTtcblx0fVxuXG5cdGRyYXcoKTogdm9pZCB7XG5cdFx0Y29uc3QgeyB3aWR0aCwgaGVpZ2h0IH0gPSB0aGlzLl9jYW52YXM7XG5cdFx0Y29uc3QgYXZhaWxXaWR0aCA9IHdpZHRoIC0gMiAqIHRoaXMuX21hcmdpbjtcblx0XHRjb25zdCBhdmFpbEhlaWdodCA9IGhlaWdodCAtIDIgKiB0aGlzLl9tYXJnaW47XG5cblx0XHRjb25zdCBzY2FsZSA9IE1hdGgubWluKGF2YWlsV2lkdGggLyB3aWR0aCwgYXZhaWxIZWlnaHQgLyBoZWlnaHQpO1xuXHRcdGNvbnN0IHJhZGl1cyA9IE1hdGgubWluKGF2YWlsV2lkdGgsIGF2YWlsSGVpZ2h0KSAvIDIgKiBzY2FsZTtcblxuXHRcdC8vIENlbnRlciBjb29yZGluYXRlc1xuXHRcdHRoaXMuX2NYID0gd2lkdGggLyAyO1xuXHRcdHRoaXMuX2NZID0gaGVpZ2h0IC8gMjtcblxuXHRcdHRoaXMuX2N0eC5jbGVhclJlY3QoMCwgMCwgd2lkdGgsIGhlaWdodCk7XG5cblx0XHRjb25zdCB0b3RhbFZhbHVlID0gdGhpcy5fZGF0YS5yZWR1Y2UoKGFjYywgY3VycikgPT4gYWNjICsgY3Vyci52YWx1ZSwgMCk7XG5cdFx0bGV0IGN1cnJlbnRBbmdsZSA9IC1NYXRoLlBJIC8gMjtcblx0XHR0aGlzLl9kYXRhLmZvckVhY2goKHNsaWNlKSA9PiB7XG5cdFx0XHRjb25zdCBzbGljZUFuZ2xlID0gKHNsaWNlLnZhbHVlIC8gdG90YWxWYWx1ZSkgKiAyICogTWF0aC5QSTtcblx0XHRcdHRoaXMuZHJhd1NsaWNlKHJhZGl1cywgc2xpY2VBbmdsZSwgc2xpY2UuY29sb3IsIGN1cnJlbnRBbmdsZSk7XG5cdFx0XHRjdXJyZW50QW5nbGUgKz0gc2xpY2VBbmdsZTtcblx0XHR9KTtcblxuXHRcdHRoaXMuZHJhd0xlZ2VuZCgyLCAyMCk7XG5cdH1cblxuXHRwcml2YXRlIGRyYXdTbGljZShyYWRpdXM6IG51bWJlciwgc2xpY2VBbmdsZTogbnVtYmVyLCBjb2xvcjogc3RyaW5nLCBzdGFydEFuZ2xlOiBudW1iZXIpOiB2b2lkIHtcblx0XHR0aGlzLl9jdHguYmVnaW5QYXRoKCk7XG5cdFx0dGhpcy5fY3R4LmFyYyh0aGlzLl9jWCwgdGhpcy5fY1ksIHJhZGl1cywgc3RhcnRBbmdsZSwgc3RhcnRBbmdsZSArIHNsaWNlQW5nbGUpO1xuXHRcdHRoaXMuX2N0eC5saW5lVG8odGhpcy5fY1gsIHRoaXMuX2NZKTtcblx0XHR0aGlzLl9jdHguZmlsbFN0eWxlID0gY29sb3I7XG5cdFx0dGhpcy5fY3R4LmNsb3NlUGF0aCgpO1xuXHRcdHRoaXMuX2N0eC5maWxsKCk7XG5cdH1cblxuXHRwcml2YXRlIGRyYXdMZWdlbmQoeDogbnVtYmVyLCB5OiBudW1iZXIpOiB2b2lkIHtcblx0XHRjb25zdCBsaW5lSGVpZ2h0ID0gdGhpcy5fZm9udFNpemUgKyA1O1xuXG5cdFx0dGhpcy5fZGF0YS5mb3JFYWNoKChzbGljZSwgaW5kZXgpID0+IHtcblx0XHRcdGNvbnN0IHRleHRYID0geCArIHRoaXMuX2xlZ2VuZFdpZHRoIC8gNTtcblx0XHRcdGNvbnN0IHRleHRZID0geSArIGluZGV4ICogbGluZUhlaWdodCAtIDEwO1xuXG5cdFx0XHQvLyBEcmF3IGxlZ2VuZCBzcXVhcmVcblx0XHRcdHRoaXMuX2N0eC5maWxsU3R5bGUgPSBzbGljZS5jb2xvcjtcblx0XHRcdHRoaXMuX2N0eC5maWxsUmVjdCh0ZXh0WCAtIDEwLCB0ZXh0WSwgNSwgNSk7XG5cblx0XHRcdC8vIERyYXcgbGFiZWxcblx0XHRcdHRoaXMuX2N0eC5maWxsU3R5bGUgPSB0aGlzLl9sYWJlbENvbG9yO1xuXHRcdFx0dGhpcy5fY3R4LmZvbnQgPSBgJHt0aGlzLl9mb250U2l6ZX1weCBzYW5zLXNlcmlmYDtcblx0XHRcdHRoaXMuX2N0eC5maWxsVGV4dChgJHtzbGljZS5sYWJlbH0gKCR7c2xpY2UudmFsdWV9KWAsIHRleHRYLCB0ZXh0WSArIDgpO1xuXHRcdH0pO1xuXHR9XG59XG4iXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxJQUFBQSxtQkFBdUI7OztBQ0F2QixzQkFBbUk7QUFJNUgsSUFBTSxlQUFOLGNBQTJCLGlDQUFpQjtBQUFBLEVBb0IvQyxZQUFZLEtBQVUsUUFBa0I7QUFDcEMsVUFBTSxLQUFLLE1BQU07QUFDakIsU0FBSyxTQUFTO0FBQUEsRUFDbEI7QUFBQSxFQUVBLFVBQWdCO0FBQ1osVUFBTSxFQUFFLFlBQVksSUFBSTtBQUV4QixnQkFBWSxNQUFNO0FBRWxCLFFBQUksd0JBQVEsV0FBVyxFQUNsQixRQUFRLDBCQUEwQixFQUNsQyxVQUFVLENBQUMsUUFBUTtBQUNoQixVQUFJLGNBQWMsTUFBTSxFQUNuQixXQUFXLDBCQUEwQixFQUNyQyxRQUFRLENBQUMsUUFBb0I7QUFDMUIsYUFBSyxPQUFPLFVBQVUsS0FBSztBQUFBLE1BQy9CLENBQUM7QUFBQSxJQUNULENBQUM7QUFHTCxRQUFJLHdCQUFRLFdBQVcsRUFDbEIsUUFBUSxjQUFjLEVBQ3RCLFFBQVEsaUNBQWlDLEVBQ3pDLFlBQVksU0FBTztBQUNoQixXQUFLLHNCQUFzQjtBQUMzQixVQUFJLFVBQVUsS0FBSyxXQUFXO0FBQzlCLFVBQUksVUFBVSxLQUFLLFdBQVc7QUFDOUIsVUFBSSxTQUFTLE9BQU8sUUFBZ0I7QUFFaEMsYUFBSyxPQUFPLFNBQVMsZUFBZSxTQUFTLEdBQUc7QUFFaEQsYUFBSyxPQUFPLFVBQVUsZUFBZSxLQUFLLE9BQU8sU0FBUztBQUUxRCxjQUFNLEtBQUssT0FBTyxhQUFhO0FBQUEsTUFDbkMsQ0FBQyxHQUNHLElBQUksU0FBUyxL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QUNmLGFBQUssVUFBVSxlQUFlO0FBQzlCLGFBQUssVUFBVSxLQUFLO0FBQUEsTUFDckI7QUFBQSxJQUNELENBQUM7QUFFRCxTQUFLLFdBQVc7QUFBQSxNQUNmLElBQUk7QUFBQSxNQUNKLE1BQU07QUFBQSxNQUNOLFVBQVUsTUFBTTtBQUNmLGFBQUssVUFBVSxlQUFlO0FBQzlCLGFBQUssVUFBVSxLQUFLO0FBQUEsTUFDckI7QUFBQSxJQUNELENBQUM7QUFFRCxTQUFLLGNBQWMsSUFBSSxhQUFhLEtBQUssS0FBSyxJQUFJLENBQUM7QUFBQSxFQUVwRDtBQUFBLEVBRUEscUJBQXFCLGVBQWlDO0FBQ3JELFFBQUksa0JBQWtCLElBQUk7QUFDekIsYUFBTyxDQUFDO0FBQUEsSUFDVDtBQUVBLFVBQU0sVUFBVSxjQUFjLE1BQU0sR0FBRyxFQUFFLElBQUksWUFBVSxPQUFPLEtBQUssQ0FBQztBQUVwRSxXQUFPLFFBQVEsSUFBSSxZQUFVLE9BQU8sUUFBUSxpQkFBaUIsRUFBRSxDQUFDLEVBQUUsT0FBTyxZQUFVLFdBQVcsRUFBRTtBQUFBLEVBQ2pHO0FBQUEsRUFFQSxjQUFjLEtBQWE7QUFDMUIsUUFBSSxPQUFPLE1BQU0sT0FBTyxJQUFJO0FBQzNCLFlBQU0sU0FBUyxpQkFBaUIsU0FBUyxJQUFJO0FBQzdDLFlBQU0sV0FBVyxPQUFPLGlCQUFpQixnQkFBZ0I7QUFDekQsZUFBUyxLQUFLLE1BQU0sWUFBWSxrQkFBa0IsSUFBSSxTQUFTLElBQUksSUFBSTtBQUFBLElBQ3hFO0FBQUEsRUFDRDtBQUFBLEVBRUEsd0JBQXdCLGNBQWdDO0FBQ3ZELFFBQUksaUJBQWlCLElBQUk7QUFDeEIsYUFBTyxDQUFDO0FBQUEsSUFDVDtBQUVBLFdBQU8sYUFBYSxNQUFNLEdBQUcsRUFBRSxJQUFJLGVBQWEsVUFBVSxLQUFLLENBQUM7QUFBQSxFQUNqRTtBQUFBLEVBRUEsV0FBVztBQUFBLEVBRVg7QUFBQSxFQUVBLE1BQU0sZUFBZTtBQUNwQixTQUFLLFdBQVcsT0FBTztBQUFBLE1BQ3RCLENBQUM7QUFBQSxNQUNEO0FBQUEsTUFDQSxNQUFNLEtBQUssU0FBUztBQUFBLElBQUM7QUFBQSxFQUN2QjtBQUFBLEVBRUEsTUFBTSxlQUFlO0FBQ3BCLFVBQU0sS0FBSyxTQUFTLEtBQUssUUFBUTtBQUFBLEVBQ2xDO0FBQ0Q7IiwKICAibmFtZXMiOiBbImltcG9ydF9vYnNpZGlhbiIsICJpbXBvcnRfb2JzaWRpYW4iLCAiaW1wb3J0X29ic2lkaWFuIiwgInRyIiwgImV2dCJdCn0K + + +/* nosourcemap */ \ No newline at end of file diff --git a/.obsidian/plugins/dashboard-navigator/manifest.json b/.obsidian/plugins/dashboard-navigator/manifest.json index 8c80c56..f0553e4 100644 --- a/.obsidian/plugins/dashboard-navigator/manifest.json +++ b/.obsidian/plugins/dashboard-navigator/manifest.json @@ -1,7 +1,7 @@ { "id": "dashboard-navigator", "name": "Dashboard navigator", - "version": "2.0.0", + "version": "5.2.0", "minAppVersion": "1.1.0", "description": "Vault dashboard and navigator. Show recent files by type, files per day, week, month, search files by name, date, tags and more.", "author": "Bernardo Pires", diff --git a/.obsidian/plugins/dashboard-navigator/styles.css b/.obsidian/plugins/dashboard-navigator/styles.css index 41abcd6..9ad8e7c 100644 --- a/.obsidian/plugins/dashboard-navigator/styles.css +++ b/.obsidian/plugins/dashboard-navigator/styles.css @@ -5,6 +5,7 @@ body { --dn-background-color: var(--background-secondary); --dn-foreground-color: var(--text-normal); --dn-border-color: var(--background-modifier-border); + --dn-border-color-hover: var(--background-modifier-border-hover); --dn-file-property-color: #828282; --dn-font-size: 16px; @@ -71,7 +72,7 @@ body { margin-left: 0; margin-right: 0; margin-top: var(--size-4-1); - margin-bottom: var(--size-4-2); + margin-bottom: var(--size-4-1); flex-wrap: wrap; align-content: center; } @@ -251,6 +252,7 @@ body { display: none; } +a.dn-ext, a.dn-folder-path { color: var(--text-muted); } @@ -280,57 +282,69 @@ table#dn-table td { text-overflow: ellipsis; padding: var(--size-4-1) var(--size-4-2); min-width: 50px; - width: clamp(50px, auto, unset); font-size: var(--dn-font-size); } table#dn-table th { + position: sticky; + top: 80px; + z-index: 901; text-align: left; font-weight: var(--font-semibold); color: var(--text-normal); - border-bottom: 1px solid var(--dn-border-color); cursor: pointer; + background-color: var(--background-primary); } -table#dn-table th:not(.sort-active, th:nth-child(5)):hover { - background-color: var(--tag-background); +table#dn-table th:not(th:nth-child(6), th:nth-child(7)):hover { + background-color: var(--background-secondary); } table#dn-table th.sort-active { color: var(--text-normal); - background-color: var(--tag-background); + background-color: var(--background-secondary); } table#dn-table th.sort-active.sort-asc::before { content: " ↑"; - color: var(--text-accent); font-weight: var(--font-bold); + color: var(--interactive-accent); + } table#dn-table th.sort-active.sort-desc::before { content: " ↓"; - color: var(--text-accent); font-weight: var(--font-bold); + color: var(--interactive-accent); } table#dn-table th:nth-child(1), table#dn-table th:nth-child(2), table#dn-table th:nth-child(3), -table#dn-table th:nth-child(4) { +table#dn-table th:nth-child(4), +table#dn-table th:nth-child(5), +table#dn-table th:nth-child(6) { resize: horizontal; } -table#dn-table td:nth-child(3) { +table#dn-table th:nth-child(2), +table#dn-table td:nth-child(2) { + width: 82px; + min-width: 82px; +} + +table#dn-table td:nth-child(4) { text-align: right; padding-right: 1em; } -table#dn-table th:nth-child(5) { +table#dn-table th:nth-child(6), +table#dn-table th:nth-child(7) { cursor: default; } table#dn-table tr:hover td { - background-color: var(--nav-item-background-hover); + background-color: var(--nav-item-background-hover) !important; } .dn-search-input-container { @@ -367,25 +381,17 @@ table#dn-table tr:hover td { } .dn-pagination { - margin-bottom: var(--size-4-1); + position: sticky; + display: flex; + top: 40px; + padding: var(--size-4-1) var(--size-4-2); text-align: right; font-size: .9em; -} - -.dn-pagination span { - margin-right: 1em; -} - -.dn-pagination span { - margin-right: 1em; -} - -.dn-pagination-total-results { - float: left; -} - -.dn-pagination-total-results::after { - clear: left; + background-color: var(--background-secondary); + z-index: 900; + justify-content: space-between; + border: 1px solid var(--dn-border-color); + opacity: .9; } .dn-btn-prev:disabled, @@ -396,6 +402,7 @@ table#dn-table tr:hover td { .dn-btn-prev, .dn-btn-next { cursor: pointer; + margin-left: var(--size-4-1); } /* File icons */ @@ -513,6 +520,7 @@ a.dn-f-other::before { } .dn-no-results-found { + padding-left: var(--size-4-2); color: var(--text-faint); font-style: italic; } @@ -522,12 +530,41 @@ a.dn-tag { border-radius: var(--tag-radius); margin-right: var(--size-4-1); padding-inline-end: var(--tag-padding-x); - font-size: var(--tag-size); + font-size: var(--font-size); background-color: var(--tag-background); color: var(--tag-color); text-decoration: none; } +a.dn-tag:hover { + color: var(--text-accent-hover); +} + +a.dn-fproperties::before { + content: '•'; + color: var(--dn-border-color); +} + +a.dn-fproperties:hover::before { + content: '•'; + color: var(--text-accent-hover); +} + +a.dn-fproperties { + display: inline-block; + border-radius: var(--tag-radius); + margin-right: var(--size-4-1); + padding-inline-end: var(--tag-padding-x); + font-size: var(--font-size); + background-color: var(--tag-background); + color: var(--tag-color); + text-decoration: none; +} + +a.dn-fproperties:hover { + color: var(--text-accent-hover); +} + #dn-other, #dn-videos, #dn-audios, @@ -535,7 +572,8 @@ a.dn-tag { #dn-images, #dn-canvas, #dn-recent-notes, -#dn-recent-files { +#dn-recent-files, +#dn-last-opened-files { padding: var(--size-4-2); background-color: var(--background-primary); border: 1px solid var(--background-modifier-border); @@ -553,8 +591,7 @@ table#dn-table.dn-tbl-row tbody tr:nth-child(even) { background-color: var(--dn-even-background-color); } -table#dn-table.dn-tbl-column th:nth-child(even), -table#dn-table.dn-tbl-column td:nth-child(even) { +table#dn-table.dn-tbl-column td:nth-child(even of :not(.dn-hidden)) { background-color: var(--dn-even-background-color); } @@ -590,15 +627,60 @@ table#dn-table.dn-tbl-default td { word-wrap: break-word; } +.dn-div-top-preview-btns { + text-align: left; + display: flex; + justify-content: left; + gap: 8px; +} + .dn-div-bottom-properties { - text-align: center; + text-align: left; + display: flex; + justify-content: space-between; } -.dn-btn-close-properties { - width: 30%; +.dn-div-top-preview-btns button, +.dn-div-bottom-properties button { + margin-top: var(--size-4-1); + cursor: pointer; +} + +.dn-btn-properties-close { + width: 100px; + margin-left: 1em; +} + +.dn-btn-properties-open-file { + width: 180px; +} + +.dn-hidden { + display: none; +} + +.dn-properties-frontmatter-modal, +.dn-properties-frontmatter { + overflow-y: auto; + resize: vertical; + min-height: 48px; + height: 120px; + border: 1px solid var(--dn-border-color); + padding: var(--size-4-1); + line-height: 1.8em; + font-size: 1em; + word-wrap: break-word; + word-break: break-word; } +.modal:has(.dn-properties-modal), +.modal:has(.dn-frontmatter-modal) { + min-width: 30%; + width: 60%; + max-width: 100%; + resize: both; +} @media screen and (max-width: 1024px) { .dn-flex { @@ -621,10 +703,10 @@ table#dn-table.dn-tbl-default td { width: 30%; } - table#dn-table th:nth-child(3), - table#dn-table td:nth-child(3), - table#dn-table th:nth-child(5), - table#dn-table td:nth-child(5) { + table#dn-table th:nth-child(4), + table#dn-table td:nth-child(4), + table#dn-table th:nth-child(6), + table#dn-table td:nth-child(6) { display: none; } @@ -667,7 +749,11 @@ table#dn-table.dn-tbl-default td { table#dn-table th:nth-child(4), table#dn-table td:nth-child(4), table#dn-table th:nth-child(5), - table#dn-table td:nth-child(5) { + table#dn-table td:nth-child(5), + table#dn-table th:nth-child(6), + table#dn-table td:nth-child(6), + table#dn-table th:nth-child(7), + table#dn-table td:nth-child(7) { display: none; } @@ -676,4 +762,121 @@ table#dn-table.dn-tbl-default td { display: none; } +} + +.dn-preview { + display: none; + position: fixed; + min-width: 400px; + min-height: 300px; + width: 600px; + height: 480px; + max-width: 100%; + max-height: 100%; + overflow: auto; + border: 2px solid var(--dn-border-color); + background: var(--background-primary); + padding: 0; + + z-index: 90000; + border-radius: var(--radius-m); + box-shadow: 0 0 1em #00000082; + resize: both; +} + +.dn-preview:hover { + border: 2px solid var(--dn-border-color-hover); +} + +.dn-preview-top-bar { + background-color: var(--background-primary); + position: sticky; + top: 0; + left: 0; + padding: var(--size-4-2); + z-index: 10; +} + +.dn-preview-titlebar { + width: 90%; + cursor: move; + border-left: 4px solid var(--text-faint); + padding-left: 8px; +} + +.dn-preview-titlebar:hover { + border-left: 4px solid var(--text-accent); +} + +.dn-preview-titlebar .dn-property-value { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + +.dn-preview .dn-pr-file-name::before { + content: 'File: '; + color: var(--dn-file-property-color); +} + +.dn-preview .dn-pr-file-path::before { + content: 'Path: '; + color: var(--dn-file-property-color); +} + +.dn-preview .dn-pr-file-path { + padding: var(--size-4-1) 0; + border-bottom: 1px solid var(--dn-border-color); +} + +.dn-preview .dn-pr-content { + display: grid; + grid-template-rows: 1fr; + grid-template-columns: 1fr; + width: 100%; + background: var(--background-primary); + border-radius: var(--radius-s); + cursor: auto; +} + +.dn-preview .dn-pr-content img { + width: 100%; + height: auto; +} + +.dn-preview .markdown-embed-title { + display: none; +} + +.dn-preview .markdown-embed { + border-inline-start: 0; +} + +.dn-property-row { + display: flex; + margin-bottom: var(--size-4-1); +} + +.dn-property-name-sm { + flex: 0 0 auto; + width: 62px; + text-align: left; + color: var(--dn-file-property-color); +} + +.dn-property-name { + flex: 0 0 auto; + width: 108px; + text-align: left; + color: var(--dn-file-property-color); +} + +.dn-property-value { + flex: 1; + padding-left: 0; + text-align: left; +} + +.dn-property-value span.nav-file-tag { + margin: 0; } \ No newline at end of file diff --git a/.obsidian/plugins/line-arrange/main.js b/.obsidian/plugins/line-arrange/main.js deleted file mode 100644 index 29171ad..0000000 --- a/.obsidian/plugins/line-arrange/main.js +++ /dev/null @@ -1,141 +0,0 @@ -/* -THIS IS A GENERATED/BUNDLED FILE BY ESBUILD -if you want to view the source, please visit the github repository of this plugin -*/ - -var __defProp = Object.defineProperty; -var __getOwnPropDesc = Object.getOwnPropertyDescriptor; -var __getOwnPropNames = Object.getOwnPropertyNames; -var __hasOwnProp = Object.prototype.hasOwnProperty; -var __export = (target, all) => { - for (var name in all) - __defProp(target, name, { get: all[name], enumerable: true }); -}; -var __copyProps = (to, from, except, desc) => { - if (from && typeof from === "object" || typeof from === "function") { - for (let key of __getOwnPropNames(from)) - if (!__hasOwnProp.call(to, key) && key !== except) - __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); - } - return to; -}; -var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); - -// main.ts -var main_exports = {}; -__export(main_exports, { - default: () => lineArrange -}); -module.exports = __toCommonJS(main_exports); -var import_obsidian = require("obsidian"); -var lineArrange = class extends import_obsidian.Plugin { - // Method called when the plugin is loaded - async onload() { - this.addCommand({ - id: "lexisort-lines", - name: "Lexisort lines", - editorCallback: (editor) => { - const selection = editor.getSelection(); - editor.replaceSelection(lexiSortLines(selection)); - } - }); - this.addCommand({ - id: "reverse-lines", - name: "Reverse lines", - editorCallback: (editor) => { - const selection = editor.getSelection(); - editor.replaceSelection(reverseLines(selection)); - } - }); - this.addCommand({ - id: "sort-lines", - name: "Sort lines", - editorCallback: (editor) => { - const selection = editor.getSelection(); - editor.replaceSelection(sortLines(selection)); - } - }); - this.addCommand({ - id: "shuffle-lines", - name: "Shuffle lines", - editorCallback: (editor) => { - const selection = editor.getSelection(); - editor.replaceSelection(shuffleLines(selection)); - } - }); - } -}; -var textSize = getComputedStyle(document.body).getPropertyValue("--font-text-size"); -var textFont = getComputedStyle(document.body).getPropertyValue("--font-text"); -function lexiSortLines(orgText) { - const lines = orgText.split("\n"); - lines.sort(); - let srtLines = ""; - lines.forEach((line) => { - if (line.length > 0) { - srtLines += line + "\n"; - } else { - srtLines = "\n" + srtLines; - } - }); - return srtLines.trimEnd(); -} -function reverseLines(orgText) { - const lines = orgText.split("\n"); - lines.reverse(); - let revLines = ""; - lines.forEach((line) => { - if (line.length > 0) { - revLines += line + "\n"; - } else { - revLines = "\n" + revLines; - } - }); - return revLines.trimEnd(); -} -function sortLines(orgText) { - const lines = orgText.split("\n"); - const arr1 = new Arrangement(lines, realLineWidth); - return orderedText(arr1); -} -function realLineWidth(line) { - const canvas = document.createElement("canvas"); - const context = canvas.getContext("2d"); - if (!context) { - throw new Error("Failed to get 2D context"); - } - context.font = textSize + " " + textFont; - return Math.round(1e4 * context.measureText(line).width); -} -function shuffleLines(orgText) { - const lines = orgText.split("\n"); - const arr2 = new Arrangement(lines, randomLineWidth); - return orderedText(arr2); -} -function randomLineWidth(line) { - if (line.length > 0) - return Math.round(1e4 * (Math.random() + 1)); - else - return 0; -} -var Arrangement = class { - // Creates a key for each unique line-width and associates line to respective slot - constructor(linesList, lineFunction) { - linesList.forEach((line) => { - const width = lineFunction(line); - if (!(width in this)) { - this[width] = line; - } else { - this[width] = this[width].concat("\n" + line); - } - }); - } -}; -function orderedText(orderedLines) { - let finalText = ""; - for (const lineKey in orderedLines) { - finalText += orderedLines[lineKey] + "\n"; - } - return finalText.trimEnd(); -} -//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsibWFpbi50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiaW1wb3J0IHsgRWRpdG9yLCBQbHVnaW4gfSBmcm9tICdvYnNpZGlhbic7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIGxpbmVBcnJhbmdlIGV4dGVuZHMgUGx1Z2luIHtcbiAgICAvLyBNZXRob2QgY2FsbGVkIHdoZW4gdGhlIHBsdWdpbiBpcyBsb2FkZWRcbiAgICBhc3luYyBvbmxvYWQoKSB7XG5cbiAgICAgICAgLy8gQWRkIGEgY29tbWFuZCB0byBsZXhpY2FsbHkgc29ydCBsaW5lcyBpbiB0aGUgZWRpdG9yXG4gICAgICAgIHRoaXMuYWRkQ29tbWFuZCh7XG4gICAgICAgICAgICBpZDogJ2xleGlzb3J0LWxpbmVzJyxcbiAgICAgICAgICAgIG5hbWU6ICdMZXhpc29ydCBsaW5lcycsXG4gICAgICAgICAgICBlZGl0b3JDYWxsYmFjazogKGVkaXRvcjogRWRpdG9yKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc2VsZWN0aW9uID0gZWRpdG9yLmdldFNlbGVjdGlvbigpOyAvLyBHZXQgdGhlIHNlbGVjdGVkIHRleHRcbiAgICAgICAgICAgICAgICBlZGl0b3IucmVwbGFjZVNlbGVjdGlvbihsZXhpU29ydExpbmVzKHNlbGVjdGlvbikpOyAvLyBSZXBsYWNlIHNlbGVjdGlvbiB3aXRoIGxleGljYWxseSBzb3J0ZWQgbGluZXNcbiAgICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIEFkZCBhIGNvbW1hbmQgdG8gcmV2ZXJzZSBsaW5lcyBpbiB0aGUgZWRpdG9yXG4gICAgICAgIHRoaXMuYWRkQ29tbWFuZCh7XG4gICAgICAgICAgICBpZDogJ3JldmVyc2UtbGluZXMnLFxuICAgICAgICAgICAgbmFtZTogJ1JldmVyc2UgbGluZXMnLFxuICAgICAgICAgICAgZWRpdG9yQ2FsbGJhY2s6IChlZGl0b3I6IEVkaXRvcikgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHNlbGVjdGlvbiA9IGVkaXRvci5nZXRTZWxlY3Rpb24oKTsgLy8gR2V0IHRoZSBzZWxlY3RlZCB0ZXh0XG4gICAgICAgICAgICAgICAgZWRpdG9yLnJlcGxhY2VTZWxlY3Rpb24ocmV2ZXJzZUxpbmVzKHNlbGVjdGlvbikpOyAvLyBSZXBsYWNlIHNlbGVjdGlvbiB3aXRoIHJldmVyc2VkIGxpbmVzXG4gICAgICAgICAgICB9LFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBBZGQgYSBjb21tYW5kIHRvIHNvcnQgbGluZXMgaW4gdGhlIGVkaXRvclxuICAgICAgICB0aGlzLmFkZENvbW1hbmQoe1xuICAgICAgICAgICAgaWQ6ICdzb3J0LWxpbmVzJyxcbiAgICAgICAgICAgIG5hbWU6ICdTb3J0IGxpbmVzJyxcbiAgICAgICAgICAgIGVkaXRvckNhbGxiYWNrOiAoZWRpdG9yOiBFZGl0b3IpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBzZWxlY3Rpb24gPSBlZGl0b3IuZ2V0U2VsZWN0aW9uKCk7IC8vIEdldCB0aGUgc2VsZWN0ZWQgdGV4dFxuICAgICAgICAgICAgICAgIGVkaXRvci5yZXBsYWNlU2VsZWN0aW9uKHNvcnRMaW5lcyhzZWxlY3Rpb24pKTsgLy8gUmVwbGFjZSBzZWxlY3Rpb24gd2l0aCBzb3J0ZWQgbGluZXNcbiAgICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIEFkZCBhIGNvbW1hbmQgdG8gc2h1ZmZsZSBsaW5lcyBpbiB0aGUgZWRpdG9yXG4gICAgICAgIHRoaXMuYWRkQ29tbWFuZCh7XG4gICAgICAgICAgICBpZDogJ3NodWZmbGUtbGluZXMnLFxuICAgICAgICAgICAgbmFtZTogJ1NodWZmbGUgbGluZXMnLFxuICAgICAgICAgICAgZWRpdG9yQ2FsbGJhY2s6IChlZGl0b3I6IEVkaXRvcikgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHNlbGVjdGlvbiA9IGVkaXRvci5nZXRTZWxlY3Rpb24oKTsgLy8gR2V0IHRoZSBzZWxlY3RlZCB0ZXh0XG4gICAgICAgICAgICAgICAgZWRpdG9yLnJlcGxhY2VTZWxlY3Rpb24oc2h1ZmZsZUxpbmVzKHNlbGVjdGlvbikpOyAvLyBSZXBsYWNlIHNlbGVjdGlvbiB3aXRoIHNodWZmbGVkIGxpbmVzXG4gICAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICB9XG59XG5cbmNvbnN0IHRleHRTaXplID0gZ2V0Q29tcHV0ZWRTdHlsZShkb2N1bWVudC5ib2R5KS5nZXRQcm9wZXJ0eVZhbHVlKFwiLS1mb250LXRleHQtc2l6ZVwiKTtcbmNvbnN0IHRleHRGb250ID0gZ2V0Q29tcHV0ZWRTdHlsZShkb2N1bWVudC5ib2R5KS5nZXRQcm9wZXJ0eVZhbHVlKFwiLS1mb250LXRleHRcIik7XG5cbi8vIEZ1bmN0aW9uIHRvIGxleGljYWxseSBzb3J0IHRoZSBzZWxlY3RlZCBsaW5lcyBvZiB0ZXh0XG5mdW5jdGlvbiBsZXhpU29ydExpbmVzKG9yZ1RleHQ6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgY29uc3QgbGluZXMgPSBvcmdUZXh0LnNwbGl0KFwiXFxuXCIpOyAvLyBTcGxpdCB0aGUgb3JpZ2luYWwgdGV4dCBpbnRvIGxpbmVzXG4gICAgbGluZXMuc29ydCgpOyAvLyBTb3J0IHRoZSBhcnJheSBvZiBsaW5lc1xuICAgIGxldCBzcnRMaW5lcyA9IFwiXCI7XG4gICAgbGluZXMuZm9yRWFjaChsaW5lID0+IHtcbiAgICAgICAgaWYgKGxpbmUubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgc3J0TGluZXMgKz0gKGxpbmUgKyAnXFxuJyk7IC8vIEFkZCBlYWNoIGxpbmUgdG8gdGhlIHJldHVybmluZyB0ZXh0IHN0cmluZ1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgc3J0TGluZXMgPSAoJ1xcbicgKyBzcnRMaW5lcyk7IFxuICAgICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIHNydExpbmVzLnRyaW1FbmQoKTsgLy8gUmV0dXJuIHRoZSBsZXhpY2FsbHkgc29ydGVkIGxpbmVzXG59XG5cbi8vIEZ1bmN0aW9uIHRvIHJldmVyc2UgdGhlIHNlbGVjdGVkIGxpbmVzIG9mIHRleHRcbmZ1bmN0aW9uIHJldmVyc2VMaW5lcyhvcmdUZXh0OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGNvbnN0IGxpbmVzID0gb3JnVGV4dC5zcGxpdChcIlxcblwiKTsgLy8gU3BsaXQgdGhlIG9yaWdpbmFsIHRleHQgaW50byBsaW5lc1xuICAgIGxpbmVzLnJldmVyc2UoKTsgLy8gUmV2ZXJzZSB0aGUgYXJyYXkgb2YgbGluZXNcbiAgICBsZXQgcmV2TGluZXMgPSBcIlwiO1xuICAgIGxpbmVzLmZvckVhY2gobGluZSA9PiB7XG4gICAgICAgIGlmIChsaW5lLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIHJldkxpbmVzICs9IChsaW5lICsgJ1xcbicpOyAvLyBBZGQgZWFjaCBsaW5lIHRvIHRoZSByZXR1cm5pbmcgdGV4dCBzdHJpbmdcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldkxpbmVzID0gKCdcXG4nICsgcmV2TGluZXMpO1xuICAgICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIHJldkxpbmVzLnRyaW1FbmQoKTsgLy8gUmV0dXJuIHRoZSByZXZlcnNlZCBsaW5lc1xufVxuXG4vLyBGdW5jdGlvbiB0byBzb3J0IGxpbmVzIGJhc2VkIG9uIHRoZWlyIHZpc3VhbCB3aWR0aFxuZnVuY3Rpb24gc29ydExpbmVzKG9yZ1RleHQ6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgY29uc3QgbGluZXMgPSBvcmdUZXh0LnNwbGl0KFwiXFxuXCIpOyAvLyBTcGxpdCB0aGUgb3JpZ2luYWwgdGV4dCBpbnRvIGxpbmVzXG4gICAgY29uc3QgYXJyMSA9IG5ldyBBcnJhbmdlbWVudChsaW5lcywgcmVhbExpbmVXaWR0aCk7IC8vIENyZWF0ZSBhbiBhcnJhbmdlbWVudCBiYXNlZCBvbiByZWFsIGxpbmUgd2lkdGhcbiAgICByZXR1cm4gb3JkZXJlZFRleHQoYXJyMSk7IC8vIFJldHVybiB0aGUgb3JkZXJlZCB0ZXh0IGZyb20gdGhlIGFycmFuZ2VtZW50XG59XG5cbi8vIEZ1bmN0aW9uIHRvIGNhbGN1bGF0ZSB0aGUgdmlzdWFsIHdpZHRoIG9mIGEgbGluZVxuZnVuY3Rpb24gcmVhbExpbmVXaWR0aChsaW5lOiBzdHJpbmcpOiBudW1iZXIge1xuICAgIGNvbnN0IGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgIGNvbnN0IGNvbnRleHQgPSBjYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICBpZiAoIWNvbnRleHQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdGYWlsZWQgdG8gZ2V0IDJEIGNvbnRleHQnKTtcbiAgICB9XG4gICAgY29udGV4dC5mb250ID0gdGV4dFNpemUgKyBcIiBcIiArIHRleHRGb250O1xuICAgIHJldHVybiBNYXRoLnJvdW5kKDEwMDAwICogKGNvbnRleHQubWVhc3VyZVRleHQobGluZSkud2lkdGgpKTsgLy8gUmV0dXJuIHRoZSB3aWR0aCBhcyBhIG5vcm1hbGlzZWQgaW50ZWdlclxufVxuXG4vLyBGdW5jdGlvbiB0byBzaHVmZmxlIGxpbmVzIHJhbmRvbWx5XG5mdW5jdGlvbiBzaHVmZmxlTGluZXMob3JnVGV4dDogc3RyaW5nKSB7XG4gICAgY29uc3QgbGluZXMgPSBvcmdUZXh0LnNwbGl0KFwiXFxuXCIpOyAvLyBTcGxpdCB0aGUgb3JpZ2luYWwgdGV4dCBpbnRvIGxpbmVzXG4gICAgY29uc3QgYXJyMiA9IG5ldyBBcnJhbmdlbWVudChsaW5lcywgcmFuZG9tTGluZVdpZHRoKTsgLy8gQ3JlYXRlIGFuIGFycmFuZ2VtZW50IGJhc2VkIG9uIHJhbmRvbSBsaW5lIHdpZHRoXG4gICAgcmV0dXJuIG9yZGVyZWRUZXh0KGFycjIpOyAvLyBSZXR1cm4gdGhlIG9yZGVyZWQgdGV4dCBmcm9tIHRoZSBhcnJhbmdlbWVudFxufVxuXG4vLyBGdW5jdGlvbiB0byBnZW5lcmF0ZSBhIHJhbmRvbSB3aWR0aCBmb3IgYSBsaW5lXG5mdW5jdGlvbiByYW5kb21MaW5lV2lkdGgobGluZTogc3RyaW5nKTogbnVtYmVyIHtcbiAgICBpZiAobGluZS5sZW5ndGggPiAwKVxuICAgICAgICByZXR1cm4gTWF0aC5yb3VuZCgxMDAwMCAqIChNYXRoLnJhbmRvbSgpICsgMSkpOyAvLyBSZXR1cm4gYSByYW5kb20gbnVtYmVyIGFzIGEgbm9ybWFsaXNlZCBpbnRlZ2VyXG4gICAgZWxzZVxuICAgICAgICByZXR1cm4gMDsgLy8gUmV0dXJuIDAgZm9yIGVtcHR5IGxpbmVzXG59XG5cbi8vIENsYXNzIHRvIGFycmFuZ2UgbGluZXMgYmFzZWQgb24gdGhlaXIgY2FsY3VsYXRlZCB3aWR0aHNcbmNsYXNzIEFycmFuZ2VtZW50IHtcbiAgICBbd2lkdGg6IG51bWJlcl06IHN0cmluZztcblxuICAgIC8vIENyZWF0ZXMgYSBrZXkgZm9yIGVhY2ggdW5pcXVlIGxpbmUtd2lkdGggYW5kIGFzc29jaWF0ZXMgbGluZSB0byByZXNwZWN0aXZlIHNsb3RcbiAgICBjb25zdHJ1Y3RvcihsaW5lc0xpc3Q6IHN0cmluZ1tdLCBsaW5lRnVuY3Rpb246IChsaW5lOiBzdHJpbmcpID0+IG51bWJlcikge1xuICAgICAgICBsaW5lc0xpc3QuZm9yRWFjaChsaW5lID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHdpZHRoID0gbGluZUZ1bmN0aW9uKGxpbmUpO1xuICAgICAgICAgICAgaWYgKCEod2lkdGggaW4gdGhpcykpIHtcbiAgICAgICAgICAgICAgICB0aGlzW3dpZHRoXSA9IGxpbmU7IC8vIFN0b3JlIHRoZSBsaW5lIGlmIHRoZSB3aWR0aCBrZXkgZG9lc24ndCBleGlzdFxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzW3dpZHRoXSA9IHRoaXNbd2lkdGhdLmNvbmNhdChcIlxcblwiICsgbGluZSk7IC8vIENvbmNhdGVuYXRlIGxpbmVzIHdpdGggdGhlIHNhbWUgd2lkdGggc2xvdFxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG59XG5cbi8vIEZ1bmN0aW9uIHRvIGdlbmVyYXRlIHRoZSBmaW5hbCBvcmRlcmVkIHRleHQgZnJvbSB0aGUgYXJyYW5nZW1lbnRcbmZ1bmN0aW9uIG9yZGVyZWRUZXh0KG9yZGVyZWRMaW5lczogQXJyYW5nZW1lbnQpOiBzdHJpbmcge1xuICAgIGxldCBmaW5hbFRleHQgPSBcIlwiO1xuICAgIGZvciAoY29uc3QgbGluZUtleSBpbiBvcmRlcmVkTGluZXMpIHtcbiAgICAgICAgZmluYWxUZXh0ICs9IChvcmRlcmVkTGluZXNbbGluZUtleV0gKyAnXFxuJyk7IC8vIEFwcGVuZCBlYWNoIGxpbmUgZm9sbG93ZWQgYnkgYSBuZXdsaW5lIGNoYXJhY3RlclxuICAgIH1cbiAgICByZXR1cm4gZmluYWxUZXh0LnRyaW1FbmQoKTsgLy8gVHJpbSB0aGUgZmluYWwgdGV4dCB0byByZW1vdmUgdHJhaWxpbmcgbmV3bGluZXNcbn1cbiJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxzQkFBK0I7QUFFL0IsSUFBcUIsY0FBckIsY0FBeUMsdUJBQU87QUFBQTtBQUFBLEVBRTVDLE1BQU0sU0FBUztBQUdYLFNBQUssV0FBVztBQUFBLE1BQ1osSUFBSTtBQUFBLE1BQ0osTUFBTTtBQUFBLE1BQ04sZ0JBQWdCLENBQUMsV0FBbUI7QUFDaEMsY0FBTSxZQUFZLE9BQU8sYUFBYTtBQUN0QyxlQUFPLGlCQUFpQixjQUFjLFNBQVMsQ0FBQztBQUFBLE1BQ3BEO0FBQUEsSUFDSixDQUFDO0FBR0QsU0FBSyxXQUFXO0FBQUEsTUFDWixJQUFJO0FBQUEsTUFDSixNQUFNO0FBQUEsTUFDTixnQkFBZ0IsQ0FBQyxXQUFtQjtBQUNoQyxjQUFNLFlBQVksT0FBTyxhQUFhO0FBQ3RDLGVBQU8saUJBQWlCLGFBQWEsU0FBUyxDQUFDO0FBQUEsTUFDbkQ7QUFBQSxJQUNKLENBQUM7QUFHRCxTQUFLLFdBQVc7QUFBQSxNQUNaLElBQUk7QUFBQSxN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 diff --git a/.obsidian/plugins/line-arrange/manifest.json b/.obsidian/plugins/line-arrange/manifest.json deleted file mode 100644 index 621d301..0000000 --- a/.obsidian/plugins/line-arrange/manifest.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "id": "line-arrange", - "name": "Line Arrange", - "version": "1.2.1", - "minAppVersion": "0.15.0", - "description": "Shuffle, reverse, or sort lines, using either visual width or lexical order.", - "author": "Chitwan Singh", - "authorUrl": "https://github.com/chitwan27", - "isDesktopOnly": false -} diff --git a/.obsidian/plugins/litegallery/main.js b/.obsidian/plugins/litegallery/main.js deleted file mode 100644 index 41083da..0000000 --- a/.obsidian/plugins/litegallery/main.js +++ /dev/null @@ -1,214 +0,0 @@ -/* -THIS IS A GENERATED/BUNDLED FILE BY ESBUILD -if you want to view the source, please visit the github repository of this plugin -*/ - -var __defProp = Object.defineProperty; -var __getOwnPropDesc = Object.getOwnPropertyDescriptor; -var __getOwnPropNames = Object.getOwnPropertyNames; -var __hasOwnProp = Object.prototype.hasOwnProperty; -var __export = (target, all) => { - for (var name in all) - __defProp(target, name, { get: all[name], enumerable: true }); -}; -var __copyProps = (to, from, except, desc) => { - if (from && typeof from === "object" || typeof from === "function") { - for (let key of __getOwnPropNames(from)) - if (!__hasOwnProp.call(to, key) && key !== except) - __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); - } - return to; -}; -var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); - -// main.ts -var main_exports = {}; -__export(main_exports, { - default: () => LiteGallery -}); -module.exports = __toCommonJS(main_exports); -var import_obsidian2 = require("obsidian"); - -// settingtab.ts -var import_obsidian = require("obsidian"); -var LiteGallerySettingTab = class extends import_obsidian.PluginSettingTab { - constructor(app, plugin) { - super(app, plugin); - this.plugin = plugin; - } - display() { - let { containerEl } = this; - containerEl.empty(); - new import_obsidian.Setting(containerEl).setName("Image folders").setDesc("Comma separated list of folders to search for images (in order of priority).").addText( - (text) => text.setPlaceholder("/").setValue(this.plugin.settings.image_folders.join(",")).onChange(async (value) => { - this.plugin.settings.image_folders = value.split(","); - await this.plugin.save_settings(); - }) - ); - } -}; - -// main.ts -var DEFAULT_SETTINGS = { - image_folders: [] -}; -var LiteGallery = class extends import_obsidian2.Plugin { - async load_settings() { - this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData()); - } - async save_settings() { - await this.saveData(this.settings); - } - async onload() { - await this.load_settings(); - this.addSettingTab(new LiteGallerySettingTab(this.app, this)); - this.registerMarkdownCodeBlockProcessor("litegal", async (source, el, ctx) => { - let active_slide = 0; - let preview_scroll_speed = 0; - const image_list = source.split("\n").map((line) => line.replace(/!?\[\[/, "").replace("]]", "").trim()).filter((line) => line).map( - (image) => { - let image_exists = false; - let image_path = void 0; - let path_options = this.settings.image_folders.map((folder) => { - return `${folder.slice(-1) == "/" ? folder == "/" ? "" : folder : ( - // If folder doesn't need a trailing slash, don't add it (if it's root dir should just be empty string) - `${folder}/` - )}${image}`; - }); - for (const test_path of path_options) { - const file = this.app.vault.getAbstractFileByPath(test_path); - if (file instanceof import_obsidian2.TFile) { - image_exists = true; - image_path = this.app.vault.adapter.getResourcePath(test_path); - break; - } - } - if (image_path == void 0) { - new import_obsidian2.Notice(`LiteGallery: Image not found: ${image}`); - } - return image_path; - } - ).filter((image_path) => image_path !== void 0); - const lightbox_container = document.body.createEl("div", { - cls: "litegal-lightbox-container hidden" - }); - lightbox_container.onclick = () => { - lightbox_container.addClass("hidden"); - }; - const lightbox = lightbox_container.createEl("div"); - lightbox.classList.add("litegal-lightbox"); - lightbox.onclick = (event) => { - event.stopPropagation(); - }; - const gallery = el.createEl("div", { cls: "litegal" }); - gallery.classList.add("litegal"); - if (image_list.length > 0) { - const active_image_container = gallery.createEl("div", { - cls: "litegal-active" - }); - const active_image_container_inner = active_image_container.createEl("div", { - cls: "litegal-active-inner" - }); - const active_image = active_image_container_inner.createEl("img"); - active_image.src = image_list[active_slide]; - active_image.onclick = () => { - lightbox_container.removeClass("hidden"); - lightbox_image.src = image_list[active_slide]; - }; - const larrow = active_image_container.createEl("div", { - text: "<", - cls: "litegal-arrow litegal-arrow-left" - }); - larrow.onclick = () => { - active_slide = (active_slide - 1 + image_list.length) % image_list.length; - active_image.src = image_list[active_slide]; - }; - const rarrow = active_image_container.createEl("div", { - text: ">", - cls: "litegal-arrow litegal-arrow-right" - }); - rarrow.onclick = () => { - active_slide = (active_slide + 1) % image_list.length; - active_image.src = image_list[active_slide]; - }; - const preview_outer_container = gallery.createEl("div", { cls: "litegal-preview-outer" }); - const preview_larrow = preview_outer_container.createEl("div", { - text: "<", - cls: "litegal-arrow litegal-arrow-left" - }); - preview_larrow.onmouseenter = () => { - preview_scroll_speed = -5; - }; - preview_larrow.onmouseleave = () => { - preview_scroll_speed = 0; - }; - const preview_rarrow = preview_outer_container.createEl("div", { - text: ">", - cls: "litegal-arrow litegal-arrow-right" - }); - preview_rarrow.onmouseenter = () => { - preview_scroll_speed = 5; - }; - preview_rarrow.onmouseleave = () => { - preview_scroll_speed = 0; - }; - const preview_container = preview_outer_container.createEl("div", { - cls: "litegal-preview" - }); - setInterval(() => { - preview_container.scrollLeft += preview_scroll_speed; - }, 10); - image_list.forEach(async (image_path, i) => { - const preview_elem = preview_container.createEl("img", { - cls: "litegal-preview-img" - }); - preview_elem.src = image_path; - preview_elem.onclick = () => { - active_slide = i; - active_image.src = `${image_list[active_slide]}`; - }; - }); - const lightbox_larrow = lightbox.createEl("div", { - text: "<", - cls: "litegal-arrow litegal-arrow-left" - }); - lightbox_larrow.onclick = () => { - active_slide = (active_slide - 1 + image_list.length) % image_list.length; - lightbox_image.src = image_list[active_slide]; - active_image.src = image_list[active_slide]; - }; - const lightbox_rarrow = lightbox.createEl("div", { - text: ">", - cls: "litegal-arrow litegal-arrow-right" - }); - lightbox_rarrow.onclick = () => { - active_slide = (active_slide + 1) % image_list.length; - lightbox_image.src = image_list[active_slide]; - active_image.src = image_list[active_slide]; - }; - const lightbox_image = lightbox.createEl("img", { - cls: "litegal-lightbox-image" - }); - const lightbox_exit = lightbox.createEl("div", { - text: "X", - cls: "litegal-lightbox-exit" - }); - lightbox_exit.onclick = () => { - lightbox_container.addClass("hidden"); - }; - document.addEventListener("keydown", (event) => { - if (event.key === "Escape") { - lightbox_container.addClass("hidden"); - } - }); - } else { - gallery.createEl("p", { - text: 'No images found, please check your image list. If your images are not found, please check your "image folders" in settings.', - cls: "litegal-no-images" - }); - } - }); - } - onunload() { - } -}; diff --git a/.obsidian/plugins/litegallery/manifest.json b/.obsidian/plugins/litegallery/manifest.json deleted file mode 100644 index a6100ca..0000000 --- a/.obsidian/plugins/litegallery/manifest.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "id": "litegallery", - "name": "Lite Gallery", - "version": "1.0.5", - "minAppVersion": "0.15.0", - "description": "Easily create carousel galleries to better organize/view images in your notes.", - "author": "Jordan Poles", - "authorUrl": "https://github.com/jpoles1/", - "isDesktopOnly": false -} diff --git a/.obsidian/plugins/litegallery/styles.css b/.obsidian/plugins/litegallery/styles.css deleted file mode 100644 index 6befc23..0000000 --- a/.obsidian/plugins/litegallery/styles.css +++ /dev/null @@ -1,111 +0,0 @@ -.litegal { - width: 100%; - cursor: default; -} -.litegal-preview-outer { - position: relative; -} -.litegal-preview { - display: flex; - align-items: space-around; - flex-wrap: nowrap; - margin: 0 30px 0 40px; - overflow: scroll; -} - -.litegal-preview-img { - width: 100px; - height: 100px; - margin: 10px; - border: 1px solid #ccc; - border-radius: 5px; - overflow: hidden; - cursor: pointer; - flex-shrink: 0; -} -.litegal-active { - position: relative; -} - -.litegal-active-inner { - display: flex; - justify-content: center; -} - -.litegal-arrow { - cursor: pointer; - font-size: 30px; - margin: 0 10px; - color: #999; - background-color: rgba(0, 0, 0, 0.2); - border-radius: 5px; - padding: 5px; - position: absolute; - top: 50%; - transform: translate(0, -50%); - user-select: none; -} -.litegal-arrow:hover { - color: white; - background-color: rgba(0, 0, 0, 0.6); -} - -.litegal-preview-outer .litegal-arrow { - font-size: 20px; -} -.litegal-arrow-right { - right: 0; -} - -.litegal-lightbox-container { - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; - background-color: rgba(0, 0, 0, 0.8); - z-index: 1000; - cursor: pointer; -} -.litegal-lightbox { - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - max-width: 90%; - max-height: 90%; - overflow: hidden; - border-radius: 5px; - box-shadow: 0 0 10px rgba(0, 0, 0, 0.5); -} - -.litegal-lightbox-image { - max-width: 100%; - max-height: 100%; -} - -.litegal-lightbox-exit { - position: absolute; - top: 0; - right: 0; - font-size: 30px; - color: white; - background-color: rgba(0, 0, 0, 0.6); - border-bottom-left-radius: 5px; - border-top-right-radius: 5px; - padding: 5px; - cursor: pointer; - user-select: none; -} - -.hidden { - display: none; -} - -.litegal-no-images { - text-align: center; - margin: 20px; - color: #999; - font-style: italic; - -} \ No newline at end of file diff --git a/.obsidian/plugins/multi-column-markdown/main.js b/.obsidian/plugins/multi-column-markdown/main.js deleted file mode 100644 index c36787d..0000000 --- a/.obsidian/plugins/multi-column-markdown/main.js +++ /dev/null @@ -1,6555 +0,0 @@ -/* -THIS IS A GENERATED/BUNDLED FILE BY ROLLUP -if you want to view the source visit the plugins github repository -*/ - -'use strict'; - -var obsidian = require('obsidian'); -var state = require('@codemirror/state'); -var view = require('@codemirror/view'); -var language = require('@codemirror/language'); - -/****************************************************************************** -Copyright (c) Microsoft Corporation. - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THIS SOFTWARE. -***************************************************************************** */ - -function __awaiter(thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -} - -function getStyle(element, property) { - var _a; - const view = ((_a = element.ownerDocument) === null || _a === void 0 ? void 0 : _a.defaultView) || window; - const style = view.getComputedStyle(element); - return (style.getPropertyValue(property) || style[property]); -} - -const PIXELS_PER_INCH = 96; -const MILLIMETRES_PER_INCH = 25.4; -const POINTS_PER_INCH = 72; -const PICAS_PER_INCH = 6; -function fontSize(element) { - return element - ? getStyle(element, 'fontSize') || fontSize(element.parentElement) - : getStyle(window.document.documentElement, 'fontSize'); -} -function parse(providedLength) { - var _a; - const length = providedLength || '0'; - const value = parseFloat(length); - const match = length.match(/[\d-.]+(\w+)$/); - const unit = (_a = match === null || match === void 0 ? void 0 : match[1]) !== null && _a !== void 0 ? _a : ''; - return [value, unit.toLowerCase()]; -} -function pixels(length, element) { - var _a, _b; - const view = (_b = (_a = element === null || element === void 0 ? void 0 : element.ownerDocument) === null || _a === void 0 ? void 0 : _a.defaultView) !== null && _b !== void 0 ? _b : window; - const root = view.document.documentElement || view.document.body; - const [value, unit] = parse(length); - switch (unit) { - case 'rem': - return value * pixels(fontSize(window.document.documentElement)); - case 'em': - return value * pixels(fontSize(element), element === null || element === void 0 ? void 0 : element.parentElement); - case 'in': - return value * PIXELS_PER_INCH; - case 'q': - return (value * PIXELS_PER_INCH) / MILLIMETRES_PER_INCH / 4; - case 'mm': - return (value * PIXELS_PER_INCH) / MILLIMETRES_PER_INCH; - case 'cm': - return (value * PIXELS_PER_INCH * 10) / MILLIMETRES_PER_INCH; - case 'pt': - return (value * PIXELS_PER_INCH) / POINTS_PER_INCH; - case 'pc': - return (value * PIXELS_PER_INCH) / PICAS_PER_INCH; - case 'vh': - return (value * view.innerHeight || root.clientWidth) / 100; - case 'vw': - return (value * view.innerWidth || root.clientHeight) / 100; - case 'vmin': - return ((value * - Math.min(view.innerWidth || root.clientWidth, view.innerHeight || root.clientHeight)) / - 100); - case 'vmax': - return ((value * - Math.max(view.innerWidth || root.clientWidth, view.innerHeight || root.clientHeight)) / - 100); - default: - return value; - } -} - -/** - * File: /src/utilities/interfaces.ts * - * Author: Cameron Robinson * - * * - * Copyright (c) 2023 Cameron Robinson * - */ -class HTMLSizing { - get sizeValue() { - return this._sizeValue; - } - set sizeValue(value) { - this._sizeValue = value; - } - constructor(value, units) { - this._sizeValue = 0; - this.widthSet = false; - this.sizeUnits = "px"; - this.sizeValue = value; - this.sizeUnits = units; - } - setWidth(value) { - this.widthSet = true; - return new HTMLSizing(value, this.sizeUnits); - } - setUnits(units) { - return new HTMLSizing(this.sizeValue, units); - } - toString() { - return `${this.sizeValue}${this.sizeUnits}`; - } - convertToPX(parentElement) { - if (this.sizeUnits === "px") { - return this; - } - switch (this.sizeUnits) { - case "cm": - case "mm": - case "in": - case "pt": - case "pc": - let absUnitsResult = pixels(`${this.toString()}`); - return new HTMLSizing(absUnitsResult, "px"); - case "vw": - case "vh": - return handleViewportSizing(); - case "em": - return getFontSizeFromEl(); - case "ch": - let ch = createEl("p", { - "attr": { "style": "width: 1ch;" } - }); - return getSizeFromStyleWidth(ch); - case "ex": - let ex = createEl("p", { - "attr": { "style": "width: 1ex;" } - }); - return getSizeFromStyleWidth(ex); - } - function getSizeFromStyleWidth(el) { - const DEFAULT_SIZE = 16; - if (parentElement === null || - parentElement === undefined) { - return new HTMLSizing(this.sizeValue * DEFAULT_SIZE, "px"); - } - parentElement.appendChild(el); - let exToPxResult = this.sizeValue * el.clientWidth; - if (el.clientWidth === 0) { - exToPxResult = this.sizeValue * DEFAULT_SIZE; - } - parentElement.removeChild(el); - return new HTMLSizing(exToPxResult, "px"); - } - function getFontSizeFromEl() { - const DEFAULT_SIZE = 16; - let fontSize = DEFAULT_SIZE; - let emToPxResult = fontSize * this.sizeValue; - if (parentElement === null || - parentElement === undefined) { - return new HTMLSizing(emToPxResult, "px"); - } - let sizing = HTMLSizing.parseToSizing(parentElement.getCssPropertyValue("font-size")); - if (sizing !== null) { - fontSize = sizing.sizeValue; - emToPxResult = fontSize * this.sizeValue; - } - return new HTMLSizing(emToPxResult, "px"); - } - function handleViewportSizing() { - let scale = this.sizeValue / 100; - if (parentElement === null || parentElement === undefined) { - console.warn("Found undefined root element. Using default client size. Result may not appear as intended."); - let defaultSizing = scale * 1200; - return new HTMLSizing(defaultSizing, "px"); - } - let viewWidth = parentElement.clientWidth; - let viewHeight = parentElement.clientHeight; - switch (this.sizeUnits) { - case "vw": - let wToPxResult = scale * viewWidth; - return new HTMLSizing(wToPxResult, "px"); - case "vh": - case "%": - let hToPxResult = scale * viewHeight; - return new HTMLSizing(hToPxResult, "px"); - } - } - } - static create() { - return new HTMLSizing(0, "px"); - } - static parseToSizing(sizingText) { - if (sizingText === "") { - return null; - } - let unitData = HTMLSizing.getLengthUnit(sizingText); - if (unitData.isValid === true) { - let units = unitData.unitStr; - let sizeText = sizingText.replace(units, "").trim(); - let size = parseInt(sizeText); - if (isNaN(size)) { - return null; - } - return HTMLSizing.create().setWidth(size).setUnits(units); - } - return null; - } - static getLengthUnit(lengthStr) { - let lastChar = lengthStr.slice(lengthStr.length - 1); - let lastTwoChars = lengthStr.slice(lengthStr.length - 2); - let unitStr = ""; - let isValid = false; - if (lastChar === "%") { - unitStr = lastChar; - isValid = true; - } - else if (lastTwoChars === "cm" || - lastTwoChars === "mm" || - lastTwoChars === "in" || - lastTwoChars === "px" || - lastTwoChars === "pt" || - lastTwoChars === "pc" || - lastTwoChars === "em" || - lastTwoChars === "ex" || - lastTwoChars === "ch" || - lastTwoChars === "vw" || - lastTwoChars === "vh") { - unitStr = lastTwoChars; - isValid = true; - } - return { isValid: isValid, unitStr: unitStr }; - } -} -addEventListener("mousedown", () => { -}); -addEventListener("mouseup", () => { -}); -function defaultStartRegionData() { - return { - found: false, - startPosition: -1, - endPosition: -1, - matchLength: 0, - regionType: "CODEBLOCK" - }; -} - -/* - * Filename: multi-column-markdown/src/regionSettings.ts - * Created Date: Tuesday, February 1st 2022, 12:23:53 pm - * Author: Cameron Robinson - * - * Copyright (c) 2022 Cameron Robinson - */ -var BorderOption; -(function (BorderOption) { - BorderOption[BorderOption["enabled"] = 0] = "enabled"; - BorderOption[BorderOption["on"] = 1] = "on"; - BorderOption[BorderOption["true"] = 2] = "true"; - BorderOption[BorderOption["disabled"] = 3] = "disabled"; - BorderOption[BorderOption["off"] = 4] = "off"; - BorderOption[BorderOption["false"] = 5] = "false"; -})(BorderOption || (BorderOption = {})); -var ShadowOption; -(function (ShadowOption) { - ShadowOption[ShadowOption["enabled"] = 0] = "enabled"; - ShadowOption[ShadowOption["on"] = 1] = "on"; - ShadowOption[ShadowOption["true"] = 2] = "true"; - ShadowOption[ShadowOption["disabled"] = 3] = "disabled"; - ShadowOption[ShadowOption["off"] = 4] = "off"; - ShadowOption[ShadowOption["false"] = 5] = "false"; -})(ShadowOption || (ShadowOption = {})); -var TableAlignOption; -(function (TableAlignOption) { - TableAlignOption[TableAlignOption["enabled"] = 0] = "enabled"; - TableAlignOption[TableAlignOption["on"] = 1] = "on"; - TableAlignOption[TableAlignOption["true"] = 2] = "true"; - TableAlignOption[TableAlignOption["disabled"] = 3] = "disabled"; - TableAlignOption[TableAlignOption["off"] = 4] = "off"; - TableAlignOption[TableAlignOption["false"] = 5] = "false"; -})(TableAlignOption || (TableAlignOption = {})); -const ALL_LAYOUTS = [ - "standard", - "left", - "first", - "center", - "middle", - "second", - "right", - "third", - "last" -]; -function isColumnLayout(value) { - return ALL_LAYOUTS.includes(value.toLowerCase()); -} -function validateColumnLayout(value) { - return value.toLowerCase(); -} -var ContentOverflowType; -(function (ContentOverflowType) { - ContentOverflowType[ContentOverflowType["scroll"] = 0] = "scroll"; - ContentOverflowType[ContentOverflowType["hidden"] = 1] = "hidden"; -})(ContentOverflowType || (ContentOverflowType = {})); -var AlignmentType; -(function (AlignmentType) { - AlignmentType[AlignmentType["left"] = 0] = "left"; - AlignmentType[AlignmentType["center"] = 1] = "center"; - AlignmentType[AlignmentType["right"] = 2] = "right"; -})(AlignmentType || (AlignmentType = {})); -var TableAlignment; -(function (TableAlignment) { - TableAlignment[TableAlignment["useSettingsDefault"] = 0] = "useSettingsDefault"; - TableAlignment[TableAlignment["align"] = 1] = "align"; - TableAlignment[TableAlignment["noAlign"] = 2] = "noAlign"; -})(TableAlignment || (TableAlignment = {})); -function MCSettings_isEqual(settingsA, settingsB) { - if ((settingsA === null || settingsA === void 0 ? void 0 : settingsA.columnID) !== (settingsB === null || settingsB === void 0 ? void 0 : settingsB.columnID)) { - return false; - } - if ((settingsA === null || settingsA === void 0 ? void 0 : settingsA.numberOfColumns) !== (settingsB === null || settingsB === void 0 ? void 0 : settingsB.numberOfColumns)) { - return false; - } - if (JSON.stringify(settingsA === null || settingsA === void 0 ? void 0 : settingsA.drawBorder) !== JSON.stringify(settingsB === null || settingsB === void 0 ? void 0 : settingsB.drawBorder)) { - return false; - } - if ((settingsA === null || settingsA === void 0 ? void 0 : settingsA.drawShadow) !== (settingsB === null || settingsB === void 0 ? void 0 : settingsB.drawShadow)) { - return false; - } - if ((settingsA === null || settingsA === void 0 ? void 0 : settingsA.autoLayout) !== (settingsB === null || settingsB === void 0 ? void 0 : settingsB.autoLayout)) { - return false; - } - if (JSON.stringify(settingsA === null || settingsA === void 0 ? void 0 : settingsA.columnSize) !== JSON.stringify(settingsB === null || settingsB === void 0 ? void 0 : settingsB.columnSize)) { - return false; - } - if ((settingsA === null || settingsA === void 0 ? void 0 : settingsA.columnPosition) !== (settingsB === null || settingsB === void 0 ? void 0 : settingsB.columnPosition)) { - return false; - } - if (JSON.stringify(settingsA === null || settingsA === void 0 ? void 0 : settingsA.columnSpacing) !== JSON.stringify(settingsB === null || settingsB === void 0 ? void 0 : settingsB.columnSpacing)) { - return false; - } - if (JSON.stringify(settingsA === null || settingsA === void 0 ? void 0 : settingsA.contentOverflow) !== JSON.stringify(settingsB === null || settingsB === void 0 ? void 0 : settingsB.contentOverflow)) { - return false; - } - if (JSON.stringify(settingsA === null || settingsA === void 0 ? void 0 : settingsA.alignment) !== JSON.stringify(settingsB === null || settingsB === void 0 ? void 0 : settingsB.alignment)) { - return false; - } - if ((settingsA === null || settingsA === void 0 ? void 0 : settingsA.columnHeight) !== (settingsB === null || settingsB === void 0 ? void 0 : settingsB.columnHeight)) { - return false; - } - if ((settingsA === null || settingsA === void 0 ? void 0 : settingsA.fullDocReflow) !== (settingsB === null || settingsB === void 0 ? void 0 : settingsB.fullDocReflow)) { - return false; - } - if ((settingsA === null || settingsA === void 0 ? void 0 : settingsA.alignTablesToAlignment) !== (settingsB === null || settingsB === void 0 ? void 0 : settingsB.alignTablesToAlignment)) { - return false; - } - return true; -} -function getDefaultMultiColumnSettings() { - return { - columnID: "", - numberOfColumns: 2, - drawBorder: [true], - drawShadow: true, - autoLayout: false, - columnSize: "standard", - columnPosition: "standard", - columnSpacing: [""], - contentOverflow: [ContentOverflowType.scroll], - alignment: [AlignmentType.left], - columnHeight: null, - fullDocReflow: false, - alignTablesToAlignment: TableAlignment.useSettingsDefault - }; -} -function shouldDrawColumnBorder(index, settings) { - if (settings.drawBorder.length === 0) { - return true; - } - return getIndexedClampedArrayValue(index, settings.drawBorder); -} -function columnOverflowState(index, settings) { - if (settings.contentOverflow.length === 0) { - return ContentOverflowType.scroll; - } - return getIndexedClampedArrayValue(index, settings.contentOverflow); -} -function columnAlignmentState(index, settings) { - if (settings.alignment.length === 0) { - return AlignmentType.left; - } - return getIndexedClampedArrayValue(index, settings.alignment); -} -function columnSpacingState(index, settings) { - if (settings.columnSpacing.length === 0) { - return ""; - } - return `margin-inline: ${getIndexedClampedArrayValue(index, settings.columnSpacing)};`; -} -function getIndexedClampedArrayValue(index, arr) { - if (arr.length === 0) { - throw ("Error getting value from empty array."); - } - if (index < 0) { - return arr[0]; - } - if (index < arr.length) { - return arr[index]; - } - return arr.last(); -} - -/** - * File: /src/utilities/settingsParser.ts - * Created Date: Friday, June 3rd 2022, 8:16 pm - * Author: Cameron Robinson - * - * Copyright (c) 2022 Cameron Robinson - */ -/** - * Here we define all of the valid settings strings that the user can enter for each setting type. - * The strings are then mapped twice, first to a valid regex string that searches for the setting - * name, ignoring all extra spaces and letter case, and then maped to a RegEx object to be used - * when parsing. - */ -const COL_POSITION_OPTION_STRS = [ - "column position", - "col position", - "column location", - "col location", - "single column location", - "single column position", -]; -const COL_POSITION_REGEX_ARR = COL_POSITION_OPTION_STRS.map(convertStringToSettingsRegex).map((value) => { - return new RegExp(value, "i"); -}); -const COL_SIZE_OPTION_STRS = [ - "column size", - "column width", - "col size", - "col width", - "single column size", - "single col size", - "single column width", - "single col width", - "largest column" -]; -const COL_SIZE_OPTION_REGEX_ARR = COL_SIZE_OPTION_STRS.map(convertStringToSettingsRegex).map((value) => { - return new RegExp(value, "i"); -}); -const NUMBER_OF_COLUMNS_STRS = [ - "number of columns", - "num of cols", - "col count", - "column count" -]; -const NUMBER_OF_COLUMNS_REGEX_ARR = NUMBER_OF_COLUMNS_STRS.map(convertStringToSettingsRegex).map((value) => { - return new RegExp(value, "i"); -}); -const DRAW_BORDER_STRS = [ - "border" -]; -const DRAW_BORDER_REGEX_ARR = DRAW_BORDER_STRS.map(convertStringToSettingsRegex).map((value) => { - return new RegExp(value, "i"); -}); -const DRAW_SHADOW_STRS = [ - "shadow" -]; -const DRAW_SHADOW_REGEX_ARR = DRAW_SHADOW_STRS.map(convertStringToSettingsRegex).map((value) => { - return new RegExp(value, "i"); -}); -const AUTO_LAYOUT_SETTING_STRS = [ - "auto layout", - "fluid div", - "fluid divs", - "fluid columns", - "fluid cols", - "fluid col" -]; -const AUTO_LAYOUT_REGEX_ARR = AUTO_LAYOUT_SETTING_STRS.map(convertStringToSettingsRegex).map((value) => { - return new RegExp(value, "i"); -}); -const COLUMN_SPACING_REGEX_ARR = [ - "column spacing", - "column gap", - "column sep" -].map((value) => { - return new RegExp(convertStringToSettingsRegex(value), "i"); -}); -const COLUMN_HEIGHT_REGEX_ARR = [ - "column height", - "col height", - "column max height", - "col max height", - "max column height", - "max col height" -].map((value) => { - return new RegExp(convertStringToSettingsRegex(value), "i"); -}); -const CONTENT_OVERFLOW_REGEX_ARR = [ - "overflow", - "content overflow" -].map((value) => { - return new RegExp(convertStringToSettingsRegex(value), "i"); -}); -const ALIGNMENT_REGEX_ARR = [ - "alignment", - "content alignment", - "align", - "content align", - "align content", - "text align", - "align text", - "Text Alignment" -].map((value) => { - return new RegExp(convertStringToSettingsRegex(value), "i"); -}); -const TABLE_ALIGNMENT_REGEX_ARR = [ - "align tables to text alignment" -].map((value) => { - return new RegExp(convertStringToSettingsRegex(value), "i"); -}); -/** - * This function searches the settings string through each regex option. If one of the regex - * values match, it returns the first group found by the regex. This is depended on proper - * regex formatting which is done by the convertStringToSettingsRegex function defined below. - * - * @param settingsString The value that may match one of the setting options. - * @param validSettingFormatRegEx The settings options through which to check all options. If one of these regex - * values match on the string we break from the loop returning the found value. - * - * @returns the user entered data if the setting is a match, or null if non of the options matched. - */ -function getSettingsDataFromKeys(settingsString, validSettingFormatRegEx) { - for (let i = 0; i < validSettingFormatRegEx.length; i++) { - let regexSearchData = validSettingFormatRegEx[i].exec(settingsString); - if (regexSearchData !== null) { - return regexSearchData[1].trim(); - } - } - return null; -} -function parseSingleColumnSettings(settingsStr, originalSettings) { - originalSettings.columnSize = "medium"; - let settingsLines = settingsStr.split("\n"); - for (let i = 0; i < settingsLines.length; i++) { - let settingsLine = settingsLines[i]; - let settingsData = getSettingsDataFromKeys(settingsLine, COL_POSITION_REGEX_ARR); - if (settingsData !== null) { - originalSettings.columnPosition = parseForSingleColumnLocation(settingsData); - } - settingsData = getSettingsDataFromKeys(settingsLine, COL_SIZE_OPTION_REGEX_ARR); - if (settingsData !== null) { - originalSettings.columnSize = parseForSingleColumnSize(settingsData); - } - } - return originalSettings; -} -function parseColumnSettings(settingsStr) { - let parsedSettings = getDefaultMultiColumnSettings(); - let settingsLines = settingsStr.split("\n"); - for (let i = 0; i < settingsLines.length; i++) { - let settingsLine = settingsLines[i]; - checkSettingIsRegionID(settingsLine, parsedSettings); - checkSettingIsNumberOfColumns(settingsLine, parsedSettings); - checkSettingDefinesColumnSize(settingsLine, parsedSettings); - checkSettingIsDrawBorder(settingsLine, parsedSettings); - checkSettingIsDrawShadow(settingsLine, parsedSettings); - checkSettingIsAutoLayout(settingsLine, parsedSettings); - checkSettingIsColumnSpacing(settingsLine, parsedSettings); - checkSettingIsContentOverflow(settingsLine, parsedSettings); - checkSettingIsColumnAlignment(settingsLine, parsedSettings); - checkSettingIsColumnHeight(settingsLine, parsedSettings); - checkSettingIsTableAlignment(settingsLine, parsedSettings); - } - return parsedSettings; -} -function checkSettingIsNumberOfColumns(settingsLine, parsedSettings) { - let settingsData = getSettingsDataFromKeys(settingsLine, NUMBER_OF_COLUMNS_REGEX_ARR); - if (settingsData === null) { - return; - } - let settingValues = parseForMultiSettings(settingsData); - settingsData = settingValues[0]; - let numOfCols = parseInt(settingsData); - if (Number.isNaN(numOfCols) === false) { - if (numOfCols >= 1) { - parsedSettings.numberOfColumns = numOfCols; - } - } -} -function checkSettingIsRegionID(settingsLine, parsedSettings) { - let settingsData = getSettingsDataFromKeys(settingsLine, CODEBLOCK_REGION_ID_REGEX_ARR); - if (settingsData === null) { - return; - } - parsedSettings.columnID = settingsData; -} -function checkSettingDefinesColumnSize(settingsLine, parsedSettings) { - let settingsData = getSettingsDataFromKeys(settingsLine, COL_SIZE_OPTION_REGEX_ARR); - if (settingsData === null) { - return; - } - let settingValues = parseForMultiSettings(settingsData); - if (settingValues.length === 1) { - // If there is only 1 item we attempt to parse out a layout type. If we get a valid item we - // return here. - if (isColumnLayout(settingValues[0])) { - parsedSettings.columnSize = validateColumnLayout(settingValues[0]); - return; - } - } - let widths = []; - for (let setting of settingValues) { - let parsed = HTMLSizing.parseToSizing(setting.trim()); - if (parsed !== null) { - widths.push(parsed); - } - } - // If none are parsed properly to a width then we return a default. - if (widths.length === 0) { - console.warn("Error parsing column layout or width, defaulting to standard layout."); - parsedSettings.columnSize = "standard"; - return; - } - // If we parsed some lengths and some did not parse properly, the user has either - // poorly defined their settings or is attempting to break us. Take the first valid option - // between the two arrays. - if (widths.length !== settingValues.length) { - for (let setting of settingValues) { - let unitData = HTMLSizing.getLengthUnit(setting); - if (unitData.isValid === true) { - parsedSettings.columnSize = widths; - return; - } - if (isColumnLayout(settingValues[0])) { - parsedSettings.columnSize = validateColumnLayout(settingValues[0]); - return; - } - } - } - parsedSettings.columnSize = widths; -} -function checkSettingIsDrawBorder(settingsLine, parsedSettings) { - let settingsData = getSettingsDataFromKeys(settingsLine, DRAW_BORDER_REGEX_ARR); - if (settingsData === null) { - return; - } - let borders = []; - let settingValues = parseForMultiSettings(settingsData); - for (let settingsData of settingValues) { - let borderState = true; - let isBorderDrawn = BorderOption[settingsData]; - if (isBorderDrawn !== undefined) { - switch (isBorderDrawn) { - case (BorderOption.disabled): - case (BorderOption.off): - case (BorderOption.false): - borderState = false; - break; - } - } - borders.push(borderState); - } - parsedSettings.drawBorder = borders; -} -function checkSettingIsDrawShadow(settingsLine, parsedSettings) { - let settingsData = getSettingsDataFromKeys(settingsLine, DRAW_SHADOW_REGEX_ARR); - if (settingsData === null) { - return; - } - let settingValues = parseForMultiSettings(settingsData); - settingsData = settingValues[0]; - let isShadowDrawn = ShadowOption[settingsData]; - if (isShadowDrawn !== undefined) { - switch (isShadowDrawn) { - case (ShadowOption.disabled): - case (ShadowOption.off): - case (ShadowOption.false): - parsedSettings.drawShadow = false; - break; - } - } -} -function checkSettingIsAutoLayout(settingsLine, parsedSettings) { - let settingsData = getSettingsDataFromKeys(settingsLine, AUTO_LAYOUT_REGEX_ARR); - if (settingsData === null) { - return; - } - let settingValues = parseForMultiSettings(settingsData); - settingsData = settingValues[0]; - if (settingsData === "false" || - settingsData === "off") { - parsedSettings.autoLayout = false; - } - parsedSettings.autoLayout = true; -} -function checkSettingIsColumnSpacing(settingsLine, parsedSettings) { - let settingsData = getSettingsDataFromKeys(settingsLine, COLUMN_SPACING_REGEX_ARR); - if (settingsData === null) { - return; - } - let spacings = []; - let settingValues = parseForMultiSettings(settingsData); - for (let settingsData of settingValues) { - let parsed = HTMLSizing.parseToSizing(settingsData.trim()); - let spacingStr = ""; - if (parsed !== null) { - spacingStr = parsed.toString(); - } - else { - let noUnitsNum = parseInt(settingsData.trim()); - if (isNaN(noUnitsNum) === false) { - spacingStr = `${noUnitsNum}pt`; - } - } - spacings.push(spacingStr); - } - parsedSettings.columnSpacing = spacings; -} -function checkSettingIsContentOverflow(settingsLine, parsedSettings) { - let settingsData = getSettingsDataFromKeys(settingsLine, CONTENT_OVERFLOW_REGEX_ARR); - if (settingsData === null) { - return; - } - let overflowStates = []; - let settingValues = parseForMultiSettings(settingsData); - for (let settingsData of settingValues) { - let overflowType = ContentOverflowType.scroll; - settingsData = settingsData.toLowerCase().trim(); - if (settingsData === "hidden") { - overflowType = ContentOverflowType.hidden; - } - overflowStates.push(overflowType); - } - parsedSettings.contentOverflow = overflowStates; -} -function checkSettingIsColumnAlignment(settingsLine, parsedSettings) { - let settingsData = getSettingsDataFromKeys(settingsLine, ALIGNMENT_REGEX_ARR); - if (settingsData === null) { - return; - } - let alignments = []; - let settingValues = parseForMultiSettings(settingsData); - for (let settingsData of settingValues) { - let alignmentType = AlignmentType.left; - settingsData = settingsData.toLowerCase().trim(); - if (settingsData === "center") { - alignmentType = AlignmentType.center; - } - if (settingsData === "right") { - alignmentType = AlignmentType.right; - } - alignments.push(alignmentType); - } - parsedSettings.alignment = alignments; -} -function checkSettingIsTableAlignment(settingsLine, parsedSettings) { - let settingsData = getSettingsDataFromKeys(settingsLine, TABLE_ALIGNMENT_REGEX_ARR); - if (settingsData === null) { - return; - } - let settingValues = parseForMultiSettings(settingsData); - settingsData = settingValues[0]; - let tableAlignment = TableAlignOption[settingsData]; - if (tableAlignment !== undefined) { - switch (tableAlignment) { - case (TableAlignOption.disabled): - case (TableAlignOption.off): - case (TableAlignOption.false): - parsedSettings.alignTablesToAlignment = TableAlignment.noAlign; - break; - default: - parsedSettings.alignTablesToAlignment = TableAlignment.align; - } - } -} -function checkSettingIsColumnHeight(settingsLine, parsedSettings) { - let settingsData = getSettingsDataFromKeys(settingsLine, COLUMN_HEIGHT_REGEX_ARR); - if (settingsData === null) { - return; - } - let settingValues = parseForMultiSettings(settingsData); - settingsData = settingValues[0]; - let parsed = HTMLSizing.parseToSizing(settingsData.trim()); - if (parsed !== null) { - parsedSettings.columnHeight = parsed; - } - else { - let noUnitsNum = parseInt(settingsData.trim()); - if (isNaN(noUnitsNum) === false) { - parsedSettings.columnHeight = HTMLSizing.create().setWidth(noUnitsNum).setUnits("pt"); - } - } -} -function parseForMultiSettings(originalValue) { - // Parse off brackets. If no brackets we return original value to be parsed as sole value. - let result = /\[(.*)\]/.exec(originalValue); - if (result === null) { - return [originalValue]; - } - let settingsList = result[1]; - let settings = settingsList.split(",").map((val) => { - return val.trim(); - }); - return settings; -} -const CODEBLOCK_REGION_ID_REGEX_STRS = [ - "id", - "region id" -]; -const CODEBLOCK_REGION_ID_REGEX_ARR = CODEBLOCK_REGION_ID_REGEX_STRS.map(convertStringToSettingsRegex).map((value) => { - return new RegExp(value, "i"); -}); -function parseStartRegionCodeBlockID(settingsStr) { - let codeBlockRegionID = ""; - let settingsLines = settingsStr.split("\n"); - for (let i = 0; i < settingsLines.length; i++) { - let settingsLine = settingsLines[i]; - let settingsData = getSettingsDataFromKeys(settingsLine, CODEBLOCK_REGION_ID_REGEX_ARR); - if (settingsData !== null) { - codeBlockRegionID = settingsData; - } - } - return codeBlockRegionID; -} -function parseForSingleColumnLocation(locationString) { - switch (locationString.toLowerCase().trim().replace(" ", "")) { - case "left": - case "leftside": - case "leftmargin": - case "leftalign": - case "leftaligned": - case "leftalignement": - case "first": - case "start": - case "beginning": - return "left"; - case "middle": - case "middlealigned": - case "middlealignment": - case "center": - case "centeraligned": - case "centeralignment": - case "centered": - case "standard": - return "center"; - case "right": - case "rightside": - case "rightmargin": - case "rightalign": - case "rightaligned": - case "rightalignment": - case "last": - case "end": - return "right"; - } - return "center"; -} -function parseForSingleColumnSize(sizeString) { - switch (sizeString = sizeString.toLowerCase().trim().replace(" ", "")) { - case "small": - case "sm": - return "small"; - case "medium": - case "med": - return "medium"; - case "large": - case "lg": - return "large"; - case "full": - case "full size": - return "full"; - } - return "medium"; -} -function convertStringToSettingsRegex(originalString) { - originalString = originalString.replace(" ", "(?:[-_]| *|)"); - let regexString = `(?:${originalString} *[:=] *)(.*)`; - return regexString; -} - -const PANDOC_ENGLISH_NUMBER_OF_COLUMNS = [ - "two", - "three", - "four", - "five", - "six", - "seven", - "eight", - "nine", - "ten" -]; -function isPandocNumberOfColumns(value) { - return PANDOC_ENGLISH_NUMBER_OF_COLUMNS.includes(value); -} -function validatePandocNumberOfColumns(value) { - return value.toLowerCase(); -} -function pandocNumberOfColumnsToValue(value) { - switch (value) { - case "two": - return 2; - case "three": - return 3; - case "four": - return 4; - case "five": - return 5; - case "six": - return 6; - case "seven": - return 7; - case "eight": - return 8; - case "nine": - return 9; - case "ten": - return 10; - } -} -const PANDOC_COL_DOT_COUNT_NAME = "colDotCount"; -const PANDOC_COL_NODOT_COUNT_NAME = "colCount"; -const PANDOC_COl_SETTINGS = "colSettings"; -const PANDOC_REGEX_STR = (() => { - let nums = PANDOC_ENGLISH_NUMBER_OF_COLUMNS.join("|"); - let regex_strings = `:{3,} *(?:\\{ *\\.(?<${PANDOC_COL_DOT_COUNT_NAME}>(?:${nums}|))(?:[-_]|)columns(?<${PANDOC_COl_SETTINGS}>.*)\\}|(?<${PANDOC_COL_NODOT_COUNT_NAME}>(?:${nums}|))(?:[-_]|)columns)(?:[ :]*)$\\n?`; - return regex_strings; -})(); -const PANDOC_REGEX = new RegExp(PANDOC_REGEX_STR, "m"); -const PANDOC_OPEN_FENCE_REGEX = /^:{3,} *(?:[a-zA-Z]+|\{.*\})(?:[ :]*)$/m; -const PANDOC_CLOSE_FENCE_REGEX = /^:{3,} *$/m; -function findPandoc(text) { - let regexData = PANDOC_REGEX.exec(text); - if (regexData !== null) { - let data = defaultPandocRegexData(); - data.found = true; - data.startPosition = regexData.index; - data.endPosition = regexData.index + regexData[0].length; - let regionData = reducePandocRegionToEndDiv(text.slice(data.endPosition)); - data.endPosition += regionData.content.length + regionData.matchLength; - data.content = regionData.content; - data.matchLength = data.endPosition - data.startPosition; - data.userSettings = regexData.groups[PANDOC_COl_SETTINGS] ? regexData.groups[PANDOC_COl_SETTINGS] : ""; - data.columnCount = regexData.groups[PANDOC_COL_DOT_COUNT_NAME] ? regexData.groups[PANDOC_COL_DOT_COUNT_NAME] : regexData.groups[PANDOC_COL_NODOT_COUNT_NAME]; - return data; - } - return defaultPandocRegexData(); -} -function getPandocStartData(text) { - let data = findPandoc(text); - if (data.found === false) { - return { - found: false, - userSettings: getDefaultMultiColumnSettings() - }; - } - return { - found: true, - userSettings: parsePandocSettings(data.userSettings, data.columnCount) - }; -} -function containsPandoc(text) { - return findPandoc(text).found; -} -function containsPandocStartTag(text) { - let regexData = PANDOC_REGEX.exec(text); - if (regexData !== null) { - return true; - } - return false; -} -function containsPandocEndTag(text) { - let regexData = PANDOC_CLOSE_FENCE_REGEX.exec(text); - if (regexData !== null) { - return true; - } - return false; -} -function isValidPandocEndTag(linesAbove, currentLine) { - if (containsPandocEndTag(currentLine) === false) { - return false; - } - let contentText = linesAbove.concat(currentLine).join("\n"); - return reducePandocRegionToEndDiv(contentText).found; -} -function reducePandocRegionToEndDiv(contentText) { - let workingText = contentText; - let result = { - found: false, - content: workingText, - matchLength: 0 - }; - let state = 0; - let offset = 0; - for (let i = 0; true; i++) { - if (i > 100) { - break; - } - let fence = getNextPandocFence(workingText); - if (fence === null) { - break; - } - let result = fence.result; - if (fence.type === "close") { - // console.log(workingText.slice(result.index, result.index + result[0].length)); - offset += (result.index + result[0].length); - state--; - } - else { - // console.log(workingText.slice(result.index, result.index + result[0].length)); - offset += (result.index + result[0].length); - state++; - } - if (state === -1) { - // We have found our last close tag. - return buildReturnData(result); - } - workingText = contentText.slice(offset); - } - function buildReturnData(matchResult) { - result.content = contentText.slice(0, offset - matchResult[0].length); - result.matchLength = matchResult[0].length; - result.found = true; - return result; - } - return result; -} -function getNextPandocFence(workingText) { - let openResult = PANDOC_OPEN_FENCE_REGEX.exec(workingText); - let closeResult = PANDOC_CLOSE_FENCE_REGEX.exec(workingText); - if (openResult === null && closeResult === null) { - return null; - } - if (openResult === null && closeResult !== null) { - return { - result: closeResult, - type: "close" - }; - } - if (closeResult === null && openResult !== null) { - return { - result: openResult, - type: "open" - }; - } - if (closeResult.index < openResult.index) { - return { - result: closeResult, - type: "close" - }; - } - else { - return { - result: openResult, - type: "open" - }; - } -} -function findPandocStart(text) { - let startRegion = defaultStartRegionData(); - startRegion.regionType = "PADOC"; - let regexData = PANDOC_REGEX.exec(text); - if (regexData !== null && regexData.length > 0) { - startRegion.found = true; - startRegion.startPosition = regexData.index; - startRegion.matchLength = regexData[0].length; - startRegion.endPosition = startRegion.startPosition + startRegion.matchLength; - } - return startRegion; -} -function defaultPandocRegexData() { - return { - found: false, - startPosition: -1, - endPosition: -1, - matchLength: 0, - content: "", - userSettings: "", - columnCount: "", - regionType: "PADOC" - }; -} -const PANDOC_SETTING_REGEX = /(?[^ ]*)=(?".*"|[^ =]*)/; -function parsePandocSettings(pandocUserSettings, colCount = "") { - //TODO: Add option for column rule. - let defaultSettings = getDefaultMultiColumnSettings(); - let colCountDefined = false; - if (colCount !== "" && isPandocNumberOfColumns(colCount)) { - colCountDefined = true; - defaultSettings.numberOfColumns = pandocNumberOfColumnsToValue(validatePandocNumberOfColumns(colCount)); - } - if (pandocUserSettings.replace(" ", "") === "") { - return defaultSettings; - } - let workingString = pandocUserSettings; - let regexValue = PANDOC_SETTING_REGEX.exec(workingString); - let settingList = ""; - for (let i = 0; regexValue !== null; i < 100) { - let settingName = regexValue.groups['settingName']; - let settingValue = regexValue.groups['settingValue']; - settingList += `${settingName}: ${settingValue}\n`; - workingString = workingString.slice(regexValue.index + regexValue[0].length); - regexValue = PANDOC_SETTING_REGEX.exec(workingString); - } - let parsedSettings = parseColumnSettings(settingList); - if (colCountDefined) { - parsedSettings.numberOfColumns = defaultSettings.numberOfColumns; - } - return parsedSettings; -} - -/* - * File: multi-column-markdown/src/MultiColumnParser.ts - * Created Date: Saturday, January 22nd 2022, 6:02:46 pm - * Author: Cameron Robinson - * - * Copyright (c) 2022 Cameron Robinson - */ -const START_REGEX_STRS = ["(===|---) *start-multi-column(:?[a-zA-Z0-9-_\\s]*)?", - "(===|---) *multi-column-start(:?[a-zA-Z0-9-_\\s]*)?"]; -const START_REGEX_ARR = []; -for (let i = 0; i < START_REGEX_STRS.length; i++) { - START_REGEX_ARR.push(new RegExp(START_REGEX_STRS[i])); -} -const START_REGEX_STRS_WHOLE_LINE = ["^(===|---) *start-multi-column(:?[a-zA-Z0-9-_\\s]*)?$", - "^(===|---) *multi-column-start(:?[a-zA-Z0-9-_\\s]*)?$"]; -const START_REGEX_ARR_WHOLE_LINE = []; -for (let i = 0; i < START_REGEX_STRS_WHOLE_LINE.length; i++) { - START_REGEX_ARR_WHOLE_LINE.push(new RegExp(START_REGEX_STRS_WHOLE_LINE[i])); -} -function findStartTag(text) { - let startRegion = defaultStartRegionData(); - startRegion.regionType = "ORIGINAL"; - for (let i = 0; i < START_REGEX_ARR.length; i++) { - let regexData = START_REGEX_ARR[i].exec(text); - if (regexData !== null && regexData.length > 0) { - startRegion.startPosition = regexData.index; - startRegion.matchLength = regexData[0].length; - startRegion.endPosition = startRegion.startPosition + startRegion.matchLength; - let line = text.slice(startRegion.startPosition, startRegion.endPosition); - if (START_REGEX_ARR_WHOLE_LINE[i].test(line)) { - startRegion.found = true; - break; - } - } - } - return startRegion; -} -function containsStartTag(text) { - return findStartTag(text).found; -} -function isStartTagWithID(text) { - let startTagData = findStartTag(text); - if (startTagData.found === true) { - let key = getStartTagKey(text); - if (key === null || key === "") { - return { isStartTag: true, hasKey: false }; - } - return { isStartTag: true, hasKey: true }; - } - return { isStartTag: false, hasKey: false }; -} -const END_REGEX_STRS = ["--- *end-multi-column", - "--- *multi-column-end", - "=== *end-multi-column", - "=== *multi-column-end"]; -const END_REGEX_ARR = []; -for (let i = 0; i < END_REGEX_STRS.length; i++) { - END_REGEX_ARR.push(new RegExp(END_REGEX_STRS[i])); -} -function findEndTag(text) { - // We want to find the first end tag in the text. - // So here we loop backwards, slicing off the tail until - // there are no more end tags available - let lastValidData = getEndTagData(text); - let workingRegexData = lastValidData; - while (workingRegexData.found === true) { - lastValidData = workingRegexData; - text = text.slice(0, workingRegexData.startPosition); - workingRegexData = getEndTagData(text); - } - return lastValidData; -} -function findEndTagClosestToEnd(text) { - let workingText = text; - let offset = 0; - let lastValidData = getEndTagData(workingText); - while (lastValidData.found) { - workingText = workingText.slice(lastValidData.endPosition); - let newData = getEndTagData(workingText); - if (newData.found === false) { - break; - } - offset += lastValidData.endPosition; - lastValidData = newData; - } - return { - found: lastValidData.found, - startPosition: lastValidData.startPosition + offset, - endPosition: lastValidData.endPosition + offset, - matchLength: lastValidData.matchLength - }; -} -function containsEndTag(text) { - return findEndTag(text).found; -} -function getEndTagData(text) { - let found = false; - let startPosition = -1; - let endPosition = -1; - let matchLength = 0; - for (let i = 0; i < END_REGEX_ARR.length; i++) { - let regexData = END_REGEX_ARR[i].exec(text); - if (regexData !== null && regexData.length > 0) { - found = true; - startPosition = regexData.index; - matchLength = regexData[0].length; - break; - } - } - endPosition = startPosition + matchLength; - return { found, startPosition, endPosition, matchLength }; -} -const COL_REGEX_STRS = [["^===\\s*?column-end\\s*?===\\s*?$", ""], - ["^===\\s*?end-column\\s*?===\\s*?$", ""], - ["^===\\s*?column-break\\s*?===\\s*?$", ""], - ["^===\\s*?break-column\\s*?===\\s*?$", ""], - ["^---\\s*?column-end\\s*?---\\s*?$", ""], - ["^---\\s*?end-column\\s*?---\\s*?$", ""], - ["^---\\s*?column-break\\s*?---\\s*?$", ""], - ["^---\\s*?break-column\\s*?---\\s*?$", ""], - ["^ *?(?:\\?)\\columnbreak *?$", ""], - ["^:{3,} *column-?break *(?:(?:$\\n^)?| *):{3,} *$", "m"]]; -const COL_REGEX_ARR = []; -for (let i = 0; i < COL_REGEX_STRS.length; i++) { - COL_REGEX_ARR.push(new RegExp(COL_REGEX_STRS[i][0], COL_REGEX_STRS[i][1])); -} -function containsColEndTag(text) { - let found = false; - for (let i = 0; i < COL_REGEX_ARR.length; i++) { - if (COL_REGEX_ARR[i].test(text)) { - found = true; - break; - } - } - return found; -} -const INNER_COL_END_REGEX_ARR = [ - /^-{3}\s*?column-end\s*?-{3}\s*?$\n?/m, - /^-{3}\s*?end-column\s*?-{3}\s*?$\n?/m, - /^-{3}\s*?column-break\s*?-{3}\s*?$\n?/m, - /^-{3}\s*?break-column\s*?-{3}\s*?$\n?/m, - /^={3}\s*?column-end\s*?={3}\s*?$\n?/m, - /^={3}\s*?end-column\s*?={3}\s*?$\n?/m, - /^={3}\s*?column-break\s*?={3}\s*?$\n?/m, - /^={3}\s*?break-column\s*?={3}\s*?$\n?/m, - /^ *?(?:\\?)\\columnbreak *?$\n?/m, - /^:{3,} *column-?break *(?:(?:$\n^)?| *):{3,} *$/m -]; -function checkForParagraphInnerColEndTag(text) { - for (let i = 0; i < INNER_COL_END_REGEX_ARR.length; i++) { - let regexResult = INNER_COL_END_REGEX_ARR[i].exec(text); - if (regexResult) { - return regexResult; - } - } - return null; -} -const COL_ELEMENT_INNER_TEXT_REGEX_STRS = ["= *column-end *=", - "= *end-column *=", - "= *column-break *=", - "= *break-column *="]; -const COL_ELEMENT_INNER_TEXT_REGEX_ARR = []; -for (let i = 0; i < COL_ELEMENT_INNER_TEXT_REGEX_STRS.length; i++) { - COL_ELEMENT_INNER_TEXT_REGEX_ARR.push(new RegExp(COL_ELEMENT_INNER_TEXT_REGEX_STRS[i])); -} -function elInnerTextContainsColEndTag(text) { - let found = false; - for (let i = 0; i < COL_ELEMENT_INNER_TEXT_REGEX_ARR.length; i++) { - if (COL_ELEMENT_INNER_TEXT_REGEX_ARR[i].test(text)) { - found = true; - break; - } - } - return found; -} -const COL_SETTINGS_REGEX_STRS = ["```settings", - "```column-settings", - "```multi-column-settings"]; -const COL_SETTINGS_REGEX_ARR = []; -for (let i = 0; i < COL_SETTINGS_REGEX_STRS.length; i++) { - COL_SETTINGS_REGEX_ARR.push(new RegExp(COL_SETTINGS_REGEX_STRS[i])); -} -function containsColSettingsTag(text) { - let found = false; - for (let i = 0; i < COL_SETTINGS_REGEX_ARR.length; i++) { - if (COL_SETTINGS_REGEX_ARR[i].test(text)) { - found = true; - break; - } - } - return found; -} -function findSettingsCodeblock(text) { - let found = false; - let startPosition = -1; - let endPosition = -1; - let matchLength = 0; - for (let i = 0; i < COL_SETTINGS_REGEX_ARR.length; i++) { - let regexData = COL_SETTINGS_REGEX_ARR[i].exec(text); - if (regexData !== null && regexData.length > 0) { - found = true; - startPosition = regexData.index; - matchLength = regexData[0].length; - endPosition = startPosition + matchLength; - let remainingText = text.slice(endPosition); - regexData = CODEBLOCK_END_REGEX.exec(remainingText); - if (regexData !== null && regexData.length > 0) { - found = true; - endPosition += regexData.index + regexData[0].length; - } - break; - } - } - return { - found, - startPosition, - endPosition, - matchLength, - regionType: "CODEBLOCK" - }; -} -const CODEBLOCK_START_REGEX_STR = [ - "multi-column-start", - "start-multi-column" -].reduce((prev, cur) => { - if (prev === "") { - return cur; - } - return `${prev}|${cur}`; -}, ""); -const START_CODEBLOCK_REGEX = new RegExp(`\`\`\`(:?${CODEBLOCK_START_REGEX_STR})(.*?)\`\`\``, "ms"); -function findStartCodeblock(text) { - let startRegion = defaultStartRegionData(); - startRegion.regionType = "CODEBLOCK"; - let regexData = START_CODEBLOCK_REGEX.exec(text); - if (regexData !== null && regexData.length > 0) { - startRegion.found = true; - startRegion.startPosition = regexData.index; - startRegion.matchLength = regexData[0].length; - startRegion.endPosition = startRegion.startPosition + startRegion.matchLength; - } - return startRegion; -} -function containsStartCodeBlock(text) { - return findStartCodeblock(text).found; -} -function containsRegionStart(text) { - return containsStartCodeBlock(text) || containsStartTag(text) || containsPandoc(text); -} -function countStartTags(initialText) { - let keys = []; - let text = initialText; - let startTagData = findStartTag(text); - while (startTagData.found) { - // Slice off everything before the tag - text = text.slice(startTagData.startPosition); - /** - * Get just the start tag line and then set text to everything just - * after the start tag. - */ - let tag = text.split("\n")[0]; - text = text.slice(1); // This moves the text 1 character so we dont match the same tag. - // Parse out the key and append to the list. - let key = getStartTagKey(tag); - if (key === null) { - key = ""; - } - keys.push(key); - // Search again for another tag before looping. - startTagData = findStartTag(text); - } - text = initialText; - startTagData = findStartCodeblock(text); - while (startTagData.found) { - let settingsText = text.slice(startTagData.startPosition, startTagData.endPosition); - text = text.slice(startTagData.endPosition); - let key = parseStartRegionCodeBlockID(settingsText); - if (key === null) { - key = ""; - } - keys.push(key); - // Search again for another tag before looping. - startTagData = findStartCodeblock(text); - } - return { numberOfTags: keys.length, keys }; -} -function getStartDataAboveLine(linesAboveArray) { - return getStartBlockOrCodeblockAboveLine(linesAboveArray, [ - findStartTag, - findStartCodeblock, - findPandocStart - ]); -} -function getStartBlockOrCodeblockAboveLine(linesAboveArray, searchFunctions) { - let originalText = linesAboveArray.join("\n"); - let { tagMatchData, lastFoundTag, textAbove } = findLastValidTag(originalText); - if (tagMatchData === null) { - return null; - } - if (tagMatchData.found === false) { - return null; - } - if (tagMatchData.regionType === "CODEBLOCK") { - let endTagSerachData = findEndTag(textAbove); - if (endTagSerachData.found === true) { - return null; - } - let startBlockKey = parseStartRegionCodeBlockID(lastFoundTag); - let linesAboveArray = textAbove.split("\n"); - return { startBlockKey, linesAboveArray, startBlockType: "CODEBLOCK" }; - } - if (tagMatchData.regionType === "ORIGINAL") { - let endTagSerachData = findEndTag(textAbove); - if (endTagSerachData.found === true) { - return null; - } - let linesAboveArray = textAbove.split("\n"); - let startBlockKey = getStartTagKey(lastFoundTag); - let codeBlockData = parseCodeBlockStart(linesAboveArray); - if (codeBlockData !== null) { - startBlockKey = codeBlockData.id; - if (codeBlockData.index > 0) { - linesAboveArray = linesAboveArray.slice(codeBlockData.index + 1); - } - } - if (startBlockKey === null) { - startBlockKey = ""; - } - return { startBlockKey, linesAboveArray, startBlockType: "ORIGINAL" }; - } - if (tagMatchData.regionType === "PADOC") { - let endTagSerachData = reducePandocRegionToEndDiv(textAbove); - if (endTagSerachData.found === true) { - return null; - } - let linesAboveArray = textAbove.split("\n"); - let pandocData = getPandocStartData(`${lastFoundTag}`); - let startBlockKey = pandocData.userSettings.columnID; - return { - startBlockKey, - linesAboveArray, - startBlockType: "PADOC" - }; - } - return null; - function findLastValidTag(originalText) { - let textAbove = originalText; - let offset = 0; - let tagMatchData = null; - let lastFoundTag = ""; - for (let i = 0; true; i++) { - if (i > 100) { - break; - } - let tagsFound = []; - searchFunctions.forEach((func) => { - tagsFound.push(func(textAbove)); - }); - tagsFound = tagsFound.filter((val) => { - return val.found === true; - }).sort((a, b) => { - return a.startPosition - b.startPosition; - }); - if (tagsFound.length === 0) { - break; - } - tagMatchData = tagsFound[0]; - let startIndex = offset + tagMatchData.startPosition; - lastFoundTag = originalText.slice(startIndex, startIndex + tagMatchData.matchLength).trimEnd(); - offset += (tagMatchData.startPosition + tagMatchData.matchLength); - textAbove = originalText.slice(offset); - } - return { - tagMatchData, - lastFoundTag, - textAbove - }; - } -} -/** - * This function will filter a set of strings, returning all items starting - * from the closest open start tag through the last item in the set. - * - * The function filters out all end tags to make sure that the start tag we - * find is the proper start tag for the list sent. - * @param linesAboveArray - * @returns - */ -function getStartBlockAboveLine(linesAboveArray) { - return getStartBlockOrCodeblockAboveLine(linesAboveArray, [findStartTag]); -} -function getEndBlockBelow(linesBelow) { - // Reduce the array down into a single string so that we can - // easily RegEx over the string and find the indicies we're looking for. - let linesBelowStr = linesBelow.reduce((prev, current) => { - return prev + "\n" + current; - }, ""); - let endTagSerachData = findEndTag(linesBelowStr); - let startTagSearchData = findStartTag(linesBelowStr); - let sliceEndIndex = -1; // If neither start or end found we return the entire array. - if (endTagSerachData.found === true && startTagSearchData.found === false) { - sliceEndIndex = endTagSerachData.startPosition; - } - else if (endTagSerachData.found === false && startTagSearchData.found === true) { - sliceEndIndex = startTagSearchData.startPosition; - } - else if (endTagSerachData.found === true && startTagSearchData.found === true) { - sliceEndIndex = endTagSerachData.startPosition; - if (startTagSearchData.startPosition < endTagSerachData.startPosition) { - /** - * If we found a start tag before an end tag we want to use the start tag - * our current block is not properly ended and we use the next start tag - * as our limit - */ - sliceEndIndex = startTagSearchData.startPosition; - } - } - return linesBelow.slice(0, sliceEndIndex); -} -function getStartTagKey(startTag) { - let keySplit = startTag.split(":"); - if (keySplit.length > 1) { - return keySplit[1].replace(" ", ""); - } - return null; -} -const TAB_HEADER_END_REGEX_STR = "^```$"; -const TAB_HEADER_END_REGEX = new RegExp(TAB_HEADER_END_REGEX_STR); -function parseCodeBlockStart(codeBlockLines) { - let id = null; - for (let i = 0; i < codeBlockLines.length; i++) { - let line = codeBlockLines[i]; - if (id === null) { - let key = line.split(":")[0]; - if (key.toLowerCase() === "region id") { - id = line.split(":")[1].trim(); - } - } - else { - if (TAB_HEADER_END_REGEX.test(line)) { - return { id: id, index: i }; - } - } - } - if (id === null) { - return null; - } - else { - return { id: id, index: -1 }; - } -} -const CODEBLOCK_END_REGEX_STR = "```"; -const CODEBLOCK_END_REGEX = new RegExp(CODEBLOCK_END_REGEX_STR); - -/* - * Filename: multi-column-markdown/src/utilities/utils.ts - * Created Date: Tuesday, January 30th 2022, 4:02:19 pm - * Author: Cameron Robinson - * - * Copyright (c) 2022 Cameron Robinson - */ -function getUID(length = 10) { - if (length > 10) { - length = 10; - } - let UID = Math.random().toString(36).substring(2); - UID = UID.slice(0, length); - return UID; -} -/** - * BFS on the child nodes of the passed element searching for the first instance of the - * node type passed. Returning the element found or null if none found. - * - * @param root - * @param nodeTypeName - * @returns - */ -function searchChildrenForNodeType(root, nodeTypeName) { - nodeTypeName = nodeTypeName.toLowerCase(); - let queue = [root]; - while (queue.length > 0) { - for (let i = 0; i < queue.length; i++) { - let node = queue.shift(); - let nodeName = node.nodeName.toLowerCase(); - if (nodeName === nodeTypeName) { - return node; - } - for (let i = 0; i < node.children.length; i++) { - queue.push(node.children[i]); - } - } - } - return null; -} -function fileStillInView(sourcePath) { - let fileLeaf = getFileLeaf(sourcePath); - if (fileLeaf === null) { - return false; - } - return true; -} -function getFileLeaf(sourcePath) { - let markdownLeaves = app.workspace.getLeavesOfType("markdown"); - if (markdownLeaves.length === 0) { - return null; - } - for (let i = 0; i < markdownLeaves.length; i++) { - if (markdownLeaves[i].getViewState().state.file === sourcePath) { - return markdownLeaves[i]; - } - } - return null; -} - -/* - * Filename: multi-column-markdown/src/domObject.ts - * Created Date: Tuesday, February 1st 2022, 12:04:00 pm - * Author: Cameron Robinson - * - * Copyright (c) 2022 Cameron Robinson - */ -const UPDATE_TIMES = [125, 125, 250, 20000]; -const MID_BREAK_ERROR_MESSAGE = "Detected invalid column break syntax.\nPlease make sure column break tags are not in the middle of a paragraph block"; -var DOMObjectTag; -(function (DOMObjectTag) { - DOMObjectTag[DOMObjectTag["none"] = 0] = "none"; - DOMObjectTag[DOMObjectTag["startRegion"] = 1] = "startRegion"; - DOMObjectTag[DOMObjectTag["regionSettings"] = 2] = "regionSettings"; - DOMObjectTag[DOMObjectTag["columnBreak"] = 3] = "columnBreak"; - DOMObjectTag[DOMObjectTag["endRegion"] = 4] = "endRegion"; -})(DOMObjectTag || (DOMObjectTag = {})); -var ElementColumnBreakType; -(function (ElementColumnBreakType) { - ElementColumnBreakType[ElementColumnBreakType["none"] = 0] = "none"; - ElementColumnBreakType[ElementColumnBreakType["preBreak"] = 1] = "preBreak"; - ElementColumnBreakType[ElementColumnBreakType["postBreak"] = 2] = "postBreak"; - ElementColumnBreakType[ElementColumnBreakType["midBreak"] = 3] = "midBreak"; -})(ElementColumnBreakType || (ElementColumnBreakType = {})); -class DOMObject { - constructor(element, linesOfElement, randomID = getUID(), tag = DOMObjectTag.none) { - this.clonedElement = null; - this.elementIsColumnBreak = ElementColumnBreakType.none; - this.elementType = "undefined"; - this.elementContainer = null; - this.elementRenderedHeight = 0; - this.canvasElementUpdateTime = Date.now(); - this.canvasTimerIndex = 0; - this.lastClonedElementUpdateTime = Date.now(); - this.updateTimerIndex = 0; - this.nodeKey = element.innerText.trim(); - this.originalElement = element; - this.UID = randomID; - this.tag = tag; - this.usingOriginalElement = false; - this.linesOfElement = linesOfElement; - if (this.tag === DOMObjectTag.none) { - this.setDomObjectTag(); - } - // If our tag is still none here, we now want to check for - // an in paragraph column break flag. - if (this.tag === DOMObjectTag.none) { - this.checkForPrePostColumnBreak(); - } - } - setMainDOMElement(domElement) { - this.originalElement = domElement; - this.usingOriginalElement = true; - } - clonedElementReadyForUpdate() { - let deltaTime = Date.now() - this.lastClonedElementUpdateTime; - if (deltaTime > UPDATE_TIMES[this.updateTimerIndex]) { - return true; - } - return false; - } - canvasReadyForUpdate() { - var timingArray = UPDATE_TIMES; - let { requiresUpdate, timerIndex, updateTime } = checkIfTimingIsReadyForUpdate(timingArray, this.canvasElementUpdateTime, this.canvasTimerIndex); - if (requiresUpdate === false) { - return false; - } - this.canvasElementUpdateTime = updateTime; - this.canvasTimerIndex = timerIndex; - return true; - } - updateClonedElement(newClonedElement) { - this.clonedElement = newClonedElement; - this.updateClonedElementTimer(); - } - updateClonedElementTimer() { - this.lastClonedElementUpdateTime = Date.now(); - this.updateTimerIndex = Math.clamp(this.updateTimerIndex + 1, 0, UPDATE_TIMES.length - 1); - } - setDomObjectTag() { - let elementTextSpaced = this.linesOfElement.reduce((prev, curr) => { - return prev + "\n" + curr; - }); - if (containsEndTag(this.originalElement.textContent) === true) { - this.elementType = "unRendered"; - this.tag = DOMObjectTag.endRegion; - // el.addClass(MultiColumnStyleCSS.RegionEndTag) - // regionalManager.updateElementTag(currentObject.UID, DOMObjectTag.endRegion); - } - else if (containsColEndTag(this.originalElement.textContent) === true || - (this.originalElement.innerHTML.startsWith("")) && elInnerTextContainsColEndTag(this.originalElement.textContent)) { - this.elementType = "unRendered"; - this.tag = DOMObjectTag.columnBreak; - // el.addClass(MultiColumnStyleCSS.ColumnEndTag) - // regionalManager.updateElementTag(currentObject.UID, DOMObjectTag.columnBreak); - } - else if (containsStartTag(this.originalElement.textContent) === true) { - this.elementType = "unRendered"; - this.tag = DOMObjectTag.startRegion; - // el.addClass(MultiColumnStyleCSS.ColumnEndTag) - // regionalManager.updateElementTag(currentObject.UID, DOMObjectTag.columnBreak); - } - else if (containsColSettingsTag(elementTextSpaced) === true) { - this.elementType = "unRendered"; - // el.addClass(MultiColumnStyleCSS.RegionSettings) - // regionalManager = regionalContainer.setRegionSettings(elementTextSpaced) - // regionalManager.updateElementTag(currentObject.UID, DOMObjectTag.regionSettings); - } - } - checkForPrePostColumnBreak() { - function replaceColBreak(text) { - let colBreakData = checkForParagraphInnerColEndTag(text); - if (containsColumnBreak === null) { - return text; - } - let startIndex = colBreakData.index; - let endIndex = startIndex + colBreakData[0].length; - let pre = text.slice(0, startIndex); - let post = text.slice(endIndex); - return `${pre}${post}`; - } - let textOfElement = this.originalElement.innerText; - let containsColumnBreak = checkForParagraphInnerColEndTag(textOfElement); - if (containsColumnBreak !== null) { - let text = this.originalElement.innerText; - let startIndex = containsColumnBreak.index; - let endIndex = startIndex + containsColumnBreak[0].length; - let pre = text.slice(0, startIndex); - let post = text.slice(endIndex); - // Sometimes the element passed in is a DIV containing a child element, other - // times it is the root child element alone, here we just make sure we are accessing - // the right element we want. - let checkNode = this.originalElement; - if (this.originalElement.nodeName === "DIV") { - checkNode = this.originalElement.children[0]; - } - let paragraph = null; - if (checkNode.nodeName === "P") { - // Paragraphs simply remove the col-break tag - // we set our element here incase we need to display an error. - paragraph = checkNode; - checkNode.innerText = `${pre}${post}`; - } - else if (checkNode.nodeName === "UL" || checkNode.nodeName === "OL") { - // Attempt to get the list item that contains the column break, - // From testing this code should only run when the column break is at the end - // of a list not at the start of the list. - let listItem = null; - for (let i = checkNode.children.length - 1; i >= 0; i--) { - if (checkNode.children[i].nodeName === "LI") { - listItem = checkNode.children[i]; - break; - } - } - if (listItem !== null) { - // Replace, the list element HTML without the col-break text. - listItem.innerHTML = replaceColBreak(listItem.innerHTML); - } - } - else { - console.debug(`Element Type: ${checkNode.nodeName}, does not currently support appened column-breaks.`, checkNode.cloneNode(true)); - // if(paragraph) { - // paragraph.innerText = `${pre}${post}`; - // } - } - // console.debug("Checking where column break is", startIndex, endIndex, text.length); - if (startIndex === 0) { - // console.debug("Column break at begining of element.") - this.elementIsColumnBreak = ElementColumnBreakType.preBreak; - } - else if (endIndex === text.length) { - // console.debug("Column break at end of element.") - this.elementIsColumnBreak = ElementColumnBreakType.postBreak; - } - else { - // console.debug("Column break in the middle of element?") - this.elementIsColumnBreak = ElementColumnBreakType.midBreak; - const ERROR_COLOR_CSS = "mcm-error-message-color"; - const CENTER_ALIGN_SPAN_CSS = "mcm-span-content-alignment-center"; - if (paragraph) { - paragraph.innerHTML = `${pre}\n${MID_BREAK_ERROR_MESSAGE}\n\n${post}`.split("\n").join("
"); - } - } - } - } -} -class TaskListDOMObject extends DOMObject { - constructor(baseDOMObject) { - super(baseDOMObject.originalElement, baseDOMObject.linesOfElement, baseDOMObject.UID, DOMObjectTag.none); - this.originalCheckboxes = []; - this.checkboxElements = new Map(); - } - checkboxClicked(index) { - if (this.checkboxElements.has(index)) { - this.checkboxElements.get(index).click(); - } - if (index < this.originalCheckboxes.length) { - let originalInput = this.originalCheckboxes[index].getElementsByClassName('task-list-item-checkbox'); - if (originalInput.length === 1) { - originalInput[0].click(); - } - // else { - // console.error("Could not find checkbox to click.") - // } - } - } - getCheckboxElement(index) { - var _a; - if (this.checkboxElements.has(index) === false) { - if (index < this.originalCheckboxes.length) { - let originalInput = (_a = this.originalCheckboxes[index]) === null || _a === void 0 ? void 0 : _a.getElementsByClassName('task-list-item-checkbox'); - if ((originalInput === null || originalInput === void 0 ? void 0 : originalInput.length) >= 1) { - this.checkboxElements.set(index, originalInput[0]); - } - // else { - // console.error("Could not find checkbox element to return.", this.originalCheckboxes, index); - // } - } - } - return this.checkboxElements.get(index); - } - static checkForTaskListElement(domElement) { - if (domElement.originalElement.getElementsByClassName("task-list-item").length > 0) { - return new TaskListDOMObject(domElement); - } - return domElement; - } - static getChildCheckbox(el) { - let checkboxElements = el.getElementsByClassName('task-list-item-checkbox'); - if (checkboxElements.length === 1) { - return checkboxElements[0]; - } - return el.children[0]; - } -} -function checkIfTimingIsReadyForUpdate(timingArray, canvasElementUpdateTime, canvasTimerIndex) { - let deltaTime = Date.now() - canvasElementUpdateTime; - if (deltaTime > timingArray[canvasTimerIndex]) { - canvasElementUpdateTime = Date.now(); - canvasTimerIndex = Math.clamp(canvasTimerIndex + 1, 0, UPDATE_TIMES.length - 1); - return { - requiresUpdate: true, - updateTime: canvasElementUpdateTime, - timerIndex: canvasTimerIndex, - }; - } - return { - requiresUpdate: false, - updateTime: canvasElementUpdateTime, - timerIndex: canvasTimerIndex - }; -} - -/* - * File: multi-column-markdown/src/utilities/cssDefinitions.ts - * Created Date: Wednesday, February 16th 2022, 11:09:06 am - * Author: Cameron Robinson - * - * Copyright (c) 2022 Cameron Robinson - */ -var MultiColumnLayoutCSS; -(function (MultiColumnLayoutCSS) { - MultiColumnLayoutCSS["RegionRootContainerDiv"] = "mcm-column-root-container"; - MultiColumnLayoutCSS["RegionErrorContainerDiv"] = "mcm-column-error-region-wrapper"; - MultiColumnLayoutCSS["RegionContentContainerDiv"] = "mcm-column-region-wrapper"; - MultiColumnLayoutCSS["RegionColumnContainerDiv"] = "mcm-column-parent-container"; - MultiColumnLayoutCSS["ColumnDualElementContainer"] = "mcm-column-element-wrapper"; - MultiColumnLayoutCSS["OriginalElementType"] = "mcm-original-column-element"; - MultiColumnLayoutCSS["ClonedElementType"] = "mcm-cloned-column-element"; - MultiColumnLayoutCSS["ContentOverflowAutoScroll_X"] = "mcm-content-overflow-auto-scroll-x"; - MultiColumnLayoutCSS["ContentOverflowAutoScroll_Y"] = "mcm-content-overflow-auto-scroll-y"; - MultiColumnLayoutCSS["ContentOverflowHidden_X"] = "mcm-content-overflow-hidden-x"; - MultiColumnLayoutCSS["ContentOverflowHidden_Y"] = "mcm-content-overflow-hidden-y"; - MultiColumnLayoutCSS["AlignmentLeft"] = "mcm-content-alignment-left"; - MultiColumnLayoutCSS["AlignmentCenter"] = "mcm-content-alignment-center"; - MultiColumnLayoutCSS["AlignmentRight"] = "mcm-content-alignment-right"; - MultiColumnLayoutCSS["TableAlignment"] = "mcm-table-alignment"; - MultiColumnLayoutCSS["NoFlexShrink"] = "mcm-no-flex-shrink"; - MultiColumnLayoutCSS["ReflowContainerDiv"] = "mcm-doc-reflow-container"; - MultiColumnLayoutCSS["ErrorRegionPadding"] = "mcm-column-error-padding"; - // ------------------------------------------------------ // - MultiColumnLayoutCSS["SingleColumnSmall"] = "mcm-single-column-small"; - MultiColumnLayoutCSS["SingleColumnMed"] = "mcm-single-column-medium"; - MultiColumnLayoutCSS["SingleColumnLarge"] = "mcm-single-column-large"; - MultiColumnLayoutCSS["SingleColumnFull"] = "mcm-single-column-full"; - MultiColumnLayoutCSS["SingleColumnLeftLayout"] = "mcm-singlecol-layout-left"; - MultiColumnLayoutCSS["SingleColumnCenterLayout"] = "mcm-singlecol-layout-center"; - MultiColumnLayoutCSS["SingleColumnRightLayout"] = "mcm-singlecol-layout-right"; - // ------------------------------------------------------ // - MultiColumnLayoutCSS["TwoEqualColumns"] = "mcm-two-equal-columns"; - MultiColumnLayoutCSS["TwoColumnSmall"] = "mcm-two-column-small"; - MultiColumnLayoutCSS["TwoColumnLarge"] = "mcm-two-column-large"; - // ------------------------------------------------------ // - MultiColumnLayoutCSS["ThreeEqualColumns"] = "mcm-three-equal-columns"; - MultiColumnLayoutCSS["ThreeColumn_Large"] = "mcm-three-column-large"; - MultiColumnLayoutCSS["ThreeColumn_Small"] = "mcm-three-column-small"; -})(MultiColumnLayoutCSS || (MultiColumnLayoutCSS = {})); -var MultiColumnStyleCSS; -(function (MultiColumnStyleCSS) { - MultiColumnStyleCSS["RegionErrorMessage"] = "mcm-column-error-message"; - MultiColumnStyleCSS["RegionSettings"] = "mcm-column-settings-wrapper"; - MultiColumnStyleCSS["RegionContent"] = "mcm-column-content-wrapper"; - MultiColumnStyleCSS["RegionEndTag"] = "mcm-column-end-tag-wrapper"; - MultiColumnStyleCSS["ColumnEndTag"] = "mcm-column-break-tag-wrapper"; - MultiColumnStyleCSS["RegionShadow"] = "mcm-region-shadow"; - MultiColumnStyleCSS["ColumnShadow"] = "mcm-column-shadow"; - MultiColumnStyleCSS["ColumnBorder"] = "mcm-column-border"; - MultiColumnStyleCSS["ColumnContent"] = "mcm-column-div"; - MultiColumnStyleCSS["SmallFont"] = "mcm-small-font-message"; -})(MultiColumnStyleCSS || (MultiColumnStyleCSS = {})); -var ObsidianStyleCSS; -(function (ObsidianStyleCSS) { - ObsidianStyleCSS["RenderedMarkdown"] = "markdown-rendered"; -})(ObsidianStyleCSS || (ObsidianStyleCSS = {})); - -/** - * File: /src/utilities/elementRenderTypeParser.ts * - * Author: Cameron Robinson * - * * - * Copyright (c) 2023 Cameron Robinson * - */ -function getElementRenderType(element) { - if (isEmbededImage(element) === true) { - return "imageEmbed"; - } - if (isButtonPlugin_CrossCompatibilty(element) === true) { - return "buttonPlugin"; - } - if (isTasksPlugin(element) === true) { - return "tasksPlugin"; - } - /** - * The Dataview plugin needs to be constantly checked if the clone should be - * updated but should not always update the "dual render" aspect, so we add - * a special case for that plugin and maybe others in the future. - */ - if (hasDataview(element) === true) { - return "dataviewPlugin"; - } - else if (isPDFEmbed(element)) { - return "pdfEmbed"; - } - else if (isInternalEmbed(element)) { - return "internalEmbed"; - } - /** - * Some types of content are rendered in canvases which are not rendered properly - * when we clone the original node. Here we are flagging the element as a canvas - * element so we can clone the canvas to a copy element within the region. - * - */ - if (hasDataviewJSCanvas(element) === true) { - return "dataviewJSCanvasEmbed"; - } - if (hasDataviewJS(element) === true) { - return "dataviewJSEmbed"; - } - if (hasDataviewInline(element) === true) { - return "dataviewInlineQuery"; - } - /** - * Look for specific kinds of elements by their CSS class names here. These - * are going to be brittle links as they rely on other plugin definitions but - * as this is only adding in extra compatability to the plugins defined here - * it should be ok. - * - * These may be classes on one of the simple elements (such as a paragraph) - * that we search for below so need to look for these first. - */ - if (hasDiceRoller(element) === true) { - return "diceRoller"; - } - else if (hasCopyButton(element) === true) { - return "calloutCopyButton"; - } - else if (hasAdmonitionFold(element) === true) { - return "admonitionFold"; - } - /** - * This checks for special types of elements that should be rendered normally. Is - * slightly redundant with next check but differentiates between types of ements - * being checked. - */ - if (hasAdmonition(element) === true) { - return "admonition"; - } - else if (isIFrame(element) === true) { - return "iFrameEmbed"; - } - else if (isCustomIFrame(element) === true) { - return "customFramePlugin"; - } - /** - * If we didnt find a special element we want to check for simple elements - * such as paragraphs or lists. In the current implementation we only set up - * the special case for "specialRender" elements so this *should* be saving - * some rendering time by setting these tags properly. - */ - if (hasParagraph(element) || - hasHeader(element) || - hasList(element) || - isHorizontalRule(element) || - isTable(element)) { - return "basicElement"; - } - // If still nothing found we return other as the default response if nothing else found. - return "specialRender"; -} -function hasParagraph(element) { - return element.innerHTML.startsWith(" 0) { - return element.firstChild.nodeName.toLowerCase() === "iframe"; - } - return false; -} -function isTasksPlugin(element) { - return element.hasClass("block-language-tasks") || - element.getElementsByClassName("block-language-tasks").length !== 0; -} -function isHorizontalRule(element) { - return element.innerHTML.startsWith(" 1) ; - return null; -} -function isCustomIFrame(element) { - let isFrame = element.getElementsByClassName("custom-frames-frame").length !== 0; - return isFrame; -} -function isButtonPlugin_CrossCompatibilty(element) { - if (element.hasClass("block-language-button")) { - return true; - } - let buttonPluginBlock = element.getElementsByClassName("block-language-button")[0]; - if (buttonPluginBlock) { - return true; - } - return false; -} -function isEmbededImage(element) { - let img = element.getElementsByTagName("img")[0]; - if (img === null || - img === undefined) { - return false; - } - return true; -} - -/** - * File: /src/dom_manager/regional_managers/RegionManager.ts * - * Created Date: Sunday, May 22nd 2022, 7:49 pm * - * Author: Cameron Robinson * - * * - * Copyright (c) 2022 Cameron Robinson * - */ -class RegionManager { - get numberOfChildren() { - return this.domList.length; - } - get regionParent() { - return this._regionParent; - } - set regionParent(value) { - this._regionParent = value; - } - get errorManager() { - return this._errorManager; - } - set errorManager(value) { - this._errorManager = value; - } - updateErrorManager(newManager, rootElement) { - while (rootElement.children.length > 0) { - rootElement.childNodes.forEach(child => { - rootElement.removeChild(child); - }); - } - this._errorManager = newManager; - this._errorManager.setRegionRootElement(rootElement); - } - constructor(data) { - this.domList = []; - this.domObjectMap = new Map(); - this.regionalSettings = getDefaultMultiColumnSettings(); - this.domList = data.domList; - this.domObjectMap = data.domObjectMap; - this.regionParent = data.regionParent; - this.fileManager = data.fileManager; - this.regionalSettings = data.regionalSettings; - this.regionKey = data.regionKey; - this.errorManager = data.errorManager; - } - getRegionData() { - return { - domList: this.domList, - domObjectMap: this.domObjectMap, - regionParent: this.regionParent, - fileManager: this.fileManager, - regionalSettings: this.regionalSettings, - regionKey: this.regionKey, - rootElement: null, - errorManager: this.errorManager - }; - } - /** - * Adds a new object to the region by finding where it should be relative to its siblings. - * @param siblingsAbove The Markdown text rendered elements for sibilings above this element in the dom - * @param siblingsBelow The Markdown text rendered elements for sibilings below this element in the dom - * @param obj The object to add. - * @returns Returns the index at which the object has been added. - */ - addObject(siblingsAbove, siblingsBelow, obj) { - let nextObj = siblingsBelow.children[0]; - let addAtIndex = siblingsAbove.children.length; - if (siblingsAbove.children.length > 0) { - /** - * We want to find the first sibling withouth "" for an inner text so we can use that to anchor our - * element into the domList. For most items the first element before our new element will have the proper - * innerText. Sometimes other elements are empty and were causing issues. - * - * Now we loop back through the previous siblings looking for the first one with a valid inner text and using that - * as the anchor and offsetting our addAtIndex by the number of empty string elements we found. - */ - let prevSiblingInnerText = ""; - let prevSiblingOffset = 0; - for (let i = siblingsAbove.children.length - 1; i >= 0; i--) { - let obj = siblingsAbove.children[i]; - if (obj.innerText !== "") { - prevSiblingInnerText = obj.innerText; - break; - } - prevSiblingOffset++; - } - for (let i = this.domList.length - 1; i >= 0; i--) { - if (this.domList[i].nodeKey === prevSiblingInnerText) { - addAtIndex = i + 1 + prevSiblingOffset; - break; - } - } - } - let nextElIndex = addAtIndex; - if (nextObj !== undefined) { - nextObj.innerText; - for (let i = addAtIndex; i < this.domList.length; i++) { - if (this.domList[i].nodeKey === nextObj.innerText.trim()) { - nextElIndex = i; - break; - } - } - } - // console.log(" Prev: ", Array.from(siblingsAbove.children).slice(-3), "Adding: ", obj.originalElement, " Next: ", siblingsBelow.children[0], "Overwriting:", this.domList.slice(addAtIndex, nextElIndex)); - this.domList.splice(addAtIndex, nextElIndex - addAtIndex, obj); - this.domObjectMap.set(obj.UID, obj); - // /** - // * Make a copy of the list to log, only because - // * console log updates its references with updates in memory. - // */ - // let x = this.domList.slice(0); - // console.log(x); - return addAtIndex; - } - addObjectAtIndex(obj, index) { - this.domList.splice(index, 0, obj); - this.domObjectMap.set(obj.UID, obj); - } - removeObject(objectUID) { - // /** - // * Make a copy of the list to log - // */ - // let x = domList.slice(0); - // console.log(x); - // Get the object by key, remove it from the map and then - // from the list. - let obj = this.domObjectMap.get(objectUID); - this.domObjectMap.delete(objectUID); - if (obj === undefined) { - return; - } - if (this.domList.contains(obj)) { - this.domList.remove(obj); - } - if (this.domList.length === 0 && this.fileManager !== null) { - this.fileManager.removeRegion(this.regionKey); - } - // x = domList.slice(0); - // console.log(x); - } - updateElementTag(objectUID, newTag) { - let obj = this.domObjectMap.get(objectUID); - obj.tag = newTag; - } - setRegionalSettings(regionSettings) { - this.regionalSettings = regionSettings; - } - /** - * Creates an object containing all necessary information for the region - * to be rendered to the preview pane. - * - * @returns a MultiColumnRenderData object with the root DOM element, settings object, and - * all child objects in the order they should be rendered. - */ - getRegionRenderData() { - return { - parentRenderElement: this.regionParent, - parentRenderSettings: this.regionalSettings, - domObjects: this.domList - }; - } - /** - * This fuction is called when a start tag is removed from view meaning - * our parent element storing the multi-column region is removed. It - * removes the CSS class from all of the elements so they will be - * re-rendered in the preview window. - */ - displayOriginalElements() { - for (let i = 0; i < this.domList.length; i++) { - if (this.domList[i].originalElement) { - this.domList[i].originalElement.removeClasses([MultiColumnStyleCSS.RegionEndTag, - MultiColumnStyleCSS.ColumnEndTag, - MultiColumnStyleCSS.RegionSettings, - MultiColumnStyleCSS.RegionContent]); - if (this.domList[i].originalElement.parentElement) { - this.domList[i].originalElement.parentElement.removeChild(this.domList[i].originalElement); - } - } - } - } - getID() { - return this.regionKey; - } - updateRenderedMarkdown() { - /** - * This function acts as the update loop for the multi-column regions. - * Here we loop through all of the elements within the rendered region and - * potentially update how things are rendered. We need to do this for - * compatability with other plugins. - * - * If the multi-column region is rendered before other plugins that effect - * content within the region our rendered data may not properly display - * the content from the other plugin. Here we loop through the elements - * after all plugins have had a chance to run and can make changes to the - * DOM at this point. - */ - for (let i = 0; i < this.domList.length; i++) { - let elementType = this.domList[i].elementType; - if (elementType === "unRendered") { - continue; - } - /** - * If the element is not currently a special render element we check again - * as the original element may have been updated. - */ - if (elementType === "undefined" || - elementType === "basicElement" || - elementType === "specialRender") { - // If the new result returns as a special renderer we update so - // this wont run again for this item. - elementType = getElementRenderType(this.domList[i].originalElement); - } - let taskListObj = this.domList[i]; - /** - * Here we check for special cases - */ - if (taskListObj && - elementType === "dataviewJSEmbed") { - if (this.domList[i].clonedElementReadyForUpdate()) { - cloneElement(this.domList[i]); - this.fixClonedCheckListButtons(this.domList[i], true); - } - else { - this.fixClonedCheckListButtons(this.domList[i]); - } - continue; - } - if (taskListObj && - elementType === "basicElement") { - this.fixClonedCheckListButtons(this.domList[i]); - continue; - } - if (elementType === "basicElement") { - this.domList[i].elementType = "basicElement"; - continue; - } - if (elementType === "imageEmbed") { //ElementRenderType.fixedElementRender) { - this.domList[i].elementType = elementType; - continue; - } - if (elementType === "buttonPlugin") { - processButtonPluginUpdate(this.domList[i]); - continue; - } - if (elementType === "pdfEmbed") { - this.domList[i].elementType = elementType; - this.setUpDualRender(this.domList[i]); - continue; - } - if (elementType === "diceRoller" || - elementType === "admonitionFold" || - elementType === "calloutCopyButton" || - elementType === "dataviewPlugin" || - elementType === "internalEmbed" || - elementType === "dataviewJSCanvasEmbed" || - elementType === "dataviewJSEmbed" || - elementType === "dataviewInlineQuery" || - elementType === "tasksPlugin") { - this.domList[i].elementType = elementType; - this.setUpDualRender(this.domList[i]); - continue; - } - } - } - /** - * This function takes in the original element and its clone and checks if - * the element contains a task-list-item class. If so it loops through all - * items in the list and fixes their checkboxes to properly fire an event. - * The new checkbox calls the click function on the original checkbox so - * compatability with other plugins *should* remain. - * @param domElement - * @param initalizeCheckboxes - */ - fixClonedCheckListButtons(domElement, initalizeCheckboxes = false) { - if (domElement.originalElement === null || domElement.clonedElement === null) { - return; - } - let element = domElement.originalElement; - let clonedElement = domElement.clonedElement; - let clonedListCheckboxes = Array.from(clonedElement.getElementsByClassName("task-list-item")); - let originalListCheckboxes = Array.from(element.getElementsByClassName("task-list-item")); - if (initalizeCheckboxes === true) { - domElement.originalCheckboxes = originalListCheckboxes; - // When we initalize we remove the old input checkbox that contains - // the weird callback situation causing the bug. Then we create a new - // checkbox to replace it and set it up to fire the click event on - // the original checkbox so functionality is restored. - for (let i = 0; i < originalListCheckboxes.length; i++) { - const checkbox = createEl('input'); - let originalInput = originalListCheckboxes[i].getElementsByTagName("input")[0]; - let isChecked = false; - if (originalInput) { - isChecked = originalInput.checked; - } - else { - console.debug("Could not find original checkbox. Is it null?"); - } - let oldCheckbox = TaskListDOMObject.getChildCheckbox(clonedListCheckboxes[i]); - clonedListCheckboxes[i].replaceChild(checkbox, oldCheckbox); - checkbox.checked = isChecked; - checkbox.addClass('task-list-item-checkbox'); - checkbox.type = 'checkbox'; - checkbox.onClickEvent(() => { - domElement.checkboxClicked(i); - if (checkbox.checked) { - clonedListCheckboxes[i].addClass("is-checked"); - clonedListCheckboxes[i].setAttr("data-task", "x"); - } - else { - clonedListCheckboxes[i].removeClass("is-checked"); - clonedListCheckboxes[i].setAttr("data-task", " "); - } - }); - } - } - else { - // Whenever we reach this point we update our list of original checkboxes - // that may be different from our cache. This is due to how obsidian - // changes the DOM underneath us so we need to constantly update our cache. - domElement.originalCheckboxes = originalListCheckboxes; - } - // When the Tasks plugin is installed the cloned copy of the original element contains - // an extra element for some reason. If this occurs for other reasons here we adjust - // that to keep the clone the same as the original. - if (clonedListCheckboxes.length > originalListCheckboxes.length) { - for (let i = originalListCheckboxes.length; i < clonedListCheckboxes.length; i++) { - try { - clonedListCheckboxes[i].detach(); - } - catch (error) { - console.debug("No child found when removing from list."); - } - } - } - } - setUpDualRender(domElement) { - /** - * If our element is of "specialRender" type it *may* need to be rendered - * using the original element rather than a copy. For example, an element - * may have an onClick event that would not get coppied to the clone. - * - * If we just moved these elements into the region it would get - * moved back out into the original location in the DOM by obsidian - * when scrolling or when the file is updated. On the next refresh it - * would be moved back but that can lead to a region jumping - * around as the item is moved in and out. - * - * Here we set up the div to contain the element and create - * a visual only clone of it. The clone will only be visible - * when the original is not in the multi-column region so it - * saves us from the visual noise of the region jumping around. - */ - let originalElement = domElement.originalElement; - let clonedElement = domElement.clonedElement; - let containerElement = domElement.elementContainer; - // Get height of the original and cloned element. If the element is not currently rendered - // it will have 0 height so we need to temporarily render it to get the height. - let originalElementHeight = getElementClientHeight(originalElement, containerElement); - let clonedElementHeight = getElementClientHeight(clonedElement, containerElement); - if (domElement.elementType === "pdfEmbed") { - updatePDFEmbed(domElement); - return; - } - if (domElement.elementType === "dataviewJSCanvasEmbed") { - reRenderDataviewJS(domElement); - return; - } - /** - * We only want to clone the element once to reduce GC. But if the cloned - * element's height is not equal to the original element, this means the - * item element has been updated somewhere else without the dom being - * refreshed. This can occur when elements are updated by other plugins, - * such as Dataview. - */ - if ((clonedElement === null || - Math.abs(clonedElementHeight - originalElementHeight) > 10 || - domElement.clonedElementReadyForUpdate() === true)) { - // console.log("Updating Cloned Element.", ElementRenderType[domElement.elementType], clonedElementHeight, originalElementHeight) - // Update clone and reference. - cloneElement(domElement); - } - /** - * If the container element has less than 2 children we need to move the - * original element back into it. However some elements constantly get moved - * in and out causing some unwanted behavior. Those element will be tagged - * as specialSingleElementRender so we ignore those elements here. - */ - if (domElement.elementContainer.children.length < 2 && - domElement.elementType !== "dataviewPlugin" && - domElement.elementType !== "internalEmbed" && - domElement.elementType !== "dataviewJSEmbed") { - // console.log("Updating dual rendering.", domElement, domElement.originalElement.parentElement, domElement.originalElement.parentElement?.childElementCount); - // Make sure our CSS is up to date. - originalElement.addClass(MultiColumnLayoutCSS.OriginalElementType); - clonedElement.addClass(MultiColumnLayoutCSS.ClonedElementType); - clonedElement.removeClasses([MultiColumnStyleCSS.RegionContent, MultiColumnLayoutCSS.OriginalElementType]); - for (let i = containerElement.children.length - 1; i >= 0; i--) { - containerElement.children[i].detach(); - } - containerElement.appendChild(originalElement); - containerElement.appendChild(clonedElement); - } - } - /** - * Sets up the CSS classes and the number of columns based on the passed settings. - * @param settings The user defined settings that determine what CSS is set here. - * @param multiColumnParent The parent object that the column divs will be created under. - * @returns The list of column divs created under the passed parent element. - */ - getColumnContentDivs(settings, multiColumnParent) { - let columnContentDivs = []; - if (typeof settings.columnSize === "string" && - isColumnLayout(settings.columnSize) && - (settings.numberOfColumns === 2 || settings.numberOfColumns === 3)) { - settings.columnSize = validateColumnLayout(settings.columnSize); - multiColumnParent.removeClass(MultiColumnLayoutCSS.ContentOverflowAutoScroll_X); - multiColumnParent.addClass(MultiColumnLayoutCSS.ContentOverflowHidden_X); - buildStandardLayouts(settings, multiColumnParent, columnContentDivs); - setMaxColumnHeight(); - return columnContentDivs; - } - if (typeof settings.columnSize === "string" && - isColumnLayout(settings.columnSize) && - settings.columnSize === "standard" && - settings.numberOfColumns > 3) { - settings.columnSize = validateColumnLayout(settings.columnSize); - multiColumnParent.removeClass(MultiColumnLayoutCSS.ContentOverflowAutoScroll_X); - multiColumnParent.addClass(MultiColumnLayoutCSS.ContentOverflowHidden_X); - buildEqualLayout(settings, multiColumnParent, columnContentDivs); - setMaxColumnHeight(); - return columnContentDivs; - } - let columnSizes = []; - // If the user has defined the widths individually then we just need to create - // each column individually with each width size. - if (Array.isArray(settings.columnSize)) { - columnSizes = settings.columnSize.slice(); - } - else { - calcColumnSizes(settings, columnSizes); - } - if (columnSizes.length === 0) { - columnSizes.push(HTMLSizing.create().setWidth(50).setUnits("%")); - } - for (let i = 0; i < settings.numberOfColumns; i++) { - let sizing = getIndexedClampedArrayValue(i, columnSizes); - columnContentDivs.push(multiColumnParent.createDiv({ - cls: `${MultiColumnStyleCSS.ColumnContent}`, - attr: { "style": `width: ${sizing.toString()}` } - })); - if (i !== settings.numberOfColumns - 1) { - multiColumnParent.createDiv({ - cls: `mcm-column-spacer`, - attr: { "style": columnSpacingState(0, settings) } - }); - } - } - for (let i = 0; i < columnContentDivs.length; i++) { - columnContentDivs[i].addClass(MultiColumnLayoutCSS.NoFlexShrink); - } - setMaxColumnHeight(); - return columnContentDivs; - function setMaxColumnHeight() { - if (settings.columnHeight !== null) { - multiColumnParent.removeClass(MultiColumnLayoutCSS.ContentOverflowHidden_Y); - multiColumnParent.addClass(MultiColumnLayoutCSS.ContentOverflowAutoScroll_Y); - columnContentDivs.forEach((column) => { - column.style.height = settings.columnHeight.toString(); - column.style.maxHeight = settings.columnHeight.toString(); - column.style.minHeight = settings.columnHeight.toString(); - }); - } - } - } -} -function createErrorElement(errorText, alt = "", src = "") { - let errorEl = createDiv({ - cls: "internal-embed markdown-embed inline-embed is-loaded", - attr: { - "tabindex": "-1", - "contenteditable": "false" - } - }); - errorEl.setAttr("alt", alt); - errorEl.setAttr("src", `app://obsidian.md/${src}`); - errorEl.appendChild(createDiv({ - "cls": "embed-title markdown-embed-title", - })); - let contentEl = errorEl.createDiv({ - "cls": `markdown-embed-content`, - }); - let paragraph = contentEl.createEl("p", { - "cls": `${MultiColumnStyleCSS.RegionErrorMessage}, ${MultiColumnStyleCSS.SmallFont}` - }); - paragraph.innerText = errorText; - return errorEl; -} -function updatePDFEmbed(domElement) { - // if(domElement.canvasReadyForUpdate() === false) { - // return - // } - domElement.originalElement; - let clonedElement = domElement.clonedElement; - domElement.elementContainer; - for (let i = clonedElement.children.length - 1; i >= 0; i--) { - clonedElement.children[i].detach(); - } - clonedElement.appendChild(createErrorElement("Due to an update to Obsidian's PDF viewer, PDF embeds are currently not supported.\nSorry for the inconvienence.")); - return; -} -function reRenderDataviewJS(domElement) { - if (domElement.canvasReadyForUpdate() === false) { - return; - } - let originalElement = domElement.originalElement; - let clonedElement = domElement.clonedElement; - let containerElement = domElement.elementContainer; - containerElement.appendChild(originalElement); - if (clonedElement !== null && clonedElement.parentElement === containerElement) { - containerElement.removeChild(clonedElement); - } - function cloneCanvas(originalCanvas) { - //create a new canvas - let clonedCanvas = originalCanvas.cloneNode(true); - let context = clonedCanvas.getContext('2d'); - //set dimensions - clonedCanvas.width = originalCanvas.width; - clonedCanvas.height = originalCanvas.height; - if (clonedCanvas.width === 0 || clonedCanvas.height === 0) { - // Dont want to render if the width is 0 as it throws an error - // would happen if the old canvas hasnt been rendered yet. - return clonedCanvas; - } - //apply the old canvas to the new one - context.drawImage(originalCanvas, 0, 0); - //return the new canvas - return clonedCanvas; - } - let canvas = searchChildrenForNodeType(originalElement, "canvas"); - if (canvas !== null) { - domElement.updateClonedElement(originalElement.cloneNode(true)); - clonedElement = domElement.clonedElement; - clonedElement.addClass(MultiColumnLayoutCSS.ClonedElementType); - clonedElement.removeClasses([MultiColumnStyleCSS.RegionContent, MultiColumnLayoutCSS.OriginalElementType]); - containerElement.appendChild(clonedElement); - for (let i = clonedElement.children.length - 1; i >= 0; i--) { - clonedElement.children[i].detach(); - } - clonedElement.appendChild(cloneCanvas(canvas)); - } - containerElement.removeChild(originalElement); - containerElement.appendChild(clonedElement); -} -function calcColumnSizes(settings, columnSizes) { - let layout = settings.columnSize; - if (settings.numberOfColumns === 2) { - switch (layout) { - case ("standard"): - case ("middle"): - case ("center"): - case ("third"): - columnSizes.push(HTMLSizing.create().setWidth(50).setUnits("%")); - columnSizes.push(HTMLSizing.create().setWidth(50).setUnits("%")); - break; - case ("left"): - case ("first"): - columnSizes.push(HTMLSizing.create().setWidth(75).setUnits("%")); - columnSizes.push(HTMLSizing.create().setWidth(25).setUnits("%")); - break; - case ("right"): - case ("second"): - case ("last"): - columnSizes.push(HTMLSizing.create().setWidth(25).setUnits("%")); - columnSizes.push(HTMLSizing.create().setWidth(75).setUnits("%")); - break; - } - return; - } - if (settings.numberOfColumns === 3) { - switch (layout) { - case ("standard"): - columnSizes.push(HTMLSizing.create().setWidth(33).setUnits("%")); - columnSizes.push(HTMLSizing.create().setWidth(33).setUnits("%")); - columnSizes.push(HTMLSizing.create().setWidth(33).setUnits("%")); - break; - case ("left"): - case ("first"): - columnSizes.push(HTMLSizing.create().setWidth(50).setUnits("%")); - columnSizes.push(HTMLSizing.create().setWidth(25).setUnits("%")); - columnSizes.push(HTMLSizing.create().setWidth(25).setUnits("%")); - break; - case ("middle"): - case ("center"): - case ("second"): - columnSizes.push(HTMLSizing.create().setWidth(25).setUnits("%")); - columnSizes.push(HTMLSizing.create().setWidth(50).setUnits("%")); - columnSizes.push(HTMLSizing.create().setWidth(25).setUnits("%")); - break; - case ("right"): - case ("third"): - case ("last"): - columnSizes.push(HTMLSizing.create().setWidth(25).setUnits("%")); - columnSizes.push(HTMLSizing.create().setWidth(25).setUnits("%")); - columnSizes.push(HTMLSizing.create().setWidth(50).setUnits("%")); - break; - } - } -} -function getElementClientHeight(element, parentRenderElement) { - let height = element.clientHeight; - if (height === 0) { - parentRenderElement.appendChild(element); - height = element.clientHeight; - parentRenderElement.removeChild(element); - } - return height; -} -function buildEqualLayout(settings, multiColumnParent, columnContentDivs) { - let percent = Math.ceil(100 / settings.numberOfColumns); - for (let i = 0; i < settings.numberOfColumns; i++) { - columnContentDivs.push(multiColumnParent.createDiv({ - cls: `${MultiColumnStyleCSS.ColumnContent}`, - attr: { "style": `width: ${percent}%` } - })); - if (i !== settings.numberOfColumns - 1) { - multiColumnParent.createDiv({ - cls: `mcm-column-spacer`, - attr: { "style": columnSpacingState(0, settings) } - }); - } - } -} -function buildStandardLayouts(settings, multiColumnParent, columnContentDivs) { - let layout = settings.columnSize; - if (settings.numberOfColumns === 2) { - switch (layout) { - case ("standard"): - case ("middle"): - case ("center"): - case ("third"): - columnContentDivs.push(multiColumnParent.createDiv({ - cls: `${MultiColumnStyleCSS.ColumnContent} ${MultiColumnLayoutCSS.TwoEqualColumns}` - })); - multiColumnParent.createDiv({ - cls: `mcm-column-spacer`, - attr: { "style": columnSpacingState(0, settings) } - }); - columnContentDivs.push(multiColumnParent.createDiv({ - cls: `${MultiColumnStyleCSS.ColumnContent} ${MultiColumnLayoutCSS.TwoEqualColumns}` - })); - break; - case ("left"): - case ("first"): - columnContentDivs.push(multiColumnParent.createDiv({ - cls: `${MultiColumnStyleCSS.ColumnContent} ${MultiColumnLayoutCSS.TwoColumnLarge}` - })); - multiColumnParent.createDiv({ - cls: `mcm-column-spacer`, - attr: { "style": columnSpacingState(0, settings) } - }); - columnContentDivs.push(multiColumnParent.createDiv({ - cls: `${MultiColumnStyleCSS.ColumnContent} ${MultiColumnLayoutCSS.TwoColumnSmall}` - })); - break; - case ("right"): - case ("second"): - case ("last"): - columnContentDivs.push(multiColumnParent.createDiv({ - cls: `${MultiColumnStyleCSS.ColumnContent} ${MultiColumnLayoutCSS.TwoColumnSmall}` - })); - multiColumnParent.createDiv({ - cls: `mcm-column-spacer`, - attr: { "style": columnSpacingState(0, settings) } - }); - columnContentDivs.push(multiColumnParent.createDiv({ - cls: `${MultiColumnStyleCSS.ColumnContent} ${MultiColumnLayoutCSS.TwoColumnLarge}` - })); - break; - } - return; - } - if (settings.numberOfColumns === 3) { - switch (layout) { - case ("standard"): - columnContentDivs.push(multiColumnParent.createDiv({ - cls: `${MultiColumnStyleCSS.ColumnContent} ${MultiColumnLayoutCSS.ThreeEqualColumns}` - })); - multiColumnParent.createDiv({ - cls: `mcm-column-spacer`, - attr: { "style": columnSpacingState(0, settings) } - }); - columnContentDivs.push(multiColumnParent.createDiv({ - cls: `${MultiColumnStyleCSS.ColumnContent} ${MultiColumnLayoutCSS.ThreeEqualColumns}` - })); - multiColumnParent.createDiv({ - cls: `mcm-column-spacer`, - attr: { "style": columnSpacingState(1, settings) } - }); - columnContentDivs.push(multiColumnParent.createDiv({ - cls: `${MultiColumnStyleCSS.ColumnContent} ${MultiColumnLayoutCSS.ThreeEqualColumns}` - })); - break; - case ("left"): - case ("first"): - columnContentDivs.push(multiColumnParent.createDiv({ - cls: `${MultiColumnStyleCSS.ColumnContent} ${MultiColumnLayoutCSS.ThreeColumn_Large}` - })); - multiColumnParent.createDiv({ - cls: `mcm-column-spacer`, - attr: { "style": columnSpacingState(0, settings) } - }); - columnContentDivs.push(multiColumnParent.createDiv({ - cls: `${MultiColumnStyleCSS.ColumnContent} ${MultiColumnLayoutCSS.ThreeColumn_Small}` - })); - multiColumnParent.createDiv({ - cls: `mcm-column-spacer`, - attr: { "style": columnSpacingState(1, settings) } - }); - columnContentDivs.push(multiColumnParent.createDiv({ - cls: `${MultiColumnStyleCSS.ColumnContent} ${MultiColumnLayoutCSS.ThreeColumn_Small}` - })); - break; - case ("middle"): - case ("center"): - case ("second"): - columnContentDivs.push(multiColumnParent.createDiv({ - cls: `${MultiColumnStyleCSS.ColumnContent} ${MultiColumnLayoutCSS.ThreeColumn_Small}` - })); - multiColumnParent.createDiv({ - cls: `mcm-column-spacer`, - attr: { "style": columnSpacingState(0, settings) } - }); - columnContentDivs.push(multiColumnParent.createDiv({ - cls: `${MultiColumnStyleCSS.ColumnContent} ${MultiColumnLayoutCSS.ThreeColumn_Large}` - })); - multiColumnParent.createDiv({ - cls: `mcm-column-spacer`, - attr: { "style": columnSpacingState(1, settings) } - }); - columnContentDivs.push(multiColumnParent.createDiv({ - cls: `${MultiColumnStyleCSS.ColumnContent} ${MultiColumnLayoutCSS.ThreeColumn_Small}` - })); - break; - case ("right"): - case ("third"): - case ("last"): - columnContentDivs.push(multiColumnParent.createDiv({ - cls: `${MultiColumnStyleCSS.ColumnContent} ${MultiColumnLayoutCSS.ThreeColumn_Small}` - })); - multiColumnParent.createDiv({ - cls: `mcm-column-spacer`, - attr: { "style": columnSpacingState(0, settings) } - }); - columnContentDivs.push(multiColumnParent.createDiv({ - cls: `${MultiColumnStyleCSS.ColumnContent} ${MultiColumnLayoutCSS.ThreeColumn_Small}` - })); - multiColumnParent.createDiv({ - cls: `mcm-column-spacer`, - attr: { "style": columnSpacingState(1, settings) } - }); - columnContentDivs.push(multiColumnParent.createDiv({ - cls: `${MultiColumnStyleCSS.ColumnContent} ${MultiColumnLayoutCSS.ThreeColumn_Large}` - })); - break; - } - } -} -function fixOnClick(domElement) { - let originalElement = domElement.originalElement; - let clonedElement = domElement.clonedElement; - let originalButton = originalElement.getElementsByTagName("button")[0]; - let clonedButton = clonedElement.getElementsByTagName("button")[0]; - if (originalButton === undefined || clonedButton === undefined) { - return; - } - clonedButton.onClickEvent((ev) => { - originalButton.click(); - }); -} -function cloneElement(domElement) { - let originalElement = domElement.originalElement; - let clonedElement = domElement.clonedElement; - let containerElement = domElement.elementContainer; - domElement.updateClonedElement(originalElement.cloneNode(true)); - clonedElement = domElement.clonedElement; - /** - * If we updated the cloned element, we want to also update the - * element rendered in the parent container. - */ - for (let i = containerElement.children.length - 1; i >= 0; i--) { - containerElement.children[i].detach(); - } - // Update CSS, we add cloned class and remove classes from originalElement that do not apply. - clonedElement.addClass(MultiColumnLayoutCSS.ClonedElementType); - clonedElement.removeClasses([MultiColumnStyleCSS.RegionContent, MultiColumnLayoutCSS.OriginalElementType]); - containerElement.appendChild(clonedElement); -} -function processButtonPluginUpdate(domObject) { - domObject.elementType = "buttonPlugin"; - if (domObject.clonedElementReadyForUpdate() === true) { - cloneElement(domObject); - fixOnClick(domObject); - } -} - -const DEFAULT_SETTINGS = { - renderOnMobile: true, - autoLayoutBalanceIterations: 5, - useLivePreviewCache: false, - alignTablesToContentAlignment: true, - renderInlineElErrors: true -}; -class MCM_SettingsManager { - constructor() { - this._settings = DEFAULT_SETTINGS; - } - static get shared() { - if (MCM_SettingsManager.local === null) { - MCM_SettingsManager.local = new MCM_SettingsManager(); - } - return MCM_SettingsManager.local; - } - get settings() { return this._settings; } - set settings(newVal) { - this.updateTimestamp(); - this._settings = newVal; - } - get lastUpdateTimestamp() { return this._lastUpdateTimestamp; } - updateTimestamp() { - this._lastUpdateTimestamp = Date.now(); - } - get renderOnMobile() { return this._settings.renderOnMobile; } - get autoLayoutBalanceIterations() { return this._settings.autoLayoutBalanceIterations; } - get useLivePreviewCache() { return this._settings.useLivePreviewCache; } - get alignTablesToContentAlignment() { return this._settings.alignTablesToContentAlignment; } - get renderInlineElErrors() { return this._settings.renderInlineElErrors; } - set renderOnMobile(newVal) { - this.updateTimestamp(); - this._settings.renderOnMobile = newVal; - } - set autoLayoutBalanceIterations(newVal) { - this.updateTimestamp(); - this._settings.autoLayoutBalanceIterations = newVal; - } - set useLivePreviewCache(newVal) { - this.updateTimestamp(); - this._settings.useLivePreviewCache = newVal; - } - set alignTablesToContentAlignment(newVal) { - this.updateTimestamp(); - this._settings.alignTablesToContentAlignment = newVal; - } - set renderInlineElErrors(newVal) { - this.updateTimestamp(); - this._settings.renderInlineElErrors = newVal; - } -} -MCM_SettingsManager.local = null; - -/** - * File: /src/dom_manager/regional_managers/regionDOMManager.ts * - * Created Date: Sunday, May 22nd 2022, 7:46 pm * - * Author: Cameron Robinson * - * * - * Copyright (c) 2022 Cameron Robinson * - */ -class StandardMultiColumnRegionManager extends RegionManager { - renderRegionElementsToScreen() { - this.renderColumnMarkdown(this.regionParent, this.domList, this.regionalSettings); - } - exportRegionElementsToPDF(pdfParentElement) { - // Default set shadow to off for exporting PDFs - let renderSettings = this.regionalSettings; - renderSettings.drawShadow = false; - this.renderColumnMarkdown(pdfParentElement, this.domList.slice(), renderSettings); - } - renderRegionElementsToLivePreview(parentElement) { - this.renderColumnMarkdown(parentElement, this.domList, this.regionalSettings, true); - } - /** - * This function takes in the data for the multi-column region and sets up the - * user defined number of children with the proper css classes to be rendered properly. - * - * @param parentElement The element that the multi-column region will be rendered under. - * @param regionElements The list of DOM objects that will be coppied under the parent object - * @param settings The settings the user has defined for the region. - */ - renderColumnMarkdown(parentElement, regionElements, settings, isLivePreview = false) { - let multiColumnParent = createDiv({ - cls: `${MultiColumnLayoutCSS.RegionColumnContainerDiv} \ - ${MultiColumnLayoutCSS.ContentOverflowAutoScroll_X} \ - ${MultiColumnLayoutCSS.ContentOverflowHidden_Y}; - ` - }); - /** - * Pass our parent div and settings to parser to create the required - * column divs as children of the parent. - */ - let columnContentDivs = this.getColumnContentDivs(settings, multiColumnParent); - if (settings.drawShadow === true) { - multiColumnParent.addClass(MultiColumnStyleCSS.RegionShadow); - } - for (let i = 0; i < columnContentDivs.length; i++) { - if (shouldDrawColumnBorder(i, settings) === true) { - columnContentDivs[i].addClass(MultiColumnStyleCSS.ColumnBorder); - } - if (settings.drawShadow === true) { - columnContentDivs[i].addClass(MultiColumnStyleCSS.ColumnShadow); - } - } - // Create markdown renderer to parse the passed markdown - // between the tags. - let markdownRenderChild = new obsidian.MarkdownRenderChild(multiColumnParent); - // Remove every other child from the parent so - // we dont end up with multiple sets of data. This should - // really only need to loop once for i = 0 but loop just - // in case. - for (let i = parentElement.children.length - 1; i >= 0; i--) { - parentElement.children[i].detach(); - } - parentElement.appendChild(markdownRenderChild.containerEl); - this.appendElementsToColumns(regionElements, columnContentDivs, settings, isLivePreview); - } - appendElementsToColumns(regionElements, columnContentDivs, settings, isLivePreview = false) { - let columnIndex = 0; - for (let i = 0; i < regionElements.length; i++) { - if (regionElements[i].tag === DOMObjectTag.none || - regionElements[i].tag === DOMObjectTag.columnBreak) { - // If a standard element contains a column break tag and it is set as a pre content break tag we flip our index here. - if (regionElements[i].tag === DOMObjectTag.none && - regionElements[i].elementIsColumnBreak === ElementColumnBreakType.preBreak && - (columnIndex + 1) < settings.numberOfColumns) { - columnIndex++; - } - // We store the elements in a wrapper container until we determine - let element = createDiv({ - cls: MultiColumnLayoutCSS.ColumnDualElementContainer, - }); - if (columnOverflowState(columnIndex, settings) === ContentOverflowType.hidden) { - element.addClass(MultiColumnLayoutCSS.ContentOverflowHidden_X); - } - else { - element.addClass(MultiColumnLayoutCSS.ContentOverflowAutoScroll_X); - } - let alignment = columnAlignmentState(columnIndex, settings); - if (alignment === AlignmentType.center) { - element.addClass(MultiColumnLayoutCSS.AlignmentCenter); - } - else if (alignment === AlignmentType.right) { - element.addClass(MultiColumnLayoutCSS.AlignmentRight); - } - else { - element.addClass(MultiColumnLayoutCSS.AlignmentLeft); - } - let tableAlignment = MCM_SettingsManager.shared.alignTablesToContentAlignment; - if (settings.alignTablesToAlignment !== TableAlignment.useSettingsDefault) { - tableAlignment = settings.alignTablesToAlignment === TableAlignment.align; - } - if (tableAlignment) { - element.addClass(MultiColumnLayoutCSS.TableAlignment); - } - regionElements[i].elementContainer = element; - let elementToAppend = regionElements[i].originalElement; - if (isLivePreview === false) { - let clonedElement = regionElements[i].originalElement.cloneNode(true); - let headingCollapseElement = getHeadingCollapseElement(clonedElement); - if (headingCollapseElement !== null) { - // This removes the collapse arrow from the view if it exists. - headingCollapseElement.detach(); - } - regionElements[i].clonedElement = clonedElement; - elementToAppend = clonedElement; - } - element.appendChild(elementToAppend); - if (regionElements[i] instanceof TaskListDOMObject) { - this.fixClonedCheckListButtons(regionElements[i], true); - } - if (element !== null && regionElements[i].tag !== DOMObjectTag.columnBreak) { - columnContentDivs[columnIndex].appendChild(element); - } - /** - * If the tag is a column break we update the column index after - * appending the item to the column div. This keeps the main DOM - * cleaner by removing other items and placing them all within - * a region container. - */ - if (regionElements[i].tag === DOMObjectTag.columnBreak && - (columnIndex + 1) < settings.numberOfColumns) { - columnIndex++; - } - else if (regionElements[i].tag === DOMObjectTag.none && - regionElements[i].elementIsColumnBreak === ElementColumnBreakType.postBreak && - (columnIndex + 1) < settings.numberOfColumns) { - // If a standard element contains a column break tag and it is set as a post content break tag we flip our index here. - columnIndex++; - } - } - } - } -} - -/** - * File: /src/dom_manager/regional_managers/singleColumnRegionManager.ts * - * Author: Cameron Robinson * - * * - * Copyright (c) 2023 Cameron Robinson * - */ -class SingleColumnRegionManager extends RegionManager { - renderRegionElementsToScreen() { - this.renderColumnMarkdown(this.regionParent, this.domList, this.regionalSettings); - } - exportRegionElementsToPDF(pdfParentElement) { - // Default set shadow to off for exporting PDFs - let renderSettings = this.regionalSettings; - renderSettings.drawShadow = false; - this.renderColumnMarkdown(pdfParentElement, this.domList.slice(), renderSettings); - } - renderRegionElementsToLivePreview(parentElement) { - this.renderColumnMarkdown(parentElement, this.domList, this.regionalSettings, true); - } - /** - * This function takes in the data for the multi-column region and sets up the - * user defined number of children with the proper css classes to be rendered properly. - * - * @param parentElement The element that the multi-column region will be rendered under. - * @param regionElements The list of DOM objects that will be coppied under the parent object - * @param settings The settings the user has defined for the region. - */ - renderColumnMarkdown(parentElement, regionElements, settings, isLivePreview = false) { - let multiColumnParent = createDiv({ - cls: `${MultiColumnLayoutCSS.RegionColumnContainerDiv} \ - ${MultiColumnLayoutCSS.ContentOverflowAutoScroll_X} \ - ${MultiColumnLayoutCSS.ContentOverflowHidden_Y}; - ` - }); - if (isLeftLayout(this.regionalSettings.columnPosition)) { - multiColumnParent.addClass(MultiColumnLayoutCSS.SingleColumnLeftLayout); - } - else if (isRightLayout(this.regionalSettings.columnPosition)) { - multiColumnParent.addClass(MultiColumnLayoutCSS.SingleColumnRightLayout); - } - else { - multiColumnParent.addClass(MultiColumnLayoutCSS.SingleColumnCenterLayout); - } - /** - * Pass our parent div and settings to parser to create the required - * column divs as children of the parent. - */ - let columnContentDiv = this.createColumnContentDivs(multiColumnParent); - if (shouldDrawColumnBorder(0, settings) === true) { - columnContentDiv.addClass(MultiColumnStyleCSS.ColumnBorder); - } - if (settings.drawShadow === true) { - columnContentDiv.addClass(MultiColumnStyleCSS.ColumnShadow); - } - // Create markdown renderer to parse the passed markdown - // between the tags. - let markdownRenderChild = new obsidian.MarkdownRenderChild(multiColumnParent); - // Remove every other child from the parent so - // we dont end up with multiple sets of data. This should - // really only need to loop once for i = 0 but loop just - // in case. - for (let i = parentElement.children.length - 1; i >= 0; i--) { - parentElement.children[i].detach(); - } - parentElement.appendChild(markdownRenderChild.containerEl); - this.appendElementsToColumns(regionElements, columnContentDiv, settings, isLivePreview); - } - appendElementsToColumns(regionElements, columnContentDiv, settings, isLivePreview = false) { - for (let i = 0; i < regionElements.length; i++) { - if (regionElements[i].tag === DOMObjectTag.none || - regionElements[i].tag === DOMObjectTag.columnBreak) { - // We store the elements in a wrapper container until we determine - let element = createDiv({ - cls: MultiColumnLayoutCSS.ColumnDualElementContainer, - }); - regionElements[i].elementContainer = element; - if (columnOverflowState(0, settings) === ContentOverflowType.hidden) { - element.addClass(MultiColumnLayoutCSS.ContentOverflowHidden_X); - } - else { - element.addClass(MultiColumnLayoutCSS.ContentOverflowAutoScroll_X); - } - let alignment = columnAlignmentState(0, settings); - if (alignment === AlignmentType.center) { - element.addClass(MultiColumnLayoutCSS.AlignmentCenter); - } - else if (alignment === AlignmentType.right) { - element.addClass(MultiColumnLayoutCSS.AlignmentRight); - } - else { - element.addClass(MultiColumnLayoutCSS.AlignmentLeft); - } - let tableAlignment = MCM_SettingsManager.shared.alignTablesToContentAlignment; - if (settings.alignTablesToAlignment !== TableAlignment.useSettingsDefault) { - tableAlignment = settings.alignTablesToAlignment === TableAlignment.align; - } - if (tableAlignment) { - element.addClass(MultiColumnLayoutCSS.TableAlignment); - } - let elementToAppend = regionElements[i].originalElement; - if (isLivePreview === false) { - let clonedElement = regionElements[i].originalElement.cloneNode(true); - let headingCollapseElement = getHeadingCollapseElement(clonedElement); - if (headingCollapseElement !== null) { - // This removes the collapse arrow from the view if it exists. - headingCollapseElement.detach(); - } - regionElements[i].clonedElement = clonedElement; - elementToAppend = clonedElement; - } - element.appendChild(elementToAppend); - if (regionElements[i] instanceof TaskListDOMObject) { - this.fixClonedCheckListButtons(regionElements[i], true); - } - if (element !== null) { - columnContentDiv.appendChild(element); - } - } - } - } - createColumnContentDivs(multiColumnParent) { - let contentDiv = multiColumnParent.createDiv({ - cls: `${MultiColumnStyleCSS.ColumnContent}` - }); - if (this.regionalSettings.columnSize === "small") { - contentDiv.addClass(`${MultiColumnLayoutCSS.SingleColumnSmall}`); - } - else if (this.regionalSettings.columnSize === "large") { - contentDiv.addClass(`${MultiColumnLayoutCSS.SingleColumnLarge}`); - } - else if (this.regionalSettings.columnSize === "full") { - contentDiv.addClass(`${MultiColumnLayoutCSS.SingleColumnFull}`); - } - else { - contentDiv.addClass(`${MultiColumnLayoutCSS.SingleColumnMed}`); - } - return contentDiv; - } -} -function isLeftLayout(layout) { - if (layout === "left" || - layout === "first") { - return true; - } - return false; -} -function isRightLayout(layout) { - if (layout === "right" || - layout === "third" || - layout === "last") { - return true; - } - return false; -} - -/** - * File: /src/dom_manager/regional_managers/autoLayoutRegionManager.ts * - * Created Date: Sunday, May 22nd 2022, 10:23 pm * - * Author: Cameron Robinson * - * * - * Copyright (c) 2022 Cameron Robinson * - */ -class AutoLayoutRegionManager extends RegionManager { - constructor(data, isLivePreview = false) { - super(data); - this.isLivePreview = false; - this.previousColumnHeights = []; - this.isLivePreview = isLivePreview; - this.docReflow = data.regionalSettings.fullDocReflow; - } - renderRegionElementsToScreen() { - this.renderColumnMarkdown(this.regionParent, this.domList, this.regionalSettings); - } - exportRegionElementsToPDF(pdfParentElement) { - // Default set shadow to off for exporting PDFs - let renderSettings = this.regionalSettings; - renderSettings.drawShadow = false; - this.renderColumnMarkdown(pdfParentElement, this.domList.slice(), renderSettings); - } - renderRegionElementsToLivePreview(parentElement) { - this.renderColumnMarkdown(parentElement, this.domList, this.regionalSettings, true); - } - /** - * This function takes in the data for the multi-column region and sets up the - * user defined number of children with the proper css classes to be rendered properly. - * - * @param parentElement The element that the multi-column region will be rendered under. - * @param regionElements The list of DOM objects that will be coppied under the parent object - * @param settings The settings the user has defined for the region. - */ - renderColumnMarkdown(parentElement, regionElements, settings, isLivePreview = false) { - let multiColumnParent = createDiv({ - cls: `${MultiColumnLayoutCSS.RegionColumnContainerDiv} \ - ${MultiColumnLayoutCSS.ContentOverflowAutoScroll_X} \ - ${MultiColumnLayoutCSS.ContentOverflowHidden_Y}; - ` - }); - this.columnParent = multiColumnParent; - /** - * Pass our parent div and settings to parser to create the required - * column divs as children of the parent. - */ - this.columnDivs = this.getColumnContentDivs(settings, multiColumnParent); - if (settings.drawShadow === true) { - multiColumnParent.addClass(MultiColumnStyleCSS.RegionShadow); - } - for (let i = 0; i < this.columnDivs.length; i++) { - if (shouldDrawColumnBorder(i, settings) === true) { - this.columnDivs[i].addClass(MultiColumnStyleCSS.ColumnBorder); - } - if (settings.drawShadow === true) { - this.columnDivs[i].addClass(MultiColumnStyleCSS.ColumnShadow); - } - } - // Remove every other child from the parent so - // we dont end up with multiple sets of data. This should - // really only need to loop once for i = 0 but loop just - // in case. - for (let i = parentElement.children.length - 1; i >= 0; i--) { - parentElement.children[i].detach(); - } - parentElement.appendChild(multiColumnParent); - this.appendElementsToColumns(regionElements, this.columnDivs, settings, isLivePreview); - } - appendElementsToColumns(regionElements, columnContentDivs, settings, isLivePreview = false) { - function balanceElements() { - let totalHeight = regionElements.map((el, index) => { - // We only want to attempt to update the elementRenderedHeight if it is 0 and if it is not an unrendered element such as a endregion tag. - if (el.elementRenderedHeight === 0 && - el.tag !== DOMObjectTag.columnBreak && - el.tag !== DOMObjectTag.endRegion && - el.tag !== DOMObjectTag.regionSettings && - el.tag !== DOMObjectTag.startRegion) { - // Add element to rendered div so we can extract the rendered height. - columnContentDivs[0].appendChild(el.originalElement); - el.elementRenderedHeight = el.originalElement.clientHeight; - columnContentDivs[0].removeChild(el.originalElement); - } - return el.elementRenderedHeight; - }).reduce((prev, curr) => { return prev + curr; }, 0); - let maxColumnContentHeight = Math.trunc(totalHeight / settings.numberOfColumns); - for (let i = 0; i < columnContentDivs.length; i++) { - for (let j = columnContentDivs[i].children.length - 1; j >= 0; j--) { - columnContentDivs[i].children[j].detach(); - } - } - let columnIndex = 0; - let currentColumnHeight = 0; - function checkShouldSwitchColumns(nextElementHeight) { - if (currentColumnHeight + nextElementHeight > maxColumnContentHeight && - (columnIndex + 1) < settings.numberOfColumns) { - columnIndex++; - currentColumnHeight = 0; - } - } - for (let i = 0; i < regionElements.length; i++) { - if (regionElements[i].tag === DOMObjectTag.none || - regionElements[i].tag === DOMObjectTag.columnBreak) { - /** - * Here we check if we need to swap to the next column for the current element. - * If the user wants to keep headings with the content below it we also make sure - * that the last item in a column is not a header element by using the header and - * the next element's height as the height value. - */ - if (hasHeader(regionElements[i].originalElement) === true) { // TODO: Add this as selectable option. - let headerAndNextElementHeight = regionElements[i].elementRenderedHeight; - if (i < regionElements.length - 1) { - headerAndNextElementHeight += regionElements[i + 1].elementRenderedHeight; - } - checkShouldSwitchColumns(headerAndNextElementHeight); - } - else { - checkShouldSwitchColumns(regionElements[i].elementRenderedHeight); - } - currentColumnHeight += regionElements[i].elementRenderedHeight; - /** - * We store the elements in a wrapper container until we determine if we want to - * use the original element or a clone of the element. This helps us by allowing - * us to create a visual only clone while the update loop moves the original element - * into the columns. - */ - let element = createDiv({ - cls: MultiColumnLayoutCSS.ColumnDualElementContainer, - }); - regionElements[i].elementContainer = element; - if (columnOverflowState(columnIndex, settings) === ContentOverflowType.hidden) { - element.addClass(MultiColumnLayoutCSS.ContentOverflowHidden_X); - } - else { - element.addClass(MultiColumnLayoutCSS.ContentOverflowAutoScroll_X); - } - let alignment = columnAlignmentState(columnIndex, settings); - if (alignment === AlignmentType.center) { - element.addClass(MultiColumnLayoutCSS.AlignmentCenter); - } - else if (alignment === AlignmentType.right) { - element.addClass(MultiColumnLayoutCSS.AlignmentRight); - } - else { - element.addClass(MultiColumnLayoutCSS.AlignmentLeft); - } - let tableAlignment = MCM_SettingsManager.shared.alignTablesToContentAlignment; - if (settings.alignTablesToAlignment !== TableAlignment.useSettingsDefault) { - tableAlignment = settings.alignTablesToAlignment === TableAlignment.align; - } - if (tableAlignment) { - element.addClass(MultiColumnLayoutCSS.TableAlignment); - } - let elementToAppend = regionElements[i].originalElement; - if (isLivePreview === false) { - let clonedElement = regionElements[i].clonedElement; - if (regionElements[i].clonedElement === null) { - clonedElement = regionElements[i].originalElement.cloneNode(true); - let headingCollapseElement = getHeadingCollapseElement(clonedElement); - if (headingCollapseElement !== null) { - // This removes the collapse arrow from the view if it exists. - headingCollapseElement.detach(); - } - regionElements[i].clonedElement = clonedElement; - elementToAppend = clonedElement; - } - } - element.appendChild(elementToAppend); - if (regionElements[i] instanceof TaskListDOMObject) { - this.fixClonedCheckListButtons(regionElements[i], true); - } - if (element !== null && - columnContentDivs[columnIndex] && - regionElements[i].tag !== DOMObjectTag.columnBreak) { - columnContentDivs[columnIndex].appendChild(element); - regionElements[i].elementRenderedHeight = element.clientHeight; - } - /** - * If the tag is a column break we update the column index after - * appending the item to the column div. This keeps the main DOM - * cleaner by removing other items and placing them all within - * a region container. - * - * Removing the end column tag as an option for now. - */ - // if (regionElements[i].tag === DOMObjectTag.columnBreak && - // (columnIndex + 1) < settings.numberOfColumns) { - // columnIndex++; - // currentColumnHeight = 0; - // } - } - } - } - /** - * Attempt to balanced the elements. We need to iterate over the elements multiple times because - * our initial balance estimate may not be perfectly balanced due to different column widths causing - * elements within them to be of different heights. This can cause the elements to jump around on - * subsiquent update loops which is not ideal. Here we render the elements to the screen and update - * their height after being rendered into the estimated position. - * - * Once everything is rendered we check all of the column heights against our last iteration and - * if nothing has changed we know we are balanced. - * - * There is probably a better way of accomplishing this task but this works for the time being. - */ - let autoLayoutBalanceIterations = 1; - if (this.isLivePreview === false) { - autoLayoutBalanceIterations = MCM_SettingsManager.shared.autoLayoutBalanceIterations; - } - for (let i = 0; i < autoLayoutBalanceIterations; i++) { - balanceElements(); - let balanced = true; - for (let j = 0; j < columnContentDivs.length; j++) { - // If the column heights are undefined we set default to zero so not to encounter an error. - if (!this.previousColumnHeights[j]) { - this.previousColumnHeights.push(0); - } - // if this render height is not the same as the previous height we are still balancing. - if (this.previousColumnHeights[j] !== columnContentDivs[j].clientHeight) { - this.previousColumnHeights[j] = columnContentDivs[j].clientHeight; - balanced = false; - } - } - // if we made it out of the loop and all of the columns are the same height as last update - // we're balanced so we can break out of the loop. - if (balanced === true) { - break; - } - } - } - updateRenderedMarkdown() { - if (this.docReflow === true) { - super.updateRenderedMarkdown(); - return; - } - for (let i = 0; i < this.domList.length; i++) { - let el = this.domList[i]; - let originalClientHeight = 0; - if (el.originalElement) { - originalClientHeight = el.originalElement.clientHeight; - } - let clonedClientHeight = 0; - if (el.clonedElement) { - clonedClientHeight = el.clonedElement.clientHeight; - } - if (originalClientHeight < clonedClientHeight) { - this.domList[i].elementRenderedHeight = clonedClientHeight; - } - else { - this.domList[i].elementRenderedHeight = originalClientHeight; - } - } - let validColumns = true; - if (this.columnParent !== null && this.columnDivs !== null && this.columnDivs !== undefined && - this.columnDivs.length === this.regionalSettings.numberOfColumns) { - let totalHeight = this.domList.map((el, index) => { - // We only want to attempt to update the elementRenderedHeight if it is 0 and if it is not an unrendered element such as a endregion tag. - if (el.elementRenderedHeight === 0 && - el.tag !== DOMObjectTag.columnBreak && - el.tag !== DOMObjectTag.endRegion && - el.tag !== DOMObjectTag.regionSettings && - el.tag !== DOMObjectTag.startRegion) { - // Add element to rendered div so we can extract the rendered height. - this.columnParent.appendChild(el.originalElement); - el.elementRenderedHeight = el.originalElement.clientHeight; - this.columnParent.removeChild(el.originalElement); - } - return el.elementRenderedHeight; - }).reduce((prev, curr) => { return prev + curr; }, 0); - let maxColumnContentHeight = Math.trunc(totalHeight / this.regionalSettings.numberOfColumns); - for (let i = 0; i < this.columnDivs.length - 1; i++) { - let columnHeight = 0; - for (let j = 0; j < this.columnDivs[i].children.length; j++) { - columnHeight += this.columnDivs[i].children[j].clientHeight; - } - if (columnHeight > maxColumnContentHeight) { - validColumns = false; - break; - } - } - } - if (validColumns === false) { - this.renderColumnMarkdown(this.regionParent, this.domList, this.regionalSettings); - } - super.updateRenderedMarkdown(); - } -} - -/** - * File: /src/dom_manager/regional_managers/reflowRegionManager.ts * - * Created Date: Thursday, May 11th 2023, 9:59 pm * - * Author: Cameron Robinson * - * * - * Copyright (c) 2023 Cameron Robinson * - */ -class ReflowRegionManager extends RegionManager { - renderRegionElementsToScreen() { - this.renderColumnMarkdown(this.regionParent, this.domList, this.regionalSettings); - } - exportRegionElementsToPDF(pdfParentElement) { - // Default set shadow to off for exporting PDFs - let renderSettings = this.regionalSettings; - renderSettings.drawShadow = false; - this.renderColumnMarkdown(pdfParentElement, this.domList.slice(), renderSettings); - } - renderRegionElementsToLivePreview(parentElement) { - this.renderColumnMarkdown(parentElement, this.domList, this.regionalSettings); - } - /** - * This function takes in the data for the multi-column region and sets up the - * user defined number of children with the proper css classes to be rendered properly. - * - * @param parentElement The element that the multi-column region will be rendered under. - * @param regionElements The list of DOM objects that will be coppied under the parent object - * @param settings The settings the user has defined for the region. - */ - renderColumnMarkdown(parentElement, regionElements, settings) { - let verticalColumnParent = createDiv({ - cls: `` - }); - /** - * Pass our parent div and settings to parser to create the required - * column divs as children of the parent. - */ - // Remove every other child from the parent so - // we dont end up with multiple sets of data. This should - // really only need to loop once for i = 0 but loop just - // in case. - for (let i = parentElement.children.length - 1; i >= 0; i--) { - parentElement.children[i].detach(); - } - parentElement.appendChild(verticalColumnParent); - this.appendElementsToColumns(verticalColumnParent, regionElements, settings); - } - appendElementsToColumns(verticalColumnParent, regionElements, settings) { - this.domList.forEach((el, index) => { - // We only want to attempt to update the elementRenderedHeight if it is 0 and if it is not an unrendered element such as a endregion tag. - if (el.elementRenderedHeight === 0 && - el.tag !== DOMObjectTag.columnBreak && - el.tag !== DOMObjectTag.endRegion && - el.tag !== DOMObjectTag.regionSettings && - el.tag !== DOMObjectTag.startRegion) { - // Add element to rendered div so we can extract the rendered height. - verticalColumnParent.appendChild(el.originalElement); - el.elementRenderedHeight = el.originalElement.clientHeight; - verticalColumnParent.removeChild(el.originalElement); - } - }); - let maxColumnContentHeight = settings.columnHeight.sizeValue; - let columnIndex = 0; - let currentColumnHeight = 0; - let divCount = 1; - let colDivsCallback = (settings, multiColumnParent) => { - return this.getColumnContentDivs(settings, multiColumnParent); - }; - let columns = getFormattedColumnDivs(settings, verticalColumnParent, colDivsCallback, divCount); - for (let i = 0; i < regionElements.length; i++) { - if (regionElements[i].tag === DOMObjectTag.none || - regionElements[i].tag === DOMObjectTag.columnBreak) { - /** - * Here we check if we need to swap to the next column for the current element. - * If the user wants to keep headings with the content below it we also make sure - * that the last item in a column is not a header element by using the header and - * the next element's height as the height value. - */ - if (hasHeader(regionElements[i].originalElement) === true) { // TODO: Add this as selectable option. - let headerAndNextElementHeight = regionElements[i].elementRenderedHeight; - if (i < regionElements.length - 1) { - headerAndNextElementHeight += regionElements[i + 1].elementRenderedHeight; - } - checkShouldSwitchColumns(headerAndNextElementHeight); - } - else { - checkShouldSwitchColumns(regionElements[i].elementRenderedHeight); - } - currentColumnHeight += regionElements[i].elementRenderedHeight; - /** - * We store the elements in a wrapper container until we determine if we want to - * use the original element or a clone of the element. This helps us by allowing - * us to create a visual only clone while the update loop moves the original element - * into the columns. - */ - let element = createDiv({ - cls: MultiColumnLayoutCSS.ColumnDualElementContainer, - }); - regionElements[i].elementContainer = element; - if (columnOverflowState(columnIndex, settings) === ContentOverflowType.hidden) { - element.addClass(MultiColumnLayoutCSS.ContentOverflowHidden_X); - } - else { - element.addClass(MultiColumnLayoutCSS.ContentOverflowAutoScroll_X); - } - let alignment = columnAlignmentState(columnIndex, settings); - if (alignment === AlignmentType.center) { - element.addClass(MultiColumnLayoutCSS.AlignmentCenter); - } - else if (alignment === AlignmentType.right) { - element.addClass(MultiColumnLayoutCSS.AlignmentRight); - } - else { - element.addClass(MultiColumnLayoutCSS.AlignmentLeft); - } - let tableAlignment = MCM_SettingsManager.shared.alignTablesToContentAlignment; - if (settings.alignTablesToAlignment !== TableAlignment.useSettingsDefault) { - tableAlignment = settings.alignTablesToAlignment === TableAlignment.align; - } - if (tableAlignment) { - element.addClass(MultiColumnLayoutCSS.TableAlignment); - } - let clonedElement = regionElements[i].clonedElement; - if (regionElements[i].clonedElement === null) { - clonedElement = regionElements[i].originalElement.cloneNode(true); - let headingCollapseElement = getHeadingCollapseElement(clonedElement); - if (headingCollapseElement !== null) { - // This removes the collapse arrow from the view if it exists. - headingCollapseElement.detach(); - } - regionElements[i].clonedElement = clonedElement; - } - element.appendChild(clonedElement); - if (regionElements[i] instanceof TaskListDOMObject) { - this.fixClonedCheckListButtons(regionElements[i], true); - } - if (element !== null && - columns[columnIndex] && - regionElements[i].tag !== DOMObjectTag.columnBreak) { - columns[columnIndex].appendChild(element); - regionElements[i].elementRenderedHeight = element.clientHeight; - } - /** - * If the tag is a column break we update the column index after - * appending the item to the column div. This keeps the main DOM - * cleaner by removing other items and placing them all within - * a region container. - */ - if (regionElements[i].tag === DOMObjectTag.columnBreak) { - checkCreateNewColumns(); - columnIndex++; - currentColumnHeight = 0; - } - } - } - function checkShouldSwitchColumns(nextElementHeight) { - if (currentColumnHeight + nextElementHeight < maxColumnContentHeight) { - return; - } - checkCreateNewColumns(); - columnIndex++; - currentColumnHeight = 0; - } - function checkCreateNewColumns() { - if ((columnIndex + 1) >= columns.length) { - divCount++; - columns = columns.concat(getFormattedColumnDivs(settings, verticalColumnParent, colDivsCallback, divCount)); - } - } - } -} -function getFormattedColumnDivs(settings, verticalColumnParent, getColumnContentDivs, divCount) { - let multiColumnParent = verticalColumnParent.createDiv({ - cls: `${MultiColumnLayoutCSS.RegionColumnContainerDiv} \ - ${MultiColumnLayoutCSS.ContentOverflowAutoScroll_X} \ - ${MultiColumnLayoutCSS.ContentOverflowHidden_Y}; - ` - }); - if (divCount > 1) { - multiColumnParent.addClass(`${MultiColumnLayoutCSS.ReflowContainerDiv}`); - } - let columnDivs = getColumnContentDivs(settings, multiColumnParent); - if (settings.drawShadow === true) { - multiColumnParent.addClass(MultiColumnStyleCSS.RegionShadow); - } - for (let i = 0; i < columnDivs.length; i++) { - if (shouldDrawColumnBorder(i, settings) === true) { - columnDivs[i].addClass(MultiColumnStyleCSS.ColumnBorder); - } - if (settings.drawShadow === true) { - columnDivs[i].addClass(MultiColumnStyleCSS.ColumnShadow); - } - } - return columnDivs; -} - -/** - * File: /src/dom_manager/regional_managers/regionManagerContainer.ts * - * Created Date: Sunday, May 22nd 2022, 7:50 pm * - * Author: Cameron Robinson * - * * - * Copyright (c) 2022 Cameron Robinson * - */ -/** - * This class acts as an abstraction for the actual regional manager. It is used to update the - * subclass of RegionalManager depending on user preferences to make rendering more simplified. - */ -class RegionManagerContainer { - constructor(parentFileManager, regionKey, rootElement, regionParent, errorManager) { - this.region = new StandardMultiColumnRegionManager(createDefaultRegionManagerData(regionParent, parentFileManager, regionKey, rootElement, errorManager)); - } - getRegion() { - return this.region; - } - setRegionSettings(settingsText) { - let regionalSettings = parseColumnSettings(settingsText); - if (regionalSettings.numberOfColumns === 1) { - regionalSettings = parseSingleColumnSettings(settingsText, regionalSettings); - } - return this.setRegionParsedSettings(regionalSettings); - } - setRegionParsedSettings(regionalSettings) { - this.region.setRegionalSettings(regionalSettings); - if (regionalSettings.numberOfColumns === 1) { - if (this.region instanceof SingleColumnRegionManager === false) { - // console.debug("Converting region to single column.") - this.convertToSingleColumn(); - } - } - else if (regionalSettings.autoLayout === true) { - if (this.region instanceof AutoLayoutRegionManager === false) { - // console.debug("Converting region to auto layout.") - this.convertToAutoLayout(); - } - } - else if (regionalSettings.fullDocReflow === true) { - if (this.region instanceof ReflowRegionManager === false) { - // console.debug("Converting region to auto layout.") - this.convertToDocReflow(); - } - } - else if (regionalSettings.numberOfColumns >= 2) { - if (this.region instanceof StandardMultiColumnRegionManager === false) { - // console.debug("Converting region to standard multi-column") - this.convertToStandardMultiColumn(); - } - } - return this.region; - } - convertToSingleColumn() { - let data = this.region.getRegionData(); - this.region = new SingleColumnRegionManager(data); - return this.region; - } - convertToStandardMultiColumn() { - let data = this.region.getRegionData(); - this.region = new StandardMultiColumnRegionManager(data); - return this.region; - } - convertToAutoLayout() { - let data = this.region.getRegionData(); - this.region = new AutoLayoutRegionManager(data); - return this.region; - } - convertToDocReflow() { - let data = this.region.getRegionData(); - this.region = new ReflowRegionManager(data); - return this.region; - } -} -function createDefaultRegionManagerData(regionParent, fileManager, regionKey, rootElement, errorManager) { - return { - domList: [], - domObjectMap: new Map(), - regionParent: regionParent, - fileManager: fileManager, - regionalSettings: getDefaultMultiColumnSettings(), - regionKey: regionKey, - rootElement: rootElement, - errorManager: errorManager - }; -} - -/* - * File: multi-column-markdown/src/domManager.ts - * Created Date: Saturday, January 30th 2022, 3:16:32 pm - * Author: Cameron Robinson - * - * Copyright (c) 2022 Cameron Robinson - */ -/** - * This class handles the global managers keeping track of all open files that - * contain MCM-Regions. - */ -class GlobalDOMManager { - constructor() { - this.managers = new Map(); - } - removeFileManagerCallback(key) { - if (this.managers.has(key) === true) { - this.managers.delete(key); - } - } - getFileManager(key) { - let fileManager = null; - if (this.managers.has(key) === true) { - fileManager = this.managers.get(key); - } - else { - fileManager = new FileDOMManager(this, key); - this.managers.set(key, fileManager); - } - return fileManager; - } - getAllFileManagers() { - return Array.from(this.managers.values()); - } -} -class FileDOMManager { - constructor(parentManager, fileKey) { - this.regionMap = new Map(); - this.hasStartTag = false; - this.parentManager = parentManager; - this.fileKey = fileKey; - } - removeRegion(regionKey) { - let regionContainer = this.regionMap.get(regionKey); - if (regionContainer === undefined) { - return; - } - let regionalManager = regionContainer.getRegion(); - regionalManager.displayOriginalElements(); - this.regionMap.delete(regionKey); - if (this.regionMap.size === 0) { - this.parentManager.removeFileManagerCallback(this.fileKey); - } - } - createRegionalManager(regionKey, rootElement, errorManager, renderRegionElement) { - let regonalContainer = new RegionManagerContainer(this, regionKey, rootElement, renderRegionElement, errorManager); - this.regionMap.set(regionKey, regonalContainer); - return regonalContainer.getRegion(); - } - getRegionalContainer(regionKey) { - let regonalManager = null; - if (this.regionMap.has(regionKey) === true) { - regonalManager = this.regionMap.get(regionKey); - } - return regonalManager; - } - getAllRegionalManagers() { - let containers = Array.from(this.regionMap.values()); - let regions = containers.map((curr) => { return curr.getRegion(); }); - return regions; - } - setHasStartTag() { - this.hasStartTag = true; - } - getHasStartTag() { - return this.hasStartTag; - } - getNumberOfRegions() { - return this.regionMap.size; - } - checkKeyExists(checkKey) { - return this.regionMap.has(checkKey); - } -} - -class RegionErrorManager { - get totalNumMessages() { - return this.errorMessages.length + this.warningMessages.length; - } - constructor(rootElement, initialErrorMessages = []) { - this.errorMessages = []; - this.warningMessages = []; - this.errorMessages = initialErrorMessages; - this.setRegionRootElement(rootElement); - } - addErrorMessage(errorString) { - this.errorMessages.push(errorString); - this.updateErrorView(); - } - addWarningMessage(warningString) { - this.warningMessages.push(warningString); - this.updateErrorView(); - } - setRegionRootElement(rootElement) { - this.errorParentElement = rootElement.createDiv({ - cls: `${MultiColumnLayoutCSS.RegionErrorContainerDiv}`, - }); - this.titleRegion = this.errorParentElement.createDiv({ - cls: `${MultiColumnLayoutCSS.ErrorRegionPadding}` - }); - this.contentEl = this.errorParentElement.createDiv({ - cls: `${MultiColumnLayoutCSS.ErrorRegionPadding} mcm-message-region` - }); - this.updateErrorView(); - } - setupErrorHeader() { - if (this.errorMessages.length > 0) { - let text = "Error"; - if (this.errorMessages.length > 1) { - text = text + "s"; - } - this.titleRegion.createSpan({ - attr: { "style": "color: var(--text-error); padding: 5px;" }, - text: "\u2A02" - }); - this.titleRegion.createSpan({ - text: `${this.errorMessages.length} ${text}` - }); - } - if (this.errorMessages.length > 0 && this.warningMessages.length > 0) { - this.titleRegion.createSpan({ - text: ` and ` - }); - } - if (this.warningMessages.length > 0) { - let text = "Warning"; - if (this.warningMessages.length > 1) { - text = text + "s"; - } - this.titleRegion.createSpan({ - attr: { "style": "color: var(--color-yellow); padding: 5px;" }, - text: "\u26A0" - }); - this.titleRegion.createSpan({ - text: `${this.warningMessages.length} ${text}` - }); - } - this.titleRegion.createSpan({ - text: ` in region` - }); - let regionOpened = false; - this.titleRegion.addEventListener("click", (ev) => { - this.titleRegion.classList.toggle("mcm-error-heading-open"); - regionOpened = !regionOpened; - if (regionOpened) { - this.contentEl.style.maxHeight = this.contentEl.scrollHeight + "px"; - } - else { - this.contentEl.style.maxHeight = null; - } - }); - } - updateErrorView() { - this.resetErrorView(); - if (this.totalNumMessages === 0) { - return; - } - this.titleRegion.addClass(`mcm-error-heading`); //TODO: move to const. - this.errorParentElement.classList.add(MultiColumnStyleCSS.ColumnBorder); - this.setupErrorHeader(); - this.appendContentToEl(); - } - appendContentToEl() { - for (let i = 0; i < this.errorMessages.length; i++) { - let p = this.contentEl.createEl("p"); - p.innerHTML = `\u2A02${this.errorMessages[0]}`; - } - for (let i = 0; i < this.warningMessages.length; i++) { - let p = this.contentEl.createEl("p"); - p.innerHTML = `\u26A0${this.warningMessages[0]}`; - } - } - resetErrorView() { - var _a; - this.errorParentElement.classList.remove(MultiColumnStyleCSS.ColumnBorder); - this.titleRegion.removeClass(`mcm-error-heading`); //TODO: move to const. - while (this.titleRegion.children.length > 0) { - this.titleRegion.childNodes.forEach(child => { - this.titleRegion.removeChild(child); - }); - } - if (this.contentEl === null) { - return; - } - let children = (_a = this.contentEl) === null || _a === void 0 ? void 0 : _a.childNodes; - children.forEach(child => { - if (child !== null && child.parentElement === this.contentEl) { - this.contentEl.removeChild(child); - } - }); - } -} - -function createColBreakWarning(type, errorManager) { - let typeErrorStr = ""; - if (type === ElementColumnBreakType.preBreak) { - typeErrorStr = "at the begining of another element"; - } - if (type === ElementColumnBreakType.postBreak) { - typeErrorStr = "at the end of another element"; - } - if (type === ElementColumnBreakType.midBreak) { - typeErrorStr = "in the middle of two elements"; - } - errorManager.addWarningMessage(`Detected a column break tag ${typeErrorStr}. Please make sure to surround column breaks with empty lines on both sides, or render issues may occur.`); -} -function parseColBreakErrorType(elementInfo, errorManager) { - if (elementInfo.objectTag !== DOMObjectTag.columnBreak && - elementInfo.colBreakType === ElementColumnBreakType.none) { - return; - } - let errorType = elementInfo.colBreakType; - if (elementInfo.objectTag === DOMObjectTag.columnBreak) { - if (elementInfo.lineAbove === "" && - elementInfo.lineBelow === "") { - return; - } - let lineAbove = elementInfo.lineAbove; - let lineBelow = elementInfo.lineBelow; - if (lineAbove !== "" && lineBelow === "") { - errorType = ElementColumnBreakType.postBreak; - } - if (lineAbove === "" && lineBelow !== "") { - errorType = ElementColumnBreakType.preBreak; - } - if (lineAbove !== "" && lineBelow !== "") { - errorType = ElementColumnBreakType.midBreak; - } - } - createColBreakWarning(errorType, errorManager); -} - -function getLeafFromFilePath(workspace, filePath) { - function checkState(state) { - if (state["type"] === undefined || - state["type"] !== "markdown") { - return false; - } - if (state["state"] === undefined) { - return false; - } - if (state["state"]["file"] === undefined) { - return false; - } - let stateFilePath = state["state"]["file"]; - return stateFilePath === filePath; - } - if (workspace === null) { - return null; - } - let entries = Object.entries(workspace.getLayout()); - let items = Array.from(entries).map((val) => { - return val[1]; - }); - while (items.length > 0) { - let entryObj = items.shift(); - if (entryObj["id"] !== undefined && entryObj["type"] !== undefined) { - if (entryObj["type"] === "split" || - entryObj["type"] === "tabs") { - items = items.concat(entryObj['children']); - continue; - } - if (entryObj["type"] === "leaf" && - entryObj["id"] !== undefined && - entryObj["state"] !== undefined) { - let id = entryObj["id"]; - let state = entryObj["state"]; - console.log(state); - let valid = checkState(state); - if (valid) { - return workspace.getLeafById(id); - } - } - } - } - return null; -} -function getPreviewLeafFromFilePath(workspace, filePath) { - function checkState(state) { - if (state["type"] === undefined || - state["type"] !== "markdown") { - return false; - } - if (state["state"] === undefined) { - return false; - } - if (state["state"]["file"] === undefined) { - return false; - } - let stateFilePath = state["state"]["file"]; - return stateFilePath === filePath; - } - let entries = Object.entries(workspace.getLayout()); - let items = Array.from(entries).map((val) => { - return val[1]; - }); - while (items.length > 0) { - let entryObj = items.shift(); - if (entryObj["id"] !== undefined && entryObj["type"] !== undefined) { - if (entryObj["type"] === "split" || - entryObj["type"] === "tabs") { - items = items.concat(entryObj['children']); - continue; - } - if (entryObj["type"] === "leaf" && - entryObj["id"] !== undefined && - entryObj["state"] !== undefined) { - let id = entryObj["id"]; - let state = entryObj["state"]; - let isPreview = false; - if (state["state"] !== undefined && - state["state"]["mode"] !== undefined) { - let mode = state["state"]["mode"]; - isPreview = mode === "preview"; - } - let validFilePath = checkState(state); - if (validFilePath && isPreview) { - return workspace.getLeafById(id); - } - } - } - } - return null; -} - -/* - * Filename: multi-column-markdown/src/live_preview/MultiColumnMarkdown_Widget.ts - * Created Date: Tuesday, August 16th 2022, 4:38:43 pm - * Author: Cameron Robinson - * - * Copyright (c) 2022 Cameron Robinson - */ -const CACHE_MAX_DELTA_TIME_MS = 2 * 60 * 1000; // 2m -let livePreviewElementCache = new Map(); -function clearCache(skipKey = "") { - return __awaiter(this, void 0, void 0, function* () { - let keys = Array.from(livePreviewElementCache.keys()); - for (let key of keys) { - if (key === skipKey) { - // console.debug(`Element: ${index} | Skipping key: ${key.split(" : ")[0]}`) - continue; - } - if (livePreviewElementCache.has(key) === false) { - continue; - } - let val = livePreviewElementCache.get(key); - let deltaTimeMS = Date.now() - val.timestamp; - if ((val.element.parentNode === null || val.element.parentNode.parentNode === null) && deltaTimeMS > CACHE_MAX_DELTA_TIME_MS) { - // console.debug(`cache delta: ${deltaTimeMS} > ${CACHE_MAX_DELTA_TIME_MS} or 2 minutes.`) - livePreviewElementCache.delete(key); - } - else if (val.element.parentNode == null || val.element.parentNode.parentNode === null) ; - } - }); -} -function clearLivePreviewCache() { - clearCache(); -} -class MultiColumnMarkdown_LivePreview_Widget extends view.WidgetType { - constructor(originalText, contentData, userSettings, sourceFile, settingsText = "", regionType) { - super(); - this.domList = []; - this.regionSettings = getDefaultMultiColumnSettings(); - this.sourcePath = ""; - this.contentData = contentData; - this.settingsText = settingsText; - this.sourceFile = sourceFile; - if (this.sourceFile === null) { - return; - } - this.elementCacheID = `${this.sourceFile.path} : ${this.contentData}`; - if (this.sourceFile) { - this.sourcePath = sourceFile.path; - } - if (userSettings !== null) { - this.regionSettings = userSettings; - } - let errorManager = new RegionErrorManager(createDiv()); - if (regionType === "CODEBLOCK") { - errorManager.addErrorMessage("The codeblock region start syntax has been depricated. Please manually update to the current syntax defined in the ReadMe, run the \"Fix Multi-Column Syntax in Current File\" from the Command Palette, or use the \"Update Depricated Syntax\" command found in the plugin settings window. You must reload the file for changes to take effect."); - } - (() => __awaiter(this, void 0, void 0, function* () { - function hasBadContentBetween(contentBetween) { - let regexResult = new RegExp("((?: *\n){6,})").exec(contentBetween); - if (regexResult !== null) { - // console.log("Found at least 6 empty lines.") - return false; - } - regexResult = /^(?:(?! *$)(?! *--- *$)).+$/mg.exec(contentBetween); - if (regexResult !== null) { - return false; - } - return true; - } - let fileText = yield sourceFile.vault.cachedRead(sourceFile); - fileText = fileText.replace(originalText, "###--START_HERE--###"); - let regexResult = new RegExp("###--START_HERE--###").exec(fileText); - if (regexResult === null) { - return; - } - fileText = fileText.slice(0, regexResult.index); - let nextStartTag = findEndTagClosestToEnd(fileText); - if (nextStartTag.found === false) { - return; - } - let errorString = hasBadContentBetween(fileText.slice(nextStartTag.endPosition)); - if (errorString === false) { - return; - } - errorManager.addWarningMessage("Detected possible issue with the content between this region and the region above. \ - If you experience page jumping when clicking within this document, please make sure there are at least 6 blank \ - lines or some form of text content between the two regions. This is a known issue that is under investigation. Sorry for the inconvenience."); - }))(); - if (livePreviewElementCache.has(this.elementCacheID)) { - let cache = livePreviewElementCache.get(this.elementCacheID); - let regionManager = cache.regionManager; - let regionSettingsEqual = MCSettings_isEqual(userSettings, cache.cacheSettings); - let pluginSettingsUpdated = MCM_SettingsManager.shared.lastUpdateTimestamp > cache.pluginSettingsUpdateTimestamp; - if (regionManager && regionSettingsEqual === true && pluginSettingsUpdated === false) { - regionManager.updateErrorManager(errorManager, cache.errorRootEl); - let useLivePreviewCache = MCM_SettingsManager.shared.useLivePreviewCache; - let fileLeaf = getPreviewLeafFromFilePath(app.workspace, this.sourceFile.path); - if (useLivePreviewCache && fileLeaf === null) { - return; - } - } - else { - livePreviewElementCache.delete(this.elementCacheID); - } - } - // Render the markdown content to our temp parent element. - this.tempParent = createDiv(); - let elementMarkdownRenderer = new obsidian.MarkdownRenderChild(this.tempParent); - obsidian.MarkdownRenderer.renderMarkdown(this.contentData, this.tempParent, this.sourcePath, elementMarkdownRenderer); - let previousText = ""; - let workingText = originalText; - // take all elements, in order, and create our DOM list. - let arr = Array.from(this.tempParent.children); - for (let i = 0; i < arr.length; i++) { - let el = this.fixElementRender(arr[i]); - let domObject = new DOMObject(el, [""]); - this.domList.push(domObject); - let newData = sliceWorkingTextToEl(domObject, previousText, workingText); - previousText = newData.previousText; - workingText = newData.workingText; - newData = attemptToFixCheckboxes(domObject, previousText, workingText, sourceFile, this.elementCacheID); - previousText = newData.previousText; - workingText = newData.workingText; - workingText = checkForColumnBreakErrors(domObject, previousText, workingText, errorManager); - } - // Set up the region manager data before then creating our region manager. - let regionData = { - domList: this.domList, - domObjectMap: new Map(), - regionParent: createDiv(), - fileManager: null, - regionalSettings: this.regionSettings, - regionKey: getUID(), - rootElement: createDiv(), - errorManager: errorManager - }; - // Finally setup the type of region manager required. - if (this.regionSettings.numberOfColumns === 1) { - this.regionSettings = parseSingleColumnSettings(this.settingsText, this.regionSettings); - this.regionManager = new SingleColumnRegionManager(regionData); - } - else if (this.regionSettings.autoLayout === true) { - this.regionManager = new AutoLayoutRegionManager(regionData, true); - } - else { - this.regionManager = new StandardMultiColumnRegionManager(regionData); - } - clearCache(this.elementCacheID); - } - fixElementRender(el) { - let fixedEl = fixImageRender(el, this.sourcePath); - fixedEl = fixPDFRender(fixedEl, this.sourcePath); - fixedEl = fixFileEmbed(fixedEl, this.sourcePath); - fixedEl = fixTableRender(fixedEl); - fixedEl = fixUnSupportedRender(fixedEl); - return fixedEl; - } - toDOM() { - let useLivePreviewCache = MCM_SettingsManager.shared.useLivePreviewCache; - let fileLeaf = getPreviewLeafFromFilePath(app.workspace, this.sourceFile.path); - if (useLivePreviewCache && - livePreviewElementCache.has(this.elementCacheID) && - fileLeaf === null) { - return livePreviewElementCache.get(this.elementCacheID).element; - } - // Create our element to hold all of the live preview elements. - let el = document.createElement("div"); - el.className = "mcm-cm-preview"; - /** - * For situations where we need to know the rendered height, AutoLayout, - * the element must be rendered onto the screen to get the info, even if - * only for a moment. Here we attempt to get a leaf from the app so we - * can briefly append our element, check any data if required, and then - * remove it. - */ - let autolayoutLeaf = null; - if (app) { - let leaves = app.workspace.getLeavesOfType("markdown"); - if (leaves.length > 0) { - autolayoutLeaf = leaves[0]; - } - } - if (this.regionManager) { - this.errorRootEl = el.createDiv(); - let contentElement = el.createDiv(); - this.regionManager.getRegionData().errorManager.setRegionRootElement(this.errorRootEl); - let requireUnload = false; - if (autolayoutLeaf && this.regionManager instanceof AutoLayoutRegionManager) { - autolayoutLeaf.view.containerEl.appendChild(el); - requireUnload = true; - } - this.regionManager.renderRegionElementsToLivePreview(contentElement); - for (let domObj of this.regionManager.getRegionData().domList) { - fixListCSS(domObj.originalElement); - } - if (requireUnload) { - autolayoutLeaf.view.containerEl.removeChild(el); - } - } - fixExternalLinks(el); - livePreviewElementCache.set(this.elementCacheID, { - timestamp: Date.now(), - element: el, - regionManager: this.regionManager, - errorRootEl: this.errorRootEl, - cacheSettings: this.regionSettings, - pluginSettingsUpdateTimestamp: MCM_SettingsManager.shared.lastUpdateTimestamp - }); - return el; - } - fixElementCSS(domObject) { - fixListCSS(domObject.originalElement); - } -} -const OBSIDIAN_LIVEPREVIEW_TABLE_CLASSES = "cm-embed-block markdown-rendered cm-table-widget show-indentation-guide"; -function fixTableRender(el) { - if (el.tagName !== "TABLE") { - return el; - } - let parentDiv = createDiv({ - "cls": OBSIDIAN_LIVEPREVIEW_TABLE_CLASSES - }); - parentDiv.appendChild(el); - return parentDiv; -} -function fixFileEmbed(el, source) { - let embed = getEmbed(el); - if (embed === null) { - return el; - } - let alt = embed.getAttr("alt"); - let src = embed.getAttr("src"); - if (src === null) { - return el; - } - let file = app.metadataCache.getFirstLinkpathDest(src, source); - if (file === null) { - return el; - } - if (isMDExtension(file.extension) === false) { - return el; - } - return createLPErrorElement("File embeds are not supported in Live Preview.\nPlease use reading mode to view.", alt, src); -} -function createLPErrorElement(errorText, alt = "", src = "") { - let errorEl = createDiv({ - cls: "internal-embed markdown-embed inline-embed is-loaded", - attr: { - "tabindex": "-1", - "contenteditable": "false" - } - }); - errorEl.setAttr("alt", alt); - errorEl.setAttr("src", `app://obsidian.md/${src}`); - errorEl.appendChild(createDiv({ - "cls": "embed-title markdown-embed-title", - })); - let contentEl = errorEl.createDiv({ - "cls": `markdown-embed-content`, - }); - let paragraph = contentEl.createEl("p", { - "cls": `${MultiColumnStyleCSS.RegionErrorMessage}, ${MultiColumnStyleCSS.SmallFont}` - }); - paragraph.innerText = errorText; - return errorEl; -} -function fixPDFRender(el, source) { - let embed = getEmbed(el); - if (embed === null) { - return el; - } - let alt = embed.getAttr("alt"); - let src = embed.getAttr("src"); - if (src === null) { - return el; - } - let file = app.metadataCache.getFirstLinkpathDest(src, source); - if (file === null) { - return el; - } - if (isPDFExtension(file.extension) === false) { - return el; - } - return createLPErrorElement("Due to an update to Obsidian's PDF viewer, PDF embeds are currently not supported.\nSorry for the inconvienence.", alt, src); -} -function fixImageRender(el, source) { - let embed = getEmbed(el); - if (embed === null) { - return el; - } - let customWidth = embed.attributes.getNamedItem("width"); - let alt = embed.getAttr("alt"); - let src = embed.getAttr("src"); - if (src === null) { - return el; - } - let file = app.metadataCache.getFirstLinkpathDest(src, source); - if (file === null) { - return el; - } - // If the link source is not an image we dont want to make any adjustments. - if (isImageExtension(file.extension) === false) { - return el; - } - let fixedEl = createDiv({ - cls: "internal-embed image-embed is-loaded", - }); - fixedEl.setAttr("alt", alt); - let resourcePath = app.vault.getResourcePath(file); - let image = fixedEl.createEl("img"); - image.setAttr("src", resourcePath); - if (customWidth !== null) { - image.setAttr("width", customWidth.value); - } - return fixedEl; -} -function fixExternalLinks(el) { - let items = el.getElementsByClassName("external-link"); - for (let linkEl of Array.from(items)) { - let link = linkEl; - if (link === undefined || - link === null) { - continue; - } - // Remove the href from the link and setup an event listener to open the link in the default browser. - let href = link.getAttr("href"); - link.removeAttribute("href"); - link.addEventListener("click", (ev) => { - window.open(href); - }); - } - items = el.getElementsByClassName("internal-link"); - for (let linkEl of Array.from(items)) { - let link = linkEl; - if (link === undefined || - link === null) { - continue; - } - // Removing the href from internal links is all that seems to be required to fix the onclick. - link.removeAttribute("href"); - } - return el; -} -function getEmbed(el) { - // embeds can either be a
{ - return val !== ""; - }); - let linesBelow = textAfter.split("\n").filter((val) => { - return val !== ""; - }); - if (linesAbove.length === 0 && linesBelow.length === 0) { - return workingText; - } - let lineAbove = linesAbove.last(); - let lineBelow = linesBelow.first(); - parseColBreakErrorType({ - lineAbove: lineAbove, - lineBelow: lineBelow, - objectTag: DOMObjectTag.columnBreak, - colBreakType: ElementColumnBreakType.none - }, errorManager); - return newWorkingText; -} -function sliceWorkingTextToEl(domObject, previousText, workingText) { - function processParagraph() { - let regex = new RegExp(`^ *${escapeRegExp(domObject.originalElement.textContent)} *$`, "m"); - let result = regex.exec(workingText); - if (result) { - let updatedPrevious = previousText + workingText.slice(0, result.index); - workingText.slice(result.index, result.index + result[0].length); - let updatedWorkingText = workingText.slice(result.index); - return { - previousText: updatedPrevious, - workingText: updatedWorkingText - }; - } - return { - previousText: previousText, - workingText: workingText - }; - } - function processHeader() { - let count = parseInt(domObject.originalElement.tagName.slice(1)); - let text = '#'.repeat(count); - let regex = new RegExp(`^${text} +${escapeRegExp(domObject.originalElement.textContent)} *$`, "m"); - let result = regex.exec(workingText); - if (result) { - let updatedPrevious = previousText + workingText.slice(0, result.index); - workingText.slice(result.index, result.index + result[0].length); - let updatedWorkingText = workingText.slice(result.index); - return { - previousText: updatedPrevious, - workingText: updatedWorkingText - }; - } - return { - previousText: previousText, - workingText: workingText - }; - } - if (domObject.originalElement.tagName === "P") { - return processParagraph(); - } - if (domObject.originalElement.tagName === "H1" || - domObject.originalElement.tagName === "H2" || - domObject.originalElement.tagName === "H3" || - domObject.originalElement.tagName === "H4" || - domObject.originalElement.tagName === "H5") { - return processHeader(); - } - return { - previousText: previousText, - workingText: workingText - }; -} -function attemptToFixCheckboxes(domObject, textBeforeElement, textOfElementAndAfter, sourceFile, cacheID) { - if (domObject.originalElement.tagName !== "UL") { - return { - previousText: textBeforeElement, - workingText: textOfElementAndAfter - }; - } - if (domObject.originalElement.hasClass("contains-task-list") === false) { - return { - previousText: textBeforeElement, - workingText: textOfElementAndAfter - }; - } - let listItems = Array.from(domObject.originalElement.getElementsByTagName("li")).filter((item) => { - return item.hasClass("task-list-item"); - }); - let workingTextBefore = textBeforeElement; - let workingText = textOfElementAndAfter; - for (let listElement of listItems) { - let possibleCheckbox = listElement.getElementsByTagName("input"); - if (possibleCheckbox.length !== 1) { - console.error("Error: Could not get input for task item."); - continue; - } - let checkbox = possibleCheckbox[0]; - if (checkbox.getAttr("type") !== "checkbox") { - console.error("Error: Checkbox not of proper type"); - continue; - } - if (checkbox.hasClass("task-list-item-checkbox") === false) { - console.error("Error: Checkbox is missing proper class."); - continue; - } - if (checkbox.onclick !== null) { - console.error("Error: OnClick aready defined, not overwriting method."); - continue; - } - let checkboxIsChecked = listElement.getAttr("data-task") === "x" || listElement.getAttr("data-task") === "X"; - let checkboxTextRegexSearch = RegExp(`^( *)-( +)\\[${checkboxIsChecked ? "[xX]" : " *"}\\]( +)${escapeRegExp(listElement.innerText)}( *)$`, "m"); - let checkboxTextRegexResult = checkboxTextRegexSearch.exec(workingText); - if (checkboxTextRegexResult === null) { - console.error("Could not find text in provided document."); - continue; - } - let startOfElementIndex = checkboxTextRegexResult.index; - let endOfElementIndex = startOfElementIndex + checkboxTextRegexResult[0].length; - let newTextAfter = workingText.slice(endOfElementIndex); - let onClickNewTextAfter = newTextAfter; - workingTextBefore = workingTextBefore + workingText.slice(0, startOfElementIndex); - let onClickNewTextBefore = workingTextBefore; - workingText = workingText.slice(startOfElementIndex); - let onClickNewWorkingText = workingText; - let spaceBeforeDash = checkboxTextRegexResult[1]; - let spaceAfterDash = checkboxTextRegexResult[2]; - let spaceAfterCheck = checkboxTextRegexResult[3]; - let spaceAfterContent = checkboxTextRegexResult[4]; - let currentCacheID = cacheID; - let sourceFilePath = sourceFile.path; - checkbox.onclick = () => { - let replacementLine = `${spaceBeforeDash}-${spaceAfterDash}[${checkboxIsChecked ? " " : "X"}]${spaceAfterCheck}${listElement.innerText}${spaceAfterContent}`; - let originalTextToReplace = onClickNewTextBefore + onClickNewWorkingText; - let newReplacementText = onClickNewTextBefore + replacementLine + onClickNewTextAfter; - if (livePreviewElementCache.has(currentCacheID)) { - let newCacheID = `${sourceFilePath} : ${newReplacementText}`; - let currentData = livePreviewElementCache.get(currentCacheID); - livePreviewElementCache.set(newCacheID, currentData); - currentCacheID = newCacheID; - } - (() => __awaiter(this, void 0, void 0, function* () { - let fileText = yield sourceFile.vault.read(sourceFile); - if (fileText.contains(originalTextToReplace) === false) { - console.error("Could not update file. File does not contain region text."); - return; - } - let newFileText = fileText.replace(originalTextToReplace, newReplacementText); - sourceFile.vault.modify(sourceFile, newFileText); - }))(); - listElement.classList.toggle("is-checked"); - if (checkboxIsChecked) { - listElement.removeAttribute("data-task"); - } - else { - listElement.setAttribute("data-task", "x"); - } - checkboxIsChecked = !checkboxIsChecked; - }; - } - return { - previousText: workingTextBefore, - workingText: workingText - }; -} -function escapeRegExp(str) { - return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string -} - -/* - * Filename: multi-column-markdown/src/live_preview/cm6_livePreview.ts - * Created Date: Monday, August 1st 2022, 1:51:16 pm - * Author: Cameron Robinson - * - * Copyright (c) 2022 Cameron Robinson - */ -const multiColumnMarkdown_StateField = state.StateField.define({ - create(state) { - return view.Decoration.none; - }, - update(oldState, transaction) { - const builder = new state.RangeSetBuilder(); - let ignoreFurtherIterations = false; - // Check if view is in live preview state. - if (transaction.state.field(obsidian.editorLivePreviewField) === false) { - return builder.finish(); - } - /** - * When we have the while file we then get the entire doc text and check if it - * contains a MCM region so we know to break or not. - */ - let docLength = transaction.state.doc.length; - let docText = transaction.state.doc.sliceString(0, docLength); - if (containsRegionStart(docText) === false) { - return builder.finish(); - } - language.syntaxTree(transaction.state).iterate({ - enter(node) { - // If we find that the file does not contain any MCM regions we can flip this - // flag and skip all other node iterations, potentially saving a lot of compute time. - // - // We only want to run the generation once per state change. If - // a previous node has sucessfully generated regions we ignore all - // other nodes in the state. - if (ignoreFurtherIterations === true) { - return; - } - // We want to run on the whole file so we dont just look for a single token. - const tokenProps = node.type.prop(language.tokenClassNodeProp); - if (tokenProps !== undefined) { - return; - } - // We want to know where the user's cursor is, it can be - // selecting multiple regions of text as well so we need to know - // all locations. Used to know if we should render region as text or as preview. - let ranges = getCursorLineLocations(); - // Setup our loop to render the regions as MCM. - let workingFileText = docText; - let loopIndex = 0; - let startIndexOffset = 0; - while (true) { - let regionData = getNextRegion(workingFileText, startIndexOffset, docText); - if (regionData === null) { - break; - } - let elementText = regionData.regionText; - workingFileText = regionData.remainingText; - let startIndex = regionData.startIndex; - let endIndex = regionData.endIndex; - startIndexOffset = endIndex; - // Here we check if the cursor is in this specific region. - let cursorInRegion = checkCursorInRegion(startIndex, endIndex, ranges); - if (cursorInRegion === true) ; - else { - let foundSettings = getSettingsData(regionData); - let userSettings = null; - let settingsText = ""; - let originalText = elementText; - if (foundSettings !== null) { - elementText = foundSettings.contentData; - userSettings = foundSettings.settings; - settingsText = foundSettings.settingsText; - } - const editorInfo = transaction.state.field(obsidian.editorInfoField); - // At this point if the cursor isnt in the region we pass the data to the - // element to be rendered. - builder.add(startIndex, endIndex, view.Decoration.replace({ - widget: new MultiColumnMarkdown_LivePreview_Widget(originalText, elementText, userSettings, editorInfo.file, settingsText, regionData.regionType), - })); - } - ignoreFurtherIterations = true; - // Infinite loop protection. - loopIndex++; - if (loopIndex > 100) { - console.warn("Potential issue with rendering Multi-Column Markdown live preview regions. If problem persists please file a bug report with developer."); - break; - } - } - }, - }); - return builder.finish(); - function getCursorLineLocations() { - let ranges = []; - if (transaction.state.selection.ranges) { - ranges = transaction.state.selection.ranges.filter((range) => { - return range.empty; - }).map((range) => { - let line = transaction.state.doc.lineAt(range.head); - `${line.number}:${range.head - line.from}`; - return { - line: line, - position: range.head - }; - }); - } - return ranges; - } - function valueIsInRange(value, minVal, maxVal, inclusive = true) { - if (inclusive === true && (value === minVal || value === maxVal)) { - return true; - } - if (minVal < value && value < maxVal) { - return true; - } - return false; - } - function checkCursorInRegion(startIndex, endIndex, ranges) { - for (let i = 0; i < ranges.length; i++) { - // TODO: Maybe look into limiting this to the second and second to last line - // of the region as clicking right at the top or bottom of the region - // swaps it to unrendered. - let range = ranges[i]; - if (valueIsInRange(range.position, startIndex, endIndex) === true) { - return true; - } - } - if (transaction.state.selection) { - for (let i = 0; i < transaction.state.selection.ranges.length; i++) { - let range = transaction.state.selection.ranges[i]; - // If either the start or end of the selection is within the - // region range we do not render live preview. - if (valueIsInRange(range.from, startIndex, endIndex) || - valueIsInRange(range.to, startIndex, endIndex)) { - return true; - } - // // Or if the entire region is within the selection range - // we do not render the live preview. - if (valueIsInRange(startIndex, range.from, range.to) && - valueIsInRange(endIndex, range.from, range.to)) { - return true; - } - } - } - return false; - } - }, - provide(field) { - return view.EditorView.decorations.from(field); - }, -}); -function getNextRegion(workingFileText, startIndexOffset, wholeDoc) { - let region = findNextRegion(workingFileText); - if (region === null) { - return null; - } - if (region.dataType === "CODEBLOCK" || region.dataType === "ORIGINAL") { - // Search for the first end tag after a start block. (No recursive columns.) - let endTagData = findEndTag(workingFileText.slice(region.data.startPosition)); - if (endTagData.found === false) { - return null; - } - /** - * For the region we found get the start and end position of the tags so we - * can slice it out of the document. - */ - let startIndex = startIndexOffset + region.data.startPosition; - let endIndex = startIndex + endTagData.startPosition + endTagData.matchLength; // Without the matchLength will leave the end tag on the screen. - // This text is the entire region data including the start and end tags. - let elementText = wholeDoc.slice(startIndex, endIndex); - workingFileText = wholeDoc.slice(endIndex); - /** - * Update our start offset and the working text of the file so our next - * iteration knows where we left off - */ - let data = { - regionType: region.dataType, - regionText: elementText, - remainingText: workingFileText, - startIndex: startIndex, - endIndex: endIndex - }; - return data; - } - if (region.dataType === "PADOC") { - let pandocData = region.data; - let startIndex = startIndexOffset + pandocData.startPosition; - let endIndex = startIndexOffset + pandocData.endPosition; - workingFileText = wholeDoc.slice(endIndex); - let data = { - regionType: region.dataType, - regionText: pandocData.content, - remainingText: workingFileText, - startIndex: startIndex, - endIndex: endIndex, - columnCount: pandocData.columnCount, - userSettings: pandocData.userSettings - }; - return data; - } -} -function findNextRegion(workingFileText) { - // If there are multiple kinds of start blocks, the old way of parsing would cause issues. - // Now search for both kinds and determine what to do after search. - let startTagData_codeblockStart = { dataType: "CODEBLOCK", data: findStartCodeblock(workingFileText) }; - let startTagData_originalStart = { dataType: "ORIGINAL", data: findStartTag(workingFileText) }; - let pandocData = { dataType: "PADOC", data: findPandoc(workingFileText) }; - if (startTagData_codeblockStart.data.found === false && - startTagData_originalStart.data.found === false && - pandocData.data.found === false) { - return null; - } - let regionsFound = [startTagData_codeblockStart, startTagData_originalStart, pandocData].filter((val) => { return val.data.found === true; }); - if (regionsFound.length > 1) { - let sorted = regionsFound.sort((a, b) => { - return a.data.startPosition - b.data.endPosition; - }); - return sorted.first(); - } - if (startTagData_codeblockStart.data.found === true) { - return startTagData_codeblockStart; - } - if (startTagData_originalStart.data.found === true) { - return startTagData_originalStart; - } - if (pandocData.data.found === true) { - return pandocData; - } - throw ("Unknown type found when parsing region."); -} -function getSettingsData(regionData) { - let contentData = regionData.regionText; - function parseCodeBlockSettings(settingsStartData) { - let settingsText = contentData.slice(settingsStartData.startPosition, settingsStartData.endPosition); - contentData = contentData.replace(settingsText, ""); - let settings = parseColumnSettings(settingsText); - return { - settings: settings, - settingsText: settingsText, - contentData: contentData - }; - } - if (regionData.regionType === "CODEBLOCK") { - let settingsStartData = findStartCodeblock(contentData); - if (settingsStartData.found === false) { - return null; - } - return parseCodeBlockSettings(settingsStartData); - } - if (regionData.regionType === "ORIGINAL") { - let settingsStartData = findSettingsCodeblock(contentData); - if (settingsStartData.found === false) { - return null; - } - return parseCodeBlockSettings(settingsStartData); - } - if (regionData.regionType === "PADOC") { - let pandocData = regionData; - return { - settings: parsePandocSettings(pandocData.userSettings, pandocData.columnCount), - settingsText: "", - contentData: regionData.regionText - }; - } -} - -/** - * File: /src/live_preview/cm6_livePreivew_onClickFix.ts * - * Created Date: Friday, March 24th 2023, 6:10 pm * - * Author: Cameron Robinson * - * * - * Copyright (c) 2023 Cameron Robinson * - */ -const MultiColumnMarkdown_OnClickFix = state.StateField.define({ - create(state) { - return view.Decoration.none; - }, - update(oldState, transaction) { - const builder = new state.RangeSetBuilder(); - return builder.finish(); - }, - provide(field) { - return view.EditorView.decorations.from(field); - }, -}); - -function updateAllSyntax(originalFileContent) { - let fileCount = 0; - let regionStartCount = 0; - let columnBreakCount = 0; - let columnEndCount = 0; - let fileUpdated = false; - let { updatedFileContent, numRegionsUpdated } = updateColumnCodeblockStartSyntax(originalFileContent); - if (numRegionsUpdated > 0) { - fileCount++; - fileUpdated = true; - regionStartCount += numRegionsUpdated; - } - let colStart = updateColumnStartSyntax(updatedFileContent); - if (colStart.numRegionsUpdated) { - if (fileUpdated === false) { - fileUpdated = true; - fileCount++; - } - updatedFileContent = colStart.updatedFileContent; - regionStartCount += colStart.numRegionsUpdated; - } - let colBreak = updateColumnBreakSyntax(updatedFileContent); - if (colBreak.numRegionsUpdated) { - if (fileUpdated === false) { - fileUpdated = true; - fileCount++; - } - updatedFileContent = colBreak.updatedFileContent; - columnBreakCount += colBreak.numRegionsUpdated; - } - let colEnd = updateColumnEndSyntax(updatedFileContent); - if (colEnd.numRegionsUpdated) { - if (fileUpdated === false) { - fileUpdated = true; - fileCount++; - } - updatedFileContent = colEnd.updatedFileContent; - columnEndCount += colEnd.numRegionsUpdated; - } - return { - fileCount: fileCount, - regionStartCount: regionStartCount, - columnBreakCount: columnBreakCount, - columnEndCount: columnEndCount, - updatedFileContent: updatedFileContent, - fileWasUpdated: updatedFileContent !== originalFileContent - }; -} -const OLD_COL_END_SYNTAX_REGEX = /=== *(end-multi-column|multi-column-end)/g; -function updateColumnEndSyntax(originalFileContent) { - let matches = Array.from(originalFileContent.matchAll(OLD_COL_END_SYNTAX_REGEX)); - let updatedFileContent = originalFileContent; - let offset = 0; - for (let match of matches) { - let startIndex = match.index + offset; - let matchLength = match[0].length; - let endIndex = startIndex + matchLength; - let columnEndSyntax = match[1]; - let replacementText = `--- ${columnEndSyntax}`; - offset += replacementText.length - matchLength; - updatedFileContent = updatedFileContent.slice(0, startIndex) + replacementText + updatedFileContent.slice(endIndex); - console.groupCollapsed(); - console.log("Original File:\n\n", originalFileContent); - console.log("Updated File:\n\n", updatedFileContent); - console.groupEnd(); - } - return { - updatedFileContent: updatedFileContent, - numRegionsUpdated: matches.length - }; -} -const OLD_COL_BREAK_SYNTAX_REGEX = /===\s*?(column-end|end-column|column-break|break-column)\s*?===\s*?/g; -function updateColumnBreakSyntax(originalFileContent) { - let matches = Array.from(originalFileContent.matchAll(OLD_COL_BREAK_SYNTAX_REGEX)); - let updatedFileContent = originalFileContent; - let offset = 0; - for (let match of matches) { - let startIndex = match.index + offset; - let matchLength = match[0].length; - let endIndex = startIndex + matchLength; - let columnBreakSyntax = match[1]; - let replacementText = `--- ${columnBreakSyntax} ---`; - offset += replacementText.length - matchLength; - updatedFileContent = updatedFileContent.slice(0, startIndex) + replacementText + updatedFileContent.slice(endIndex); - console.groupCollapsed(); - console.log("Original File:\n\n", originalFileContent); - console.log("Updated File:\n\n", updatedFileContent); - console.groupEnd(); - } - return { - updatedFileContent: updatedFileContent, - numRegionsUpdated: matches.length - }; -} -const OLD_COL_START_SYNTAX_REGEX = /=== *(start-multi-column|multi-column-start)/g; -function updateColumnStartSyntax(originalFileContent) { - let matches = Array.from(originalFileContent.matchAll(OLD_COL_START_SYNTAX_REGEX)); - let updatedFileContent = originalFileContent; - let offset = 0; - for (let match of matches) { - let startIndex = match.index + offset; - let matchLength = match[0].length; - let endIndex = startIndex + matchLength; - let columnStartSyntax = match[1]; - let replacementText = `--- ${columnStartSyntax}`; - offset += replacementText.length - matchLength; - updatedFileContent = updatedFileContent.slice(0, startIndex) + replacementText + updatedFileContent.slice(endIndex); - console.groupCollapsed(); - console.log("Original File:\n\n", originalFileContent); - console.log("Updated File:\n\n", updatedFileContent); - console.groupEnd(); - } - return { - updatedFileContent: updatedFileContent, - numRegionsUpdated: matches.length - }; -} -const OLD_CODEBLOCK_COL_START_SYNTAX_REGEX = /```(start-multi-column|multi-column-start).*?```/sg; -function updateColumnCodeblockStartSyntax(originalFileContent) { - let matches = Array.from(originalFileContent.matchAll(OLD_CODEBLOCK_COL_START_SYNTAX_REGEX)); - let updatedFileContent = originalFileContent; - let offset = 0; - for (let match of matches) { - let startIndex = match.index + offset; - let matchLength = match[0].length; - let endIndex = startIndex + matchLength; - let originalSettingsText = match[0]; - let settingsText = originalSettingsText; - let columnStartSyntax = match[1]; - let columnStartLine = `--- ${columnStartSyntax}`; - let idResult = /ID:(.*)/i.exec(originalSettingsText); - if (idResult !== null) { - let id = idResult[1].trim(); - columnStartLine = `${columnStartLine}: ${id}`; - let startIndex = idResult.index; - let endIndex = startIndex + idResult[0].length; - settingsText = originalSettingsText.slice(0, startIndex); - settingsText += originalSettingsText.slice(endIndex + 1); - } - settingsText = settingsText.replace(columnStartSyntax, "column-settings"); - let replacementText = `${columnStartLine}\n${settingsText}`; - offset += replacementText.length - matchLength; - updatedFileContent = updatedFileContent.slice(0, startIndex) + replacementText + updatedFileContent.slice(endIndex); - console.groupCollapsed(); - console.log("Original File:\n\n", originalFileContent); - console.log("Updated File:\n\n", updatedFileContent); - console.groupEnd(); - } - return { - updatedFileContent: updatedFileContent, - numRegionsUpdated: matches.length - }; -} - -class MultiColumnSettingsView extends obsidian.PluginSettingTab { - constructor(app, plugin) { - super(app, plugin); - this.plugin = plugin; - } - display() { - this.containerEl.empty(); - this.containerEl.createEl("h2", { text: "Multi-Column Markdown - Settings" }); - const settingsContainerEl = this.containerEl.createDiv(); - new obsidian.Setting(settingsContainerEl) - .setName("Number of auto-layout balance iterations") - .setDesc("The maximum number of times auto-layout will try to balance elements between all of the columns. Setting this too high may cause Obsidian to slow down during loading and refreshing of Auto-Layout columns.") - .addSlider((slider) => { - slider.setLimits(1, 15, 2); - slider.setValue(MCM_SettingsManager.shared.autoLayoutBalanceIterations); - slider.setDynamicTooltip(); - slider.onChange((val) => { - MCM_SettingsManager.shared.autoLayoutBalanceIterations = val; - this.plugin.saveSettings(); - }); - }); - new obsidian.Setting(settingsContainerEl) - .setName("Align tables with text alignment by default") - .setDesc(this.buildTableAlignDocFrag()) - .addToggle((t) => t.setValue(MCM_SettingsManager.shared.alignTablesToContentAlignment) - .onChange((v) => { - MCM_SettingsManager.shared.alignTablesToContentAlignment = v; - this.plugin.saveSettings(); - })); - new obsidian.Setting(settingsContainerEl) - .setName("Use Live Preview render cache") - .setDesc(this.buildRenderCacheDocFrag()) - .addToggle((t) => t.setValue(MCM_SettingsManager.shared.useLivePreviewCache) - .onChange((v) => { - MCM_SettingsManager.shared.useLivePreviewCache = v; - this.plugin.saveSettings(); - })); - if (obsidian.Platform.isMobile === true) { - new obsidian.Setting(settingsContainerEl) - .setName("Render column regions on mobile devices") - .addToggle((t) => t.setValue(MCM_SettingsManager.shared.renderOnMobile).onChange((v) => { - MCM_SettingsManager.shared.renderOnMobile = v; - this.plugin.saveSettings(); - })); - } - this.containerEl.createEl("h5", { attr: { "style": "color: var(--text-error); margin-bottom: 0px;" }, text: "DANGER ZONE" }); - this.containerEl.createEl("hr", { attr: { "style": "margin-top: 1px; margin-bottom: 0.75em;" } }); - const dangerZoneContainerEl = this.containerEl.createDiv(); - this.buildUpdateDepricated(dangerZoneContainerEl); - this.buildFixMissingIDs(dangerZoneContainerEl); - this.containerEl.createEl("br"); - let { bgColor, fontColor, coffeeColor } = getDonateButtonColors(this.containerEl); - new obsidian.Setting(this.containerEl) - .setName("Donate") - .setDesc(`If you like this Plugin, please consider providing a one time donation to support it's development.`) - .addButton((b) => { - b.buttonEl.setAttr("style", "background-color: transparent; height: 30pt; padding: 0px;"); - const div = b.buttonEl.createDiv({ attr: { "style": "width: 100%; height: 100%" } }); - div.createEl("a", { - href: "https://www.buymeacoffee.com/ckrobinson" - }).createEl("img", { - attr: { - style: "width: 100%; height: 100%", - src: `https://img.buymeacoffee.com/button-api/?text=Buy me a coffee&emoji=&slug=ckrobinson&button_colour=${bgColor}&font_colour=${fontColor}&font_family=Cookie&outline_colour=000000&coffee_colour=${coffeeColor}` - } - }); - }); - } - buildRenderCacheDocFrag() { - let docFrag = new DocumentFragment(); - docFrag.createDiv({}, div => { - div.createSpan({}, span => { - span.innerText = "Caches rendered content in Live Preview to reduce render cycles and element flashing on note interaction."; - }); - div.createEl("br"); - div.createEl("br"); - div.createSpan({}, span => { - span.innerText = "Only uses cache when a file Live Preview tab is open. If both reading view and Live Preview are opened this feature is disabled."; - }); - div.createEl("br"); - div.createEl("br"); - div.createEl("h5", {}, span => { - span.setAttr("style", "color: var(--text-error); margin-bottom: 0px; margin-top: 3px;"); - span.innerText = "EXPERIMENTAL:"; - }); - div.createSpan({}, span => { - span.setAttr("style", "color: var(--text-error);"); - span.innerText = "This feature is experimental only and has intermittently caused notes to erase column content during development. A fix has been implemented \ - but due to the potential data loss you must opt-in to using this feature. If content is erased you can use Undo to restore the file data. \ - Please make backups and disable if you experience any data loss."; - }); - }); - return docFrag; - } - buildTableAlignDocFrag() { - let docFrag = new DocumentFragment(); - docFrag.createDiv({}, div => { - div.createSpan({}, span => { - span.innerText = "Sets the defalut behavior when determining whether to align table to text alignment."; - }); - div.createEl("br"); - div.createEl("ul").createEl("li", { text: "This value is overwritten when defining the column setting: 'Align Tables to Text Alignment: true/false'" }); - }); - return docFrag; - } - buildUpdateDepricated(dangerZoneContainerEl) { - let docFrag = new DocumentFragment(); - docFrag.createDiv({}, div => { - div.createSpan({}, span => { - span.innerText = "This may take a while for large vaults, you can continue to use Obsidian but application may slow down during process."; - }); - div.createEl("br"); - div.createEl("br"); - div.createEl("h5", {}, span => { - span.setAttr("style", "color: var(--text-error); margin-bottom: 0px; margin-top: 3px;"); - span.innerText = "WARNING:"; - }); - div.createSpan({}, span => { - span.setAttr("style", "color: var(--text-error);"); - span.innerText = "This action modifies any note file with depricated syntax and could lead to corrupted file text."; - }); - div.createEl("br"); - div.createSpan({}, span => { - span.setAttr("style", "color: var(--text-error);"); - span.innerText = "No guarentee is given. Please make sure to back your vault up first."; - }); - }); - let modalDescriptionEl = createDiv({}, div => { - div.createSpan({ text: "This action may corrupt vault data." }); - div.createEl("br"); - div.createSpan({ text: "Please confirm you have backed up your vault." }); - }); - new obsidian.Setting(dangerZoneContainerEl) - .setName("Update ALL depricated Multi-Column syntax.") - .setDesc(docFrag) - .addButton((b) => b.setButtonText("Update Syntax").onClick(() => { - const modal = ConfirmModal.confirmModalWithElement(this.app, modalDescriptionEl, { primary: "Confirm", secondary: "Cancel" }); - modal.onClose = () => { - if (modal.confirmed === false) { - return; - } - updateFileSyntax(); - }; - modal.open(); - })); - } - buildFixMissingIDs(dangerZoneContainerEl) { - let docFrag = new DocumentFragment(); - docFrag.createDiv({}, div => { - div.createSpan({}, span => { - span.innerText = "This will only modify column regions without a pre-defined ID, and which use the up to date core syntax. Will not modify depricated syntax or fenced-divs."; - }); - div.createEl("br"); - div.createEl("br"); - div.createSpan({}, span => { - span.innerText = "This may take a while for large vaults, you can continue to use Obsidian but application may slow down during process."; - }); - div.createEl("br"); - div.createEl("br"); - div.createEl("h5", {}, span => { - span.setAttr("style", "color: var(--text-error); margin-bottom: 0px; margin-top: 3px;"); - span.innerText = "WARNING:"; - }); - div.createSpan({}, span => { - span.setAttr("style", "color: var(--text-error);"); - span.innerText = "This action modifies any note file missing column IDs and could lead to corrupted file text."; - }); - div.createEl("br"); - div.createSpan({}, span => { - span.setAttr("style", "color: var(--text-error);"); - span.innerText = "No guarentee is given. Please make sure to back your vault up first."; - }); - }); - let modalDescriptionEl = createDiv({}, div => { - div.createSpan({ text: "This action may corrupt vault data." }); - div.createEl("br"); - div.createSpan({ text: "Please confirm you have backed up your vault." }); - }); - new obsidian.Setting(dangerZoneContainerEl) - .setName("Append IDs to all Multi-Column regions in vault.") - .setDesc(docFrag) - .addButton((b) => b.setButtonText("Add IDs").onClick(() => { - const modal = ConfirmModal.confirmModalWithElement(this.app, modalDescriptionEl, { primary: "Confirm", secondary: "Cancel" }); - modal.onClose = () => { - if (modal.confirmed === false) { - return; - } - findAndReplaceMissingIDs(); - }; - modal.open(); - })); - } -} -class ConfirmModal extends obsidian.Modal { - static confirmModalWithText(app, text, buttons) { - return new ConfirmModal(app, createSpan({ text: text }), buttons); - } - static confirmModalWithElement(app, descriptionEl, buttons) { - return new ConfirmModal(app, descriptionEl, buttons); - } - constructor(app, descriptionEl, buttons) { - super(app); - this.confirmed = false; - this.descriptionEl = descriptionEl; - this.buttons = buttons; - } - display() { - return __awaiter(this, void 0, void 0, function* () { - this.contentEl.empty(); - this.contentEl.appendChild(this.descriptionEl); - const buttonEl = this.contentEl.createDiv(); - new obsidian.ButtonComponent(buttonEl) - .setButtonText(this.buttons.primary) - .setCta() - .onClick(() => { - this.confirmed = true; - this.close(); - }); - new obsidian.ButtonComponent(buttonEl) - .setButtonText(this.buttons.secondary) - .onClick(() => { - this.close(); - }); - }); - } - onOpen() { - this.display(); - } -} -function findAndReplaceMissingIDs() { - return __awaiter(this, void 0, void 0, function* () { - function searchFileForMissingID(docText) { - let lines = docText.split("\n"); - /** - * Loop through all of the lines checking if the line is a - * start tag and if so is it missing an ID. - */ - let linesWithoutIDs = 0; - for (let i = 0; i < lines.length; i++) { - let data = isStartTagWithID(lines[i]); - if (data.isStartTag === true && data.hasKey === false) { - let originalText = lines[i]; - let text = originalText; - text = text.trimEnd(); - if (text.charAt(text.length - 1) === ":") { - text = text.slice(0, text.length - 1); - } - text = `${text}: ID_${getUID(4)}`; - lines[i] = text; - linesWithoutIDs++; - } - } - if (linesWithoutIDs === 0) { - return { - updatedFileContent: docText, - numRegionsUpdated: 0 - }; - } - let newFileContent = lines.join("\n"); - return { - updatedFileContent: newFileContent, - numRegionsUpdated: linesWithoutIDs - }; - } - let count = 0; - let fileCount = 0; - for (let mdFile of app.vault.getMarkdownFiles()) { - let originalFileContent = yield app.vault.read(mdFile); - let result = searchFileForMissingID(originalFileContent); - if (result.numRegionsUpdated > 0) { - count += result.numRegionsUpdated; - fileCount++; - let updatedFileContent = result.updatedFileContent; - if (updatedFileContent !== originalFileContent) { - app.vault.modify(mdFile, updatedFileContent); - } - else { - console.log("No changes, not updating file."); - } - } - } - new obsidian.Notice(`Finished updating:\n${count} region IDs, across ${fileCount} files.`); - }); -} -function updateFileSyntax() { - return __awaiter(this, void 0, void 0, function* () { - let fileCount = 0; - let regionStartCount = 0; - let columnBreakCount = 0; - let columnEndCount = 0; - for (let mdFile of app.vault.getMarkdownFiles()) { - let originalFileContent = yield app.vault.read(mdFile); - let result = updateAllSyntax(originalFileContent); - fileCount += result.fileCount; - regionStartCount += result.regionStartCount; - columnBreakCount += result.columnBreakCount; - columnEndCount += result.columnEndCount; - let updatedFileContent = result.updatedFileContent; - // TODO: Add in final file modification when done testing. - if (result.fileWasUpdated) { - app.vault.modify(mdFile, updatedFileContent); - } - } - new obsidian.Notice(`Finished updating:\n${regionStartCount} start syntaxes,\n${columnBreakCount} column breaks, and\n${columnEndCount} column end tags,\nacross ${fileCount} files.`); - }); -} -function getDonateButtonColors(containerEl) { - let computedStyle = getComputedStyle(containerEl); - let fontColor = computedStyle.getPropertyValue('--text-normal'); - let bgColor = computedStyle.getPropertyValue('--accent'); - let coffeeColor = "ffffff"; - if (isValidHexColor(fontColor) && - isValidHexColor(bgColor)) { - fontColor = fontColor.slice(1); - bgColor = bgColor.slice(1); - coffeeColor = fontColor; - } - else { - fontColor = "000000"; - bgColor = "FFDD00"; - coffeeColor = "ffffff"; - } - return { bgColor, fontColor, coffeeColor }; -} -function isValidHexColor(possibleColor) { - let firstChar = possibleColor[0]; - if (firstChar !== "#") { - return false; - } - if (possibleColor.length !== 7) { - return false; - } - return /^#[0-9A-F]{6}$/i.test(possibleColor); -} - -/* - * File: multi-column-markdown/src/main.ts - * Created Date: Tuesday, October 5th 2021, 1:09 pm - * Author: Cameron Robinson - * - * Copyright (c) 2022 Cameron Robinson - */ -const CODEBLOCK_START_STRS = [ - "start-multi-column", - "multi-column-start" -]; -class MultiColumnMarkdown extends obsidian.Plugin { - constructor() { - super(...arguments); - this.settingsManager = MCM_SettingsManager.shared; - this.globalManager = new GlobalDOMManager(); - //#endregion PDF Exporting. - } - onload() { - return __awaiter(this, void 0, void 0, function* () { - console.log("Loading multi-column markdown"); - yield this.loadSettings(); - this.globalManager = new GlobalDOMManager(); - this.registerEditorExtension(multiColumnMarkdown_StateField); - this.registerEditorExtension(MultiColumnMarkdown_OnClickFix); - for (let i = 0; i < CODEBLOCK_START_STRS.length; i++) { - let startStr = CODEBLOCK_START_STRS[i]; - this.setupMarkdownCodeblockPostProcessor(startStr); - } - this.setupMarkdownPostProcessor(); - this.addSettingTab(new MultiColumnSettingsView(this.app, this)); - this.addCommand({ - id: `toggle-mobile-rendering-mcm`, - name: `Toggle Mobile Rendering - Multi-Column Markdown`, - callback: () => __awaiter(this, void 0, void 0, function* () { - this.settingsManager.renderOnMobile = !this.settingsManager.renderOnMobile; - yield this.saveSettings(); - let noticeString = `Toggled mobile rendering ${this.settingsManager.renderOnMobile ? "on" : "off"}.`; - if (obsidian.Platform.isMobile === true) { - noticeString += ` Please reload any open files for change to take effect.`; - } - new obsidian.Notice(noticeString); - }) - }); - //TODO: Set up this as a modal to set settings automatically - this.addCommand({ - id: `insert-multi-column-region`, - name: `Insert Multi-Column Region`, - editorCallback: (editor, view) => { - try { - let cursorStartPosition = editor.getCursor("from"); - editor.getDoc().replaceSelection(` ---- start-multi-column: ID_${getUID(4)} -\`\`\`column-settings -Number of Columns: 2 -Largest Column: standard -\`\`\` - - - ---- column-break --- - - - ---- end-multi-column - -${editor.getDoc().getSelection()}`); - cursorStartPosition.line = cursorStartPosition.line + 7; - cursorStartPosition.ch = 0; - editor.setCursor(cursorStartPosition); - } - catch (e) { - new obsidian.Notice("Encountered an error inserting a multi-column region. Please try again later."); - } - } - }); - this.addCommand({ - id: `clear-lp-cache-mcm`, - name: `Clear Live Preview Cache - Multi-Column Markdown`, - callback: () => __awaiter(this, void 0, void 0, function* () { - clearLivePreviewCache(); - }) - }); - this.addCommand({ - id: `add-IDs-To-multi-column-region`, - name: `Fix Missing IDs for Multi-Column Regions`, - editorCallback: (editor, view) => { - try { - /** - * Not sure if there is an easier way to do this. - * - * Get all of the lines of the document split by newlines. - */ - let docText = editor.getRange({ line: 0, ch: 0 }, { line: editor.getDoc().lineCount(), ch: 0 }); - let lines = docText.split("\n"); - let startCodeblock = findStartCodeblock(docText); - let lineOffset = 0; - let numCodeblocksUpdated = 0; - while (startCodeblock.found === true) { - // Get the text of the settings block so we can check if it contains an ID, - // also so we can get the length of the first line, used to calculate where to append a new ID if needed - let settingsText = docText.slice(startCodeblock.startPosition, startCodeblock.endPosition); - let firstLineOfCodeblockLength = settingsText.split("\n")[0].length; - // We need the lines before the block to know where to start replacing text - // and the lines including the block to know where to set our offset to after this iteration. - let linesBefore = docText.slice(0, startCodeblock.startPosition); - let startReplacementLineIndex = (linesBefore.split("\n").length - 1) + lineOffset; - let linesOf = docText.slice(0, startCodeblock.endPosition); - let endReplacementLineIndex = (linesOf.split("\n").length - 1) + lineOffset; - let settingsID = parseStartRegionCodeBlockID(settingsText); - if (settingsID === "") { - // copy the first line of the codeblock and append a new ID, then replace the first line of the block - let replacementText = editor.getRange({ line: startReplacementLineIndex, ch: 0 }, { line: startReplacementLineIndex, ch: firstLineOfCodeblockLength }) + `\nID: ID_${getUID(4)}`; - editor.replaceRange(replacementText, { line: startReplacementLineIndex, ch: 0 }, { line: startReplacementLineIndex, ch: firstLineOfCodeblockLength }); - endReplacementLineIndex += 1; - numCodeblocksUpdated += 1; - } - lineOffset = endReplacementLineIndex; - docText = docText.slice(startCodeblock.endPosition); - startCodeblock = findStartCodeblock(docText); - } - /** - * Loop through all of the lines checking if the line is a - * start tag and if so is it missing an ID. - */ - let linesWithoutIDs = []; - let textWithoutIDs = []; - for (let i = 0; i < lines.length; i++) { - let data = isStartTagWithID(lines[i]); - if (data.isStartTag === true && data.hasKey === false) { - linesWithoutIDs.push(i); - textWithoutIDs.push(lines[i]); - } - } - if (linesWithoutIDs.length === 0 && numCodeblocksUpdated === 0) { - new obsidian.Notice("Found 0 missing IDs in the current document."); - return; - } - /** - * Now loop through each line that is missing an ID and - * generate a random ID and replace the original text. - */ - for (let i = 0; i < linesWithoutIDs.length; i++) { - let originalText = textWithoutIDs[i]; - let text = originalText; - text = text.trimEnd(); - if (text.charAt(text.length - 1) === ":") { - text = text.slice(0, text.length - 1); - } - text = `${text}: ID_${getUID(4)}`; - editor.replaceRange(text, { line: linesWithoutIDs[i], ch: 0 }, { line: linesWithoutIDs[i], ch: originalText.length }); - } - new obsidian.Notice(`Replaced ${linesWithoutIDs.length + numCodeblocksUpdated} missing ID(s) in the current document.`); - } - catch (e) { - new obsidian.Notice("Encountered an error addign IDs to multi-column regions. Please try again later."); - } - } - }); - this.addCommand({ - id: `mcm-Toggle-Document-Reflow`, - name: `Setup Multi-Column Reflow - Multi-Column Markdown`, - editorCallback: (editor, view) => { - app.fileManager.processFrontMatter(view.file, (frontmatter) => { - let isReflow = isMultiColumnReflow(frontmatter); - if (isReflow) { - return; - } - frontmatter["Multi-Column Markdown"] = [ - { "Number of Columns": 2 }, - { "Column Size": "Standard" } - ]; - view.editor.refresh(); - }); - } - }); - this.addCommand({ - id: `mcm-fix-file-multi-column-syntax`, - name: `Fix Multi-Column Syntax in Current File.`, - editorCallback: (editor, view) => { - try { - let fromPosition = { line: 0, ch: 0 }; - let toPosition = { line: editor.getDoc().lineCount(), ch: 0 }; - let docText = editor.getRange(fromPosition, toPosition); - let result = updateAllSyntax(docText); - let regionStartCount = result.regionStartCount; - let columnBreakCount = result.columnBreakCount; - let columnEndCount = result.columnEndCount; - let updatedFileContent = result.updatedFileContent; - if (result.fileWasUpdated) { - editor.replaceRange(updatedFileContent, fromPosition, toPosition); - new obsidian.Notice(`Finished updating:\n${regionStartCount} start syntaxes,\n${columnBreakCount} column breaks, and\n${columnEndCount} column end tags.`); - } - else { - new obsidian.Notice(`Found no region syntax to update.`); - } - } - catch (e) { - new obsidian.Notice("Encountered an error fixing multi-column region syntax. Please try again later."); - } - } - }); - this.registerInterval(window.setInterval(() => { - this.UpdateOpenFilePreviews(); - }, 500)); - }); - } - UpdateOpenFilePreviews() { - let fileManagers = this.globalManager.getAllFileManagers(); - fileManagers.forEach(element => { - let regionalManagers = element.getAllRegionalManagers(); - regionalManagers.forEach(regionManager => { - regionManager.updateRenderedMarkdown(); - }); - }); - } - setupMarkdownPostProcessor() { - this.registerMarkdownPostProcessor((el, ctx) => __awaiter(this, void 0, void 0, function* () { - if (this.settingsManager.renderOnMobile === false && - obsidian.Platform.isMobile === true) { - return; - } - const sourcePath = ctx.sourcePath; - let fileDOMManager = this.globalManager.getFileManager(sourcePath); - if (fileDOMManager === null) { - console.warn("Found null DOM manager. Could not process multi-column markdown."); - return; - } - /** - * Here we check if the export "print" flag is in the DOM so we can determine if we - * are exporting and handle that case. - */ - if (this.checkExporting(el)) { - this.exportDocumentToPDF(el, fileDOMManager, sourcePath); - } - // Get the info for our current context and then check - // if the entire text contains a start tag. If there is - // no start tag in the document we can just return and - // ignore the rest of the parsing. - let info = ctx.getSectionInfo(el); - /** - * We need the context info to properly parse so returning here - * info is null. TODO: Set error in view if this occurs. - */ - if (!info) { - return; - } - let docString = info.text; - let docLines = docString.split("\n"); - let reflowFrontmatter = isMultiColumnReflow(ctx.frontmatter); - if (reflowFrontmatter === true) { - this.renderDocReflow(el, ctx, sourcePath, fileDOMManager, docString, info); - return; - } - else { - fileDOMManager.removeRegion("Multi-Column Reflow Region"); - } - /** - * If we encounter a start tag on the document we set the flag to start - * parsing the rest of the document. - */ - if (containsRegionStart(docString)) { - fileDOMManager.setHasStartTag(); - } - /** - * If the document does not contain any start tags we ignore the - * rest of the parsing. This is only set to true once the first - * start tag element is parsed above. - */ - if (fileDOMManager.getHasStartTag() === false) { - return; - } - /** - * Take the info provided and generate the required variables from - * the line start and end values. - */ - let relativeTexts = extractElementRelativeLocationData(docLines, info); - /** - * If the current line is a start tag we want to set up the - * region manager. The regional manager takes care - * of all items between it's start and end tags while the - * file manager we got above above takes care of all regional - * managers in each file. - */ - if (containsStartTag(relativeTexts.textOfElement)) { - createStartElement(el, relativeTexts.linesOfElement, ctx, fileDOMManager, docString); - return; - } - // Pandoc Start Region Tag. - if (containsPandocStartTag(relativeTexts.textOfElement)) { - createPandocStartElement(el, relativeTexts.textOfElement, ctx, fileDOMManager, docString); - return; - } - /** - * Check if any of the lines above us contain a start block, and if - * so get the lines from our current element to the start block. - */ - let startBockAbove = getStartDataAboveLine(relativeTexts.linesAboveArray); - if (startBockAbove === null) { - return; - } - /** - * We now know we're within a multi-column region, so we update our - * list of lines above to just be the items within this region. - */ - relativeTexts.linesAboveArray = startBockAbove.linesAboveArray; - /** - * We use the start block's key to get our regional manager. If this - * lookup fails we can not continue processing this element. - */ - let regionalContainer = fileDOMManager.getRegionalContainer(startBockAbove.startBlockKey); - if (regionalContainer === null) { - return; - } - regionalContainer.getRegion(); - /** - * To make sure we're placing the item in the right location (and - * overwrite elements that are now gone) we now want all of the - * lines after this element up to the end tag. - */ - relativeTexts.linesBelowArray = getEndBlockBelow(relativeTexts.linesBelowArray); - /** - * Now we take the lines above our current element up until the - * start region tag and render that into an HTML element. We will - * use these elements to determine where to place our current element. - */ - this.appendToRegionalManager(el, regionalContainer, ctx, relativeTexts, sourcePath, startBockAbove, (domObj) => { - onUnloadElement(domObj, regionalContainer); - }); - return; - })); - } - appendToRegionalManager(el, regionalContainer, ctx, relativeLines, sourcePath, parentStartBlock, onUnloadCallback) { - let { linesAboveArray, linesOfElement, linesBelowArray, textOfElement } = relativeLines; - let siblingsAbove = renderMarkdownFromLines(linesAboveArray, sourcePath); - let siblingsBelow = renderMarkdownFromLines(linesBelowArray, sourcePath); - let regionalManager = regionalContainer.getRegion(); - /** - * Set up our dom object to be added to the manager. - */ - let currentObject = new DOMObject(el, linesOfElement); - el.id = currentObject.UID; - currentObject = TaskListDOMObject.checkForTaskListElement(currentObject); - /** - * Now we add the object to the manager and then setup the - * callback for when the object is removed from view that will remove - * the item from the manager. - */ - regionalManager.addObject(siblingsAbove, siblingsBelow, currentObject); - let elementMarkdownRenderer = new obsidian.MarkdownRenderChild(el); - elementMarkdownRenderer.onunload = () => { - onUnloadCallback(currentObject); - }; - ctx.addChild(elementMarkdownRenderer); - /** - * Now we check if our current element is a special flag so we can - * properly set the element tag within the regional manager. - */ - if (containsEndTag(el.textContent) === true && - parentStartBlock.startBlockType !== "PADOC") { - currentObject.elementType = "unRendered"; - regionalManager.updateElementTag(currentObject.UID, DOMObjectTag.endRegion); - } - if (isValidPandocEndTag(linesAboveArray, el.textContent) === true && - parentStartBlock.startBlockType === "PADOC") { - currentObject.elementType = "unRendered"; - regionalManager.updateElementTag(currentObject.UID, DOMObjectTag.endRegion); - } - else if (containsColEndTag(textOfElement) === true) { - currentObject.elementType = "unRendered"; - regionalManager.updateElementTag(currentObject.UID, DOMObjectTag.columnBreak); - } - else if (containsColSettingsTag(textOfElement) === true) { - currentObject.elementType = "unRendered"; - regionalManager = regionalContainer.setRegionSettings(textOfElement); - regionalManager.updateElementTag(currentObject.UID, DOMObjectTag.regionSettings); - } - setElementCSS(currentObject, el); - parseColBreakErrorType({ - lineAbove: linesAboveArray.last(), - lineBelow: linesBelowArray.first(), - objectTag: currentObject.tag, - colBreakType: currentObject.elementIsColumnBreak - }, regionalManager.errorManager); - regionalManager.renderRegionElementsToScreen(); - return regionalManager; - } - setupMarkdownCodeblockPostProcessor(startStr) { - this.registerMarkdownCodeBlockProcessor(startStr, (source, el, ctx) => { - var _a; - if (this.settingsManager.renderOnMobile === false && - obsidian.Platform.isMobile === true) { - return; - } - const sourcePath = ctx.sourcePath; - // Set up our CSS so that the codeblock only renders this data in reading mode - // source/live preview mode is handled by the CM6 implementation. - (_a = el.parentElement) === null || _a === void 0 ? void 0 : _a.addClass("preivew-mcm-start-block"); - // To determine what kind of view we are rendering in we need a markdown leaf. - // Really this should never return here since rendering is only done in markdown leaves. - let markdownLeaves = app.workspace.getLeavesOfType("markdown"); - if (markdownLeaves.length === 0) { - return; - } - if (this.globalManager === null || this.globalManager === undefined) { - // console.log("Global manager is undefined?"); - return; - } - let fileDOMManager = this.globalManager.getFileManager(sourcePath); - if (fileDOMManager === null) { - return; - } - if (ctx.frontmatter && - ctx.frontmatter["Multi-Column Reflow"] !== undefined) { - return; - } - else { - fileDOMManager.removeRegion("Multi-Column Reflow Region"); - } - // Set file to have start tag. - fileDOMManager.setHasStartTag(); - // Get the info for our current context and then check - // if the entire text contains a start tag. If there is - // no start tag in the document we can just return and - // ignore the rest of the parsing. - let info = ctx.getSectionInfo(el); - /** - * We need the context info to properly parse so returning here - * info is null. TODO: Set error in view if this occurs. - */ - if (!info) { - return; - } - /** - * Set up the current element to act as the parent for the - * multi-column region. - */ - el.classList.add(MultiColumnLayoutCSS.RegionRootContainerDiv); - let errorManager = new RegionErrorManager(el, ["The codeblock region start syntax has been depricated. Please manually update to the current syntax defined in the ReadMe, run the \"Fix Multi-Column Syntax in Current File\" from the Command Palette, or use the \"Update Depricated Syntax\" command found in the plugin settings window. You must reload the file for changes to take effect."]); - let renderColumnRegion = el.createDiv({ - cls: MultiColumnLayoutCSS.RegionContentContainerDiv - }); - let regionKey = parseStartRegionCodeBlockID(source); - let createNewRegionManager = true; - if (fileDOMManager.checkKeyExists(regionKey) === true) { - createNewRegionManager = false; - let { numberOfTags, keys } = countStartTags(info.text); - let numMatches = 0; - for (let i = 0; i < numberOfTags; i++) { - // Because we checked if key exists one of these has to match. - if (keys[i] === regionKey) { - numMatches++; - } - } - // We only want to display an error if there are more than 2 of the same id across - // the whole document. This prevents erros when obsidian reloads the whole document - // and there are two of the same key in the map. - if (numMatches >= 2) { - if (regionKey === "") { - errorManager.addErrorMessage("Found multiple regions with empty IDs. Please set a unique ID in the codeblock.\nEG: 'ID: randomID'"); - } - else { - errorManager.addErrorMessage("Region ID already exists in document, please set a unique ID."); - } - return; - } - } - el.id = `MultiColumnID:${regionKey}`; - // If something changes in the codeblock we dont necessarily want to update our - // old reference to the region manager. This could be a potential bug area. - if (createNewRegionManager === true) { - // Create a new regional manager. - let elementMarkdownRenderer = new obsidian.MarkdownRenderChild(el); - fileDOMManager.createRegionalManager(regionKey, el, errorManager, renderColumnRegion); - // Set up the on unload callback. This can be called if the user changes - // the start/settings codeblock in any way. We only want to unload - // if the file is being removed from view. - elementMarkdownRenderer.onunload = () => { - if (fileDOMManager && fileStillInView(sourcePath) === false) { - // console.debug("File not in any markdown leaf. Removing region from dom manager.") - fileDOMManager.removeRegion(regionKey); - } - }; - ctx.addChild(elementMarkdownRenderer); - } - let regionalManagerContainer = fileDOMManager.getRegionalContainer(regionKey); - if (regionalManagerContainer !== null) { - let regionalManager = regionalManagerContainer.setRegionSettings(source); - regionalManager.regionParent = renderColumnRegion; - } - }); - } - loadSettings() { - return __awaiter(this, void 0, void 0, function* () { - this.settingsManager.settings = Object.assign({}, DEFAULT_SETTINGS, yield this.loadData()); - }); - } - saveSettings() { - return __awaiter(this, void 0, void 0, function* () { - yield this.saveData(this.settingsManager.settings); - }); - } - renderDocReflow(el, ctx, sourcePath, fileDOMManager, docString, info) { - let regionalContainer = null; - if (fileDOMManager.checkKeyExists("Multi-Column Reflow Region") === true && - el.getElementsByClassName("frontmatter").length === 0) { - regionalContainer = fileDOMManager.getRegionalContainer("Multi-Column Reflow Region"); - } - else if (fileDOMManager.checkKeyExists("Multi-Column Reflow Region") === true && - el.getElementsByClassName("frontmatter").length === 1) { - let parentEl = createDiv(); - el.appendChild(parentEl); - // Get current data, remove old region. - regionalContainer = fileDOMManager.getRegionalContainer("Multi-Column Reflow Region"); - let domList = regionalContainer.getRegion().getRegionData().domList.slice(); - fileDOMManager.removeRegion("Multi-Column Reflow Region"); - // Create new region. - setupStartTag(parentEl, ctx, fileDOMManager, docString, "Multi-Column Reflow Region"); - regionalContainer = fileDOMManager.getRegionalContainer("Multi-Column Reflow Region"); - let settings = getMultiColumnSettingsFromFrontmatter(ctx); - let leaf = getLeafFromFilePath(this.app.workspace, ctx.sourcePath); - let clientHeight = calcVisibleClietHeight(leaf, this.app.workspace); - if (settings.columnHeight === null) { - settings.columnHeight = HTMLSizing.create().setWidth(clientHeight).setUnits("px"); - } - else { - settings.columnHeight = settings.columnHeight.convertToPX(this.app.workspace.containerEl); - } - regionalContainer.setRegionParsedSettings(settings); - // Re-Render after small delay. - // Delay is so the auto layout check can properly read the client height. - function delayRender() { - return __awaiter(this, void 0, void 0, function* () { - setTimeout(() => { - // Append all items to region. - let regionalManager = regionalContainer.getRegion(); - let listLength = domList.length; - for (let i = 0; i < listLength; i++) { - let domObj = domList.shift(); - regionalManager.addObjectAtIndex(domObj, i); - setElementCSS(domObj, domObj.originalElement); - } - regionalContainer.getRegion().renderRegionElementsToScreen(); - }, 50); - }); - } - delayRender(); - return; - } - else { - // The first element to hit this point appears to be the yaml information which we can use - // as our root div since the whole doc is going to be re-formatted. - let parentEl = createDiv(); - el.appendChild(parentEl); - setupStartTag(parentEl, ctx, fileDOMManager, docString, "Multi-Column Reflow Region"); - regionalContainer = fileDOMManager.getRegionalContainer("Multi-Column Reflow Region"); - let settings = getMultiColumnSettingsFromFrontmatter(ctx); - let leaf = getLeafFromFilePath(this.app.workspace, ctx.sourcePath); - let clientHeight = calcVisibleClietHeight(leaf, this.app.workspace); - if (settings.columnHeight === null) { - settings.columnHeight = HTMLSizing.create().setWidth(clientHeight).setUnits("px"); - } - else { - settings.columnHeight = settings.columnHeight.convertToPX(this.app.workspace.containerEl); - } - regionalContainer.setRegionParsedSettings(settings); - return; - } - if (regionalContainer === null) { - return; - } - let docLines = docString.split("\n"); - let relativeTexts = extractElementRelativeLocationData(docLines, info); - relativeTexts.linesBelowArray = getEndBlockBelow(relativeTexts.linesBelowArray); - if (containsStartTag(relativeTexts.textOfElement) || - containsColSettingsTag(relativeTexts.textOfElement)) { - if (containsStartTag(relativeTexts.textOfElement)) { - setElementCSSByTag(DOMObjectTag.startRegion, el); - } - else if (containsColSettingsTag(relativeTexts.textOfElement)) { - setElementCSSByTag(DOMObjectTag.regionSettings, el); - } - return; - } - let startBockAbove = { - linesAboveArray: relativeTexts.linesAboveArray, - startBlockKey: "Multi-Column Reflow Region", - startBlockType: "ORIGINAL" - }; - this.appendToRegionalManager(el, regionalContainer, ctx, relativeTexts, sourcePath, startBockAbove, (domObj) => { - onUnloadElement(domObj, regionalContainer); - }); - } - //#region PDF Exporting. - isStartCodeblockInExport(node) { - for (let i = 0; i < CODEBLOCK_START_STRS.length; i++) { - if (node.hasClass(`block-language-${CODEBLOCK_START_STRS[i]}`)) { - return true; - } - } - return false; - } - exportDocumentToPDF(el, fileDOMManager, sourcePath) { - return __awaiter(this, void 0, void 0, function* () { - // A true export will be passed an element with all other items in the doc as children. - // So if there are no children we can just return - let docChildren = Array.from(el.childNodes); - if (docChildren.length === 0) { - return; - } - let childrenToRemove = []; - // To export codeblocks we need to get the IDs so we can get the data from our managers. - // however since the ID isnt being stored in the element yet this means we need to read - // all of the IDs out of the full document. - let codeblockStartBlocks = []; - let aFile = this.app.vault.getAbstractFileByPath(sourcePath); - if (aFile instanceof obsidian.TFile) { - let file = aFile; - let fileText = yield this.app.vault.cachedRead(file); // Is cached read Ok here? It should be. - // Once we have our data we search the text for all codeblock start values. - // storing them into our queue. - let codeBlockData = findStartCodeblock(fileText); - while (codeBlockData.found === true) { - let codeblockText = fileText.slice(codeBlockData.startPosition, codeBlockData.endPosition); - fileText = fileText.slice(codeBlockData.endPosition); - codeblockStartBlocks.push(codeblockText); - codeBlockData = findStartCodeblock(fileText); - } - } - else { - console.error(`Error getting file from source path: ${sourcePath}`); - } - let inBlock = false; - for (let i = 0; i < docChildren.length; i++) { - let child = docChildren[i]; - if (child instanceof HTMLElement) { - if (inBlock === false) { - let foundBlockData = false; - let regionKey = ""; - let blockData = isStartTagWithID(child.textContent); - let pandocData = getPandocStartData(child.textContent); - if (blockData.isStartTag === true) { - // If an old-style start tag. - foundBlockData = true; - if (blockData.hasKey === true) { - let foundKey = getStartTagKey(child.textContent); - if (foundKey !== null) { - regionKey = foundKey; - } - } - } - else if (blockData.isStartTag === false && this.isStartCodeblockInExport(child)) { - // If the start tag from the old version is null we then check to see if the element is - // a codeblock start. If it is we use the next available codeblock data to retrieve our ID. - let codeblockText = codeblockStartBlocks.shift(); - if (codeblockText === undefined) { - console.error("Found undefined codeblock data when exporting."); - return; - } - let id = parseStartRegionCodeBlockID(codeblockText); - if (id !== "") { - foundBlockData = true; - regionKey = id; - } - } - else if (pandocData.found) { - foundBlockData = true; - regionKey = pandocData.userSettings.columnID; - } - if (foundBlockData === true && regionKey !== "") { - inBlock = true; - for (let i = child.children.length - 1; i >= 0; i--) { - child.children[i].detach(); - } - child.innerText = ""; - child.classList.add(MultiColumnLayoutCSS.RegionRootContainerDiv); - let errorManager = new RegionErrorManager(el); - let renderColumnRegion = child.createDiv({ - cls: MultiColumnLayoutCSS.RegionContentContainerDiv - }); - let regionalContainer = fileDOMManager.getRegionalContainer(regionKey); - if (regionalContainer === null || regionalContainer.getRegion().numberOfChildren === 0) { - // If the number of children is 0, we are probably in LivePreview, where the codeblock start regions have been processed by native obsidian live preview but do not have any children linked to them. - errorManager.addErrorMessage("Error rendering multi-column region.\nPlease close and reopen the file, then make sure you are in reading mode before exporting."); - } - else { - let regionalManager = regionalContainer.getRegion(); - regionalManager.exportRegionElementsToPDF(renderColumnRegion); - } - } - } - else { - if (containsEndTag(child.textContent) === true || - containsPandocEndTag(child.textContent) === true) { - inBlock = false; - } - childrenToRemove.push(child); - } - } - } - childrenToRemove.forEach(child => { - if (child.parentElement === el) { - el.removeChild(child); - } - }); - }); - } - checkExporting(element) { - if (element === null) { - return false; - } - if (element.classList.contains("print")) { - return true; - } - if (element.parentNode !== null) { - return this.checkExporting(element.parentElement); - } - return false; - } -} -function setElementCSS(currentObject, el) { - setElementCSSByTag(currentObject.tag, el); -} -function setElementCSSByTag(tag, el) { - if (tag === DOMObjectTag.endRegion) { - el.addClass(MultiColumnStyleCSS.RegionEndTag); - } - else if (tag === DOMObjectTag.columnBreak) { - el.addClass(MultiColumnStyleCSS.ColumnEndTag); - } - else if (tag === DOMObjectTag.regionSettings) { - el.addClass(MultiColumnStyleCSS.RegionSettings); - } - else { - el.addClass(MultiColumnStyleCSS.RegionContent); - } -} -function onUnloadElement(currentObject, regionalContainer) { - if (regionalContainer === null) { - return; - } - let regionalManager = regionalContainer.getRegion(); - if (regionalManager) { - // We can attempt to update the view here after the item is removed - // but need to get the item's parent element before removing object from manager. - let regionRenderData = regionalManager.getRegionRenderData(); - regionalManager.removeObject(currentObject.UID); - /** - * Need to check here if element is null as this closure will be called - * repeatedly on file change. - */ - if (regionRenderData.parentRenderElement === null) { - return; - } - regionalManager.renderRegionElementsToScreen(); - } -} -function extractElementRelativeLocationData(docLines, info) { - let linesAboveArray = docLines.slice(0, info.lineStart); - let linesOfElement = docLines.slice(info.lineStart, info.lineEnd + 1); - let textOfElement = linesOfElement.join("\n"); - let linesBelowArray = docLines.slice(info.lineEnd + 1); - return { - linesAboveArray, - linesOfElement, - linesBelowArray, - textOfElement - }; -} -function createStartElement(el, linesOfElement, ctx, fileDOMManager, docString) { - el.children[0].detach(); - let startBlockData = getStartBlockAboveLine(linesOfElement); - if (startBlockData === null) { - return; - } - let regionID = startBlockData.startBlockKey; - setupStartTag(el, ctx, fileDOMManager, docString, regionID); - return; -} -function createPandocStartElement(el, textOfElement, ctx, fileDOMManager, docString) { - el.children[0].detach(); - let pandocData = getPandocStartData(textOfElement); - let settings = pandocData.userSettings; - let regionManager = setupStartTag(el, ctx, fileDOMManager, docString, settings.columnID); - regionManager.setRegionalSettings(settings); - return; -} -function renderMarkdownFromLines(mdLines, sourcePath) { - /** - * We re-render all of the items above our element, until the start tag, - * so we can determine where to place the new item in the manager. - * - * TODO: Can reduce the amount needing to be rendered by only rendering to - * the start tag or a column-break whichever is closer. - */ - let siblings = createDiv(); - let markdownRenderChild = new obsidian.MarkdownRenderChild(siblings); - obsidian.MarkdownRenderer.renderMarkdown(mdLines.reduce((prev, current) => { - return prev + "\n" + current; - }, ""), siblings, sourcePath, markdownRenderChild); - return siblings; -} -function setupStartTag(el, ctx, fileDOMManager, docString, regionID) { - /** - * Set up the current element to act as the parent for the - * multi-column region. - */ - el.classList.add(MultiColumnLayoutCSS.RegionRootContainerDiv); - let errorManager = new RegionErrorManager(el); - let renderColumnRegion = el.createDiv({ - cls: MultiColumnLayoutCSS.RegionContentContainerDiv - }); - if (fileDOMManager.checkKeyExists(regionID) === true) { - let { numberOfTags, keys } = countStartTags(docString); - let numMatches = 0; - for (let i = 0; i < numberOfTags; i++) { - // Because we checked if key exists one of these has to match. - if (keys[i] === regionID) { - numMatches++; - } - } - // We only want to display an error if there are more than 2 of the same id across - // the whole document. This prevents erros when obsidian reloads the whole document - // and there are two of the same key in the map. - if (numMatches >= 2) { - if (regionID === "") { - errorManager.addErrorMessage("Found multiple regions with empty IDs. Please set a unique ID after each start tag.\nEG: '--- multi-column-start: randomID'\nOr use 'Fix Missing IDs' in the command palette and reload the document."); - } - else { - errorManager.addErrorMessage("Region ID already exists in document, please set a unique ID.\nEG: '--- multi-column-start: randomID'"); - } - return; - } - } - el.id = `MultiColumnID:${regionID}`; - let elementMarkdownRenderer = new obsidian.MarkdownRenderChild(el); - let regionManager = fileDOMManager.createRegionalManager(regionID, el, errorManager, renderColumnRegion); - elementMarkdownRenderer.onunload = () => { - if (fileDOMManager) { - fileDOMManager.removeRegion(regionID); - } - }; - ctx.addChild(elementMarkdownRenderer); - return regionManager; -} -const FRONTMATTER_REGEX = [ - /Multi[- ]*Column *Markdown/i, - /Multi[- ]*Column *Reflow/i -]; -function isMultiColumnReflow(frontmatter) { - if (frontmatter === null || - frontmatter === undefined) { - return false; - } - for (let regex of FRONTMATTER_REGEX) { - let frontmatterReflowData = obsidian.parseFrontMatterEntry(frontmatter, regex); - if (frontmatterReflowData !== null) { - return true; - } - } - let [keys, values] = Object.entries(frontmatter); - if (keys === undefined) { - return false; - } - for (let key of keys) { - if (typeof key !== "string") { - continue; - } - for (let regex of FRONTMATTER_REGEX) { - let regexResult = regex.exec(key); - if (regexResult !== null) { - return true; - } - } - } - return false; -} -function getMultiColumnSettingsFromFrontmatter(ctx) { - let settings = getDefaultMultiColumnSettings(); - settings.fullDocReflow = true; - if (ctx.frontmatter === null || - ctx.frontmatter === undefined) { - return settings; - } - for (let regex of FRONTMATTER_REGEX) { - let frontmatterReflowData = obsidian.parseFrontMatterEntry(ctx.frontmatter, regex); - if (frontmatterReflowData !== null && - Array.isArray(frontmatterReflowData)) { - settings = parseFrontmatterSettings(frontmatterReflowData); - settings.fullDocReflow = true; - break; - } - } - return settings; -} -function parseFrontmatterSettings(frontmatterReflowData) { - let str = ""; - for (let obj of frontmatterReflowData) { - let [key, value] = Object.entries(obj)[0]; - str += `${key}: [${value}]\n`; - } - let settings = parseColumnSettings(str); - return settings; -} -function getContentHeightFromLeaf(leaf) { - let contentEl = leaf.view["contentEl"]; - if (contentEl !== undefined && - contentEl.clientHeight > 0) { - return contentEl.clientHeight; - } - let clientHeight = leaf.view.containerEl.clientHeight; - let titleContainer = leaf.view["titleContainerEl"]; - if (titleContainer !== undefined && - titleContainer.clientHeight > 0) { - return clientHeight - titleContainer.clientHeight; - } - return clientHeight - 50; -} -function calcVisibleClietHeight(leaf, workspace) { - let clientHeight = 0; - if (leaf) { - clientHeight = getContentHeightFromLeaf(leaf); - } - else if ((workspace !== null && workspace !== undefined) && - (workspace.containerEl !== null && workspace.containerEl !== undefined) && - workspace.containerEl.clientHeight > 0) { - clientHeight = workspace.containerEl.clientHeight - 100; - } - else { - clientHeight = 1000; - } - return clientHeight; -} - -module.exports = MultiColumnMarkdown; -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZXMiOlsibm9kZV9tb2R1bGVzL3RzbGliL3RzbGliLmVzNi5qcyIsIm5vZGVfbW9kdWxlcy9AcGFjb3RlL2dldC1zdHlsZS9saWIvZXNtL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL0BwYWNvdGUvcGl4ZWxzL2xpYi9lc20vaW5kZXguanMiLCJzcmMvdXRpbGl0aWVzL2ludGVyZmFjZXMudHMiLCJzcmMvcmVnaW9uU2V0dGluZ3MudHMiLCJzcmMvdXRpbGl0aWVzL3NldHRpbmdzUGFyc2VyLnRzIiwic3JjL3V0aWxpdGllcy9wYW5kb2NQYXJzZXIudHMiLCJzcmMvdXRpbGl0aWVzL3RleHRQYXJzZXIudHMiLCJzcmMvdXRpbGl0aWVzL3V0aWxzLnRzIiwic3JjL2RvbV9tYW5hZ2VyL2RvbU9iamVjdC50cyIsInNyYy91dGlsaXRpZXMvY3NzRGVmaW5pdGlvbnMudHMiLCJzcmMvdXRpbGl0aWVzL2VsZW1lbnRSZW5kZXJUeXBlUGFyc2VyLnRzIiwic3JjL2RvbV9tYW5hZ2VyL3JlZ2lvbmFsX21hbmFnZXJzL3JlZ2lvbk1hbmFnZXIudHMiLCJzcmMvcGx1Z2luU2V0dGluZ3MudHMiLCJzcmMvZG9tX21hbmFnZXIvcmVnaW9uYWxfbWFuYWdlcnMvc3RhbmRhcmRNdWx0aUNvbHVtblJlZ2lvbk1hbmFnZXIudHMiLCJzcmMvZG9tX21hbmFnZXIvcmVnaW9uYWxfbWFuYWdlcnMvc2luZ2xlQ29sdW1uUmVnaW9uTWFuYWdlci50cyIsInNyYy9kb21fbWFuYWdlci9yZWdpb25hbF9tYW5hZ2Vycy9hdXRvTGF5b3V0UmVnaW9uTWFuYWdlci50cyIsInNyYy9kb21fbWFuYWdlci9yZWdpb25hbF9tYW5hZ2Vycy9yZWZsb3dSZWdpb25NYW5hZ2VyLnRzIiwic3JjL2RvbV9tYW5hZ2VyL3JlZ2lvbmFsX21hbmFnZXJzL3JlZ2lvbk1hbmFnZXJDb250YWluZXIudHMiLCJzcmMvZG9tX21hbmFnZXIvZG9tTWFuYWdlci50cyIsInNyYy9kb21fbWFuYWdlci9yZWdpb25FcnJvck1hbmFnZXIudHMiLCJzcmMvdXRpbGl0aWVzL2Vycm9yTWVzc2FnZS50cyIsInNyYy91dGlsaXRpZXMvb2JzaVV0aWxzLnRzIiwic3JjL2xpdmVfcHJldmlldy9tY21fbGl2ZVByZXZpZXdfd2lkZ2V0LnRzIiwic3JjL2xpdmVfcHJldmlldy9jbTZfbGl2ZVByZXZpZXcudHMiLCJzcmMvbGl2ZV9wcmV2aWV3L2NtNl9saXZlUHJlaXZld19vbkNsaWNrRml4LnRzIiwic3JjL3V0aWxpdGllcy9zeW50YXhVcGRhdGUudHMiLCJzcmMvc2V0dGluZ3MvTXVsdGlDb2x1bW5TZXR0aW5nc1ZpZXcudHMiLCJzcmMvbWFpbi50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXHJcbkNvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLlxyXG5cclxuUGVybWlzc2lvbiB0byB1c2UsIGNvcHksIG1vZGlmeSwgYW5kL29yIGRpc3RyaWJ1dGUgdGhpcyBzb2Z0d2FyZSBmb3IgYW55XHJcbnB1cnBvc2Ugd2l0aCBvciB3aXRob3V0IGZlZSBpcyBoZXJlYnkgZ3JhbnRlZC5cclxuXHJcblRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIgQU5EIFRIRSBBVVRIT1IgRElTQ0xBSU1TIEFMTCBXQVJSQU5USUVTIFdJVEhcclxuUkVHQVJEIFRPIFRISVMgU09GVFdBUkUgSU5DTFVESU5HIEFMTCBJTVBMSUVEIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZXHJcbkFORCBGSVRORVNTLiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SIEJFIExJQUJMRSBGT1IgQU5ZIFNQRUNJQUwsIERJUkVDVCxcclxuSU5ESVJFQ1QsIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFUyBPUiBBTlkgREFNQUdFUyBXSEFUU09FVkVSIFJFU1VMVElORyBGUk9NXHJcbkxPU1MgT0YgVVNFLCBEQVRBIE9SIFBST0ZJVFMsIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBORUdMSUdFTkNFIE9SXHJcbk9USEVSIFRPUlRJT1VTIEFDVElPTiwgQVJJU0lORyBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBVU0UgT1JcclxuUEVSRk9STUFOQ0UgT0YgVEhJUyBTT0ZUV0FSRS5cclxuKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogKi9cclxuLyogZ2xvYmFsIFJlZmxlY3QsIFByb21pc2UgKi9cclxuXHJcbnZhciBleHRlbmRTdGF0aWNzID0gZnVuY3Rpb24oZCwgYikge1xyXG4gICAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxyXG4gICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcclxuICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdOyB9O1xyXG4gICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XHJcbn07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19leHRlbmRzKGQsIGIpIHtcclxuICAgIGlmICh0eXBlb2YgYiAhPT0gXCJmdW5jdGlvblwiICYmIGIgIT09IG51bGwpXHJcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNsYXNzIGV4dGVuZHMgdmFsdWUgXCIgKyBTdHJpbmcoYikgKyBcIiBpcyBub3QgYSBjb25zdHJ1Y3RvciBvciBudWxsXCIpO1xyXG4gICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcclxuICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxyXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xyXG59XHJcblxyXG5leHBvcnQgdmFyIF9fYXNzaWduID0gZnVuY3Rpb24oKSB7XHJcbiAgICBfX2Fzc2lnbiA9IE9iamVjdC5hc3NpZ24gfHwgZnVuY3Rpb24gX19hc3NpZ24odCkge1xyXG4gICAgICAgIGZvciAodmFyIHMsIGkgPSAxLCBuID0gYXJndW1lbnRzLmxlbmd0aDsgaSA8IG47IGkrKykge1xyXG4gICAgICAgICAgICBzID0gYXJndW1lbnRzW2ldO1xyXG4gICAgICAgICAgICBmb3IgKHZhciBwIGluIHMpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocywgcCkpIHRbcF0gPSBzW3BdO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gdDtcclxuICAgIH1cclxuICAgIHJldHVybiBfX2Fzc2lnbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19yZXN0KHMsIGUpIHtcclxuICAgIHZhciB0ID0ge307XHJcbiAgICBmb3IgKHZhciBwIGluIHMpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocywgcCkgJiYgZS5pbmRleE9mKHApIDwgMClcclxuICAgICAgICB0W3BdID0gc1twXTtcclxuICAgIGlmIChzICE9IG51bGwgJiYgdHlwZW9mIE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMgPT09IFwiZnVuY3Rpb25cIilcclxuICAgICAgICBmb3IgKHZhciBpID0gMCwgcCA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMocyk7IGkgPCBwLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgIGlmIChlLmluZGV4T2YocFtpXSkgPCAwICYmIE9iamVjdC5wcm90b3R5cGUucHJvcGVydHlJc0VudW1lcmFibGUuY2FsbChzLCBwW2ldKSlcclxuICAgICAgICAgICAgICAgIHRbcFtpXV0gPSBzW3BbaV1dO1xyXG4gICAgICAgIH1cclxuICAgIHJldHVybiB0O1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xyXG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcclxuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XHJcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xyXG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcGFyYW0ocGFyYW1JbmRleCwgZGVjb3JhdG9yKSB7XHJcbiAgICByZXR1cm4gZnVuY3Rpb24gKHRhcmdldCwga2V5KSB7IGRlY29yYXRvcih0YXJnZXQsIGtleSwgcGFyYW1JbmRleCk7IH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZXNEZWNvcmF0ZShjdG9yLCBkZXNjcmlwdG9ySW4sIGRlY29yYXRvcnMsIGNvbnRleHRJbiwgaW5pdGlhbGl6ZXJzLCBleHRyYUluaXRpYWxpemVycykge1xyXG4gICAgZnVuY3Rpb24gYWNjZXB0KGYpIHsgaWYgKGYgIT09IHZvaWQgMCAmJiB0eXBlb2YgZiAhPT0gXCJmdW5jdGlvblwiKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiRnVuY3Rpb24gZXhwZWN0ZWRcIik7IHJldHVybiBmOyB9XHJcbiAgICB2YXIga2luZCA9IGNvbnRleHRJbi5raW5kLCBrZXkgPSBraW5kID09PSBcImdldHRlclwiID8gXCJnZXRcIiA6IGtpbmQgPT09IFwic2V0dGVyXCIgPyBcInNldFwiIDogXCJ2YWx1ZVwiO1xyXG4gICAgdmFyIHRhcmdldCA9ICFkZXNjcmlwdG9ySW4gJiYgY3RvciA/IGNvbnRleHRJbltcInN0YXRpY1wiXSA/IGN0b3IgOiBjdG9yLnByb3RvdHlwZSA6IG51bGw7XHJcbiAgICB2YXIgZGVzY3JpcHRvciA9IGRlc2NyaXB0b3JJbiB8fCAodGFyZ2V0ID8gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGNvbnRleHRJbi5uYW1lKSA6IHt9KTtcclxuICAgIHZhciBfLCBkb25lID0gZmFsc2U7XHJcbiAgICBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xyXG4gICAgICAgIHZhciBjb250ZXh0ID0ge307XHJcbiAgICAgICAgZm9yICh2YXIgcCBpbiBjb250ZXh0SW4pIGNvbnRleHRbcF0gPSBwID09PSBcImFjY2Vzc1wiID8ge30gOiBjb250ZXh0SW5bcF07XHJcbiAgICAgICAgZm9yICh2YXIgcCBpbiBjb250ZXh0SW4uYWNjZXNzKSBjb250ZXh0LmFjY2Vzc1twXSA9IGNvbnRleHRJbi5hY2Nlc3NbcF07XHJcbiAgICAgICAgY29udGV4dC5hZGRJbml0aWFsaXplciA9IGZ1bmN0aW9uIChmKSB7IGlmIChkb25lKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IGFkZCBpbml0aWFsaXplcnMgYWZ0ZXIgZGVjb3JhdGlvbiBoYXMgY29tcGxldGVkXCIpOyBleHRyYUluaXRpYWxpemVycy5wdXNoKGFjY2VwdChmIHx8IG51bGwpKTsgfTtcclxuICAgICAgICB2YXIgcmVzdWx0ID0gKDAsIGRlY29yYXRvcnNbaV0pKGtpbmQgPT09IFwiYWNjZXNzb3JcIiA/IHsgZ2V0OiBkZXNjcmlwdG9yLmdldCwgc2V0OiBkZXNjcmlwdG9yLnNldCB9IDogZGVzY3JpcHRvcltrZXldLCBjb250ZXh0KTtcclxuICAgICAgICBpZiAoa2luZCA9PT0gXCJhY2Nlc3NvclwiKSB7XHJcbiAgICAgICAgICAgIGlmIChyZXN1bHQgPT09IHZvaWQgMCkgY29udGludWU7XHJcbiAgICAgICAgICAgIGlmIChyZXN1bHQgPT09IG51bGwgfHwgdHlwZW9mIHJlc3VsdCAhPT0gXCJvYmplY3RcIikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk9iamVjdCBleHBlY3RlZFwiKTtcclxuICAgICAgICAgICAgaWYgKF8gPSBhY2NlcHQocmVzdWx0LmdldCkpIGRlc2NyaXB0b3IuZ2V0ID0gXztcclxuICAgICAgICAgICAgaWYgKF8gPSBhY2NlcHQocmVzdWx0LnNldCkpIGRlc2NyaXB0b3Iuc2V0ID0gXztcclxuICAgICAgICAgICAgaWYgKF8gPSBhY2NlcHQocmVzdWx0LmluaXQpKSBpbml0aWFsaXplcnMucHVzaChfKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSBpZiAoXyA9IGFjY2VwdChyZXN1bHQpKSB7XHJcbiAgICAgICAgICAgIGlmIChraW5kID09PSBcImZpZWxkXCIpIGluaXRpYWxpemVycy5wdXNoKF8pO1xyXG4gICAgICAgICAgICBlbHNlIGRlc2NyaXB0b3Jba2V5XSA9IF87XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG4gICAgaWYgKHRhcmdldCkgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgY29udGV4dEluLm5hbWUsIGRlc2NyaXB0b3IpO1xyXG4gICAgZG9uZSA9IHRydWU7XHJcbn07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19ydW5Jbml0aWFsaXplcnModGhpc0FyZywgaW5pdGlhbGl6ZXJzLCB2YWx1ZSkge1xyXG4gICAgdmFyIHVzZVZhbHVlID0gYXJndW1lbnRzLmxlbmd0aCA+IDI7XHJcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGluaXRpYWxpemVycy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgIHZhbHVlID0gdXNlVmFsdWUgPyBpbml0aWFsaXplcnNbaV0uY2FsbCh0aGlzQXJnLCB2YWx1ZSkgOiBpbml0aWFsaXplcnNbaV0uY2FsbCh0aGlzQXJnKTtcclxuICAgIH1cclxuICAgIHJldHVybiB1c2VWYWx1ZSA/IHZhbHVlIDogdm9pZCAwO1xyXG59O1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcHJvcEtleSh4KSB7XHJcbiAgICByZXR1cm4gdHlwZW9mIHggPT09IFwic3ltYm9sXCIgPyB4IDogXCJcIi5jb25jYXQoeCk7XHJcbn07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19zZXRGdW5jdGlvbk5hbWUoZiwgbmFtZSwgcHJlZml4KSB7XHJcbiAgICBpZiAodHlwZW9mIG5hbWUgPT09IFwic3ltYm9sXCIpIG5hbWUgPSBuYW1lLmRlc2NyaXB0aW9uID8gXCJbXCIuY29uY2F0KG5hbWUuZGVzY3JpcHRpb24sIFwiXVwiKSA6IFwiXCI7XHJcbiAgICByZXR1cm4gT2JqZWN0LmRlZmluZVByb3BlcnR5KGYsIFwibmFtZVwiLCB7IGNvbmZpZ3VyYWJsZTogdHJ1ZSwgdmFsdWU6IHByZWZpeCA/IFwiXCIuY29uY2F0KHByZWZpeCwgXCIgXCIsIG5hbWUpIDogbmFtZSB9KTtcclxufTtcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX21ldGFkYXRhKG1ldGFkYXRhS2V5LCBtZXRhZGF0YVZhbHVlKSB7XHJcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QubWV0YWRhdGEgPT09IFwiZnVuY3Rpb25cIikgcmV0dXJuIFJlZmxlY3QubWV0YWRhdGEobWV0YWRhdGFLZXksIG1ldGFkYXRhVmFsdWUpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19hd2FpdGVyKHRoaXNBcmcsIF9hcmd1bWVudHMsIFAsIGdlbmVyYXRvcikge1xyXG4gICAgZnVuY3Rpb24gYWRvcHQodmFsdWUpIHsgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgUCA/IHZhbHVlIDogbmV3IFAoZnVuY3Rpb24gKHJlc29sdmUpIHsgcmVzb2x2ZSh2YWx1ZSk7IH0pOyB9XHJcbiAgICByZXR1cm4gbmV3IChQIHx8IChQID0gUHJvbWlzZSkpKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcclxuICAgICAgICBmdW5jdGlvbiBmdWxmaWxsZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3IubmV4dCh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XHJcbiAgICAgICAgZnVuY3Rpb24gcmVqZWN0ZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3JbXCJ0aHJvd1wiXSh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XHJcbiAgICAgICAgZnVuY3Rpb24gc3RlcChyZXN1bHQpIHsgcmVzdWx0LmRvbmUgPyByZXNvbHZlKHJlc3VsdC52YWx1ZSkgOiBhZG9wdChyZXN1bHQudmFsdWUpLnRoZW4oZnVsZmlsbGVkLCByZWplY3RlZCk7IH1cclxuICAgICAgICBzdGVwKChnZW5lcmF0b3IgPSBnZW5lcmF0b3IuYXBwbHkodGhpc0FyZywgX2FyZ3VtZW50cyB8fCBbXSkpLm5leHQoKSk7XHJcbiAgICB9KTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZ2VuZXJhdG9yKHRoaXNBcmcsIGJvZHkpIHtcclxuICAgIHZhciBfID0geyBsYWJlbDogMCwgc2VudDogZnVuY3Rpb24oKSB7IGlmICh0WzBdICYgMSkgdGhyb3cgdFsxXTsgcmV0dXJuIHRbMV07IH0sIHRyeXM6IFtdLCBvcHM6IFtdIH0sIGYsIHksIHQsIGc7XHJcbiAgICByZXR1cm4gZyA9IHsgbmV4dDogdmVyYigwKSwgXCJ0aHJvd1wiOiB2ZXJiKDEpLCBcInJldHVyblwiOiB2ZXJiKDIpIH0sIHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiAoZ1tTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzOyB9KSwgZztcclxuICAgIGZ1bmN0aW9uIHZlcmIobikgeyByZXR1cm4gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIHN0ZXAoW24sIHZdKTsgfTsgfVxyXG4gICAgZnVuY3Rpb24gc3RlcChvcCkge1xyXG4gICAgICAgIGlmIChmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiR2VuZXJhdG9yIGlzIGFscmVhZHkgZXhlY3V0aW5nLlwiKTtcclxuICAgICAgICB3aGlsZSAoZyAmJiAoZyA9IDAsIG9wWzBdICYmIChfID0gMCkpLCBfKSB0cnkge1xyXG4gICAgICAgICAgICBpZiAoZiA9IDEsIHkgJiYgKHQgPSBvcFswXSAmIDIgPyB5W1wicmV0dXJuXCJdIDogb3BbMF0gPyB5W1widGhyb3dcIl0gfHwgKCh0ID0geVtcInJldHVyblwiXSkgJiYgdC5jYWxsKHkpLCAwKSA6IHkubmV4dCkgJiYgISh0ID0gdC5jYWxsKHksIG9wWzFdKSkuZG9uZSkgcmV0dXJuIHQ7XHJcbiAgICAgICAgICAgIGlmICh5ID0gMCwgdCkgb3AgPSBbb3BbMF0gJiAyLCB0LnZhbHVlXTtcclxuICAgICAgICAgICAgc3dpdGNoIChvcFswXSkge1xyXG4gICAgICAgICAgICAgICAgY2FzZSAwOiBjYXNlIDE6IHQgPSBvcDsgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICBjYXNlIDQ6IF8ubGFiZWwrKzsgcmV0dXJuIHsgdmFsdWU6IG9wWzFdLCBkb25lOiBmYWxzZSB9O1xyXG4gICAgICAgICAgICAgICAgY2FzZSA1OiBfLmxhYmVsKys7IHkgPSBvcFsxXTsgb3AgPSBbMF07IGNvbnRpbnVlO1xyXG4gICAgICAgICAgICAgICAgY2FzZSA3OiBvcCA9IF8ub3BzLnBvcCgpOyBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xyXG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcclxuICAgICAgICAgICAgICAgICAgICBpZiAoISh0ID0gXy50cnlzLCB0ID0gdC5sZW5ndGggPiAwICYmIHRbdC5sZW5ndGggLSAxXSkgJiYgKG9wWzBdID09PSA2IHx8IG9wWzBdID09PSAyKSkgeyBfID0gMDsgY29udGludWU7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDMgJiYgKCF0IHx8IChvcFsxXSA+IHRbMF0gJiYgb3BbMV0gPCB0WzNdKSkpIHsgXy5sYWJlbCA9IG9wWzFdOyBicmVhazsgfVxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChvcFswXSA9PT0gNiAmJiBfLmxhYmVsIDwgdFsxXSkgeyBfLmxhYmVsID0gdFsxXTsgdCA9IG9wOyBicmVhazsgfVxyXG4gICAgICAgICAgICAgICAgICAgIGlmICh0ICYmIF8ubGFiZWwgPCB0WzJdKSB7IF8ubGFiZWwgPSB0WzJdOyBfLm9wcy5wdXNoKG9wKTsgYnJlYWs7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAodFsyXSkgXy5vcHMucG9wKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBvcCA9IGJvZHkuY2FsbCh0aGlzQXJnLCBfKTtcclxuICAgICAgICB9IGNhdGNoIChlKSB7IG9wID0gWzYsIGVdOyB5ID0gMDsgfSBmaW5hbGx5IHsgZiA9IHQgPSAwOyB9XHJcbiAgICAgICAgaWYgKG9wWzBdICYgNSkgdGhyb3cgb3BbMV07IHJldHVybiB7IHZhbHVlOiBvcFswXSA/IG9wWzFdIDogdm9pZCAwLCBkb25lOiB0cnVlIH07XHJcbiAgICB9XHJcbn1cclxuXHJcbmV4cG9ydCB2YXIgX19jcmVhdGVCaW5kaW5nID0gT2JqZWN0LmNyZWF0ZSA/IChmdW5jdGlvbihvLCBtLCBrLCBrMikge1xyXG4gICAgaWYgKGsyID09PSB1bmRlZmluZWQpIGsyID0gaztcclxuICAgIHZhciBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihtLCBrKTtcclxuICAgIGlmICghZGVzYyB8fCAoXCJnZXRcIiBpbiBkZXNjID8gIW0uX19lc01vZHVsZSA6IGRlc2Mud3JpdGFibGUgfHwgZGVzYy5jb25maWd1cmFibGUpKSB7XHJcbiAgICAgICAgZGVzYyA9IHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBmdW5jdGlvbigpIHsgcmV0dXJuIG1ba107IH0gfTtcclxuICAgIH1cclxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvLCBrMiwgZGVzYyk7XHJcbn0pIDogKGZ1bmN0aW9uKG8sIG0sIGssIGsyKSB7XHJcbiAgICBpZiAoazIgPT09IHVuZGVmaW5lZCkgazIgPSBrO1xyXG4gICAgb1trMl0gPSBtW2tdO1xyXG59KTtcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2V4cG9ydFN0YXIobSwgbykge1xyXG4gICAgZm9yICh2YXIgcCBpbiBtKSBpZiAocCAhPT0gXCJkZWZhdWx0XCIgJiYgIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvLCBwKSkgX19jcmVhdGVCaW5kaW5nKG8sIG0sIHApO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX192YWx1ZXMobykge1xyXG4gICAgdmFyIHMgPSB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgU3ltYm9sLml0ZXJhdG9yLCBtID0gcyAmJiBvW3NdLCBpID0gMDtcclxuICAgIGlmIChtKSByZXR1cm4gbS5jYWxsKG8pO1xyXG4gICAgaWYgKG8gJiYgdHlwZW9mIG8ubGVuZ3RoID09PSBcIm51bWJlclwiKSByZXR1cm4ge1xyXG4gICAgICAgIG5leHQ6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgaWYgKG8gJiYgaSA+PSBvLmxlbmd0aCkgbyA9IHZvaWQgMDtcclxuICAgICAgICAgICAgcmV0dXJuIHsgdmFsdWU6IG8gJiYgb1tpKytdLCBkb25lOiAhbyB9O1xyXG4gICAgICAgIH1cclxuICAgIH07XHJcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKHMgPyBcIk9iamVjdCBpcyBub3QgaXRlcmFibGUuXCIgOiBcIlN5bWJvbC5pdGVyYXRvciBpcyBub3QgZGVmaW5lZC5cIik7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3JlYWQobywgbikge1xyXG4gICAgdmFyIG0gPSB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgb1tTeW1ib2wuaXRlcmF0b3JdO1xyXG4gICAgaWYgKCFtKSByZXR1cm4gbztcclxuICAgIHZhciBpID0gbS5jYWxsKG8pLCByLCBhciA9IFtdLCBlO1xyXG4gICAgdHJ5IHtcclxuICAgICAgICB3aGlsZSAoKG4gPT09IHZvaWQgMCB8fCBuLS0gPiAwKSAmJiAhKHIgPSBpLm5leHQoKSkuZG9uZSkgYXIucHVzaChyLnZhbHVlKTtcclxuICAgIH1cclxuICAgIGNhdGNoIChlcnJvcikgeyBlID0geyBlcnJvcjogZXJyb3IgfTsgfVxyXG4gICAgZmluYWxseSB7XHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgaWYgKHIgJiYgIXIuZG9uZSAmJiAobSA9IGlbXCJyZXR1cm5cIl0pKSBtLmNhbGwoaSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGZpbmFsbHkgeyBpZiAoZSkgdGhyb3cgZS5lcnJvcjsgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIGFyO1xyXG59XHJcblxyXG4vKiogQGRlcHJlY2F0ZWQgKi9cclxuZXhwb3J0IGZ1bmN0aW9uIF9fc3ByZWFkKCkge1xyXG4gICAgZm9yICh2YXIgYXIgPSBbXSwgaSA9IDA7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspXHJcbiAgICAgICAgYXIgPSBhci5jb25jYXQoX19yZWFkKGFyZ3VtZW50c1tpXSkpO1xyXG4gICAgcmV0dXJuIGFyO1xyXG59XHJcblxyXG4vKiogQGRlcHJlY2F0ZWQgKi9cclxuZXhwb3J0IGZ1bmN0aW9uIF9fc3ByZWFkQXJyYXlzKCkge1xyXG4gICAgZm9yICh2YXIgcyA9IDAsIGkgPSAwLCBpbCA9IGFyZ3VtZW50cy5sZW5ndGg7IGkgPCBpbDsgaSsrKSBzICs9IGFyZ3VtZW50c1tpXS5sZW5ndGg7XHJcbiAgICBmb3IgKHZhciByID0gQXJyYXkocyksIGsgPSAwLCBpID0gMDsgaSA8IGlsOyBpKyspXHJcbiAgICAgICAgZm9yICh2YXIgYSA9IGFyZ3VtZW50c1tpXSwgaiA9IDAsIGpsID0gYS5sZW5ndGg7IGogPCBqbDsgaisrLCBrKyspXHJcbiAgICAgICAgICAgIHJba10gPSBhW2pdO1xyXG4gICAgcmV0dXJuIHI7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3NwcmVhZEFycmF5KHRvLCBmcm9tLCBwYWNrKSB7XHJcbiAgICBpZiAocGFjayB8fCBhcmd1bWVudHMubGVuZ3RoID09PSAyKSBmb3IgKHZhciBpID0gMCwgbCA9IGZyb20ubGVuZ3RoLCBhcjsgaSA8IGw7IGkrKykge1xyXG4gICAgICAgIGlmIChhciB8fCAhKGkgaW4gZnJvbSkpIHtcclxuICAgICAgICAgICAgaWYgKCFhcikgYXIgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChmcm9tLCAwLCBpKTtcclxuICAgICAgICAgICAgYXJbaV0gPSBmcm9tW2ldO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuICAgIHJldHVybiB0by5jb25jYXQoYXIgfHwgQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoZnJvbSkpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19hd2FpdCh2KSB7XHJcbiAgICByZXR1cm4gdGhpcyBpbnN0YW5jZW9mIF9fYXdhaXQgPyAodGhpcy52ID0gdiwgdGhpcykgOiBuZXcgX19hd2FpdCh2KTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXN5bmNHZW5lcmF0b3IodGhpc0FyZywgX2FyZ3VtZW50cywgZ2VuZXJhdG9yKSB7XHJcbiAgICBpZiAoIVN5bWJvbC5hc3luY0l0ZXJhdG9yKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiU3ltYm9sLmFzeW5jSXRlcmF0b3IgaXMgbm90IGRlZmluZWQuXCIpO1xyXG4gICAgdmFyIGcgPSBnZW5lcmF0b3IuYXBwbHkodGhpc0FyZywgX2FyZ3VtZW50cyB8fCBbXSksIGksIHEgPSBbXTtcclxuICAgIHJldHVybiBpID0ge30sIHZlcmIoXCJuZXh0XCIpLCB2ZXJiKFwidGhyb3dcIiksIHZlcmIoXCJyZXR1cm5cIiksIGlbU3ltYm9sLmFzeW5jSXRlcmF0b3JdID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpczsgfSwgaTtcclxuICAgIGZ1bmN0aW9uIHZlcmIobikgeyBpZiAoZ1tuXSkgaVtuXSA9IGZ1bmN0aW9uICh2KSB7IHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAoYSwgYikgeyBxLnB1c2goW24sIHYsIGEsIGJdKSA+IDEgfHwgcmVzdW1lKG4sIHYpOyB9KTsgfTsgfVxyXG4gICAgZnVuY3Rpb24gcmVzdW1lKG4sIHYpIHsgdHJ5IHsgc3RlcChnW25dKHYpKTsgfSBjYXRjaCAoZSkgeyBzZXR0bGUocVswXVszXSwgZSk7IH0gfVxyXG4gICAgZnVuY3Rpb24gc3RlcChyKSB7IHIudmFsdWUgaW5zdGFuY2VvZiBfX2F3YWl0ID8gUHJvbWlzZS5yZXNvbHZlKHIudmFsdWUudikudGhlbihmdWxmaWxsLCByZWplY3QpIDogc2V0dGxlKHFbMF1bMl0sIHIpOyB9XHJcbiAgICBmdW5jdGlvbiBmdWxmaWxsKHZhbHVlKSB7IHJlc3VtZShcIm5leHRcIiwgdmFsdWUpOyB9XHJcbiAgICBmdW5jdGlvbiByZWplY3QodmFsdWUpIHsgcmVzdW1lKFwidGhyb3dcIiwgdmFsdWUpOyB9XHJcbiAgICBmdW5jdGlvbiBzZXR0bGUoZiwgdikgeyBpZiAoZih2KSwgcS5zaGlmdCgpLCBxLmxlbmd0aCkgcmVzdW1lKHFbMF1bMF0sIHFbMF1bMV0pOyB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2FzeW5jRGVsZWdhdG9yKG8pIHtcclxuICAgIHZhciBpLCBwO1xyXG4gICAgcmV0dXJuIGkgPSB7fSwgdmVyYihcIm5leHRcIiksIHZlcmIoXCJ0aHJvd1wiLCBmdW5jdGlvbiAoZSkgeyB0aHJvdyBlOyB9KSwgdmVyYihcInJldHVyblwiKSwgaVtTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpczsgfSwgaTtcclxuICAgIGZ1bmN0aW9uIHZlcmIobiwgZikgeyBpW25dID0gb1tuXSA/IGZ1bmN0aW9uICh2KSB7IHJldHVybiAocCA9ICFwKSA/IHsgdmFsdWU6IF9fYXdhaXQob1tuXSh2KSksIGRvbmU6IGZhbHNlIH0gOiBmID8gZih2KSA6IHY7IH0gOiBmOyB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2FzeW5jVmFsdWVzKG8pIHtcclxuICAgIGlmICghU3ltYm9sLmFzeW5jSXRlcmF0b3IpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJTeW1ib2wuYXN5bmNJdGVyYXRvciBpcyBub3QgZGVmaW5lZC5cIik7XHJcbiAgICB2YXIgbSA9IG9bU3ltYm9sLmFzeW5jSXRlcmF0b3JdLCBpO1xyXG4gICAgcmV0dXJuIG0gPyBtLmNhbGwobykgOiAobyA9IHR5cGVvZiBfX3ZhbHVlcyA9PT0gXCJmdW5jdGlvblwiID8gX192YWx1ZXMobykgOiBvW1N5bWJvbC5pdGVyYXRvcl0oKSwgaSA9IHt9LCB2ZXJiKFwibmV4dFwiKSwgdmVyYihcInRocm93XCIpLCB2ZXJiKFwicmV0dXJuXCIpLCBpW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0sIGkpO1xyXG4gICAgZnVuY3Rpb24gdmVyYihuKSB7IGlbbl0gPSBvW25dICYmIGZ1bmN0aW9uICh2KSB7IHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7IHYgPSBvW25dKHYpLCBzZXR0bGUocmVzb2x2ZSwgcmVqZWN0LCB2LmRvbmUsIHYudmFsdWUpOyB9KTsgfTsgfVxyXG4gICAgZnVuY3Rpb24gc2V0dGxlKHJlc29sdmUsIHJlamVjdCwgZCwgdikgeyBQcm9taXNlLnJlc29sdmUodikudGhlbihmdW5jdGlvbih2KSB7IHJlc29sdmUoeyB2YWx1ZTogdiwgZG9uZTogZCB9KTsgfSwgcmVqZWN0KTsgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19tYWtlVGVtcGxhdGVPYmplY3QoY29va2VkLCByYXcpIHtcclxuICAgIGlmIChPYmplY3QuZGVmaW5lUHJvcGVydHkpIHsgT2JqZWN0LmRlZmluZVByb3BlcnR5KGNvb2tlZCwgXCJyYXdcIiwgeyB2YWx1ZTogcmF3IH0pOyB9IGVsc2UgeyBjb29rZWQucmF3ID0gcmF3OyB9XHJcbiAgICByZXR1cm4gY29va2VkO1xyXG59O1xyXG5cclxudmFyIF9fc2V0TW9kdWxlRGVmYXVsdCA9IE9iamVjdC5jcmVhdGUgPyAoZnVuY3Rpb24obywgdikge1xyXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG8sIFwiZGVmYXVsdFwiLCB7IGVudW1lcmFibGU6IHRydWUsIHZhbHVlOiB2IH0pO1xyXG59KSA6IGZ1bmN0aW9uKG8sIHYpIHtcclxuICAgIG9bXCJkZWZhdWx0XCJdID0gdjtcclxufTtcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2ltcG9ydFN0YXIobW9kKSB7XHJcbiAgICBpZiAobW9kICYmIG1vZC5fX2VzTW9kdWxlKSByZXR1cm4gbW9kO1xyXG4gICAgdmFyIHJlc3VsdCA9IHt9O1xyXG4gICAgaWYgKG1vZCAhPSBudWxsKSBmb3IgKHZhciBrIGluIG1vZCkgaWYgKGsgIT09IFwiZGVmYXVsdFwiICYmIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChtb2QsIGspKSBfX2NyZWF0ZUJpbmRpbmcocmVzdWx0LCBtb2QsIGspO1xyXG4gICAgX19zZXRNb2R1bGVEZWZhdWx0KHJlc3VsdCwgbW9kKTtcclxuICAgIHJldHVybiByZXN1bHQ7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2ltcG9ydERlZmF1bHQobW9kKSB7XHJcbiAgICByZXR1cm4gKG1vZCAmJiBtb2QuX19lc01vZHVsZSkgPyBtb2QgOiB7IGRlZmF1bHQ6IG1vZCB9O1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19jbGFzc1ByaXZhdGVGaWVsZEdldChyZWNlaXZlciwgc3RhdGUsIGtpbmQsIGYpIHtcclxuICAgIGlmIChraW5kID09PSBcImFcIiAmJiAhZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgYWNjZXNzb3Igd2FzIGRlZmluZWQgd2l0aG91dCBhIGdldHRlclwiKTtcclxuICAgIGlmICh0eXBlb2Ygc3RhdGUgPT09IFwiZnVuY3Rpb25cIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZiA6ICFzdGF0ZS5oYXMocmVjZWl2ZXIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHJlYWQgcHJpdmF0ZSBtZW1iZXIgZnJvbSBhbiBvYmplY3Qgd2hvc2UgY2xhc3MgZGlkIG5vdCBkZWNsYXJlIGl0XCIpO1xyXG4gICAgcmV0dXJuIGtpbmQgPT09IFwibVwiID8gZiA6IGtpbmQgPT09IFwiYVwiID8gZi5jYWxsKHJlY2VpdmVyKSA6IGYgPyBmLnZhbHVlIDogc3RhdGUuZ2V0KHJlY2VpdmVyKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fY2xhc3NQcml2YXRlRmllbGRTZXQocmVjZWl2ZXIsIHN0YXRlLCB2YWx1ZSwga2luZCwgZikge1xyXG4gICAgaWYgKGtpbmQgPT09IFwibVwiKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBtZXRob2QgaXMgbm90IHdyaXRhYmxlXCIpO1xyXG4gICAgaWYgKGtpbmQgPT09IFwiYVwiICYmICFmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBhY2Nlc3NvciB3YXMgZGVmaW5lZCB3aXRob3V0IGEgc2V0dGVyXCIpO1xyXG4gICAgaWYgKHR5cGVvZiBzdGF0ZSA9PT0gXCJmdW5jdGlvblwiID8gcmVjZWl2ZXIgIT09IHN0YXRlIHx8ICFmIDogIXN0YXRlLmhhcyhyZWNlaXZlcikpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3Qgd3JpdGUgcHJpdmF0ZSBtZW1iZXIgdG8gYW4gb2JqZWN0IHdob3NlIGNsYXNzIGRpZCBub3QgZGVjbGFyZSBpdFwiKTtcclxuICAgIHJldHVybiAoa2luZCA9PT0gXCJhXCIgPyBmLmNhbGwocmVjZWl2ZXIsIHZhbHVlKSA6IGYgPyBmLnZhbHVlID0gdmFsdWUgOiBzdGF0ZS5zZXQocmVjZWl2ZXIsIHZhbHVlKSksIHZhbHVlO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19jbGFzc1ByaXZhdGVGaWVsZEluKHN0YXRlLCByZWNlaXZlcikge1xyXG4gICAgaWYgKHJlY2VpdmVyID09PSBudWxsIHx8ICh0eXBlb2YgcmVjZWl2ZXIgIT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIHJlY2VpdmVyICE9PSBcImZ1bmN0aW9uXCIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHVzZSAnaW4nIG9wZXJhdG9yIG9uIG5vbi1vYmplY3RcIik7XHJcbiAgICByZXR1cm4gdHlwZW9mIHN0YXRlID09PSBcImZ1bmN0aW9uXCIgPyByZWNlaXZlciA9PT0gc3RhdGUgOiBzdGF0ZS5oYXMocmVjZWl2ZXIpO1xyXG59XHJcbiIsImV4cG9ydCBmdW5jdGlvbiBnZXRTdHlsZShlbGVtZW50LCBwcm9wZXJ0eSkge1xuICAgIHZhciBfYTtcbiAgICBjb25zdCB2aWV3ID0gKChfYSA9IGVsZW1lbnQub3duZXJEb2N1bWVudCkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLmRlZmF1bHRWaWV3KSB8fCB3aW5kb3c7XG4gICAgY29uc3Qgc3R5bGUgPSB2aWV3LmdldENvbXB1dGVkU3R5bGUoZWxlbWVudCk7XG4gICAgcmV0dXJuIChzdHlsZS5nZXRQcm9wZXJ0eVZhbHVlKHByb3BlcnR5KSB8fCBzdHlsZVtwcm9wZXJ0eV0pO1xufVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9aW5kZXguanMubWFwIiwiaW1wb3J0IHsgZ2V0U3R5bGUgfSBmcm9tICdAcGFjb3RlL2dldC1zdHlsZSc7XG5jb25zdCBQSVhFTFNfUEVSX0lOQ0ggPSA5NjtcbmNvbnN0IE1JTExJTUVUUkVTX1BFUl9JTkNIID0gMjUuNDtcbmNvbnN0IFBPSU5UU19QRVJfSU5DSCA9IDcyO1xuY29uc3QgUElDQVNfUEVSX0lOQ0ggPSA2O1xuZnVuY3Rpb24gZm9udFNpemUoZWxlbWVudCkge1xuICAgIHJldHVybiBlbGVtZW50XG4gICAgICAgID8gZ2V0U3R5bGUoZWxlbWVudCwgJ2ZvbnRTaXplJykgfHwgZm9udFNpemUoZWxlbWVudC5wYXJlbnRFbGVtZW50KVxuICAgICAgICA6IGdldFN0eWxlKHdpbmRvdy5kb2N1bWVudC5kb2N1bWVudEVsZW1lbnQsICdmb250U2l6ZScpO1xufVxuZnVuY3Rpb24gcGFyc2UocHJvdmlkZWRMZW5ndGgpIHtcbiAgICB2YXIgX2E7XG4gICAgY29uc3QgbGVuZ3RoID0gcHJvdmlkZWRMZW5ndGggfHwgJzAnO1xuICAgIGNvbnN0IHZhbHVlID0gcGFyc2VGbG9hdChsZW5ndGgpO1xuICAgIGNvbnN0IG1hdGNoID0gbGVuZ3RoLm1hdGNoKC9bXFxkLS5dKyhcXHcrKSQvKTtcbiAgICBjb25zdCB1bml0ID0gKF9hID0gbWF0Y2ggPT09IG51bGwgfHwgbWF0Y2ggPT09IHZvaWQgMCA/IHZvaWQgMCA6IG1hdGNoWzFdKSAhPT0gbnVsbCAmJiBfYSAhPT0gdm9pZCAwID8gX2EgOiAnJztcbiAgICByZXR1cm4gW3ZhbHVlLCB1bml0LnRvTG93ZXJDYXNlKCldO1xufVxuZXhwb3J0IGZ1bmN0aW9uIHBpeGVscyhsZW5ndGgsIGVsZW1lbnQpIHtcbiAgICB2YXIgX2EsIF9iO1xuICAgIGNvbnN0IHZpZXcgPSAoX2IgPSAoX2EgPSBlbGVtZW50ID09PSBudWxsIHx8IGVsZW1lbnQgPT09IHZvaWQgMCA/IHZvaWQgMCA6IGVsZW1lbnQub3duZXJEb2N1bWVudCkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLmRlZmF1bHRWaWV3KSAhPT0gbnVsbCAmJiBfYiAhPT0gdm9pZCAwID8gX2IgOiB3aW5kb3c7XG4gICAgY29uc3Qgcm9vdCA9IHZpZXcuZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50IHx8IHZpZXcuZG9jdW1lbnQuYm9keTtcbiAgICBjb25zdCBbdmFsdWUsIHVuaXRdID0gcGFyc2UobGVuZ3RoKTtcbiAgICBzd2l0Y2ggKHVuaXQpIHtcbiAgICAgICAgY2FzZSAncmVtJzpcbiAgICAgICAgICAgIHJldHVybiB2YWx1ZSAqIHBpeGVscyhmb250U2l6ZSh3aW5kb3cuZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50KSk7XG4gICAgICAgIGNhc2UgJ2VtJzpcbiAgICAgICAgICAgIHJldHVybiB2YWx1ZSAqIHBpeGVscyhmb250U2l6ZShlbGVtZW50KSwgZWxlbWVudCA9PT0gbnVsbCB8fCBlbGVtZW50ID09PSB2b2lkIDAgPyB2b2lkIDAgOiBlbGVtZW50LnBhcmVudEVsZW1lbnQpO1xuICAgICAgICBjYXNlICdpbic6XG4gICAgICAgICAgICByZXR1cm4gdmFsdWUgKiBQSVhFTFNfUEVSX0lOQ0g7XG4gICAgICAgIGNhc2UgJ3EnOlxuICAgICAgICAgICAgcmV0dXJuICh2YWx1ZSAqIFBJWEVMU19QRVJfSU5DSCkgLyBNSUxMSU1FVFJFU19QRVJfSU5DSCAvIDQ7XG4gICAgICAgIGNhc2UgJ21tJzpcbiAgICAgICAgICAgIHJldHVybiAodmFsdWUgKiBQSVhFTFNfUEVSX0lOQ0gpIC8gTUlMTElNRVRSRVNfUEVSX0lOQ0g7XG4gICAgICAgIGNhc2UgJ2NtJzpcbiAgICAgICAgICAgIHJldHVybiAodmFsdWUgKiBQSVhFTFNfUEVSX0lOQ0ggKiAxMCkgLyBNSUxMSU1FVFJFU19QRVJfSU5DSDtcbiAgICAgICAgY2FzZSAncHQnOlxuICAgICAgICAgICAgcmV0dXJuICh2YWx1ZSAqIFBJWEVMU19QRVJfSU5DSCkgLyBQT0lOVFNfUEVSX0lOQ0g7XG4gICAgICAgIGNhc2UgJ3BjJzpcbiAgICAgICAgICAgIHJldHVybiAodmFsdWUgKiBQSVhFTFNfUEVSX0lOQ0gpIC8gUElDQVNfUEVSX0lOQ0g7XG4gICAgICAgIGNhc2UgJ3ZoJzpcbiAgICAgICAgICAgIHJldHVybiAodmFsdWUgKiB2aWV3LmlubmVySGVpZ2h0IHx8IHJvb3QuY2xpZW50V2lkdGgpIC8gMTAwO1xuICAgICAgICBjYXNlICd2dyc6XG4gICAgICAgICAgICByZXR1cm4gKHZhbHVlICogdmlldy5pbm5lcldpZHRoIHx8IHJvb3QuY2xpZW50SGVpZ2h0KSAvIDEwMDtcbiAgICAgICAgY2FzZSAndm1pbic6XG4gICAgICAgICAgICByZXR1cm4gKCh2YWx1ZSAqXG4gICAgICAgICAgICAgICAgTWF0aC5taW4odmlldy5pbm5lcldpZHRoIHx8IHJvb3QuY2xpZW50V2lkdGgsIHZpZXcuaW5uZXJIZWlnaHQgfHwgcm9vdC5jbGllbnRIZWlnaHQpKSAvXG4gICAgICAgICAgICAgICAgMTAwKTtcbiAgICAgICAgY2FzZSAndm1heCc6XG4gICAgICAgICAgICByZXR1cm4gKCh2YWx1ZSAqXG4gICAgICAgICAgICAgICAgTWF0aC5tYXgodmlldy5pbm5lcldpZHRoIHx8IHJvb3QuY2xpZW50V2lkdGgsIHZpZXcuaW5uZXJIZWlnaHQgfHwgcm9vdC5jbGllbnRIZWlnaHQpKSAvXG4gICAgICAgICAgICAgICAgMTAwKTtcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9XG59XG4vLyMgc291cmNlTWFwcGluZ1VSTD1pbmRleC5qcy5tYXAiLCIvKipcbiAqIEZpbGU6IC9zcmMvdXRpbGl0aWVzL2ludGVyZmFjZXMudHMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gKiBBdXRob3I6IENhbWVyb24gUm9iaW5zb24gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAqIENvcHlyaWdodCAoYykgMjAyMyBDYW1lcm9uIFJvYmluc29uICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gKi9cbmltcG9ydCB7IHBpeGVscyB9IGZyb20gJ0BwYWNvdGUvcGl4ZWxzJ1xuXG5leHBvcnQgY2xhc3MgSFRNTFNpemluZyB7XG5cbiAgICBwcml2YXRlIF9zaXplVmFsdWU6IG51bWJlciA9IDA7XG4gICAgcHVibGljIGdldCBzaXplVmFsdWUoKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3NpemVWYWx1ZTtcbiAgICB9XG4gICAgcHVibGljIHNldCBzaXplVmFsdWUodmFsdWU6IG51bWJlcikge1xuICAgICAgICB0aGlzLl9zaXplVmFsdWUgPSB2YWx1ZTtcbiAgICB9XG4gICAgcHJpdmF0ZSB3aWR0aFNldDogYm9vbGVhbiA9IGZhbHNlO1xuICAgIHByaXZhdGUgc2l6ZVVuaXRzOiBzdHJpbmcgPSBcInB4XCI7XG4gICAgcHJpdmF0ZSBjb25zdHJ1Y3Rvcih2YWx1ZTogbnVtYmVyLCB1bml0czogc3RyaW5nKSB7XG4gICAgICAgIHRoaXMuc2l6ZVZhbHVlID0gdmFsdWU7XG4gICAgICAgIHRoaXMuc2l6ZVVuaXRzID0gdW5pdHM7XG4gICAgfVxuICAgIHB1YmxpYyBzZXRXaWR0aCh2YWx1ZTogbnVtYmVyKTogSFRNTFNpemluZyB7XG4gICAgICAgIHRoaXMud2lkdGhTZXQgPSB0cnVlO1xuICAgICAgICByZXR1cm4gbmV3IEhUTUxTaXppbmcodmFsdWUsIHRoaXMuc2l6ZVVuaXRzKTtcbiAgICB9XG4gICAgcHVibGljIHNldFVuaXRzKHVuaXRzOiBzdHJpbmcpOiBIVE1MU2l6aW5nIHtcbiAgICAgICAgcmV0dXJuIG5ldyBIVE1MU2l6aW5nKHRoaXMuc2l6ZVZhbHVlLCB1bml0cyk7XG4gICAgfVxuICAgIHB1YmxpYyB0b1N0cmluZygpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gYCR7dGhpcy5zaXplVmFsdWV9JHt0aGlzLnNpemVVbml0c31gO1xuICAgIH1cblxuICAgIGNvbnZlcnRUb1BYKHBhcmVudEVsZW1lbnQ6IEhUTUxFbGVtZW50KSB7XG4gICAgICAgIGlmKHRoaXMuc2l6ZVVuaXRzID09PSBcInB4XCIpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG5cbiAgICAgICAgc3dpdGNoKHRoaXMuc2l6ZVVuaXRzKSB7XG4gICAgICAgICAgICBjYXNlIFwiY21cIjpcbiAgICAgICAgICAgIGNhc2UgXCJtbVwiOlxuICAgICAgICAgICAgY2FzZSBcImluXCI6XG4gICAgICAgICAgICBjYXNlIFwicHRcIjpcbiAgICAgICAgICAgIGNhc2UgXCJwY1wiOlxuICAgICAgICAgICAgICAgIGxldCBhYnNVbml0c1Jlc3VsdCA9IHBpeGVscyhgJHt0aGlzLnRvU3RyaW5nKCl9YCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBIVE1MU2l6aW5nKGFic1VuaXRzUmVzdWx0LCBcInB4XCIpO1xuICAgICAgICAgICAgY2FzZSBcInZ3XCI6XG4gICAgICAgICAgICBjYXNlIFwidmhcIjpcbiAgICAgICAgICAgICAgICByZXR1cm4gaGFuZGxlVmlld3BvcnRTaXppbmcoKTtcbiAgICAgICAgICAgIGNhc2UgXCJlbVwiOlxuICAgICAgICAgICAgICAgIHJldHVybiBnZXRGb250U2l6ZUZyb21FbCgpO1xuICAgICAgICAgICAgY2FzZSBcImNoXCI6XG4gICAgICAgICAgICAgICAgbGV0IGNoID0gY3JlYXRlRWwoXCJwXCIsIHtcbiAgICAgICAgICAgICAgICAgICAgXCJhdHRyXCI6IHsgXCJzdHlsZVwiOiBcIndpZHRoOiAxY2g7XCIgfVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgcmV0dXJuIGdldFNpemVGcm9tU3R5bGVXaWR0aChjaCk7XG5cbiAgICAgICAgICAgIGNhc2UgXCJleFwiOlxuICAgICAgICAgICAgICAgIGxldCBleCA9IGNyZWF0ZUVsKFwicFwiLCB7XG4gICAgICAgICAgICAgICAgICAgIFwiYXR0clwiOiB7IFwic3R5bGVcIjogXCJ3aWR0aDogMWV4O1wiIH1cbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIHJldHVybiBnZXRTaXplRnJvbVN0eWxlV2lkdGgoZXgpO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gZ2V0U2l6ZUZyb21TdHlsZVdpZHRoKGVsOiBIVE1MUGFyYWdyYXBoRWxlbWVudCkge1xuXG4gICAgICAgICAgICBjb25zdCBERUZBVUxUX1NJWkUgPSAxNjtcbiAgICAgICAgICAgIGlmKHBhcmVudEVsZW1lbnQgPT09IG51bGwgfHxcbiAgICAgICAgICAgICAgICBwYXJlbnRFbGVtZW50ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgIHJldHVybiBuZXcgSFRNTFNpemluZyh0aGlzLnNpemVWYWx1ZSAqIERFRkFVTFRfU0laRSwgXCJweFwiKTtcbiAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHBhcmVudEVsZW1lbnQuYXBwZW5kQ2hpbGQoZWwpO1xuICAgICAgICAgICAgbGV0IGV4VG9QeFJlc3VsdCA9IHRoaXMuc2l6ZVZhbHVlICogZWwuY2xpZW50V2lkdGg7XG4gICAgICAgICAgICBpZihlbC5jbGllbnRXaWR0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIGV4VG9QeFJlc3VsdCA9IHRoaXMuc2l6ZVZhbHVlICogREVGQVVMVF9TSVpFO1xuICAgICAgICAgICAgfSBcblxuICAgICAgICAgICAgcGFyZW50RWxlbWVudC5yZW1vdmVDaGlsZChlbCk7XG4gICAgICAgICAgICByZXR1cm4gbmV3IEhUTUxTaXppbmcoZXhUb1B4UmVzdWx0LCBcInB4XCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gZ2V0Rm9udFNpemVGcm9tRWwoKSB7XG5cbiAgICAgICAgICAgIGNvbnN0IERFRkFVTFRfU0laRSA9IDE2O1xuICAgICAgICAgICAgbGV0IGZvbnRTaXplID0gREVGQVVMVF9TSVpFO1xuICAgICAgICAgICAgbGV0IGVtVG9QeFJlc3VsdCA9IGZvbnRTaXplICogdGhpcy5zaXplVmFsdWU7XG5cbiAgICAgICAgICAgIGlmKHBhcmVudEVsZW1lbnQgPT09IG51bGwgfHxcbiAgICAgICAgICAgICAgIHBhcmVudEVsZW1lbnQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgSFRNTFNpemluZyhlbVRvUHhSZXN1bHQsIFwicHhcIik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxldCBzaXppbmcgPSBIVE1MU2l6aW5nLnBhcnNlVG9TaXppbmcocGFyZW50RWxlbWVudC5nZXRDc3NQcm9wZXJ0eVZhbHVlKFwiZm9udC1zaXplXCIpKTtcbiAgICAgICAgICAgIGlmIChzaXppbmcgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBmb250U2l6ZSA9IHNpemluZy5zaXplVmFsdWU7XG4gICAgICAgICAgICAgICAgZW1Ub1B4UmVzdWx0ID0gZm9udFNpemUgKiB0aGlzLnNpemVWYWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIG5ldyBIVE1MU2l6aW5nKGVtVG9QeFJlc3VsdCwgXCJweFwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIGhhbmRsZVZpZXdwb3J0U2l6aW5nKCkge1xuXG4gICAgICAgICAgICBsZXQgc2NhbGUgPSB0aGlzLnNpemVWYWx1ZSAvIDEwMDtcbiAgICAgICAgICAgIGlmKHBhcmVudEVsZW1lbnQgPT09IG51bGwgfHwgcGFyZW50RWxlbWVudCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKFwiRm91bmQgdW5kZWZpbmVkIHJvb3QgZWxlbWVudC4gVXNpbmcgZGVmYXVsdCBjbGllbnQgc2l6ZS4gUmVzdWx0IG1heSBub3QgYXBwZWFyIGFzIGludGVuZGVkLlwiKTtcbiAgICAgICAgICAgICAgICBsZXQgZGVmYXVsdFNpemluZyA9IHNjYWxlICogMTIwMDtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEhUTUxTaXppbmcoZGVmYXVsdFNpemluZywgXCJweFwiKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbGV0IHZpZXdXaWR0aCA9IHBhcmVudEVsZW1lbnQuY2xpZW50V2lkdGg7XG4gICAgICAgICAgICBsZXQgdmlld0hlaWdodCA9IHBhcmVudEVsZW1lbnQuY2xpZW50SGVpZ2h0O1xuICAgICAgICAgICAgc3dpdGNoKHRoaXMuc2l6ZVVuaXRzKSB7XG4gICAgICAgICAgICAgICAgY2FzZSBcInZ3XCI6XG4gICAgICAgICAgICAgICAgICAgIGxldCB3VG9QeFJlc3VsdCA9IHNjYWxlICogdmlld1dpZHRoO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEhUTUxTaXppbmcod1RvUHhSZXN1bHQsIFwicHhcIik7XG4gICAgICAgICAgICAgICAgY2FzZSBcInZoXCI6XG4gICAgICAgICAgICAgICAgY2FzZSBcIiVcIjpcbiAgICAgICAgICAgICAgICAgICAgbGV0IGhUb1B4UmVzdWx0ID0gc2NhbGUgKiB2aWV3SGVpZ2h0O1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEhUTUxTaXppbmcoaFRvUHhSZXN1bHQsIFwicHhcIik7XG5cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBzdGF0aWMgY3JlYXRlKCk6IEhUTUxTaXppbmcge1xuICAgICAgICByZXR1cm4gbmV3IEhUTUxTaXppbmcoMCwgXCJweFwiKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgc3RhdGljIHBhcnNlVG9TaXppbmcoc2l6aW5nVGV4dDogc3RyaW5nKTogSFRNTFNpemluZyB8IG51bGwge1xuXG4gICAgICAgIGlmKHNpemluZ1RleHQgPT09IFwiXCIpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHVuaXREYXRhID0gSFRNTFNpemluZy5nZXRMZW5ndGhVbml0KHNpemluZ1RleHQpO1xuICAgICAgICBpZih1bml0RGF0YS5pc1ZhbGlkID09PSB0cnVlKSB7XG5cbiAgICAgICAgICAgIGxldCB1bml0czogc3RyaW5nID0gdW5pdERhdGEudW5pdFN0clxuICAgICAgICAgICAgbGV0IHNpemVUZXh0OiBzdHJpbmcgPSBzaXppbmdUZXh0LnJlcGxhY2UodW5pdHMsIFwiXCIpLnRyaW0oKTtcbiAgICAgICAgICAgIGxldCBzaXplOiBudW1iZXIgPSBwYXJzZUludChzaXplVGV4dCk7XG4gICAgICAgICAgICBpZihpc05hTihzaXplKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gSFRNTFNpemluZy5jcmVhdGUoKS5zZXRXaWR0aChzaXplKS5zZXRVbml0cyh1bml0cyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgcHVibGljIHN0YXRpYyAgZ2V0TGVuZ3RoVW5pdChsZW5ndGhTdHI6IHN0cmluZyk6IHsgaXNWYWxpZDogYm9vbGVhbiwgdW5pdFN0cjogc3RyaW5nIH0ge1xuXG4gICAgICAgIGxldCBsYXN0Q2hhciA9IGxlbmd0aFN0ci5zbGljZShsZW5ndGhTdHIubGVuZ3RoIC0gMSk7XG4gICAgICAgIGxldCBsYXN0VHdvQ2hhcnMgPSBsZW5ndGhTdHIuc2xpY2UobGVuZ3RoU3RyLmxlbmd0aCAtIDIpO1xuICAgIFxuICAgICAgICBsZXQgdW5pdFN0ciA9IFwiXCJcbiAgICAgICAgbGV0IGlzVmFsaWQgPSBmYWxzZTtcbiAgICAgICAgaWYobGFzdENoYXIgPT09IFwiJVwiKSB7XG4gICAgICAgICAgICB1bml0U3RyID0gbGFzdENoYXI7XG4gICAgICAgICAgICBpc1ZhbGlkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmKGxhc3RUd29DaGFycyA9PT0gXCJjbVwiIHx8XG4gICAgICAgICAgICAgICAgbGFzdFR3b0NoYXJzID09PSBcIm1tXCIgfHxcbiAgICAgICAgICAgICAgICBsYXN0VHdvQ2hhcnMgPT09IFwiaW5cIiB8fFxuICAgICAgICAgICAgICAgIGxhc3RUd29DaGFycyA9PT0gXCJweFwiIHx8XG4gICAgICAgICAgICAgICAgbGFzdFR3b0NoYXJzID09PSBcInB0XCIgfHxcbiAgICAgICAgICAgICAgICBsYXN0VHdvQ2hhcnMgPT09IFwicGNcIiB8fFxuICAgICAgICAgICAgICAgIGxhc3RUd29DaGFycyA9PT0gXCJlbVwiIHx8XG4gICAgICAgICAgICAgICAgbGFzdFR3b0NoYXJzID09PSBcImV4XCIgfHxcbiAgICAgICAgICAgICAgICBsYXN0VHdvQ2hhcnMgPT09IFwiY2hcIiB8fFxuICAgICAgICAgICAgICAgIGxhc3RUd29DaGFycyA9PT0gXCJ2d1wiIHx8XG4gICAgICAgICAgICAgICAgbGFzdFR3b0NoYXJzID09PSBcInZoXCIgKSB7XG4gICAgICAgICAgICB1bml0U3RyID0gbGFzdFR3b0NoYXJzO1xuICAgICAgICAgICAgaXNWYWxpZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICBcbiAgICAgICAgcmV0dXJuIHsgaXNWYWxpZDogaXNWYWxpZCwgdW5pdFN0cjogdW5pdFN0ciB9XG4gICAgfVxufVxuXG5jb25zdCBBTExfTU9VU0VfU1RBVEVTID0gW1xuICAgIFwidXBcIixcbiAgICBcImRvd25cIiwgXG5dIGFzIGNvbnN0O1xudHlwZSBNb3VzZVN0YXRlVHVwbGUgPSB0eXBlb2YgQUxMX01PVVNFX1NUQVRFUztcbmV4cG9ydCB0eXBlIE1vdXNlU3RhdGUgPSBNb3VzZVN0YXRlVHVwbGVbbnVtYmVyXTtcbmV4cG9ydCBsZXQgbW91c2VTdGF0ZTogTW91c2VTdGF0ZSA9IFwidXBcIjsgXG5hZGRFdmVudExpc3RlbmVyKFwibW91c2Vkb3duXCIsICgpID0+IHtcblx0bW91c2VTdGF0ZSA9IFwiZG93blwiXG59KVxuYWRkRXZlbnRMaXN0ZW5lcihcIm1vdXNldXBcIiwgKCkgPT4ge1xuXHRtb3VzZVN0YXRlID0gXCJ1cFwiXG59KVxuXG5leHBvcnQgaW50ZXJmYWNlIFN0YXJ0VGFnUmVnZXhNYXRjaCB7XG4gICAgZm91bmQ6IGJvb2xlYW47XG4gICAgc3RhcnRQb3NpdGlvbjogbnVtYmVyO1xuICAgIGVuZFBvc2l0aW9uOiBudW1iZXI7XG4gICAgbWF0Y2hMZW5ndGg6IG51bWJlcjtcbiAgICByZWdpb25UeXBlOiBSZWdpb25UeXBlO1xufVxuZXhwb3J0IGZ1bmN0aW9uIGRlZmF1bHRTdGFydFJlZ2lvbkRhdGEoKTogU3RhcnRUYWdSZWdleE1hdGNoIHtcblxuICAgIHJldHVybiB7XG4gICAgICAgIGZvdW5kOiBmYWxzZSxcbiAgICAgICAgc3RhcnRQb3NpdGlvbjogLTEsXG4gICAgICAgIGVuZFBvc2l0aW9uOiAtMSxcbiAgICAgICAgbWF0Y2hMZW5ndGg6IDAsXG4gICAgICAgIHJlZ2lvblR5cGU6IFwiQ09ERUJMT0NLXCJcbiAgICB9XG59XG5cbmNvbnN0IEFMTF9SRUdJT05fVFlQRVM9IFtcbiAgICBcIkNPREVCTE9DS1wiLFxuICAgIFwiT1JJR0lOQUxcIiwgXG4gICAgXCJQQURPQ1wiXG5dIGFzIGNvbnN0O1xudHlwZSBSZWdpb25UeXBlVHVwbGUgPSB0eXBlb2YgQUxMX1JFR0lPTl9UWVBFUztcbmV4cG9ydCB0eXBlIFJlZ2lvblR5cGUgPSBSZWdpb25UeXBlVHVwbGVbbnVtYmVyXTsiLCIvKlxuICogRmlsZW5hbWU6IG11bHRpLWNvbHVtbi1tYXJrZG93bi9zcmMvcmVnaW9uU2V0dGluZ3MudHNcbiAqIENyZWF0ZWQgRGF0ZTogVHVlc2RheSwgRmVicnVhcnkgMXN0IDIwMjIsIDEyOjIzOjUzIHBtXG4gKiBBdXRob3I6IENhbWVyb24gUm9iaW5zb25cbiAqIFxuICogQ29weXJpZ2h0IChjKSAyMDIyIENhbWVyb24gUm9iaW5zb25cbiAqL1xuXG5pbXBvcnQgeyBIVE1MU2l6aW5nIH0gZnJvbSBcIi4vdXRpbGl0aWVzL2ludGVyZmFjZXNcIlxuXG5leHBvcnQgZW51bSBCb3JkZXJPcHRpb24ge1xuICAgIGVuYWJsZWQsXG4gICAgb24sXG4gICAgdHJ1ZSxcbiAgICBkaXNhYmxlZCxcbiAgICBvZmYsXG4gICAgZmFsc2Vcbn1cblxuZXhwb3J0IGVudW0gU2hhZG93T3B0aW9uIHtcbiAgICBlbmFibGVkLFxuICAgIG9uLFxuICAgIHRydWUsXG4gICAgZGlzYWJsZWQsXG4gICAgb2ZmLFxuICAgIGZhbHNlXG59XG5cbmV4cG9ydCBlbnVtIFRhYmxlQWxpZ25PcHRpb24ge1xuICAgIGVuYWJsZWQsXG4gICAgb24sXG4gICAgdHJ1ZSxcbiAgICBkaXNhYmxlZCxcbiAgICBvZmYsXG4gICAgZmFsc2Vcbn1cblxuY29uc3QgQUxMX0xBWU9VVFMgPSBbXG4gICAgXCJzdGFuZGFyZFwiLFxuICAgIFwibGVmdFwiLCBcbiAgICBcImZpcnN0XCIsIFxuICAgIFwiY2VudGVyXCIsXG4gICAgXCJtaWRkbGVcIixcbiAgICBcInNlY29uZFwiLFxuICAgIFwicmlnaHRcIixcbiAgICBcInRoaXJkXCIsXG4gICAgXCJsYXN0XCJcbl0gYXMgY29uc3Q7XG50eXBlIENvbHVtbkxheW91dFR1cGxlID0gdHlwZW9mIEFMTF9MQVlPVVRTO1xuZXhwb3J0IHR5cGUgQ29sdW1uTGF5b3V0ID0gQ29sdW1uTGF5b3V0VHVwbGVbbnVtYmVyXTtcblxuZXhwb3J0IGZ1bmN0aW9uIGlzQ29sdW1uTGF5b3V0KHZhbHVlOiBzdHJpbmcpOiB2YWx1ZSBpcyBDb2x1bW5MYXlvdXQge1xuICByZXR1cm4gQUxMX0xBWU9VVFMuaW5jbHVkZXModmFsdWUudG9Mb3dlckNhc2UoKSBhcyBDb2x1bW5MYXlvdXQpXG59XG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVDb2x1bW5MYXlvdXQodmFsdWU6IHN0cmluZyB8IENvbHVtbkxheW91dCk6IENvbHVtbkxheW91dCB7XG4gICAgcmV0dXJuICh2YWx1ZS50b0xvd2VyQ2FzZSgpIGFzIENvbHVtbkxheW91dClcbn1cblxuY29uc3QgQUxMX1NJTkdMRV9DT0xVTU5fU0laRVMgPSBbXG4gICAgXCJzbWFsbFwiLFxuICAgIFwibWVkaXVtXCIsXG4gICAgXCJsYXJnZVwiLFxuICAgIFwiZnVsbFwiXG5dXG50eXBlIFNpbmdsZUNvbHVtblNpemVUdXBsZSA9IHR5cGVvZiBBTExfU0lOR0xFX0NPTFVNTl9TSVpFUztcbmV4cG9ydCB0eXBlIFNpbmdsZUNvbHVtblNpemUgPSBTaW5nbGVDb2x1bW5TaXplVHVwbGVbbnVtYmVyXTtcbmV4cG9ydCBmdW5jdGlvbiBpc1NpbmdsZUNvbHVtblNpemUodmFsdWU6IHN0cmluZyk6IHZhbHVlIGlzIFNpbmdsZUNvbHVtblNpemUge1xuICAgIHJldHVybiBBTExfU0lOR0xFX0NPTFVNTl9TSVpFUy5pbmNsdWRlcyh2YWx1ZS50b0xvd2VyQ2FzZSgpIGFzIFNpbmdsZUNvbHVtblNpemUpXG59XG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVTaW5nbGVDb2x1bW5TaXplKHZhbHVlOiBzdHJpbmcgfCBTaW5nbGVDb2x1bW5TaXplKTogU2luZ2xlQ29sdW1uU2l6ZSB7XG4gICAgcmV0dXJuICh2YWx1ZS50b0xvd2VyQ2FzZSgpIGFzIFNpbmdsZUNvbHVtblNpemUpXG59XG5cbmV4cG9ydCBlbnVtIENvbnRlbnRPdmVyZmxvd1R5cGUge1xuICAgIHNjcm9sbCxcbiAgICBoaWRkZW5cbn1cblxuZXhwb3J0IGVudW0gQWxpZ25tZW50VHlwZSB7XG4gICAgbGVmdCxcbiAgICBjZW50ZXIsXG4gICAgcmlnaHRcbn1cblxuZXhwb3J0IGVudW0gVGFibGVBbGlnbm1lbnQge1xuICAgIHVzZVNldHRpbmdzRGVmYXVsdCxcbiAgICBhbGlnbixcbiAgICBub0FsaWduXG59XG5cbmV4cG9ydCB0eXBlIE11bHRpQ29sdW1uU2V0dGluZ3MgPSB7XG4gICAgY29sdW1uSUQ6IHN0cmluZyxcbiAgICBudW1iZXJPZkNvbHVtbnM6IG51bWJlcixcbiAgICBkcmF3Qm9yZGVyOiBib29sZWFuW10sXG4gICAgZHJhd1NoYWRvdzogYm9vbGVhbixcbiAgICBhdXRvTGF5b3V0OiBib29sZWFuXG4gICAgY29sdW1uU2l6ZTogU2luZ2xlQ29sdW1uU2l6ZSB8IENvbHVtbkxheW91dCB8IEhUTUxTaXppbmdbXSxcbiAgICBjb2x1bW5Qb3NpdGlvbjogQ29sdW1uTGF5b3V0LFxuICAgIGNvbHVtblNwYWNpbmc6IHN0cmluZ1tdLFxuICAgIGNvbnRlbnRPdmVyZmxvdzogQ29udGVudE92ZXJmbG93VHlwZVtdLFxuICAgIGFsaWdubWVudDogQWxpZ25tZW50VHlwZVtdLFxuICAgIGNvbHVtbkhlaWdodDogSFRNTFNpemluZyB8IG51bGwsXG4gICAgZnVsbERvY1JlZmxvdzogYm9vbGVhbixcbiAgICBhbGlnblRhYmxlc1RvQWxpZ25tZW50OiBUYWJsZUFsaWdubWVudFxufVxuZXhwb3J0IGZ1bmN0aW9uIE1DU2V0dGluZ3NfaXNFcXVhbChzZXR0aW5nc0E6IE11bHRpQ29sdW1uU2V0dGluZ3MsIHNldHRpbmdzQjogTXVsdGlDb2x1bW5TZXR0aW5ncyk6IGJvb2xlYW4ge1xuXG4gICAgaWYoc2V0dGluZ3NBPy5jb2x1bW5JRCAhPT0gc2V0dGluZ3NCPy5jb2x1bW5JRCkge1xuICAgICAgICByZXR1cm4gZmFsc2VcbiAgICB9XG4gICAgaWYoc2V0dGluZ3NBPy5udW1iZXJPZkNvbHVtbnMgIT09IHNldHRpbmdzQj8ubnVtYmVyT2ZDb2x1bW5zKSB7XG4gICAgICAgIHJldHVybiBmYWxzZVxuICAgIH1cbiAgICBpZihKU09OLnN0cmluZ2lmeShzZXR0aW5nc0E/LmRyYXdCb3JkZXIpICE9PSBKU09OLnN0cmluZ2lmeShzZXR0aW5nc0I/LmRyYXdCb3JkZXIpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZVxuICAgIH1cbiAgICBpZihzZXR0aW5nc0E/LmRyYXdTaGFkb3cgIT09IHNldHRpbmdzQj8uZHJhd1NoYWRvdykge1xuICAgICAgICByZXR1cm4gZmFsc2VcbiAgICB9XG4gICAgaWYoc2V0dGluZ3NBPy5hdXRvTGF5b3V0ICE9PSBzZXR0aW5nc0I/LmF1dG9MYXlvdXQpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlXG4gICAgfVxuICAgIGlmKEpTT04uc3RyaW5naWZ5KHNldHRpbmdzQT8uY29sdW1uU2l6ZSkgIT09IEpTT04uc3RyaW5naWZ5KHNldHRpbmdzQj8uY29sdW1uU2l6ZSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlXG4gICAgfVxuICAgIGlmKHNldHRpbmdzQT8uY29sdW1uUG9zaXRpb24gIT09IHNldHRpbmdzQj8uY29sdW1uUG9zaXRpb24pIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlXG4gICAgfVxuICAgIGlmKEpTT04uc3RyaW5naWZ5KHNldHRpbmdzQT8uY29sdW1uU3BhY2luZykgIT09IEpTT04uc3RyaW5naWZ5KHNldHRpbmdzQj8uY29sdW1uU3BhY2luZykpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlXG4gICAgfVxuICAgIGlmKEpTT04uc3RyaW5naWZ5KHNldHRpbmdzQT8uY29udGVudE92ZXJmbG93KSAhPT0gSlNPTi5zdHJpbmdpZnkoc2V0dGluZ3NCPy5jb250ZW50T3ZlcmZsb3cpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZVxuICAgIH1cbiAgICBpZihKU09OLnN0cmluZ2lmeShzZXR0aW5nc0E/LmFsaWdubWVudCkgIT09IEpTT04uc3RyaW5naWZ5KHNldHRpbmdzQj8uYWxpZ25tZW50KSkge1xuICAgICAgICByZXR1cm4gZmFsc2VcbiAgICB9XG4gICAgaWYoc2V0dGluZ3NBPy5jb2x1bW5IZWlnaHQgIT09IHNldHRpbmdzQj8uY29sdW1uSGVpZ2h0KSB7XG4gICAgICAgIHJldHVybiBmYWxzZVxuICAgIH1cbiAgICBpZihzZXR0aW5nc0E/LmZ1bGxEb2NSZWZsb3cgIT09IHNldHRpbmdzQj8uZnVsbERvY1JlZmxvdykge1xuICAgICAgICByZXR1cm4gZmFsc2VcbiAgICB9XG4gICAgaWYoc2V0dGluZ3NBPy5hbGlnblRhYmxlc1RvQWxpZ25tZW50ICE9PSBzZXR0aW5nc0I/LmFsaWduVGFibGVzVG9BbGlnbm1lbnQpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlXG4gICAgfVxuICAgIHJldHVybiB0cnVlXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXREZWZhdWx0TXVsdGlDb2x1bW5TZXR0aW5ncygpOiBNdWx0aUNvbHVtblNldHRpbmdzIHtcblxuICAgIHJldHVybiB7XG4gICAgICAgIGNvbHVtbklEOiBcIlwiLFxuICAgICAgICBudW1iZXJPZkNvbHVtbnM6IDIsXG4gICAgICAgIGRyYXdCb3JkZXI6IFt0cnVlXSxcbiAgICAgICAgZHJhd1NoYWRvdzogdHJ1ZSxcbiAgICAgICAgYXV0b0xheW91dDogZmFsc2UsXG4gICAgICAgIGNvbHVtblNpemU6IFwic3RhbmRhcmRcIixcbiAgICAgICAgY29sdW1uUG9zaXRpb246IFwic3RhbmRhcmRcIixcbiAgICAgICAgY29sdW1uU3BhY2luZzogW1wiXCJdLFxuICAgICAgICBjb250ZW50T3ZlcmZsb3c6IFtDb250ZW50T3ZlcmZsb3dUeXBlLnNjcm9sbF0sXG4gICAgICAgIGFsaWdubWVudDogW0FsaWdubWVudFR5cGUubGVmdF0sXG4gICAgICAgIGNvbHVtbkhlaWdodDogbnVsbCxcbiAgICAgICAgZnVsbERvY1JlZmxvdzogZmFsc2UsXG4gICAgICAgIGFsaWduVGFibGVzVG9BbGlnbm1lbnQ6IFRhYmxlQWxpZ25tZW50LnVzZVNldHRpbmdzRGVmYXVsdFxuICAgIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNob3VsZERyYXdDb2x1bW5Cb3JkZXIoaW5kZXg6IG51bWJlciwgc2V0dGluZ3M6IE11bHRpQ29sdW1uU2V0dGluZ3MpOiBib29sZWFuIHtcblxuICAgIGlmKHNldHRpbmdzLmRyYXdCb3JkZXIubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBnZXRJbmRleGVkQ2xhbXBlZEFycmF5VmFsdWUoaW5kZXgsIHNldHRpbmdzLmRyYXdCb3JkZXIpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY29sdW1uT3ZlcmZsb3dTdGF0ZShpbmRleDogbnVtYmVyLCBzZXR0aW5nczogTXVsdGlDb2x1bW5TZXR0aW5ncyk6IENvbnRlbnRPdmVyZmxvd1R5cGUge1xuXG4gICAgaWYoc2V0dGluZ3MuY29udGVudE92ZXJmbG93Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgICByZXR1cm4gQ29udGVudE92ZXJmbG93VHlwZS5zY3JvbGxcbiAgICB9XG5cbiAgICByZXR1cm4gZ2V0SW5kZXhlZENsYW1wZWRBcnJheVZhbHVlKGluZGV4LCBzZXR0aW5ncy5jb250ZW50T3ZlcmZsb3cpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY29sdW1uQWxpZ25tZW50U3RhdGUoaW5kZXg6IG51bWJlciwgc2V0dGluZ3M6IE11bHRpQ29sdW1uU2V0dGluZ3MpOiBBbGlnbm1lbnRUeXBlIHtcblxuICAgIGlmKHNldHRpbmdzLmFsaWdubWVudC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmV0dXJuIEFsaWdubWVudFR5cGUubGVmdFxuICAgIH1cblxuICAgIHJldHVybiBnZXRJbmRleGVkQ2xhbXBlZEFycmF5VmFsdWUoaW5kZXgsIHNldHRpbmdzLmFsaWdubWVudClcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNvbHVtblNwYWNpbmdTdGF0ZShpbmRleDogbnVtYmVyLCBzZXR0aW5nczogTXVsdGlDb2x1bW5TZXR0aW5ncyk6IHN0cmluZyB7XG5cbiAgICBpZihzZXR0aW5ncy5jb2x1bW5TcGFjaW5nLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICByZXR1cm4gXCJcIjtcbiAgICB9XG5cbiAgICByZXR1cm4gYG1hcmdpbi1pbmxpbmU6ICR7Z2V0SW5kZXhlZENsYW1wZWRBcnJheVZhbHVlKGluZGV4LCBzZXR0aW5ncy5jb2x1bW5TcGFjaW5nKX07YDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEluZGV4ZWRDbGFtcGVkQXJyYXlWYWx1ZTxUPihpbmRleDogbnVtYmVyLCBhcnI6IFRbXSkge1xuXG4gICAgaWYoYXJyLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICB0aHJvdyhcIkVycm9yIGdldHRpbmcgdmFsdWUgZnJvbSBlbXB0eSBhcnJheS5cIilcbiAgICB9XG5cbiAgICBpZihpbmRleCA8IDApIHtcbiAgICAgICAgcmV0dXJuIGFyclswXTtcbiAgICB9XG5cbiAgICBpZihpbmRleCA8IGFyci5sZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIGFycltpbmRleF07XG4gICAgfVxuXG4gICAgcmV0dXJuIGFyci5sYXN0KCk7XG59IiwiLyoqXG4gKiBGaWxlOiAvc3JjL3V0aWxpdGllcy9zZXR0aW5nc1BhcnNlci50cyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gKiBDcmVhdGVkIERhdGU6IEZyaWRheSwgSnVuZSAzcmQgMjAyMiwgODoxNiBwbSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gKiBBdXRob3I6IENhbWVyb24gUm9iaW5zb24gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjIgQ2FtZXJvbiBSb2JpbnNvbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gKi9cblxuaW1wb3J0IHsgSFRNTFNpemluZyB9IGZyb20gXCJzcmMvdXRpbGl0aWVzL2ludGVyZmFjZXNcIjtcbmltcG9ydCB7IE11bHRpQ29sdW1uU2V0dGluZ3MsIENvbHVtbkxheW91dCwgQm9yZGVyT3B0aW9uLCBTaGFkb3dPcHRpb24sIGdldERlZmF1bHRNdWx0aUNvbHVtblNldHRpbmdzLCBTaW5nbGVDb2x1bW5TaXplLCBDb250ZW50T3ZlcmZsb3dUeXBlLCBBbGlnbm1lbnRUeXBlLCBpc0NvbHVtbkxheW91dCwgdmFsaWRhdGVDb2x1bW5MYXlvdXQsIFRhYmxlQWxpZ25PcHRpb24sIFRhYmxlQWxpZ25tZW50IH0gZnJvbSBcIi4uL3JlZ2lvblNldHRpbmdzXCI7XG5cbi8qKlxuICogSGVyZSB3ZSBkZWZpbmUgYWxsIG9mIHRoZSB2YWxpZCBzZXR0aW5ncyBzdHJpbmdzIHRoYXQgdGhlIHVzZXIgY2FuIGVudGVyIGZvciBlYWNoIHNldHRpbmcgdHlwZS5cbiAqIFRoZSBzdHJpbmdzIGFyZSB0aGVuIG1hcHBlZCB0d2ljZSwgZmlyc3QgdG8gYSB2YWxpZCByZWdleCBzdHJpbmcgdGhhdCBzZWFyY2hlcyBmb3IgdGhlIHNldHRpbmdcbiAqIG5hbWUsIGlnbm9yaW5nIGFsbCBleHRyYSBzcGFjZXMgYW5kIGxldHRlciBjYXNlLCBhbmQgdGhlbiBtYXBlZCB0byBhIFJlZ0V4IG9iamVjdCB0byBiZSB1c2VkIFxuICogd2hlbiBwYXJzaW5nLlxuICovXG5jb25zdCBDT0xfUE9TSVRJT05fT1BUSU9OX1NUUlM6IHN0cmluZ1tdID0gW1xuICAgIFwiY29sdW1uIHBvc2l0aW9uXCIsXG4gICAgXCJjb2wgcG9zaXRpb25cIixcbiAgICBcImNvbHVtbiBsb2NhdGlvblwiLFxuICAgIFwiY29sIGxvY2F0aW9uXCIsXG4gICAgXCJzaW5nbGUgY29sdW1uIGxvY2F0aW9uXCIsXG4gICAgXCJzaW5nbGUgY29sdW1uIHBvc2l0aW9uXCIsXG5dO1xuY29uc3QgQ09MX1BPU0lUSU9OX1JFR0VYX0FSUjogUmVnRXhwW10gPSBDT0xfUE9TSVRJT05fT1BUSU9OX1NUUlMubWFwKGNvbnZlcnRTdHJpbmdUb1NldHRpbmdzUmVnZXgpLm1hcCgodmFsdWUpID0+IHtcbiAgICByZXR1cm4gbmV3IFJlZ0V4cCh2YWx1ZSwgXCJpXCIpO1xufSk7XG5cbmNvbnN0IENPTF9TSVpFX09QVElPTl9TVFJTOiBzdHJpbmdbXSA9IFtcbiAgICBcImNvbHVtbiBzaXplXCIsXG4gICAgXCJjb2x1bW4gd2lkdGhcIixcbiAgICBcImNvbCBzaXplXCIsXG4gICAgXCJjb2wgd2lkdGhcIixcbiAgICBcInNpbmdsZSBjb2x1bW4gc2l6ZVwiLFxuICAgIFwic2luZ2xlIGNvbCBzaXplXCIsXG4gICAgXCJzaW5nbGUgY29sdW1uIHdpZHRoXCIsXG4gICAgXCJzaW5nbGUgY29sIHdpZHRoXCIsXG4gICAgXCJsYXJnZXN0IGNvbHVtblwiXG5dO1xuY29uc3QgQ09MX1NJWkVfT1BUSU9OX1JFR0VYX0FSUjogUmVnRXhwW10gPSBDT0xfU0laRV9PUFRJT05fU1RSUy5tYXAoY29udmVydFN0cmluZ1RvU2V0dGluZ3NSZWdleCkubWFwKCh2YWx1ZSkgPT4ge1xuICAgIHJldHVybiBuZXcgUmVnRXhwKHZhbHVlLCBcImlcIik7XG59KTtcblxuY29uc3QgTlVNQkVSX09GX0NPTFVNTlNfU1RSUyA9IFtcbiAgICBcIm51bWJlciBvZiBjb2x1bW5zXCIsXG4gICAgXCJudW0gb2YgY29sc1wiLFxuICAgIFwiY29sIGNvdW50XCIsXG4gICAgXCJjb2x1bW4gY291bnRcIlxuXVxuY29uc3QgTlVNQkVSX09GX0NPTFVNTlNfUkVHRVhfQVJSOiBSZWdFeHBbXSA9IE5VTUJFUl9PRl9DT0xVTU5TX1NUUlMubWFwKGNvbnZlcnRTdHJpbmdUb1NldHRpbmdzUmVnZXgpLm1hcCgodmFsdWUpID0+IHtcbiAgICByZXR1cm4gbmV3IFJlZ0V4cCh2YWx1ZSwgXCJpXCIpO1xufSk7XG5cbmNvbnN0IERSQVdfQk9SREVSX1NUUlMgPSBbXG4gICAgXCJib3JkZXJcIlxuXVxuY29uc3QgRFJBV19CT1JERVJfUkVHRVhfQVJSOiBSZWdFeHBbXSA9IERSQVdfQk9SREVSX1NUUlMubWFwKGNvbnZlcnRTdHJpbmdUb1NldHRpbmdzUmVnZXgpLm1hcCgodmFsdWUpID0+IHtcbiAgICByZXR1cm4gbmV3IFJlZ0V4cCh2YWx1ZSwgXCJpXCIpO1xufSk7XG5cbmNvbnN0IERSQVdfU0hBRE9XX1NUUlMgPSBbXG4gICAgXCJzaGFkb3dcIlxuXVxuY29uc3QgRFJBV19TSEFET1dfUkVHRVhfQVJSOiBSZWdFeHBbXSA9IERSQVdfU0hBRE9XX1NUUlMubWFwKGNvbnZlcnRTdHJpbmdUb1NldHRpbmdzUmVnZXgpLm1hcCgodmFsdWUpID0+IHtcbiAgICByZXR1cm4gbmV3IFJlZ0V4cCh2YWx1ZSwgXCJpXCIpO1xufSk7XG5cbmNvbnN0IEFVVE9fTEFZT1VUX1NFVFRJTkdfU1RSUyA9IFtcbiAgICBcImF1dG8gbGF5b3V0XCIsXG4gICAgXCJmbHVpZCBkaXZcIixcbiAgICBcImZsdWlkIGRpdnNcIixcbiAgICBcImZsdWlkIGNvbHVtbnNcIixcbiAgICBcImZsdWlkIGNvbHNcIixcbiAgICBcImZsdWlkIGNvbFwiXG5dXG5jb25zdCBBVVRPX0xBWU9VVF9SRUdFWF9BUlI6IFJlZ0V4cFtdID0gQVVUT19MQVlPVVRfU0VUVElOR19TVFJTLm1hcChjb252ZXJ0U3RyaW5nVG9TZXR0aW5nc1JlZ2V4KS5tYXAoKHZhbHVlKSA9PiB7XG4gICAgcmV0dXJuIG5ldyBSZWdFeHAodmFsdWUsIFwiaVwiKTtcbn0pO1xuXG5jb25zdCBDT0xVTU5fU1BBQ0lOR19SRUdFWF9BUlI6IFJlZ0V4cFtdID0gW1xuICAgIFwiY29sdW1uIHNwYWNpbmdcIixcbiAgICBcImNvbHVtbiBnYXBcIixcbiAgICBcImNvbHVtbiBzZXBcIlxuXS5tYXAoKHZhbHVlKSA9PiB7XG4gICAgcmV0dXJuIG5ldyBSZWdFeHAoY29udmVydFN0cmluZ1RvU2V0dGluZ3NSZWdleCh2YWx1ZSksIFwiaVwiKTtcbn0pO1xuXG5jb25zdCBDT0xVTU5fSEVJR0hUX1JFR0VYX0FSUjogUmVnRXhwW10gPSBbXG4gICAgXCJjb2x1bW4gaGVpZ2h0XCIsXG4gICAgXCJjb2wgaGVpZ2h0XCIsXG4gICAgXCJjb2x1bW4gbWF4IGhlaWdodFwiLFxuICAgIFwiY29sIG1heCBoZWlnaHRcIixcbiAgICBcIm1heCBjb2x1bW4gaGVpZ2h0XCIsXG4gICAgXCJtYXggY29sIGhlaWdodFwiXG5dLm1hcCgodmFsdWUpID0+IHtcbiAgICByZXR1cm4gbmV3IFJlZ0V4cChjb252ZXJ0U3RyaW5nVG9TZXR0aW5nc1JlZ2V4KHZhbHVlKSwgXCJpXCIpO1xufSk7XG5cbmNvbnN0IENPTlRFTlRfT1ZFUkZMT1dfUkVHRVhfQVJSOiBSZWdFeHBbXSA9IFtcbiAgICBcIm92ZXJmbG93XCIsXG4gICAgXCJjb250ZW50IG92ZXJmbG93XCJcbl0ubWFwKCh2YWx1ZSkgPT4ge1xuICAgIHJldHVybiBuZXcgUmVnRXhwKGNvbnZlcnRTdHJpbmdUb1NldHRpbmdzUmVnZXgodmFsdWUpLCBcImlcIilcbn0pO1xuXG5jb25zdCBBTElHTk1FTlRfUkVHRVhfQVJSOiBSZWdFeHBbXSA9IFtcbiAgICBcImFsaWdubWVudFwiLFxuICAgIFwiY29udGVudCBhbGlnbm1lbnRcIixcbiAgICBcImFsaWduXCIsXG4gICAgXCJjb250ZW50IGFsaWduXCIsXG4gICAgXCJhbGlnbiBjb250ZW50XCIsXG4gICAgXCJ0ZXh0IGFsaWduXCIsXG4gICAgXCJhbGlnbiB0ZXh0XCIsXG4gICAgXCJUZXh0IEFsaWdubWVudFwiXG5dLm1hcCgodmFsdWUpID0+IHtcbiAgICByZXR1cm4gbmV3IFJlZ0V4cChjb252ZXJ0U3RyaW5nVG9TZXR0aW5nc1JlZ2V4KHZhbHVlKSwgXCJpXCIpO1xufSk7XG5cbmNvbnN0IFRBQkxFX0FMSUdOTUVOVF9SRUdFWF9BUlI6IFJlZ0V4cFtdID0gW1xuICAgIFwiYWxpZ24gdGFibGVzIHRvIHRleHQgYWxpZ25tZW50XCJcbl0ubWFwKCh2YWx1ZSkgPT4ge1xuICAgIHJldHVybiBuZXcgUmVnRXhwKGNvbnZlcnRTdHJpbmdUb1NldHRpbmdzUmVnZXgodmFsdWUpLCBcImlcIik7XG59KTtcblxuLyoqXG4gKiBUaGlzIGZ1bmN0aW9uIHNlYXJjaGVzIHRoZSBzZXR0aW5ncyBzdHJpbmcgdGhyb3VnaCBlYWNoIHJlZ2V4IG9wdGlvbi4gSWYgb25lIG9mIHRoZSByZWdleFxuICogdmFsdWVzIG1hdGNoLCBpdCByZXR1cm5zIHRoZSBmaXJzdCBncm91cCBmb3VuZCBieSB0aGUgcmVnZXguIFRoaXMgaXMgZGVwZW5kZWQgb24gcHJvcGVyXG4gKiByZWdleCBmb3JtYXR0aW5nIHdoaWNoIGlzIGRvbmUgYnkgdGhlIGNvbnZlcnRTdHJpbmdUb1NldHRpbmdzUmVnZXggZnVuY3Rpb24gZGVmaW5lZCBiZWxvdy5cbiAqIFxuICogQHBhcmFtIHNldHRpbmdzU3RyaW5nIFRoZSB2YWx1ZSB0aGF0IG1heSBtYXRjaCBvbmUgb2YgdGhlIHNldHRpbmcgb3B0aW9ucy5cbiAqIEBwYXJhbSB2YWxpZFNldHRpbmdGb3JtYXRSZWdFeCBUaGUgc2V0dGluZ3Mgb3B0aW9ucyB0aHJvdWdoIHdoaWNoIHRvIGNoZWNrIGFsbCBvcHRpb25zLiBJZiBvbmUgb2YgdGhlc2UgcmVnZXggXG4gKiB2YWx1ZXMgbWF0Y2ggb24gdGhlIHN0cmluZyB3ZSBicmVhayBmcm9tIHRoZSBsb29wIHJldHVybmluZyB0aGUgZm91bmQgdmFsdWUuXG4gKiBcbiAqIEByZXR1cm5zIHRoZSB1c2VyIGVudGVyZWQgZGF0YSBpZiB0aGUgc2V0dGluZyBpcyBhIG1hdGNoLCBvciBudWxsIGlmIG5vbiBvZiB0aGUgb3B0aW9ucyBtYXRjaGVkLlxuICovXG5mdW5jdGlvbiBnZXRTZXR0aW5nc0RhdGFGcm9tS2V5cyhzZXR0aW5nc1N0cmluZzogc3RyaW5nLCB2YWxpZFNldHRpbmdGb3JtYXRSZWdFeDogUmVnRXhwW10pOiBzdHJpbmcgfCBudWxsIHtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdmFsaWRTZXR0aW5nRm9ybWF0UmVnRXgubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICBsZXQgcmVnZXhTZWFyY2hEYXRhID0gdmFsaWRTZXR0aW5nRm9ybWF0UmVnRXhbaV0uZXhlYyhzZXR0aW5nc1N0cmluZylcbiAgICAgICAgaWYocmVnZXhTZWFyY2hEYXRhICE9PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVnZXhTZWFyY2hEYXRhWzFdLnRyaW0oKVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZVNpbmdsZUNvbHVtblNldHRpbmdzKHNldHRpbmdzU3RyOiBzdHJpbmcsIG9yaWdpbmFsU2V0dGluZ3M6IE11bHRpQ29sdW1uU2V0dGluZ3MpOiBNdWx0aUNvbHVtblNldHRpbmdzIHtcblxuICAgIG9yaWdpbmFsU2V0dGluZ3MuY29sdW1uU2l6ZSA9IFwibWVkaXVtXCI7XG4gICAgbGV0IHNldHRpbmdzTGluZXMgPSBzZXR0aW5nc1N0ci5zcGxpdChcIlxcblwiKTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNldHRpbmdzTGluZXMubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICBsZXQgc2V0dGluZ3NMaW5lID0gc2V0dGluZ3NMaW5lc1tpXTtcbiAgICAgICAgbGV0IHNldHRpbmdzRGF0YSA9IGdldFNldHRpbmdzRGF0YUZyb21LZXlzKHNldHRpbmdzTGluZSwgQ09MX1BPU0lUSU9OX1JFR0VYX0FSUik7XG4gICAgICAgIGlmIChzZXR0aW5nc0RhdGEgIT09IG51bGwpIHtcblxuICAgICAgICAgICAgb3JpZ2luYWxTZXR0aW5ncy5jb2x1bW5Qb3NpdGlvbiA9IHBhcnNlRm9yU2luZ2xlQ29sdW1uTG9jYXRpb24oc2V0dGluZ3NEYXRhKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHNldHRpbmdzRGF0YSA9IGdldFNldHRpbmdzRGF0YUZyb21LZXlzKHNldHRpbmdzTGluZSwgQ09MX1NJWkVfT1BUSU9OX1JFR0VYX0FSUik7XG4gICAgICAgIGlmIChzZXR0aW5nc0RhdGEgIT09IG51bGwpIHtcblxuICAgICAgICAgICAgb3JpZ2luYWxTZXR0aW5ncy5jb2x1bW5TaXplID0gcGFyc2VGb3JTaW5nbGVDb2x1bW5TaXplKHNldHRpbmdzRGF0YSlcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBvcmlnaW5hbFNldHRpbmdzO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VDb2x1bW5TZXR0aW5ncyhzZXR0aW5nc1N0cjogc3RyaW5nKTogTXVsdGlDb2x1bW5TZXR0aW5ncyB7XG5cbiAgICBsZXQgcGFyc2VkU2V0dGluZ3MgPSBnZXREZWZhdWx0TXVsdGlDb2x1bW5TZXR0aW5ncygpO1xuXG4gICAgbGV0IHNldHRpbmdzTGluZXMgPSBzZXR0aW5nc1N0ci5zcGxpdChcIlxcblwiKTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2V0dGluZ3NMaW5lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBsZXQgc2V0dGluZ3NMaW5lID0gc2V0dGluZ3NMaW5lc1tpXTtcblxuICAgICAgICBjaGVja1NldHRpbmdJc1JlZ2lvbklEKHNldHRpbmdzTGluZSwgcGFyc2VkU2V0dGluZ3MpO1xuICAgICAgICBjaGVja1NldHRpbmdJc051bWJlck9mQ29sdW1ucyhzZXR0aW5nc0xpbmUsIHBhcnNlZFNldHRpbmdzKTtcbiAgICAgICAgY2hlY2tTZXR0aW5nRGVmaW5lc0NvbHVtblNpemUoc2V0dGluZ3NMaW5lLCBwYXJzZWRTZXR0aW5ncyk7XG4gICAgICAgIGNoZWNrU2V0dGluZ0lzRHJhd0JvcmRlcihzZXR0aW5nc0xpbmUsIHBhcnNlZFNldHRpbmdzKTtcbiAgICAgICAgY2hlY2tTZXR0aW5nSXNEcmF3U2hhZG93KHNldHRpbmdzTGluZSwgcGFyc2VkU2V0dGluZ3MpO1xuICAgICAgICBjaGVja1NldHRpbmdJc0F1dG9MYXlvdXQoc2V0dGluZ3NMaW5lLCBwYXJzZWRTZXR0aW5ncyk7XG4gICAgICAgIGNoZWNrU2V0dGluZ0lzQ29sdW1uU3BhY2luZyhzZXR0aW5nc0xpbmUsIHBhcnNlZFNldHRpbmdzKTtcbiAgICAgICAgY2hlY2tTZXR0aW5nSXNDb250ZW50T3ZlcmZsb3coc2V0dGluZ3NMaW5lLCBwYXJzZWRTZXR0aW5ncyk7XG4gICAgICAgIGNoZWNrU2V0dGluZ0lzQ29sdW1uQWxpZ25tZW50KHNldHRpbmdzTGluZSwgcGFyc2VkU2V0dGluZ3MpO1xuICAgICAgICBjaGVja1NldHRpbmdJc0NvbHVtbkhlaWdodChzZXR0aW5nc0xpbmUsIHBhcnNlZFNldHRpbmdzKTtcbiAgICAgICAgY2hlY2tTZXR0aW5nSXNUYWJsZUFsaWdubWVudChzZXR0aW5nc0xpbmUsIHBhcnNlZFNldHRpbmdzKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcGFyc2VkU2V0dGluZ3M7XG59XG5cbmZ1bmN0aW9uIGNoZWNrU2V0dGluZ0lzTnVtYmVyT2ZDb2x1bW5zKHNldHRpbmdzTGluZTogc3RyaW5nLCBwYXJzZWRTZXR0aW5nczogTXVsdGlDb2x1bW5TZXR0aW5ncykge1xuXG4gICAgbGV0IHNldHRpbmdzRGF0YSA9IGdldFNldHRpbmdzRGF0YUZyb21LZXlzKHNldHRpbmdzTGluZSwgTlVNQkVSX09GX0NPTFVNTlNfUkVHRVhfQVJSKTtcbiAgICBpZiAoc2V0dGluZ3NEYXRhID09PSBudWxsKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBsZXQgc2V0dGluZ1ZhbHVlcyA9IHBhcnNlRm9yTXVsdGlTZXR0aW5ncyhzZXR0aW5nc0RhdGEpO1xuICAgIHNldHRpbmdzRGF0YSA9IHNldHRpbmdWYWx1ZXNbMF07XG5cbiAgICBsZXQgbnVtT2ZDb2xzID0gcGFyc2VJbnQoc2V0dGluZ3NEYXRhKTtcbiAgICBpZiAoTnVtYmVyLmlzTmFOKG51bU9mQ29scykgPT09IGZhbHNlKSB7XG4gICAgICAgIGlmIChudW1PZkNvbHMgPj0gMSkge1xuICAgICAgICAgICAgcGFyc2VkU2V0dGluZ3MubnVtYmVyT2ZDb2x1bW5zID0gbnVtT2ZDb2xzO1xuICAgICAgICB9XG4gICAgfVxufVxuXG5mdW5jdGlvbiBjaGVja1NldHRpbmdJc1JlZ2lvbklEKHNldHRpbmdzTGluZTogc3RyaW5nLCBwYXJzZWRTZXR0aW5nczogTXVsdGlDb2x1bW5TZXR0aW5ncykge1xuICAgIGxldCBzZXR0aW5nc0RhdGEgPSBnZXRTZXR0aW5nc0RhdGFGcm9tS2V5cyhzZXR0aW5nc0xpbmUsIENPREVCTE9DS19SRUdJT05fSURfUkVHRVhfQVJSKTtcbiAgICBpZiAoc2V0dGluZ3NEYXRhID09PSBudWxsKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBwYXJzZWRTZXR0aW5ncy5jb2x1bW5JRCA9IHNldHRpbmdzRGF0YTtcbn1cblxuZnVuY3Rpb24gY2hlY2tTZXR0aW5nRGVmaW5lc0NvbHVtblNpemUoc2V0dGluZ3NMaW5lOiBzdHJpbmcsIHBhcnNlZFNldHRpbmdzOiBNdWx0aUNvbHVtblNldHRpbmdzKSB7XG5cbiAgICBsZXQgc2V0dGluZ3NEYXRhID0gZ2V0U2V0dGluZ3NEYXRhRnJvbUtleXMoc2V0dGluZ3NMaW5lLCBDT0xfU0laRV9PUFRJT05fUkVHRVhfQVJSKTtcbiAgICBpZiAoc2V0dGluZ3NEYXRhID09PSBudWxsKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBsZXQgc2V0dGluZ1ZhbHVlcyA9IHBhcnNlRm9yTXVsdGlTZXR0aW5ncyhzZXR0aW5nc0RhdGEpO1xuICAgIGlmKHNldHRpbmdWYWx1ZXMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgIC8vIElmIHRoZXJlIGlzIG9ubHkgMSBpdGVtIHdlIGF0dGVtcHQgdG8gcGFyc2Ugb3V0IGEgbGF5b3V0IHR5cGUuIElmIHdlIGdldCBhIHZhbGlkIGl0ZW0gd2UgXG4gICAgICAgIC8vIHJldHVybiBoZXJlLlxuICAgICAgICBpZiAoaXNDb2x1bW5MYXlvdXQoc2V0dGluZ1ZhbHVlc1swXSkpIHtcbiAgICAgICAgICAgIHBhcnNlZFNldHRpbmdzLmNvbHVtblNpemUgPSB2YWxpZGF0ZUNvbHVtbkxheW91dChzZXR0aW5nVmFsdWVzWzBdKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGxldCB3aWR0aHM6IEhUTUxTaXppbmdbXSA9IFtdXG4gICAgZm9yKGxldCBzZXR0aW5nIG9mIHNldHRpbmdWYWx1ZXMpIHtcblxuICAgICAgICBsZXQgcGFyc2VkID0gSFRNTFNpemluZy5wYXJzZVRvU2l6aW5nKHNldHRpbmcudHJpbSgpKTtcbiAgICAgICAgaWYocGFyc2VkICE9PSBudWxsKSB7XG4gICAgICAgICAgICB3aWR0aHMucHVzaChwYXJzZWQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gSWYgbm9uZSBhcmUgcGFyc2VkIHByb3Blcmx5IHRvIGEgd2lkdGggdGhlbiB3ZSByZXR1cm4gYSBkZWZhdWx0LlxuICAgIGlmKHdpZHRocy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgY29uc29sZS53YXJuKFwiRXJyb3IgcGFyc2luZyBjb2x1bW4gbGF5b3V0IG9yIHdpZHRoLCBkZWZhdWx0aW5nIHRvIHN0YW5kYXJkIGxheW91dC5cIilcbiAgICAgICAgcGFyc2VkU2V0dGluZ3MuY29sdW1uU2l6ZSA9IFwic3RhbmRhcmRcIjtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIElmIHdlIHBhcnNlZCBzb21lIGxlbmd0aHMgYW5kIHNvbWUgZGlkIG5vdCBwYXJzZSBwcm9wZXJseSwgdGhlIHVzZXIgaGFzIGVpdGhlclxuICAgIC8vIHBvb3JseSBkZWZpbmVkIHRoZWlyIHNldHRpbmdzIG9yIGlzIGF0dGVtcHRpbmcgdG8gYnJlYWsgdXMuIFRha2UgdGhlIGZpcnN0IHZhbGlkIG9wdGlvblxuICAgIC8vIGJldHdlZW4gdGhlIHR3byBhcnJheXMuXG4gICAgaWYod2lkdGhzLmxlbmd0aCAhPT0gc2V0dGluZ1ZhbHVlcy5sZW5ndGgpIHtcblxuICAgICAgICBmb3IobGV0IHNldHRpbmcgb2Ygc2V0dGluZ1ZhbHVlcykge1xuXG4gICAgICAgICAgICBsZXQgdW5pdERhdGEgPSBIVE1MU2l6aW5nLmdldExlbmd0aFVuaXQoc2V0dGluZyk7XG4gICAgICAgICAgICBpZih1bml0RGF0YS5pc1ZhbGlkID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgcGFyc2VkU2V0dGluZ3MuY29sdW1uU2l6ZSA9IHdpZHRocztcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChpc0NvbHVtbkxheW91dChzZXR0aW5nVmFsdWVzWzBdKSkge1xuICAgICAgICAgICAgICAgIHBhcnNlZFNldHRpbmdzLmNvbHVtblNpemUgPSB2YWxpZGF0ZUNvbHVtbkxheW91dChzZXR0aW5nVmFsdWVzWzBdKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwYXJzZWRTZXR0aW5ncy5jb2x1bW5TaXplID0gd2lkdGhzO1xufVxuXG5mdW5jdGlvbiBjaGVja1NldHRpbmdJc0RyYXdCb3JkZXIoc2V0dGluZ3NMaW5lOiBzdHJpbmcsIHBhcnNlZFNldHRpbmdzOiBNdWx0aUNvbHVtblNldHRpbmdzKSB7XG5cbiAgICBsZXQgc2V0dGluZ3NEYXRhID0gZ2V0U2V0dGluZ3NEYXRhRnJvbUtleXMoc2V0dGluZ3NMaW5lLCBEUkFXX0JPUkRFUl9SRUdFWF9BUlIpO1xuICAgIGlmIChzZXR0aW5nc0RhdGEgPT09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGxldCBib3JkZXJzOiBib29sZWFuW10gPSBbXVxuICAgIGxldCBzZXR0aW5nVmFsdWVzID0gcGFyc2VGb3JNdWx0aVNldHRpbmdzKHNldHRpbmdzRGF0YSk7XG4gICAgZm9yKGxldCBzZXR0aW5nc0RhdGEgb2Ygc2V0dGluZ1ZhbHVlcykge1xuXG4gICAgICAgIGxldCBib3JkZXJTdGF0ZSA9IHRydWU7XG4gICAgICAgIGxldCBpc0JvcmRlckRyYXduOiBCb3JkZXJPcHRpb24gPSAoPGFueT5Cb3JkZXJPcHRpb24pW3NldHRpbmdzRGF0YV07XG4gICAgICAgIGlmIChpc0JvcmRlckRyYXduICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHN3aXRjaCAoaXNCb3JkZXJEcmF3bikge1xuICAgICAgICAgICAgICAgIGNhc2UgKEJvcmRlck9wdGlvbi5kaXNhYmxlZCk6XG4gICAgICAgICAgICAgICAgY2FzZSAoQm9yZGVyT3B0aW9uLm9mZik6XG4gICAgICAgICAgICAgICAgY2FzZSAoQm9yZGVyT3B0aW9uLmZhbHNlKTpcbiAgICAgICAgICAgICAgICAgICAgYm9yZGVyU3RhdGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIGJvcmRlcnMucHVzaChib3JkZXJTdGF0ZSk7XG4gICAgfVxuXG4gICAgcGFyc2VkU2V0dGluZ3MuZHJhd0JvcmRlciA9IGJvcmRlcnM7XG59XG5cbmZ1bmN0aW9uIGNoZWNrU2V0dGluZ0lzRHJhd1NoYWRvdyhzZXR0aW5nc0xpbmU6IHN0cmluZywgcGFyc2VkU2V0dGluZ3M6IE11bHRpQ29sdW1uU2V0dGluZ3MpIHtcblxuICAgIGxldCBzZXR0aW5nc0RhdGEgPSBnZXRTZXR0aW5nc0RhdGFGcm9tS2V5cyhzZXR0aW5nc0xpbmUsIERSQVdfU0hBRE9XX1JFR0VYX0FSUik7XG4gICAgaWYgKHNldHRpbmdzRGF0YSA9PT0gbnVsbCkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgbGV0IHNldHRpbmdWYWx1ZXMgPSBwYXJzZUZvck11bHRpU2V0dGluZ3Moc2V0dGluZ3NEYXRhKTtcbiAgICBzZXR0aW5nc0RhdGEgPSBzZXR0aW5nVmFsdWVzWzBdO1xuXG4gICAgbGV0IGlzU2hhZG93RHJhd246IFNoYWRvd09wdGlvbiA9ICg8YW55PlNoYWRvd09wdGlvbilbc2V0dGluZ3NEYXRhXTtcbiAgICBpZiAoaXNTaGFkb3dEcmF3biAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHN3aXRjaCAoaXNTaGFkb3dEcmF3bikge1xuICAgICAgICAgICAgY2FzZSAoU2hhZG93T3B0aW9uLmRpc2FibGVkKTpcbiAgICAgICAgICAgIGNhc2UgKFNoYWRvd09wdGlvbi5vZmYpOlxuICAgICAgICAgICAgY2FzZSAoU2hhZG93T3B0aW9uLmZhbHNlKTpcbiAgICAgICAgICAgICAgICBwYXJzZWRTZXR0aW5ncy5kcmF3U2hhZG93ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIGNoZWNrU2V0dGluZ0lzQXV0b0xheW91dChzZXR0aW5nc0xpbmU6IHN0cmluZywgcGFyc2VkU2V0dGluZ3M6IE11bHRpQ29sdW1uU2V0dGluZ3MpIHtcbiAgICBcbiAgICBsZXQgc2V0dGluZ3NEYXRhID0gZ2V0U2V0dGluZ3NEYXRhRnJvbUtleXMoc2V0dGluZ3NMaW5lLCBBVVRPX0xBWU9VVF9SRUdFWF9BUlIpO1xuICAgIGlmIChzZXR0aW5nc0RhdGEgPT09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGxldCBzZXR0aW5nVmFsdWVzID0gcGFyc2VGb3JNdWx0aVNldHRpbmdzKHNldHRpbmdzRGF0YSk7XG4gICAgc2V0dGluZ3NEYXRhID0gc2V0dGluZ1ZhbHVlc1swXTtcblxuXG4gICAgaWYgKHNldHRpbmdzRGF0YSA9PT0gXCJmYWxzZVwiIHx8IFxuICAgICAgICBzZXR0aW5nc0RhdGEgPT09IFwib2ZmXCIgICAgICkge1xuXG4gICAgICAgIHBhcnNlZFNldHRpbmdzLmF1dG9MYXlvdXQgPSBmYWxzZTtcbiAgICB9XG4gICAgcGFyc2VkU2V0dGluZ3MuYXV0b0xheW91dCA9IHRydWU7XG59XG5cbmZ1bmN0aW9uIGNoZWNrU2V0dGluZ0lzQ29sdW1uU3BhY2luZyhzZXR0aW5nc0xpbmU6IHN0cmluZywgcGFyc2VkU2V0dGluZ3M6IE11bHRpQ29sdW1uU2V0dGluZ3MpIHtcbiAgICBcbiAgICBsZXQgc2V0dGluZ3NEYXRhID0gZ2V0U2V0dGluZ3NEYXRhRnJvbUtleXMoc2V0dGluZ3NMaW5lLCBDT0xVTU5fU1BBQ0lOR19SRUdFWF9BUlIpO1xuICAgIGlmIChzZXR0aW5nc0RhdGEgPT09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuXG4gICAgbGV0IHNwYWNpbmdzOiBzdHJpbmdbXSA9IFtdXG5cbiAgICBsZXQgc2V0dGluZ1ZhbHVlcyA9IHBhcnNlRm9yTXVsdGlTZXR0aW5ncyhzZXR0aW5nc0RhdGEpO1xuICAgIGZvcihsZXQgc2V0dGluZ3NEYXRhIG9mIHNldHRpbmdWYWx1ZXMpIHtcbiAgICAgICAgXG4gICAgICAgIGxldCBwYXJzZWQgPSBIVE1MU2l6aW5nLnBhcnNlVG9TaXppbmcoc2V0dGluZ3NEYXRhLnRyaW0oKSk7XG4gICAgICAgIGxldCBzcGFjaW5nU3RyID0gXCJcIjtcbiAgICAgICAgaWYgKHBhcnNlZCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgc3BhY2luZ1N0ciA9IHBhcnNlZC50b1N0cmluZygpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgIFxuICAgICAgICAgICAgbGV0IG5vVW5pdHNOdW0gPSBwYXJzZUludChzZXR0aW5nc0RhdGEudHJpbSgpKTtcbiAgICAgICAgICAgIGlmIChpc05hTihub1VuaXRzTnVtKSA9PT0gZmFsc2UpIHtcbiAgICBcbiAgICAgICAgICAgICAgICBzcGFjaW5nU3RyID0gYCR7bm9Vbml0c051bX1wdGA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgc3BhY2luZ3MucHVzaChzcGFjaW5nU3RyKTtcbiAgICB9XG5cbiAgICBwYXJzZWRTZXR0aW5ncy5jb2x1bW5TcGFjaW5nID0gc3BhY2luZ3M7XG59XG5cbmZ1bmN0aW9uIGNoZWNrU2V0dGluZ0lzQ29udGVudE92ZXJmbG93KHNldHRpbmdzTGluZTogc3RyaW5nLCBwYXJzZWRTZXR0aW5nczogTXVsdGlDb2x1bW5TZXR0aW5ncykge1xuICAgIFxuICAgIGxldCBzZXR0aW5nc0RhdGEgPSBnZXRTZXR0aW5nc0RhdGFGcm9tS2V5cyhzZXR0aW5nc0xpbmUsIENPTlRFTlRfT1ZFUkZMT1dfUkVHRVhfQVJSKTtcbiAgICBpZiAoc2V0dGluZ3NEYXRhID09PSBudWxsKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBsZXQgb3ZlcmZsb3dTdGF0ZXM6IENvbnRlbnRPdmVyZmxvd1R5cGVbXSA9IFtdXG4gICAgbGV0IHNldHRpbmdWYWx1ZXMgPSBwYXJzZUZvck11bHRpU2V0dGluZ3Moc2V0dGluZ3NEYXRhKTtcblxuICAgIGZvcihsZXQgc2V0dGluZ3NEYXRhIG9mIHNldHRpbmdWYWx1ZXMpIHtcbiAgICAgICAgXG4gICAgICAgIGxldCBvdmVyZmxvd1R5cGUgPSBDb250ZW50T3ZlcmZsb3dUeXBlLnNjcm9sbDtcbiAgICAgICAgc2V0dGluZ3NEYXRhID0gc2V0dGluZ3NEYXRhLnRvTG93ZXJDYXNlKCkudHJpbSgpO1xuICAgICAgICBpZiAoc2V0dGluZ3NEYXRhID09PSBcImhpZGRlblwiKSB7XG4gICAgICAgICAgICBvdmVyZmxvd1R5cGUgPSBDb250ZW50T3ZlcmZsb3dUeXBlLmhpZGRlbjtcbiAgICAgICAgfVxuICAgICAgICBvdmVyZmxvd1N0YXRlcy5wdXNoKG92ZXJmbG93VHlwZSk7XG4gICAgfVxuICAgIHBhcnNlZFNldHRpbmdzLmNvbnRlbnRPdmVyZmxvdyA9IG92ZXJmbG93U3RhdGVzO1xufVxuXG5mdW5jdGlvbiBjaGVja1NldHRpbmdJc0NvbHVtbkFsaWdubWVudChzZXR0aW5nc0xpbmU6IHN0cmluZywgcGFyc2VkU2V0dGluZ3M6IE11bHRpQ29sdW1uU2V0dGluZ3MpIHtcbiAgICBcbiAgICBsZXQgc2V0dGluZ3NEYXRhID0gZ2V0U2V0dGluZ3NEYXRhRnJvbUtleXMoc2V0dGluZ3NMaW5lLCBBTElHTk1FTlRfUkVHRVhfQVJSKTtcbiAgICBpZiAoc2V0dGluZ3NEYXRhID09PSBudWxsKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cblxuICAgIGxldCBhbGlnbm1lbnRzOiBBbGlnbm1lbnRUeXBlW10gPSBbXVxuXG4gICAgbGV0IHNldHRpbmdWYWx1ZXMgPSBwYXJzZUZvck11bHRpU2V0dGluZ3Moc2V0dGluZ3NEYXRhKTtcbiAgICBmb3IobGV0IHNldHRpbmdzRGF0YSBvZiBzZXR0aW5nVmFsdWVzKSB7XG4gICAgICAgIFxuICAgICAgICBsZXQgYWxpZ25tZW50VHlwZSA9IEFsaWdubWVudFR5cGUubGVmdDtcbiAgICAgICAgc2V0dGluZ3NEYXRhID0gc2V0dGluZ3NEYXRhLnRvTG93ZXJDYXNlKCkudHJpbSgpO1xuICAgICAgICBpZiAoc2V0dGluZ3NEYXRhID09PSBcImNlbnRlclwiKSB7XG4gICAgICAgICAgICBhbGlnbm1lbnRUeXBlID0gQWxpZ25tZW50VHlwZS5jZW50ZXI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHNldHRpbmdzRGF0YSA9PT0gXCJyaWdodFwiKSB7XG4gICAgICAgICAgICBhbGlnbm1lbnRUeXBlID0gQWxpZ25tZW50VHlwZS5yaWdodDtcbiAgICAgICAgfVxuICAgICAgICBhbGlnbm1lbnRzLnB1c2goYWxpZ25tZW50VHlwZSk7XG4gICAgfVxuICAgIHBhcnNlZFNldHRpbmdzLmFsaWdubWVudCA9IGFsaWdubWVudHM7XG59XG5cbmZ1bmN0aW9uIGNoZWNrU2V0dGluZ0lzVGFibGVBbGlnbm1lbnQoc2V0dGluZ3NMaW5lOiBzdHJpbmcsIHBhcnNlZFNldHRpbmdzOiBNdWx0aUNvbHVtblNldHRpbmdzKSB7XG4gICAgXG4gICAgbGV0IHNldHRpbmdzRGF0YSA9IGdldFNldHRpbmdzRGF0YUZyb21LZXlzKHNldHRpbmdzTGluZSwgVEFCTEVfQUxJR05NRU5UX1JFR0VYX0FSUik7XG4gICAgaWYgKHNldHRpbmdzRGF0YSA9PT0gbnVsbCkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgbGV0IHNldHRpbmdWYWx1ZXMgPSBwYXJzZUZvck11bHRpU2V0dGluZ3Moc2V0dGluZ3NEYXRhKTtcbiAgICBzZXR0aW5nc0RhdGEgPSBzZXR0aW5nVmFsdWVzWzBdO1xuXG4gICAgbGV0IHRhYmxlQWxpZ25tZW50OiBUYWJsZUFsaWduT3B0aW9uID0gKDxhbnk+VGFibGVBbGlnbk9wdGlvbilbc2V0dGluZ3NEYXRhXTtcbiAgICBpZiAodGFibGVBbGlnbm1lbnQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBzd2l0Y2ggKHRhYmxlQWxpZ25tZW50KSB7XG4gICAgICAgICAgICBjYXNlIChUYWJsZUFsaWduT3B0aW9uLmRpc2FibGVkKTpcbiAgICAgICAgICAgIGNhc2UgKFRhYmxlQWxpZ25PcHRpb24ub2ZmKTpcbiAgICAgICAgICAgIGNhc2UgKFRhYmxlQWxpZ25PcHRpb24uZmFsc2UpOlxuICAgICAgICAgICAgICAgIHBhcnNlZFNldHRpbmdzLmFsaWduVGFibGVzVG9BbGlnbm1lbnQgPSBUYWJsZUFsaWdubWVudC5ub0FsaWduO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICBwYXJzZWRTZXR0aW5ncy5hbGlnblRhYmxlc1RvQWxpZ25tZW50ID0gVGFibGVBbGlnbm1lbnQuYWxpZ247XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIGNoZWNrU2V0dGluZ0lzQ29sdW1uSGVpZ2h0KHNldHRpbmdzTGluZTogc3RyaW5nLCBwYXJzZWRTZXR0aW5nczogTXVsdGlDb2x1bW5TZXR0aW5ncykge1xuXG4gICAgbGV0IHNldHRpbmdzRGF0YSA9IGdldFNldHRpbmdzRGF0YUZyb21LZXlzKHNldHRpbmdzTGluZSwgQ09MVU1OX0hFSUdIVF9SRUdFWF9BUlIpO1xuICAgIGlmKHNldHRpbmdzRGF0YSA9PT0gbnVsbCkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgbGV0IHNldHRpbmdWYWx1ZXMgPSBwYXJzZUZvck11bHRpU2V0dGluZ3Moc2V0dGluZ3NEYXRhKTtcbiAgICBzZXR0aW5nc0RhdGEgPSBzZXR0aW5nVmFsdWVzWzBdO1xuXG4gICAgbGV0IHBhcnNlZCA9IEhUTUxTaXppbmcucGFyc2VUb1NpemluZyhzZXR0aW5nc0RhdGEudHJpbSgpKTtcbiAgICBpZiAocGFyc2VkICE9PSBudWxsKSB7XG5cbiAgICAgICAgcGFyc2VkU2V0dGluZ3MuY29sdW1uSGVpZ2h0ID0gcGFyc2VkO1xuICAgIH1cbiAgICBlbHNlIHtcblxuICAgICAgICBsZXQgbm9Vbml0c051bSA9IHBhcnNlSW50KHNldHRpbmdzRGF0YS50cmltKCkpO1xuICAgICAgICBpZiAoaXNOYU4obm9Vbml0c051bSkgPT09IGZhbHNlKSB7XG5cbiAgICAgICAgICAgIHBhcnNlZFNldHRpbmdzLmNvbHVtbkhlaWdodCA9IEhUTUxTaXppbmcuY3JlYXRlKCkuc2V0V2lkdGgobm9Vbml0c051bSkuc2V0VW5pdHMoXCJwdFwiKVxuICAgICAgICB9XG4gICAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZUZvck11bHRpU2V0dGluZ3Mob3JpZ2luYWxWYWx1ZTogc3RyaW5nKTogc3RyaW5nW10ge1xuXG4gICAgLy8gUGFyc2Ugb2ZmIGJyYWNrZXRzLiBJZiBubyBicmFja2V0cyB3ZSByZXR1cm4gb3JpZ2luYWwgdmFsdWUgdG8gYmUgcGFyc2VkIGFzIHNvbGUgdmFsdWUuXG4gICAgbGV0IHJlc3VsdCA9IC9cXFsoLiopXFxdLy5leGVjKG9yaWdpbmFsVmFsdWUpO1xuICAgIGlmKHJlc3VsdCA9PT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gW29yaWdpbmFsVmFsdWVdO1xuICAgIH1cblxuICAgIGxldCBzZXR0aW5nc0xpc3Q6IHN0cmluZyA9IHJlc3VsdFsxXTtcbiAgICBsZXQgc2V0dGluZ3M6IHN0cmluZ1tdID0gc2V0dGluZ3NMaXN0LnNwbGl0KFwiLFwiKS5tYXAoKHZhbCkgPT4ge1xuICAgICAgICByZXR1cm4gdmFsLnRyaW0oKTtcbiAgICB9KVxuXG4gICAgcmV0dXJuIHNldHRpbmdzO1xufVxuXG5jb25zdCBDT0RFQkxPQ0tfUkVHSU9OX0lEX1JFR0VYX1NUUlMgPSBbXG4gICAgXCJpZFwiLFxuICAgIFwicmVnaW9uIGlkXCJcbl1cbmNvbnN0IENPREVCTE9DS19SRUdJT05fSURfUkVHRVhfQVJSOiBSZWdFeHBbXSA9IENPREVCTE9DS19SRUdJT05fSURfUkVHRVhfU1RSUy5tYXAoY29udmVydFN0cmluZ1RvU2V0dGluZ3NSZWdleCkubWFwKCh2YWx1ZSkgPT4ge1xuICAgIHJldHVybiBuZXcgUmVnRXhwKHZhbHVlLCBcImlcIik7XG59KTtcbmV4cG9ydCBmdW5jdGlvbiBwYXJzZVN0YXJ0UmVnaW9uQ29kZUJsb2NrSUQoc2V0dGluZ3NTdHI6IHN0cmluZyk6IHN0cmluZyB7XG5cbiAgICBsZXQgY29kZUJsb2NrUmVnaW9uSUQgPSBcIlwiXG4gICAgbGV0IHNldHRpbmdzTGluZXMgPSBzZXR0aW5nc1N0ci5zcGxpdChcIlxcblwiKTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2V0dGluZ3NMaW5lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBsZXQgc2V0dGluZ3NMaW5lID0gc2V0dGluZ3NMaW5lc1tpXTtcblxuICAgICAgICBsZXQgc2V0dGluZ3NEYXRhID0gZ2V0U2V0dGluZ3NEYXRhRnJvbUtleXMoc2V0dGluZ3NMaW5lLCBDT0RFQkxPQ0tfUkVHSU9OX0lEX1JFR0VYX0FSUik7XG4gICAgICAgIGlmIChzZXR0aW5nc0RhdGEgIT09IG51bGwpIHtcblxuICAgICAgICAgICAgY29kZUJsb2NrUmVnaW9uSUQgPSBzZXR0aW5nc0RhdGFcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2RlQmxvY2tSZWdpb25JRDtcbn1cblxuZnVuY3Rpb24gcGFyc2VGb3JTaW5nbGVDb2x1bW5Mb2NhdGlvbihsb2NhdGlvblN0cmluZzogc3RyaW5nKTogQ29sdW1uTGF5b3V0e1xuXG4gICAgc3dpdGNoIChsb2NhdGlvblN0cmluZy50b0xvd2VyQ2FzZSgpLnRyaW0oKS5yZXBsYWNlKFwiIFwiLCBcIlwiKSkge1xuICAgICAgICBjYXNlIFwibGVmdFwiOlxuICAgICAgICBjYXNlIFwibGVmdHNpZGVcIjpcbiAgICAgICAgY2FzZSBcImxlZnRtYXJnaW5cIjpcbiAgICAgICAgY2FzZSBcImxlZnRhbGlnblwiOlxuICAgICAgICBjYXNlIFwibGVmdGFsaWduZWRcIjpcbiAgICAgICAgY2FzZSBcImxlZnRhbGlnbmVtZW50XCI6XG4gICAgICAgIGNhc2UgXCJmaXJzdFwiOlxuICAgICAgICBjYXNlIFwic3RhcnRcIjpcbiAgICAgICAgY2FzZSBcImJlZ2lubmluZ1wiOlxuICAgICAgICAgICAgcmV0dXJuIFwibGVmdFwiXG4gICAgICAgIGNhc2UgXCJtaWRkbGVcIjpcbiAgICAgICAgY2FzZSBcIm1pZGRsZWFsaWduZWRcIjpcbiAgICAgICAgY2FzZSBcIm1pZGRsZWFsaWdubWVudFwiOlxuICAgICAgICBjYXNlIFwiY2VudGVyXCI6XG4gICAgICAgIGNhc2UgXCJjZW50ZXJhbGlnbmVkXCI6XG4gICAgICAgIGNhc2UgXCJjZW50ZXJhbGlnbm1lbnRcIjpcbiAgICAgICAgY2FzZSBcImNlbnRlcmVkXCI6XG4gICAgICAgIGNhc2UgXCJzdGFuZGFyZFwiOlxuICAgICAgICAgICAgcmV0dXJuIFwiY2VudGVyXCJcbiAgICAgICAgY2FzZSBcInJpZ2h0XCI6XG4gICAgICAgIGNhc2UgXCJyaWdodHNpZGVcIjpcbiAgICAgICAgY2FzZSBcInJpZ2h0bWFyZ2luXCI6XG4gICAgICAgIGNhc2UgXCJyaWdodGFsaWduXCI6XG4gICAgICAgIGNhc2UgXCJyaWdodGFsaWduZWRcIjpcbiAgICAgICAgY2FzZSBcInJpZ2h0YWxpZ25tZW50XCI6XG4gICAgICAgIGNhc2UgXCJsYXN0XCI6XG4gICAgICAgIGNhc2UgXCJlbmRcIjpcbiAgICAgICAgICAgIHJldHVybiBcInJpZ2h0XCJcbiAgICB9XG5cbiAgICByZXR1cm4gXCJjZW50ZXJcIlxufVxuXG5mdW5jdGlvbiBwYXJzZUZvclNpbmdsZUNvbHVtblNpemUoc2l6ZVN0cmluZzogc3RyaW5nKTogU2luZ2xlQ29sdW1uU2l6ZSB7XG5cbiAgICBzd2l0Y2ggKHNpemVTdHJpbmcgPSBzaXplU3RyaW5nLnRvTG93ZXJDYXNlKCkudHJpbSgpLnJlcGxhY2UoXCIgXCIsIFwiXCIpKSB7XG4gICAgICAgIGNhc2UgXCJzbWFsbFwiOlxuICAgICAgICBjYXNlIFwic21cIjpcbiAgICAgICAgICAgIHJldHVybiBcInNtYWxsXCI7XG4gICAgICAgIGNhc2UgXCJtZWRpdW1cIjpcbiAgICAgICAgY2FzZSBcIm1lZFwiOlxuICAgICAgICAgICAgcmV0dXJuIFwibWVkaXVtXCI7XG4gICAgICAgIGNhc2UgXCJsYXJnZVwiOlxuICAgICAgICBjYXNlIFwibGdcIjpcbiAgICAgICAgICAgIHJldHVybiBcImxhcmdlXCI7XG4gICAgICAgIGNhc2UgXCJmdWxsXCI6XG4gICAgICAgIGNhc2UgXCJmdWxsIHNpemVcIjpcbiAgICAgICAgICAgIHJldHVybiBcImZ1bGxcIjtcbiAgICB9XG5cbiAgICByZXR1cm4gXCJtZWRpdW1cIlxufVxuXG5mdW5jdGlvbiBjb252ZXJ0U3RyaW5nVG9TZXR0aW5nc1JlZ2V4KG9yaWdpbmFsU3RyaW5nOiBTdHJpbmcpOiBzdHJpbmcge1xuXG4gICAgb3JpZ2luYWxTdHJpbmcgPSBvcmlnaW5hbFN0cmluZy5yZXBsYWNlKFwiIFwiLCBcIig/OlstX118ICp8KVwiKTtcblxuICAgIGxldCByZWdleFN0cmluZyA9IGAoPzoke29yaWdpbmFsU3RyaW5nfSAqWzo9XSAqKSguKilgO1xuICAgIHJldHVybiByZWdleFN0cmluZztcbn1cblxuIiwiaW1wb3J0IHsgTXVsdGlDb2x1bW5TZXR0aW5ncywgZ2V0RGVmYXVsdE11bHRpQ29sdW1uU2V0dGluZ3MgfSBmcm9tIFwic3JjL3JlZ2lvblNldHRpbmdzXCI7XG5pbXBvcnQgeyBwYXJzZUNvbHVtblNldHRpbmdzIH0gZnJvbSBcIi4vc2V0dGluZ3NQYXJzZXJcIjtcbmltcG9ydCB7IFN0YXJ0VGFnUmVnZXhNYXRjaCwgZGVmYXVsdFN0YXJ0UmVnaW9uRGF0YSB9IGZyb20gXCIuL2ludGVyZmFjZXNcIjtcblxuXG5leHBvcnQgY29uc3QgUEFORE9DX0VOR0xJU0hfTlVNQkVSX09GX0NPTFVNTlMgPSBbXG4gICAgXCJ0d29cIixcbiAgICBcInRocmVlXCIsXG4gICAgXCJmb3VyXCIsXG4gICAgXCJmaXZlXCIsXG4gICAgXCJzaXhcIixcbiAgICBcInNldmVuXCIsXG4gICAgXCJlaWdodFwiLFxuICAgIFwibmluZVwiLFxuICAgIFwidGVuXCJcbl0gYXMgY29uc3Q7XG50eXBlIFBhbmRvY051bWJlck9mQ29sdW1uc1R1cGxlID0gdHlwZW9mIFBBTkRPQ19FTkdMSVNIX05VTUJFUl9PRl9DT0xVTU5TO1xuZXhwb3J0IHR5cGUgUGFuZG9jTnVtYmVyT2ZDb2x1bW5zID0gUGFuZG9jTnVtYmVyT2ZDb2x1bW5zVHVwbGVbbnVtYmVyXTtcbmV4cG9ydCBmdW5jdGlvbiBpc1BhbmRvY051bWJlck9mQ29sdW1ucyh2YWx1ZTogc3RyaW5nKTogdmFsdWUgaXMgUGFuZG9jTnVtYmVyT2ZDb2x1bW5zIHtcbiAgICByZXR1cm4gUEFORE9DX0VOR0xJU0hfTlVNQkVSX09GX0NPTFVNTlMuaW5jbHVkZXModmFsdWUgYXMgUGFuZG9jTnVtYmVyT2ZDb2x1bW5zKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZVBhbmRvY051bWJlck9mQ29sdW1ucyh2YWx1ZTogc3RyaW5nIHwgUGFuZG9jTnVtYmVyT2ZDb2x1bW5zKTogUGFuZG9jTnVtYmVyT2ZDb2x1bW5zIHtcbiAgICByZXR1cm4gKHZhbHVlLnRvTG93ZXJDYXNlKCkgYXMgUGFuZG9jTnVtYmVyT2ZDb2x1bW5zKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBwYW5kb2NOdW1iZXJPZkNvbHVtbnNUb1ZhbHVlKHZhbHVlOiBQYW5kb2NOdW1iZXJPZkNvbHVtbnMpOiBudW1iZXIge1xuICAgIHN3aXRjaCAodmFsdWUpIHtcbiAgICAgICAgY2FzZSBcInR3b1wiOlxuICAgICAgICAgICAgcmV0dXJuIDI7XG4gICAgICAgIGNhc2UgXCJ0aHJlZVwiOlxuICAgICAgICAgICAgcmV0dXJuIDM7XG4gICAgICAgIGNhc2UgXCJmb3VyXCI6XG4gICAgICAgICAgICByZXR1cm4gNDtcbiAgICAgICAgY2FzZSBcImZpdmVcIjpcbiAgICAgICAgICAgIHJldHVybiA1O1xuICAgICAgICBjYXNlIFwic2l4XCI6XG4gICAgICAgICAgICByZXR1cm4gNjtcbiAgICAgICAgY2FzZSBcInNldmVuXCI6XG4gICAgICAgICAgICByZXR1cm4gNztcbiAgICAgICAgY2FzZSBcImVpZ2h0XCI6XG4gICAgICAgICAgICByZXR1cm4gODtcbiAgICAgICAgY2FzZSBcIm5pbmVcIjpcbiAgICAgICAgICAgIHJldHVybiA5O1xuICAgICAgICBjYXNlIFwidGVuXCI6XG4gICAgICAgICAgICByZXR1cm4gMTA7XG4gICAgfVxufVxuY29uc3QgUEFORE9DX0NPTF9ET1RfQ09VTlRfTkFNRSA9IFwiY29sRG90Q291bnRcIjtcbmNvbnN0IFBBTkRPQ19DT0xfTk9ET1RfQ09VTlRfTkFNRSA9IFwiY29sQ291bnRcIjtcbmNvbnN0IFBBTkRPQ19DT0xfQ09OVEVOVCA9IFwiY29sQ29udGVudFwiO1xuY29uc3QgUEFORE9DX0NPbF9TRVRUSU5HUyA9IFwiY29sU2V0dGluZ3NcIjtcbmNvbnN0IFBBTkRPQ19SRUdFWF9TVFI6IHN0cmluZyA9ICgoKSA9PiB7XG5cbiAgICBsZXQgbnVtcyA9IFBBTkRPQ19FTkdMSVNIX05VTUJFUl9PRl9DT0xVTU5TLmpvaW4oXCJ8XCIpO1xuICAgIGxldCByZWdleF9zdHJpbmdzID0gYDp7Myx9ICooPzpcXFxceyAqXFxcXC4oPzwke1BBTkRPQ19DT0xfRE9UX0NPVU5UX05BTUV9Pig/OiR7bnVtc318KSkoPzpbLV9dfCljb2x1bW5zKD88JHtQQU5ET0NfQ09sX1NFVFRJTkdTfT4uKilcXFxcfXwoPzwke1BBTkRPQ19DT0xfTk9ET1RfQ09VTlRfTkFNRX0+KD86JHtudW1zfXwpKSg/OlstX118KWNvbHVtbnMpKD86WyA6XSopJFxcXFxuP2A7XG4gICAgcmV0dXJuIHJlZ2V4X3N0cmluZ3M7XG59KSgpO1xuY29uc3QgUEFORE9DX1JFR0VYID0gbmV3IFJlZ0V4cChQQU5ET0NfUkVHRVhfU1RSLCBcIm1cIik7XG5jb25zdCBQQU5ET0NfT1BFTl9GRU5DRV9SRUdFWCA9IC9eOnszLH0gKig/OlthLXpBLVpdK3xcXHsuKlxcfSkoPzpbIDpdKikkL207XG5jb25zdCBQQU5ET0NfQ0xPU0VfRkVOQ0VfUkVHRVggPSAvXjp7Myx9ICokL207XG5leHBvcnQgZnVuY3Rpb24gZmluZFBhbmRvYyh0ZXh0OiBzdHJpbmcpOiBQYW5kb2NSZWdleERhdGEge1xuXG4gICAgbGV0IHJlZ2V4RGF0YSA9IFBBTkRPQ19SRUdFWC5leGVjKHRleHQpO1xuICAgIGlmIChyZWdleERhdGEgIT09IG51bGwpIHtcblxuICAgICAgICBsZXQgZGF0YSA9IGRlZmF1bHRQYW5kb2NSZWdleERhdGEoKTtcbiAgICAgICAgZGF0YS5mb3VuZCA9IHRydWU7XG4gICAgICAgIGRhdGEuc3RhcnRQb3NpdGlvbiA9IHJlZ2V4RGF0YS5pbmRleDtcbiAgICAgICAgZGF0YS5lbmRQb3NpdGlvbiA9IHJlZ2V4RGF0YS5pbmRleCArIHJlZ2V4RGF0YVswXS5sZW5ndGg7XG5cbiAgICAgICAgbGV0IHJlZ2lvbkRhdGEgPSByZWR1Y2VQYW5kb2NSZWdpb25Ub0VuZERpdih0ZXh0LnNsaWNlKGRhdGEuZW5kUG9zaXRpb24pKTtcbiAgICAgICAgZGF0YS5lbmRQb3NpdGlvbiArPSByZWdpb25EYXRhLmNvbnRlbnQubGVuZ3RoICsgcmVnaW9uRGF0YS5tYXRjaExlbmd0aDtcbiAgICAgICAgZGF0YS5jb250ZW50ID0gcmVnaW9uRGF0YS5jb250ZW50O1xuICAgICAgICBkYXRhLm1hdGNoTGVuZ3RoID0gZGF0YS5lbmRQb3NpdGlvbiAtIGRhdGEuc3RhcnRQb3NpdGlvbjtcblxuICAgICAgICBkYXRhLnVzZXJTZXR0aW5ncyA9IHJlZ2V4RGF0YS5ncm91cHNbUEFORE9DX0NPbF9TRVRUSU5HU10gPyByZWdleERhdGEuZ3JvdXBzW1BBTkRPQ19DT2xfU0VUVElOR1NdIDogXCJcIjtcbiAgICAgICAgZGF0YS5jb2x1bW5Db3VudCA9IHJlZ2V4RGF0YS5ncm91cHNbUEFORE9DX0NPTF9ET1RfQ09VTlRfTkFNRV0gPyByZWdleERhdGEuZ3JvdXBzW1BBTkRPQ19DT0xfRE9UX0NPVU5UX05BTUVdIDogcmVnZXhEYXRhLmdyb3Vwc1tQQU5ET0NfQ09MX05PRE9UX0NPVU5UX05BTUVdO1xuICAgICAgICByZXR1cm4gZGF0YTtcbiAgICB9XG5cbiAgICByZXR1cm4gZGVmYXVsdFBhbmRvY1JlZ2V4RGF0YSgpO1xufVxuZXhwb3J0IGludGVyZmFjZSBQYW5kb2NTdGFydERhdGEge1xuICAgIGZvdW5kOiBib29sZWFuO1xuICAgIHVzZXJTZXR0aW5nczogTXVsdGlDb2x1bW5TZXR0aW5ncztcbn1cbmV4cG9ydCBmdW5jdGlvbiBnZXRQYW5kb2NTdGFydERhdGEodGV4dDogc3RyaW5nKTogUGFuZG9jU3RhcnREYXRhIHtcblxuICAgIGxldCBkYXRhID0gZmluZFBhbmRvYyh0ZXh0KTtcbiAgICBpZiAoZGF0YS5mb3VuZCA9PT0gZmFsc2UpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGZvdW5kOiBmYWxzZSxcbiAgICAgICAgICAgIHVzZXJTZXR0aW5nczogZ2V0RGVmYXVsdE11bHRpQ29sdW1uU2V0dGluZ3MoKVxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAgIGZvdW5kOiB0cnVlLFxuICAgICAgICB1c2VyU2V0dGluZ3M6IHBhcnNlUGFuZG9jU2V0dGluZ3MoZGF0YS51c2VyU2V0dGluZ3MsIGRhdGEuY29sdW1uQ291bnQpXG4gICAgfTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBjb250YWluc1BhbmRvYyh0ZXh0OiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gZmluZFBhbmRvYyh0ZXh0KS5mb3VuZDtcbn1cbmV4cG9ydCBmdW5jdGlvbiBjb250YWluc1BhbmRvY1N0YXJ0VGFnKHRleHQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuXG4gICAgbGV0IHJlZ2V4RGF0YSA9IFBBTkRPQ19SRUdFWC5leGVjKHRleHQpO1xuICAgIGlmIChyZWdleERhdGEgIT09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBjb250YWluc1BhbmRvY0VuZFRhZyh0ZXh0OiBzdHJpbmcpOiBib29sZWFuIHtcblxuICAgIGxldCByZWdleERhdGEgPSBQQU5ET0NfQ0xPU0VfRkVOQ0VfUkVHRVguZXhlYyh0ZXh0KTtcbiAgICBpZiAocmVnZXhEYXRhICE9PSBudWxsKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG59XG5leHBvcnQgZnVuY3Rpb24gaXNWYWxpZFBhbmRvY0VuZFRhZyhsaW5lc0Fib3ZlOiBzdHJpbmdbXSwgY3VycmVudExpbmU6IHN0cmluZyk6IGJvb2xlYW4ge1xuXG4gICAgaWYgKGNvbnRhaW5zUGFuZG9jRW5kVGFnKGN1cnJlbnRMaW5lKSA9PT0gZmFsc2UpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGxldCBjb250ZW50VGV4dCA9IGxpbmVzQWJvdmUuY29uY2F0KGN1cnJlbnRMaW5lKS5qb2luKFwiXFxuXCIpO1xuICAgIHJldHVybiByZWR1Y2VQYW5kb2NSZWdpb25Ub0VuZERpdihjb250ZW50VGV4dCkuZm91bmQ7XG59XG5leHBvcnQgZnVuY3Rpb24gcmVkdWNlUGFuZG9jUmVnaW9uVG9FbmREaXYoY29udGVudFRleHQ6IHN0cmluZykge1xuXG4gICAgbGV0IHdvcmtpbmdUZXh0ID0gY29udGVudFRleHQ7XG5cbiAgICBsZXQgcmVzdWx0ID0ge1xuICAgICAgICBmb3VuZDogZmFsc2UsXG4gICAgICAgIGNvbnRlbnQ6IHdvcmtpbmdUZXh0LFxuICAgICAgICBtYXRjaExlbmd0aDogMFxuICAgIH07XG5cbiAgICBsZXQgc3RhdGUgPSAwO1xuICAgIGxldCBvZmZzZXQgPSAwO1xuICAgIGZvciAobGV0IGkgPSAwOyB0cnVlOyBpKyspIHtcbiAgICAgICAgaWYgKGkgPiAxMDApIHtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGZlbmNlID0gZ2V0TmV4dFBhbmRvY0ZlbmNlKHdvcmtpbmdUZXh0KTtcbiAgICAgICAgaWYgKGZlbmNlID09PSBudWxsKSB7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCByZXN1bHQgPSBmZW5jZS5yZXN1bHQ7XG4gICAgICAgIGlmIChmZW5jZS50eXBlID09PSBcImNsb3NlXCIpIHtcbiAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKHdvcmtpbmdUZXh0LnNsaWNlKHJlc3VsdC5pbmRleCwgcmVzdWx0LmluZGV4ICsgcmVzdWx0WzBdLmxlbmd0aCkpO1xuICAgICAgICAgICAgb2Zmc2V0ICs9IChyZXN1bHQuaW5kZXggKyByZXN1bHRbMF0ubGVuZ3RoKTtcbiAgICAgICAgICAgIHN0YXRlLS07XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBjb25zb2xlLmxvZyh3b3JraW5nVGV4dC5zbGljZShyZXN1bHQuaW5kZXgsIHJlc3VsdC5pbmRleCArIHJlc3VsdFswXS5sZW5ndGgpKTtcbiAgICAgICAgICAgIG9mZnNldCArPSAocmVzdWx0LmluZGV4ICsgcmVzdWx0WzBdLmxlbmd0aCk7XG4gICAgICAgICAgICBzdGF0ZSsrO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHN0YXRlID09PSAtMSkge1xuICAgICAgICAgICAgLy8gV2UgaGF2ZSBmb3VuZCBvdXIgbGFzdCBjbG9zZSB0YWcuXG4gICAgICAgICAgICByZXR1cm4gYnVpbGRSZXR1cm5EYXRhKHJlc3VsdCk7XG4gICAgICAgIH1cblxuICAgICAgICB3b3JraW5nVGV4dCA9IGNvbnRlbnRUZXh0LnNsaWNlKG9mZnNldCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYnVpbGRSZXR1cm5EYXRhKG1hdGNoUmVzdWx0OiBSZWdFeHBFeGVjQXJyYXkpIHtcbiAgICAgICAgcmVzdWx0LmNvbnRlbnQgPSBjb250ZW50VGV4dC5zbGljZSgwLCBvZmZzZXQgLSBtYXRjaFJlc3VsdFswXS5sZW5ndGgpO1xuICAgICAgICByZXN1bHQubWF0Y2hMZW5ndGggPSBtYXRjaFJlc3VsdFswXS5sZW5ndGg7XG4gICAgICAgIHJlc3VsdC5mb3VuZCA9IHRydWU7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cbmZ1bmN0aW9uIGdldE5leHRQYW5kb2NGZW5jZSh3b3JraW5nVGV4dDogc3RyaW5nKTogeyByZXN1bHQ6IFJlZ0V4cEV4ZWNBcnJheTsgdHlwZTogXCJvcGVuXCIgfCBcImNsb3NlXCI7IH0ge1xuXG4gICAgbGV0IG9wZW5SZXN1bHQgPSBQQU5ET0NfT1BFTl9GRU5DRV9SRUdFWC5leGVjKHdvcmtpbmdUZXh0KTtcbiAgICBsZXQgY2xvc2VSZXN1bHQgPSBQQU5ET0NfQ0xPU0VfRkVOQ0VfUkVHRVguZXhlYyh3b3JraW5nVGV4dCk7XG5cbiAgICBpZiAob3BlblJlc3VsdCA9PT0gbnVsbCAmJiBjbG9zZVJlc3VsdCA9PT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBpZiAob3BlblJlc3VsdCA9PT0gbnVsbCAmJiBjbG9zZVJlc3VsdCAhPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgcmVzdWx0OiBjbG9zZVJlc3VsdCxcbiAgICAgICAgICAgIHR5cGU6IFwiY2xvc2VcIlxuICAgICAgICB9O1xuICAgIH1cblxuICAgIGlmIChjbG9zZVJlc3VsdCA9PT0gbnVsbCAmJiBvcGVuUmVzdWx0ICE9PSBudWxsKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICByZXN1bHQ6IG9wZW5SZXN1bHQsXG4gICAgICAgICAgICB0eXBlOiBcIm9wZW5cIlxuICAgICAgICB9O1xuICAgIH1cblxuICAgIGlmIChjbG9zZVJlc3VsdC5pbmRleCA8IG9wZW5SZXN1bHQuaW5kZXgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHJlc3VsdDogY2xvc2VSZXN1bHQsXG4gICAgICAgICAgICB0eXBlOiBcImNsb3NlXCJcbiAgICAgICAgfTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICByZXN1bHQ6IG9wZW5SZXN1bHQsXG4gICAgICAgICAgICB0eXBlOiBcIm9wZW5cIlxuICAgICAgICB9O1xuICAgIH1cbn1cbmV4cG9ydCBmdW5jdGlvbiBmaW5kUGFuZG9jU3RhcnQodGV4dDogc3RyaW5nKTogU3RhcnRUYWdSZWdleE1hdGNoIHtcblxuICAgIGxldCBzdGFydFJlZ2lvbiA9IGRlZmF1bHRTdGFydFJlZ2lvbkRhdGEoKTtcbiAgICBzdGFydFJlZ2lvbi5yZWdpb25UeXBlID0gXCJQQURPQ1wiO1xuXG4gICAgbGV0IHJlZ2V4RGF0YSA9IFBBTkRPQ19SRUdFWC5leGVjKHRleHQpO1xuICAgIGlmIChyZWdleERhdGEgIT09IG51bGwgJiYgcmVnZXhEYXRhLmxlbmd0aCA+IDApIHtcblxuICAgICAgICBzdGFydFJlZ2lvbi5mb3VuZCA9IHRydWU7XG4gICAgICAgIHN0YXJ0UmVnaW9uLnN0YXJ0UG9zaXRpb24gPSByZWdleERhdGEuaW5kZXg7XG4gICAgICAgIHN0YXJ0UmVnaW9uLm1hdGNoTGVuZ3RoID0gcmVnZXhEYXRhWzBdLmxlbmd0aDtcbiAgICAgICAgc3RhcnRSZWdpb24uZW5kUG9zaXRpb24gPSBzdGFydFJlZ2lvbi5zdGFydFBvc2l0aW9uICsgc3RhcnRSZWdpb24ubWF0Y2hMZW5ndGg7XG4gICAgfVxuXG4gICAgcmV0dXJuIHN0YXJ0UmVnaW9uO1xufVxuZXhwb3J0IGludGVyZmFjZSBQYW5kb2NSZWdleERhdGEgZXh0ZW5kcyBTdGFydFRhZ1JlZ2V4TWF0Y2gge1xuICAgIGZvdW5kOiBib29sZWFuO1xuICAgIHN0YXJ0UG9zaXRpb246IG51bWJlcjtcbiAgICBlbmRQb3NpdGlvbjogbnVtYmVyO1xuICAgIGNvbnRlbnQ6IHN0cmluZztcbiAgICB1c2VyU2V0dGluZ3M6IHN0cmluZztcbiAgICBjb2x1bW5Db3VudDogc3RyaW5nO1xufVxuZnVuY3Rpb24gZGVmYXVsdFBhbmRvY1JlZ2V4RGF0YSgpOiBQYW5kb2NSZWdleERhdGEge1xuICAgIHJldHVybiB7XG4gICAgICAgIGZvdW5kOiBmYWxzZSxcbiAgICAgICAgc3RhcnRQb3NpdGlvbjogLTEsXG4gICAgICAgIGVuZFBvc2l0aW9uOiAtMSxcbiAgICAgICAgbWF0Y2hMZW5ndGg6IDAsXG4gICAgICAgIGNvbnRlbnQ6IFwiXCIsXG4gICAgICAgIHVzZXJTZXR0aW5nczogXCJcIixcbiAgICAgICAgY29sdW1uQ291bnQ6IFwiXCIsXG4gICAgICAgIHJlZ2lvblR5cGU6IFwiUEFET0NcIlxuICAgIH07XG59XG5cbmNvbnN0IFBBTkRPQ19TRVRUSU5HX1JFR0VYID0gLyg/PHNldHRpbmdOYW1lPlteIF0qKT0oPzxzZXR0aW5nVmFsdWU+XCIuKlwifFteID1dKikvO1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlUGFuZG9jU2V0dGluZ3MocGFuZG9jVXNlclNldHRpbmdzOiBzdHJpbmcsIGNvbENvdW50OiBzdHJpbmcgPSBcIlwiKTogTXVsdGlDb2x1bW5TZXR0aW5ncyB7XG5cbiAgICAvL1RPRE86IEFkZCBvcHRpb24gZm9yIGNvbHVtbiBydWxlLiBcblxuICAgIGxldCBkZWZhdWx0U2V0dGluZ3MgPSBnZXREZWZhdWx0TXVsdGlDb2x1bW5TZXR0aW5ncygpO1xuICAgIGxldCBjb2xDb3VudERlZmluZWQgPSBmYWxzZTtcbiAgICBpZiAoY29sQ291bnQgIT09IFwiXCIgJiYgaXNQYW5kb2NOdW1iZXJPZkNvbHVtbnMoY29sQ291bnQpKSB7XG4gICAgICAgIGNvbENvdW50RGVmaW5lZCA9IHRydWU7XG4gICAgICAgIGRlZmF1bHRTZXR0aW5ncy5udW1iZXJPZkNvbHVtbnMgPSBwYW5kb2NOdW1iZXJPZkNvbHVtbnNUb1ZhbHVlKHZhbGlkYXRlUGFuZG9jTnVtYmVyT2ZDb2x1bW5zKGNvbENvdW50KSk7XG4gICAgfVxuXG4gICAgaWYgKHBhbmRvY1VzZXJTZXR0aW5ncy5yZXBsYWNlKFwiIFwiLCBcIlwiKSA9PT0gXCJcIikge1xuICAgICAgICByZXR1cm4gZGVmYXVsdFNldHRpbmdzO1xuICAgIH1cblxuICAgIGxldCB3b3JraW5nU3RyaW5nID0gcGFuZG9jVXNlclNldHRpbmdzO1xuICAgIGxldCByZWdleFZhbHVlID0gUEFORE9DX1NFVFRJTkdfUkVHRVguZXhlYyh3b3JraW5nU3RyaW5nKTtcbiAgICBsZXQgc2V0dGluZ0xpc3QgPSBcIlwiXG4gICAgZm9yIChsZXQgaSA9IDA7IHJlZ2V4VmFsdWUgIT09IG51bGw7IGkgPCAxMDApIHtcblxuICAgICAgICBsZXQgc2V0dGluZ05hbWUgPSByZWdleFZhbHVlLmdyb3Vwc1snc2V0dGluZ05hbWUnXTtcbiAgICAgICAgbGV0IHNldHRpbmdWYWx1ZSA9IHJlZ2V4VmFsdWUuZ3JvdXBzWydzZXR0aW5nVmFsdWUnXTtcbiAgICAgICAgc2V0dGluZ0xpc3QgKz0gYCR7c2V0dGluZ05hbWV9OiAke3NldHRpbmdWYWx1ZX1cXG5gXG5cbiAgICAgICAgd29ya2luZ1N0cmluZyA9IHdvcmtpbmdTdHJpbmcuc2xpY2UocmVnZXhWYWx1ZS5pbmRleCArIHJlZ2V4VmFsdWVbMF0ubGVuZ3RoKTtcbiAgICAgICAgcmVnZXhWYWx1ZSA9IFBBTkRPQ19TRVRUSU5HX1JFR0VYLmV4ZWMod29ya2luZ1N0cmluZyk7XG4gICAgfVxuXG4gICAgbGV0IHBhcnNlZFNldHRpbmdzID0gcGFyc2VDb2x1bW5TZXR0aW5ncyhzZXR0aW5nTGlzdClcbiAgICBpZihjb2xDb3VudERlZmluZWQpIHtcbiAgICAgICAgcGFyc2VkU2V0dGluZ3MubnVtYmVyT2ZDb2x1bW5zID0gZGVmYXVsdFNldHRpbmdzLm51bWJlck9mQ29sdW1uc1xuICAgIH1cblxuICAgIHJldHVybiBwYXJzZWRTZXR0aW5ncztcbn0iLCIvKlxuICogRmlsZTogbXVsdGktY29sdW1uLW1hcmtkb3duL3NyYy9NdWx0aUNvbHVtblBhcnNlci50c1xuICogQ3JlYXRlZCBEYXRlOiBTYXR1cmRheSwgSmFudWFyeSAyMm5kIDIwMjIsIDY6MDI6NDYgcG1cbiAqIEF1dGhvcjogQ2FtZXJvbiBSb2JpbnNvblxuICogXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjIgQ2FtZXJvbiBSb2JpbnNvblxuICovXG5cbmltcG9ydCB7IHBhcnNlU3RhcnRSZWdpb25Db2RlQmxvY2tJRCB9IGZyb20gXCIuL3NldHRpbmdzUGFyc2VyXCI7XG5pbXBvcnQgeyBjb250YWluc1BhbmRvYywgZmluZFBhbmRvY1N0YXJ0LCByZWR1Y2VQYW5kb2NSZWdpb25Ub0VuZERpdiwgZ2V0UGFuZG9jU3RhcnREYXRhIH0gZnJvbSBcIi4vcGFuZG9jUGFyc2VyXCI7XG5pbXBvcnQgeyBSZWdpb25UeXBlLCBTdGFydFRhZ1JlZ2V4TWF0Y2gsIGRlZmF1bHRTdGFydFJlZ2lvbkRhdGEgfSBmcm9tIFwiLi9pbnRlcmZhY2VzXCI7XG5cbmNvbnN0IFNUQVJUX1JFR0VYX1NUUlMgPSBbXCIoPT09fC0tLSkgKnN0YXJ0LW11bHRpLWNvbHVtbig6P1thLXpBLVowLTktX1xcXFxzXSopP1wiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBcIig9PT18LS0tKSAqbXVsdGktY29sdW1uLXN0YXJ0KDo/W2EtekEtWjAtOS1fXFxcXHNdKik/XCJdXG5jb25zdCBTVEFSVF9SRUdFWF9BUlI6IFJlZ0V4cFtdID0gW107XG5mb3IobGV0IGkgPSAwOyBpIDwgU1RBUlRfUkVHRVhfU1RSUy5sZW5ndGg7IGkrKykge1xuICAgIFNUQVJUX1JFR0VYX0FSUi5wdXNoKG5ldyBSZWdFeHAoU1RBUlRfUkVHRVhfU1RSU1tpXSkpO1xufVxuXG5jb25zdCBTVEFSVF9SRUdFWF9TVFJTX1dIT0xFX0xJTkUgPSBbXCJeKD09PXwtLS0pICpzdGFydC1tdWx0aS1jb2x1bW4oOj9bYS16QS1aMC05LV9cXFxcc10qKT8kXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJeKD09PXwtLS0pICptdWx0aS1jb2x1bW4tc3RhcnQoOj9bYS16QS1aMC05LV9cXFxcc10qKT8kXCJdXG5jb25zdCBTVEFSVF9SRUdFWF9BUlJfV0hPTEVfTElORTogUmVnRXhwW10gPSBbXTtcbmZvcihsZXQgaSA9IDA7IGkgPCBTVEFSVF9SRUdFWF9TVFJTX1dIT0xFX0xJTkUubGVuZ3RoOyBpKyspIHtcbiAgICBTVEFSVF9SRUdFWF9BUlJfV0hPTEVfTElORS5wdXNoKG5ldyBSZWdFeHAoU1RBUlRfUkVHRVhfU1RSU19XSE9MRV9MSU5FW2ldKSk7XG59XG5cblxuZXhwb3J0IGZ1bmN0aW9uIGZpbmRTdGFydFRhZyh0ZXh0OiBzdHJpbmcpOiBTdGFydFRhZ1JlZ2V4TWF0Y2gge1xuXG4gICAgbGV0IHN0YXJ0UmVnaW9uID0gZGVmYXVsdFN0YXJ0UmVnaW9uRGF0YSgpO1xuICAgIHN0YXJ0UmVnaW9uLnJlZ2lvblR5cGUgPSBcIk9SSUdJTkFMXCI7XG5cbiAgICBmb3IobGV0IGkgPSAwOyBpPCBTVEFSVF9SRUdFWF9BUlIubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICBsZXQgcmVnZXhEYXRhID0gU1RBUlRfUkVHRVhfQVJSW2ldLmV4ZWModGV4dClcbiAgICAgICAgaWYocmVnZXhEYXRhICE9PSBudWxsICYmIHJlZ2V4RGF0YS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBzdGFydFJlZ2lvbi5zdGFydFBvc2l0aW9uID0gcmVnZXhEYXRhLmluZGV4XG4gICAgICAgICAgICBzdGFydFJlZ2lvbi5tYXRjaExlbmd0aCA9IHJlZ2V4RGF0YVswXS5sZW5ndGg7XG4gICAgICAgICAgICBzdGFydFJlZ2lvbi5lbmRQb3NpdGlvbiA9IHN0YXJ0UmVnaW9uLnN0YXJ0UG9zaXRpb24gKyBzdGFydFJlZ2lvbi5tYXRjaExlbmd0aDtcblxuICAgICAgICAgICAgbGV0IGxpbmUgPSB0ZXh0LnNsaWNlKHN0YXJ0UmVnaW9uLnN0YXJ0UG9zaXRpb24sIHN0YXJ0UmVnaW9uLmVuZFBvc2l0aW9uKTtcbiAgICAgICAgICAgIGlmKFNUQVJUX1JFR0VYX0FSUl9XSE9MRV9MSU5FW2ldLnRlc3QobGluZSkpIHtcbiAgICAgICAgICAgICAgICBzdGFydFJlZ2lvbi5mb3VuZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHN0YXJ0UmVnaW9uO1xufVxuZXhwb3J0IGZ1bmN0aW9uIGNvbnRhaW5zU3RhcnRUYWcodGV4dDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGZpbmRTdGFydFRhZyh0ZXh0KS5mb3VuZFxufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNTdGFydFRhZ1dpdGhJRCh0ZXh0OiBzdHJpbmcpOiB7aXNTdGFydFRhZzogYm9vbGVhbiwgaGFzS2V5OiBib29sZWFufSB7XG5cbiAgICBsZXQgc3RhcnRUYWdEYXRhID0gZmluZFN0YXJ0VGFnKHRleHQpO1xuICAgIGlmKHN0YXJ0VGFnRGF0YS5mb3VuZCA9PT0gdHJ1ZSkge1xuXG4gICAgICAgIGxldCBrZXkgPSBnZXRTdGFydFRhZ0tleSh0ZXh0KVxuICAgICAgICBpZihrZXkgPT09IG51bGwgfHwga2V5ID09PSBcIlwiKSB7XG4gICAgICAgICAgICByZXR1cm4ge2lzU3RhcnRUYWc6IHRydWUsIGhhc0tleTogZmFsc2V9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7aXNTdGFydFRhZzogdHJ1ZSwgaGFzS2V5OiB0cnVlfTtcbiAgICB9XG5cbiAgICByZXR1cm4ge2lzU3RhcnRUYWc6IGZhbHNlLCBoYXNLZXk6IGZhbHNlfTtcbn1cblxuY29uc3QgRU5EX1JFR0VYX1NUUlMgPSBbXCItLS0gKmVuZC1tdWx0aS1jb2x1bW5cIixcbiAgICAgICAgICAgICAgICAgICAgICAgIFwiLS0tICptdWx0aS1jb2x1bW4tZW5kXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBcIj09PSAqZW5kLW11bHRpLWNvbHVtblwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgXCI9PT0gKm11bHRpLWNvbHVtbi1lbmRcIl1cbmNvbnN0IEVORF9SRUdFWF9BUlI6IFJlZ0V4cFtdID0gW107XG5mb3IobGV0IGkgPSAwOyBpIDwgRU5EX1JFR0VYX1NUUlMubGVuZ3RoOyBpKyspIHtcbiAgICBFTkRfUkVHRVhfQVJSLnB1c2gobmV3IFJlZ0V4cChFTkRfUkVHRVhfU1RSU1tpXSkpO1xufVxuXG50eXBlIFRhZ1Bvc2l0aW9uaW5nRGF0YSA9IHtcbiAgICBmb3VuZDogYm9vbGVhbjtcbiAgICBzdGFydFBvc2l0aW9uOiBudW1iZXI7XG4gICAgZW5kUG9zaXRpb246IG51bWJlcjtcbiAgICBtYXRjaExlbmd0aDogbnVtYmVyO1xufTtcblxuZXhwb3J0IGZ1bmN0aW9uIGZpbmRFbmRUYWcodGV4dDogc3RyaW5nKTogVGFnUG9zaXRpb25pbmdEYXRhIHtcblxuICAgIC8vIFdlIHdhbnQgdG8gZmluZCB0aGUgZmlyc3QgZW5kIHRhZyBpbiB0aGUgdGV4dC5cbiAgICAvLyBTbyBoZXJlIHdlIGxvb3AgYmFja3dhcmRzLCBzbGljaW5nIG9mZiB0aGUgdGFpbCB1bnRpbFxuICAgIC8vIHRoZXJlIGFyZSBubyBtb3JlIGVuZCB0YWdzIGF2YWlsYWJsZVxuICAgIGxldCBsYXN0VmFsaWREYXRhID0gZ2V0RW5kVGFnRGF0YSh0ZXh0KTtcbiAgICBsZXQgd29ya2luZ1JlZ2V4RGF0YSA9IGxhc3RWYWxpZERhdGE7XG4gICAgd2hpbGUod29ya2luZ1JlZ2V4RGF0YS5mb3VuZCA9PT0gdHJ1ZSkge1xuXG4gICAgICAgIGxhc3RWYWxpZERhdGEgPSB3b3JraW5nUmVnZXhEYXRhO1xuICAgICAgICB0ZXh0ID0gdGV4dC5zbGljZSgwLCB3b3JraW5nUmVnZXhEYXRhLnN0YXJ0UG9zaXRpb24pO1xuICAgICAgICB3b3JraW5nUmVnZXhEYXRhID0gZ2V0RW5kVGFnRGF0YSh0ZXh0KTtcbiAgICB9XG5cbiAgICByZXR1cm4gbGFzdFZhbGlkRGF0YTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGZpbmRFbmRUYWdDbG9zZXN0VG9FbmQodGV4dDogc3RyaW5nKTogVGFnUG9zaXRpb25pbmdEYXRhIHtcblxuICAgIGxldCB3b3JraW5nVGV4dCA9IHRleHQ7XG4gICAgbGV0IG9mZnNldCA9IDA7XG5cbiAgICBsZXQgbGFzdFZhbGlkRGF0YSA9IGdldEVuZFRhZ0RhdGEod29ya2luZ1RleHQpO1xuICAgIHdoaWxlKGxhc3RWYWxpZERhdGEuZm91bmQpIHtcblxuICAgICAgICB3b3JraW5nVGV4dCA9IHdvcmtpbmdUZXh0LnNsaWNlKGxhc3RWYWxpZERhdGEuZW5kUG9zaXRpb24pO1xuICAgICAgICBsZXQgbmV3RGF0YSA9IGdldEVuZFRhZ0RhdGEod29ya2luZ1RleHQpO1xuICAgICAgICBpZihuZXdEYXRhLmZvdW5kID09PSBmYWxzZSkge1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgb2Zmc2V0ICs9IGxhc3RWYWxpZERhdGEuZW5kUG9zaXRpb247XG4gICAgICAgIGxhc3RWYWxpZERhdGEgPSBuZXdEYXRhO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAgIGZvdW5kOiBsYXN0VmFsaWREYXRhLmZvdW5kLFxuICAgICAgICBzdGFydFBvc2l0aW9uOiBsYXN0VmFsaWREYXRhLnN0YXJ0UG9zaXRpb24gKyBvZmZzZXQsXG4gICAgICAgIGVuZFBvc2l0aW9uOiBsYXN0VmFsaWREYXRhLmVuZFBvc2l0aW9uICsgb2Zmc2V0LFxuICAgICAgICBtYXRjaExlbmd0aDogbGFzdFZhbGlkRGF0YS5tYXRjaExlbmd0aFxuICAgIH07XG59XG5leHBvcnQgZnVuY3Rpb24gY29udGFpbnNFbmRUYWcodGV4dDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGZpbmRFbmRUYWcodGV4dCkuZm91bmRcbn1cblxuZnVuY3Rpb24gZ2V0RW5kVGFnRGF0YSh0ZXh0OiBzdHJpbmcpIHtcblxuICAgIGxldCBmb3VuZCA9IGZhbHNlO1xuICAgIGxldCBzdGFydFBvc2l0aW9uID0gLTE7XG4gICAgbGV0IGVuZFBvc2l0aW9uID0gLTFcbiAgICBsZXQgbWF0Y2hMZW5ndGggPSAwO1xuICAgIGZvcihsZXQgaSA9IDA7IGk8IEVORF9SRUdFWF9BUlIubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICBsZXQgcmVnZXhEYXRhID0gRU5EX1JFR0VYX0FSUltpXS5leGVjKHRleHQpXG4gICAgICAgIGlmKHJlZ2V4RGF0YSAhPT0gbnVsbCAmJiByZWdleERhdGEubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgZm91bmQgPSB0cnVlO1xuICAgICAgICAgICAgc3RhcnRQb3NpdGlvbiA9IHJlZ2V4RGF0YS5pbmRleFxuICAgICAgICAgICAgbWF0Y2hMZW5ndGggPSByZWdleERhdGFbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZW5kUG9zaXRpb24gPSBzdGFydFBvc2l0aW9uICsgbWF0Y2hMZW5ndGg7XG5cbiAgICByZXR1cm4geyBmb3VuZCwgc3RhcnRQb3NpdGlvbiwgZW5kUG9zaXRpb24sIG1hdGNoTGVuZ3RoIH07XG59XG5cbmNvbnN0IENPTF9SRUdFWF9TVFJTOiBbc3RyaW5nLHN0cmluZ11bXSA9IFtbXCJePT09XFxcXHMqP2NvbHVtbi1lbmRcXFxccyo/PT09XFxcXHMqPyRcIiAgICxcIlwiXSwgLy8gW1JlZ2V4LCBSZWdleCBGbGFnc11cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbXCJePT09XFxcXHMqP2VuZC1jb2x1bW5cXFxccyo/PT09XFxcXHMqPyRcIiAgICxcIlwiXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbXCJePT09XFxcXHMqP2NvbHVtbi1icmVha1xcXFxzKj89PT1cXFxccyo/JFwiICxcIlwiXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbXCJePT09XFxcXHMqP2JyZWFrLWNvbHVtblxcXFxzKj89PT1cXFxccyo/JFwiICxcIlwiXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbXCJeLS0tXFxcXHMqP2NvbHVtbi1lbmRcXFxccyo/LS0tXFxcXHMqPyRcIiAgICxcIlwiXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbXCJeLS0tXFxcXHMqP2VuZC1jb2x1bW5cXFxccyo/LS0tXFxcXHMqPyRcIiAgICxcIlwiXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbXCJeLS0tXFxcXHMqP2NvbHVtbi1icmVha1xcXFxzKj8tLS1cXFxccyo/JFwiICxcIlwiXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbXCJeLS0tXFxcXHMqP2JyZWFrLWNvbHVtblxcXFxzKj8tLS1cXFxccyo/JFwiICxcIlwiXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbXCJeICo/KD86XFxcXD8pXFxcXGNvbHVtbmJyZWFrICo/JFwiICAgICAgICAsXCJcIl0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW1wiXjp7Myx9ICpjb2x1bW4tP2JyZWFrICooPzooPzokXFxcXG5eKT98ICopOnszLH0gKiRcIiAsXCJtXCJdXTtcbmNvbnN0IENPTF9SRUdFWF9BUlI6IFJlZ0V4cFtdID0gW107XG5mb3IobGV0IGkgPSAwOyBpIDwgQ09MX1JFR0VYX1NUUlMubGVuZ3RoOyBpKyspIHtcbiAgICBDT0xfUkVHRVhfQVJSLnB1c2gobmV3IFJlZ0V4cChDT0xfUkVHRVhfU1RSU1tpXVswXSwgQ09MX1JFR0VYX1NUUlNbaV1bMV0pKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBjb250YWluc0NvbEVuZFRhZyh0ZXh0OiBzdHJpbmcpOiBib29sZWFuIHtcblxuICAgIGxldCBmb3VuZCA9IGZhbHNlO1xuICAgIGZvcihsZXQgaSA9IDA7IGk8IENPTF9SRUdFWF9BUlIubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICBpZihDT0xfUkVHRVhfQVJSW2ldLnRlc3QodGV4dCkpIHtcbiAgICAgICAgICAgIGZvdW5kID0gdHJ1ZTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZvdW5kO1xufVxuXG5jb25zdCBJTk5FUl9DT0xfRU5EX1JFR0VYX0FSUjogUmVnRXhwW10gPSBbXG4gICAgL14tezN9XFxzKj9jb2x1bW4tZW5kXFxzKj8tezN9XFxzKj8kXFxuPy9tLFxuICAgIC9eLXszfVxccyo/ZW5kLWNvbHVtblxccyo/LXszfVxccyo/JFxcbj8vbSxcbiAgICAvXi17M31cXHMqP2NvbHVtbi1icmVha1xccyo/LXszfVxccyo/JFxcbj8vbSxcbiAgICAvXi17M31cXHMqP2JyZWFrLWNvbHVtblxccyo/LXszfVxccyo/JFxcbj8vbSxcbiAgICAvXj17M31cXHMqP2NvbHVtbi1lbmRcXHMqPz17M31cXHMqPyRcXG4/L20sXG4gICAgL149ezN9XFxzKj9lbmQtY29sdW1uXFxzKj89ezN9XFxzKj8kXFxuPy9tLFxuICAgIC9ePXszfVxccyo/Y29sdW1uLWJyZWFrXFxzKj89ezN9XFxzKj8kXFxuPy9tLFxuICAgIC9ePXszfVxccyo/YnJlYWstY29sdW1uXFxzKj89ezN9XFxzKj8kXFxuPy9tLFxuICAgIC9eICo/KD86XFxcXD8pXFxcXGNvbHVtbmJyZWFrICo/JFxcbj8vbSxcbiAgICAvXjp7Myx9ICpjb2x1bW4tP2JyZWFrICooPzooPzokXFxuXik/fCAqKTp7Myx9ICokL21cbl1cbmV4cG9ydCBmdW5jdGlvbiBjaGVja0ZvclBhcmFncmFwaElubmVyQ29sRW5kVGFnKHRleHQ6IHN0cmluZyk6IFJlZ0V4cEV4ZWNBcnJheSB8IG51bGwge1xuXG4gICAgZm9yKGxldCBpID0gMDsgaTwgSU5ORVJfQ09MX0VORF9SRUdFWF9BUlIubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICBsZXQgcmVnZXhSZXN1bHQgPSBJTk5FUl9DT0xfRU5EX1JFR0VYX0FSUltpXS5leGVjKHRleHQpO1xuICAgICAgICBpZihyZWdleFJlc3VsdCkge1xuICAgICAgICAgICAgcmV0dXJuIHJlZ2V4UmVzdWx0O1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xufVxuXG5jb25zdCBDT0xfRUxFTUVOVF9JTk5FUl9URVhUX1JFR0VYX1NUUlM6IHN0cmluZ1tdID0gW1wiPSAqY29sdW1uLWVuZCAqPVwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiPSAqZW5kLWNvbHVtbiAqPVwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiPSAqY29sdW1uLWJyZWFrICo9XCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCI9ICpicmVhay1jb2x1bW4gKj1cIl1cbmNvbnN0IENPTF9FTEVNRU5UX0lOTkVSX1RFWFRfUkVHRVhfQVJSOiBSZWdFeHBbXSA9IFtdO1xuZm9yKGxldCBpID0gMDsgaSA8IENPTF9FTEVNRU5UX0lOTkVSX1RFWFRfUkVHRVhfU1RSUy5sZW5ndGg7IGkrKykge1xuICAgIENPTF9FTEVNRU5UX0lOTkVSX1RFWFRfUkVHRVhfQVJSLnB1c2gobmV3IFJlZ0V4cChDT0xfRUxFTUVOVF9JTk5FUl9URVhUX1JFR0VYX1NUUlNbaV0pKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBlbElubmVyVGV4dENvbnRhaW5zQ29sRW5kVGFnKHRleHQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuXG4gICAgbGV0IGZvdW5kID0gZmFsc2U7XG4gICAgZm9yKGxldCBpID0gMDsgaTwgQ09MX0VMRU1FTlRfSU5ORVJfVEVYVF9SRUdFWF9BUlIubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICBpZihDT0xfRUxFTUVOVF9JTk5FUl9URVhUX1JFR0VYX0FSUltpXS50ZXN0KHRleHQpKSB7XG4gICAgICAgICAgICBmb3VuZCA9IHRydWU7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmb3VuZDtcbn1cblxuY29uc3QgQ09MX1NFVFRJTkdTX1JFR0VYX1NUUlMgPSBbXCJgYGBzZXR0aW5nc1wiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJgYGBjb2x1bW4tc2V0dGluZ3NcIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiYGBgbXVsdGktY29sdW1uLXNldHRpbmdzXCJdO1xuY29uc3QgQ09MX1NFVFRJTkdTX1JFR0VYX0FSUjogUmVnRXhwW10gPSBbXTtcbmZvcihsZXQgaSA9IDA7IGkgPCBDT0xfU0VUVElOR1NfUkVHRVhfU1RSUy5sZW5ndGg7IGkrKykge1xuICAgIENPTF9TRVRUSU5HU19SRUdFWF9BUlIucHVzaChuZXcgUmVnRXhwKENPTF9TRVRUSU5HU19SRUdFWF9TVFJTW2ldKSk7XG59XG5leHBvcnQgZnVuY3Rpb24gY29udGFpbnNDb2xTZXR0aW5nc1RhZyh0ZXh0OiBzdHJpbmcpOiBib29sZWFuIHtcblxuICAgIGxldCBmb3VuZCA9IGZhbHNlO1xuICAgIGZvcihsZXQgaSA9IDA7IGk8IENPTF9TRVRUSU5HU19SRUdFWF9BUlIubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICBpZihDT0xfU0VUVElOR1NfUkVHRVhfQVJSW2ldLnRlc3QodGV4dCkpIHtcbiAgICAgICAgICAgIGZvdW5kID0gdHJ1ZTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZvdW5kO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZmluZFNldHRpbmdzQ29kZWJsb2NrKHRleHQ6IHN0cmluZyk6IFN0YXJ0VGFnUmVnZXhNYXRjaCB7XG5cbiAgICBsZXQgZm91bmQgPSBmYWxzZTtcbiAgICBsZXQgc3RhcnRQb3NpdGlvbiA9IC0xO1xuICAgIGxldCBlbmRQb3NpdGlvbiA9IC0xXG4gICAgbGV0IG1hdGNoTGVuZ3RoID0gMDtcbiAgICBmb3IobGV0IGkgPSAwOyBpPCBDT0xfU0VUVElOR1NfUkVHRVhfQVJSLmxlbmd0aDsgaSsrKSB7XG5cbiAgICAgICAgbGV0IHJlZ2V4RGF0YSA9IENPTF9TRVRUSU5HU19SRUdFWF9BUlJbaV0uZXhlYyh0ZXh0KVxuICAgICAgICBpZihyZWdleERhdGEgIT09IG51bGwgJiYgcmVnZXhEYXRhLmxlbmd0aCA+IDApIHtcblxuICAgICAgICAgICAgZm91bmQgPSB0cnVlO1xuICAgICAgICAgICAgc3RhcnRQb3NpdGlvbiA9IHJlZ2V4RGF0YS5pbmRleFxuICAgICAgICAgICAgbWF0Y2hMZW5ndGggPSByZWdleERhdGFbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgZW5kUG9zaXRpb24gPSBzdGFydFBvc2l0aW9uICsgbWF0Y2hMZW5ndGg7XG5cbiAgICAgICAgICAgIGxldCByZW1haW5pbmdUZXh0ID0gdGV4dC5zbGljZShlbmRQb3NpdGlvbilcbiAgICAgICAgICAgIHJlZ2V4RGF0YSA9IENPREVCTE9DS19FTkRfUkVHRVguZXhlYyhyZW1haW5pbmdUZXh0KVxuICAgICAgICAgICAgaWYocmVnZXhEYXRhICE9PSBudWxsICYmIHJlZ2V4RGF0YS5sZW5ndGggPiAwKSB7XG5cbiAgICAgICAgICAgICAgICBmb3VuZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgZW5kUG9zaXRpb24gKz0gcmVnZXhEYXRhLmluZGV4ICsgcmVnZXhEYXRhWzBdLmxlbmd0aCBcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHsgXG4gICAgICAgIGZvdW5kLCBcbiAgICAgICAgc3RhcnRQb3NpdGlvbiwgXG4gICAgICAgIGVuZFBvc2l0aW9uLCBcbiAgICAgICAgbWF0Y2hMZW5ndGgsXG4gICAgICAgIHJlZ2lvblR5cGU6IFwiQ09ERUJMT0NLXCJcbiAgICB9O1xufVxuXG5jb25zdCBDT0RFQkxPQ0tfU1RBUlRfUkVHRVhfU1RSOiBzdHJpbmcgPSBbXG5cIm11bHRpLWNvbHVtbi1zdGFydFwiLFxuXCJzdGFydC1tdWx0aS1jb2x1bW5cIlxuXS5yZWR1Y2UoKHByZXYsIGN1cikgPT4ge1xuICAgIGlmKHByZXYgPT09IFwiXCIpIHtcbiAgICAgICAgcmV0dXJuIGN1cjtcbiAgICB9XG4gICAgcmV0dXJuIGAke3ByZXZ9fCR7Y3VyfWA7XG59LCBcIlwiKVxuY29uc3QgU1RBUlRfQ09ERUJMT0NLX1JFR0VYOiBSZWdFeHAgPSBuZXcgUmVnRXhwKGBcXGBcXGBcXGAoOj8ke0NPREVCTE9DS19TVEFSVF9SRUdFWF9TVFJ9KSguKj8pXFxgXFxgXFxgYCwgXCJtc1wiKTtcblxuZXhwb3J0IGZ1bmN0aW9uIGZpbmRTdGFydENvZGVibG9jayh0ZXh0OiBzdHJpbmcpOiBTdGFydFRhZ1JlZ2V4TWF0Y2gge1xuXG4gICAgbGV0IHN0YXJ0UmVnaW9uID0gZGVmYXVsdFN0YXJ0UmVnaW9uRGF0YSgpO1xuICAgIHN0YXJ0UmVnaW9uLnJlZ2lvblR5cGUgPSBcIkNPREVCTE9DS1wiO1xuXG4gICAgbGV0IHJlZ2V4RGF0YSA9IFNUQVJUX0NPREVCTE9DS19SRUdFWC5leGVjKHRleHQpXG4gICAgaWYocmVnZXhEYXRhICE9PSBudWxsICYmIHJlZ2V4RGF0YS5sZW5ndGggPiAwKSB7XG5cbiAgICAgICAgc3RhcnRSZWdpb24uZm91bmQgPSB0cnVlO1xuICAgICAgICBzdGFydFJlZ2lvbi5zdGFydFBvc2l0aW9uID0gcmVnZXhEYXRhLmluZGV4XG4gICAgICAgIHN0YXJ0UmVnaW9uLm1hdGNoTGVuZ3RoID0gcmVnZXhEYXRhWzBdLmxlbmd0aDtcbiAgICAgICAgc3RhcnRSZWdpb24uZW5kUG9zaXRpb24gPSBzdGFydFJlZ2lvbi5zdGFydFBvc2l0aW9uICsgc3RhcnRSZWdpb24ubWF0Y2hMZW5ndGg7XG4gICAgfVxuXG4gICAgcmV0dXJuIHN0YXJ0UmVnaW9uO1xufVxuZXhwb3J0IGZ1bmN0aW9uIGNvbnRhaW5zU3RhcnRDb2RlQmxvY2sodGV4dDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGZpbmRTdGFydENvZGVibG9jayh0ZXh0KS5mb3VuZFxufVxuXG5leHBvcnQgZnVuY3Rpb24gY29udGFpbnNSZWdpb25TdGFydCh0ZXh0OiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gY29udGFpbnNTdGFydENvZGVCbG9jayh0ZXh0KSB8fCBjb250YWluc1N0YXJ0VGFnKHRleHQpIHx8IGNvbnRhaW5zUGFuZG9jKHRleHQpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY291bnRTdGFydFRhZ3MoaW5pdGlhbFRleHQ6IHN0cmluZyk6IHsgbnVtYmVyT2ZUYWdzOiBudW1iZXIsIGtleXM6IHN0cmluZ1tdIH0ge1xuXG4gICAgbGV0IGtleXM6IHN0cmluZ1tdID0gW107XG4gICAgbGV0IHRleHQgPSBpbml0aWFsVGV4dFxuICAgIGxldCBzdGFydFRhZ0RhdGEgPSBmaW5kU3RhcnRUYWcodGV4dCk7XG4gICAgd2hpbGUoc3RhcnRUYWdEYXRhLmZvdW5kKSB7XG4gICAgICAgIFxuICAgICAgICAvLyBTbGljZSBvZmYgZXZlcnl0aGluZyBiZWZvcmUgdGhlIHRhZ1xuICAgICAgICB0ZXh0ID0gdGV4dC5zbGljZShzdGFydFRhZ0RhdGEuc3RhcnRQb3NpdGlvbik7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEdldCBqdXN0IHRoZSBzdGFydCB0YWcgbGluZSBhbmQgdGhlbiBzZXQgdGV4dCB0byBldmVyeXRoaW5nIGp1c3RcbiAgICAgICAgICogYWZ0ZXIgdGhlIHN0YXJ0IHRhZy5cbiAgICAgICAgICovXG4gICAgICAgIGxldCB0YWcgPSB0ZXh0LnNwbGl0KFwiXFxuXCIpWzBdO1xuICAgICAgICB0ZXh0ID0gdGV4dC5zbGljZSgxKTsgLy8gVGhpcyBtb3ZlcyB0aGUgdGV4dCAxIGNoYXJhY3RlciBzbyB3ZSBkb250IG1hdGNoIHRoZSBzYW1lIHRhZy5cblxuICAgICAgICAvLyBQYXJzZSBvdXQgdGhlIGtleSBhbmQgYXBwZW5kIHRvIHRoZSBsaXN0LlxuICAgICAgICBsZXQga2V5ID0gZ2V0U3RhcnRUYWdLZXkodGFnKTtcbiAgICAgICAgaWYoa2V5ID09PSBudWxsKSB7XG4gICAgICAgICAgICBrZXkgPSBcIlwiXG4gICAgICAgIH1cbiAgICAgICAga2V5cy5wdXNoKGtleSk7XG5cbiAgICAgICAgLy8gU2VhcmNoIGFnYWluIGZvciBhbm90aGVyIHRhZyBiZWZvcmUgbG9vcGluZy5cbiAgICAgICAgc3RhcnRUYWdEYXRhID0gZmluZFN0YXJ0VGFnKHRleHQpO1xuICAgIH1cblxuICAgIHRleHQgPSBpbml0aWFsVGV4dDtcbiAgICBzdGFydFRhZ0RhdGEgPSBmaW5kU3RhcnRDb2RlYmxvY2sodGV4dCk7XG4gICAgd2hpbGUoc3RhcnRUYWdEYXRhLmZvdW5kKSB7XG4gICAgICAgIFxuICAgICAgICBsZXQgc2V0dGluZ3NUZXh0ID0gdGV4dC5zbGljZShzdGFydFRhZ0RhdGEuc3RhcnRQb3NpdGlvbiwgc3RhcnRUYWdEYXRhLmVuZFBvc2l0aW9uKTtcbiAgICAgICAgdGV4dCA9IHRleHQuc2xpY2Uoc3RhcnRUYWdEYXRhLmVuZFBvc2l0aW9uKTtcblxuICAgICAgICBsZXQga2V5ID0gcGFyc2VTdGFydFJlZ2lvbkNvZGVCbG9ja0lEKHNldHRpbmdzVGV4dCk7XG4gICAgICAgIGlmKGtleSA9PT0gbnVsbCkge1xuICAgICAgICAgICAga2V5ID0gXCJcIlxuICAgICAgICB9XG4gICAgICAgIGtleXMucHVzaChrZXkpO1xuXG4gICAgICAgIC8vIFNlYXJjaCBhZ2FpbiBmb3IgYW5vdGhlciB0YWcgYmVmb3JlIGxvb3BpbmcuXG4gICAgICAgIHN0YXJ0VGFnRGF0YSA9IGZpbmRTdGFydENvZGVibG9jayh0ZXh0KTtcbiAgICB9XG5cbiAgICByZXR1cm4geyBudW1iZXJPZlRhZ3M6IGtleXMubGVuZ3RoLCBrZXlzIH07XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3RhcnRUYWdEYXRhIHtcbiAgICBzdGFydEJsb2NrS2V5OiBzdHJpbmc7XG4gICAgbGluZXNBYm92ZUFycmF5OiBzdHJpbmdbXTtcbiAgICBzdGFydEJsb2NrVHlwZTogUmVnaW9uVHlwZTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBnZXRTdGFydERhdGFBYm92ZUxpbmUobGluZXNBYm92ZUFycmF5OiBzdHJpbmdbXSk6IFN0YXJ0VGFnRGF0YSB7XG4gICAgcmV0dXJuIGdldFN0YXJ0QmxvY2tPckNvZGVibG9ja0Fib3ZlTGluZShsaW5lc0Fib3ZlQXJyYXksIFtcbiAgICAgICAgZmluZFN0YXJ0VGFnLFxuICAgICAgICBmaW5kU3RhcnRDb2RlYmxvY2ssXG4gICAgICAgIGZpbmRQYW5kb2NTdGFydFxuICAgIF0pXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRTdGFydEJsb2NrT3JDb2RlYmxvY2tBYm92ZUxpbmUobGluZXNBYm92ZUFycmF5OiBzdHJpbmdbXSwgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlYXJjaEZ1bmN0aW9uczogKCh0ZXh0OiBzdHJpbmcpID0+IFN0YXJ0VGFnUmVnZXhNYXRjaClbXSk6IHsgc3RhcnRCbG9ja0tleTogc3RyaW5nLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5lc0Fib3ZlQXJyYXk6IHN0cmluZ1tdLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXJ0QmxvY2tUeXBlOiBSZWdpb25UeXBlICB9IHwgbnVsbCB7XG5cbiAgICBsZXQgb3JpZ2luYWxUZXh0ID0gbGluZXNBYm92ZUFycmF5LmpvaW4oXCJcXG5cIik7XG4gICAgbGV0IHt0YWdNYXRjaERhdGEsIGxhc3RGb3VuZFRhZywgdGV4dEFib3ZlfSA9ICBmaW5kTGFzdFZhbGlkVGFnKG9yaWdpbmFsVGV4dCk7XG5cbiAgICBpZih0YWdNYXRjaERhdGEgPT09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgaWYodGFnTWF0Y2hEYXRhLmZvdW5kID09PSBmYWxzZSkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBpZih0YWdNYXRjaERhdGEucmVnaW9uVHlwZSA9PT0gXCJDT0RFQkxPQ0tcIikge1xuICAgIFxuICAgICAgICBsZXQgZW5kVGFnU2VyYWNoRGF0YSA9IGZpbmRFbmRUYWcodGV4dEFib3ZlKTtcbiAgICAgICAgaWYoZW5kVGFnU2VyYWNoRGF0YS5mb3VuZCA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgc3RhcnRCbG9ja0tleSA9IHBhcnNlU3RhcnRSZWdpb25Db2RlQmxvY2tJRChsYXN0Rm91bmRUYWcpO1xuICAgICAgICBsZXQgbGluZXNBYm92ZUFycmF5ID0gdGV4dEFib3ZlLnNwbGl0KFwiXFxuXCIpO1xuXG4gICAgICAgIHJldHVybiB7IHN0YXJ0QmxvY2tLZXksIGxpbmVzQWJvdmVBcnJheSwgc3RhcnRCbG9ja1R5cGU6IFwiQ09ERUJMT0NLXCIgfTtcbiAgICB9XG5cbiAgICBpZih0YWdNYXRjaERhdGEucmVnaW9uVHlwZSA9PT0gXCJPUklHSU5BTFwiKSB7XG4gICAgXG4gICAgICAgIGxldCBlbmRUYWdTZXJhY2hEYXRhID0gZmluZEVuZFRhZyh0ZXh0QWJvdmUpO1xuICAgICAgICBpZihlbmRUYWdTZXJhY2hEYXRhLmZvdW5kID09PSB0cnVlKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBsaW5lc0Fib3ZlQXJyYXkgPSB0ZXh0QWJvdmUuc3BsaXQoXCJcXG5cIik7XG4gICAgICAgIGxldCBzdGFydEJsb2NrS2V5ID0gZ2V0U3RhcnRUYWdLZXkobGFzdEZvdW5kVGFnKTtcblxuICAgICAgICBsZXQgY29kZUJsb2NrRGF0YSA9IHBhcnNlQ29kZUJsb2NrU3RhcnQobGluZXNBYm92ZUFycmF5KVxuICAgICAgICBpZihjb2RlQmxvY2tEYXRhICE9PSBudWxsKSB7XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIHN0YXJ0QmxvY2tLZXkgPSBjb2RlQmxvY2tEYXRhLmlkO1xuICAgICAgICAgICAgaWYoY29kZUJsb2NrRGF0YS5pbmRleCA+IDApIHtcbiAgICAgICAgICAgICAgICBsaW5lc0Fib3ZlQXJyYXkgPSBsaW5lc0Fib3ZlQXJyYXkuc2xpY2UoY29kZUJsb2NrRGF0YS5pbmRleCArIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYoc3RhcnRCbG9ja0tleSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgc3RhcnRCbG9ja0tleSA9IFwiXCI7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4geyBzdGFydEJsb2NrS2V5LCBsaW5lc0Fib3ZlQXJyYXksIHN0YXJ0QmxvY2tUeXBlOiBcIk9SSUdJTkFMXCIgfTtcbiAgICB9XG5cbiAgICBpZih0YWdNYXRjaERhdGEucmVnaW9uVHlwZSA9PT0gXCJQQURPQ1wiKSB7XG5cbiAgICAgICAgbGV0IGVuZFRhZ1NlcmFjaERhdGEgPSByZWR1Y2VQYW5kb2NSZWdpb25Ub0VuZERpdih0ZXh0QWJvdmUpXG4gICAgICAgIGlmKGVuZFRhZ1NlcmFjaERhdGEuZm91bmQgPT09IHRydWUpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGxpbmVzQWJvdmVBcnJheSA9IHRleHRBYm92ZS5zcGxpdChcIlxcblwiKTtcblxuICAgICAgICBsZXQgcGFuZG9jRGF0YSA9IGdldFBhbmRvY1N0YXJ0RGF0YShgJHtsYXN0Rm91bmRUYWd9YCk7XG4gICAgICAgIGxldCBzdGFydEJsb2NrS2V5ID0gcGFuZG9jRGF0YS51c2VyU2V0dGluZ3MuY29sdW1uSUQ7XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHN0YXJ0QmxvY2tLZXksXG4gICAgICAgICAgICBsaW5lc0Fib3ZlQXJyYXksXG4gICAgICAgICAgICBzdGFydEJsb2NrVHlwZTogXCJQQURPQ1wiXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcblxuICAgIGZ1bmN0aW9uIGZpbmRMYXN0VmFsaWRUYWcob3JpZ2luYWxUZXh0OiBzdHJpbmcpIHtcblxuICAgICAgICBsZXQgdGV4dEFib3ZlID0gb3JpZ2luYWxUZXh0O1xuICAgICAgICBsZXQgb2Zmc2V0ID0gMDtcbiAgICAgICAgbGV0IHRhZ01hdGNoRGF0YTogU3RhcnRUYWdSZWdleE1hdGNoID0gbnVsbDtcbiAgICAgICAgbGV0IGxhc3RGb3VuZFRhZyA9IFwiXCJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IHRydWU7IGkrKykge1xuICAgICAgICAgICAgaWYgKGkgPiAxMDApIHtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbGV0IHRhZ3NGb3VuZDogU3RhcnRUYWdSZWdleE1hdGNoW10gPSBbXTtcbiAgICAgICAgICAgIHNlYXJjaEZ1bmN0aW9ucy5mb3JFYWNoKChmdW5jKSA9PiB7XG4gICAgICAgICAgICAgICAgdGFnc0ZvdW5kLnB1c2goZnVuYyh0ZXh0QWJvdmUpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGFnc0ZvdW5kID0gdGFnc0ZvdW5kLmZpbHRlcigodmFsKSA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHZhbC5mb3VuZCA9PT0gdHJ1ZTtcbiAgICAgICAgICAgIH0pLnNvcnQoKGEsIGIpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYS5zdGFydFBvc2l0aW9uIC0gYi5zdGFydFBvc2l0aW9uO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGlmICh0YWdzRm91bmQubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRhZ01hdGNoRGF0YSA9IHRhZ3NGb3VuZFswXTtcbiAgICAgICAgICAgIGxldCBzdGFydEluZGV4ID0gb2Zmc2V0ICsgdGFnTWF0Y2hEYXRhLnN0YXJ0UG9zaXRpb247XG4gICAgICAgICAgICBsYXN0Rm91bmRUYWcgPSBvcmlnaW5hbFRleHQuc2xpY2Uoc3RhcnRJbmRleCwgc3RhcnRJbmRleCArIHRhZ01hdGNoRGF0YS5tYXRjaExlbmd0aCkudHJpbUVuZCgpO1xuXG4gICAgICAgICAgICBvZmZzZXQgKz0gKHRhZ01hdGNoRGF0YS5zdGFydFBvc2l0aW9uICsgdGFnTWF0Y2hEYXRhLm1hdGNoTGVuZ3RoKTtcbiAgICAgICAgICAgIHRleHRBYm92ZSA9IG9yaWdpbmFsVGV4dC5zbGljZShvZmZzZXQpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHRhZ01hdGNoRGF0YSxcbiAgICAgICAgICAgIGxhc3RGb3VuZFRhZyxcbiAgICAgICAgICAgIHRleHRBYm92ZVxuICAgICAgICB9XG4gICAgfVxufVxuXG4vKipcbiAqIFRoaXMgZnVuY3Rpb24gd2lsbCBmaWx0ZXIgYSBzZXQgb2Ygc3RyaW5ncywgcmV0dXJuaW5nIGFsbCBpdGVtcyBzdGFydGluZ1xuICogZnJvbSB0aGUgY2xvc2VzdCBvcGVuIHN0YXJ0IHRhZyB0aHJvdWdoIHRoZSBsYXN0IGl0ZW0gaW4gdGhlIHNldC4gXG4gKiBcbiAqIFRoZSBmdW5jdGlvbiBmaWx0ZXJzIG91dCBhbGwgZW5kIHRhZ3MgdG8gbWFrZSBzdXJlIHRoYXQgdGhlIHN0YXJ0IHRhZyB3ZSBcbiAqIGZpbmQgaXMgdGhlIHByb3BlciBzdGFydCB0YWcgZm9yIHRoZSBsaXN0IHNlbnQuIFxuICogQHBhcmFtIGxpbmVzQWJvdmVBcnJheSBcbiAqIEByZXR1cm5zIFxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0U3RhcnRCbG9ja0Fib3ZlTGluZShsaW5lc0Fib3ZlQXJyYXk6IHN0cmluZ1tdKTogeyBzdGFydEJsb2NrS2V5OiBzdHJpbmcsIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5lc0Fib3ZlQXJyYXk6IHN0cmluZ1tdIH0gfCBudWxsIHtcblxuICAgIHJldHVybiBnZXRTdGFydEJsb2NrT3JDb2RlYmxvY2tBYm92ZUxpbmUobGluZXNBYm92ZUFycmF5LCBbZmluZFN0YXJ0VGFnXSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRFbmRCbG9ja0JlbG93KGxpbmVzQmVsb3c6IHN0cmluZ1tdKTogc3RyaW5nW10ge1xuXG4gICAgLy8gUmVkdWNlIHRoZSBhcnJheSBkb3duIGludG8gYSBzaW5nbGUgc3RyaW5nIHNvIHRoYXQgd2UgY2FuXG4gICAgLy8gZWFzaWx5IFJlZ0V4IG92ZXIgdGhlIHN0cmluZyBhbmQgZmluZCB0aGUgaW5kaWNpZXMgd2UncmUgbG9va2luZyBmb3IuXG4gICAgbGV0IGxpbmVzQmVsb3dTdHIgPSBsaW5lc0JlbG93LnJlZHVjZSgocHJldiwgY3VycmVudCkgPT4ge1xuICAgICAgICByZXR1cm4gcHJldiArIFwiXFxuXCIgICsgY3VycmVudDtcbiAgICB9LCBcIlwiKTtcbiAgICBsZXQgZW5kVGFnU2VyYWNoRGF0YSA9IGZpbmRFbmRUYWcobGluZXNCZWxvd1N0cik7XG4gICAgbGV0IHN0YXJ0VGFnU2VhcmNoRGF0YSA9IGZpbmRTdGFydFRhZyhsaW5lc0JlbG93U3RyKTtcblxuICAgIGxldCBzbGljZUVuZEluZGV4ID0gLTE7IC8vIElmIG5laXRoZXIgc3RhcnQgb3IgZW5kIGZvdW5kIHdlIHJldHVybiB0aGUgZW50aXJlIGFycmF5LlxuICAgIGlmKGVuZFRhZ1NlcmFjaERhdGEuZm91bmQgPT09IHRydWUgJiYgc3RhcnRUYWdTZWFyY2hEYXRhLmZvdW5kID09PSBmYWxzZSkge1xuXG4gICAgICAgIHNsaWNlRW5kSW5kZXggPSBlbmRUYWdTZXJhY2hEYXRhLnN0YXJ0UG9zaXRpb247XG4gICAgfVxuICAgIGVsc2UgaWYoZW5kVGFnU2VyYWNoRGF0YS5mb3VuZCA9PT0gZmFsc2UgJiYgc3RhcnRUYWdTZWFyY2hEYXRhLmZvdW5kID09PSB0cnVlKSB7XG5cbiAgICAgICAgc2xpY2VFbmRJbmRleCA9IHN0YXJ0VGFnU2VhcmNoRGF0YS5zdGFydFBvc2l0aW9uO1xuICAgIH1cbiAgICBlbHNlIGlmKGVuZFRhZ1NlcmFjaERhdGEuZm91bmQgPT09IHRydWUgJiYgc3RhcnRUYWdTZWFyY2hEYXRhLmZvdW5kID09PSB0cnVlKSB7XG5cbiAgICAgICAgc2xpY2VFbmRJbmRleCA9IGVuZFRhZ1NlcmFjaERhdGEuc3RhcnRQb3NpdGlvbjtcbiAgICAgICAgaWYoc3RhcnRUYWdTZWFyY2hEYXRhLnN0YXJ0UG9zaXRpb24gPCBlbmRUYWdTZXJhY2hEYXRhLnN0YXJ0UG9zaXRpb24pIHtcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBJZiB3ZSBmb3VuZCBhIHN0YXJ0IHRhZyBiZWZvcmUgYW4gZW5kIHRhZyB3ZSB3YW50IHRvIHVzZSB0aGUgc3RhcnQgdGFnXG4gICAgICAgICAgICAgKiBvdXIgY3VycmVudCBibG9jayBpcyBub3QgcHJvcGVybHkgZW5kZWQgYW5kIHdlIHVzZSB0aGUgbmV4dCBzdGFydCB0YWcgXG4gICAgICAgICAgICAgKiBhcyBvdXIgbGltaXRcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgc2xpY2VFbmRJbmRleCA9IHN0YXJ0VGFnU2VhcmNoRGF0YS5zdGFydFBvc2l0aW9uO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGxpbmVzQmVsb3cuc2xpY2UoMCwgc2xpY2VFbmRJbmRleCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRTdGFydFRhZ0tleShzdGFydFRhZzogc3RyaW5nKTogc3RyaW5nIHwgbnVsbCB7XG5cbiAgICBsZXQga2V5U3BsaXQgPSBzdGFydFRhZy5zcGxpdChcIjpcIik7XG4gICAgaWYoa2V5U3BsaXQubGVuZ3RoID4gMSl7XG4gICAgICAgIHJldHVybiBrZXlTcGxpdFsxXS5yZXBsYWNlKFwiIFwiLCBcIlwiKVxuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xufVxuXG5cbmNvbnN0IFRBQl9IRUFERVJfRU5EX1JFR0VYX1NUUiA9IFwiXmBgYCRcIjtcbmNvbnN0IFRBQl9IRUFERVJfRU5EX1JFR0VYOiBSZWdFeHAgPSBuZXcgUmVnRXhwKFRBQl9IRUFERVJfRU5EX1JFR0VYX1NUUik7XG5leHBvcnQgZnVuY3Rpb24gcGFyc2VDb2RlQmxvY2tTdGFydChjb2RlQmxvY2tMaW5lczogc3RyaW5nW10pOiB7IGlkOiBzdHJpbmcsIGluZGV4OiBudW1iZXJ9IHwgbnVsbCB7XG5cbiAgICBsZXQgaWQgPSBudWxsO1xuICAgIGZvcihsZXQgaSA9IDA7IGkgPCBjb2RlQmxvY2tMaW5lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBsZXQgbGluZSA9IGNvZGVCbG9ja0xpbmVzW2ldO1xuXG4gICAgICAgIGlmKGlkID09PSBudWxsKSB7XG4gICAgICAgICAgICBsZXQga2V5ID0gbGluZS5zcGxpdChcIjpcIilbMF07XG4gICAgICAgICAgICBpZihrZXkudG9Mb3dlckNhc2UoKSA9PT0gXCJyZWdpb24gaWRcIikge1xuICAgICAgICAgICAgICAgIGlkID0gbGluZS5zcGxpdChcIjpcIilbMV0udHJpbSgpXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBpZihUQUJfSEVBREVSX0VORF9SRUdFWC50ZXN0KGxpbmUpKSB7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4geyBpZDogaWQsIGluZGV4OiBpIH07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZihpZCA9PT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHJldHVybiB7IGlkOiBpZCwgaW5kZXg6IC0xIH1cbiAgICB9XG59XG5jb25zdCBDT0RFQkxPQ0tfRU5EX1JFR0VYX1NUUiA9IFwiYGBgXCI7XG5jb25zdCBDT0RFQkxPQ0tfRU5EX1JFR0VYOiBSZWdFeHAgPSBuZXcgUmVnRXhwKENPREVCTE9DS19FTkRfUkVHRVhfU1RSKTtcbmV4cG9ydCBmdW5jdGlvbiBmaW5kRW5kT2ZDb2RlQmxvY2sodGV4dDogc3RyaW5nKTogeyBmb3VuZDogYm9vbGVhbiwgc3RhcnRQb3NpdGlvbjogbnVtYmVyLCBlbmRQb3NpdGlvbjogbnVtYmVyLCBtYXRjaExlbmd0aDogbnVtYmVyIH0ge1xuXG4gICAgbGV0IGZvdW5kID0gZmFsc2U7XG4gICAgbGV0IHN0YXJ0UG9zaXRpb24gPSAtMTtcbiAgICBsZXQgbWF0Y2hMZW5ndGggPSAwO1xuICAgIGxldCBlbmRQb3NpdGlvbiA9IC0xO1xuXG4gICAgbGV0IHJlZ2V4RGF0YSA9IENPREVCTE9DS19FTkRfUkVHRVguZXhlYyh0ZXh0KVxuICAgIGlmKHJlZ2V4RGF0YSAhPT0gbnVsbCAmJiByZWdleERhdGEubGVuZ3RoID4gMCkge1xuICAgICAgICBmb3VuZCA9IHRydWU7XG4gICAgICAgIHN0YXJ0UG9zaXRpb24gPSByZWdleERhdGEuaW5kZXhcbiAgICAgICAgbWF0Y2hMZW5ndGggPSByZWdleERhdGFbMF0ubGVuZ3RoXG4gICAgfVxuICAgIGVuZFBvc2l0aW9uID0gc3RhcnRQb3NpdGlvbiArIG1hdGNoTGVuZ3RoO1xuXG4gICAgcmV0dXJuIHsgZm91bmQsIHN0YXJ0UG9zaXRpb24sIGVuZFBvc2l0aW9uLCBtYXRjaExlbmd0aCB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VDb2RlQmxvY2tTZXR0aW5ncyhjb2RlQmxvY2tMaW5lczogc3RyaW5nW10pOiBzdHJpbmcge1xuXG4gICAgbGV0IHNldHRpbmdzTGluZXMgPSBbXTtcbiAgICBmb3IobGV0IGkgPSAwOyBpIDwgY29kZUJsb2NrTGluZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgbGV0IGxpbmUgPSBjb2RlQmxvY2tMaW5lc1tpXTtcblxuICAgICAgICBsZXQga2V5ID0gbGluZS5zcGxpdChcIjpcIilbMF07XG4gICAgICAgIGlmKGtleS50b0xvd2VyQ2FzZSgpICE9PSBcInJlZ2lvbiBpZFwiKSB7XG4gICAgICAgICAgICBzZXR0aW5nc0xpbmVzLnB1c2gobGluZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gc2V0dGluZ3NMaW5lcy5qb2luKFwiXFxuXCIpO1xufSIsIi8qXG4gKiBGaWxlbmFtZTogbXVsdGktY29sdW1uLW1hcmtkb3duL3NyYy91dGlsaXRpZXMvdXRpbHMudHNcbiAqIENyZWF0ZWQgRGF0ZTogVHVlc2RheSwgSmFudWFyeSAzMHRoIDIwMjIsIDQ6MDI6MTkgcG1cbiAqIEF1dGhvcjogQ2FtZXJvbiBSb2JpbnNvblxuICogXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjIgQ2FtZXJvbiBSb2JpbnNvblxuICovXG5cbmltcG9ydCB7IFdvcmtzcGFjZUxlYWYgfSBmcm9tIFwib2JzaWRpYW5cIjtcblxuZXhwb3J0IGZ1bmN0aW9uIGdldFVJRChsZW5ndGg6IG51bWJlciA9IDEwKTogc3RyaW5nIHtcblxuICAgIGlmKGxlbmd0aCA+IDEwKSB7XG4gICAgICAgIGxlbmd0aCA9IDEwO1xuICAgIH1cbiAgICBsZXQgVUlEID0gTWF0aC5yYW5kb20oKS50b1N0cmluZygzNikuc3Vic3RyaW5nKDIpO1xuICAgIFVJRCA9IFVJRC5zbGljZSgwLCBsZW5ndGgpO1xuICAgIFxuICAgIHJldHVybiBVSUQ7XG59XG5cbi8qKlxuICogQkZTIG9uIHRoZSBjaGlsZCBub2RlcyBvZiB0aGUgcGFzc2VkIGVsZW1lbnQgc2VhcmNoaW5nIGZvciB0aGUgZmlyc3QgaW5zdGFuY2Ugb2YgdGhlXG4gKiBub2RlIHR5cGUgcGFzc2VkLiBSZXR1cm5pbmcgdGhlIGVsZW1lbnQgZm91bmQgb3IgbnVsbCBpZiBub25lIGZvdW5kLlxuICogXG4gKiBAcGFyYW0gcm9vdCBcbiAqIEBwYXJhbSBub2RlVHlwZU5hbWVcbiAqIEByZXR1cm5zIFxuICovXG5leHBvcnQgZnVuY3Rpb24gc2VhcmNoQ2hpbGRyZW5Gb3JOb2RlVHlwZShyb290OiBIVE1MRWxlbWVudCwgbm9kZVR5cGVOYW1lOiBzdHJpbmcpOiBIVE1MRWxlbWVudCB8IG51bGwge1xuXG4gICAgbm9kZVR5cGVOYW1lID0gbm9kZVR5cGVOYW1lLnRvTG93ZXJDYXNlKCk7XG4gICAgbGV0IHF1ZXVlOiBIVE1MRWxlbWVudFtdID0gW3Jvb3RdXG4gICAgd2hpbGUocXVldWUubGVuZ3RoID4gMCl7XG4gICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCBxdWV1ZS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgXG4gICAgICAgICAgICBsZXQgbm9kZSA9IHF1ZXVlLnNoaWZ0KClcblxuICAgICAgICAgICAgbGV0IG5vZGVOYW1lID0gbm9kZS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpXG4gICAgICAgICAgICBpZihub2RlTmFtZSA9PT0gbm9kZVR5cGVOYW1lKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5vZGUgYXMgSFRNTEVsZW1lbnQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCBub2RlLmNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgcXVldWUucHVzaChub2RlLmNoaWxkcmVuW2ldIGFzIEhUTUxFbGVtZW50KVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzZWFyY2hDaGlsZHJlbkZvck5vZGVzT2ZUeXBlKHJvb3Q6IEhUTUxFbGVtZW50LCBub2RlVHlwZU5hbWU6IHN0cmluZywgcGFyZW50Q2xhc3M6IHN0cmluZyk6IEhUTUxFbGVtZW50W10gfCBudWxsIHtcbiAgICBsZXQgZWxGb3VuZCA9IHNlYXJjaENoaWxkcmVuRm9yTm9kZVR5cGUocm9vdCwgbm9kZVR5cGVOYW1lKVxuICAgIGlmKGVsRm91bmQgIT09IG51bGwpIHtcblxuICAgICAgICBsZXQgY3VycmVudFBhcmVudCA9IGVsRm91bmQucGFyZW50RWxlbWVudDtcbiAgICAgICAgd2hpbGUoY3VycmVudFBhcmVudCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgaWYoY3VycmVudFBhcmVudC5oYXNDbGFzcyhwYXJlbnRDbGFzcykpIHtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGN1cnJlbnRQYXJlbnQgPSBjdXJyZW50UGFyZW50LnBhcmVudEVsZW1lbnRcbiAgICAgICAgfVxuICAgICAgICBpZihjdXJyZW50UGFyZW50ID09PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbFxuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGNhbnZhc2VzOiBIVE1MRWxlbWVudFtdID0gW107XG4gICAgICAgIGZvcihsZXQgY2hpbGQgb2YgQXJyYXkuZnJvbShjdXJyZW50UGFyZW50LmNoaWxkcmVuKSkge1xuICAgICAgICAgICAgXG4gICAgICAgICAgICBsZXQgY2FudmFzID0gc2VhcmNoQ2hpbGRyZW5Gb3JOb2RlVHlwZShjaGlsZCBhcyBIVE1MRWxlbWVudCwgbm9kZVR5cGVOYW1lKVxuICAgICAgICAgICAgaWYoY2FudmFzICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgY2FudmFzZXMucHVzaChjYW52YXMpXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYoY2FudmFzZXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgcmV0dXJuIGNhbnZhc2VzXG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRGaWxlU291cmNlTW9kZShzb3VyY2VQYXRoOiBzdHJpbmcpOiBzdHJpbmcge1xuXG4gICAgbGV0IGZpbGVMZWFmID0gZ2V0RmlsZUxlYWYoc291cmNlUGF0aCk7XG4gICAgaWYoZmlsZUxlYWYgPT09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIFwiXCI7XG4gICAgfVxuICAgIHJldHVybiBmaWxlTGVhZi5nZXRWaWV3U3RhdGUoKS5zdGF0ZS5tb2RlO1xufVxuZXhwb3J0IGZ1bmN0aW9uIGdldExlYWZTb3VyY2VNb2RlKGZpbGVMZWFmOiBXb3Jrc3BhY2VMZWFmKTogc3RyaW5nIHtcblxuICAgIHJldHVybiBmaWxlTGVhZi5nZXRWaWV3U3RhdGUoKS5zdGF0ZS5tb2RlO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZmlsZVN0aWxsSW5WaWV3KHNvdXJjZVBhdGg6IHN0cmluZyk6Ym9vbGVhbiB7XG5cbiAgICBsZXQgZmlsZUxlYWYgPSBnZXRGaWxlTGVhZihzb3VyY2VQYXRoKTtcbiAgICBpZihmaWxlTGVhZiA9PT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0RmlsZUxlYWYoc291cmNlUGF0aDogc3RyaW5nKTogV29ya3NwYWNlTGVhZiB8IG51bGwge1xuXG4gICAgbGV0IG1hcmtkb3duTGVhdmVzID0gYXBwLndvcmtzcGFjZS5nZXRMZWF2ZXNPZlR5cGUoXCJtYXJrZG93blwiKTtcbiAgICBpZihtYXJrZG93bkxlYXZlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgZm9yKGxldCBpID0gMDsgaSA8IG1hcmtkb3duTGVhdmVzLmxlbmd0aDsgaSsrKSB7XG5cbiAgICAgICAgaWYobWFya2Rvd25MZWF2ZXNbaV0uZ2V0Vmlld1N0YXRlKCkuc3RhdGUuZmlsZSA9PT0gc291cmNlUGF0aCkge1xuICAgICAgICAgICAgcmV0dXJuIG1hcmtkb3duTGVhdmVzW2ldO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG59IiwiLypcbiAqIEZpbGVuYW1lOiBtdWx0aS1jb2x1bW4tbWFya2Rvd24vc3JjL2RvbU9iamVjdC50c1xuICogQ3JlYXRlZCBEYXRlOiBUdWVzZGF5LCBGZWJydWFyeSAxc3QgMjAyMiwgMTI6MDQ6MDAgcG1cbiAqIEF1dGhvcjogQ2FtZXJvbiBSb2JpbnNvblxuICogXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjIgQ2FtZXJvbiBSb2JpbnNvblxuICovXG5cbmltcG9ydCB7IGdldFVJRCB9IGZyb20gXCIuLi91dGlsaXRpZXMvdXRpbHNcIjtcbmltcG9ydCB7IEVsZW1lbnRSZW5kZXJUeXBlIH0gZnJvbSBcIi4uL3V0aWxpdGllcy9lbGVtZW50UmVuZGVyVHlwZVBhcnNlclwiO1xuaW1wb3J0IHsgY2hlY2tGb3JQYXJhZ3JhcGhJbm5lckNvbEVuZFRhZywgY29udGFpbnNDb2xFbmRUYWcsIGNvbnRhaW5zQ29sU2V0dGluZ3NUYWcsIGNvbnRhaW5zRW5kVGFnLCBjb250YWluc1N0YXJ0VGFnLCBlbElubmVyVGV4dENvbnRhaW5zQ29sRW5kVGFnIH0gZnJvbSBcInNyYy91dGlsaXRpZXMvdGV4dFBhcnNlclwiO1xuXG5jb25zdCBVUERBVEVfVElNRVM6IG51bWJlcltdID0gWzEyNSwgMTI1LCAyNTAsIDIwMDAwXTtcbmNvbnN0IE1JRF9CUkVBS19FUlJPUl9NRVNTQUdFOiBzdHJpbmcgPSBcIkRldGVjdGVkIGludmFsaWQgY29sdW1uIGJyZWFrIHN5bnRheC5cXG5QbGVhc2UgbWFrZSBzdXJlIGNvbHVtbiBicmVhayB0YWdzIGFyZSBub3QgaW4gdGhlIG1pZGRsZSBvZiBhIHBhcmFncmFwaCBibG9ja1wiXG5cbmV4cG9ydCBlbnVtIERPTU9iamVjdFRhZyB7XG4gICAgbm9uZSxcbiAgICBzdGFydFJlZ2lvbixcbiAgICByZWdpb25TZXR0aW5ncyxcbiAgICBjb2x1bW5CcmVhayxcbiAgICBlbmRSZWdpb25cbn1cblxuZXhwb3J0IGVudW0gRWxlbWVudENvbHVtbkJyZWFrVHlwZSB7XG4gICAgbm9uZSA9IDAsXG4gICAgcHJlQnJlYWssXG4gICAgcG9zdEJyZWFrLFxuICAgIG1pZEJyZWFrXG59XG5cbmV4cG9ydCBjbGFzcyBET01PYmplY3Qge1xuICAgIG5vZGVLZXk6IHN0cmluZztcbiAgICBvcmlnaW5hbEVsZW1lbnQ6IEhUTUxFbGVtZW50O1xuICAgIGNsb25lZEVsZW1lbnQ6IEhUTUxFbGVtZW50ID0gbnVsbDtcbiAgICBVSUQ6IHN0cmluZztcbiAgICB0YWc6IERPTU9iamVjdFRhZztcbiAgICBlbGVtZW50SXNDb2x1bW5CcmVhazogRWxlbWVudENvbHVtbkJyZWFrVHlwZSA9IEVsZW1lbnRDb2x1bW5CcmVha1R5cGUubm9uZTtcbiAgICB1c2luZ09yaWdpbmFsRWxlbWVudDogYm9vbGVhblxuICAgIGVsZW1lbnRUeXBlOiBFbGVtZW50UmVuZGVyVHlwZSA9IFwidW5kZWZpbmVkXCI7XG4gICAgZWxlbWVudENvbnRhaW5lcjogSFRNTERpdkVsZW1lbnQgPSBudWxsO1xuICAgIGVsZW1lbnRSZW5kZXJlZEhlaWdodCA9IDA7XG4gICAgbGluZXNPZkVsZW1lbnQ6IHN0cmluZ1tdXG5cbiAgICBjYW52YXNFbGVtZW50VXBkYXRlVGltZTogbnVtYmVyID0gRGF0ZS5ub3coKTtcbiAgICBjYW52YXNUaW1lckluZGV4ID0gMDtcblxuICAgIGxhc3RDbG9uZWRFbGVtZW50VXBkYXRlVGltZTogbnVtYmVyID0gRGF0ZS5ub3coKTtcbiAgICB1cGRhdGVUaW1lckluZGV4ID0gMDtcblxuICAgIGNvbnN0cnVjdG9yKGVsZW1lbnQ6IEhUTUxFbGVtZW50LFxuICAgICAgICAgICAgICAgIGxpbmVzT2ZFbGVtZW50OiBzdHJpbmdbXSxcbiAgICAgICAgICAgICAgICByYW5kb21JRDpzdHJpbmcgPSBnZXRVSUQoKSwgXG4gICAgICAgICAgICAgICAgdGFnOiBET01PYmplY3RUYWcgPSBET01PYmplY3RUYWcubm9uZSApIHtcbiAgICAgICAgdGhpcy5ub2RlS2V5ID0gZWxlbWVudC5pbm5lclRleHQudHJpbSgpO1xuICAgICAgICB0aGlzLm9yaWdpbmFsRWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgICAgIHRoaXMuVUlEID0gcmFuZG9tSUQ7XG4gICAgICAgIHRoaXMudGFnID0gdGFnO1xuICAgICAgICB0aGlzLnVzaW5nT3JpZ2luYWxFbGVtZW50ID0gZmFsc2VcbiAgICAgICAgdGhpcy5saW5lc09mRWxlbWVudCA9IGxpbmVzT2ZFbGVtZW50O1xuXG4gICAgICAgIGlmKHRoaXMudGFnID09PSBET01PYmplY3RUYWcubm9uZSkge1xuICAgICAgICAgICAgdGhpcy5zZXREb21PYmplY3RUYWcoKVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gSWYgb3VyIHRhZyBpcyBzdGlsbCBub25lIGhlcmUsIHdlIG5vdyB3YW50IHRvIGNoZWNrIGZvclxuICAgICAgICAvLyBhbiBpbiBwYXJhZ3JhcGggY29sdW1uIGJyZWFrIGZsYWcuXG4gICAgICAgIGlmKHRoaXMudGFnID09PSBET01PYmplY3RUYWcubm9uZSkge1xuICAgICAgICAgICAgdGhpcy5jaGVja0ZvclByZVBvc3RDb2x1bW5CcmVhaygpXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBzZXRNYWluRE9NRWxlbWVudChkb21FbGVtZW50OiBIVE1MRWxlbWVudCkge1xuICAgICAgICB0aGlzLm9yaWdpbmFsRWxlbWVudCA9IGRvbUVsZW1lbnQ7XG4gICAgICAgIHRoaXMudXNpbmdPcmlnaW5hbEVsZW1lbnQgPSB0cnVlXG4gICAgfVxuXG4gICAgY2xvbmVkRWxlbWVudFJlYWR5Rm9yVXBkYXRlKCk6IGJvb2xlYW4ge1xuXG4gICAgICAgIGxldCBkZWx0YVRpbWUgPSBEYXRlLm5vdygpIC0gdGhpcy5sYXN0Q2xvbmVkRWxlbWVudFVwZGF0ZVRpbWU7XG4gICAgICAgIGlmKGRlbHRhVGltZSA+IFVQREFURV9USU1FU1t0aGlzLnVwZGF0ZVRpbWVySW5kZXhdKSB7XG5cbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNhbnZhc1JlYWR5Rm9yVXBkYXRlKCk6IGJvb2xlYW4ge1xuICAgICAgICB2YXIgdGltaW5nQXJyYXkgPSBVUERBVEVfVElNRVNcbiAgICAgICAgbGV0IHtyZXF1aXJlc1VwZGF0ZSwgdGltZXJJbmRleCwgdXBkYXRlVGltZX0gPSBjaGVja0lmVGltaW5nSXNSZWFkeUZvclVwZGF0ZSh0aW1pbmdBcnJheSwgdGhpcy5jYW52YXNFbGVtZW50VXBkYXRlVGltZSwgdGhpcy5jYW52YXNUaW1lckluZGV4KVxuICAgICAgICBpZihyZXF1aXJlc1VwZGF0ZSA9PT0gZmFsc2Upe1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlXG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jYW52YXNFbGVtZW50VXBkYXRlVGltZSA9IHVwZGF0ZVRpbWU7XG4gICAgICAgIHRoaXMuY2FudmFzVGltZXJJbmRleCA9IHRpbWVySW5kZXhcbiAgICAgICAgcmV0dXJuIHRydWVcbiAgICB9XG5cbiAgICB1cGRhdGVDbG9uZWRFbGVtZW50KG5ld0Nsb25lZEVsZW1lbnQ6IEhUTUxFbGVtZW50KSB7XG5cbiAgICAgICAgdGhpcy5jbG9uZWRFbGVtZW50ID0gbmV3Q2xvbmVkRWxlbWVudDtcbiAgICAgICAgdGhpcy51cGRhdGVDbG9uZWRFbGVtZW50VGltZXIoKVxuICAgIH1cblxuICAgIHVwZGF0ZUNsb25lZEVsZW1lbnRUaW1lcigpIHtcbiAgICAgICAgdGhpcy5sYXN0Q2xvbmVkRWxlbWVudFVwZGF0ZVRpbWUgPSBEYXRlLm5vdygpO1xuICAgICAgICB0aGlzLnVwZGF0ZVRpbWVySW5kZXggPSBNYXRoLmNsYW1wKHRoaXMudXBkYXRlVGltZXJJbmRleCArIDEsIDAsIFVQREFURV9USU1FUy5sZW5ndGggLSAxKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHNldERvbU9iamVjdFRhZygpIHtcblxuICAgICAgICBsZXQgZWxlbWVudFRleHRTcGFjZWQgPSB0aGlzLmxpbmVzT2ZFbGVtZW50LnJlZHVjZSgocHJldiwgY3VycikgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIHByZXYgKyBcIlxcblwiICsgY3VycjtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYoY29udGFpbnNFbmRUYWcodGhpcy5vcmlnaW5hbEVsZW1lbnQudGV4dENvbnRlbnQpID09PSB0cnVlKSB7XG5cbiAgICAgICAgICAgIHRoaXMuZWxlbWVudFR5cGUgPSBcInVuUmVuZGVyZWRcIjtcbiAgICAgICAgICAgIHRoaXMudGFnID0gRE9NT2JqZWN0VGFnLmVuZFJlZ2lvbjtcbiAgICAgICAgICAgIC8vIGVsLmFkZENsYXNzKE11bHRpQ29sdW1uU3R5bGVDU1MuUmVnaW9uRW5kVGFnKVxuICAgICAgICAgICAgLy8gcmVnaW9uYWxNYW5hZ2VyLnVwZGF0ZUVsZW1lbnRUYWcoY3VycmVudE9iamVjdC5VSUQsIERPTU9iamVjdFRhZy5lbmRSZWdpb24pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYoY29udGFpbnNDb2xFbmRUYWcodGhpcy5vcmlnaW5hbEVsZW1lbnQudGV4dENvbnRlbnQpID09PSB0cnVlIHx8IFxuICAgICAgICAodGhpcy5vcmlnaW5hbEVsZW1lbnQuaW5uZXJIVE1MLnN0YXJ0c1dpdGgoXCI8bWFyaz5cIikpICYmIGVsSW5uZXJUZXh0Q29udGFpbnNDb2xFbmRUYWcodGhpcy5vcmlnaW5hbEVsZW1lbnQudGV4dENvbnRlbnQpKSB7XG5cbiAgICAgICAgICAgIHRoaXMuZWxlbWVudFR5cGUgPSBcInVuUmVuZGVyZWRcIlxuICAgICAgICAgICAgdGhpcy50YWcgPSBET01PYmplY3RUYWcuY29sdW1uQnJlYWs7XG4gICAgICAgICAgICAvLyBlbC5hZGRDbGFzcyhNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtbkVuZFRhZylcbiAgICAgICAgICAgIC8vIHJlZ2lvbmFsTWFuYWdlci51cGRhdGVFbGVtZW50VGFnKGN1cnJlbnRPYmplY3QuVUlELCBET01PYmplY3RUYWcuY29sdW1uQnJlYWspO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYoY29udGFpbnNTdGFydFRhZyh0aGlzLm9yaWdpbmFsRWxlbWVudC50ZXh0Q29udGVudCkgPT09IHRydWUpIHtcblxuICAgICAgICAgICAgdGhpcy5lbGVtZW50VHlwZSA9IFwidW5SZW5kZXJlZFwiXG4gICAgICAgICAgICB0aGlzLnRhZyA9IERPTU9iamVjdFRhZy5zdGFydFJlZ2lvbjtcbiAgICAgICAgICAgIC8vIGVsLmFkZENsYXNzKE11bHRpQ29sdW1uU3R5bGVDU1MuQ29sdW1uRW5kVGFnKVxuICAgICAgICAgICAgLy8gcmVnaW9uYWxNYW5hZ2VyLnVwZGF0ZUVsZW1lbnRUYWcoY3VycmVudE9iamVjdC5VSUQsIERPTU9iamVjdFRhZy5jb2x1bW5CcmVhayk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZihjb250YWluc0NvbFNldHRpbmdzVGFnKGVsZW1lbnRUZXh0U3BhY2VkKSA9PT0gdHJ1ZSkge1xuXG4gICAgICAgICAgICB0aGlzLmVsZW1lbnRUeXBlID0gXCJ1blJlbmRlcmVkXCJcbiAgICAgICAgICAgIC8vIGVsLmFkZENsYXNzKE11bHRpQ29sdW1uU3R5bGVDU1MuUmVnaW9uU2V0dGluZ3MpXG4gICAgICAgICAgICAvLyByZWdpb25hbE1hbmFnZXIgPSByZWdpb25hbENvbnRhaW5lci5zZXRSZWdpb25TZXR0aW5ncyhlbGVtZW50VGV4dFNwYWNlZClcbiAgICAgICAgICAgIC8vIHJlZ2lvbmFsTWFuYWdlci51cGRhdGVFbGVtZW50VGFnKGN1cnJlbnRPYmplY3QuVUlELCBET01PYmplY3RUYWcucmVnaW9uU2V0dGluZ3MpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgY2hlY2tGb3JQcmVQb3N0Q29sdW1uQnJlYWsoKSB7XG4gICAgICAgIGZ1bmN0aW9uIHJlcGxhY2VDb2xCcmVhayh0ZXh0OiBzdHJpbmcpOiBzdHJpbmcge1xuXG4gICAgICAgICAgICBsZXQgY29sQnJlYWtEYXRhID0gY2hlY2tGb3JQYXJhZ3JhcGhJbm5lckNvbEVuZFRhZyh0ZXh0KTtcbiAgICAgICAgICAgIGlmKGNvbnRhaW5zQ29sdW1uQnJlYWsgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGV4dDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbGV0IHN0YXJ0SW5kZXggPSBjb2xCcmVha0RhdGEuaW5kZXg7XG4gICAgICAgICAgICBsZXQgZW5kSW5kZXggPSBzdGFydEluZGV4ICsgY29sQnJlYWtEYXRhWzBdLmxlbmd0aDtcbiAgICAgICAgICAgIGxldCBwcmUgPSB0ZXh0LnNsaWNlKDAsIHN0YXJ0SW5kZXgpO1xuICAgICAgICAgICAgbGV0IHBvc3QgPSB0ZXh0LnNsaWNlKGVuZEluZGV4KTtcblxuICAgICAgICAgICAgcmV0dXJuIGAke3ByZX0ke3Bvc3R9YDtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCB0ZXh0T2ZFbGVtZW50ID0gdGhpcy5vcmlnaW5hbEVsZW1lbnQuaW5uZXJUZXh0O1xuICAgICAgICBsZXQgY29udGFpbnNDb2x1bW5CcmVhayA9IGNoZWNrRm9yUGFyYWdyYXBoSW5uZXJDb2xFbmRUYWcodGV4dE9mRWxlbWVudCk7XG4gICAgICAgIGlmKGNvbnRhaW5zQ29sdW1uQnJlYWsgIT09IG51bGwpIHtcblxuICAgICAgICAgICAgbGV0IHRleHQgPSB0aGlzLm9yaWdpbmFsRWxlbWVudC5pbm5lclRleHQ7XG4gICAgICAgICAgICBsZXQgc3RhcnRJbmRleCA9IGNvbnRhaW5zQ29sdW1uQnJlYWsuaW5kZXg7XG4gICAgICAgICAgICBsZXQgZW5kSW5kZXggPSBzdGFydEluZGV4ICsgY29udGFpbnNDb2x1bW5CcmVha1swXS5sZW5ndGg7XG4gICAgICAgICAgICBsZXQgcHJlID0gdGV4dC5zbGljZSgwLCBzdGFydEluZGV4KTtcbiAgICAgICAgICAgIGxldCBwb3N0ID0gdGV4dC5zbGljZShlbmRJbmRleClcblxuICAgICAgICAgICAgLy8gU29tZXRpbWVzIHRoZSBlbGVtZW50IHBhc3NlZCBpbiBpcyBhIERJViBjb250YWluaW5nIGEgY2hpbGQgZWxlbWVudCwgb3RoZXJcbiAgICAgICAgICAgIC8vIHRpbWVzIGl0IGlzIHRoZSByb290IGNoaWxkIGVsZW1lbnQgYWxvbmUsIGhlcmUgd2UganVzdCBtYWtlIHN1cmUgd2UgYXJlIGFjY2Vzc2luZ1xuICAgICAgICAgICAgLy8gdGhlIHJpZ2h0IGVsZW1lbnQgd2Ugd2FudC5cbiAgICAgICAgICAgIGxldCBjaGVja05vZGUgPSB0aGlzLm9yaWdpbmFsRWxlbWVudDtcbiAgICAgICAgICAgIGlmKHRoaXMub3JpZ2luYWxFbGVtZW50Lm5vZGVOYW1lID09PSBcIkRJVlwiKSB7XG4gICAgICAgICAgICAgICAgY2hlY2tOb2RlID0gdGhpcy5vcmlnaW5hbEVsZW1lbnQuY2hpbGRyZW5bMF0gYXMgSFRNTEVsZW1lbnQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxldCBwYXJhZ3JhcGggPSBudWxsO1xuICAgICAgICAgICAgaWYoY2hlY2tOb2RlLm5vZGVOYW1lID09PSBcIlBcIikge1xuXG4gICAgICAgICAgICAgICAgLy8gUGFyYWdyYXBocyBzaW1wbHkgcmVtb3ZlIHRoZSBjb2wtYnJlYWsgdGFnXG4gICAgICAgICAgICAgICAgLy8gd2Ugc2V0IG91ciBlbGVtZW50IGhlcmUgaW5jYXNlIHdlIG5lZWQgdG8gZGlzcGxheSBhbiBlcnJvci5cbiAgICAgICAgICAgICAgICBwYXJhZ3JhcGggPSBjaGVja05vZGU7XG4gICAgICAgICAgICAgICAgY2hlY2tOb2RlLmlubmVyVGV4dCA9IGAke3ByZX0ke3Bvc3R9YDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYoY2hlY2tOb2RlLm5vZGVOYW1lID09PSBcIlVMXCIgfHwgY2hlY2tOb2RlLm5vZGVOYW1lID09PSBcIk9MXCIpIHtcblxuICAgICAgICAgICAgICAgIC8vIEF0dGVtcHQgdG8gZ2V0IHRoZSBsaXN0IGl0ZW0gdGhhdCBjb250YWlucyB0aGUgY29sdW1uIGJyZWFrLFxuICAgICAgICAgICAgICAgIC8vIEZyb20gdGVzdGluZyB0aGlzIGNvZGUgc2hvdWxkIG9ubHkgcnVuIHdoZW4gdGhlIGNvbHVtbiBicmVhayBpcyBhdCB0aGUgZW5kXG4gICAgICAgICAgICAgICAgLy8gb2YgYSBsaXN0IG5vdCBhdCB0aGUgc3RhcnQgb2YgdGhlIGxpc3QuXG4gICAgICAgICAgICAgICAgbGV0IGxpc3RJdGVtID0gbnVsbDtcbiAgICAgICAgICAgICAgICBmb3IobGV0IGkgPSBjaGVja05vZGUuY2hpbGRyZW4ubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICAgICAgICAgICAgaWYoY2hlY2tOb2RlLmNoaWxkcmVuW2ldLm5vZGVOYW1lID09PSBcIkxJXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxpc3RJdGVtID0gY2hlY2tOb2RlLmNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZihsaXN0SXRlbSAhPT0gbnVsbCkge1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIFJlcGxhY2UsIHRoZSBsaXN0IGVsZW1lbnQgSFRNTCB3aXRob3V0IHRoZSBjb2wtYnJlYWsgdGV4dC5cbiAgICAgICAgICAgICAgICAgICAgKGxpc3RJdGVtIGFzIEhUTUxFbGVtZW50KS5pbm5lckhUTUwgPSByZXBsYWNlQ29sQnJlYWsoKGxpc3RJdGVtIGFzIEhUTUxFbGVtZW50KS5pbm5lckhUTUwpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoYEVsZW1lbnQgVHlwZTogJHtjaGVja05vZGUubm9kZU5hbWV9LCBkb2VzIG5vdCBjdXJyZW50bHkgc3VwcG9ydCBhcHBlbmVkIGNvbHVtbi1icmVha3MuYCwgY2hlY2tOb2RlLmNsb25lTm9kZSh0cnVlKSk7XG4gICAgICAgICAgICAgICAgLy8gaWYocGFyYWdyYXBoKSB7XG4gICAgICAgICAgICAgICAgLy8gICAgIHBhcmFncmFwaC5pbm5lclRleHQgPSBgJHtwcmV9JHtwb3N0fWA7XG4gICAgICAgICAgICAgICAgLy8gfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBjb25zb2xlLmRlYnVnKFwiQ2hlY2tpbmcgd2hlcmUgY29sdW1uIGJyZWFrIGlzXCIsIHN0YXJ0SW5kZXgsIGVuZEluZGV4LCB0ZXh0Lmxlbmd0aCk7XG4gICAgICAgICAgICBpZihzdGFydEluZGV4ID09PSAwKSB7XG4gICAgICAgICAgICAgICAgLy8gY29uc29sZS5kZWJ1ZyhcIkNvbHVtbiBicmVhayBhdCBiZWdpbmluZyBvZiBlbGVtZW50LlwiKVxuICAgICAgICAgICAgICAgIHRoaXMuZWxlbWVudElzQ29sdW1uQnJlYWsgPSBFbGVtZW50Q29sdW1uQnJlYWtUeXBlLnByZUJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZihlbmRJbmRleCA9PT0gdGV4dC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmRlYnVnKFwiQ29sdW1uIGJyZWFrIGF0IGVuZCBvZiBlbGVtZW50LlwiKVxuICAgICAgICAgICAgICAgIHRoaXMuZWxlbWVudElzQ29sdW1uQnJlYWsgPSBFbGVtZW50Q29sdW1uQnJlYWtUeXBlLnBvc3RCcmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIGNvbnNvbGUuZGVidWcoXCJDb2x1bW4gYnJlYWsgaW4gdGhlIG1pZGRsZSBvZiBlbGVtZW50P1wiKVxuICAgICAgICAgICAgICAgIHRoaXMuZWxlbWVudElzQ29sdW1uQnJlYWsgPSBFbGVtZW50Q29sdW1uQnJlYWtUeXBlLm1pZEJyZWFrO1xuXG4gICAgICAgICAgICAgICAgY29uc3QgRVJST1JfQ09MT1JfQ1NTID0gXCJtY20tZXJyb3ItbWVzc2FnZS1jb2xvclwiO1xuICAgICAgICAgICAgICAgIGNvbnN0IENFTlRFUl9BTElHTl9TUEFOX0NTUyA9IFwibWNtLXNwYW4tY29udGVudC1hbGlnbm1lbnQtY2VudGVyXCI7XG4gICAgICAgICAgICAgICAgaWYocGFyYWdyYXBoKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmFncmFwaC5pbm5lckhUTUwgPSBgJHtwcmV9XFxuPHNwYW4gY2xhc3M9XCIke0VSUk9SX0NPTE9SX0NTU30gJHtDRU5URVJfQUxJR05fU1BBTl9DU1N9XCI+JHtNSURfQlJFQUtfRVJST1JfTUVTU0FHRX08L3NwYW4+XFxuXFxuJHtwb3N0fWAuc3BsaXQoXCJcXG5cIikuam9pbihcIjxicj5cIik7XG5cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmV4cG9ydCBjbGFzcyBET01TdGFydFJlZ2lvbk9iamVjdCBleHRlbmRzIERPTU9iamVjdCB7XG5cbiAgICByZWdpb25FbGVtZW50OiBIVE1MRWxlbWVudDtcblxuICAgIGNvbnN0cnVjdG9yKGJhc2VET01PYmplY3Q6IERPTU9iamVjdCwgcmVnaW9uRWxlbWVudDogSFRNTEVsZW1lbnQpIHtcblxuICAgICAgICBzdXBlcihiYXNlRE9NT2JqZWN0Lm9yaWdpbmFsRWxlbWVudCwgYmFzZURPTU9iamVjdC5saW5lc09mRWxlbWVudCwgYmFzZURPTU9iamVjdC5VSUQsIERPTU9iamVjdFRhZy5zdGFydFJlZ2lvbik7XG4gICAgICAgIHRoaXMucmVnaW9uRWxlbWVudCA9IHJlZ2lvbkVsZW1lbnQ7XG4gICAgfVxufVxuXG5leHBvcnQgY2xhc3MgVGFza0xpc3RET01PYmplY3QgZXh0ZW5kcyBET01PYmplY3Qge1xuXG4gICAgb3JpZ2luYWxDaGVja2JveGVzOiBIVE1MRWxlbWVudFtdID0gW107XG4gICAgY2hlY2tib3hFbGVtZW50czogTWFwPG51bWJlciwgSFRNTElucHV0RWxlbWVudD4gPSBuZXcgTWFwKCk7XG5cbiAgICBjb25zdHJ1Y3RvcihiYXNlRE9NT2JqZWN0OiBET01PYmplY3QpIHtcblxuICAgICAgICBzdXBlcihiYXNlRE9NT2JqZWN0Lm9yaWdpbmFsRWxlbWVudCwgYmFzZURPTU9iamVjdC5saW5lc09mRWxlbWVudCwgYmFzZURPTU9iamVjdC5VSUQsIERPTU9iamVjdFRhZy5ub25lKTtcbiAgICB9XG5cbiAgICBjaGVja2JveENsaWNrZWQoaW5kZXg6IG51bWJlcikge1xuICAgICAgICBcbiAgICAgICAgaWYodGhpcy5jaGVja2JveEVsZW1lbnRzLmhhcyhpbmRleCkpIHtcbiAgICAgICAgICAgIHRoaXMuY2hlY2tib3hFbGVtZW50cy5nZXQoaW5kZXgpLmNsaWNrKCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZihpbmRleCA8IHRoaXMub3JpZ2luYWxDaGVja2JveGVzLmxlbmd0aCkge1xuXG4gICAgICAgICAgICBsZXQgb3JpZ2luYWxJbnB1dCA9IHRoaXMub3JpZ2luYWxDaGVja2JveGVzW2luZGV4XS5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKCd0YXNrLWxpc3QtaXRlbS1jaGVja2JveCcpXG4gICAgICAgICAgICBpZihvcmlnaW5hbElucHV0Lmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgICAgICAgIChvcmlnaW5hbElucHV0WzBdIGFzIEhUTUxJbnB1dEVsZW1lbnQpLmNsaWNrKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBlbHNlIHtcbiAgICAgICAgICAgIC8vICAgICBjb25zb2xlLmVycm9yKFwiQ291bGQgbm90IGZpbmQgY2hlY2tib3ggdG8gY2xpY2suXCIpXG4gICAgICAgICAgICAvLyB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBnZXRDaGVja2JveEVsZW1lbnQoaW5kZXg6IG51bWJlcik6IEhUTUxJbnB1dEVsZW1lbnQgfCB1bmRlZmluZWQge1xuXG5cbiAgICAgICAgaWYodGhpcy5jaGVja2JveEVsZW1lbnRzLmhhcyhpbmRleCkgPT09IGZhbHNlKSB7XG5cbiAgICAgICAgICAgIGlmKGluZGV4IDwgdGhpcy5vcmlnaW5hbENoZWNrYm94ZXMubGVuZ3RoKSB7XG5cbiAgICAgICAgICAgICAgICBsZXQgb3JpZ2luYWxJbnB1dCA9IHRoaXMub3JpZ2luYWxDaGVja2JveGVzW2luZGV4XT8uZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSgndGFzay1saXN0LWl0ZW0tY2hlY2tib3gnKVxuICAgICAgICAgICAgICAgIGlmKG9yaWdpbmFsSW5wdXQ/Lmxlbmd0aCA+PSAxKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jaGVja2JveEVsZW1lbnRzLnNldChpbmRleCwgKG9yaWdpbmFsSW5wdXRbMF0gYXMgSFRNTElucHV0RWxlbWVudCkpXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vICAgICBjb25zb2xlLmVycm9yKFwiQ291bGQgbm90IGZpbmQgY2hlY2tib3ggZWxlbWVudCB0byByZXR1cm4uXCIsIHRoaXMub3JpZ2luYWxDaGVja2JveGVzLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgLy8gfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmNoZWNrYm94RWxlbWVudHMuZ2V0KGluZGV4KTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY2hlY2tGb3JUYXNrTGlzdEVsZW1lbnQoZG9tRWxlbWVudDogRE9NT2JqZWN0KSB7XG5cbiAgICAgICAgaWYoZG9tRWxlbWVudC5vcmlnaW5hbEVsZW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZShcInRhc2stbGlzdC1pdGVtXCIpLmxlbmd0aCA+IDAgKSB7XG5cbiAgICAgICAgICAgIHJldHVybiBuZXcgVGFza0xpc3RET01PYmplY3QoZG9tRWxlbWVudCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZG9tRWxlbWVudDtcbiAgICB9XG5cbiAgICBzdGF0aWMgZ2V0Q2hpbGRDaGVja2JveChlbDogSFRNTEVsZW1lbnQpOiBIVE1MRWxlbWVudCB7XG5cbiAgICAgICAgbGV0IGNoZWNrYm94RWxlbWVudHMgPSBlbC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKCd0YXNrLWxpc3QtaXRlbS1jaGVja2JveCcpXG4gICAgICAgIGlmKGNoZWNrYm94RWxlbWVudHMubGVuZ3RoID09PSAxKSB7XG5cbiAgICAgICAgICAgIHJldHVybiBjaGVja2JveEVsZW1lbnRzWzBdIGFzIEhUTUxFbGVtZW50O1xuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICByZXR1cm4gZWwuY2hpbGRyZW5bMF0gYXMgSFRNTEVsZW1lbnRcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGNoZWNrSWZUaW1pbmdJc1JlYWR5Rm9yVXBkYXRlKHRpbWluZ0FycmF5OiBudW1iZXJbXSwgY2FudmFzRWxlbWVudFVwZGF0ZVRpbWU6IG51bWJlciwgY2FudmFzVGltZXJJbmRleDogbnVtYmVyKSB7XG4gICAgbGV0IGRlbHRhVGltZSA9IERhdGUubm93KCkgLSBjYW52YXNFbGVtZW50VXBkYXRlVGltZVxuICAgIGlmKGRlbHRhVGltZSA+IHRpbWluZ0FycmF5W2NhbnZhc1RpbWVySW5kZXhdKSB7XG4gICAgICAgIGNhbnZhc0VsZW1lbnRVcGRhdGVUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgICAgY2FudmFzVGltZXJJbmRleCA9IE1hdGguY2xhbXAoY2FudmFzVGltZXJJbmRleCArIDEsIDAsIFVQREFURV9USU1FUy5sZW5ndGggLSAxKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHJlcXVpcmVzVXBkYXRlOiB0cnVlLFxuICAgICAgICAgICAgdXBkYXRlVGltZTogY2FudmFzRWxlbWVudFVwZGF0ZVRpbWUsXG4gICAgICAgICAgICB0aW1lckluZGV4OiBjYW52YXNUaW1lckluZGV4LFxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgcmVxdWlyZXNVcGRhdGU6IGZhbHNlLFxuICAgICAgICB1cGRhdGVUaW1lOiBjYW52YXNFbGVtZW50VXBkYXRlVGltZSxcbiAgICAgICAgdGltZXJJbmRleDogY2FudmFzVGltZXJJbmRleFxuICAgIH1cbn0iLCIvKlxuICogRmlsZTogbXVsdGktY29sdW1uLW1hcmtkb3duL3NyYy91dGlsaXRpZXMvY3NzRGVmaW5pdGlvbnMudHNcbiAqIENyZWF0ZWQgRGF0ZTogV2VkbmVzZGF5LCBGZWJydWFyeSAxNnRoIDIwMjIsIDExOjA5OjA2IGFtXG4gKiBBdXRob3I6IENhbWVyb24gUm9iaW5zb25cbiAqIFxuICogQ29weXJpZ2h0IChjKSAyMDIyIENhbWVyb24gUm9iaW5zb25cbiAqL1xuXG5leHBvcnQgZW51bSBNdWx0aUNvbHVtbkxheW91dENTUyB7XG5cbiAgICBSZWdpb25Sb290Q29udGFpbmVyRGl2ID0gXCJtY20tY29sdW1uLXJvb3QtY29udGFpbmVyXCIsXG4gICAgUmVnaW9uRXJyb3JDb250YWluZXJEaXYgPSBcIm1jbS1jb2x1bW4tZXJyb3ItcmVnaW9uLXdyYXBwZXJcIixcbiAgICBSZWdpb25Db250ZW50Q29udGFpbmVyRGl2ID0gXCJtY20tY29sdW1uLXJlZ2lvbi13cmFwcGVyXCIsXG4gICAgUmVnaW9uQ29sdW1uQ29udGFpbmVyRGl2ID0gXCJtY20tY29sdW1uLXBhcmVudC1jb250YWluZXJcIixcbiAgICBDb2x1bW5EdWFsRWxlbWVudENvbnRhaW5lciA9IFwibWNtLWNvbHVtbi1lbGVtZW50LXdyYXBwZXJcIixcbiAgICBPcmlnaW5hbEVsZW1lbnRUeXBlID0gXCJtY20tb3JpZ2luYWwtY29sdW1uLWVsZW1lbnRcIixcbiAgICBDbG9uZWRFbGVtZW50VHlwZSA9IFwibWNtLWNsb25lZC1jb2x1bW4tZWxlbWVudFwiLFxuXG4gICAgQ29udGVudE92ZXJmbG93QXV0b1Njcm9sbF9YID0gXCJtY20tY29udGVudC1vdmVyZmxvdy1hdXRvLXNjcm9sbC14XCIsXG4gICAgQ29udGVudE92ZXJmbG93QXV0b1Njcm9sbF9ZID0gXCJtY20tY29udGVudC1vdmVyZmxvdy1hdXRvLXNjcm9sbC15XCIsXG4gICAgQ29udGVudE92ZXJmbG93SGlkZGVuX1ggPSBcIm1jbS1jb250ZW50LW92ZXJmbG93LWhpZGRlbi14XCIsXG4gICAgQ29udGVudE92ZXJmbG93SGlkZGVuX1kgPSBcIm1jbS1jb250ZW50LW92ZXJmbG93LWhpZGRlbi15XCIsXG5cbiAgICBBbGlnbm1lbnRMZWZ0ID0gXCJtY20tY29udGVudC1hbGlnbm1lbnQtbGVmdFwiLFxuICAgIEFsaWdubWVudENlbnRlciA9IFwibWNtLWNvbnRlbnQtYWxpZ25tZW50LWNlbnRlclwiLFxuICAgIEFsaWdubWVudFJpZ2h0ID0gXCJtY20tY29udGVudC1hbGlnbm1lbnQtcmlnaHRcIixcblxuICAgIFRhYmxlQWxpZ25tZW50ID0gXCJtY20tdGFibGUtYWxpZ25tZW50XCIsXG5cbiAgICBOb0ZsZXhTaHJpbmsgPSBcIm1jbS1uby1mbGV4LXNocmlua1wiLFxuXG4gICAgUmVmbG93Q29udGFpbmVyRGl2ID0gXCJtY20tZG9jLXJlZmxvdy1jb250YWluZXJcIixcblxuICAgIEVycm9yUmVnaW9uUGFkZGluZyA9IFwibWNtLWNvbHVtbi1lcnJvci1wYWRkaW5nXCIsXG5cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cblxuICAgIFNpbmdsZUNvbHVtblNtYWxsID0gXCJtY20tc2luZ2xlLWNvbHVtbi1zbWFsbFwiLFxuICAgIFNpbmdsZUNvbHVtbk1lZCA9IFwibWNtLXNpbmdsZS1jb2x1bW4tbWVkaXVtXCIsXG4gICAgU2luZ2xlQ29sdW1uTGFyZ2UgPSBcIm1jbS1zaW5nbGUtY29sdW1uLWxhcmdlXCIsXG4gICAgU2luZ2xlQ29sdW1uRnVsbCA9IFwibWNtLXNpbmdsZS1jb2x1bW4tZnVsbFwiLFxuXG4gICAgU2luZ2xlQ29sdW1uTGVmdExheW91dCA9IFwibWNtLXNpbmdsZWNvbC1sYXlvdXQtbGVmdFwiLFxuICAgIFNpbmdsZUNvbHVtbkNlbnRlckxheW91dCA9IFwibWNtLXNpbmdsZWNvbC1sYXlvdXQtY2VudGVyXCIsXG4gICAgU2luZ2xlQ29sdW1uUmlnaHRMYXlvdXQgPSBcIm1jbS1zaW5nbGVjb2wtbGF5b3V0LXJpZ2h0XCIsXG5cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cblxuICAgIFR3b0VxdWFsQ29sdW1ucyA9IFwibWNtLXR3by1lcXVhbC1jb2x1bW5zXCIsXG5cbiAgICBUd29Db2x1bW5TbWFsbCA9IFwibWNtLXR3by1jb2x1bW4tc21hbGxcIixcbiAgICBUd29Db2x1bW5MYXJnZSA9IFwibWNtLXR3by1jb2x1bW4tbGFyZ2VcIixcblxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAvL1xuXG4gICAgVGhyZWVFcXVhbENvbHVtbnMgPSBcIm1jbS10aHJlZS1lcXVhbC1jb2x1bW5zXCIsXG5cbiAgICBUaHJlZUNvbHVtbl9MYXJnZSA9IFwibWNtLXRocmVlLWNvbHVtbi1sYXJnZVwiLFxuICAgIFRocmVlQ29sdW1uX1NtYWxsID0gXCJtY20tdGhyZWUtY29sdW1uLXNtYWxsXCIsXG59XG5cbmV4cG9ydCBlbnVtIE11bHRpQ29sdW1uU3R5bGVDU1Mge1xuXG4gICAgUmVnaW9uRXJyb3JNZXNzYWdlID0gXCJtY20tY29sdW1uLWVycm9yLW1lc3NhZ2VcIixcbiAgICBSZWdpb25TZXR0aW5ncyA9IFwibWNtLWNvbHVtbi1zZXR0aW5ncy13cmFwcGVyXCIsXG4gICAgUmVnaW9uQ29udGVudCA9IFwibWNtLWNvbHVtbi1jb250ZW50LXdyYXBwZXJcIixcbiAgICBSZWdpb25FbmRUYWcgPSBcIm1jbS1jb2x1bW4tZW5kLXRhZy13cmFwcGVyXCIsXG4gICAgQ29sdW1uRW5kVGFnID0gXCJtY20tY29sdW1uLWJyZWFrLXRhZy13cmFwcGVyXCIsXG4gICAgUmVnaW9uU2hhZG93ID0gXCJtY20tcmVnaW9uLXNoYWRvd1wiLFxuICAgIENvbHVtblNoYWRvdyA9IFwibWNtLWNvbHVtbi1zaGFkb3dcIixcbiAgICBDb2x1bW5Cb3JkZXIgPSBcIm1jbS1jb2x1bW4tYm9yZGVyXCIsXG4gICAgQ29sdW1uQ29udGVudCA9IFwibWNtLWNvbHVtbi1kaXZcIixcbiAgICBTbWFsbEZvbnQgPSBcIm1jbS1zbWFsbC1mb250LW1lc3NhZ2VcIlxufVxuXG5leHBvcnQgZW51bSBPYnNpZGlhblN0eWxlQ1NTIHtcbiAgICBSZW5kZXJlZE1hcmtkb3duID0gXCJtYXJrZG93bi1yZW5kZXJlZFwiXG59IiwiLyoqXG4gKiBGaWxlOiAvc3JjL3V0aWxpdGllcy9lbGVtZW50UmVuZGVyVHlwZVBhcnNlci50cyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICogQXV0aG9yOiBDYW1lcm9uIFJvYmluc29uICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjMgQ2FtZXJvbiBSb2JpbnNvbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICovXG5cbmltcG9ydCB7IHNlYXJjaENoaWxkcmVuRm9yTm9kZVR5cGUgfSBmcm9tIFwiLi91dGlsc1wiO1xuXG5jb25zdCBBTExfRUxFTUVOVF9SRU5ERVJfVFlQRVMgPSBbXG4gICAgXCJ1bmRlZmluZWRcIixcbiAgICBcImJhc2ljRWxlbWVudFwiLFxuICAgIFwic3BlY2lhbFJlbmRlclwiLFxuICAgIFwiYnV0dG9uUGx1Z2luXCIsXG4gICAgXCJkYXRhdmlld1BsdWdpblwiLFxuICAgIFwiaW1hZ2VFbWJlZFwiLFxuICAgIFwiYWRtb25pdGlvbkZvbGRcIixcbiAgICBcImNhbGxvdXRDb3B5QnV0dG9uXCIsXG4gICAgXCJpbnRlcm5hbEVtYmVkXCIsXG4gICAgXCJkYXRhdmlld0pTQ2FudmFzRW1iZWRcIixcbiAgICBcImRhdGF2aWV3SlNFbWJlZFwiLFxuICAgIFwiZGF0YXZpZXdJbmxpbmVRdWVyeVwiLFxuICAgIFwiZGljZVJvbGxlclwiLFxuICAgIFwiYWRtb25pdGlvblwiLFxuICAgIFwiY3VzdG9tRnJhbWVQbHVnaW5cIixcbiAgICBcImlGcmFtZUVtYmVkXCIsXG4gICAgXCJ0YXNrc1BsdWdpblwiLFxuICAgIFwidW5SZW5kZXJlZFwiLFxuICAgIFwicGRmRW1iZWRcIlxuXSBhcyBjb25zdDtcbmV4cG9ydCB0eXBlIEVsZW1lbnRSZW5kZXJUeXBlID0gdHlwZW9mIEFMTF9FTEVNRU5UX1JFTkRFUl9UWVBFU1tudW1iZXJdO1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0RWxlbWVudFJlbmRlclR5cGUoZWxlbWVudDogSFRNTEVsZW1lbnQpOiBFbGVtZW50UmVuZGVyVHlwZSB7XG5cbiAgICBpZihpc0VtYmVkZWRJbWFnZShlbGVtZW50KSA9PT0gdHJ1ZSkge1xuICAgICAgICByZXR1cm4gXCJpbWFnZUVtYmVkXCJcbiAgICB9XG5cbiAgICBpZihpc0J1dHRvblBsdWdpbl9Dcm9zc0NvbXBhdGliaWx0eShlbGVtZW50KSA9PT0gdHJ1ZSkge1xuICAgICAgICByZXR1cm4gXCJidXR0b25QbHVnaW5cIlxuICAgIH1cblxuICAgIGlmKGlzVGFza3NQbHVnaW4oZWxlbWVudCkgPT09IHRydWUpIHtcbiAgICAgICAgcmV0dXJuIFwidGFza3NQbHVnaW5cIlxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBEYXRhdmlldyBwbHVnaW4gbmVlZHMgdG8gYmUgY29uc3RhbnRseSBjaGVja2VkIGlmIHRoZSBjbG9uZSBzaG91bGQgYmVcbiAgICAgKiB1cGRhdGVkIGJ1dCBzaG91bGQgbm90IGFsd2F5cyB1cGRhdGUgdGhlIFwiZHVhbCByZW5kZXJcIiBhc3BlY3QsIHNvIHdlIGFkZFxuICAgICAqIGEgc3BlY2lhbCBjYXNlIGZvciB0aGF0IHBsdWdpbiBhbmQgbWF5YmUgb3RoZXJzIGluIHRoZSBmdXR1cmUuXG4gICAgICovXG4gICAgaWYoaGFzRGF0YXZpZXcoZWxlbWVudCkgPT09IHRydWUpIHtcbiAgICAgICAgcmV0dXJuIFwiZGF0YXZpZXdQbHVnaW5cIlxuICAgIH1cbiAgICBlbHNlIGlmKGlzUERGRW1iZWQoZWxlbWVudCkpIHtcbiAgICAgICAgcmV0dXJuIFwicGRmRW1iZWRcIlxuICAgIH1cbiAgICBlbHNlIGlmKGlzSW50ZXJuYWxFbWJlZChlbGVtZW50KSkge1xuICAgICAgICByZXR1cm4gXCJpbnRlcm5hbEVtYmVkXCJcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTb21lIHR5cGVzIG9mIGNvbnRlbnQgYXJlIHJlbmRlcmVkIGluIGNhbnZhc2VzIHdoaWNoIGFyZSBub3QgcmVuZGVyZWQgcHJvcGVybHlcbiAgICAgKiB3aGVuIHdlIGNsb25lIHRoZSBvcmlnaW5hbCBub2RlLiBIZXJlIHdlIGFyZSBmbGFnZ2luZyB0aGUgZWxlbWVudCBhcyBhIGNhbnZhc1xuICAgICAqIGVsZW1lbnQgc28gd2UgY2FuIGNsb25lIHRoZSBjYW52YXMgdG8gYSBjb3B5IGVsZW1lbnQgd2l0aGluIHRoZSByZWdpb24uXG4gICAgICogXG4gICAgICovXG4gICAgaWYoIGhhc0RhdGF2aWV3SlNDYW52YXMoZWxlbWVudCkgPT09IHRydWUpIHtcbiAgICAgICAgcmV0dXJuIFwiZGF0YXZpZXdKU0NhbnZhc0VtYmVkXCJcbiAgICB9XG4gICAgaWYoIGhhc0RhdGF2aWV3SlMoZWxlbWVudCkgPT09IHRydWUpIHtcbiAgICAgICAgcmV0dXJuIFwiZGF0YXZpZXdKU0VtYmVkXCJcbiAgICB9XG4gICAgaWYoaGFzRGF0YXZpZXdJbmxpbmUoZWxlbWVudCkgPT09IHRydWUpIHtcbiAgICAgICAgcmV0dXJuIFwiZGF0YXZpZXdJbmxpbmVRdWVyeVwiXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTG9vayBmb3Igc3BlY2lmaWMga2luZHMgb2YgZWxlbWVudHMgYnkgdGhlaXIgQ1NTIGNsYXNzIG5hbWVzIGhlcmUuIFRoZXNlIFxuICAgICAqIGFyZSBnb2luZyB0byBiZSBicml0dGxlIGxpbmtzIGFzIHRoZXkgcmVseSBvbiBvdGhlciBwbHVnaW4gZGVmaW5pdGlvbnMgYnV0XG4gICAgICogYXMgdGhpcyBpcyBvbmx5IGFkZGluZyBpbiBleHRyYSBjb21wYXRhYmlsaXR5IHRvIHRoZSBwbHVnaW5zIGRlZmluZWQgaGVyZSBcbiAgICAgKiBpdCBzaG91bGQgYmUgb2suXG4gICAgICogXG4gICAgICogVGhlc2UgbWF5IGJlIGNsYXNzZXMgb24gb25lIG9mIHRoZSBzaW1wbGUgZWxlbWVudHMgKHN1Y2ggYXMgYSBwYXJhZ3JhcGgpXG4gICAgICogdGhhdCB3ZSBzZWFyY2ggZm9yIGJlbG93IHNvIG5lZWQgdG8gbG9vayBmb3IgdGhlc2UgZmlyc3QuXG4gICAgICovXG4gICAgaWYoaGFzRGljZVJvbGxlcihlbGVtZW50KSA9PT0gdHJ1ZSkge1xuICAgICAgICByZXR1cm4gXCJkaWNlUm9sbGVyXCJcbiAgICB9XG4gICAgZWxzZSBpZihoYXNDb3B5QnV0dG9uKGVsZW1lbnQpID09PSB0cnVlKSB7XG4gICAgICAgIHJldHVybiBcImNhbGxvdXRDb3B5QnV0dG9uXCJcbiAgICB9XG4gICAgZWxzZSBpZihoYXNBZG1vbml0aW9uRm9sZChlbGVtZW50KSA9PT0gdHJ1ZSkge1xuICAgICAgICByZXR1cm4gXCJhZG1vbml0aW9uRm9sZFwiXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBjaGVja3MgZm9yIHNwZWNpYWwgdHlwZXMgb2YgZWxlbWVudHMgdGhhdCBzaG91bGQgYmUgcmVuZGVyZWQgbm9ybWFsbHkuIElzXG4gICAgICogc2xpZ2h0bHkgcmVkdW5kYW50IHdpdGggbmV4dCBjaGVjayBidXQgZGlmZmVyZW50aWF0ZXMgYmV0d2VlbiB0eXBlcyBvZiBlbWVudHMgXG4gICAgICogYmVpbmcgY2hlY2tlZC5cbiAgICAgKi9cbiAgICBpZihoYXNBZG1vbml0aW9uKGVsZW1lbnQpID09PSB0cnVlKSB7XG4gICAgICAgIHJldHVybiBcImFkbW9uaXRpb25cIlxuICAgIH1cbiAgICBlbHNlIGlmIChpc0lGcmFtZShlbGVtZW50KSA9PT0gdHJ1ZSkge1xuXG4gICAgICAgIHJldHVybiBcImlGcmFtZUVtYmVkXCJcbiAgICB9XG4gICAgZWxzZSBpZihpc0N1c3RvbUlGcmFtZShlbGVtZW50KSA9PT0gdHJ1ZSkge1xuICAgICAgICBcbiAgICAgICAgcmV0dXJuIFwiY3VzdG9tRnJhbWVQbHVnaW5cIlxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIElmIHdlIGRpZG50IGZpbmQgYSBzcGVjaWFsIGVsZW1lbnQgd2Ugd2FudCB0byBjaGVjayBmb3Igc2ltcGxlIGVsZW1lbnRzXG4gICAgICogc3VjaCBhcyBwYXJhZ3JhcGhzIG9yIGxpc3RzLiBJbiB0aGUgY3VycmVudCBpbXBsZW1lbnRhdGlvbiB3ZSBvbmx5IHNldCB1cFxuICAgICAqIHRoZSBzcGVjaWFsIGNhc2UgZm9yIFwic3BlY2lhbFJlbmRlclwiIGVsZW1lbnRzIHNvIHRoaXMgKnNob3VsZCogYmUgc2F2aW5nXG4gICAgICogc29tZSByZW5kZXJpbmcgdGltZSBieSBzZXR0aW5nIHRoZXNlIHRhZ3MgcHJvcGVybHkuXG4gICAgICovXG4gICAgaWYoaGFzUGFyYWdyYXBoKGVsZW1lbnQpIHx8IFxuICAgICAgIGhhc0hlYWRlcihlbGVtZW50KSAgICB8fFxuICAgICAgIGhhc0xpc3QoZWxlbWVudCkgfHxcbiAgICAgICBpc0hvcml6b250YWxSdWxlKGVsZW1lbnQpIHx8XG4gICAgICAgaXNUYWJsZShlbGVtZW50KSkge1xuXG4gICAgICAgIHJldHVybiBcImJhc2ljRWxlbWVudFwiXG4gICAgfVxuXG4gICAgLy8gSWYgc3RpbGwgbm90aGluZyBmb3VuZCB3ZSByZXR1cm4gb3RoZXIgYXMgdGhlIGRlZmF1bHQgcmVzcG9uc2UgaWYgbm90aGluZyBlbHNlIGZvdW5kLlxuICAgIHJldHVybiBcInNwZWNpYWxSZW5kZXJcIlxufVxuXG5mdW5jdGlvbiBoYXNQYXJhZ3JhcGgoZWxlbWVudDogSFRNTEVsZW1lbnQpOiBib29sZWFuIHtcbiAgICByZXR1cm4gZWxlbWVudC5pbm5lckhUTUwuc3RhcnRzV2l0aChcIjxwXCIpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaGFzSGVhZGVyKGVsZW1lbnQ6IEhUTUxFbGVtZW50KTogYm9vbGVhbiB7XG5cbiAgICBpZihlbGVtZW50LmlubmVySFRNTC5zdGFydHNXaXRoKFwiPGgxXCIpIHx8IFxuICAgICAgIGVsZW1lbnQuaW5uZXJIVE1MLnN0YXJ0c1dpdGgoXCI8aDJcIikgfHwgXG4gICAgICAgZWxlbWVudC5pbm5lckhUTUwuc3RhcnRzV2l0aChcIjxoM1wiKSB8fCBcbiAgICAgICBlbGVtZW50LmlubmVySFRNTC5zdGFydHNXaXRoKFwiPGg0XCIpIHx8XG4gICAgICAgZWxlbWVudC5pbm5lckhUTUwuc3RhcnRzV2l0aChcIjxoNVwiKSB8fFxuICAgICAgIGVsZW1lbnQuaW5uZXJIVE1MLnN0YXJ0c1dpdGgoXCI8aDZcIikpIHtcblxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGhhc0xpc3QoZWxlbWVudDogSFRNTEVsZW1lbnQpOiBib29sZWFuIHtcbiAgICBcbiAgICBpZihlbGVtZW50LmlubmVySFRNTC5zdGFydHNXaXRoKFwiPHVsXCIpIHx8IFxuICAgICAgIGVsZW1lbnQuaW5uZXJIVE1MLnN0YXJ0c1dpdGgoXCI8b2xcIikpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBoYXNDb3B5QnV0dG9uKGVsZW1lbnQ6IEhUTUxFbGVtZW50KTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGVsZW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZShcImNvcHktY29kZS1idXR0b25cIikubGVuZ3RoICE9PSAwIHx8IFxuICAgICAgICAgICAgZWxlbWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKFwiYWRtb25pdGlvbi1jb250ZW50LWNvcHlcIikubGVuZ3RoICE9PSAwO1xufVxuXG5mdW5jdGlvbiBoYXNEaWNlUm9sbGVyKGVsZW1lbnQ6IEhUTUxFbGVtZW50KTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGVsZW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZShcImRpY2Utcm9sbGVyXCIpLmxlbmd0aCAhPT0gMDtcbn1cblxuZnVuY3Rpb24gaGFzQWRtb25pdGlvbihlbGVtZW50OiBIVE1MRWxlbWVudCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBlbGVtZW50LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoXCJhZG1vbml0aW9uXCIpLmxlbmd0aCAhPT0gMDtcbn1cblxuZnVuY3Rpb24gaXNJRnJhbWUoZWxlbWVudDogSFRNTEVsZW1lbnQpOiBib29sZWFuIHtcblxuICAgIGlmKGVsZW1lbnQuY2hpbGRyZW4ubGVuZ3RoID4gMCkge1xuXG4gICAgICAgIHJldHVybiBlbGVtZW50LmZpcnN0Q2hpbGQubm9kZU5hbWUudG9Mb3dlckNhc2UoKSA9PT0gXCJpZnJhbWVcIjtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2Vcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzVGFza3NQbHVnaW4oZWxlbWVudDogSFRNTEVsZW1lbnQpOiBib29sZWFuIHsgICAgXG4gICAgcmV0dXJuIGVsZW1lbnQuaGFzQ2xhc3MoXCJibG9jay1sYW5ndWFnZS10YXNrc1wiKSB8fCBcbiAgICBlbGVtZW50LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoXCJibG9jay1sYW5ndWFnZS10YXNrc1wiKS5sZW5ndGggIT09IDBcbn1cblxuZnVuY3Rpb24gaXNIb3Jpem9udGFsUnVsZShlbGVtZW50OiBIVE1MRWxlbWVudCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBlbGVtZW50LmlubmVySFRNTC5zdGFydHNXaXRoKFwiPGhyXCIpXG59XG5cbmZ1bmN0aW9uIGlzVGFibGUoZWxlbWVudDogSFRNTEVsZW1lbnQpOiBib29sZWFuIHtcbiAgICByZXR1cm4gZWxlbWVudC5pbm5lckhUTUwuc3RhcnRzV2l0aChcIjx0YWJsZVwiKVxufVxuXG5mdW5jdGlvbiBoYXNBZG1vbml0aW9uRm9sZChlbGVtZW50OiBIVE1MRWxlbWVudCkge1xuICAgIHJldHVybiBlbGVtZW50LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoXCJjYWxsb3V0LWZvbGRcIikubGVuZ3RoICE9PSAwO1xufVxuXG5mdW5jdGlvbiBoYXNEYXRhdmlldyhlbGVtZW50OiBIVE1MRWxlbWVudCkge1xuXG4gICAgbGV0IGlzRGF0YXZpZXcgPSBlbGVtZW50LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoXCJibG9jay1sYW5ndWFnZS1kYXRhdmlld1wiKS5sZW5ndGggIT09IDA7XG4gICAgcmV0dXJuIGlzRGF0YXZpZXc7XG59XG5cbmZ1bmN0aW9uIGhhc0RhdGF2aWV3SW5saW5lKGVsZW1lbnQ6IEhUTUxFbGVtZW50KSB7XG4gICAgbGV0IGlzRGF0YXZpZXcgPSBlbGVtZW50LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoXCJkYXRhdmlldy1pbmxpbmUtcXVlcnlcIikubGVuZ3RoICE9PSAwO1xuICAgIHJldHVybiBpc0RhdGF2aWV3O1xufVxuXG5mdW5jdGlvbiBoYXNEYXRhdmlld0pTQ2FudmFzKGVsZW1lbnQ6IEhUTUxFbGVtZW50KSB7XG5cbiAgICBsZXQgaXNEYXRhdmlld0pTID0gZWxlbWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKFwiYmxvY2stbGFuZ3VhZ2UtZGF0YXZpZXdqc1wiKS5sZW5ndGggIT09IDA7XG4gICAgbGV0IGNhbnZhcyA9IHNlYXJjaENoaWxkcmVuRm9yTm9kZVR5cGUoZWxlbWVudCwgXCJjYW52YXNcIik7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1lYW5zIG9ubHkgZGF0YXZpZXdKUyBjaGFydCBjYW52YXMgZWxlbWVudHMgc2hvdWxkIGJlIHJlbmRlcmVkIHByb3Blcmx5LiBPdGhlciBjYW52YXNlcyB3aWxsIFxuICAgICAqIG5lZWQgdGhpZXIgb3duIGNhc2UgcHV0IGluIG9yIHRoZSByZXN0cmljdGlvbiByZW1vdmVkIGFmdGVyIHRlc3RpbmcuXG4gICAgICovXG4gICAgcmV0dXJuIGNhbnZhcyAhPT0gbnVsbCAmJiBpc0RhdGF2aWV3SlMgXG59XG5cbmZ1bmN0aW9uIGhhc0RhdGF2aWV3SlMoZWxlbWVudDogSFRNTEVsZW1lbnQpIHtcblxuICAgIGxldCBpc0RhdGF2aWV3SlMgPSBlbGVtZW50LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoXCJibG9jay1sYW5ndWFnZS1kYXRhdmlld2pzXCIpLmxlbmd0aCAhPT0gMDtcbiAgICByZXR1cm4gaXNEYXRhdmlld0pTIFxufVxuXG5mdW5jdGlvbiBpc0ludGVybmFsRW1iZWQoZWxlbWVudDogSFRNTEVsZW1lbnQpIHtcbiAgICBsZXQgaXNFbWJlZCA9IGVsZW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZShcImludGVybmFsLWVtYmVkXCIpLmxlbmd0aCAhPT0gMDtcbiAgICByZXR1cm4gaXNFbWJlZDtcbn1cblxuZnVuY3Rpb24gaXNQREZFbWJlZChlbGVtZW50OiBIVE1MRWxlbWVudCk6IGJvb2xlYW4ge1xuICAgIGxldCBpc1BERkVtYmVkID0gZWxlbWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKFwicGRmLWVtYmVkXCIpLmxlbmd0aCAhPT0gMDtcbiAgICByZXR1cm4gaXNQREZFbWJlZDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEhlYWRpbmdDb2xsYXBzZUVsZW1lbnQoZWxlbWVudDogSFRNTEVsZW1lbnQpOiBFbGVtZW50IHwgbnVsbCB7XG5cbiAgICBpZihlbGVtZW50ID09PSBudWxsKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGxldCBjaGlsZEVsZW1lbnRzID0gZWxlbWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKFwiaGVhZGluZy1jb2xsYXBzZS1pbmRpY2F0b3JcIilcbiAgICBpZihjaGlsZEVsZW1lbnRzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICByZXR1cm4gY2hpbGRFbGVtZW50c1swXTtcbiAgICB9XG4gICAgaWYoY2hpbGRFbGVtZW50cy5sZW5ndGggPiAxKSB7XG4gICAgICAgIC8vIGNvbnNvbGUuZGVidWcoXCJGb3VuZCBtdWx0aXBsZSBoZWFkaW5nIGNvbGxhcHNlIGluZGljYXRvcnMgaW4gZWxlbWVudC5cIilcbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG59XG5cbmZ1bmN0aW9uIGlzQ3VzdG9tSUZyYW1lKGVsZW1lbnQ6IEhUTUxFbGVtZW50KSB7XG4gICAgbGV0IGlzRnJhbWUgPSBlbGVtZW50LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoXCJjdXN0b20tZnJhbWVzLWZyYW1lXCIpLmxlbmd0aCAhPT0gMDtcbiAgICByZXR1cm4gaXNGcmFtZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzQnV0dG9uUGx1Z2luX0Nyb3NzQ29tcGF0aWJpbHR5KGVsZW1lbnQ6IEhUTUxFbGVtZW50KSB7XG5cbiAgICBpZihlbGVtZW50Lmhhc0NsYXNzKFwiYmxvY2stbGFuZ3VhZ2UtYnV0dG9uXCIpKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIGxldCBidXR0b25QbHVnaW5CbG9jayA9IGVsZW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZShcImJsb2NrLWxhbmd1YWdlLWJ1dHRvblwiKVswXTtcbiAgICBpZihidXR0b25QbHVnaW5CbG9jaykge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGlzRW1iZWRlZEltYWdlKGVsZW1lbnQ6IEhUTUxFbGVtZW50KTogYm9vbGVhbiB7XG4gICAgXG4gICAgbGV0IGltZyA9IGVsZW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoXCJpbWdcIilbMF07XG4gICAgaWYoaW1nID09PSBudWxsIHx8IFxuICAgICAgIGltZyA9PT0gdW5kZWZpbmVkKSB7XG5cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbn0iLCIvKipcbiAqIEZpbGU6IC9zcmMvZG9tX21hbmFnZXIvcmVnaW9uYWxfbWFuYWdlcnMvUmVnaW9uTWFuYWdlci50cyAgICAgICAgICAgICAgICAgICAqXG4gKiBDcmVhdGVkIERhdGU6IFN1bmRheSwgTWF5IDIybmQgMjAyMiwgNzo0OSBwbSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICogQXV0aG9yOiBDYW1lcm9uIFJvYmluc29uICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjIgQ2FtZXJvbiBSb2JpbnNvbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICovXG5cbmltcG9ydCB7IERPTU9iamVjdCwgRE9NT2JqZWN0VGFnLCBUYXNrTGlzdERPTU9iamVjdCB9IGZyb20gJy4uL2RvbU9iamVjdCc7XG5pbXBvcnQgeyBNdWx0aUNvbHVtblNldHRpbmdzLCBDb2x1bW5MYXlvdXQsIGdldERlZmF1bHRNdWx0aUNvbHVtblNldHRpbmdzLCBjb2x1bW5TcGFjaW5nU3RhdGUsIGdldEluZGV4ZWRDbGFtcGVkQXJyYXlWYWx1ZSwgaXNDb2x1bW5MYXlvdXQsIHZhbGlkYXRlQ29sdW1uTGF5b3V0IH0gZnJvbSBcIi4uLy4uL3JlZ2lvblNldHRpbmdzXCI7XG5pbXBvcnQgeyBNdWx0aUNvbHVtbkxheW91dENTUywgTXVsdGlDb2x1bW5TdHlsZUNTUyB9IGZyb20gJy4uLy4uL3V0aWxpdGllcy9jc3NEZWZpbml0aW9ucyc7XG5pbXBvcnQgeyBGaWxlRE9NTWFuYWdlciB9IGZyb20gJy4uL2RvbU1hbmFnZXInO1xuaW1wb3J0IHsgZ2V0RWxlbWVudFJlbmRlclR5cGUgfSBmcm9tICdzcmMvdXRpbGl0aWVzL2VsZW1lbnRSZW5kZXJUeXBlUGFyc2VyJztcbmltcG9ydCB7IFJlZ2lvbk1hbmFnZXJEYXRhIH0gZnJvbSAnLi9yZWdpb25NYW5hZ2VyQ29udGFpbmVyJztcbmltcG9ydCB7IHNlYXJjaENoaWxkcmVuRm9yTm9kZVR5cGUsIHNlYXJjaENoaWxkcmVuRm9yTm9kZXNPZlR5cGUgfSBmcm9tICdzcmMvdXRpbGl0aWVzL3V0aWxzJztcbmltcG9ydCB7IEhUTUxTaXppbmcgfSBmcm9tICdzcmMvdXRpbGl0aWVzL2ludGVyZmFjZXMnO1xuaW1wb3J0IHsgUmVnaW9uRXJyb3JNYW5hZ2VyIH0gZnJvbSAnLi4vcmVnaW9uRXJyb3JNYW5hZ2VyJztcblxuZXhwb3J0IHR5cGUgTXVsdGlDb2x1bW5SZW5kZXJEYXRhID0geyBcbiAgICBwYXJlbnRSZW5kZXJFbGVtZW50OiBIVE1MRWxlbWVudCwgXG4gICAgcGFyZW50UmVuZGVyU2V0dGluZ3M6IE11bHRpQ29sdW1uU2V0dGluZ3MsXG4gICAgZG9tT2JqZWN0czogRE9NT2JqZWN0W11cbn1cblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIFJlZ2lvbk1hbmFnZXIge1xuXG4gICAgcHJvdGVjdGVkIGRvbUxpc3Q6IERPTU9iamVjdFtdID0gW107XG4gICAgcHVibGljIGdldCBudW1iZXJPZkNoaWxkcmVuKCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLmRvbUxpc3QubGVuZ3RoO1xuICAgIH1cbiAgICBwcm90ZWN0ZWQgZG9tT2JqZWN0TWFwOiBNYXA8c3RyaW5nLCBET01PYmplY3Q+ID0gbmV3IE1hcCgpO1xuICAgIHByaXZhdGUgX3JlZ2lvblBhcmVudDogSFRNTEVsZW1lbnQ7XG4gICAgcHVibGljIGdldCByZWdpb25QYXJlbnQoKTogSFRNTEVsZW1lbnQge1xuICAgICAgICByZXR1cm4gdGhpcy5fcmVnaW9uUGFyZW50O1xuICAgIH1cbiAgICBwdWJsaWMgc2V0IHJlZ2lvblBhcmVudCh2YWx1ZTogSFRNTEVsZW1lbnQpIHtcbiAgICAgICAgdGhpcy5fcmVnaW9uUGFyZW50ID0gdmFsdWU7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGZpbGVNYW5hZ2VyOiBGaWxlRE9NTWFuYWdlcjtcbiAgICBwcm90ZWN0ZWQgcmVnaW9uYWxTZXR0aW5nczogTXVsdGlDb2x1bW5TZXR0aW5ncyA9IGdldERlZmF1bHRNdWx0aUNvbHVtblNldHRpbmdzKCk7XG5cbiAgICBwcm90ZWN0ZWQgcmVnaW9uS2V5OiBzdHJpbmc7XG4gICAgcHJpdmF0ZSBfZXJyb3JNYW5hZ2VyOiBSZWdpb25FcnJvck1hbmFnZXI7XG4gICAgcHVibGljIGdldCBlcnJvck1hbmFnZXIoKTogUmVnaW9uRXJyb3JNYW5hZ2VyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2Vycm9yTWFuYWdlcjtcbiAgICB9XG4gICAgcHJvdGVjdGVkIHNldCBlcnJvck1hbmFnZXIodmFsdWU6IFJlZ2lvbkVycm9yTWFuYWdlcikge1xuICAgICAgICB0aGlzLl9lcnJvck1hbmFnZXIgPSB2YWx1ZTtcbiAgICB9XG4gICAgcHVibGljIHVwZGF0ZUVycm9yTWFuYWdlcihuZXdNYW5hZ2VyOiBSZWdpb25FcnJvck1hbmFnZXIsIHJvb3RFbGVtZW50OiBIVE1MRGl2RWxlbWVudCkge1xuICAgICAgICB3aGlsZShyb290RWxlbWVudC5jaGlsZHJlbi5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICByb290RWxlbWVudC5jaGlsZE5vZGVzLmZvckVhY2goY2hpbGQgPT4ge1xuICAgICAgICAgICAgICAgIHJvb3RFbGVtZW50LnJlbW92ZUNoaWxkKGNoaWxkKVxuICAgICAgICAgICAgfSlcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9lcnJvck1hbmFnZXIgPSBuZXdNYW5hZ2VyO1xuICAgICAgICB0aGlzLl9lcnJvck1hbmFnZXIuc2V0UmVnaW9uUm9vdEVsZW1lbnQocm9vdEVsZW1lbnQpXG4gICAgfVxuXG4gICAgY29uc3RydWN0b3IoZGF0YTogUmVnaW9uTWFuYWdlckRhdGEpIHtcbiAgICAgICAgdGhpcy5kb21MaXN0ID0gZGF0YS5kb21MaXN0O1xuICAgICAgICB0aGlzLmRvbU9iamVjdE1hcCA9IGRhdGEuZG9tT2JqZWN0TWFwO1xuICAgICAgICB0aGlzLnJlZ2lvblBhcmVudCA9IGRhdGEucmVnaW9uUGFyZW50O1xuXG4gICAgICAgIHRoaXMuZmlsZU1hbmFnZXIgPSBkYXRhLmZpbGVNYW5hZ2VyO1xuICAgICAgICB0aGlzLnJlZ2lvbmFsU2V0dGluZ3MgPSBkYXRhLnJlZ2lvbmFsU2V0dGluZ3M7XG5cbiAgICAgICAgdGhpcy5yZWdpb25LZXkgPSBkYXRhLnJlZ2lvbktleTtcbiAgICAgICAgdGhpcy5lcnJvck1hbmFnZXIgPSBkYXRhLmVycm9yTWFuYWdlclxuICAgIH1cblxuICAgIHB1YmxpYyBnZXRSZWdpb25EYXRhKCk6IFJlZ2lvbk1hbmFnZXJEYXRhIHtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZG9tTGlzdDogdGhpcy5kb21MaXN0LFxuICAgICAgICAgICAgZG9tT2JqZWN0TWFwOiB0aGlzLmRvbU9iamVjdE1hcCxcbiAgICAgICAgICAgIHJlZ2lvblBhcmVudDogdGhpcy5yZWdpb25QYXJlbnQsXG5cbiAgICAgICAgICAgIGZpbGVNYW5hZ2VyOiB0aGlzLmZpbGVNYW5hZ2VyLFxuICAgICAgICAgICAgcmVnaW9uYWxTZXR0aW5nczogdGhpcy5yZWdpb25hbFNldHRpbmdzLFxuXG4gICAgICAgICAgICByZWdpb25LZXk6IHRoaXMucmVnaW9uS2V5LFxuICAgICAgICAgICAgcm9vdEVsZW1lbnQ6IG51bGwsXG4gICAgICAgICAgICBlcnJvck1hbmFnZXI6IHRoaXMuZXJyb3JNYW5hZ2VyXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkcyBhIG5ldyBvYmplY3QgdG8gdGhlIHJlZ2lvbiBieSBmaW5kaW5nIHdoZXJlIGl0IHNob3VsZCBiZSByZWxhdGl2ZSB0byBpdHMgc2libGluZ3MuXG4gICAgICogQHBhcmFtIHNpYmxpbmdzQWJvdmUgVGhlIE1hcmtkb3duIHRleHQgcmVuZGVyZWQgZWxlbWVudHMgZm9yIHNpYmlsaW5ncyBhYm92ZSB0aGlzIGVsZW1lbnQgaW4gdGhlIGRvbVxuICAgICAqIEBwYXJhbSBzaWJsaW5nc0JlbG93IFRoZSBNYXJrZG93biB0ZXh0IHJlbmRlcmVkIGVsZW1lbnRzIGZvciBzaWJpbGluZ3MgYmVsb3cgdGhpcyBlbGVtZW50IGluIHRoZSBkb21cbiAgICAgKiBAcGFyYW0gb2JqIFRoZSBvYmplY3QgdG8gYWRkLlxuICAgICAqIEByZXR1cm5zIFJldHVybnMgdGhlIGluZGV4IGF0IHdoaWNoIHRoZSBvYmplY3QgaGFzIGJlZW4gYWRkZWQuXG4gICAgICovXG4gICAgcHVibGljIGFkZE9iamVjdChzaWJsaW5nc0Fib3ZlOiBIVE1MRGl2RWxlbWVudCwgc2libGluZ3NCZWxvdzogSFRNTERpdkVsZW1lbnQsIG9iajogRE9NT2JqZWN0KTogbnVtYmVyIHtcblxuICAgICAgICBsZXQgbmV4dE9iaiA9IHNpYmxpbmdzQmVsb3cuY2hpbGRyZW5bMF0gYXMgSFRNTEVsZW1lbnQ7XG5cbiAgICAgICAgbGV0IGFkZEF0SW5kZXggPSBzaWJsaW5nc0Fib3ZlLmNoaWxkcmVuLmxlbmd0aDtcblxuICAgICAgICBpZiAoc2libGluZ3NBYm92ZS5jaGlsZHJlbi5sZW5ndGggPiAwKSB7XG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogV2Ugd2FudCB0byBmaW5kIHRoZSBmaXJzdCBzaWJsaW5nIHdpdGhvdXRoIFwiXCIgZm9yIGFuIGlubmVyIHRleHQgc28gd2UgY2FuIHVzZSB0aGF0IHRvIGFuY2hvciBvdXJcbiAgICAgICAgICAgICAqIGVsZW1lbnQgaW50byB0aGUgZG9tTGlzdC4gRm9yIG1vc3QgaXRlbXMgdGhlIGZpcnN0IGVsZW1lbnQgYmVmb3JlIG91ciBuZXcgZWxlbWVudCB3aWxsIGhhdmUgdGhlIHByb3BlclxuICAgICAgICAgICAgICogaW5uZXJUZXh0LiBTb21ldGltZXMgb3RoZXIgZWxlbWVudHMgYXJlIGVtcHR5IGFuZCB3ZXJlIGNhdXNpbmcgaXNzdWVzLlxuICAgICAgICAgICAgICogXG4gICAgICAgICAgICAgKiBOb3cgd2UgbG9vcCBiYWNrIHRocm91Z2ggdGhlIHByZXZpb3VzIHNpYmxpbmdzIGxvb2tpbmcgZm9yIHRoZSBmaXJzdCBvbmUgd2l0aCBhIHZhbGlkIGlubmVyIHRleHQgYW5kIHVzaW5nIHRoYXQgXG4gICAgICAgICAgICAgKiBhcyB0aGUgYW5jaG9yIGFuZCBvZmZzZXR0aW5nIG91ciBhZGRBdEluZGV4IGJ5IHRoZSBudW1iZXIgb2YgZW1wdHkgc3RyaW5nIGVsZW1lbnRzIHdlIGZvdW5kLlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBsZXQgcHJldlNpYmxpbmdJbm5lclRleHQgPSBcIlwiXG4gICAgICAgICAgICBsZXQgcHJldlNpYmxpbmdPZmZzZXQgPSAwO1xuICAgICAgICAgICAgZm9yKGxldCBpID0gc2libGluZ3NBYm92ZS5jaGlsZHJlbi5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuXG4gICAgICAgICAgICAgICAgbGV0IG9iaiA9IHNpYmxpbmdzQWJvdmUuY2hpbGRyZW5baV0gYXMgSFRNTEVsZW1lbnQ7XG4gICAgICAgICAgICAgICAgaWYob2JqLmlubmVyVGV4dCAhPT0gXCJcIikge1xuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICBwcmV2U2libGluZ0lubmVyVGV4dCA9IG9iai5pbm5lclRleHQ7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHByZXZTaWJsaW5nT2Zmc2V0Kys7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvciAobGV0IGkgPSB0aGlzLmRvbUxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5kb21MaXN0W2ldLm5vZGVLZXkgPT09IHByZXZTaWJsaW5nSW5uZXJUZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgIGFkZEF0SW5kZXggPSBpICsgMSArIHByZXZTaWJsaW5nT2Zmc2V0O1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgbmV4dEVsSW5kZXggPSBhZGRBdEluZGV4O1xuICAgICAgICBsZXQgbmV4dE9ialRleHQgPSBcIlwiO1xuICAgICAgICBpZiAobmV4dE9iaiAhPT0gdW5kZWZpbmVkKSB7XG5cbiAgICAgICAgICAgIGxldCBmb3VuZE5leHQgPSBmYWxzZTtcbiAgICAgICAgICAgIG5leHRPYmpUZXh0ID0gbmV4dE9iai5pbm5lclRleHQ7XG5cbiAgICAgICAgICAgIGZvciAobGV0IGkgPSBhZGRBdEluZGV4OyBpIDwgdGhpcy5kb21MaXN0Lmxlbmd0aDsgaSsrKSB7XG5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5kb21MaXN0W2ldLm5vZGVLZXkgPT09IG5leHRPYmouaW5uZXJUZXh0LnRyaW0oKSkge1xuXG4gICAgICAgICAgICAgICAgICAgIG5leHRFbEluZGV4ID0gaTtcbiAgICAgICAgICAgICAgICAgICAgZm91bmROZXh0ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gY29uc29sZS5sb2coXCIgUHJldjogXCIsIEFycmF5LmZyb20oc2libGluZ3NBYm92ZS5jaGlsZHJlbikuc2xpY2UoLTMpLCBcIkFkZGluZzogXCIsIG9iai5vcmlnaW5hbEVsZW1lbnQsIFwiIE5leHQ6IFwiLCBzaWJsaW5nc0JlbG93LmNoaWxkcmVuWzBdLCBcIk92ZXJ3cml0aW5nOlwiLCB0aGlzLmRvbUxpc3Quc2xpY2UoYWRkQXRJbmRleCwgbmV4dEVsSW5kZXgpKTtcbiAgICAgICAgdGhpcy5kb21MaXN0LnNwbGljZShhZGRBdEluZGV4LCBuZXh0RWxJbmRleCAtIGFkZEF0SW5kZXgsIG9iaik7XG4gICAgICAgIHRoaXMuZG9tT2JqZWN0TWFwLnNldChvYmouVUlELCBvYmopO1xuXG4gICAgICAgIC8vIC8qKlxuICAgICAgICAvLyAgKiBNYWtlIGEgY29weSBvZiB0aGUgbGlzdCB0byBsb2csIG9ubHkgYmVjYXVzZVxuICAgICAgICAvLyAgKiBjb25zb2xlIGxvZyB1cGRhdGVzIGl0cyByZWZlcmVuY2VzIHdpdGggdXBkYXRlcyBpbiBtZW1vcnkuXG4gICAgICAgIC8vICAqL1xuICAgICAgICAvLyBsZXQgeCA9IHRoaXMuZG9tTGlzdC5zbGljZSgwKTtcbiAgICAgICAgLy8gY29uc29sZS5sb2coeCk7XG4gICAgICAgIHJldHVybiBhZGRBdEluZGV4O1xuICAgIH1cblxuICAgIHB1YmxpYyBhZGRPYmplY3RBdEluZGV4KG9iajogRE9NT2JqZWN0LCBpbmRleDogbnVtYmVyKSB7XG5cbiAgICAgICAgdGhpcy5kb21MaXN0LnNwbGljZShpbmRleCwgMCwgb2JqKTtcbiAgICAgICAgdGhpcy5kb21PYmplY3RNYXAuc2V0KG9iai5VSUQsIG9iaik7XG4gICAgfVxuXG4gICAgcHVibGljIHJlbW92ZU9iamVjdChvYmplY3RVSUQ6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICAvLyAvKipcbiAgICAgICAgLy8gICogTWFrZSBhIGNvcHkgb2YgdGhlIGxpc3QgdG8gbG9nXG4gICAgICAgIC8vICAqL1xuICAgICAgICAvLyBsZXQgeCA9IGRvbUxpc3Quc2xpY2UoMCk7XG4gICAgICAgIC8vIGNvbnNvbGUubG9nKHgpO1xuICAgICAgICAvLyBHZXQgdGhlIG9iamVjdCBieSBrZXksIHJlbW92ZSBpdCBmcm9tIHRoZSBtYXAgYW5kIHRoZW5cbiAgICAgICAgLy8gZnJvbSB0aGUgbGlzdC5cbiAgICAgICAgbGV0IG9iaiA9IHRoaXMuZG9tT2JqZWN0TWFwLmdldChvYmplY3RVSUQpO1xuICAgICAgICB0aGlzLmRvbU9iamVjdE1hcC5kZWxldGUob2JqZWN0VUlEKTtcblxuICAgICAgICBpZiAob2JqID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmRvbUxpc3QuY29udGFpbnMob2JqKSkge1xuICAgICAgICAgICAgdGhpcy5kb21MaXN0LnJlbW92ZShvYmopO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuZG9tTGlzdC5sZW5ndGggPT09IDAgJiYgdGhpcy5maWxlTWFuYWdlciAhPT0gbnVsbCkge1xuICAgICAgICAgICAgdGhpcy5maWxlTWFuYWdlci5yZW1vdmVSZWdpb24odGhpcy5yZWdpb25LZXkpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8geCA9IGRvbUxpc3Quc2xpY2UoMCk7XG4gICAgICAgIC8vIGNvbnNvbGUubG9nKHgpO1xuICAgIH1cblxuICAgIHB1YmxpYyB1cGRhdGVFbGVtZW50VGFnKG9iamVjdFVJRDogc3RyaW5nLCBuZXdUYWc6IERPTU9iamVjdFRhZyk6IHZvaWQge1xuXG4gICAgICAgIGxldCBvYmogPSB0aGlzLmRvbU9iamVjdE1hcC5nZXQob2JqZWN0VUlEKTtcbiAgICAgICAgb2JqLnRhZyA9IG5ld1RhZztcbiAgICB9XG5cbiAgICBwdWJsaWMgc2V0UmVnaW9uYWxTZXR0aW5ncyhyZWdpb25TZXR0aW5nczogTXVsdGlDb2x1bW5TZXR0aW5ncyk6IHZvaWQge1xuICAgICAgICB0aGlzLnJlZ2lvbmFsU2V0dGluZ3MgPSByZWdpb25TZXR0aW5ncztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIG9iamVjdCBjb250YWluaW5nIGFsbCBuZWNlc3NhcnkgaW5mb3JtYXRpb24gZm9yIHRoZSByZWdpb25cbiAgICAgKiB0byBiZSByZW5kZXJlZCB0byB0aGUgcHJldmlldyBwYW5lLlxuICAgICAqXG4gICAgICogQHJldHVybnMgYSBNdWx0aUNvbHVtblJlbmRlckRhdGEgb2JqZWN0IHdpdGggdGhlIHJvb3QgRE9NIGVsZW1lbnQsIHNldHRpbmdzIG9iamVjdCwgYW5kXG4gICAgICogYWxsIGNoaWxkIG9iamVjdHMgaW4gdGhlIG9yZGVyIHRoZXkgc2hvdWxkIGJlIHJlbmRlcmVkLlxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRSZWdpb25SZW5kZXJEYXRhKCk6IE11bHRpQ29sdW1uUmVuZGVyRGF0YSB7XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHBhcmVudFJlbmRlckVsZW1lbnQ6IHRoaXMucmVnaW9uUGFyZW50LFxuICAgICAgICAgICAgcGFyZW50UmVuZGVyU2V0dGluZ3M6IHRoaXMucmVnaW9uYWxTZXR0aW5ncyxcbiAgICAgICAgICAgIGRvbU9iamVjdHM6IHRoaXMuZG9tTGlzdFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgZnVjdGlvbiBpcyBjYWxsZWQgd2hlbiBhIHN0YXJ0IHRhZyBpcyByZW1vdmVkIGZyb20gdmlldyBtZWFuaW5nXG4gICAgICogb3VyIHBhcmVudCBlbGVtZW50IHN0b3JpbmcgdGhlIG11bHRpLWNvbHVtbiByZWdpb24gaXMgcmVtb3ZlZC4gSXRcbiAgICAgKiByZW1vdmVzIHRoZSBDU1MgY2xhc3MgZnJvbSBhbGwgb2YgdGhlIGVsZW1lbnRzIHNvIHRoZXkgd2lsbCBiZVxuICAgICAqIHJlLXJlbmRlcmVkIGluIHRoZSBwcmV2aWV3IHdpbmRvdy5cbiAgICAgKi9cbiAgICBwdWJsaWMgZGlzcGxheU9yaWdpbmFsRWxlbWVudHMoKSB7XG5cblxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuZG9tTGlzdC5sZW5ndGg7IGkrKykge1xuXG4gICAgICAgICAgICBpZiAodGhpcy5kb21MaXN0W2ldLm9yaWdpbmFsRWxlbWVudCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZG9tTGlzdFtpXS5vcmlnaW5hbEVsZW1lbnQucmVtb3ZlQ2xhc3NlcyhbTXVsdGlDb2x1bW5TdHlsZUNTUy5SZWdpb25FbmRUYWcsXG4gICAgICAgICAgICAgICAgTXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5FbmRUYWcsXG4gICAgICAgICAgICAgICAgTXVsdGlDb2x1bW5TdHlsZUNTUy5SZWdpb25TZXR0aW5ncyxcbiAgICAgICAgICAgICAgICBNdWx0aUNvbHVtblN0eWxlQ1NTLlJlZ2lvbkNvbnRlbnRdKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5kb21MaXN0W2ldLm9yaWdpbmFsRWxlbWVudC5wYXJlbnRFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZG9tTGlzdFtpXS5vcmlnaW5hbEVsZW1lbnQucGFyZW50RWxlbWVudC5yZW1vdmVDaGlsZCh0aGlzLmRvbUxpc3RbaV0ub3JpZ2luYWxFbGVtZW50KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgXG4gICAgcHVibGljIGdldElEKCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiB0aGlzLnJlZ2lvbktleTtcbiAgICB9XG5cbiAgICBwdWJsaWMgdXBkYXRlUmVuZGVyZWRNYXJrZG93bigpIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFRoaXMgZnVuY3Rpb24gYWN0cyBhcyB0aGUgdXBkYXRlIGxvb3AgZm9yIHRoZSBtdWx0aS1jb2x1bW4gcmVnaW9ucy5cbiAgICAgICAgICogSGVyZSB3ZSBsb29wIHRocm91Z2ggYWxsIG9mIHRoZSBlbGVtZW50cyB3aXRoaW4gdGhlIHJlbmRlcmVkIHJlZ2lvbiBhbmRcbiAgICAgICAgICogcG90ZW50aWFsbHkgdXBkYXRlIGhvdyB0aGluZ3MgYXJlIHJlbmRlcmVkLiBXZSBuZWVkIHRvIGRvIHRoaXMgZm9yXG4gICAgICAgICAqIGNvbXBhdGFiaWxpdHkgd2l0aCBvdGhlciBwbHVnaW5zLlxuICAgICAgICAgKlxuICAgICAgICAgKiBJZiB0aGUgbXVsdGktY29sdW1uIHJlZ2lvbiBpcyByZW5kZXJlZCBiZWZvcmUgb3RoZXIgcGx1Z2lucyB0aGF0IGVmZmVjdFxuICAgICAgICAgKiBjb250ZW50IHdpdGhpbiB0aGUgcmVnaW9uIG91ciByZW5kZXJlZCBkYXRhIG1heSBub3QgcHJvcGVybHkgZGlzcGxheVxuICAgICAgICAgKiB0aGUgY29udGVudCBmcm9tIHRoZSBvdGhlciBwbHVnaW4uIEhlcmUgd2UgbG9vcCB0aHJvdWdoIHRoZSBlbGVtZW50c1xuICAgICAgICAgKiBhZnRlciBhbGwgcGx1Z2lucyBoYXZlIGhhZCBhIGNoYW5jZSB0byBydW4gYW5kIGNhbiBtYWtlIGNoYW5nZXMgdG8gdGhlXG4gICAgICAgICAqIERPTSBhdCB0aGlzIHBvaW50LlxuICAgICAgICAgKi9cbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmRvbUxpc3QubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICAgICAgbGV0IGVsZW1lbnRUeXBlID0gdGhpcy5kb21MaXN0W2ldLmVsZW1lbnRUeXBlO1xuICAgICAgICAgICAgaWYoZWxlbWVudFR5cGUgPT09IFwidW5SZW5kZXJlZFwiKSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogSWYgdGhlIGVsZW1lbnQgaXMgbm90IGN1cnJlbnRseSBhIHNwZWNpYWwgcmVuZGVyIGVsZW1lbnQgd2UgY2hlY2sgYWdhaW5cbiAgICAgICAgICAgICAqIGFzIHRoZSBvcmlnaW5hbCBlbGVtZW50IG1heSBoYXZlIGJlZW4gdXBkYXRlZC5cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgaWYoZWxlbWVudFR5cGUgPT09IFwidW5kZWZpbmVkXCIgfHxcbiAgICAgICAgICAgICAgIGVsZW1lbnRUeXBlID09PSBcImJhc2ljRWxlbWVudFwiIHx8XG4gICAgICAgICAgICAgICBlbGVtZW50VHlwZSA9PT0gXCJzcGVjaWFsUmVuZGVyXCIpIHtcblxuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBuZXcgcmVzdWx0IHJldHVybnMgYXMgYSBzcGVjaWFsIHJlbmRlcmVyIHdlIHVwZGF0ZSBzb1xuICAgICAgICAgICAgICAgIC8vIHRoaXMgd29udCBydW4gYWdhaW4gZm9yIHRoaXMgaXRlbS5cbiAgICAgICAgICAgICAgICBlbGVtZW50VHlwZSA9IGdldEVsZW1lbnRSZW5kZXJUeXBlKHRoaXMuZG9tTGlzdFtpXS5vcmlnaW5hbEVsZW1lbnQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBsZXQgdGFza0xpc3RPYmogPSAodGhpcy5kb21MaXN0W2ldIGFzIFRhc2tMaXN0RE9NT2JqZWN0KVxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBIZXJlIHdlIGNoZWNrIGZvciBzcGVjaWFsIGNhc2VzXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGlmICh0YXNrTGlzdE9iaiAmJiBcbiAgICAgICAgICAgICAgICBlbGVtZW50VHlwZSA9PT0gXCJkYXRhdmlld0pTRW1iZWRcIikge1xuXG4gICAgICAgICAgICAgICAgaWYodGhpcy5kb21MaXN0W2ldLmNsb25lZEVsZW1lbnRSZWFkeUZvclVwZGF0ZSgpKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgY2xvbmVFbGVtZW50KHRoaXMuZG9tTGlzdFtpXSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZml4Q2xvbmVkQ2hlY2tMaXN0QnV0dG9ucyh0aGlzLmRvbUxpc3RbaV0gYXMgVGFza0xpc3RET01PYmplY3QsIHRydWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5maXhDbG9uZWRDaGVja0xpc3RCdXR0b25zKHRoaXMuZG9tTGlzdFtpXSBhcyBUYXNrTGlzdERPTU9iamVjdClcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29udGludWVcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHRhc2tMaXN0T2JqICYmIFxuICAgICAgICAgICAgICAgIGVsZW1lbnRUeXBlID09PSBcImJhc2ljRWxlbWVudFwiKSB7XG5cbiAgICAgICAgICAgICAgICB0aGlzLmZpeENsb25lZENoZWNrTGlzdEJ1dHRvbnModGhpcy5kb21MaXN0W2ldIGFzIFRhc2tMaXN0RE9NT2JqZWN0KTtcbiAgICAgICAgICAgICAgICBjb250aW51ZVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihlbGVtZW50VHlwZSA9PT0gXCJiYXNpY0VsZW1lbnRcIikge1xuICAgICAgICAgICAgICAgIHRoaXMuZG9tTGlzdFtpXS5lbGVtZW50VHlwZSA9IFwiYmFzaWNFbGVtZW50XCJcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoZWxlbWVudFR5cGUgPT09IFwiaW1hZ2VFbWJlZFwiKSB7Ly9FbGVtZW50UmVuZGVyVHlwZS5maXhlZEVsZW1lbnRSZW5kZXIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRvbUxpc3RbaV0uZWxlbWVudFR5cGUgPSBlbGVtZW50VHlwZTtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoZWxlbWVudFR5cGUgPT09IFwiYnV0dG9uUGx1Z2luXCIpIHtcbiAgICAgICAgICAgICAgICBwcm9jZXNzQnV0dG9uUGx1Z2luVXBkYXRlKHRoaXMuZG9tTGlzdFtpXSlcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoZWxlbWVudFR5cGUgPT09IFwicGRmRW1iZWRcIikge1xuICAgICAgICAgICAgICAgIHRoaXMuZG9tTGlzdFtpXS5lbGVtZW50VHlwZSA9IGVsZW1lbnRUeXBlO1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0VXBEdWFsUmVuZGVyKHRoaXMuZG9tTGlzdFtpXSk7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGVsZW1lbnRUeXBlID09PSBcImRpY2VSb2xsZXJcIiB8fFxuICAgICAgICAgICAgICAgZWxlbWVudFR5cGUgPT09IFwiYWRtb25pdGlvbkZvbGRcIiB8fFxuICAgICAgICAgICAgICAgZWxlbWVudFR5cGUgPT09IFwiY2FsbG91dENvcHlCdXR0b25cIiB8fFxuICAgICAgICAgICAgICAgZWxlbWVudFR5cGUgPT09IFwiZGF0YXZpZXdQbHVnaW5cIiB8fFxuICAgICAgICAgICAgICAgZWxlbWVudFR5cGUgPT09IFwiaW50ZXJuYWxFbWJlZFwiIHx8XG4gICAgICAgICAgICAgICBlbGVtZW50VHlwZSA9PT0gXCJkYXRhdmlld0pTQ2FudmFzRW1iZWRcIiB8fFxuICAgICAgICAgICAgICAgZWxlbWVudFR5cGUgPT09IFwiZGF0YXZpZXdKU0VtYmVkXCIgfHwgXG4gICAgICAgICAgICAgICBlbGVtZW50VHlwZSA9PT0gXCJkYXRhdmlld0lubGluZVF1ZXJ5XCIgfHxcbiAgICAgICAgICAgICAgIGVsZW1lbnRUeXBlID09PSBcInRhc2tzUGx1Z2luXCJcbiAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIHRoaXMuZG9tTGlzdFtpXS5lbGVtZW50VHlwZSA9IGVsZW1lbnRUeXBlO1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0VXBEdWFsUmVuZGVyKHRoaXMuZG9tTGlzdFtpXSk7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIGZ1bmN0aW9uIHRha2VzIGluIHRoZSBvcmlnaW5hbCBlbGVtZW50IGFuZCBpdHMgY2xvbmUgYW5kIGNoZWNrcyBpZlxuICAgICAqIHRoZSBlbGVtZW50IGNvbnRhaW5zIGEgdGFzay1saXN0LWl0ZW0gY2xhc3MuIElmIHNvIGl0IGxvb3BzIHRocm91Z2ggYWxsXG4gICAgICogaXRlbXMgaW4gdGhlIGxpc3QgYW5kIGZpeGVzIHRoZWlyIGNoZWNrYm94ZXMgdG8gcHJvcGVybHkgZmlyZSBhbiBldmVudC5cbiAgICAgKiBUaGUgbmV3IGNoZWNrYm94IGNhbGxzIHRoZSBjbGljayBmdW5jdGlvbiBvbiB0aGUgb3JpZ2luYWwgY2hlY2tib3ggc29cbiAgICAgKiBjb21wYXRhYmlsaXR5IHdpdGggb3RoZXIgcGx1Z2lucyAqc2hvdWxkKiByZW1haW4uXG4gICAgICogQHBhcmFtIGRvbUVsZW1lbnRcbiAgICAgKiBAcGFyYW0gaW5pdGFsaXplQ2hlY2tib3hlc1xuICAgICAqL1xuICAgIHByb3RlY3RlZCBmaXhDbG9uZWRDaGVja0xpc3RCdXR0b25zKGRvbUVsZW1lbnQ6IFRhc2tMaXN0RE9NT2JqZWN0LCBpbml0YWxpemVDaGVja2JveGVzOiBib29sZWFuID0gZmFsc2UpIHtcblxuICAgICAgICBpZihkb21FbGVtZW50Lm9yaWdpbmFsRWxlbWVudCA9PT0gbnVsbCB8fCBkb21FbGVtZW50LmNsb25lZEVsZW1lbnQgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBlbGVtZW50OiBIVE1MRWxlbWVudCA9IGRvbUVsZW1lbnQub3JpZ2luYWxFbGVtZW50O1xuICAgICAgICBsZXQgY2xvbmVkRWxlbWVudDogSFRNTEVsZW1lbnQgPSBkb21FbGVtZW50LmNsb25lZEVsZW1lbnQ7XG5cbiAgICAgICAgbGV0IGNsb25lZExpc3RDaGVja2JveGVzID0gQXJyYXkuZnJvbShjbG9uZWRFbGVtZW50LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoXCJ0YXNrLWxpc3QtaXRlbVwiKSkgYXMgSFRNTEVsZW1lbnRbXTtcbiAgICAgICAgbGV0IG9yaWdpbmFsTGlzdENoZWNrYm94ZXMgPSBBcnJheS5mcm9tKGVsZW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZShcInRhc2stbGlzdC1pdGVtXCIpKSBhcyBIVE1MRWxlbWVudFtdO1xuXG4gICAgICAgIGlmIChpbml0YWxpemVDaGVja2JveGVzID09PSB0cnVlKSB7XG5cbiAgICAgICAgICAgIGRvbUVsZW1lbnQub3JpZ2luYWxDaGVja2JveGVzID0gb3JpZ2luYWxMaXN0Q2hlY2tib3hlcztcbiAgICAgICAgICAgIC8vIFdoZW4gd2UgaW5pdGFsaXplIHdlIHJlbW92ZSB0aGUgb2xkIGlucHV0IGNoZWNrYm94IHRoYXQgY29udGFpbnNcbiAgICAgICAgICAgIC8vIHRoZSB3ZWlyZCBjYWxsYmFjayBzaXR1YXRpb24gY2F1c2luZyB0aGUgYnVnLiBUaGVuIHdlIGNyZWF0ZSBhIG5ld1xuICAgICAgICAgICAgLy8gY2hlY2tib3ggdG8gcmVwbGFjZSBpdCBhbmQgc2V0IGl0IHVwIHRvIGZpcmUgdGhlIGNsaWNrIGV2ZW50IG9uXG4gICAgICAgICAgICAvLyB0aGUgb3JpZ2luYWwgY2hlY2tib3ggc28gZnVuY3Rpb25hbGl0eSBpcyByZXN0b3JlZC5cbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3JpZ2luYWxMaXN0Q2hlY2tib3hlcy5sZW5ndGg7IGkrKykge1xuXG4gICAgICAgICAgICAgICAgY29uc3QgY2hlY2tib3ggPSBjcmVhdGVFbCgnaW5wdXQnKTtcblxuICAgICAgICAgICAgICAgIGxldCBvcmlnaW5hbElucHV0ID0gb3JpZ2luYWxMaXN0Q2hlY2tib3hlc1tpXS5nZXRFbGVtZW50c0J5VGFnTmFtZShcImlucHV0XCIpWzBdXG5cbiAgICAgICAgICAgICAgICBsZXQgaXNDaGVja2VkID0gZmFsc2VcbiAgICAgICAgICAgICAgICBpZihvcmlnaW5hbElucHV0KSB7XG4gICAgICAgICAgICAgICAgICAgIGlzQ2hlY2tlZCA9IG9yaWdpbmFsSW5wdXQuY2hlY2tlZFxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5kZWJ1ZyhcIkNvdWxkIG5vdCBmaW5kIG9yaWdpbmFsIGNoZWNrYm94LiBJcyBpdCBudWxsP1wiKVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGxldCBvbGRDaGVja2JveCA9IFRhc2tMaXN0RE9NT2JqZWN0LmdldENoaWxkQ2hlY2tib3goY2xvbmVkTGlzdENoZWNrYm94ZXNbaV0pXG4gICAgICAgICAgICAgICAgY2xvbmVkTGlzdENoZWNrYm94ZXNbaV0ucmVwbGFjZUNoaWxkKGNoZWNrYm94LCBvbGRDaGVja2JveCk7XG5cbiAgICAgICAgICAgICAgICBjaGVja2JveC5jaGVja2VkID0gaXNDaGVja2VkXG4gICAgICAgICAgICAgICAgY2hlY2tib3guYWRkQ2xhc3MoJ3Rhc2stbGlzdC1pdGVtLWNoZWNrYm94Jyk7XG4gICAgICAgICAgICAgICAgY2hlY2tib3gudHlwZSA9ICdjaGVja2JveCc7XG4gICAgICAgICAgICAgICAgY2hlY2tib3gub25DbGlja0V2ZW50KCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgZG9tRWxlbWVudC5jaGVja2JveENsaWNrZWQoaSk7XG4gICAgICAgICAgICAgICAgICAgIGlmKGNoZWNrYm94LmNoZWNrZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsb25lZExpc3RDaGVja2JveGVzW2ldLmFkZENsYXNzKFwiaXMtY2hlY2tlZFwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgY2xvbmVkTGlzdENoZWNrYm94ZXNbaV0uc2V0QXR0cihcImRhdGEtdGFza1wiLCBcInhcIilcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsb25lZExpc3RDaGVja2JveGVzW2ldLnJlbW92ZUNsYXNzKFwiaXMtY2hlY2tlZFwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgY2xvbmVkTGlzdENoZWNrYm94ZXNbaV0uc2V0QXR0cihcImRhdGEtdGFza1wiLCBcIiBcIilcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuXG4gICAgICAgICAgICAvLyBXaGVuZXZlciB3ZSByZWFjaCB0aGlzIHBvaW50IHdlIHVwZGF0ZSBvdXIgbGlzdCBvZiBvcmlnaW5hbCBjaGVja2JveGVzXG4gICAgICAgICAgICAvLyB0aGF0IG1heSBiZSBkaWZmZXJlbnQgZnJvbSBvdXIgY2FjaGUuIFRoaXMgaXMgZHVlIHRvIGhvdyBvYnNpZGlhblxuICAgICAgICAgICAgLy8gY2hhbmdlcyB0aGUgRE9NIHVuZGVybmVhdGggdXMgc28gd2UgbmVlZCB0byBjb25zdGFudGx5IHVwZGF0ZSBvdXIgY2FjaGUuXG4gICAgICAgICAgICBkb21FbGVtZW50Lm9yaWdpbmFsQ2hlY2tib3hlcyA9IG9yaWdpbmFsTGlzdENoZWNrYm94ZXM7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBXaGVuIHRoZSBUYXNrcyBwbHVnaW4gaXMgaW5zdGFsbGVkIHRoZSBjbG9uZWQgY29weSBvZiB0aGUgb3JpZ2luYWwgZWxlbWVudCBjb250YWluc1xuICAgICAgICAvLyBhbiBleHRyYSBlbGVtZW50IGZvciBzb21lIHJlYXNvbi4gSWYgdGhpcyBvY2N1cnMgZm9yIG90aGVyIHJlYXNvbnMgaGVyZSB3ZSBhZGp1c3RcbiAgICAgICAgLy8gdGhhdCB0byBrZWVwIHRoZSBjbG9uZSB0aGUgc2FtZSBhcyB0aGUgb3JpZ2luYWwuXG4gICAgICAgIGlmIChjbG9uZWRMaXN0Q2hlY2tib3hlcy5sZW5ndGggPiBvcmlnaW5hbExpc3RDaGVja2JveGVzLmxlbmd0aCkge1xuXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gb3JpZ2luYWxMaXN0Q2hlY2tib3hlcy5sZW5ndGg7IGkgPCBjbG9uZWRMaXN0Q2hlY2tib3hlcy5sZW5ndGg7IGkrKykge1xuXG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgY2xvbmVkTGlzdENoZWNrYm94ZXNbaV0uZGV0YWNoKClcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKFwiTm8gY2hpbGQgZm91bmQgd2hlbiByZW1vdmluZyBmcm9tIGxpc3QuXCIpXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIHNldFVwRHVhbFJlbmRlcihkb21FbGVtZW50OiBET01PYmplY3QpIHtcblxuICAgICAgICAvKipcbiAgICAgICAgICogSWYgb3VyIGVsZW1lbnQgaXMgb2YgXCJzcGVjaWFsUmVuZGVyXCIgdHlwZSBpdCAqbWF5KiBuZWVkIHRvIGJlIHJlbmRlcmVkXG4gICAgICAgICAqIHVzaW5nIHRoZSBvcmlnaW5hbCBlbGVtZW50IHJhdGhlciB0aGFuIGEgY29weS4gRm9yIGV4YW1wbGUsIGFuIGVsZW1lbnRcbiAgICAgICAgICogbWF5IGhhdmUgYW4gb25DbGljayBldmVudCB0aGF0IHdvdWxkIG5vdCBnZXQgY29wcGllZCB0byB0aGUgY2xvbmUuXG4gICAgICAgICAqXG4gICAgICAgICAqIElmIHdlIGp1c3QgbW92ZWQgdGhlc2UgZWxlbWVudHMgaW50byB0aGUgcmVnaW9uIGl0IHdvdWxkIGdldFxuICAgICAgICAgKiBtb3ZlZCBiYWNrIG91dCBpbnRvIHRoZSBvcmlnaW5hbCBsb2NhdGlvbiBpbiB0aGUgRE9NIGJ5IG9ic2lkaWFuXG4gICAgICAgICAqIHdoZW4gc2Nyb2xsaW5nIG9yIHdoZW4gdGhlIGZpbGUgaXMgdXBkYXRlZC4gT24gdGhlIG5leHQgcmVmcmVzaCBpdFxuICAgICAgICAgKiB3b3VsZCBiZSBtb3ZlZCBiYWNrIGJ1dCB0aGF0IGNhbiBsZWFkIHRvIGEgcmVnaW9uIGp1bXBpbmdcbiAgICAgICAgICogYXJvdW5kIGFzIHRoZSBpdGVtIGlzIG1vdmVkIGluIGFuZCBvdXQuXG4gICAgICAgICAqXG4gICAgICAgICAqIEhlcmUgd2Ugc2V0IHVwIHRoZSBkaXYgdG8gY29udGFpbiB0aGUgZWxlbWVudCBhbmQgY3JlYXRlXG4gICAgICAgICAqIGEgdmlzdWFsIG9ubHkgY2xvbmUgb2YgaXQuIFRoZSBjbG9uZSB3aWxsIG9ubHkgYmUgdmlzaWJsZVxuICAgICAgICAgKiB3aGVuIHRoZSBvcmlnaW5hbCBpcyBub3QgaW4gdGhlIG11bHRpLWNvbHVtbiByZWdpb24gc28gaXRcbiAgICAgICAgICogc2F2ZXMgdXMgZnJvbSB0aGUgdmlzdWFsIG5vaXNlIG9mIHRoZSByZWdpb24ganVtcGluZyBhcm91bmQuXG4gICAgICAgICAqL1xuXG4gICAgICAgICBsZXQgb3JpZ2luYWxFbGVtZW50ID0gZG9tRWxlbWVudC5vcmlnaW5hbEVsZW1lbnQ7XG4gICAgICAgICBsZXQgY2xvbmVkRWxlbWVudCA9IGRvbUVsZW1lbnQuY2xvbmVkRWxlbWVudDtcbiAgICAgICAgIGxldCBjb250YWluZXJFbGVtZW50OiBIVE1MRGl2RWxlbWVudCA9IGRvbUVsZW1lbnQuZWxlbWVudENvbnRhaW5lcjtcblxuICAgICAgICAvLyBHZXQgaGVpZ2h0IG9mIHRoZSBvcmlnaW5hbCBhbmQgY2xvbmVkIGVsZW1lbnQuIElmIHRoZSBlbGVtZW50IGlzIG5vdCBjdXJyZW50bHkgcmVuZGVyZWRcbiAgICAgICAgLy8gaXQgd2lsbCBoYXZlIDAgaGVpZ2h0IHNvIHdlIG5lZWQgdG8gdGVtcG9yYXJpbHkgcmVuZGVyIGl0IHRvIGdldCB0aGUgaGVpZ2h0LlxuICAgICAgICBsZXQgb3JpZ2luYWxFbGVtZW50SGVpZ2h0ID0gZ2V0RWxlbWVudENsaWVudEhlaWdodChvcmlnaW5hbEVsZW1lbnQsIGNvbnRhaW5lckVsZW1lbnQpO1xuICAgICAgICBsZXQgY2xvbmVkRWxlbWVudEhlaWdodCA9IGdldEVsZW1lbnRDbGllbnRIZWlnaHQoY2xvbmVkRWxlbWVudCwgY29udGFpbmVyRWxlbWVudCk7XG5cbiAgICAgICAgaWYoZG9tRWxlbWVudC5lbGVtZW50VHlwZSA9PT0gXCJwZGZFbWJlZFwiKSB7XG4gICAgICAgICAgICB1cGRhdGVQREZFbWJlZChkb21FbGVtZW50KVxuICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgIH1cbiAgICAgICAgaWYoZG9tRWxlbWVudC5lbGVtZW50VHlwZSA9PT0gXCJkYXRhdmlld0pTQ2FudmFzRW1iZWRcIikge1xuICAgICAgICAgICAgcmVSZW5kZXJEYXRhdmlld0pTKGRvbUVsZW1lbnQpXG4gICAgICAgICAgICByZXR1cm5cbiAgICAgICAgfVxuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBXZSBvbmx5IHdhbnQgdG8gY2xvbmUgdGhlIGVsZW1lbnQgb25jZSB0byByZWR1Y2UgR0MuIEJ1dCBpZiB0aGUgY2xvbmVkIFxuICAgICAgICAgKiBlbGVtZW50J3MgaGVpZ2h0IGlzIG5vdCBlcXVhbCB0byB0aGUgb3JpZ2luYWwgZWxlbWVudCwgdGhpcyBtZWFucyB0aGVcbiAgICAgICAgICogaXRlbSBlbGVtZW50IGhhcyBiZWVuIHVwZGF0ZWQgc29tZXdoZXJlIGVsc2Ugd2l0aG91dCB0aGUgZG9tIGJlaW5nIFxuICAgICAgICAgKiByZWZyZXNoZWQuIFRoaXMgY2FuIG9jY3VyIHdoZW4gZWxlbWVudHMgYXJlIHVwZGF0ZWQgYnkgb3RoZXIgcGx1Z2lucywgXG4gICAgICAgICAqIHN1Y2ggYXMgRGF0YXZpZXcuXG4gICAgICAgICAqL1xuICAgICAgICBpZigoY2xvbmVkRWxlbWVudCA9PT0gbnVsbCAgfHwgXG4gICAgICAgICAgIE1hdGguYWJzKGNsb25lZEVsZW1lbnRIZWlnaHQgLSBvcmlnaW5hbEVsZW1lbnRIZWlnaHQpID4gMTAgfHxcbiAgICAgICAgICAgZG9tRWxlbWVudC5jbG9uZWRFbGVtZW50UmVhZHlGb3JVcGRhdGUoKSA9PT0gdHJ1ZSkpIHtcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCJVcGRhdGluZyBDbG9uZWQgRWxlbWVudC5cIiwgRWxlbWVudFJlbmRlclR5cGVbZG9tRWxlbWVudC5lbGVtZW50VHlwZV0sIGNsb25lZEVsZW1lbnRIZWlnaHQsIG9yaWdpbmFsRWxlbWVudEhlaWdodClcbiAgICAgICAgICAgIC8vIFVwZGF0ZSBjbG9uZSBhbmQgcmVmZXJlbmNlLlxuICAgICAgICAgICAgY2xvbmVFbGVtZW50KGRvbUVsZW1lbnQpO1xuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICAvKiogXG4gICAgICAgICAqIElmIHRoZSBjb250YWluZXIgZWxlbWVudCBoYXMgbGVzcyB0aGFuIDIgY2hpbGRyZW4gd2UgbmVlZCB0byBtb3ZlIHRoZVxuICAgICAgICAgKiBvcmlnaW5hbCBlbGVtZW50IGJhY2sgaW50byBpdC4gSG93ZXZlciBzb21lIGVsZW1lbnRzIGNvbnN0YW50bHkgZ2V0IG1vdmVkXG4gICAgICAgICAqIGluIGFuZCBvdXQgY2F1c2luZyBzb21lIHVud2FudGVkIGJlaGF2aW9yLiBUaG9zZSBlbGVtZW50IHdpbGwgYmUgdGFnZ2VkXG4gICAgICAgICAqIGFzIHNwZWNpYWxTaW5nbGVFbGVtZW50UmVuZGVyIHNvIHdlIGlnbm9yZSB0aG9zZSBlbGVtZW50cyBoZXJlLlxuICAgICAgICAgKi9cbiAgICAgICAgaWYoZG9tRWxlbWVudC5lbGVtZW50Q29udGFpbmVyLmNoaWxkcmVuLmxlbmd0aCA8IDIgJiYgXG4gICAgICAgICAgIGRvbUVsZW1lbnQuZWxlbWVudFR5cGUgIT09IFwiZGF0YXZpZXdQbHVnaW5cIiAmJlxuICAgICAgICAgICBkb21FbGVtZW50LmVsZW1lbnRUeXBlICE9PSBcImludGVybmFsRW1iZWRcIiAmJlxuICAgICAgICAgICBkb21FbGVtZW50LmVsZW1lbnRUeXBlICE9PSBcImRhdGF2aWV3SlNFbWJlZFwiKSB7XG5cbiAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKFwiVXBkYXRpbmcgZHVhbCByZW5kZXJpbmcuXCIsIGRvbUVsZW1lbnQsIGRvbUVsZW1lbnQub3JpZ2luYWxFbGVtZW50LnBhcmVudEVsZW1lbnQsIGRvbUVsZW1lbnQub3JpZ2luYWxFbGVtZW50LnBhcmVudEVsZW1lbnQ/LmNoaWxkRWxlbWVudENvdW50KTtcblxuICAgICAgICAgICAgLy8gTWFrZSBzdXJlIG91ciBDU1MgaXMgdXAgdG8gZGF0ZS5cbiAgICAgICAgICAgIG9yaWdpbmFsRWxlbWVudC5hZGRDbGFzcyhNdWx0aUNvbHVtbkxheW91dENTUy5PcmlnaW5hbEVsZW1lbnRUeXBlKTtcbiAgICAgICAgICAgIGNsb25lZEVsZW1lbnQuYWRkQ2xhc3MoTXVsdGlDb2x1bW5MYXlvdXRDU1MuQ2xvbmVkRWxlbWVudFR5cGUpO1xuICAgICAgICAgICAgY2xvbmVkRWxlbWVudC5yZW1vdmVDbGFzc2VzKFtNdWx0aUNvbHVtblN0eWxlQ1NTLlJlZ2lvbkNvbnRlbnQsIE11bHRpQ29sdW1uTGF5b3V0Q1NTLk9yaWdpbmFsRWxlbWVudFR5cGVdKTtcbiAgICBcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSBjb250YWluZXJFbGVtZW50LmNoaWxkcmVuLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgICAgICAgICAgY29udGFpbmVyRWxlbWVudC5jaGlsZHJlbltpXS5kZXRhY2goKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnRhaW5lckVsZW1lbnQuYXBwZW5kQ2hpbGQob3JpZ2luYWxFbGVtZW50KTtcbiAgICAgICAgICAgIGNvbnRhaW5lckVsZW1lbnQuYXBwZW5kQ2hpbGQoY2xvbmVkRWxlbWVudCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHVwIHRoZSBDU1MgY2xhc3NlcyBhbmQgdGhlIG51bWJlciBvZiBjb2x1bW5zIGJhc2VkIG9uIHRoZSBwYXNzZWQgc2V0dGluZ3MuXG4gICAgICogQHBhcmFtIHNldHRpbmdzIFRoZSB1c2VyIGRlZmluZWQgc2V0dGluZ3MgdGhhdCBkZXRlcm1pbmUgd2hhdCBDU1MgaXMgc2V0IGhlcmUuXG4gICAgICogQHBhcmFtIG11bHRpQ29sdW1uUGFyZW50IFRoZSBwYXJlbnQgb2JqZWN0IHRoYXQgdGhlIGNvbHVtbiBkaXZzIHdpbGwgYmUgY3JlYXRlZCB1bmRlci5cbiAgICAgKiBAcmV0dXJucyBUaGUgbGlzdCBvZiBjb2x1bW4gZGl2cyBjcmVhdGVkIHVuZGVyIHRoZSBwYXNzZWQgcGFyZW50IGVsZW1lbnQuXG4gICAgICovXG4gICAgZ2V0Q29sdW1uQ29udGVudERpdnMoc2V0dGluZ3M6IE11bHRpQ29sdW1uU2V0dGluZ3MsIG11bHRpQ29sdW1uUGFyZW50OiBIVE1MRGl2RWxlbWVudCk6IEhUTUxEaXZFbGVtZW50W10ge1xuXG4gICAgICAgIGxldCBjb2x1bW5Db250ZW50RGl2czogSFRNTERpdkVsZW1lbnRbXSA9IFtdXG4gICAgICAgIFxuICAgICAgICBpZih0eXBlb2Ygc2V0dGluZ3MuY29sdW1uU2l6ZSA9PT0gXCJzdHJpbmdcIiAmJlxuICAgICAgICAgICBpc0NvbHVtbkxheW91dChzZXR0aW5ncy5jb2x1bW5TaXplKSAgICAgJiYgXG4gICAgICAgICAgIChzZXR0aW5ncy5udW1iZXJPZkNvbHVtbnMgPT09IDIgfHwgc2V0dGluZ3MubnVtYmVyT2ZDb2x1bW5zID09PSAzKSkgeyAgICAgIFxuXG4gICAgICAgICAgICBzZXR0aW5ncy5jb2x1bW5TaXplID0gdmFsaWRhdGVDb2x1bW5MYXlvdXQoc2V0dGluZ3MuY29sdW1uU2l6ZSlcbiAgICAgICAgICAgIG11bHRpQ29sdW1uUGFyZW50LnJlbW92ZUNsYXNzKE11bHRpQ29sdW1uTGF5b3V0Q1NTLkNvbnRlbnRPdmVyZmxvd0F1dG9TY3JvbGxfWCk7XG4gICAgICAgICAgICBtdWx0aUNvbHVtblBhcmVudC5hZGRDbGFzcyhNdWx0aUNvbHVtbkxheW91dENTUy5Db250ZW50T3ZlcmZsb3dIaWRkZW5fWCk7XG5cbiAgICAgICAgICAgIGJ1aWxkU3RhbmRhcmRMYXlvdXRzKHNldHRpbmdzLCBtdWx0aUNvbHVtblBhcmVudCwgY29sdW1uQ29udGVudERpdnMpXG4gICAgICAgICAgICBzZXRNYXhDb2x1bW5IZWlnaHQoKTtcbiAgICAgICAgICAgIHJldHVybiBjb2x1bW5Db250ZW50RGl2cztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHR5cGVvZiBzZXR0aW5ncy5jb2x1bW5TaXplID09PSBcInN0cmluZ1wiICYmXG4gICAgICAgICAgIGlzQ29sdW1uTGF5b3V0KHNldHRpbmdzLmNvbHVtblNpemUpICAgICAmJiBcbiAgICAgICAgICAgc2V0dGluZ3MuY29sdW1uU2l6ZSA9PT0gXCJzdGFuZGFyZFwiICYmIFxuICAgICAgICAgICBzZXR0aW5ncy5udW1iZXJPZkNvbHVtbnMgPiAzICl7XG5cbiAgICAgICAgICAgIHNldHRpbmdzLmNvbHVtblNpemUgPSB2YWxpZGF0ZUNvbHVtbkxheW91dChzZXR0aW5ncy5jb2x1bW5TaXplKTtcbiAgICAgICAgICAgIG11bHRpQ29sdW1uUGFyZW50LnJlbW92ZUNsYXNzKE11bHRpQ29sdW1uTGF5b3V0Q1NTLkNvbnRlbnRPdmVyZmxvd0F1dG9TY3JvbGxfWCk7XG4gICAgICAgICAgICBtdWx0aUNvbHVtblBhcmVudC5hZGRDbGFzcyhNdWx0aUNvbHVtbkxheW91dENTUy5Db250ZW50T3ZlcmZsb3dIaWRkZW5fWCk7XG5cbiAgICAgICAgICAgIGJ1aWxkRXF1YWxMYXlvdXQoc2V0dGluZ3MsIG11bHRpQ29sdW1uUGFyZW50LCBjb2x1bW5Db250ZW50RGl2cyk7XG5cbiAgICAgICAgICAgIHNldE1heENvbHVtbkhlaWdodCgpO1xuICAgICAgICAgICAgcmV0dXJuIGNvbHVtbkNvbnRlbnREaXZzO1xuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICBsZXQgY29sdW1uU2l6ZXM6IEhUTUxTaXppbmdbXSA9IFtdO1xuICAgICAgICAvLyBJZiB0aGUgdXNlciBoYXMgZGVmaW5lZCB0aGUgd2lkdGhzIGluZGl2aWR1YWxseSB0aGVuIHdlIGp1c3QgbmVlZCB0byBjcmVhdGVcbiAgICAgICAgLy8gZWFjaCBjb2x1bW4gaW5kaXZpZHVhbGx5IHdpdGggZWFjaCB3aWR0aCBzaXplLlxuICAgICAgICBpZihBcnJheS5pc0FycmF5KHNldHRpbmdzLmNvbHVtblNpemUpKSB7XG4gICAgICAgICAgICBjb2x1bW5TaXplcyA9IHNldHRpbmdzLmNvbHVtblNpemUuc2xpY2UoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNhbGNDb2x1bW5TaXplcyhzZXR0aW5ncywgY29sdW1uU2l6ZXMpXG4gICAgICAgIH1cblxuICAgICAgICBpZihjb2x1bW5TaXplcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIGNvbHVtblNpemVzLnB1c2goSFRNTFNpemluZy5jcmVhdGUoKS5zZXRXaWR0aCg1MCkuc2V0VW5pdHMoXCIlXCIpKVxuICAgICAgICB9XG5cbiAgICAgICAgZm9yKGxldCBpID0gMDsgaSA8IHNldHRpbmdzLm51bWJlck9mQ29sdW1uczsgaSsrKSB7XG5cbiAgICAgICAgICAgIGxldCBzaXppbmcgPSBnZXRJbmRleGVkQ2xhbXBlZEFycmF5VmFsdWUoaSwgY29sdW1uU2l6ZXMpO1xuXG4gICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2cy5wdXNoKG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgY2xzOiBgJHtNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtbkNvbnRlbnR9YCxcbiAgICAgICAgICAgICAgICBhdHRyOiB7XCJzdHlsZVwiOiBgd2lkdGg6ICR7c2l6aW5nLnRvU3RyaW5nKCl9YH1cbiAgICAgICAgICAgIH0pKTtcblxuICAgICAgICAgICAgaWYoaSAhPT0gc2V0dGluZ3MubnVtYmVyT2ZDb2x1bW5zIC0gMSkge1xuICAgICAgICAgICAgICAgIG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgIGNsczogYG1jbS1jb2x1bW4tc3BhY2VyYCxcbiAgICAgICAgICAgICAgICAgICAgYXR0cjoge1wic3R5bGVcIjogY29sdW1uU3BhY2luZ1N0YXRlKDAsIHNldHRpbmdzKX1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCBjb2x1bW5Db250ZW50RGl2cy5sZW5ndGg7IGkrKykge1xuXG4gICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2c1tpXS5hZGRDbGFzcyhNdWx0aUNvbHVtbkxheW91dENTUy5Ob0ZsZXhTaHJpbmspO1xuICAgICAgICB9XG5cbiAgICAgICAgc2V0TWF4Q29sdW1uSGVpZ2h0KCk7XG5cbiAgICAgICAgcmV0dXJuIGNvbHVtbkNvbnRlbnREaXZzO1xuXG4gICAgICAgIGZ1bmN0aW9uIHNldE1heENvbHVtbkhlaWdodCgpIHtcbiAgICAgICAgICAgIGlmIChzZXR0aW5ncy5jb2x1bW5IZWlnaHQgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBtdWx0aUNvbHVtblBhcmVudC5yZW1vdmVDbGFzcyhNdWx0aUNvbHVtbkxheW91dENTUy5Db250ZW50T3ZlcmZsb3dIaWRkZW5fWSk7XG4gICAgICAgICAgICAgICAgbXVsdGlDb2x1bW5QYXJlbnQuYWRkQ2xhc3MoTXVsdGlDb2x1bW5MYXlvdXRDU1MuQ29udGVudE92ZXJmbG93QXV0b1Njcm9sbF9ZKTtcbiAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2cy5mb3JFYWNoKChjb2x1bW4pID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uLnN0eWxlLmhlaWdodCA9IHNldHRpbmdzLmNvbHVtbkhlaWdodC50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICBjb2x1bW4uc3R5bGUubWF4SGVpZ2h0ID0gc2V0dGluZ3MuY29sdW1uSGVpZ2h0LnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbi5zdHlsZS5taW5IZWlnaHQgPSBzZXR0aW5ncy5jb2x1bW5IZWlnaHQudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBhYnN0cmFjdCByZW5kZXJSZWdpb25FbGVtZW50c1RvU2NyZWVuKCk6IHZvaWQ7XG4gICAgcHVibGljIGFic3RyYWN0IGV4cG9ydFJlZ2lvbkVsZW1lbnRzVG9QREYocGRmUGFyZW50RWxlbWVudDogSFRNTEVsZW1lbnQpOiB2b2lkO1xuICAgIHB1YmxpYyBhYnN0cmFjdCByZW5kZXJSZWdpb25FbGVtZW50c1RvTGl2ZVByZXZpZXcocGFyZW50RWxlbWVudDogSFRNTEVsZW1lbnQpOiB2b2lkXG59XG5cbmZ1bmN0aW9uIGNyZWF0ZUVycm9yRWxlbWVudChlcnJvclRleHQ6IHN0cmluZywgYWx0OiBzdHJpbmcgPSBcIlwiLCBzcmM6IHN0cmluZyA9IFwiXCIpOiBIVE1MRGl2RWxlbWVudCB7XG4gICAgbGV0IGVycm9yRWwgPSBjcmVhdGVEaXYoe1xuICAgICAgICBjbHM6IFwiaW50ZXJuYWwtZW1iZWQgbWFya2Rvd24tZW1iZWQgaW5saW5lLWVtYmVkIGlzLWxvYWRlZFwiLFxuICAgICAgICBhdHRyOiB7XG4gICAgICAgICAgICBcInRhYmluZGV4XCI6IFwiLTFcIixcbiAgICAgICAgICAgIFwiY29udGVudGVkaXRhYmxlXCI6IFwiZmFsc2VcIlxuICAgICAgICB9XG4gICAgfSlcbiAgICBlcnJvckVsLnNldEF0dHIoXCJhbHRcIiwgYWx0KTtcbiAgICBlcnJvckVsLnNldEF0dHIoXCJzcmNcIiwgYGFwcDovL29ic2lkaWFuLm1kLyR7c3JjfWApXG4gICAgZXJyb3JFbC5hcHBlbmRDaGlsZChjcmVhdGVEaXYoXG4gICAgICAgIHtcbiAgICAgICAgICAgIFwiY2xzXCI6IFwiZW1iZWQtdGl0bGUgbWFya2Rvd24tZW1iZWQtdGl0bGVcIixcbiAgICAgICAgfVxuICAgICkpO1xuICAgIGxldCBjb250ZW50RWwgPSBlcnJvckVsLmNyZWF0ZURpdih7XG4gICAgICAgIFwiY2xzXCI6IGBtYXJrZG93bi1lbWJlZC1jb250ZW50YCxcbiAgICB9KTtcbiAgICBsZXQgcGFyYWdyYXBoID0gY29udGVudEVsLmNyZWF0ZUVsKFwicFwiLCB7XG4gICAgICAgIFwiY2xzXCI6IGAke011bHRpQ29sdW1uU3R5bGVDU1MuUmVnaW9uRXJyb3JNZXNzYWdlfSwgJHtNdWx0aUNvbHVtblN0eWxlQ1NTLlNtYWxsRm9udH1gXG4gICAgfSk7XG4gICAgcGFyYWdyYXBoLmlubmVyVGV4dCA9IGVycm9yVGV4dDtcblxuICAgIHJldHVybiBlcnJvckVsXG59XG5cbmZ1bmN0aW9uIHVwZGF0ZVBERkVtYmVkKGRvbUVsZW1lbnQ6IERPTU9iamVjdCkge1xuICAgIFxuICAgIC8vIGlmKGRvbUVsZW1lbnQuY2FudmFzUmVhZHlGb3JVcGRhdGUoKSA9PT0gZmFsc2UpIHtcbiAgICAvLyAgICAgcmV0dXJuXG4gICAgLy8gfVxuXG4gICAgbGV0IG9yaWdpbmFsRWxlbWVudCA9IGRvbUVsZW1lbnQub3JpZ2luYWxFbGVtZW50O1xuICAgIGxldCBjbG9uZWRFbGVtZW50ID0gZG9tRWxlbWVudC5jbG9uZWRFbGVtZW50O1xuICAgIGxldCBjb250YWluZXJFbGVtZW50OiBIVE1MRGl2RWxlbWVudCA9IGRvbUVsZW1lbnQuZWxlbWVudENvbnRhaW5lcjtcbiAgICBmb3IgKGxldCBpID0gY2xvbmVkRWxlbWVudC5jaGlsZHJlbi5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICBjbG9uZWRFbGVtZW50LmNoaWxkcmVuW2ldLmRldGFjaCgpO1xuICAgIH1cbiAgICBjbG9uZWRFbGVtZW50LmFwcGVuZENoaWxkKGNyZWF0ZUVycm9yRWxlbWVudChcIkR1ZSB0byBhbiB1cGRhdGUgdG8gT2JzaWRpYW4ncyBQREYgdmlld2VyLCBQREYgZW1iZWRzIGFyZSBjdXJyZW50bHkgbm90IHN1cHBvcnRlZC5cXG5Tb3JyeSBmb3IgdGhlIGluY29udmllbmVuY2UuXCIpKVxuICAgIHJldHVyblxufVxuXG5mdW5jdGlvbiByZVJlbmRlckRhdGF2aWV3SlMoZG9tRWxlbWVudDogRE9NT2JqZWN0KSB7XG4gICAgaWYoZG9tRWxlbWVudC5jYW52YXNSZWFkeUZvclVwZGF0ZSgpID09PSBmYWxzZSkge1xuICAgICAgICByZXR1cm5cbiAgICB9XG5cbiAgICBsZXQgb3JpZ2luYWxFbGVtZW50ID0gZG9tRWxlbWVudC5vcmlnaW5hbEVsZW1lbnQ7XG4gICAgbGV0IGNsb25lZEVsZW1lbnQgPSBkb21FbGVtZW50LmNsb25lZEVsZW1lbnQ7XG4gICAgbGV0IGNvbnRhaW5lckVsZW1lbnQ6IEhUTUxEaXZFbGVtZW50ID0gZG9tRWxlbWVudC5lbGVtZW50Q29udGFpbmVyO1xuXG4gICAgY29udGFpbmVyRWxlbWVudC5hcHBlbmRDaGlsZChvcmlnaW5hbEVsZW1lbnQpO1xuICAgIGlmKGNsb25lZEVsZW1lbnQgIT09IG51bGwgJiYgY2xvbmVkRWxlbWVudC5wYXJlbnRFbGVtZW50ID09PSBjb250YWluZXJFbGVtZW50KSB7XG4gICAgICAgIGNvbnRhaW5lckVsZW1lbnQucmVtb3ZlQ2hpbGQoY2xvbmVkRWxlbWVudCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY2xvbmVDYW52YXMob3JpZ2luYWxDYW52YXM6IEhUTUxDYW52YXNFbGVtZW50KTogSFRNTENhbnZhc0VsZW1lbnQge1xuXG4gICAgICAgIC8vY3JlYXRlIGEgbmV3IGNhbnZhc1xuICAgICAgICBsZXQgY2xvbmVkQ2FudmFzOiBIVE1MQ2FudmFzRWxlbWVudCA9IG9yaWdpbmFsQ2FudmFzLmNsb25lTm9kZSh0cnVlKSBhcyBIVE1MQ2FudmFzRWxlbWVudDtcbiAgICAgICAgbGV0IGNvbnRleHQ6IENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRCA9IGNsb25lZENhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuICAgIFxuICAgICAgICAvL3NldCBkaW1lbnNpb25zXG4gICAgICAgIGNsb25lZENhbnZhcy53aWR0aCA9IG9yaWdpbmFsQ2FudmFzLndpZHRoO1xuICAgICAgICBjbG9uZWRDYW52YXMuaGVpZ2h0ID0gb3JpZ2luYWxDYW52YXMuaGVpZ2h0O1xuXG4gICAgICAgIGlmKGNsb25lZENhbnZhcy53aWR0aCA9PT0gMCB8fCBjbG9uZWRDYW52YXMuaGVpZ2h0ID09PSAwKXtcbiAgICAgICAgICAgIC8vIERvbnQgd2FudCB0byByZW5kZXIgaWYgdGhlIHdpZHRoIGlzIDAgYXMgaXQgdGhyb3dzIGFuIGVycm9yXG4gICAgICAgICAgICAvLyB3b3VsZCBoYXBwZW4gaWYgdGhlIG9sZCBjYW52YXMgaGFzbnQgYmVlbiByZW5kZXJlZCB5ZXQuXG4gICAgICAgICAgICByZXR1cm4gY2xvbmVkQ2FudmFzO1xuICAgICAgICB9IFxuXG4gICAgICAgIC8vYXBwbHkgdGhlIG9sZCBjYW52YXMgdG8gdGhlIG5ldyBvbmVcbiAgICAgICAgY29udGV4dC5kcmF3SW1hZ2Uob3JpZ2luYWxDYW52YXMsIDAsIDApO1xuICAgIFxuICAgICAgICAvL3JldHVybiB0aGUgbmV3IGNhbnZhc1xuICAgICAgICByZXR1cm4gY2xvbmVkQ2FudmFzO1xuICAgIH1cblxuICAgIGxldCBjYW52YXMgPSBzZWFyY2hDaGlsZHJlbkZvck5vZGVUeXBlKG9yaWdpbmFsRWxlbWVudCwgXCJjYW52YXNcIik7XG4gICAgaWYoY2FudmFzICE9PSBudWxsKSB7XG4gICAgICAgIFxuICAgICAgICBkb21FbGVtZW50LnVwZGF0ZUNsb25lZEVsZW1lbnQob3JpZ2luYWxFbGVtZW50LmNsb25lTm9kZSh0cnVlKSBhcyBIVE1MRGl2RWxlbWVudCk7XG4gICAgICAgIGNsb25lZEVsZW1lbnQgPSBkb21FbGVtZW50LmNsb25lZEVsZW1lbnQ7XG4gICAgICAgIGNsb25lZEVsZW1lbnQuYWRkQ2xhc3MoTXVsdGlDb2x1bW5MYXlvdXRDU1MuQ2xvbmVkRWxlbWVudFR5cGUpO1xuICAgICAgICBjbG9uZWRFbGVtZW50LnJlbW92ZUNsYXNzZXMoW011bHRpQ29sdW1uU3R5bGVDU1MuUmVnaW9uQ29udGVudCwgTXVsdGlDb2x1bW5MYXlvdXRDU1MuT3JpZ2luYWxFbGVtZW50VHlwZV0pO1xuICAgICAgICBjb250YWluZXJFbGVtZW50LmFwcGVuZENoaWxkKGNsb25lZEVsZW1lbnQpO1xuXG4gICAgICAgIGZvciAobGV0IGkgPSBjbG9uZWRFbGVtZW50LmNoaWxkcmVuLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgICAgICBjbG9uZWRFbGVtZW50LmNoaWxkcmVuW2ldLmRldGFjaCgpO1xuICAgICAgICB9XG4gICAgICAgIGNsb25lZEVsZW1lbnQuYXBwZW5kQ2hpbGQoY2xvbmVDYW52YXMoY2FudmFzIGFzIEhUTUxDYW52YXNFbGVtZW50KSlcbiAgICB9XG5cbiAgICBjb250YWluZXJFbGVtZW50LnJlbW92ZUNoaWxkKG9yaWdpbmFsRWxlbWVudCk7XG4gICAgY29udGFpbmVyRWxlbWVudC5hcHBlbmRDaGlsZChjbG9uZWRFbGVtZW50KTtcbn1cblxuZnVuY3Rpb24gY2FsY0NvbHVtblNpemVzKHNldHRpbmdzOiBNdWx0aUNvbHVtblNldHRpbmdzLCBjb2x1bW5TaXplczogSFRNTFNpemluZ1tdKSB7XG4gICAgbGV0IGxheW91dCA9IHNldHRpbmdzLmNvbHVtblNpemUgYXMgQ29sdW1uTGF5b3V0O1xuXG4gICAgaWYoc2V0dGluZ3MubnVtYmVyT2ZDb2x1bW5zID09PSAyKSB7XG4gICAgICAgIHN3aXRjaChsYXlvdXQpIHtcbiAgICAgICAgICAgIGNhc2UoXCJzdGFuZGFyZFwiKTpcbiAgICAgICAgICAgIGNhc2UoXCJtaWRkbGVcIik6XG4gICAgICAgICAgICBjYXNlKFwiY2VudGVyXCIpOlxuICAgICAgICAgICAgY2FzZShcInRoaXJkXCIpOlxuICAgICAgICAgICAgICAgIGNvbHVtblNpemVzLnB1c2goSFRNTFNpemluZy5jcmVhdGUoKS5zZXRXaWR0aCg1MCkuc2V0VW5pdHMoXCIlXCIpKVxuICAgICAgICAgICAgICAgIGNvbHVtblNpemVzLnB1c2goSFRNTFNpemluZy5jcmVhdGUoKS5zZXRXaWR0aCg1MCkuc2V0VW5pdHMoXCIlXCIpKVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICBjYXNlKFwibGVmdFwiKTpcbiAgICAgICAgICAgIGNhc2UoXCJmaXJzdFwiKTpcbiAgICAgICAgICAgICAgICBjb2x1bW5TaXplcy5wdXNoKEhUTUxTaXppbmcuY3JlYXRlKCkuc2V0V2lkdGgoNzUpLnNldFVuaXRzKFwiJVwiKSlcbiAgICAgICAgICAgICAgICBjb2x1bW5TaXplcy5wdXNoKEhUTUxTaXppbmcuY3JlYXRlKCkuc2V0V2lkdGgoMjUpLnNldFVuaXRzKFwiJVwiKSlcbiAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgY2FzZShcInJpZ2h0XCIpOlxuICAgICAgICAgICAgY2FzZShcInNlY29uZFwiKTpcbiAgICAgICAgICAgIGNhc2UoXCJsYXN0XCIpOlxuICAgICAgICAgICAgICAgIGNvbHVtblNpemVzLnB1c2goSFRNTFNpemluZy5jcmVhdGUoKS5zZXRXaWR0aCgyNSkuc2V0VW5pdHMoXCIlXCIpKVxuICAgICAgICAgICAgICAgIGNvbHVtblNpemVzLnB1c2goSFRNTFNpemluZy5jcmVhdGUoKS5zZXRXaWR0aCg3NSkuc2V0VW5pdHMoXCIlXCIpKVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZihzZXR0aW5ncy5udW1iZXJPZkNvbHVtbnMgPT09IDMpIHtcbiAgICAgICAgc3dpdGNoKGxheW91dCkge1xuICAgICAgICAgICAgY2FzZShcInN0YW5kYXJkXCIpOlxuICAgICAgICAgICAgICAgIGNvbHVtblNpemVzLnB1c2goSFRNTFNpemluZy5jcmVhdGUoKS5zZXRXaWR0aCgzMykuc2V0VW5pdHMoXCIlXCIpKVxuICAgICAgICAgICAgICAgIGNvbHVtblNpemVzLnB1c2goSFRNTFNpemluZy5jcmVhdGUoKS5zZXRXaWR0aCgzMykuc2V0VW5pdHMoXCIlXCIpKVxuICAgICAgICAgICAgICAgIGNvbHVtblNpemVzLnB1c2goSFRNTFNpemluZy5jcmVhdGUoKS5zZXRXaWR0aCgzMykuc2V0VW5pdHMoXCIlXCIpKVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICBjYXNlKFwibGVmdFwiKTpcbiAgICAgICAgICAgIGNhc2UoXCJmaXJzdFwiKTpcbiAgICAgICAgICAgICAgICBjb2x1bW5TaXplcy5wdXNoKEhUTUxTaXppbmcuY3JlYXRlKCkuc2V0V2lkdGgoNTApLnNldFVuaXRzKFwiJVwiKSlcbiAgICAgICAgICAgICAgICBjb2x1bW5TaXplcy5wdXNoKEhUTUxTaXppbmcuY3JlYXRlKCkuc2V0V2lkdGgoMjUpLnNldFVuaXRzKFwiJVwiKSlcbiAgICAgICAgICAgICAgICBjb2x1bW5TaXplcy5wdXNoKEhUTUxTaXppbmcuY3JlYXRlKCkuc2V0V2lkdGgoMjUpLnNldFVuaXRzKFwiJVwiKSlcbiAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgY2FzZShcIm1pZGRsZVwiKTpcbiAgICAgICAgICAgIGNhc2UoXCJjZW50ZXJcIik6XG4gICAgICAgICAgICBjYXNlKFwic2Vjb25kXCIpOlxuICAgICAgICAgICAgICAgIGNvbHVtblNpemVzLnB1c2goSFRNTFNpemluZy5jcmVhdGUoKS5zZXRXaWR0aCgyNSkuc2V0VW5pdHMoXCIlXCIpKVxuICAgICAgICAgICAgICAgIGNvbHVtblNpemVzLnB1c2goSFRNTFNpemluZy5jcmVhdGUoKS5zZXRXaWR0aCg1MCkuc2V0VW5pdHMoXCIlXCIpKVxuICAgICAgICAgICAgICAgIGNvbHVtblNpemVzLnB1c2goSFRNTFNpemluZy5jcmVhdGUoKS5zZXRXaWR0aCgyNSkuc2V0VW5pdHMoXCIlXCIpKVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICBjYXNlKFwicmlnaHRcIik6XG4gICAgICAgICAgICBjYXNlKFwidGhpcmRcIik6XG4gICAgICAgICAgICBjYXNlKFwibGFzdFwiKTpcbiAgICAgICAgICAgICAgICBjb2x1bW5TaXplcy5wdXNoKEhUTUxTaXppbmcuY3JlYXRlKCkuc2V0V2lkdGgoMjUpLnNldFVuaXRzKFwiJVwiKSlcbiAgICAgICAgICAgICAgICBjb2x1bW5TaXplcy5wdXNoKEhUTUxTaXppbmcuY3JlYXRlKCkuc2V0V2lkdGgoMjUpLnNldFVuaXRzKFwiJVwiKSlcbiAgICAgICAgICAgICAgICBjb2x1bW5TaXplcy5wdXNoKEhUTUxTaXppbmcuY3JlYXRlKCkuc2V0V2lkdGgoNTApLnNldFVuaXRzKFwiJVwiKSlcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cbn1cblxuZnVuY3Rpb24gZ2V0RWxlbWVudENsaWVudEhlaWdodChlbGVtZW50OiBIVE1MRWxlbWVudCwgcGFyZW50UmVuZGVyRWxlbWVudDogSFRNTERpdkVsZW1lbnQpOiBudW1iZXIge1xuXG4gICAgbGV0IGhlaWdodCA9IGVsZW1lbnQuY2xpZW50SGVpZ2h0O1xuICAgIGlmKGhlaWdodCA9PT0gMCkge1xuICAgICAgICBwYXJlbnRSZW5kZXJFbGVtZW50LmFwcGVuZENoaWxkKGVsZW1lbnQpO1xuICAgICAgICBoZWlnaHQgPSBlbGVtZW50LmNsaWVudEhlaWdodFxuICAgICAgICBwYXJlbnRSZW5kZXJFbGVtZW50LnJlbW92ZUNoaWxkKGVsZW1lbnQpO1xuICAgIH1cbiAgICByZXR1cm4gaGVpZ2h0XG59XG5cbmZ1bmN0aW9uIGJ1aWxkRXF1YWxMYXlvdXQoc2V0dGluZ3M6IE11bHRpQ29sdW1uU2V0dGluZ3MsIG11bHRpQ29sdW1uUGFyZW50OiBIVE1MRGl2RWxlbWVudCwgY29sdW1uQ29udGVudERpdnM6IEhUTUxEaXZFbGVtZW50W10pIHtcblxuICAgIGxldCBwZXJjZW50ID0gTWF0aC5jZWlsKDEwMCAvIHNldHRpbmdzLm51bWJlck9mQ29sdW1ucyk7XG5cbiAgICBmb3IobGV0IGkgPSAwOyBpIDwgc2V0dGluZ3MubnVtYmVyT2ZDb2x1bW5zOyBpKyspIHtcbiAgICAgICAgXG4gICAgICAgIGNvbHVtbkNvbnRlbnREaXZzLnB1c2gobXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgIGNsczogYCR7TXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5Db250ZW50fWAsXG4gICAgICAgICAgICBhdHRyOiB7XCJzdHlsZVwiOiBgd2lkdGg6ICR7cGVyY2VudH0lYH1cbiAgICAgICAgfSkpO1xuXG4gICAgICAgIGlmKGkgIT09IHNldHRpbmdzLm51bWJlck9mQ29sdW1ucyAtIDEpIHtcbiAgICAgICAgICAgIG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgY2xzOiBgbWNtLWNvbHVtbi1zcGFjZXJgLFxuICAgICAgICAgICAgICAgIGF0dHI6IHtcInN0eWxlXCI6IGNvbHVtblNwYWNpbmdTdGF0ZSgwLCBzZXR0aW5ncyl9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuZnVuY3Rpb24gYnVpbGRTdGFuZGFyZExheW91dHMoc2V0dGluZ3M6IE11bHRpQ29sdW1uU2V0dGluZ3MsIG11bHRpQ29sdW1uUGFyZW50OiBIVE1MRGl2RWxlbWVudCwgY29sdW1uQ29udGVudERpdnM6IEhUTUxEaXZFbGVtZW50W10pIHtcblxuICAgIGxldCBsYXlvdXQgPSBzZXR0aW5ncy5jb2x1bW5TaXplIGFzIENvbHVtbkxheW91dDtcblxuICAgIGlmKHNldHRpbmdzLm51bWJlck9mQ29sdW1ucyA9PT0gMikge1xuICAgICAgICBzd2l0Y2gobGF5b3V0KSB7XG4gICAgICAgICAgICBjYXNlKFwic3RhbmRhcmRcIik6XG4gICAgICAgICAgICBjYXNlKFwibWlkZGxlXCIpOlxuICAgICAgICAgICAgY2FzZShcImNlbnRlclwiKTpcbiAgICAgICAgICAgIGNhc2UoXCJ0aGlyZFwiKTpcbiAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2cy5wdXNoKG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgIGNsczogYCR7TXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5Db250ZW50fSAke011bHRpQ29sdW1uTGF5b3V0Q1NTLlR3b0VxdWFsQ29sdW1uc31gXG4gICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgICAgIG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgIGNsczogYG1jbS1jb2x1bW4tc3BhY2VyYCxcbiAgICAgICAgICAgICAgICAgICAgYXR0cjoge1wic3R5bGVcIjogY29sdW1uU3BhY2luZ1N0YXRlKDAsIHNldHRpbmdzKX1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2cy5wdXNoKG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgIGNsczogYCR7TXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5Db250ZW50fSAke011bHRpQ29sdW1uTGF5b3V0Q1NTLlR3b0VxdWFsQ29sdW1uc31gXG4gICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICBjYXNlKFwibGVmdFwiKTpcbiAgICAgICAgICAgIGNhc2UoXCJmaXJzdFwiKTpcbiAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2cy5wdXNoKG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgIGNsczogYCR7TXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5Db250ZW50fSAke011bHRpQ29sdW1uTGF5b3V0Q1NTLlR3b0NvbHVtbkxhcmdlfWBcbiAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgICAgbXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgY2xzOiBgbWNtLWNvbHVtbi1zcGFjZXJgLFxuICAgICAgICAgICAgICAgICAgICBhdHRyOiB7XCJzdHlsZVwiOiBjb2x1bW5TcGFjaW5nU3RhdGUoMCwgc2V0dGluZ3MpfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzLnB1c2gobXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgY2xzOiBgJHtNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtbkNvbnRlbnR9ICR7TXVsdGlDb2x1bW5MYXlvdXRDU1MuVHdvQ29sdW1uU21hbGx9YFxuICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgY2FzZShcInJpZ2h0XCIpOlxuICAgICAgICAgICAgY2FzZShcInNlY29uZFwiKTpcbiAgICAgICAgICAgIGNhc2UoXCJsYXN0XCIpOlxuICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzLnB1c2gobXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgY2xzOiBgJHtNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtbkNvbnRlbnR9ICR7TXVsdGlDb2x1bW5MYXlvdXRDU1MuVHdvQ29sdW1uU21hbGx9YFxuICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgICBtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xuICAgICAgICAgICAgICAgICAgICBjbHM6IGBtY20tY29sdW1uLXNwYWNlcmAsXG4gICAgICAgICAgICAgICAgICAgIGF0dHI6IHtcInN0eWxlXCI6IGNvbHVtblNwYWNpbmdTdGF0ZSgwLCBzZXR0aW5ncyl9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnMucHVzaChtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xuICAgICAgICAgICAgICAgICAgICBjbHM6IGAke011bHRpQ29sdW1uU3R5bGVDU1MuQ29sdW1uQ29udGVudH0gJHtNdWx0aUNvbHVtbkxheW91dENTUy5Ud29Db2x1bW5MYXJnZX1gXG4gICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZihzZXR0aW5ncy5udW1iZXJPZkNvbHVtbnMgPT09IDMpIHtcbiAgICAgICAgc3dpdGNoKGxheW91dCkge1xuICAgICAgICAgICAgY2FzZShcInN0YW5kYXJkXCIpOlxuICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzLnB1c2gobXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgY2xzOiBgJHtNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtbkNvbnRlbnR9ICR7TXVsdGlDb2x1bW5MYXlvdXRDU1MuVGhyZWVFcXVhbENvbHVtbnN9YFxuICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgICBtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xuICAgICAgICAgICAgICAgICAgICBjbHM6IGBtY20tY29sdW1uLXNwYWNlcmAsXG4gICAgICAgICAgICAgICAgICAgIGF0dHI6IHtcInN0eWxlXCI6IGNvbHVtblNwYWNpbmdTdGF0ZSgwLCBzZXR0aW5ncyl9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnMucHVzaChtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xuICAgICAgICAgICAgICAgICAgICBjbHM6IGAke011bHRpQ29sdW1uU3R5bGVDU1MuQ29sdW1uQ29udGVudH0gJHtNdWx0aUNvbHVtbkxheW91dENTUy5UaHJlZUVxdWFsQ29sdW1uc31gXG4gICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgICAgIG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgIGNsczogYG1jbS1jb2x1bW4tc3BhY2VyYCxcbiAgICAgICAgICAgICAgICAgICAgYXR0cjoge1wic3R5bGVcIjogY29sdW1uU3BhY2luZ1N0YXRlKDEsIHNldHRpbmdzKX1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2cy5wdXNoKG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgIGNsczogYCR7TXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5Db250ZW50fSAke011bHRpQ29sdW1uTGF5b3V0Q1NTLlRocmVlRXF1YWxDb2x1bW5zfWBcbiAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgIGNhc2UoXCJsZWZ0XCIpOlxuICAgICAgICAgICAgY2FzZShcImZpcnN0XCIpOlxuICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzLnB1c2gobXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgY2xzOiBgJHtNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtbkNvbnRlbnR9ICR7TXVsdGlDb2x1bW5MYXlvdXRDU1MuVGhyZWVDb2x1bW5fTGFyZ2V9YFxuICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgICBtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xuICAgICAgICAgICAgICAgICAgICBjbHM6IGBtY20tY29sdW1uLXNwYWNlcmAsXG4gICAgICAgICAgICAgICAgICAgIGF0dHI6IHtcInN0eWxlXCI6IGNvbHVtblNwYWNpbmdTdGF0ZSgwLCBzZXR0aW5ncyl9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnMucHVzaChtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xuICAgICAgICAgICAgICAgICAgICBjbHM6IGAke011bHRpQ29sdW1uU3R5bGVDU1MuQ29sdW1uQ29udGVudH0gJHtNdWx0aUNvbHVtbkxheW91dENTUy5UaHJlZUNvbHVtbl9TbWFsbH1gXG4gICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgICAgIG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgIGNsczogYG1jbS1jb2x1bW4tc3BhY2VyYCxcbiAgICAgICAgICAgICAgICAgICAgYXR0cjoge1wic3R5bGVcIjogY29sdW1uU3BhY2luZ1N0YXRlKDEsIHNldHRpbmdzKX1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2cy5wdXNoKG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgIGNsczogYCR7TXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5Db250ZW50fSAke011bHRpQ29sdW1uTGF5b3V0Q1NTLlRocmVlQ29sdW1uX1NtYWxsfWBcbiAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgIGNhc2UoXCJtaWRkbGVcIik6XG4gICAgICAgICAgICBjYXNlKFwiY2VudGVyXCIpOlxuICAgICAgICAgICAgY2FzZShcInNlY29uZFwiKTpcbiAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2cy5wdXNoKG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgIGNsczogYCR7TXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5Db250ZW50fSAke011bHRpQ29sdW1uTGF5b3V0Q1NTLlRocmVlQ29sdW1uX1NtYWxsfWBcbiAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgICAgbXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgY2xzOiBgbWNtLWNvbHVtbi1zcGFjZXJgLFxuICAgICAgICAgICAgICAgICAgICBhdHRyOiB7XCJzdHlsZVwiOiBjb2x1bW5TcGFjaW5nU3RhdGUoMCwgc2V0dGluZ3MpfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzLnB1c2gobXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgY2xzOiBgJHtNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtbkNvbnRlbnR9ICR7TXVsdGlDb2x1bW5MYXlvdXRDU1MuVGhyZWVDb2x1bW5fTGFyZ2V9YFxuICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgICBtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xuICAgICAgICAgICAgICAgICAgICBjbHM6IGBtY20tY29sdW1uLXNwYWNlcmAsXG4gICAgICAgICAgICAgICAgICAgIGF0dHI6IHtcInN0eWxlXCI6IGNvbHVtblNwYWNpbmdTdGF0ZSgxLCBzZXR0aW5ncyl9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnMucHVzaChtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xuICAgICAgICAgICAgICAgICAgICBjbHM6IGAke011bHRpQ29sdW1uU3R5bGVDU1MuQ29sdW1uQ29udGVudH0gJHtNdWx0aUNvbHVtbkxheW91dENTUy5UaHJlZUNvbHVtbl9TbWFsbH1gXG4gICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICBjYXNlKFwicmlnaHRcIik6XG4gICAgICAgICAgICBjYXNlKFwidGhpcmRcIik6XG4gICAgICAgICAgICBjYXNlKFwibGFzdFwiKTpcbiAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2cy5wdXNoKG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgIGNsczogYCR7TXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5Db250ZW50fSAke011bHRpQ29sdW1uTGF5b3V0Q1NTLlRocmVlQ29sdW1uX1NtYWxsfWBcbiAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgICAgbXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgY2xzOiBgbWNtLWNvbHVtbi1zcGFjZXJgLFxuICAgICAgICAgICAgICAgICAgICBhdHRyOiB7XCJzdHlsZVwiOiBjb2x1bW5TcGFjaW5nU3RhdGUoMCwgc2V0dGluZ3MpfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzLnB1c2gobXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgY2xzOiBgJHtNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtbkNvbnRlbnR9ICR7TXVsdGlDb2x1bW5MYXlvdXRDU1MuVGhyZWVDb2x1bW5fU21hbGx9YFxuICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgICBtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xuICAgICAgICAgICAgICAgICAgICBjbHM6IGBtY20tY29sdW1uLXNwYWNlcmAsXG4gICAgICAgICAgICAgICAgICAgIGF0dHI6IHtcInN0eWxlXCI6IGNvbHVtblNwYWNpbmdTdGF0ZSgxLCBzZXR0aW5ncyl9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnMucHVzaChtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xuICAgICAgICAgICAgICAgICAgICBjbHM6IGAke011bHRpQ29sdW1uU3R5bGVDU1MuQ29sdW1uQ29udGVudH0gJHtNdWx0aUNvbHVtbkxheW91dENTUy5UaHJlZUNvbHVtbl9MYXJnZX1gXG4gICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxufVxuXG5mdW5jdGlvbiBmaXhPbkNsaWNrKGRvbUVsZW1lbnQ6IERPTU9iamVjdCkge1xuXG4gICAgbGV0IG9yaWdpbmFsRWxlbWVudCA9IGRvbUVsZW1lbnQub3JpZ2luYWxFbGVtZW50O1xuICAgIGxldCBjbG9uZWRFbGVtZW50ID0gZG9tRWxlbWVudC5jbG9uZWRFbGVtZW50O1xuXG4gICAgbGV0IG9yaWdpbmFsQnV0dG9uID0gb3JpZ2luYWxFbGVtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKFwiYnV0dG9uXCIpWzBdO1xuICAgIGxldCBjbG9uZWRCdXR0b24gPSBjbG9uZWRFbGVtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKFwiYnV0dG9uXCIpWzBdO1xuXG4gICAgaWYob3JpZ2luYWxCdXR0b24gPT09IHVuZGVmaW5lZCB8fCBjbG9uZWRCdXR0b24gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY2xvbmVkQnV0dG9uLm9uQ2xpY2tFdmVudCgoZXYpID0+IHtcblxuICAgICAgICBvcmlnaW5hbEJ1dHRvbi5jbGljaygpO1xuICAgIH0pXG59XG5cbmZ1bmN0aW9uIGNsb25lRWxlbWVudChkb21FbGVtZW50OiBET01PYmplY3QpIHtcblxuICAgIGxldCBvcmlnaW5hbEVsZW1lbnQgPSBkb21FbGVtZW50Lm9yaWdpbmFsRWxlbWVudDtcbiAgICBsZXQgY2xvbmVkRWxlbWVudCA9IGRvbUVsZW1lbnQuY2xvbmVkRWxlbWVudDtcbiAgICBsZXQgY29udGFpbmVyRWxlbWVudDogSFRNTERpdkVsZW1lbnQgPSBkb21FbGVtZW50LmVsZW1lbnRDb250YWluZXI7XG5cbiAgICBkb21FbGVtZW50LnVwZGF0ZUNsb25lZEVsZW1lbnQob3JpZ2luYWxFbGVtZW50LmNsb25lTm9kZSh0cnVlKSBhcyBIVE1MRGl2RWxlbWVudCk7XG4gICAgY2xvbmVkRWxlbWVudCA9IGRvbUVsZW1lbnQuY2xvbmVkRWxlbWVudDtcblxuICAgIC8qKlxuICAgICAqIElmIHdlIHVwZGF0ZWQgdGhlIGNsb25lZCBlbGVtZW50LCB3ZSB3YW50IHRvIGFsc28gdXBkYXRlIHRoZVxuICAgICAqIGVsZW1lbnQgcmVuZGVyZWQgaW4gdGhlIHBhcmVudCBjb250YWluZXIuXG4gICAgICovXG4gICAgZm9yIChsZXQgaSA9IGNvbnRhaW5lckVsZW1lbnQuY2hpbGRyZW4ubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgY29udGFpbmVyRWxlbWVudC5jaGlsZHJlbltpXS5kZXRhY2goKTtcbiAgICB9XG5cbiAgICAvLyBVcGRhdGUgQ1NTLCB3ZSBhZGQgY2xvbmVkIGNsYXNzIGFuZCByZW1vdmUgY2xhc3NlcyBmcm9tIG9yaWdpbmFsRWxlbWVudCB0aGF0IGRvIG5vdCBhcHBseS5cbiAgICBjbG9uZWRFbGVtZW50LmFkZENsYXNzKE11bHRpQ29sdW1uTGF5b3V0Q1NTLkNsb25lZEVsZW1lbnRUeXBlKTtcbiAgICBjbG9uZWRFbGVtZW50LnJlbW92ZUNsYXNzZXMoW011bHRpQ29sdW1uU3R5bGVDU1MuUmVnaW9uQ29udGVudCwgTXVsdGlDb2x1bW5MYXlvdXRDU1MuT3JpZ2luYWxFbGVtZW50VHlwZV0pO1xuICAgIGNvbnRhaW5lckVsZW1lbnQuYXBwZW5kQ2hpbGQoY2xvbmVkRWxlbWVudCk7XG59XG5cbmZ1bmN0aW9uIHByb2Nlc3NCdXR0b25QbHVnaW5VcGRhdGUoZG9tT2JqZWN0OiBET01PYmplY3QpIHtcblxuICAgIGRvbU9iamVjdC5lbGVtZW50VHlwZSA9IFwiYnV0dG9uUGx1Z2luXCJcbiAgICBpZihkb21PYmplY3QuY2xvbmVkRWxlbWVudFJlYWR5Rm9yVXBkYXRlKCkgPT09IHRydWUpIHtcbiAgICAgICAgY2xvbmVFbGVtZW50KGRvbU9iamVjdCk7XG4gICAgICAgIGZpeE9uQ2xpY2soZG9tT2JqZWN0KTtcbiAgICB9XG59IiwiZXhwb3J0IGludGVyZmFjZSBNQ01fU2V0dGluZ3Mge1xuICAgIHJlbmRlck9uTW9iaWxlOiBib29sZWFuO1xuICAgIGF1dG9MYXlvdXRCYWxhbmNlSXRlcmF0aW9uczogbnVtYmVyO1xuICAgIHVzZUxpdmVQcmV2aWV3Q2FjaGU6IGJvb2xlYW47XG4gICAgYWxpZ25UYWJsZXNUb0NvbnRlbnRBbGlnbm1lbnQ6IGJvb2xlYW47XG4gICAgcmVuZGVySW5saW5lRWxFcnJvcnM6IGJvb2xlYW47XG59XG5leHBvcnQgY29uc3QgREVGQVVMVF9TRVRUSU5HUzogTUNNX1NldHRpbmdzID0ge1xuICAgIHJlbmRlck9uTW9iaWxlOiB0cnVlLFxuICAgIGF1dG9MYXlvdXRCYWxhbmNlSXRlcmF0aW9uczogNSxcbiAgICB1c2VMaXZlUHJldmlld0NhY2hlOiBmYWxzZSxcbiAgICBhbGlnblRhYmxlc1RvQ29udGVudEFsaWdubWVudDogdHJ1ZSxcbiAgICByZW5kZXJJbmxpbmVFbEVycm9yczogdHJ1ZVxufTtcblxuZXhwb3J0IGNsYXNzIE1DTV9TZXR0aW5nc01hbmFnZXIge1xuXG4gICAgcHJpdmF0ZSBzdGF0aWMgbG9jYWw6IE1DTV9TZXR0aW5nc01hbmFnZXIgfCBudWxsID0gbnVsbDtcbiAgICBwdWJsaWMgc3RhdGljIGdldCBzaGFyZWQoKTogTUNNX1NldHRpbmdzTWFuYWdlciB7XG4gICAgICAgIGlmKE1DTV9TZXR0aW5nc01hbmFnZXIubG9jYWwgPT09IG51bGwpIHtcbiAgICAgICAgICAgIE1DTV9TZXR0aW5nc01hbmFnZXIubG9jYWwgPSBuZXcgTUNNX1NldHRpbmdzTWFuYWdlcigpXG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIE1DTV9TZXR0aW5nc01hbmFnZXIubG9jYWw7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfc2V0dGluZ3M6IE1DTV9TZXR0aW5ncyA9IERFRkFVTFRfU0VUVElOR1M7XG4gICAgcHVibGljIGdldCBzZXR0aW5ncygpOiBNQ01fU2V0dGluZ3MgeyByZXR1cm4gdGhpcy5fc2V0dGluZ3MgfVxuICAgIHB1YmxpYyBzZXQgc2V0dGluZ3MobmV3VmFsOiBNQ01fU2V0dGluZ3MpIHtcbiAgICAgICAgdGhpcy51cGRhdGVUaW1lc3RhbXAoKVxuICAgICAgICB0aGlzLl9zZXR0aW5ncyA9IG5ld1ZhbFxuICAgIH1cblxuICAgIHByaXZhdGUgX2xhc3RVcGRhdGVUaW1lc3RhbXA6IG51bWJlclxuICAgIHB1YmxpYyBnZXQgbGFzdFVwZGF0ZVRpbWVzdGFtcCgpOiBudW1iZXIgeyByZXR1cm4gdGhpcy5fbGFzdFVwZGF0ZVRpbWVzdGFtcCB9XG4gICAgcHJpdmF0ZSB1cGRhdGVUaW1lc3RhbXAoKSB7XG4gICAgICAgIHRoaXMuX2xhc3RVcGRhdGVUaW1lc3RhbXAgPSBEYXRlLm5vdygpXG4gICAgfVxuXG4gICAgcHVibGljIGdldCByZW5kZXJPbk1vYmlsZSgpOiBib29sZWFuIHsgcmV0dXJuIHRoaXMuX3NldHRpbmdzLnJlbmRlck9uTW9iaWxlIH1cbiAgICBwdWJsaWMgZ2V0IGF1dG9MYXlvdXRCYWxhbmNlSXRlcmF0aW9ucygpOiBudW1iZXIgeyByZXR1cm4gdGhpcy5fc2V0dGluZ3MuYXV0b0xheW91dEJhbGFuY2VJdGVyYXRpb25zIH1cbiAgICBwdWJsaWMgZ2V0IHVzZUxpdmVQcmV2aWV3Q2FjaGUoKTogYm9vbGVhbiB7IHJldHVybiB0aGlzLl9zZXR0aW5ncy51c2VMaXZlUHJldmlld0NhY2hlIH1cbiAgICBwdWJsaWMgZ2V0IGFsaWduVGFibGVzVG9Db250ZW50QWxpZ25tZW50KCk6IGJvb2xlYW4geyByZXR1cm4gdGhpcy5fc2V0dGluZ3MuYWxpZ25UYWJsZXNUb0NvbnRlbnRBbGlnbm1lbnQgfVxuICAgIHB1YmxpYyBnZXQgcmVuZGVySW5saW5lRWxFcnJvcnMoKTogYm9vbGVhbiB7IHJldHVybiB0aGlzLl9zZXR0aW5ncy5yZW5kZXJJbmxpbmVFbEVycm9ycyB9XG5cbiAgICBwdWJsaWMgc2V0IHJlbmRlck9uTW9iaWxlKG5ld1ZhbDogYm9vbGVhbikge1xuICAgICAgICB0aGlzLnVwZGF0ZVRpbWVzdGFtcCgpXG4gICAgICAgIHRoaXMuX3NldHRpbmdzLnJlbmRlck9uTW9iaWxlID0gbmV3VmFsXG4gICAgfVxuICAgIHB1YmxpYyBzZXQgYXV0b0xheW91dEJhbGFuY2VJdGVyYXRpb25zKG5ld1ZhbDogbnVtYmVyKSB7XG4gICAgICAgIHRoaXMudXBkYXRlVGltZXN0YW1wKClcbiAgICAgICAgdGhpcy5fc2V0dGluZ3MuYXV0b0xheW91dEJhbGFuY2VJdGVyYXRpb25zID0gbmV3VmFsXG4gICAgfVxuICAgIHB1YmxpYyBzZXQgdXNlTGl2ZVByZXZpZXdDYWNoZShuZXdWYWw6IGJvb2xlYW4pIHtcbiAgICAgICAgdGhpcy51cGRhdGVUaW1lc3RhbXAoKVxuICAgICAgICB0aGlzLl9zZXR0aW5ncy51c2VMaXZlUHJldmlld0NhY2hlID0gbmV3VmFsXG4gICAgfVxuICAgIHB1YmxpYyBzZXQgYWxpZ25UYWJsZXNUb0NvbnRlbnRBbGlnbm1lbnQobmV3VmFsOiBib29sZWFuKSB7XG4gICAgICAgIHRoaXMudXBkYXRlVGltZXN0YW1wKClcbiAgICAgICAgdGhpcy5fc2V0dGluZ3MuYWxpZ25UYWJsZXNUb0NvbnRlbnRBbGlnbm1lbnQgPSBuZXdWYWxcbiAgICB9XG4gICAgcHVibGljIHNldCByZW5kZXJJbmxpbmVFbEVycm9ycyhuZXdWYWw6IGJvb2xlYW4pIHtcbiAgICAgICAgdGhpcy51cGRhdGVUaW1lc3RhbXAoKVxuICAgICAgICB0aGlzLl9zZXR0aW5ncy5yZW5kZXJJbmxpbmVFbEVycm9ycyA9IG5ld1ZhbFxuICAgIH1cbn0iLCIvKipcbiAqIEZpbGU6IC9zcmMvZG9tX21hbmFnZXIvcmVnaW9uYWxfbWFuYWdlcnMvcmVnaW9uRE9NTWFuYWdlci50cyAgICAgICAgICAgICAgICAqXG4gKiBDcmVhdGVkIERhdGU6IFN1bmRheSwgTWF5IDIybmQgMjAyMiwgNzo0NiBwbSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICogQXV0aG9yOiBDYW1lcm9uIFJvYmluc29uICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjIgQ2FtZXJvbiBSb2JpbnNvbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICovXG5cbmltcG9ydCB7IERPTU9iamVjdCwgRE9NT2JqZWN0VGFnLCBFbGVtZW50Q29sdW1uQnJlYWtUeXBlLCBUYXNrTGlzdERPTU9iamVjdCB9IGZyb20gJy4uL2RvbU9iamVjdCc7XG5pbXBvcnQgeyBNdWx0aUNvbHVtblNldHRpbmdzLCBDb250ZW50T3ZlcmZsb3dUeXBlLCBBbGlnbm1lbnRUeXBlLCBzaG91bGREcmF3Q29sdW1uQm9yZGVyLCBjb2x1bW5PdmVyZmxvd1N0YXRlLCBjb2x1bW5BbGlnbm1lbnRTdGF0ZSwgVGFibGVBbGlnbm1lbnQgfSBmcm9tIFwiLi4vLi4vcmVnaW9uU2V0dGluZ3NcIjtcbmltcG9ydCB7IE11bHRpQ29sdW1uTGF5b3V0Q1NTLCBNdWx0aUNvbHVtblN0eWxlQ1NTIH0gZnJvbSAnLi4vLi4vdXRpbGl0aWVzL2Nzc0RlZmluaXRpb25zJztcbmltcG9ydCB7IE1hcmtkb3duUmVuZGVyQ2hpbGQgfSBmcm9tICdvYnNpZGlhbic7XG5pbXBvcnQgeyBSZWdpb25NYW5hZ2VyIH0gZnJvbSAnLi9yZWdpb25NYW5hZ2VyJztcbmltcG9ydCB7IGdldEhlYWRpbmdDb2xsYXBzZUVsZW1lbnQgfSBmcm9tICdzcmMvdXRpbGl0aWVzL2VsZW1lbnRSZW5kZXJUeXBlUGFyc2VyJztcbmltcG9ydCB7IE1DTV9TZXR0aW5nc01hbmFnZXIgfSBmcm9tICdzcmMvcGx1Z2luU2V0dGluZ3MnO1xuXG5leHBvcnQgY2xhc3MgU3RhbmRhcmRNdWx0aUNvbHVtblJlZ2lvbk1hbmFnZXIgZXh0ZW5kcyBSZWdpb25NYW5hZ2VyIHtcblxuXG4gICAgcHVibGljIHJlbmRlclJlZ2lvbkVsZW1lbnRzVG9TY3JlZW4oKTogdm9pZCB7XG5cbiAgICAgICAgdGhpcy5yZW5kZXJDb2x1bW5NYXJrZG93bih0aGlzLnJlZ2lvblBhcmVudCwgdGhpcy5kb21MaXN0LCB0aGlzLnJlZ2lvbmFsU2V0dGluZ3MpO1xuICAgIH1cbiAgICBwdWJsaWMgZXhwb3J0UmVnaW9uRWxlbWVudHNUb1BERihwZGZQYXJlbnRFbGVtZW50OiBIVE1MRWxlbWVudCk6IHZvaWQge1xuXG4gICAgICAgIC8vIERlZmF1bHQgc2V0IHNoYWRvdyB0byBvZmYgZm9yIGV4cG9ydGluZyBQREZzXG4gICAgICAgIGxldCByZW5kZXJTZXR0aW5ncyA9IHRoaXMucmVnaW9uYWxTZXR0aW5ncztcbiAgICAgICAgcmVuZGVyU2V0dGluZ3MuZHJhd1NoYWRvdyA9IGZhbHNlO1xuICAgICAgICB0aGlzLnJlbmRlckNvbHVtbk1hcmtkb3duKHBkZlBhcmVudEVsZW1lbnQsIHRoaXMuZG9tTGlzdC5zbGljZSgpLCByZW5kZXJTZXR0aW5ncyk7XG4gICAgfVxuICAgIHB1YmxpYyByZW5kZXJSZWdpb25FbGVtZW50c1RvTGl2ZVByZXZpZXcocGFyZW50RWxlbWVudDogSFRNTEVsZW1lbnQpOiB2b2lkIHtcblxuICAgICAgICB0aGlzLnJlbmRlckNvbHVtbk1hcmtkb3duKHBhcmVudEVsZW1lbnQsIHRoaXMuZG9tTGlzdCwgdGhpcy5yZWdpb25hbFNldHRpbmdzLCB0cnVlKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogVGhpcyBmdW5jdGlvbiB0YWtlcyBpbiB0aGUgZGF0YSBmb3IgdGhlIG11bHRpLWNvbHVtbiByZWdpb24gYW5kIHNldHMgdXAgdGhlIFxuICAgICAqIHVzZXIgZGVmaW5lZCBudW1iZXIgb2YgY2hpbGRyZW4gd2l0aCB0aGUgcHJvcGVyIGNzcyBjbGFzc2VzIHRvIGJlIHJlbmRlcmVkIHByb3Blcmx5LlxuICAgICAqIFxuICAgICAqIEBwYXJhbSBwYXJlbnRFbGVtZW50IFRoZSBlbGVtZW50IHRoYXQgdGhlIG11bHRpLWNvbHVtbiByZWdpb24gd2lsbCBiZSByZW5kZXJlZCB1bmRlci5cbiAgICAgKiBAcGFyYW0gcmVnaW9uRWxlbWVudHMgVGhlIGxpc3Qgb2YgRE9NIG9iamVjdHMgdGhhdCB3aWxsIGJlIGNvcHBpZWQgdW5kZXIgdGhlIHBhcmVudCBvYmplY3RcbiAgICAgKiBAcGFyYW0gc2V0dGluZ3MgVGhlIHNldHRpbmdzIHRoZSB1c2VyIGhhcyBkZWZpbmVkIGZvciB0aGUgcmVnaW9uLlxuICAgICAqL1xuICAgIHByaXZhdGUgcmVuZGVyQ29sdW1uTWFya2Rvd24ocGFyZW50RWxlbWVudDogSFRNTEVsZW1lbnQsIHJlZ2lvbkVsZW1lbnRzOiBET01PYmplY3RbXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNldHRpbmdzOiBNdWx0aUNvbHVtblNldHRpbmdzLCBpc0xpdmVQcmV2aWV3OiBib29sZWFuID0gZmFsc2UpIHtcblxuICAgICAgICBsZXQgbXVsdGlDb2x1bW5QYXJlbnQgPSBjcmVhdGVEaXYoe1xuICAgICAgICAgICAgY2xzOiBgJHtNdWx0aUNvbHVtbkxheW91dENTUy5SZWdpb25Db2x1bW5Db250YWluZXJEaXZ9IFxcXG4gICAgICAgICAgICAgICAgICAke011bHRpQ29sdW1uTGF5b3V0Q1NTLkNvbnRlbnRPdmVyZmxvd0F1dG9TY3JvbGxfWH0gXFxcbiAgICAgICAgICAgICAgICAgICR7TXVsdGlDb2x1bW5MYXlvdXRDU1MuQ29udGVudE92ZXJmbG93SGlkZGVuX1l9O1xuICAgICAgICAgICAgICAgICAgYFxuICAgICAgICB9KTtcblxuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBQYXNzIG91ciBwYXJlbnQgZGl2IGFuZCBzZXR0aW5ncyB0byBwYXJzZXIgdG8gY3JlYXRlIHRoZSByZXF1aXJlZFxuICAgICAgICAgKiBjb2x1bW4gZGl2cyBhcyBjaGlsZHJlbiBvZiB0aGUgcGFyZW50LlxuICAgICAgICAgKi9cbiAgICAgICAgbGV0IGNvbHVtbkNvbnRlbnREaXZzID0gdGhpcy5nZXRDb2x1bW5Db250ZW50RGl2cyhzZXR0aW5ncywgbXVsdGlDb2x1bW5QYXJlbnQpO1xuICAgICAgICBpZihzZXR0aW5ncy5kcmF3U2hhZG93ID09PSB0cnVlKSB7XG4gICAgICAgICAgICBtdWx0aUNvbHVtblBhcmVudC5hZGRDbGFzcyhNdWx0aUNvbHVtblN0eWxlQ1NTLlJlZ2lvblNoYWRvdyk7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IobGV0IGkgPSAwOyBpIDwgY29sdW1uQ29udGVudERpdnMubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICAgICAgaWYoc2hvdWxkRHJhd0NvbHVtbkJvcmRlcihpLCBzZXR0aW5ncykgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2c1tpXS5hZGRDbGFzcyhNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtbkJvcmRlcik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKHNldHRpbmdzLmRyYXdTaGFkb3cgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2c1tpXS5hZGRDbGFzcyhNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtblNoYWRvdyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDcmVhdGUgbWFya2Rvd24gcmVuZGVyZXIgdG8gcGFyc2UgdGhlIHBhc3NlZCBtYXJrZG93blxuICAgICAgICAvLyBiZXR3ZWVuIHRoZSB0YWdzLlxuICAgICAgICBsZXQgbWFya2Rvd25SZW5kZXJDaGlsZCA9IG5ldyBNYXJrZG93blJlbmRlckNoaWxkKFxuICAgICAgICAgICAgbXVsdGlDb2x1bW5QYXJlbnRcbiAgICAgICAgKTtcblxuICAgICAgICAvLyBSZW1vdmUgZXZlcnkgb3RoZXIgY2hpbGQgZnJvbSB0aGUgcGFyZW50IHNvIFxuICAgICAgICAvLyB3ZSBkb250IGVuZCB1cCB3aXRoIG11bHRpcGxlIHNldHMgb2YgZGF0YS4gVGhpcyBzaG91bGRcbiAgICAgICAgLy8gcmVhbGx5IG9ubHkgbmVlZCB0byBsb29wIG9uY2UgZm9yIGkgPSAwIGJ1dCBsb29wIGp1c3RcbiAgICAgICAgLy8gaW4gY2FzZS5cbiAgICAgICAgZm9yKGxldCBpID0gcGFyZW50RWxlbWVudC5jaGlsZHJlbi5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICAgICAgcGFyZW50RWxlbWVudC5jaGlsZHJlbltpXS5kZXRhY2goKTtcbiAgICAgICAgfVxuICAgICAgICBwYXJlbnRFbGVtZW50LmFwcGVuZENoaWxkKG1hcmtkb3duUmVuZGVyQ2hpbGQuY29udGFpbmVyRWwpO1xuXG4gICAgICAgIHRoaXMuYXBwZW5kRWxlbWVudHNUb0NvbHVtbnMocmVnaW9uRWxlbWVudHMsIGNvbHVtbkNvbnRlbnREaXZzLCBzZXR0aW5ncywgaXNMaXZlUHJldmlldyk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhcHBlbmRFbGVtZW50c1RvQ29sdW1ucyhyZWdpb25FbGVtZW50czogRE9NT2JqZWN0W10sIGNvbHVtbkNvbnRlbnREaXZzOiBIVE1MRGl2RWxlbWVudFtdLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V0dGluZ3M6IE11bHRpQ29sdW1uU2V0dGluZ3MsIGlzTGl2ZVByZXZpZXc6IGJvb2xlYW4gPSBmYWxzZSkge1xuXG4gICAgICAgIGxldCBjb2x1bW5JbmRleCA9IDA7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcmVnaW9uRWxlbWVudHMubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICAgICAgaWYgKHJlZ2lvbkVsZW1lbnRzW2ldLnRhZyA9PT0gRE9NT2JqZWN0VGFnLm5vbmUgfHxcbiAgICAgICAgICAgICAgICByZWdpb25FbGVtZW50c1tpXS50YWcgPT09IERPTU9iamVjdFRhZy5jb2x1bW5CcmVhaykge1xuXG4gICAgICAgICAgICAgICAgLy8gSWYgYSBzdGFuZGFyZCBlbGVtZW50IGNvbnRhaW5zIGEgY29sdW1uIGJyZWFrIHRhZyBhbmQgaXQgaXMgc2V0IGFzIGEgcHJlIGNvbnRlbnQgYnJlYWsgdGFnIHdlIGZsaXAgb3VyIGluZGV4IGhlcmUuXG4gICAgICAgICAgICAgICAgaWYocmVnaW9uRWxlbWVudHNbaV0udGFnID09PSBET01PYmplY3RUYWcubm9uZSAmJiBcbiAgICAgICAgICAgICAgICAgICByZWdpb25FbGVtZW50c1tpXS5lbGVtZW50SXNDb2x1bW5CcmVhayA9PT0gRWxlbWVudENvbHVtbkJyZWFrVHlwZS5wcmVCcmVhayAmJiBcbiAgICAgICAgICAgICAgICAgICAoY29sdW1uSW5kZXggKyAxKSA8IHNldHRpbmdzLm51bWJlck9mQ29sdW1ucykge1xuICAgICAgICAgICAgICAgICAgICBjb2x1bW5JbmRleCsrO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIFdlIHN0b3JlIHRoZSBlbGVtZW50cyBpbiBhIHdyYXBwZXIgY29udGFpbmVyIHVudGlsIHdlIGRldGVybWluZVxuICAgICAgICAgICAgICAgIGxldCBlbGVtZW50ID0gY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgY2xzOiBNdWx0aUNvbHVtbkxheW91dENTUy5Db2x1bW5EdWFsRWxlbWVudENvbnRhaW5lcixcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIGlmKGNvbHVtbk92ZXJmbG93U3RhdGUoY29sdW1uSW5kZXgsIHNldHRpbmdzKSA9PT0gQ29udGVudE92ZXJmbG93VHlwZS5oaWRkZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5hZGRDbGFzcyhNdWx0aUNvbHVtbkxheW91dENTUy5Db250ZW50T3ZlcmZsb3dIaWRkZW5fWClcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuYWRkQ2xhc3MoTXVsdGlDb2x1bW5MYXlvdXRDU1MuQ29udGVudE92ZXJmbG93QXV0b1Njcm9sbF9YKVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGxldCBhbGlnbm1lbnQgPSBjb2x1bW5BbGlnbm1lbnRTdGF0ZShjb2x1bW5JbmRleCwgc2V0dGluZ3MpO1xuICAgICAgICAgICAgICAgIGlmKGFsaWdubWVudCA9PT0gQWxpZ25tZW50VHlwZS5jZW50ZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5hZGRDbGFzcyhNdWx0aUNvbHVtbkxheW91dENTUy5BbGlnbm1lbnRDZW50ZXIpXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGFsaWdubWVudCA9PT0gQWxpZ25tZW50VHlwZS5yaWdodCkge1xuICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmFkZENsYXNzKE11bHRpQ29sdW1uTGF5b3V0Q1NTLkFsaWdubWVudFJpZ2h0KVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5hZGRDbGFzcyhNdWx0aUNvbHVtbkxheW91dENTUy5BbGlnbm1lbnRMZWZ0KVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGxldCB0YWJsZUFsaWdubWVudCA9IE1DTV9TZXR0aW5nc01hbmFnZXIuc2hhcmVkLmFsaWduVGFibGVzVG9Db250ZW50QWxpZ25tZW50O1xuICAgICAgICAgICAgICAgIGlmKHNldHRpbmdzLmFsaWduVGFibGVzVG9BbGlnbm1lbnQgIT09IFRhYmxlQWxpZ25tZW50LnVzZVNldHRpbmdzRGVmYXVsdCkge1xuICAgICAgICAgICAgICAgICAgICB0YWJsZUFsaWdubWVudCA9IHNldHRpbmdzLmFsaWduVGFibGVzVG9BbGlnbm1lbnQgPT09IFRhYmxlQWxpZ25tZW50LmFsaWduXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmKHRhYmxlQWxpZ25tZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuYWRkQ2xhc3MoTXVsdGlDb2x1bW5MYXlvdXRDU1MuVGFibGVBbGlnbm1lbnQpXG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmVnaW9uRWxlbWVudHNbaV0uZWxlbWVudENvbnRhaW5lciA9IGVsZW1lbnQ7XG5cbiAgICAgICAgICAgICAgICBsZXQgZWxlbWVudFRvQXBwZW5kOiBIVE1MRWxlbWVudCA9IHJlZ2lvbkVsZW1lbnRzW2ldLm9yaWdpbmFsRWxlbWVudDtcbiAgICAgICAgICAgICAgICBpZihpc0xpdmVQcmV2aWV3ID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgICAgICBsZXQgY2xvbmVkRWxlbWVudCA9IHJlZ2lvbkVsZW1lbnRzW2ldLm9yaWdpbmFsRWxlbWVudC5jbG9uZU5vZGUodHJ1ZSkgYXMgSFRNTERpdkVsZW1lbnQ7XG4gICAgICAgICAgICAgICAgICAgIGxldCBoZWFkaW5nQ29sbGFwc2VFbGVtZW50ID0gZ2V0SGVhZGluZ0NvbGxhcHNlRWxlbWVudChjbG9uZWRFbGVtZW50KTtcbiAgICAgICAgICAgICAgICAgICAgaWYoaGVhZGluZ0NvbGxhcHNlRWxlbWVudCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhpcyByZW1vdmVzIHRoZSBjb2xsYXBzZSBhcnJvdyBmcm9tIHRoZSB2aWV3IGlmIGl0IGV4aXN0cy5cbiAgICAgICAgICAgICAgICAgICAgICAgIGhlYWRpbmdDb2xsYXBzZUVsZW1lbnQuZGV0YWNoKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmVnaW9uRWxlbWVudHNbaV0uY2xvbmVkRWxlbWVudCA9IGNsb25lZEVsZW1lbnQ7XG4gICAgICAgICAgICAgICAgICAgIGVsZW1lbnRUb0FwcGVuZCA9IGNsb25lZEVsZW1lbnQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZWxlbWVudC5hcHBlbmRDaGlsZChlbGVtZW50VG9BcHBlbmQpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHJlZ2lvbkVsZW1lbnRzW2ldIGluc3RhbmNlb2YgVGFza0xpc3RET01PYmplY3QpIHtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLmZpeENsb25lZENoZWNrTGlzdEJ1dHRvbnMocmVnaW9uRWxlbWVudHNbaV0gYXMgVGFza0xpc3RET01PYmplY3QsIHRydWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChlbGVtZW50ICE9PSBudWxsICYmIHJlZ2lvbkVsZW1lbnRzW2ldLnRhZyAhPT0gRE9NT2JqZWN0VGFnLmNvbHVtbkJyZWFrKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnNbY29sdW1uSW5kZXhdLmFwcGVuZENoaWxkKGVsZW1lbnQpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICAgICAqIElmIHRoZSB0YWcgaXMgYSBjb2x1bW4gYnJlYWsgd2UgdXBkYXRlIHRoZSBjb2x1bW4gaW5kZXggYWZ0ZXJcbiAgICAgICAgICAgICAgICAgKiBhcHBlbmRpbmcgdGhlIGl0ZW0gdG8gdGhlIGNvbHVtbiBkaXYuIFRoaXMga2VlcHMgdGhlIG1haW4gRE9NXG4gICAgICAgICAgICAgICAgICogY2xlYW5lciBieSByZW1vdmluZyBvdGhlciBpdGVtcyBhbmQgcGxhY2luZyB0aGVtIGFsbCB3aXRoaW5cbiAgICAgICAgICAgICAgICAgKiBhIHJlZ2lvbiBjb250YWluZXIuXG4gICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgaWYgKHJlZ2lvbkVsZW1lbnRzW2ldLnRhZyA9PT0gRE9NT2JqZWN0VGFnLmNvbHVtbkJyZWFrICYmXG4gICAgICAgICAgICAgICAgICAgIChjb2x1bW5JbmRleCArIDEpIDwgc2V0dGluZ3MubnVtYmVyT2ZDb2x1bW5zKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgY29sdW1uSW5kZXgrKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZihyZWdpb25FbGVtZW50c1tpXS50YWcgPT09IERPTU9iamVjdFRhZy5ub25lICYmIFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVnaW9uRWxlbWVudHNbaV0uZWxlbWVudElzQ29sdW1uQnJlYWsgPT09IEVsZW1lbnRDb2x1bW5CcmVha1R5cGUucG9zdEJyZWFrICYmIFxuICAgICAgICAgICAgICAgICAgICAgICAgKGNvbHVtbkluZGV4ICsgMSkgPCBzZXR0aW5ncy5udW1iZXJPZkNvbHVtbnMpIHtcblxuICAgICAgICAgICAgICAgICAgICAvLyBJZiBhIHN0YW5kYXJkIGVsZW1lbnQgY29udGFpbnMgYSBjb2x1bW4gYnJlYWsgdGFnIGFuZCBpdCBpcyBzZXQgYXMgYSBwb3N0IGNvbnRlbnQgYnJlYWsgdGFnIHdlIGZsaXAgb3VyIGluZGV4IGhlcmUuXG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbkluZGV4Kys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuIiwiLyoqXG4gKiBGaWxlOiAvc3JjL2RvbV9tYW5hZ2VyL3JlZ2lvbmFsX21hbmFnZXJzL3NpbmdsZUNvbHVtblJlZ2lvbk1hbmFnZXIudHMgICAgICAgKlxuICogQXV0aG9yOiBDYW1lcm9uIFJvYmluc29uICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjMgQ2FtZXJvbiBSb2JpbnNvbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICovXG5cbmltcG9ydCB7IERPTU9iamVjdCwgRE9NT2JqZWN0VGFnLCBUYXNrTGlzdERPTU9iamVjdCB9IGZyb20gJy4uL2RvbU9iamVjdCc7XG5pbXBvcnQgeyBNdWx0aUNvbHVtblNldHRpbmdzLCBDb2x1bW5MYXlvdXQsIENvbnRlbnRPdmVyZmxvd1R5cGUsIEFsaWdubWVudFR5cGUsIGNvbHVtbk92ZXJmbG93U3RhdGUsIGNvbHVtbkFsaWdubWVudFN0YXRlLCBzaG91bGREcmF3Q29sdW1uQm9yZGVyLCBUYWJsZUFsaWdubWVudCB9IGZyb20gXCIuLi8uLi9yZWdpb25TZXR0aW5nc1wiO1xuaW1wb3J0IHsgTXVsdGlDb2x1bW5MYXlvdXRDU1MsIE11bHRpQ29sdW1uU3R5bGVDU1MgfSBmcm9tICcuLi8uLi91dGlsaXRpZXMvY3NzRGVmaW5pdGlvbnMnO1xuaW1wb3J0IHsgTWFya2Rvd25SZW5kZXJDaGlsZCB9IGZyb20gJ29ic2lkaWFuJztcbmltcG9ydCB7IFJlZ2lvbk1hbmFnZXIgfSBmcm9tICcuL3JlZ2lvbk1hbmFnZXInO1xuaW1wb3J0IHsgZ2V0SGVhZGluZ0NvbGxhcHNlRWxlbWVudCB9IGZyb20gJ3NyYy91dGlsaXRpZXMvZWxlbWVudFJlbmRlclR5cGVQYXJzZXInO1xuaW1wb3J0IHsgTUNNX1NldHRpbmdzTWFuYWdlciB9IGZyb20gJ3NyYy9wbHVnaW5TZXR0aW5ncyc7XG5cbmV4cG9ydCBjbGFzcyBTaW5nbGVDb2x1bW5SZWdpb25NYW5hZ2VyIGV4dGVuZHMgUmVnaW9uTWFuYWdlciB7XG5cblxuICAgIHB1YmxpYyByZW5kZXJSZWdpb25FbGVtZW50c1RvU2NyZWVuKCk6IHZvaWQge1xuXG4gICAgICAgIHRoaXMucmVuZGVyQ29sdW1uTWFya2Rvd24odGhpcy5yZWdpb25QYXJlbnQsIHRoaXMuZG9tTGlzdCwgdGhpcy5yZWdpb25hbFNldHRpbmdzKTtcbiAgICB9XG4gICAgcHVibGljIGV4cG9ydFJlZ2lvbkVsZW1lbnRzVG9QREYocGRmUGFyZW50RWxlbWVudDogSFRNTEVsZW1lbnQpOiB2b2lkIHtcblxuICAgICAgICAvLyBEZWZhdWx0IHNldCBzaGFkb3cgdG8gb2ZmIGZvciBleHBvcnRpbmcgUERGc1xuICAgICAgICBsZXQgcmVuZGVyU2V0dGluZ3MgPSB0aGlzLnJlZ2lvbmFsU2V0dGluZ3M7XG4gICAgICAgIHJlbmRlclNldHRpbmdzLmRyYXdTaGFkb3cgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5yZW5kZXJDb2x1bW5NYXJrZG93bihwZGZQYXJlbnRFbGVtZW50LCB0aGlzLmRvbUxpc3Quc2xpY2UoKSwgcmVuZGVyU2V0dGluZ3MpO1xuICAgIH1cbiAgICBwdWJsaWMgcmVuZGVyUmVnaW9uRWxlbWVudHNUb0xpdmVQcmV2aWV3KHBhcmVudEVsZW1lbnQ6IEhUTUxFbGVtZW50KTogdm9pZCB7XG5cbiAgICAgICAgdGhpcy5yZW5kZXJDb2x1bW5NYXJrZG93bihwYXJlbnRFbGVtZW50LCB0aGlzLmRvbUxpc3QsIHRoaXMucmVnaW9uYWxTZXR0aW5ncywgdHJ1ZSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFRoaXMgZnVuY3Rpb24gdGFrZXMgaW4gdGhlIGRhdGEgZm9yIHRoZSBtdWx0aS1jb2x1bW4gcmVnaW9uIGFuZCBzZXRzIHVwIHRoZVxuICAgICAqIHVzZXIgZGVmaW5lZCBudW1iZXIgb2YgY2hpbGRyZW4gd2l0aCB0aGUgcHJvcGVyIGNzcyBjbGFzc2VzIHRvIGJlIHJlbmRlcmVkIHByb3Blcmx5LlxuICAgICAqXG4gICAgICogQHBhcmFtIHBhcmVudEVsZW1lbnQgVGhlIGVsZW1lbnQgdGhhdCB0aGUgbXVsdGktY29sdW1uIHJlZ2lvbiB3aWxsIGJlIHJlbmRlcmVkIHVuZGVyLlxuICAgICAqIEBwYXJhbSByZWdpb25FbGVtZW50cyBUaGUgbGlzdCBvZiBET00gb2JqZWN0cyB0aGF0IHdpbGwgYmUgY29wcGllZCB1bmRlciB0aGUgcGFyZW50IG9iamVjdFxuICAgICAqIEBwYXJhbSBzZXR0aW5ncyBUaGUgc2V0dGluZ3MgdGhlIHVzZXIgaGFzIGRlZmluZWQgZm9yIHRoZSByZWdpb24uXG4gICAgICovXG4gICAgcHJvdGVjdGVkIHJlbmRlckNvbHVtbk1hcmtkb3duKHBhcmVudEVsZW1lbnQ6IEhUTUxFbGVtZW50LCByZWdpb25FbGVtZW50czogRE9NT2JqZWN0W10sIHNldHRpbmdzOiBNdWx0aUNvbHVtblNldHRpbmdzLCBpc0xpdmVQcmV2aWV3OiBib29sZWFuID0gZmFsc2UpIHtcblxuICAgICAgICBsZXQgbXVsdGlDb2x1bW5QYXJlbnQgPSBjcmVhdGVEaXYoe1xuICAgICAgICAgICAgY2xzOiBgJHtNdWx0aUNvbHVtbkxheW91dENTUy5SZWdpb25Db2x1bW5Db250YWluZXJEaXZ9IFxcXG4gICAgICAgICAgICAgICAgICAke011bHRpQ29sdW1uTGF5b3V0Q1NTLkNvbnRlbnRPdmVyZmxvd0F1dG9TY3JvbGxfWH0gXFxcbiAgICAgICAgICAgICAgICAgICR7TXVsdGlDb2x1bW5MYXlvdXRDU1MuQ29udGVudE92ZXJmbG93SGlkZGVuX1l9O1xuICAgICAgICAgICAgICAgICAgYFxuICAgICAgICB9KTtcblxuICAgICAgICBpZihpc0xlZnRMYXlvdXQodGhpcy5yZWdpb25hbFNldHRpbmdzLmNvbHVtblBvc2l0aW9uKSl7XG4gICAgICAgICAgICBtdWx0aUNvbHVtblBhcmVudC5hZGRDbGFzcyhNdWx0aUNvbHVtbkxheW91dENTUy5TaW5nbGVDb2x1bW5MZWZ0TGF5b3V0KVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYoaXNSaWdodExheW91dCh0aGlzLnJlZ2lvbmFsU2V0dGluZ3MuY29sdW1uUG9zaXRpb24pKSB7XG4gICAgICAgICAgICBtdWx0aUNvbHVtblBhcmVudC5hZGRDbGFzcyhNdWx0aUNvbHVtbkxheW91dENTUy5TaW5nbGVDb2x1bW5SaWdodExheW91dClcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIG11bHRpQ29sdW1uUGFyZW50LmFkZENsYXNzKE11bHRpQ29sdW1uTGF5b3V0Q1NTLlNpbmdsZUNvbHVtbkNlbnRlckxheW91dClcbiAgICAgICAgfVxuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBQYXNzIG91ciBwYXJlbnQgZGl2IGFuZCBzZXR0aW5ncyB0byBwYXJzZXIgdG8gY3JlYXRlIHRoZSByZXF1aXJlZFxuICAgICAgICAgKiBjb2x1bW4gZGl2cyBhcyBjaGlsZHJlbiBvZiB0aGUgcGFyZW50LlxuICAgICAgICAgKi9cbiAgICAgICAgbGV0IGNvbHVtbkNvbnRlbnREaXYgPSB0aGlzLmNyZWF0ZUNvbHVtbkNvbnRlbnREaXZzKG11bHRpQ29sdW1uUGFyZW50KTtcbiAgICAgICAgaWYoc2hvdWxkRHJhd0NvbHVtbkJvcmRlcigwLCBzZXR0aW5ncykgPT09IHRydWUpIHtcbiAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXYuYWRkQ2xhc3MoTXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5Cb3JkZXIpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChzZXR0aW5ncy5kcmF3U2hhZG93ID09PSB0cnVlKSB7XG4gICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2LmFkZENsYXNzKE11bHRpQ29sdW1uU3R5bGVDU1MuQ29sdW1uU2hhZG93KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENyZWF0ZSBtYXJrZG93biByZW5kZXJlciB0byBwYXJzZSB0aGUgcGFzc2VkIG1hcmtkb3duXG4gICAgICAgIC8vIGJldHdlZW4gdGhlIHRhZ3MuXG4gICAgICAgIGxldCBtYXJrZG93blJlbmRlckNoaWxkID0gbmV3IE1hcmtkb3duUmVuZGVyQ2hpbGQoXG4gICAgICAgICAgICBtdWx0aUNvbHVtblBhcmVudFxuICAgICAgICApO1xuXG4gICAgICAgIC8vIFJlbW92ZSBldmVyeSBvdGhlciBjaGlsZCBmcm9tIHRoZSBwYXJlbnQgc28gXG4gICAgICAgIC8vIHdlIGRvbnQgZW5kIHVwIHdpdGggbXVsdGlwbGUgc2V0cyBvZiBkYXRhLiBUaGlzIHNob3VsZFxuICAgICAgICAvLyByZWFsbHkgb25seSBuZWVkIHRvIGxvb3Agb25jZSBmb3IgaSA9IDAgYnV0IGxvb3AganVzdFxuICAgICAgICAvLyBpbiBjYXNlLlxuICAgICAgICBmb3IgKGxldCBpID0gcGFyZW50RWxlbWVudC5jaGlsZHJlbi5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICAgICAgcGFyZW50RWxlbWVudC5jaGlsZHJlbltpXS5kZXRhY2goKTtcbiAgICAgICAgfVxuICAgICAgICBwYXJlbnRFbGVtZW50LmFwcGVuZENoaWxkKG1hcmtkb3duUmVuZGVyQ2hpbGQuY29udGFpbmVyRWwpO1xuXG4gICAgICAgIHRoaXMuYXBwZW5kRWxlbWVudHNUb0NvbHVtbnMocmVnaW9uRWxlbWVudHMsIGNvbHVtbkNvbnRlbnREaXYsIHNldHRpbmdzLCBpc0xpdmVQcmV2aWV3KTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgYXBwZW5kRWxlbWVudHNUb0NvbHVtbnMocmVnaW9uRWxlbWVudHM6IERPTU9iamVjdFtdLCBjb2x1bW5Db250ZW50RGl2OiBIVE1MRGl2RWxlbWVudCwgc2V0dGluZ3M6IE11bHRpQ29sdW1uU2V0dGluZ3MsIGlzTGl2ZVByZXZpZXc6IGJvb2xlYW4gPSBmYWxzZSkge1xuXG5cbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCByZWdpb25FbGVtZW50cy5sZW5ndGg7IGkrKykge1xuXG4gICAgICAgICAgICBpZiAocmVnaW9uRWxlbWVudHNbaV0udGFnID09PSBET01PYmplY3RUYWcubm9uZSB8fFxuICAgICAgICAgICAgICAgIHJlZ2lvbkVsZW1lbnRzW2ldLnRhZyA9PT0gRE9NT2JqZWN0VGFnLmNvbHVtbkJyZWFrKSB7XG5cbiAgICAgICAgICAgICAgICAvLyBXZSBzdG9yZSB0aGUgZWxlbWVudHMgaW4gYSB3cmFwcGVyIGNvbnRhaW5lciB1bnRpbCB3ZSBkZXRlcm1pbmVcbiAgICAgICAgICAgICAgICBsZXQgZWxlbWVudCA9IGNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgIGNsczogTXVsdGlDb2x1bW5MYXlvdXRDU1MuQ29sdW1uRHVhbEVsZW1lbnRDb250YWluZXIsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgcmVnaW9uRWxlbWVudHNbaV0uZWxlbWVudENvbnRhaW5lciA9IGVsZW1lbnQ7XG5cbiAgICAgICAgICAgICAgICBpZihjb2x1bW5PdmVyZmxvd1N0YXRlKDAsIHNldHRpbmdzKSA9PT0gQ29udGVudE92ZXJmbG93VHlwZS5oaWRkZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5hZGRDbGFzcyhNdWx0aUNvbHVtbkxheW91dENTUy5Db250ZW50T3ZlcmZsb3dIaWRkZW5fWClcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuYWRkQ2xhc3MoTXVsdGlDb2x1bW5MYXlvdXRDU1MuQ29udGVudE92ZXJmbG93QXV0b1Njcm9sbF9YKVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBsZXQgYWxpZ25tZW50ID0gY29sdW1uQWxpZ25tZW50U3RhdGUoMCwgc2V0dGluZ3MpO1xuICAgICAgICAgICAgICAgIGlmKGFsaWdubWVudCA9PT0gQWxpZ25tZW50VHlwZS5jZW50ZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5hZGRDbGFzcyhNdWx0aUNvbHVtbkxheW91dENTUy5BbGlnbm1lbnRDZW50ZXIpXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGFsaWdubWVudCA9PT0gQWxpZ25tZW50VHlwZS5yaWdodCkge1xuICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmFkZENsYXNzKE11bHRpQ29sdW1uTGF5b3V0Q1NTLkFsaWdubWVudFJpZ2h0KVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5hZGRDbGFzcyhNdWx0aUNvbHVtbkxheW91dENTUy5BbGlnbm1lbnRMZWZ0KVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGxldCB0YWJsZUFsaWdubWVudCA9IE1DTV9TZXR0aW5nc01hbmFnZXIuc2hhcmVkLmFsaWduVGFibGVzVG9Db250ZW50QWxpZ25tZW50O1xuICAgICAgICAgICAgICAgIGlmKHNldHRpbmdzLmFsaWduVGFibGVzVG9BbGlnbm1lbnQgIT09IFRhYmxlQWxpZ25tZW50LnVzZVNldHRpbmdzRGVmYXVsdCkge1xuICAgICAgICAgICAgICAgICAgICB0YWJsZUFsaWdubWVudCA9IHNldHRpbmdzLmFsaWduVGFibGVzVG9BbGlnbm1lbnQgPT09IFRhYmxlQWxpZ25tZW50LmFsaWduXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmKHRhYmxlQWxpZ25tZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuYWRkQ2xhc3MoTXVsdGlDb2x1bW5MYXlvdXRDU1MuVGFibGVBbGlnbm1lbnQpXG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgbGV0IGVsZW1lbnRUb0FwcGVuZDogSFRNTEVsZW1lbnQgPSByZWdpb25FbGVtZW50c1tpXS5vcmlnaW5hbEVsZW1lbnQ7XG4gICAgICAgICAgICAgICAgaWYoaXNMaXZlUHJldmlldyA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGNsb25lZEVsZW1lbnQgPSByZWdpb25FbGVtZW50c1tpXS5vcmlnaW5hbEVsZW1lbnQuY2xvbmVOb2RlKHRydWUpIGFzIEhUTUxEaXZFbGVtZW50O1xuICAgICAgICAgICAgICAgICAgICBsZXQgaGVhZGluZ0NvbGxhcHNlRWxlbWVudCA9IGdldEhlYWRpbmdDb2xsYXBzZUVsZW1lbnQoY2xvbmVkRWxlbWVudCk7XG4gICAgICAgICAgICAgICAgICAgIGlmKGhlYWRpbmdDb2xsYXBzZUVsZW1lbnQgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgcmVtb3ZlcyB0aGUgY29sbGFwc2UgYXJyb3cgZnJvbSB0aGUgdmlldyBpZiBpdCBleGlzdHMuXG4gICAgICAgICAgICAgICAgICAgICAgICBoZWFkaW5nQ29sbGFwc2VFbGVtZW50LmRldGFjaCgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJlZ2lvbkVsZW1lbnRzW2ldLmNsb25lZEVsZW1lbnQgPSBjbG9uZWRFbGVtZW50O1xuICAgICAgICAgICAgICAgICAgICBlbGVtZW50VG9BcHBlbmQgPSBjbG9uZWRFbGVtZW50XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsZW1lbnQuYXBwZW5kQ2hpbGQoZWxlbWVudFRvQXBwZW5kKTtcblxuICAgICAgICAgICAgICAgIGlmIChyZWdpb25FbGVtZW50c1tpXSBpbnN0YW5jZW9mIFRhc2tMaXN0RE9NT2JqZWN0KSB7XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5maXhDbG9uZWRDaGVja0xpc3RCdXR0b25zKHJlZ2lvbkVsZW1lbnRzW2ldIGFzIFRhc2tMaXN0RE9NT2JqZWN0LCB0cnVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoZWxlbWVudCAhPT0gbnVsbCkge1xuXG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXYuYXBwZW5kQ2hpbGQoZWxlbWVudCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgY3JlYXRlQ29sdW1uQ29udGVudERpdnMobXVsdGlDb2x1bW5QYXJlbnQ6IEhUTUxEaXZFbGVtZW50KTogSFRNTERpdkVsZW1lbnQge1xuXG4gICAgICAgIGxldCBjb250ZW50RGl2ID0gbXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgIGNsczogYCR7TXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5Db250ZW50fWBcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYodGhpcy5yZWdpb25hbFNldHRpbmdzLmNvbHVtblNpemUgPT09IFwic21hbGxcIikge1xuICAgICAgICAgICAgY29udGVudERpdi5hZGRDbGFzcyhgJHtNdWx0aUNvbHVtbkxheW91dENTUy5TaW5nbGVDb2x1bW5TbWFsbH1gKVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYodGhpcy5yZWdpb25hbFNldHRpbmdzLmNvbHVtblNpemUgPT09IFwibGFyZ2VcIikge1xuICAgICAgICAgICAgY29udGVudERpdi5hZGRDbGFzcyhgJHtNdWx0aUNvbHVtbkxheW91dENTUy5TaW5nbGVDb2x1bW5MYXJnZX1gKVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYodGhpcy5yZWdpb25hbFNldHRpbmdzLmNvbHVtblNpemUgPT09IFwiZnVsbFwiKSB7XG4gICAgICAgICAgICBjb250ZW50RGl2LmFkZENsYXNzKGAke011bHRpQ29sdW1uTGF5b3V0Q1NTLlNpbmdsZUNvbHVtbkZ1bGx9YClcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNvbnRlbnREaXYuYWRkQ2xhc3MoYCR7TXVsdGlDb2x1bW5MYXlvdXRDU1MuU2luZ2xlQ29sdW1uTWVkfWApXG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gY29udGVudERpdjtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGlzQ2VudGVyZWQobGF5b3V0OiBDb2x1bW5MYXlvdXQpOiBib29sZWFuIHtcblxuICAgIGlmKGxheW91dCA9PT0gXCJzdGFuZGFyZFwiIHx8XG4gICAgICAgbGF5b3V0ID09PSBcIm1pZGRsZVwiICAgfHxcbiAgICAgICBsYXlvdXQgPT09IFwiY2VudGVyXCIgICB8fFxuICAgICAgIGxheW91dCA9PT0gXCJzZWNvbmRcIiAgICApIHtcblxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2Vcbn1cblxuZnVuY3Rpb24gaXNMZWZ0TGF5b3V0KGxheW91dDogQ29sdW1uTGF5b3V0KTogYm9vbGVhbiB7XG5cbiAgICBpZihsYXlvdXQgPT09IFwibGVmdFwiIHx8XG4gICAgICAgbGF5b3V0ID09PSBcImZpcnN0XCIgKSB7XG4gXG4gICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgfVxuIFxuICAgICByZXR1cm4gZmFsc2Vcbn1cblxuZnVuY3Rpb24gaXNSaWdodExheW91dChsYXlvdXQ6IENvbHVtbkxheW91dCk6IGJvb2xlYW4ge1xuXG4gICAgaWYobGF5b3V0ID09PSBcInJpZ2h0XCIgfHxcbiAgICAgICBsYXlvdXQgPT09IFwidGhpcmRcIiB8fFxuICAgICAgIGxheW91dCA9PT0gXCJsYXN0XCIgKSB7XG4gXG4gICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgfVxuIFxuICAgICByZXR1cm4gZmFsc2Vcbn0iLCIvKipcbiAqIEZpbGU6IC9zcmMvZG9tX21hbmFnZXIvcmVnaW9uYWxfbWFuYWdlcnMvYXV0b0xheW91dFJlZ2lvbk1hbmFnZXIudHMgICAgICAgICAqXG4gKiBDcmVhdGVkIERhdGU6IFN1bmRheSwgTWF5IDIybmQgMjAyMiwgMTA6MjMgcG0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICogQXV0aG9yOiBDYW1lcm9uIFJvYmluc29uICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjIgQ2FtZXJvbiBSb2JpbnNvbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICovXG5cbmltcG9ydCB7IERPTU9iamVjdCwgRE9NT2JqZWN0VGFnLCBUYXNrTGlzdERPTU9iamVjdCB9IGZyb20gJy4uL2RvbU9iamVjdCc7XG5pbXBvcnQgeyBBbGlnbm1lbnRUeXBlLCBDb250ZW50T3ZlcmZsb3dUeXBlLCBNdWx0aUNvbHVtblNldHRpbmdzLCBUYWJsZUFsaWdubWVudCwgY29sdW1uQWxpZ25tZW50U3RhdGUsIGNvbHVtbk92ZXJmbG93U3RhdGUsIHNob3VsZERyYXdDb2x1bW5Cb3JkZXIgfSBmcm9tIFwiLi4vLi4vcmVnaW9uU2V0dGluZ3NcIjtcbmltcG9ydCB7IE11bHRpQ29sdW1uTGF5b3V0Q1NTLCBNdWx0aUNvbHVtblN0eWxlQ1NTIH0gZnJvbSAnLi4vLi4vdXRpbGl0aWVzL2Nzc0RlZmluaXRpb25zJztcbmltcG9ydCB7IFJlZ2lvbk1hbmFnZXIgfSBmcm9tICcuL3JlZ2lvbk1hbmFnZXInO1xuaW1wb3J0IHsgZ2V0SGVhZGluZ0NvbGxhcHNlRWxlbWVudCwgaGFzSGVhZGVyIH0gZnJvbSAnc3JjL3V0aWxpdGllcy9lbGVtZW50UmVuZGVyVHlwZVBhcnNlcic7XG5pbXBvcnQgeyBSZWdpb25NYW5hZ2VyRGF0YSB9IGZyb20gJy4vcmVnaW9uTWFuYWdlckNvbnRhaW5lcic7XG5pbXBvcnQgeyBNQ01fU2V0dGluZ3NNYW5hZ2VyIH0gZnJvbSAnc3JjL3BsdWdpblNldHRpbmdzJztcblxuZXhwb3J0IGNsYXNzIEF1dG9MYXlvdXRSZWdpb25NYW5hZ2VyIGV4dGVuZHMgUmVnaW9uTWFuYWdlciB7XG5cbiAgICBwcml2YXRlIGlzTGl2ZVByZXZpZXc6IGJvb2xlYW4gPSBmYWxzZTtcbiAgICBwcml2YXRlIHByZXZpb3VzQ29sdW1uSGVpZ2h0czogbnVtYmVyW10gPSBbXVxuXG4gICAgcHJpdmF0ZSBjb2x1bW5QYXJlbnQ6IEhUTUxEaXZFbGVtZW50O1xuICAgIHByaXZhdGUgY29sdW1uRGl2czogSFRNTERpdkVsZW1lbnRbXTtcbiAgICBwcml2YXRlIGRvY1JlZmxvdzogYm9vbGVhbjtcblxuICAgIGNvbnN0cnVjdG9yKGRhdGE6IFJlZ2lvbk1hbmFnZXJEYXRhLCBpc0xpdmVQcmV2aWV3OiBib29sZWFuID0gZmFsc2UpIHtcbiAgICAgICAgc3VwZXIoZGF0YSk7XG5cbiAgICAgICAgdGhpcy5pc0xpdmVQcmV2aWV3ID0gaXNMaXZlUHJldmlldztcbiAgICAgICAgdGhpcy5kb2NSZWZsb3cgPSBkYXRhLnJlZ2lvbmFsU2V0dGluZ3MuZnVsbERvY1JlZmxvdztcbiAgICB9XG5cbiAgICBwdWJsaWMgcmVuZGVyUmVnaW9uRWxlbWVudHNUb1NjcmVlbigpOiB2b2lkIHtcblxuICAgICAgICAgdGhpcy5yZW5kZXJDb2x1bW5NYXJrZG93bih0aGlzLnJlZ2lvblBhcmVudCwgdGhpcy5kb21MaXN0LCB0aGlzLnJlZ2lvbmFsU2V0dGluZ3MpO1xuICAgIH1cbiAgICBwdWJsaWMgZXhwb3J0UmVnaW9uRWxlbWVudHNUb1BERihwZGZQYXJlbnRFbGVtZW50OiBIVE1MRWxlbWVudCk6IHZvaWQge1xuXG4gICAgICAgIC8vIERlZmF1bHQgc2V0IHNoYWRvdyB0byBvZmYgZm9yIGV4cG9ydGluZyBQREZzXG4gICAgICAgIGxldCByZW5kZXJTZXR0aW5ncyA9IHRoaXMucmVnaW9uYWxTZXR0aW5ncztcbiAgICAgICAgcmVuZGVyU2V0dGluZ3MuZHJhd1NoYWRvdyA9IGZhbHNlO1xuICAgICAgICB0aGlzLnJlbmRlckNvbHVtbk1hcmtkb3duKHBkZlBhcmVudEVsZW1lbnQsIHRoaXMuZG9tTGlzdC5zbGljZSgpLCByZW5kZXJTZXR0aW5ncyk7XG4gICAgfVxuICAgIHB1YmxpYyByZW5kZXJSZWdpb25FbGVtZW50c1RvTGl2ZVByZXZpZXcocGFyZW50RWxlbWVudDogSFRNTEVsZW1lbnQpOiB2b2lkIHtcblxuICAgICAgICB0aGlzLnJlbmRlckNvbHVtbk1hcmtkb3duKHBhcmVudEVsZW1lbnQsIHRoaXMuZG9tTGlzdCwgdGhpcy5yZWdpb25hbFNldHRpbmdzLCB0cnVlKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogVGhpcyBmdW5jdGlvbiB0YWtlcyBpbiB0aGUgZGF0YSBmb3IgdGhlIG11bHRpLWNvbHVtbiByZWdpb24gYW5kIHNldHMgdXAgdGhlIFxuICAgICAqIHVzZXIgZGVmaW5lZCBudW1iZXIgb2YgY2hpbGRyZW4gd2l0aCB0aGUgcHJvcGVyIGNzcyBjbGFzc2VzIHRvIGJlIHJlbmRlcmVkIHByb3Blcmx5LlxuICAgICAqIFxuICAgICAqIEBwYXJhbSBwYXJlbnRFbGVtZW50IFRoZSBlbGVtZW50IHRoYXQgdGhlIG11bHRpLWNvbHVtbiByZWdpb24gd2lsbCBiZSByZW5kZXJlZCB1bmRlci5cbiAgICAgKiBAcGFyYW0gcmVnaW9uRWxlbWVudHMgVGhlIGxpc3Qgb2YgRE9NIG9iamVjdHMgdGhhdCB3aWxsIGJlIGNvcHBpZWQgdW5kZXIgdGhlIHBhcmVudCBvYmplY3RcbiAgICAgKiBAcGFyYW0gc2V0dGluZ3MgVGhlIHNldHRpbmdzIHRoZSB1c2VyIGhhcyBkZWZpbmVkIGZvciB0aGUgcmVnaW9uLlxuICAgICAqL1xuICAgIHByaXZhdGUgcmVuZGVyQ29sdW1uTWFya2Rvd24ocGFyZW50RWxlbWVudDogSFRNTEVsZW1lbnQsIHJlZ2lvbkVsZW1lbnRzOiBET01PYmplY3RbXSwgc2V0dGluZ3M6IE11bHRpQ29sdW1uU2V0dGluZ3MsIGlzTGl2ZVByZXZpZXc6IGJvb2xlYW4gPSBmYWxzZSkge1xuXG4gICAgICAgIGxldCBtdWx0aUNvbHVtblBhcmVudCA9IGNyZWF0ZURpdih7XG4gICAgICAgICAgICBjbHM6IGAke011bHRpQ29sdW1uTGF5b3V0Q1NTLlJlZ2lvbkNvbHVtbkNvbnRhaW5lckRpdn0gXFxcbiAgICAgICAgICAgICAgICAgICR7TXVsdGlDb2x1bW5MYXlvdXRDU1MuQ29udGVudE92ZXJmbG93QXV0b1Njcm9sbF9YfSBcXFxuICAgICAgICAgICAgICAgICAgJHtNdWx0aUNvbHVtbkxheW91dENTUy5Db250ZW50T3ZlcmZsb3dIaWRkZW5fWX07XG4gICAgICAgICAgICAgICAgICBgXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmNvbHVtblBhcmVudCA9IG11bHRpQ29sdW1uUGFyZW50O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBQYXNzIG91ciBwYXJlbnQgZGl2IGFuZCBzZXR0aW5ncyB0byBwYXJzZXIgdG8gY3JlYXRlIHRoZSByZXF1aXJlZFxuICAgICAgICAgKiBjb2x1bW4gZGl2cyBhcyBjaGlsZHJlbiBvZiB0aGUgcGFyZW50LlxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5jb2x1bW5EaXZzID0gdGhpcy5nZXRDb2x1bW5Db250ZW50RGl2cyhzZXR0aW5ncywgbXVsdGlDb2x1bW5QYXJlbnQpO1xuXG4gICAgICAgIGlmIChzZXR0aW5ncy5kcmF3U2hhZG93ID09PSB0cnVlKSB7XG4gICAgICAgICAgICBtdWx0aUNvbHVtblBhcmVudC5hZGRDbGFzcyhNdWx0aUNvbHVtblN0eWxlQ1NTLlJlZ2lvblNoYWRvdyk7XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmNvbHVtbkRpdnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmKHNob3VsZERyYXdDb2x1bW5Cb3JkZXIoaSwgc2V0dGluZ3MpID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jb2x1bW5EaXZzW2ldLmFkZENsYXNzKE11bHRpQ29sdW1uU3R5bGVDU1MuQ29sdW1uQm9yZGVyKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHNldHRpbmdzLmRyYXdTaGFkb3cgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbHVtbkRpdnNbaV0uYWRkQ2xhc3MoTXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5TaGFkb3cpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVtb3ZlIGV2ZXJ5IG90aGVyIGNoaWxkIGZyb20gdGhlIHBhcmVudCBzbyBcbiAgICAgICAgLy8gd2UgZG9udCBlbmQgdXAgd2l0aCBtdWx0aXBsZSBzZXRzIG9mIGRhdGEuIFRoaXMgc2hvdWxkXG4gICAgICAgIC8vIHJlYWxseSBvbmx5IG5lZWQgdG8gbG9vcCBvbmNlIGZvciBpID0gMCBidXQgbG9vcCBqdXN0XG4gICAgICAgIC8vIGluIGNhc2UuXG4gICAgICAgIGZvciAobGV0IGkgPSBwYXJlbnRFbGVtZW50LmNoaWxkcmVuLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgICAgICBwYXJlbnRFbGVtZW50LmNoaWxkcmVuW2ldLmRldGFjaCgpO1xuICAgICAgICB9XG4gICAgICAgIHBhcmVudEVsZW1lbnQuYXBwZW5kQ2hpbGQobXVsdGlDb2x1bW5QYXJlbnQpO1xuXG4gICAgICAgIHRoaXMuYXBwZW5kRWxlbWVudHNUb0NvbHVtbnMocmVnaW9uRWxlbWVudHMsIHRoaXMuY29sdW1uRGl2cywgc2V0dGluZ3MsIGlzTGl2ZVByZXZpZXcpO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXBwZW5kRWxlbWVudHNUb0NvbHVtbnMocmVnaW9uRWxlbWVudHM6IERPTU9iamVjdFtdLCBjb2x1bW5Db250ZW50RGl2czogSFRNTERpdkVsZW1lbnRbXSwgc2V0dGluZ3M6IE11bHRpQ29sdW1uU2V0dGluZ3MsIGlzTGl2ZVByZXZpZXc6IGJvb2xlYW4gPSBmYWxzZSkge1xuXG4gICAgICAgIGZ1bmN0aW9uIGJhbGFuY2VFbGVtZW50cygpIHtcblxuICAgICAgICAgICAgbGV0IHRvdGFsSGVpZ2h0ID0gcmVnaW9uRWxlbWVudHMubWFwKChlbDogRE9NT2JqZWN0LCBpbmRleDogbnVtYmVyKSA9PiB7IFxuXG4gICAgICAgICAgICAgICAgLy8gV2Ugb25seSB3YW50IHRvIGF0dGVtcHQgdG8gdXBkYXRlIHRoZSBlbGVtZW50UmVuZGVyZWRIZWlnaHQgaWYgaXQgaXMgMCBhbmQgaWYgaXQgaXMgbm90IGFuIHVucmVuZGVyZWQgZWxlbWVudCBzdWNoIGFzIGEgZW5kcmVnaW9uIHRhZy5cbiAgICAgICAgICAgICAgICBpZihlbC5lbGVtZW50UmVuZGVyZWRIZWlnaHQgPT09IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgZWwudGFnICE9PSBET01PYmplY3RUYWcuY29sdW1uQnJlYWsgJiZcbiAgICAgICAgICAgICAgICAgICAgZWwudGFnICE9PSBET01PYmplY3RUYWcuZW5kUmVnaW9uICYmXG4gICAgICAgICAgICAgICAgICAgIGVsLnRhZyAhPT0gRE9NT2JqZWN0VGFnLnJlZ2lvblNldHRpbmdzICYmXG4gICAgICAgICAgICAgICAgICAgIGVsLnRhZyAhPT0gRE9NT2JqZWN0VGFnLnN0YXJ0UmVnaW9uKSB7XG4gICAgXG4gICAgICAgICAgICAgICAgICAgIC8vIEFkZCBlbGVtZW50IHRvIHJlbmRlcmVkIGRpdiBzbyB3ZSBjYW4gZXh0cmFjdCB0aGUgcmVuZGVyZWQgaGVpZ2h0LlxuICAgICAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2c1swXS5hcHBlbmRDaGlsZChlbC5vcmlnaW5hbEVsZW1lbnQpXG4gICAgICAgICAgICAgICAgICAgIGVsLmVsZW1lbnRSZW5kZXJlZEhlaWdodCA9IGVsLm9yaWdpbmFsRWxlbWVudC5jbGllbnRIZWlnaHRcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnNbMF0ucmVtb3ZlQ2hpbGQoZWwub3JpZ2luYWxFbGVtZW50KVxuICAgICAgICAgICAgICAgIH1cbiAgICBcbiAgICAgICAgICAgICAgICByZXR1cm4gZWwuZWxlbWVudFJlbmRlcmVkSGVpZ2h0IFxuICAgICAgICAgICAgfSkucmVkdWNlKChwcmV2OiBudW1iZXIsIGN1cnI6IG51bWJlcikgPT4geyByZXR1cm4gcHJldiArIGN1cnIgfSwgMCk7XG4gICAgICAgICAgICBsZXQgbWF4Q29sdW1uQ29udGVudEhlaWdodCA9IE1hdGgudHJ1bmModG90YWxIZWlnaHQgLyBzZXR0aW5ncy5udW1iZXJPZkNvbHVtbnMpO1xuXG4gICAgICAgICAgICBmb3IobGV0IGkgPSAwOyBpIDwgY29sdW1uQ29udGVudERpdnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gY29sdW1uQ29udGVudERpdnNbaV0uY2hpbGRyZW4ubGVuZ3RoIC0gMTsgaiA+PSAwOyBqLS0pIHtcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnNbaV0uY2hpbGRyZW5bal0uZGV0YWNoKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBsZXQgY29sdW1uSW5kZXggPSAwO1xuICAgICAgICAgICAgbGV0IGN1cnJlbnRDb2x1bW5IZWlnaHQgPSAwO1xuICAgICAgICAgICAgZnVuY3Rpb24gY2hlY2tTaG91bGRTd2l0Y2hDb2x1bW5zKG5leHRFbGVtZW50SGVpZ2h0OiBudW1iZXIpIHtcbiAgICBcbiAgICAgICAgICAgICAgICBpZiAoY3VycmVudENvbHVtbkhlaWdodCArIG5leHRFbGVtZW50SGVpZ2h0ID4gbWF4Q29sdW1uQ29udGVudEhlaWdodCAmJlxuICAgICAgICAgICAgICAgICAgICAoY29sdW1uSW5kZXggKyAxKSA8IHNldHRpbmdzLm51bWJlck9mQ29sdW1ucykge1xuICAgIFxuICAgICAgICAgICAgICAgICAgICBjb2x1bW5JbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50Q29sdW1uSGVpZ2h0ID0gMDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcmVnaW9uRWxlbWVudHMubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICAgICAgICAgIGlmIChyZWdpb25FbGVtZW50c1tpXS50YWcgPT09IERPTU9iamVjdFRhZy5ub25lIHx8XG4gICAgICAgICAgICAgICAgICAgIHJlZ2lvbkVsZW1lbnRzW2ldLnRhZyA9PT0gRE9NT2JqZWN0VGFnLmNvbHVtbkJyZWFrKSB7XG4gICAgXG4gICAgICAgICAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICAgICAgICAgKiBIZXJlIHdlIGNoZWNrIGlmIHdlIG5lZWQgdG8gc3dhcCB0byB0aGUgbmV4dCBjb2x1bW4gZm9yIHRoZSBjdXJyZW50IGVsZW1lbnQuXG4gICAgICAgICAgICAgICAgICAgICAqIElmIHRoZSB1c2VyIHdhbnRzIHRvIGtlZXAgaGVhZGluZ3Mgd2l0aCB0aGUgY29udGVudCBiZWxvdyBpdCB3ZSBhbHNvIG1ha2Ugc3VyZVxuICAgICAgICAgICAgICAgICAgICAgKiB0aGF0IHRoZSBsYXN0IGl0ZW0gaW4gYSBjb2x1bW4gaXMgbm90IGEgaGVhZGVyIGVsZW1lbnQgYnkgdXNpbmcgdGhlIGhlYWRlciBhbmRcbiAgICAgICAgICAgICAgICAgICAgICogdGhlIG5leHQgZWxlbWVudCdzIGhlaWdodCBhcyB0aGUgaGVpZ2h0IHZhbHVlLiBcbiAgICAgICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgICAgIGlmKGhhc0hlYWRlcihyZWdpb25FbGVtZW50c1tpXS5vcmlnaW5hbEVsZW1lbnQpID09PSB0cnVlKSB7IC8vIFRPRE86IEFkZCB0aGlzIGFzIHNlbGVjdGFibGUgb3B0aW9uLlxuICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGhlYWRlckFuZE5leHRFbGVtZW50SGVpZ2h0ID0gcmVnaW9uRWxlbWVudHNbaV0uZWxlbWVudFJlbmRlcmVkSGVpZ2h0O1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYoaSA8IHJlZ2lvbkVsZW1lbnRzLmxlbmd0aCAtIDEpIHtcbiAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoZWFkZXJBbmROZXh0RWxlbWVudEhlaWdodCArPSByZWdpb25FbGVtZW50c1tpICsgMV0uZWxlbWVudFJlbmRlcmVkSGVpZ2h0O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgY2hlY2tTaG91bGRTd2l0Y2hDb2x1bW5zKGhlYWRlckFuZE5leHRFbGVtZW50SGVpZ2h0KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoZWNrU2hvdWxkU3dpdGNoQ29sdW1ucyhyZWdpb25FbGVtZW50c1tpXS5lbGVtZW50UmVuZGVyZWRIZWlnaHQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRDb2x1bW5IZWlnaHQgKz0gcmVnaW9uRWxlbWVudHNbaV0uZWxlbWVudFJlbmRlcmVkSGVpZ2h0XG4gICAgXG4gICAgXG4gICAgICAgICAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICAgICAgICAgKiBXZSBzdG9yZSB0aGUgZWxlbWVudHMgaW4gYSB3cmFwcGVyIGNvbnRhaW5lciB1bnRpbCB3ZSBkZXRlcm1pbmUgaWYgd2Ugd2FudCB0byBcbiAgICAgICAgICAgICAgICAgICAgICogdXNlIHRoZSBvcmlnaW5hbCBlbGVtZW50IG9yIGEgY2xvbmUgb2YgdGhlIGVsZW1lbnQuIFRoaXMgaGVscHMgdXMgYnkgYWxsb3dpbmcgXG4gICAgICAgICAgICAgICAgICAgICAqIHVzIHRvIGNyZWF0ZSBhIHZpc3VhbCBvbmx5IGNsb25lIHdoaWxlIHRoZSB1cGRhdGUgbG9vcCBtb3ZlcyB0aGUgb3JpZ2luYWwgZWxlbWVudCBcbiAgICAgICAgICAgICAgICAgICAgICogaW50byB0aGUgY29sdW1ucy5cbiAgICAgICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgICAgIGxldCBlbGVtZW50ID0gY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsczogTXVsdGlDb2x1bW5MYXlvdXRDU1MuQ29sdW1uRHVhbEVsZW1lbnRDb250YWluZXIsXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICByZWdpb25FbGVtZW50c1tpXS5lbGVtZW50Q29udGFpbmVyID0gZWxlbWVudDtcbiAgICBcbiAgICAgICAgICAgICAgICAgICAgaWYoY29sdW1uT3ZlcmZsb3dTdGF0ZShjb2x1bW5JbmRleCwgc2V0dGluZ3MpID09PSBDb250ZW50T3ZlcmZsb3dUeXBlLmhpZGRlbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5hZGRDbGFzcyhNdWx0aUNvbHVtbkxheW91dENTUy5Db250ZW50T3ZlcmZsb3dIaWRkZW5fWClcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuYWRkQ2xhc3MoTXVsdGlDb2x1bW5MYXlvdXRDU1MuQ29udGVudE92ZXJmbG93QXV0b1Njcm9sbF9YKVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICBsZXQgYWxpZ25tZW50ID0gY29sdW1uQWxpZ25tZW50U3RhdGUoY29sdW1uSW5kZXgsIHNldHRpbmdzKTtcbiAgICAgICAgICAgICAgICAgICAgaWYoYWxpZ25tZW50ID09PSBBbGlnbm1lbnRUeXBlLmNlbnRlcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5hZGRDbGFzcyhNdWx0aUNvbHVtbkxheW91dENTUy5BbGlnbm1lbnRDZW50ZXIpXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoYWxpZ25tZW50ID09PSBBbGlnbm1lbnRUeXBlLnJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmFkZENsYXNzKE11bHRpQ29sdW1uTGF5b3V0Q1NTLkFsaWdubWVudFJpZ2h0KVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5hZGRDbGFzcyhNdWx0aUNvbHVtbkxheW91dENTUy5BbGlnbm1lbnRMZWZ0KVxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgbGV0IHRhYmxlQWxpZ25tZW50ID0gTUNNX1NldHRpbmdzTWFuYWdlci5zaGFyZWQuYWxpZ25UYWJsZXNUb0NvbnRlbnRBbGlnbm1lbnQ7XG4gICAgICAgICAgICAgICAgICAgIGlmKHNldHRpbmdzLmFsaWduVGFibGVzVG9BbGlnbm1lbnQgIT09IFRhYmxlQWxpZ25tZW50LnVzZVNldHRpbmdzRGVmYXVsdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGFibGVBbGlnbm1lbnQgPSBzZXR0aW5ncy5hbGlnblRhYmxlc1RvQWxpZ25tZW50ID09PSBUYWJsZUFsaWdubWVudC5hbGlnblxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmKHRhYmxlQWxpZ25tZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmFkZENsYXNzKE11bHRpQ29sdW1uTGF5b3V0Q1NTLlRhYmxlQWxpZ25tZW50KVxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgbGV0IGVsZW1lbnRUb0FwcGVuZDogSFRNTEVsZW1lbnQgPSByZWdpb25FbGVtZW50c1tpXS5vcmlnaW5hbEVsZW1lbnQ7XG4gICAgICAgICAgICAgICAgICAgIGlmKGlzTGl2ZVByZXZpZXcgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgY2xvbmVkRWxlbWVudCA9IHJlZ2lvbkVsZW1lbnRzW2ldLmNsb25lZEVsZW1lbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZihyZWdpb25FbGVtZW50c1tpXS5jbG9uZWRFbGVtZW50ID09PSBudWxsKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbG9uZWRFbGVtZW50ID0gcmVnaW9uRWxlbWVudHNbaV0ub3JpZ2luYWxFbGVtZW50LmNsb25lTm9kZSh0cnVlKSBhcyBIVE1MRGl2RWxlbWVudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgaGVhZGluZ0NvbGxhcHNlRWxlbWVudCA9IGdldEhlYWRpbmdDb2xsYXBzZUVsZW1lbnQoY2xvbmVkRWxlbWVudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYoaGVhZGluZ0NvbGxhcHNlRWxlbWVudCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIHJlbW92ZXMgdGhlIGNvbGxhcHNlIGFycm93IGZyb20gdGhlIHZpZXcgaWYgaXQgZXhpc3RzLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoZWFkaW5nQ29sbGFwc2VFbGVtZW50LmRldGFjaCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZ2lvbkVsZW1lbnRzW2ldLmNsb25lZEVsZW1lbnQgPSBjbG9uZWRFbGVtZW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnRUb0FwcGVuZCA9IGNsb25lZEVsZW1lbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5hcHBlbmRDaGlsZChlbGVtZW50VG9BcHBlbmQpO1xuICAgIFxuICAgICAgICAgICAgICAgICAgICBpZiAocmVnaW9uRWxlbWVudHNbaV0gaW5zdGFuY2VvZiBUYXNrTGlzdERPTU9iamVjdCkge1xuICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5maXhDbG9uZWRDaGVja0xpc3RCdXR0b25zKHJlZ2lvbkVsZW1lbnRzW2ldIGFzIFRhc2tMaXN0RE9NT2JqZWN0LCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgIFxuICAgICAgICAgICAgICAgICAgICBpZiAoZWxlbWVudCAhPT0gbnVsbCAmJiBcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzW2NvbHVtbkluZGV4XSAmJiBcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlZ2lvbkVsZW1lbnRzW2ldLnRhZyAhPT0gRE9NT2JqZWN0VGFnLmNvbHVtbkJyZWFrKSB7XG4gICAgXG4gICAgICAgICAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2c1tjb2x1bW5JbmRleF0uYXBwZW5kQ2hpbGQoZWxlbWVudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWdpb25FbGVtZW50c1tpXS5lbGVtZW50UmVuZGVyZWRIZWlnaHQgPSBlbGVtZW50LmNsaWVudEhlaWdodDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgIFxuICAgICAgICAgICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAgICAgICAgICogSWYgdGhlIHRhZyBpcyBhIGNvbHVtbiBicmVhayB3ZSB1cGRhdGUgdGhlIGNvbHVtbiBpbmRleCBhZnRlclxuICAgICAgICAgICAgICAgICAgICAgKiBhcHBlbmRpbmcgdGhlIGl0ZW0gdG8gdGhlIGNvbHVtbiBkaXYuIFRoaXMga2VlcHMgdGhlIG1haW4gRE9NXG4gICAgICAgICAgICAgICAgICAgICAqIGNsZWFuZXIgYnkgcmVtb3Zpbmcgb3RoZXIgaXRlbXMgYW5kIHBsYWNpbmcgdGhlbSBhbGwgd2l0aGluXG4gICAgICAgICAgICAgICAgICAgICAqIGEgcmVnaW9uIGNvbnRhaW5lci5cbiAgICAgICAgICAgICAgICAgICAgICogXG4gICAgICAgICAgICAgICAgICAgICAqIFJlbW92aW5nIHRoZSBlbmQgY29sdW1uIHRhZyBhcyBhbiBvcHRpb24gZm9yIG5vdy5cbiAgICAgICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgICAgIC8vIGlmIChyZWdpb25FbGVtZW50c1tpXS50YWcgPT09IERPTU9iamVjdFRhZy5jb2x1bW5CcmVhayAmJlxuICAgICAgICAgICAgICAgICAgICAvLyAgICAoY29sdW1uSW5kZXggKyAxKSA8IHNldHRpbmdzLm51bWJlck9mQ29sdW1ucykge1xuICAgIFxuICAgICAgICAgICAgICAgICAgICAvLyAgICAgY29sdW1uSW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgLy8gICAgIGN1cnJlbnRDb2x1bW5IZWlnaHQgPSAwO1xuICAgICAgICAgICAgICAgICAgICAvLyB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEF0dGVtcHQgdG8gYmFsYW5jZWQgdGhlIGVsZW1lbnRzLiBXZSBuZWVkIHRvIGl0ZXJhdGUgb3ZlciB0aGUgZWxlbWVudHMgbXVsdGlwbGUgdGltZXMgYmVjYXVzZVxuICAgICAgICAgKiBvdXIgaW5pdGlhbCBiYWxhbmNlIGVzdGltYXRlIG1heSBub3QgYmUgcGVyZmVjdGx5IGJhbGFuY2VkIGR1ZSB0byBkaWZmZXJlbnQgY29sdW1uIHdpZHRocyBjYXVzaW5nIFxuICAgICAgICAgKiBlbGVtZW50cyB3aXRoaW4gdGhlbSB0byBiZSBvZiBkaWZmZXJlbnQgaGVpZ2h0cy4gVGhpcyBjYW4gY2F1c2UgdGhlIGVsZW1lbnRzIHRvIGp1bXAgYXJvdW5kIG9uIFxuICAgICAgICAgKiBzdWJzaXF1ZW50IHVwZGF0ZSBsb29wcyB3aGljaCBpcyBub3QgaWRlYWwuIEhlcmUgd2UgcmVuZGVyIHRoZSBlbGVtZW50cyB0byB0aGUgc2NyZWVuIGFuZCB1cGRhdGUgXG4gICAgICAgICAqIHRoZWlyIGhlaWdodCBhZnRlciBiZWluZyByZW5kZXJlZCBpbnRvIHRoZSBlc3RpbWF0ZWQgcG9zaXRpb24uIFxuICAgICAgICAgKiBcbiAgICAgICAgICogT25jZSBldmVyeXRoaW5nIGlzIHJlbmRlcmVkIHdlIGNoZWNrIGFsbCBvZiB0aGUgY29sdW1uIGhlaWdodHMgYWdhaW5zdCBvdXIgbGFzdCBpdGVyYXRpb24gYW5kIFxuICAgICAgICAgKiBpZiBub3RoaW5nIGhhcyBjaGFuZ2VkIHdlIGtub3cgd2UgYXJlIGJhbGFuY2VkLlxuICAgICAgICAgKiBcbiAgICAgICAgICogVGhlcmUgaXMgcHJvYmFibHkgYSBiZXR0ZXIgd2F5IG9mIGFjY29tcGxpc2hpbmcgdGhpcyB0YXNrIGJ1dCB0aGlzIHdvcmtzIGZvciB0aGUgdGltZSBiZWluZy5cbiAgICAgICAgICovXG5cbiAgICAgICAgbGV0IGF1dG9MYXlvdXRCYWxhbmNlSXRlcmF0aW9ucyA9IDE7XG4gICAgICAgIGlmKHRoaXMuaXNMaXZlUHJldmlldyA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIGF1dG9MYXlvdXRCYWxhbmNlSXRlcmF0aW9ucyA9IE1DTV9TZXR0aW5nc01hbmFnZXIuc2hhcmVkLmF1dG9MYXlvdXRCYWxhbmNlSXRlcmF0aW9uc1xuICAgICAgICB9XG4gICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCBhdXRvTGF5b3V0QmFsYW5jZUl0ZXJhdGlvbnM7IGkrKykge1xuICAgICAgICAgICAgXG4gICAgICAgICAgICBiYWxhbmNlRWxlbWVudHMoKVxuXG4gICAgICAgICAgICBsZXQgYmFsYW5jZWQgPSB0cnVlO1xuICAgICAgICAgICAgZm9yKGxldCBqID0gMDsgaiA8IGNvbHVtbkNvbnRlbnREaXZzLmxlbmd0aDsgaisrKSB7XG5cbiAgICAgICAgICAgICAgICAvLyBJZiB0aGUgY29sdW1uIGhlaWdodHMgYXJlIHVuZGVmaW5lZCB3ZSBzZXQgZGVmYXVsdCB0byB6ZXJvIHNvIG5vdCB0byBlbmNvdW50ZXIgYW4gZXJyb3IuXG4gICAgICAgICAgICAgICAgaWYoIXRoaXMucHJldmlvdXNDb2x1bW5IZWlnaHRzW2pdKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucHJldmlvdXNDb2x1bW5IZWlnaHRzLnB1c2goMClcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBpZiB0aGlzIHJlbmRlciBoZWlnaHQgaXMgbm90IHRoZSBzYW1lIGFzIHRoZSBwcmV2aW91cyBoZWlnaHQgd2UgYXJlIHN0aWxsIGJhbGFuY2luZy5cbiAgICAgICAgICAgICAgICBpZih0aGlzLnByZXZpb3VzQ29sdW1uSGVpZ2h0c1tqXSAhPT0gY29sdW1uQ29udGVudERpdnNbal0uY2xpZW50SGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucHJldmlvdXNDb2x1bW5IZWlnaHRzW2pdID0gY29sdW1uQ29udGVudERpdnNbal0uY2xpZW50SGVpZ2h0XG4gICAgICAgICAgICAgICAgICAgIGJhbGFuY2VkID0gZmFsc2VcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIGlmIHdlIG1hZGUgaXQgb3V0IG9mIHRoZSBsb29wIGFuZCBhbGwgb2YgdGhlIGNvbHVtbnMgYXJlIHRoZSBzYW1lIGhlaWdodCBhcyBsYXN0IHVwZGF0ZVxuICAgICAgICAgICAgLy8gd2UncmUgYmFsYW5jZWQgc28gd2UgY2FuIGJyZWFrIG91dCBvZiB0aGUgbG9vcC5cbiAgICAgICAgICAgIGlmKGJhbGFuY2VkID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgdXBkYXRlUmVuZGVyZWRNYXJrZG93bigpIHtcblxuICAgICAgICBpZih0aGlzLmRvY1JlZmxvdyA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgc3VwZXIudXBkYXRlUmVuZGVyZWRNYXJrZG93bigpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmRvbUxpc3QubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICAgICAgbGV0IGVsID0gdGhpcy5kb21MaXN0W2ldXG4gICAgICAgICAgICBsZXQgb3JpZ2luYWxDbGllbnRIZWlnaHQgPSAwO1xuICAgICAgICAgICAgaWYgKGVsLm9yaWdpbmFsRWxlbWVudCkge1xuICAgICAgICAgICAgICAgIG9yaWdpbmFsQ2xpZW50SGVpZ2h0ID0gZWwub3JpZ2luYWxFbGVtZW50LmNsaWVudEhlaWdodFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGNsb25lZENsaWVudEhlaWdodCA9IDA7XG4gICAgICAgICAgICBpZiAoZWwuY2xvbmVkRWxlbWVudCkge1xuICAgICAgICAgICAgICAgIGNsb25lZENsaWVudEhlaWdodCA9IGVsLmNsb25lZEVsZW1lbnQuY2xpZW50SGVpZ2h0XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChvcmlnaW5hbENsaWVudEhlaWdodCA8IGNsb25lZENsaWVudEhlaWdodCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZG9tTGlzdFtpXS5lbGVtZW50UmVuZGVyZWRIZWlnaHQgPSBjbG9uZWRDbGllbnRIZWlnaHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRvbUxpc3RbaV0uZWxlbWVudFJlbmRlcmVkSGVpZ2h0ID0gb3JpZ2luYWxDbGllbnRIZWlnaHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgdmFsaWRDb2x1bW5zID0gdHJ1ZTtcbiAgICAgICAgaWYodGhpcy5jb2x1bW5QYXJlbnQgIT09IG51bGwgJiYgdGhpcy5jb2x1bW5EaXZzICE9PSBudWxsICYmIHRoaXMuY29sdW1uRGl2cyAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAgICAgICB0aGlzLmNvbHVtbkRpdnMubGVuZ3RoID09PSB0aGlzLnJlZ2lvbmFsU2V0dGluZ3MubnVtYmVyT2ZDb2x1bW5zKSB7XG5cbiAgICAgICAgICAgIGxldCB0b3RhbEhlaWdodCA9IHRoaXMuZG9tTGlzdC5tYXAoKGVsOiBET01PYmplY3QsIGluZGV4OiBudW1iZXIpID0+IHsgXG5cbiAgICAgICAgICAgICAgICAvLyBXZSBvbmx5IHdhbnQgdG8gYXR0ZW1wdCB0byB1cGRhdGUgdGhlIGVsZW1lbnRSZW5kZXJlZEhlaWdodCBpZiBpdCBpcyAwIGFuZCBpZiBpdCBpcyBub3QgYW4gdW5yZW5kZXJlZCBlbGVtZW50IHN1Y2ggYXMgYSBlbmRyZWdpb24gdGFnLlxuICAgICAgICAgICAgICAgIGlmKGVsLmVsZW1lbnRSZW5kZXJlZEhlaWdodCA9PT0gMCAmJlxuICAgICAgICAgICAgICAgICAgICBlbC50YWcgIT09IERPTU9iamVjdFRhZy5jb2x1bW5CcmVhayAmJlxuICAgICAgICAgICAgICAgICAgICBlbC50YWcgIT09IERPTU9iamVjdFRhZy5lbmRSZWdpb24gJiZcbiAgICAgICAgICAgICAgICAgICAgZWwudGFnICE9PSBET01PYmplY3RUYWcucmVnaW9uU2V0dGluZ3MgJiZcbiAgICAgICAgICAgICAgICAgICAgZWwudGFnICE9PSBET01PYmplY3RUYWcuc3RhcnRSZWdpb24pIHtcbiAgICBcbiAgICAgICAgICAgICAgICAgICAgLy8gQWRkIGVsZW1lbnQgdG8gcmVuZGVyZWQgZGl2IHNvIHdlIGNhbiBleHRyYWN0IHRoZSByZW5kZXJlZCBoZWlnaHQuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29sdW1uUGFyZW50LmFwcGVuZENoaWxkKGVsLm9yaWdpbmFsRWxlbWVudClcbiAgICAgICAgICAgICAgICAgICAgZWwuZWxlbWVudFJlbmRlcmVkSGVpZ2h0ID0gZWwub3JpZ2luYWxFbGVtZW50LmNsaWVudEhlaWdodFxuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbHVtblBhcmVudC5yZW1vdmVDaGlsZChlbC5vcmlnaW5hbEVsZW1lbnQpXG4gICAgICAgICAgICAgICAgfVxuICAgIFxuICAgICAgICAgICAgICAgIHJldHVybiBlbC5lbGVtZW50UmVuZGVyZWRIZWlnaHQgXG4gICAgICAgICAgICB9KS5yZWR1Y2UoKHByZXY6IG51bWJlciwgY3VycjogbnVtYmVyKSA9PiB7IHJldHVybiBwcmV2ICsgY3VyciB9LCAwKTtcbiAgICAgICAgICAgIGxldCBtYXhDb2x1bW5Db250ZW50SGVpZ2h0ID0gTWF0aC50cnVuYyh0b3RhbEhlaWdodCAvIHRoaXMucmVnaW9uYWxTZXR0aW5ncy5udW1iZXJPZkNvbHVtbnMpO1xuXG4gICAgICAgICAgICBmb3IobGV0IGkgPSAwOyBpIDwgdGhpcy5jb2x1bW5EaXZzLmxlbmd0aCAtIDE7IGkrKykge1xuXG4gICAgICAgICAgICAgICAgbGV0IGNvbHVtbkhlaWdodCA9IDBcbiAgICAgICAgICAgICAgICBmb3IobGV0IGogPSAwOyBqIDwgdGhpcy5jb2x1bW5EaXZzW2ldLmNoaWxkcmVuLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbkhlaWdodCArPSB0aGlzLmNvbHVtbkRpdnNbaV0uY2hpbGRyZW5bal0uY2xpZW50SGVpZ2h0XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYoY29sdW1uSGVpZ2h0ID4gbWF4Q29sdW1uQ29udGVudEhlaWdodCkge1xuICAgICAgICAgICAgICAgICAgICB2YWxpZENvbHVtbnMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYodmFsaWRDb2x1bW5zID09PSBmYWxzZSkge1xuXG4gICAgICAgICAgICB0aGlzLnJlbmRlckNvbHVtbk1hcmtkb3duKHRoaXMucmVnaW9uUGFyZW50LCB0aGlzLmRvbUxpc3QsIHRoaXMucmVnaW9uYWxTZXR0aW5ncyk7XG4gICAgICAgIH1cblxuICAgICAgICBzdXBlci51cGRhdGVSZW5kZXJlZE1hcmtkb3duKCk7XG4gICAgfVxufVxuXG4iLCIvKipcbiAqIEZpbGU6IC9zcmMvZG9tX21hbmFnZXIvcmVnaW9uYWxfbWFuYWdlcnMvcmVmbG93UmVnaW9uTWFuYWdlci50cyAgICAgICAgICAgICAqXG4gKiBDcmVhdGVkIERhdGU6IFRodXJzZGF5LCBNYXkgMTF0aCAyMDIzLCA5OjU5IHBtICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICogQXV0aG9yOiBDYW1lcm9uIFJvYmluc29uICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjMgQ2FtZXJvbiBSb2JpbnNvbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICovXG5cbmltcG9ydCB7IERPTU9iamVjdCwgRE9NT2JqZWN0VGFnLCBUYXNrTGlzdERPTU9iamVjdCB9IGZyb20gJy4uL2RvbU9iamVjdCc7XG5pbXBvcnQgeyBBbGlnbm1lbnRUeXBlLCBDb250ZW50T3ZlcmZsb3dUeXBlLCBNdWx0aUNvbHVtblNldHRpbmdzLCBUYWJsZUFsaWdubWVudCwgY29sdW1uQWxpZ25tZW50U3RhdGUsIGNvbHVtbk92ZXJmbG93U3RhdGUsIHNob3VsZERyYXdDb2x1bW5Cb3JkZXIgfSBmcm9tIFwiLi4vLi4vcmVnaW9uU2V0dGluZ3NcIjtcbmltcG9ydCB7IE11bHRpQ29sdW1uTGF5b3V0Q1NTLCBNdWx0aUNvbHVtblN0eWxlQ1NTIH0gZnJvbSAnLi4vLi4vdXRpbGl0aWVzL2Nzc0RlZmluaXRpb25zJztcbmltcG9ydCB7IFJlZ2lvbk1hbmFnZXIgfSBmcm9tICcuL3JlZ2lvbk1hbmFnZXInO1xuaW1wb3J0IHsgZ2V0SGVhZGluZ0NvbGxhcHNlRWxlbWVudCwgaGFzSGVhZGVyIH0gZnJvbSAnc3JjL3V0aWxpdGllcy9lbGVtZW50UmVuZGVyVHlwZVBhcnNlcic7XG5pbXBvcnQgeyBNQ01fU2V0dGluZ3NNYW5hZ2VyIH0gZnJvbSAnc3JjL3BsdWdpblNldHRpbmdzJztcblxuZXhwb3J0IGNsYXNzIFJlZmxvd1JlZ2lvbk1hbmFnZXIgZXh0ZW5kcyBSZWdpb25NYW5hZ2VyIHtcblxuICAgIHB1YmxpYyByZW5kZXJSZWdpb25FbGVtZW50c1RvU2NyZWVuKCk6IHZvaWQge1xuXG4gICAgICAgICB0aGlzLnJlbmRlckNvbHVtbk1hcmtkb3duKHRoaXMucmVnaW9uUGFyZW50LCB0aGlzLmRvbUxpc3QsIHRoaXMucmVnaW9uYWxTZXR0aW5ncyk7XG4gICAgfVxuICAgIHB1YmxpYyBleHBvcnRSZWdpb25FbGVtZW50c1RvUERGKHBkZlBhcmVudEVsZW1lbnQ6IEhUTUxFbGVtZW50KTogdm9pZCB7XG5cbiAgICAgICAgLy8gRGVmYXVsdCBzZXQgc2hhZG93IHRvIG9mZiBmb3IgZXhwb3J0aW5nIFBERnNcbiAgICAgICAgbGV0IHJlbmRlclNldHRpbmdzID0gdGhpcy5yZWdpb25hbFNldHRpbmdzO1xuICAgICAgICByZW5kZXJTZXR0aW5ncy5kcmF3U2hhZG93ID0gZmFsc2U7XG4gICAgICAgIHRoaXMucmVuZGVyQ29sdW1uTWFya2Rvd24ocGRmUGFyZW50RWxlbWVudCwgdGhpcy5kb21MaXN0LnNsaWNlKCksIHJlbmRlclNldHRpbmdzKTtcbiAgICB9XG4gICAgcHVibGljIHJlbmRlclJlZ2lvbkVsZW1lbnRzVG9MaXZlUHJldmlldyhwYXJlbnRFbGVtZW50OiBIVE1MRWxlbWVudCk6IHZvaWQge1xuXG4gICAgICAgIHRoaXMucmVuZGVyQ29sdW1uTWFya2Rvd24ocGFyZW50RWxlbWVudCwgdGhpcy5kb21MaXN0LCB0aGlzLnJlZ2lvbmFsU2V0dGluZ3MpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBUaGlzIGZ1bmN0aW9uIHRha2VzIGluIHRoZSBkYXRhIGZvciB0aGUgbXVsdGktY29sdW1uIHJlZ2lvbiBhbmQgc2V0cyB1cCB0aGUgXG4gICAgICogdXNlciBkZWZpbmVkIG51bWJlciBvZiBjaGlsZHJlbiB3aXRoIHRoZSBwcm9wZXIgY3NzIGNsYXNzZXMgdG8gYmUgcmVuZGVyZWQgcHJvcGVybHkuXG4gICAgICogXG4gICAgICogQHBhcmFtIHBhcmVudEVsZW1lbnQgVGhlIGVsZW1lbnQgdGhhdCB0aGUgbXVsdGktY29sdW1uIHJlZ2lvbiB3aWxsIGJlIHJlbmRlcmVkIHVuZGVyLlxuICAgICAqIEBwYXJhbSByZWdpb25FbGVtZW50cyBUaGUgbGlzdCBvZiBET00gb2JqZWN0cyB0aGF0IHdpbGwgYmUgY29wcGllZCB1bmRlciB0aGUgcGFyZW50IG9iamVjdFxuICAgICAqIEBwYXJhbSBzZXR0aW5ncyBUaGUgc2V0dGluZ3MgdGhlIHVzZXIgaGFzIGRlZmluZWQgZm9yIHRoZSByZWdpb24uXG4gICAgICovXG4gICAgcHJpdmF0ZSByZW5kZXJDb2x1bW5NYXJrZG93bihwYXJlbnRFbGVtZW50OiBIVE1MRWxlbWVudCwgcmVnaW9uRWxlbWVudHM6IERPTU9iamVjdFtdLCBzZXR0aW5nczogTXVsdGlDb2x1bW5TZXR0aW5ncykge1xuXG4gICAgICAgIGxldCB2ZXJ0aWNhbENvbHVtblBhcmVudCA9IGNyZWF0ZURpdih7XG4gICAgICAgICAgICBjbHM6IGBgXG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBQYXNzIG91ciBwYXJlbnQgZGl2IGFuZCBzZXR0aW5ncyB0byBwYXJzZXIgdG8gY3JlYXRlIHRoZSByZXF1aXJlZFxuICAgICAgICAgKiBjb2x1bW4gZGl2cyBhcyBjaGlsZHJlbiBvZiB0aGUgcGFyZW50LlxuICAgICAgICAgKi9cblxuICAgICAgICAvLyBSZW1vdmUgZXZlcnkgb3RoZXIgY2hpbGQgZnJvbSB0aGUgcGFyZW50IHNvIFxuICAgICAgICAvLyB3ZSBkb250IGVuZCB1cCB3aXRoIG11bHRpcGxlIHNldHMgb2YgZGF0YS4gVGhpcyBzaG91bGRcbiAgICAgICAgLy8gcmVhbGx5IG9ubHkgbmVlZCB0byBsb29wIG9uY2UgZm9yIGkgPSAwIGJ1dCBsb29wIGp1c3RcbiAgICAgICAgLy8gaW4gY2FzZS5cbiAgICAgICAgZm9yIChsZXQgaSA9IHBhcmVudEVsZW1lbnQuY2hpbGRyZW4ubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICAgIHBhcmVudEVsZW1lbnQuY2hpbGRyZW5baV0uZGV0YWNoKCk7XG4gICAgICAgIH1cbiAgICAgICAgcGFyZW50RWxlbWVudC5hcHBlbmRDaGlsZCh2ZXJ0aWNhbENvbHVtblBhcmVudCk7XG5cbiAgICAgICAgdGhpcy5hcHBlbmRFbGVtZW50c1RvQ29sdW1ucyh2ZXJ0aWNhbENvbHVtblBhcmVudCwgcmVnaW9uRWxlbWVudHMsIHNldHRpbmdzKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFwcGVuZEVsZW1lbnRzVG9Db2x1bW5zKHZlcnRpY2FsQ29sdW1uUGFyZW50OiBIVE1MRGl2RWxlbWVudCwgcmVnaW9uRWxlbWVudHM6IERPTU9iamVjdFtdLCBzZXR0aW5nczogTXVsdGlDb2x1bW5TZXR0aW5ncykge1xuXG4gICAgICAgIHRoaXMuZG9tTGlzdC5mb3JFYWNoKChlbDogRE9NT2JqZWN0LCBpbmRleDogbnVtYmVyKSA9PiB7IFxuXG4gICAgICAgICAgICAvLyBXZSBvbmx5IHdhbnQgdG8gYXR0ZW1wdCB0byB1cGRhdGUgdGhlIGVsZW1lbnRSZW5kZXJlZEhlaWdodCBpZiBpdCBpcyAwIGFuZCBpZiBpdCBpcyBub3QgYW4gdW5yZW5kZXJlZCBlbGVtZW50IHN1Y2ggYXMgYSBlbmRyZWdpb24gdGFnLlxuICAgICAgICAgICAgaWYoZWwuZWxlbWVudFJlbmRlcmVkSGVpZ2h0ID09PSAwICYmXG4gICAgICAgICAgICAgICAgZWwudGFnICE9PSBET01PYmplY3RUYWcuY29sdW1uQnJlYWsgJiZcbiAgICAgICAgICAgICAgICBlbC50YWcgIT09IERPTU9iamVjdFRhZy5lbmRSZWdpb24gJiZcbiAgICAgICAgICAgICAgICBlbC50YWcgIT09IERPTU9iamVjdFRhZy5yZWdpb25TZXR0aW5ncyAmJlxuICAgICAgICAgICAgICAgIGVsLnRhZyAhPT0gRE9NT2JqZWN0VGFnLnN0YXJ0UmVnaW9uKSB7XG5cbiAgICAgICAgICAgICAgICAvLyBBZGQgZWxlbWVudCB0byByZW5kZXJlZCBkaXYgc28gd2UgY2FuIGV4dHJhY3QgdGhlIHJlbmRlcmVkIGhlaWdodC5cbiAgICAgICAgICAgICAgICB2ZXJ0aWNhbENvbHVtblBhcmVudC5hcHBlbmRDaGlsZChlbC5vcmlnaW5hbEVsZW1lbnQpXG4gICAgICAgICAgICAgICAgZWwuZWxlbWVudFJlbmRlcmVkSGVpZ2h0ID0gZWwub3JpZ2luYWxFbGVtZW50LmNsaWVudEhlaWdodFxuICAgICAgICAgICAgICAgIHZlcnRpY2FsQ29sdW1uUGFyZW50LnJlbW92ZUNoaWxkKGVsLm9yaWdpbmFsRWxlbWVudClcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSlcblxuICAgICAgICBsZXQgbWF4Q29sdW1uQ29udGVudEhlaWdodCA9IHNldHRpbmdzLmNvbHVtbkhlaWdodC5zaXplVmFsdWVcblxuICAgICAgICBsZXQgY29sdW1uSW5kZXggPSAwO1xuICAgICAgICBsZXQgY3VycmVudENvbHVtbkhlaWdodCA9IDA7XG4gICAgICAgIGxldCBkaXZDb3VudCA9IDE7XG4gICAgICAgIGxldCBjb2xEaXZzQ2FsbGJhY2sgPSAoc2V0dGluZ3M6IE11bHRpQ29sdW1uU2V0dGluZ3MsIG11bHRpQ29sdW1uUGFyZW50OiBIVE1MRGl2RWxlbWVudCkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0Q29sdW1uQ29udGVudERpdnMoc2V0dGluZ3MsIG11bHRpQ29sdW1uUGFyZW50KTtcbiAgICAgICAgfTtcbiAgICAgICAgbGV0IGNvbHVtbnMgPSBnZXRGb3JtYXR0ZWRDb2x1bW5EaXZzKHNldHRpbmdzLCB2ZXJ0aWNhbENvbHVtblBhcmVudCwgY29sRGl2c0NhbGxiYWNrLCBkaXZDb3VudCk7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcmVnaW9uRWxlbWVudHMubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICAgICAgaWYgKHJlZ2lvbkVsZW1lbnRzW2ldLnRhZyA9PT0gRE9NT2JqZWN0VGFnLm5vbmUgfHxcbiAgICAgICAgICAgICAgICByZWdpb25FbGVtZW50c1tpXS50YWcgPT09IERPTU9iamVjdFRhZy5jb2x1bW5CcmVhaykge1xuXG4gICAgICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgICAgICogSGVyZSB3ZSBjaGVjayBpZiB3ZSBuZWVkIHRvIHN3YXAgdG8gdGhlIG5leHQgY29sdW1uIGZvciB0aGUgY3VycmVudCBlbGVtZW50LlxuICAgICAgICAgICAgICAgICAqIElmIHRoZSB1c2VyIHdhbnRzIHRvIGtlZXAgaGVhZGluZ3Mgd2l0aCB0aGUgY29udGVudCBiZWxvdyBpdCB3ZSBhbHNvIG1ha2Ugc3VyZVxuICAgICAgICAgICAgICAgICAqIHRoYXQgdGhlIGxhc3QgaXRlbSBpbiBhIGNvbHVtbiBpcyBub3QgYSBoZWFkZXIgZWxlbWVudCBieSB1c2luZyB0aGUgaGVhZGVyIGFuZFxuICAgICAgICAgICAgICAgICAqIHRoZSBuZXh0IGVsZW1lbnQncyBoZWlnaHQgYXMgdGhlIGhlaWdodCB2YWx1ZS4gXG4gICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgaWYoaGFzSGVhZGVyKHJlZ2lvbkVsZW1lbnRzW2ldLm9yaWdpbmFsRWxlbWVudCkgPT09IHRydWUpIHsgLy8gVE9ETzogQWRkIHRoaXMgYXMgc2VsZWN0YWJsZSBvcHRpb24uXG5cbiAgICAgICAgICAgICAgICAgICAgbGV0IGhlYWRlckFuZE5leHRFbGVtZW50SGVpZ2h0ID0gcmVnaW9uRWxlbWVudHNbaV0uZWxlbWVudFJlbmRlcmVkSGVpZ2h0O1xuICAgICAgICAgICAgICAgICAgICBpZihpIDwgcmVnaW9uRWxlbWVudHMubGVuZ3RoIC0gMSkge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBoZWFkZXJBbmROZXh0RWxlbWVudEhlaWdodCArPSByZWdpb25FbGVtZW50c1tpICsgMV0uZWxlbWVudFJlbmRlcmVkSGVpZ2h0O1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgY2hlY2tTaG91bGRTd2l0Y2hDb2x1bW5zKGhlYWRlckFuZE5leHRFbGVtZW50SGVpZ2h0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG5cbiAgICAgICAgICAgICAgICAgICAgY2hlY2tTaG91bGRTd2l0Y2hDb2x1bW5zKHJlZ2lvbkVsZW1lbnRzW2ldLmVsZW1lbnRSZW5kZXJlZEhlaWdodCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGN1cnJlbnRDb2x1bW5IZWlnaHQgKz0gcmVnaW9uRWxlbWVudHNbaV0uZWxlbWVudFJlbmRlcmVkSGVpZ2h0XG5cbiAgICAgICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAgICAgKiBXZSBzdG9yZSB0aGUgZWxlbWVudHMgaW4gYSB3cmFwcGVyIGNvbnRhaW5lciB1bnRpbCB3ZSBkZXRlcm1pbmUgaWYgd2Ugd2FudCB0byBcbiAgICAgICAgICAgICAgICAgKiB1c2UgdGhlIG9yaWdpbmFsIGVsZW1lbnQgb3IgYSBjbG9uZSBvZiB0aGUgZWxlbWVudC4gVGhpcyBoZWxwcyB1cyBieSBhbGxvd2luZyBcbiAgICAgICAgICAgICAgICAgKiB1cyB0byBjcmVhdGUgYSB2aXN1YWwgb25seSBjbG9uZSB3aGlsZSB0aGUgdXBkYXRlIGxvb3AgbW92ZXMgdGhlIG9yaWdpbmFsIGVsZW1lbnQgXG4gICAgICAgICAgICAgICAgICogaW50byB0aGUgY29sdW1ucy5cbiAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICBsZXQgZWxlbWVudCA9IGNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgIGNsczogTXVsdGlDb2x1bW5MYXlvdXRDU1MuQ29sdW1uRHVhbEVsZW1lbnRDb250YWluZXIsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgcmVnaW9uRWxlbWVudHNbaV0uZWxlbWVudENvbnRhaW5lciA9IGVsZW1lbnQ7XG5cbiAgICAgICAgICAgICAgICBpZihjb2x1bW5PdmVyZmxvd1N0YXRlKGNvbHVtbkluZGV4LCBzZXR0aW5ncykgPT09IENvbnRlbnRPdmVyZmxvd1R5cGUuaGlkZGVuKSB7XG4gICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuYWRkQ2xhc3MoTXVsdGlDb2x1bW5MYXlvdXRDU1MuQ29udGVudE92ZXJmbG93SGlkZGVuX1gpXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmFkZENsYXNzKE11bHRpQ29sdW1uTGF5b3V0Q1NTLkNvbnRlbnRPdmVyZmxvd0F1dG9TY3JvbGxfWClcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgbGV0IGFsaWdubWVudCA9IGNvbHVtbkFsaWdubWVudFN0YXRlKGNvbHVtbkluZGV4LCBzZXR0aW5ncyk7XG4gICAgICAgICAgICAgICAgaWYoYWxpZ25tZW50ID09PSBBbGlnbm1lbnRUeXBlLmNlbnRlcikge1xuICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmFkZENsYXNzKE11bHRpQ29sdW1uTGF5b3V0Q1NTLkFsaWdubWVudENlbnRlcilcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoYWxpZ25tZW50ID09PSBBbGlnbm1lbnRUeXBlLnJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuYWRkQ2xhc3MoTXVsdGlDb2x1bW5MYXlvdXRDU1MuQWxpZ25tZW50UmlnaHQpXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmFkZENsYXNzKE11bHRpQ29sdW1uTGF5b3V0Q1NTLkFsaWdubWVudExlZnQpXG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgbGV0IHRhYmxlQWxpZ25tZW50ID0gTUNNX1NldHRpbmdzTWFuYWdlci5zaGFyZWQuYWxpZ25UYWJsZXNUb0NvbnRlbnRBbGlnbm1lbnQ7XG4gICAgICAgICAgICAgICAgaWYoc2V0dGluZ3MuYWxpZ25UYWJsZXNUb0FsaWdubWVudCAhPT0gVGFibGVBbGlnbm1lbnQudXNlU2V0dGluZ3NEZWZhdWx0KSB7XG4gICAgICAgICAgICAgICAgICAgIHRhYmxlQWxpZ25tZW50ID0gc2V0dGluZ3MuYWxpZ25UYWJsZXNUb0FsaWdubWVudCA9PT0gVGFibGVBbGlnbm1lbnQuYWxpZ25cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYodGFibGVBbGlnbm1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5hZGRDbGFzcyhNdWx0aUNvbHVtbkxheW91dENTUy5UYWJsZUFsaWdubWVudClcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBsZXQgY2xvbmVkRWxlbWVudCA9IHJlZ2lvbkVsZW1lbnRzW2ldLmNsb25lZEVsZW1lbnQ7XG4gICAgICAgICAgICAgICAgaWYocmVnaW9uRWxlbWVudHNbaV0uY2xvbmVkRWxlbWVudCA9PT0gbnVsbCkge1xuXG4gICAgICAgICAgICAgICAgICAgIGNsb25lZEVsZW1lbnQgPSByZWdpb25FbGVtZW50c1tpXS5vcmlnaW5hbEVsZW1lbnQuY2xvbmVOb2RlKHRydWUpIGFzIEhUTUxEaXZFbGVtZW50O1xuICAgICAgICAgICAgICAgICAgICBsZXQgaGVhZGluZ0NvbGxhcHNlRWxlbWVudCA9IGdldEhlYWRpbmdDb2xsYXBzZUVsZW1lbnQoY2xvbmVkRWxlbWVudCk7XG4gICAgICAgICAgICAgICAgICAgIGlmKGhlYWRpbmdDb2xsYXBzZUVsZW1lbnQgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgcmVtb3ZlcyB0aGUgY29sbGFwc2UgYXJyb3cgZnJvbSB0aGUgdmlldyBpZiBpdCBleGlzdHMuXG4gICAgICAgICAgICAgICAgICAgICAgICBoZWFkaW5nQ29sbGFwc2VFbGVtZW50LmRldGFjaCgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgXG4gICAgICAgICAgICAgICAgICAgIHJlZ2lvbkVsZW1lbnRzW2ldLmNsb25lZEVsZW1lbnQgPSBjbG9uZWRFbGVtZW50O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbGVtZW50LmFwcGVuZENoaWxkKGNsb25lZEVsZW1lbnQpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHJlZ2lvbkVsZW1lbnRzW2ldIGluc3RhbmNlb2YgVGFza0xpc3RET01PYmplY3QpIHtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLmZpeENsb25lZENoZWNrTGlzdEJ1dHRvbnMocmVnaW9uRWxlbWVudHNbaV0gYXMgVGFza0xpc3RET01PYmplY3QsIHRydWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChlbGVtZW50ICE9PSBudWxsICYmIFxuICAgICAgICAgICAgICAgICAgICBjb2x1bW5zW2NvbHVtbkluZGV4XSAmJiBcbiAgICAgICAgICAgICAgICAgICAgcmVnaW9uRWxlbWVudHNbaV0udGFnICE9PSBET01PYmplY3RUYWcuY29sdW1uQnJlYWspIHtcblxuICAgICAgICAgICAgICAgICAgICBjb2x1bW5zW2NvbHVtbkluZGV4XS5hcHBlbmRDaGlsZChlbGVtZW50KTtcbiAgICAgICAgICAgICAgICAgICAgcmVnaW9uRWxlbWVudHNbaV0uZWxlbWVudFJlbmRlcmVkSGVpZ2h0ID0gZWxlbWVudC5jbGllbnRIZWlnaHQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgICAgICogSWYgdGhlIHRhZyBpcyBhIGNvbHVtbiBicmVhayB3ZSB1cGRhdGUgdGhlIGNvbHVtbiBpbmRleCBhZnRlclxuICAgICAgICAgICAgICAgICAqIGFwcGVuZGluZyB0aGUgaXRlbSB0byB0aGUgY29sdW1uIGRpdi4gVGhpcyBrZWVwcyB0aGUgbWFpbiBET01cbiAgICAgICAgICAgICAgICAgKiBjbGVhbmVyIGJ5IHJlbW92aW5nIG90aGVyIGl0ZW1zIGFuZCBwbGFjaW5nIHRoZW0gYWxsIHdpdGhpblxuICAgICAgICAgICAgICAgICAqIGEgcmVnaW9uIGNvbnRhaW5lci5cbiAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICBpZiAocmVnaW9uRWxlbWVudHNbaV0udGFnID09PSBET01PYmplY3RUYWcuY29sdW1uQnJlYWspIHtcblxuICAgICAgICAgICAgICAgICAgICBjaGVja0NyZWF0ZU5ld0NvbHVtbnMoKTtcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uSW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudENvbHVtbkhlaWdodCA9IDA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gY2hlY2tTaG91bGRTd2l0Y2hDb2x1bW5zKG5leHRFbGVtZW50SGVpZ2h0OiBudW1iZXIpIHtcblxuICAgICAgICAgICAgaWYgKGN1cnJlbnRDb2x1bW5IZWlnaHQgKyBuZXh0RWxlbWVudEhlaWdodCA8IG1heENvbHVtbkNvbnRlbnRIZWlnaHQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNoZWNrQ3JlYXRlTmV3Q29sdW1ucygpO1xuICAgICAgICAgICAgY29sdW1uSW5kZXgrKztcbiAgICAgICAgICAgIGN1cnJlbnRDb2x1bW5IZWlnaHQgPSAwO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gY2hlY2tDcmVhdGVOZXdDb2x1bW5zKCkge1xuICAgICAgICAgICAgaWYgKChjb2x1bW5JbmRleCArIDEpID49IGNvbHVtbnMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgZGl2Q291bnQrKztcbiAgICAgICAgICAgICAgICBjb2x1bW5zID0gY29sdW1ucy5jb25jYXQoZ2V0Rm9ybWF0dGVkQ29sdW1uRGl2cyhzZXR0aW5ncywgdmVydGljYWxDb2x1bW5QYXJlbnQsIGNvbERpdnNDYWxsYmFjaywgZGl2Q291bnQpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn1cblxuZnVuY3Rpb24gZ2V0Rm9ybWF0dGVkQ29sdW1uRGl2cyhcbiAgICBzZXR0aW5nczogTXVsdGlDb2x1bW5TZXR0aW5ncywgXG4gICAgdmVydGljYWxDb2x1bW5QYXJlbnQ6IEhUTUxEaXZFbGVtZW50LCBcbiAgICBnZXRDb2x1bW5Db250ZW50RGl2czogKHNldHRpbmdzOiBNdWx0aUNvbHVtblNldHRpbmdzLCBtdWx0aUNvbHVtblBhcmVudDogSFRNTERpdkVsZW1lbnQpID0+IEhUTUxEaXZFbGVtZW50W10sXG4gICAgZGl2Q291bnQ6IG51bWJlcikge1xuICAgICAgICBcbiAgICBsZXQgbXVsdGlDb2x1bW5QYXJlbnQgPSB2ZXJ0aWNhbENvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xuICAgICAgICBjbHM6IGAke011bHRpQ29sdW1uTGF5b3V0Q1NTLlJlZ2lvbkNvbHVtbkNvbnRhaW5lckRpdn0gXFxcbiAgICAgICAgICAgICAgJHtNdWx0aUNvbHVtbkxheW91dENTUy5Db250ZW50T3ZlcmZsb3dBdXRvU2Nyb2xsX1h9IFxcXG4gICAgICAgICAgICAgICR7TXVsdGlDb2x1bW5MYXlvdXRDU1MuQ29udGVudE92ZXJmbG93SGlkZGVuX1l9O1xuICAgICAgICAgICAgICBgXG4gICAgfSk7XG4gICAgaWYoZGl2Q291bnQgPiAxKSB7XG4gICAgICAgIG11bHRpQ29sdW1uUGFyZW50LmFkZENsYXNzKGAke011bHRpQ29sdW1uTGF5b3V0Q1NTLlJlZmxvd0NvbnRhaW5lckRpdn1gKTtcbiAgICB9XG5cbiAgICBsZXQgY29sdW1uRGl2cyA9IGdldENvbHVtbkNvbnRlbnREaXZzKHNldHRpbmdzLCBtdWx0aUNvbHVtblBhcmVudCk7XG4gICAgaWYgKHNldHRpbmdzLmRyYXdTaGFkb3cgPT09IHRydWUpIHtcbiAgICAgICAgbXVsdGlDb2x1bW5QYXJlbnQuYWRkQ2xhc3MoTXVsdGlDb2x1bW5TdHlsZUNTUy5SZWdpb25TaGFkb3cpO1xuICAgIH1cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNvbHVtbkRpdnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYgKHNob3VsZERyYXdDb2x1bW5Cb3JkZXIoaSwgc2V0dGluZ3MpID09PSB0cnVlKSB7XG4gICAgICAgICAgICBjb2x1bW5EaXZzW2ldLmFkZENsYXNzKE11bHRpQ29sdW1uU3R5bGVDU1MuQ29sdW1uQm9yZGVyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzZXR0aW5ncy5kcmF3U2hhZG93ID09PSB0cnVlKSB7XG4gICAgICAgICAgICBjb2x1bW5EaXZzW2ldLmFkZENsYXNzKE11bHRpQ29sdW1uU3R5bGVDU1MuQ29sdW1uU2hhZG93KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2x1bW5EaXZzXG59IiwiLyoqXG4gKiBGaWxlOiAvc3JjL2RvbV9tYW5hZ2VyL3JlZ2lvbmFsX21hbmFnZXJzL3JlZ2lvbk1hbmFnZXJDb250YWluZXIudHMgICAgICAgICAgKlxuICogQ3JlYXRlZCBEYXRlOiBTdW5kYXksIE1heSAyMm5kIDIwMjIsIDc6NTAgcG0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAqIEF1dGhvcjogQ2FtZXJvbiBSb2JpbnNvbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICogQ29weXJpZ2h0IChjKSAyMDIyIENhbWVyb24gUm9iaW5zb24gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAqL1xuXG5pbXBvcnQgeyBwYXJzZUNvbHVtblNldHRpbmdzLCBwYXJzZVNpbmdsZUNvbHVtblNldHRpbmdzIH0gZnJvbSBcIi4uLy4uL3V0aWxpdGllcy9zZXR0aW5nc1BhcnNlclwiO1xuaW1wb3J0IHsgRE9NT2JqZWN0IH0gZnJvbSAnLi4vZG9tT2JqZWN0JztcbmltcG9ydCB7IE11bHRpQ29sdW1uU2V0dGluZ3MsIGdldERlZmF1bHRNdWx0aUNvbHVtblNldHRpbmdzIH0gZnJvbSBcIi4uLy4uL3JlZ2lvblNldHRpbmdzXCI7XG5pbXBvcnQgeyBGaWxlRE9NTWFuYWdlciB9IGZyb20gJy4uL2RvbU1hbmFnZXInO1xuaW1wb3J0IHsgU3RhbmRhcmRNdWx0aUNvbHVtblJlZ2lvbk1hbmFnZXIgYXMgU3RhbmRhcmRNdWx0aUNvbHVtblJlZ2lvbk1hbmFnZXIgfSBmcm9tICcuL3N0YW5kYXJkTXVsdGlDb2x1bW5SZWdpb25NYW5hZ2VyJztcbmltcG9ydCB7IFNpbmdsZUNvbHVtblJlZ2lvbk1hbmFnZXIgfSBmcm9tIFwiLi9zaW5nbGVDb2x1bW5SZWdpb25NYW5hZ2VyXCI7XG5pbXBvcnQgeyBSZWdpb25NYW5hZ2VyIH0gZnJvbSBcIi4vcmVnaW9uTWFuYWdlclwiO1xuaW1wb3J0IHsgQXV0b0xheW91dFJlZ2lvbk1hbmFnZXIgfSBmcm9tICcuL2F1dG9MYXlvdXRSZWdpb25NYW5hZ2VyJztcbmltcG9ydCB7IFJlZmxvd1JlZ2lvbk1hbmFnZXIgfSBmcm9tIFwiLi9yZWZsb3dSZWdpb25NYW5hZ2VyXCI7XG5pbXBvcnQgeyBNQ01fU2V0dGluZ3MsIERFRkFVTFRfU0VUVElOR1MgfSBmcm9tICcuLi8uLi9wbHVnaW5TZXR0aW5ncyc7XG5pbXBvcnQgeyBSZWdpb25FcnJvck1hbmFnZXIgfSBmcm9tIFwiLi4vcmVnaW9uRXJyb3JNYW5hZ2VyXCI7XG5cbi8qKlxuICogVGhpcyBjbGFzcyBhY3RzIGFzIGFuIGFic3RyYWN0aW9uIGZvciB0aGUgYWN0dWFsIHJlZ2lvbmFsIG1hbmFnZXIuIEl0IGlzIHVzZWQgdG8gdXBkYXRlIHRoZVxuICogc3ViY2xhc3Mgb2YgUmVnaW9uYWxNYW5hZ2VyIGRlcGVuZGluZyBvbiB1c2VyIHByZWZlcmVuY2VzIHRvIG1ha2UgcmVuZGVyaW5nIG1vcmUgc2ltcGxpZmllZC5cbiAqL1xuZXhwb3J0IGNsYXNzIFJlZ2lvbk1hbmFnZXJDb250YWluZXIge1xuXG4gICAgcHJvdGVjdGVkIHJlZ2lvbjogUmVnaW9uTWFuYWdlcjtcblxuICAgIGNvbnN0cnVjdG9yKHBhcmVudEZpbGVNYW5hZ2VyOiBGaWxlRE9NTWFuYWdlciwgcmVnaW9uS2V5OiBzdHJpbmcsIHJvb3RFbGVtZW50OiBIVE1MRWxlbWVudCwgcmVnaW9uUGFyZW50OiBIVE1MRWxlbWVudCwgZXJyb3JNYW5hZ2VyOiBSZWdpb25FcnJvck1hbmFnZXIpIHtcbiAgICAgICAgdGhpcy5yZWdpb24gPSBuZXcgU3RhbmRhcmRNdWx0aUNvbHVtblJlZ2lvbk1hbmFnZXIoY3JlYXRlRGVmYXVsdFJlZ2lvbk1hbmFnZXJEYXRhKHJlZ2lvblBhcmVudCwgcGFyZW50RmlsZU1hbmFnZXIsIHJlZ2lvbktleSwgcm9vdEVsZW1lbnQsIGVycm9yTWFuYWdlcikpO1xuICAgIH1cbiAgICBcbiAgICBwdWJsaWMgZ2V0UmVnaW9uKCk6IFJlZ2lvbk1hbmFnZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5yZWdpb247XG4gICAgfVxuXG4gICAgcHVibGljIHNldFJlZ2lvblNldHRpbmdzKHNldHRpbmdzVGV4dDogc3RyaW5nKTogUmVnaW9uTWFuYWdlciB7XG5cbiAgICAgICAgbGV0IHJlZ2lvbmFsU2V0dGluZ3MgPSBwYXJzZUNvbHVtblNldHRpbmdzKHNldHRpbmdzVGV4dCk7XG4gICAgICAgIGlmIChyZWdpb25hbFNldHRpbmdzLm51bWJlck9mQ29sdW1ucyA9PT0gMSkge1xuXG4gICAgICAgICAgICByZWdpb25hbFNldHRpbmdzID0gcGFyc2VTaW5nbGVDb2x1bW5TZXR0aW5ncyhzZXR0aW5nc1RleHQsIHJlZ2lvbmFsU2V0dGluZ3MpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLnNldFJlZ2lvblBhcnNlZFNldHRpbmdzKHJlZ2lvbmFsU2V0dGluZ3MpO1xuICAgIH1cblxuICAgIHB1YmxpYyBzZXRSZWdpb25QYXJzZWRTZXR0aW5ncyhyZWdpb25hbFNldHRpbmdzOiBNdWx0aUNvbHVtblNldHRpbmdzKTogUmVnaW9uTWFuYWdlciB7XG5cbiAgICAgICAgdGhpcy5yZWdpb24uc2V0UmVnaW9uYWxTZXR0aW5ncyhyZWdpb25hbFNldHRpbmdzKTtcblxuICAgICAgICBpZiAocmVnaW9uYWxTZXR0aW5ncy5udW1iZXJPZkNvbHVtbnMgPT09IDEpIHtcblxuICAgICAgICAgICAgaWYodGhpcy5yZWdpb24gaW5zdGFuY2VvZiBTaW5nbGVDb2x1bW5SZWdpb25NYW5hZ2VyID09PSBmYWxzZSkge1xuXG4gICAgICAgICAgICAgICAgLy8gY29uc29sZS5kZWJ1ZyhcIkNvbnZlcnRpbmcgcmVnaW9uIHRvIHNpbmdsZSBjb2x1bW4uXCIpXG4gICAgICAgICAgICAgICAgdGhpcy5jb252ZXJ0VG9TaW5nbGVDb2x1bW4oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmKHJlZ2lvbmFsU2V0dGluZ3MuYXV0b0xheW91dCA9PT0gdHJ1ZSkge1xuXG4gICAgICAgICAgICBpZih0aGlzLnJlZ2lvbiBpbnN0YW5jZW9mIEF1dG9MYXlvdXRSZWdpb25NYW5hZ2VyID09PSBmYWxzZSkge1xuXG4gICAgICAgICAgICAgICAgLy8gY29uc29sZS5kZWJ1ZyhcIkNvbnZlcnRpbmcgcmVnaW9uIHRvIGF1dG8gbGF5b3V0LlwiKVxuICAgICAgICAgICAgICAgIHRoaXMuY29udmVydFRvQXV0b0xheW91dCgpXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZihyZWdpb25hbFNldHRpbmdzLmZ1bGxEb2NSZWZsb3cgPT09IHRydWUpIHtcbiAgICAgICAgICAgIGlmKHRoaXMucmVnaW9uIGluc3RhbmNlb2YgUmVmbG93UmVnaW9uTWFuYWdlciA9PT0gZmFsc2UpIHtcblxuICAgICAgICAgICAgICAgIC8vIGNvbnNvbGUuZGVidWcoXCJDb252ZXJ0aW5nIHJlZ2lvbiB0byBhdXRvIGxheW91dC5cIilcbiAgICAgICAgICAgICAgICB0aGlzLmNvbnZlcnRUb0RvY1JlZmxvdygpXG4gICAgICAgICAgICB9IFxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHJlZ2lvbmFsU2V0dGluZ3MubnVtYmVyT2ZDb2x1bW5zID49IDIpIHtcblxuICAgICAgICAgICAgaWYodGhpcy5yZWdpb24gaW5zdGFuY2VvZiBTdGFuZGFyZE11bHRpQ29sdW1uUmVnaW9uTWFuYWdlciA9PT0gZmFsc2UpIHtcblxuICAgICAgICAgICAgICAgIC8vIGNvbnNvbGUuZGVidWcoXCJDb252ZXJ0aW5nIHJlZ2lvbiB0byBzdGFuZGFyZCBtdWx0aS1jb2x1bW5cIilcbiAgICAgICAgICAgICAgICB0aGlzLmNvbnZlcnRUb1N0YW5kYXJkTXVsdGlDb2x1bW4oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzLnJlZ2lvbjtcbiAgICB9XG5cbiAgICBwcml2YXRlIGNvbnZlcnRUb1NpbmdsZUNvbHVtbigpOiBTaW5nbGVDb2x1bW5SZWdpb25NYW5hZ2VyIHtcblxuICAgICAgICBsZXQgZGF0YSA9IHRoaXMucmVnaW9uLmdldFJlZ2lvbkRhdGEoKTtcbiAgICAgICAgdGhpcy5yZWdpb24gPSBuZXcgU2luZ2xlQ29sdW1uUmVnaW9uTWFuYWdlcihkYXRhKTtcblxuICAgICAgICByZXR1cm4gdGhpcy5yZWdpb24gYXMgU2luZ2xlQ29sdW1uUmVnaW9uTWFuYWdlcjtcbiAgICB9XG5cbiAgICBwcml2YXRlIGNvbnZlcnRUb1N0YW5kYXJkTXVsdGlDb2x1bW4oKTogU3RhbmRhcmRNdWx0aUNvbHVtblJlZ2lvbk1hbmFnZXIge1xuXG4gICAgICAgIGxldCBkYXRhID0gdGhpcy5yZWdpb24uZ2V0UmVnaW9uRGF0YSgpO1xuICAgICAgICB0aGlzLnJlZ2lvbiA9IG5ldyBTdGFuZGFyZE11bHRpQ29sdW1uUmVnaW9uTWFuYWdlcihkYXRhKTtcblxuICAgICAgICByZXR1cm4gdGhpcy5yZWdpb24gYXMgU3RhbmRhcmRNdWx0aUNvbHVtblJlZ2lvbk1hbmFnZXI7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjb252ZXJ0VG9BdXRvTGF5b3V0KCk6IEF1dG9MYXlvdXRSZWdpb25NYW5hZ2VyIHtcblxuICAgICAgICBsZXQgZGF0YSA9IHRoaXMucmVnaW9uLmdldFJlZ2lvbkRhdGEoKTtcbiAgICAgICAgdGhpcy5yZWdpb24gPSBuZXcgQXV0b0xheW91dFJlZ2lvbk1hbmFnZXIoZGF0YSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMucmVnaW9uIGFzIEF1dG9MYXlvdXRSZWdpb25NYW5hZ2VyO1xuICAgIH1cblxuICAgIHByaXZhdGUgY29udmVydFRvRG9jUmVmbG93KCk6IFJlZmxvd1JlZ2lvbk1hbmFnZXIge1xuXG4gICAgICAgIGxldCBkYXRhID0gdGhpcy5yZWdpb24uZ2V0UmVnaW9uRGF0YSgpO1xuICAgICAgICB0aGlzLnJlZ2lvbiA9IG5ldyBSZWZsb3dSZWdpb25NYW5hZ2VyKGRhdGEpO1xuXG4gICAgICAgIHJldHVybiB0aGlzLnJlZ2lvbiBhcyBSZWZsb3dSZWdpb25NYW5hZ2VyO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gY3JlYXRlRGVmYXVsdFJlZ2lvbk1hbmFnZXJEYXRhKHJlZ2lvblBhcmVudDogSFRNTEVsZW1lbnQsIGZpbGVNYW5hZ2VyOiBGaWxlRE9NTWFuYWdlciwgcmVnaW9uS2V5OiBzdHJpbmcsIHJvb3RFbGVtZW50OiBIVE1MRWxlbWVudCwgZXJyb3JNYW5hZ2VyOiBSZWdpb25FcnJvck1hbmFnZXIpOiBSZWdpb25NYW5hZ2VyRGF0YSB7XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBkb21MaXN0OiBbXSxcbiAgICAgICAgZG9tT2JqZWN0TWFwOiBuZXcgTWFwKCksXG4gICAgICAgIHJlZ2lvblBhcmVudDogcmVnaW9uUGFyZW50LFxuICAgICAgICBmaWxlTWFuYWdlcjogZmlsZU1hbmFnZXIsXG4gICAgICAgIHJlZ2lvbmFsU2V0dGluZ3M6IGdldERlZmF1bHRNdWx0aUNvbHVtblNldHRpbmdzKCksXG4gICAgICAgIHJlZ2lvbktleTogcmVnaW9uS2V5LFxuICAgICAgICByb290RWxlbWVudDogcm9vdEVsZW1lbnQsXG4gICAgICAgIGVycm9yTWFuYWdlcjogZXJyb3JNYW5hZ2VyXG4gICAgfTtcbn1cblxuZXhwb3J0IHR5cGUgUmVnaW9uTWFuYWdlckRhdGEgPSB7XG4gICAgZG9tTGlzdDogRE9NT2JqZWN0W107XG4gICAgZG9tT2JqZWN0TWFwOiBNYXA8c3RyaW5nLCBET01PYmplY3Q+O1xuICAgIHJlZ2lvblBhcmVudDogSFRNTEVsZW1lbnQ7XG5cbiAgICBmaWxlTWFuYWdlcjogRmlsZURPTU1hbmFnZXI7XG4gICAgcmVnaW9uYWxTZXR0aW5nczogTXVsdGlDb2x1bW5TZXR0aW5ncztcblxuICAgIHJlZ2lvbktleTogc3RyaW5nO1xuICAgIHJvb3RFbGVtZW50OiBIVE1MRWxlbWVudDtcbiAgICBlcnJvck1hbmFnZXI6IFJlZ2lvbkVycm9yTWFuYWdlcjtcbn07XG4iLCIvKlxuICogRmlsZTogbXVsdGktY29sdW1uLW1hcmtkb3duL3NyYy9kb21NYW5hZ2VyLnRzXG4gKiBDcmVhdGVkIERhdGU6IFNhdHVyZGF5LCBKYW51YXJ5IDMwdGggMjAyMiwgMzoxNjozMiBwbVxuICogQXV0aG9yOiBDYW1lcm9uIFJvYmluc29uXG4gKiBcbiAqIENvcHlyaWdodCAoYykgMjAyMiBDYW1lcm9uIFJvYmluc29uXG4gKi9cblxuaW1wb3J0IHsgUmVnaW9uTWFuYWdlciB9IGZyb20gXCIuL3JlZ2lvbmFsX21hbmFnZXJzL3JlZ2lvbk1hbmFnZXJcIjtcbmltcG9ydCB7IFJlZ2lvbk1hbmFnZXJDb250YWluZXIgfSBmcm9tIFwiLi9yZWdpb25hbF9tYW5hZ2Vycy9yZWdpb25NYW5hZ2VyQ29udGFpbmVyXCI7XG5pbXBvcnQgeyBSZWdpb25FcnJvck1hbmFnZXIgfSBmcm9tIFwiLi9yZWdpb25FcnJvck1hbmFnZXJcIjtcblxuLyoqXG4gKiBUaGlzIGNsYXNzIGhhbmRsZXMgdGhlIGdsb2JhbCBtYW5hZ2VycyBrZWVwaW5nIHRyYWNrIG9mIGFsbCBvcGVuIGZpbGVzIHRoYXRcbiAqIGNvbnRhaW4gTUNNLVJlZ2lvbnMuXG4gKi9cbmV4cG9ydCBjbGFzcyBHbG9iYWxET01NYW5hZ2VyIHtcbiAgICBtYW5hZ2VyczogTWFwPHN0cmluZywgRmlsZURPTU1hbmFnZXI+O1xuXG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMubWFuYWdlcnMgPSBuZXcgTWFwKCk7XG4gICAgfVxuXG4gICAgcHVibGljIHJlbW92ZUZpbGVNYW5hZ2VyQ2FsbGJhY2soa2V5OiBzdHJpbmcpIHtcbiAgICAgICAgaWYodGhpcy5tYW5hZ2Vycy5oYXMoa2V5KSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgdGhpcy5tYW5hZ2Vycy5kZWxldGUoa2V5KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBnZXRGaWxlTWFuYWdlcihrZXk6IHN0cmluZykge1xuXG4gICAgICAgIGxldCBmaWxlTWFuYWdlciA9IG51bGw7XG4gICAgICAgIGlmKHRoaXMubWFuYWdlcnMuaGFzKGtleSkgPT09IHRydWUpIHtcbiAgICAgICAgICAgIGZpbGVNYW5hZ2VyID0gdGhpcy5tYW5hZ2Vycy5nZXQoa2V5KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGZpbGVNYW5hZ2VyID0gbmV3IEZpbGVET01NYW5hZ2VyKHRoaXMsIGtleSk7XG4gICAgICAgICAgICB0aGlzLm1hbmFnZXJzLnNldChrZXksIGZpbGVNYW5hZ2VyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmaWxlTWFuYWdlcjtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0QWxsRmlsZU1hbmFnZXJzKCkge1xuICAgICAgICByZXR1cm4gQXJyYXkuZnJvbSh0aGlzLm1hbmFnZXJzLnZhbHVlcygpKTtcbiAgICB9XG59XG5cbmV4cG9ydCBjbGFzcyBGaWxlRE9NTWFuYWdlciB7XG4gICAgcmVnaW9uTWFwOiBNYXA8c3RyaW5nLCBSZWdpb25NYW5hZ2VyQ29udGFpbmVyPjtcbiAgICBoYXNTdGFydFRhZzogYm9vbGVhbjtcbiAgICBmaWxlS2V5OiBzdHJpbmc7XG4gICAgcGFyZW50TWFuYWdlcjogR2xvYmFsRE9NTWFuYWdlcjtcblxuICAgIGNvbnN0cnVjdG9yKHBhcmVudE1hbmFnZXI6IEdsb2JhbERPTU1hbmFnZXIsIGZpbGVLZXk6IHN0cmluZykge1xuICAgICAgICB0aGlzLnJlZ2lvbk1hcCA9IG5ldyBNYXAoKTtcbiAgICAgICAgdGhpcy5oYXNTdGFydFRhZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLnBhcmVudE1hbmFnZXIgPSBwYXJlbnRNYW5hZ2VyO1xuICAgICAgICB0aGlzLmZpbGVLZXkgPSBmaWxlS2V5O1xuICAgIH1cblxuICAgIHJlbW92ZVJlZ2lvbihyZWdpb25LZXk6IHN0cmluZyk6IHZvaWQge1xuXG4gICAgICAgIGxldCByZWdpb25Db250YWluZXIgPSB0aGlzLnJlZ2lvbk1hcC5nZXQocmVnaW9uS2V5KTtcbiAgICAgICAgaWYocmVnaW9uQ29udGFpbmVyID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCByZWdpb25hbE1hbmFnZXIgPSByZWdpb25Db250YWluZXIuZ2V0UmVnaW9uKCk7XG4gICAgICAgIHJlZ2lvbmFsTWFuYWdlci5kaXNwbGF5T3JpZ2luYWxFbGVtZW50cygpO1xuXG4gICAgICAgIHRoaXMucmVnaW9uTWFwLmRlbGV0ZShyZWdpb25LZXkpO1xuICAgICAgICBcbiAgICAgICAgaWYodGhpcy5yZWdpb25NYXAuc2l6ZSA9PT0gMCkge1xuICAgICAgICAgICAgdGhpcy5wYXJlbnRNYW5hZ2VyLnJlbW92ZUZpbGVNYW5hZ2VyQ2FsbGJhY2sodGhpcy5maWxlS2V5KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGNyZWF0ZVJlZ2lvbmFsTWFuYWdlcihyZWdpb25LZXk6IHN0cmluZywgcm9vdEVsZW1lbnQ6IEhUTUxFbGVtZW50LCBlcnJvck1hbmFnZXI6IFJlZ2lvbkVycm9yTWFuYWdlciwgcmVuZGVyUmVnaW9uRWxlbWVudDogSFRNTEVsZW1lbnQpOiBSZWdpb25NYW5hZ2VyIHtcblxuICAgICAgICBsZXQgcmVnb25hbENvbnRhaW5lciA9IG5ldyBSZWdpb25NYW5hZ2VyQ29udGFpbmVyKHRoaXMsIHJlZ2lvbktleSwgcm9vdEVsZW1lbnQsIHJlbmRlclJlZ2lvbkVsZW1lbnQsIGVycm9yTWFuYWdlcik7XG4gICAgICAgIHRoaXMucmVnaW9uTWFwLnNldChyZWdpb25LZXksIHJlZ29uYWxDb250YWluZXIpO1xuICAgICAgICByZXR1cm4gcmVnb25hbENvbnRhaW5lci5nZXRSZWdpb24oKTtcbiAgICB9XG5cbiAgICBnZXRSZWdpb25hbENvbnRhaW5lcihyZWdpb25LZXk6IHN0cmluZyk6IFJlZ2lvbk1hbmFnZXJDb250YWluZXIgfCBudWxsIHtcblxuICAgICAgICBsZXQgcmVnb25hbE1hbmFnZXIgPSBudWxsO1xuICAgICAgICBpZih0aGlzLnJlZ2lvbk1hcC5oYXMocmVnaW9uS2V5KSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgcmVnb25hbE1hbmFnZXIgPSB0aGlzLnJlZ2lvbk1hcC5nZXQocmVnaW9uS2V5KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZWdvbmFsTWFuYWdlcjtcbiAgICB9XG5cbiAgICBnZXRBbGxSZWdpb25hbE1hbmFnZXJzKCk6IFJlZ2lvbk1hbmFnZXJbXSB7XG5cbiAgICAgICAgbGV0IGNvbnRhaW5lcnMgPSBBcnJheS5mcm9tKHRoaXMucmVnaW9uTWFwLnZhbHVlcygpKVxuICAgICAgICBsZXQgcmVnaW9uczogUmVnaW9uTWFuYWdlcltdID0gY29udGFpbmVycy5tYXAoKGN1cnIpID0+IHsgcmV0dXJuIGN1cnIuZ2V0UmVnaW9uKCkgfSk7XG4gICAgICAgIHJldHVybiByZWdpb25zO1xuICAgIH1cblxuICAgIHNldEhhc1N0YXJ0VGFnKCkge1xuICAgICAgICB0aGlzLmhhc1N0YXJ0VGFnID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBnZXRIYXNTdGFydFRhZygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaGFzU3RhcnRUYWc7XG4gICAgfVxuXG4gICAgZ2V0TnVtYmVyT2ZSZWdpb25zKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5yZWdpb25NYXAuc2l6ZVxuICAgIH1cblxuICAgIGNoZWNrS2V5RXhpc3RzKGNoZWNrS2V5OiBzdHJpbmcpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucmVnaW9uTWFwLmhhcyhjaGVja0tleSk7XG4gICAgfVxufSIsImltcG9ydCB7IE11bHRpQ29sdW1uTGF5b3V0Q1NTLCBNdWx0aUNvbHVtblN0eWxlQ1NTIH0gZnJvbSBcInNyYy91dGlsaXRpZXMvY3NzRGVmaW5pdGlvbnNcIjtcblxuZXhwb3J0IGNsYXNzIFJlZ2lvbkVycm9yTWFuYWdlciB7XG5cbiAgICAvL1RPRE86IEFkZCB3YXJuaW5nc1xuXG4gICAgZXJyb3JQYXJlbnRFbGVtZW50OiBIVE1MRWxlbWVudDtcbiAgICBjb250ZW50RWw6IEhUTUxFbGVtZW50O1xuICAgIHRpdGxlUmVnaW9uOiBIVE1MRWxlbWVudDtcblxuICAgIGVycm9yTWVzc2FnZXM6IHN0cmluZ1tdID0gW107XG4gICAgd2FybmluZ01lc3NhZ2VzOiBzdHJpbmdbXSA9IFtdO1xuXG4gICAgcHJpdmF0ZSBnZXQgdG90YWxOdW1NZXNzYWdlcygpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5lcnJvck1lc3NhZ2VzLmxlbmd0aCArIHRoaXMud2FybmluZ01lc3NhZ2VzLmxlbmd0aFxuICAgIH1cblxuICAgIGNvbnN0cnVjdG9yKHJvb3RFbGVtZW50OiBIVE1MRWxlbWVudCwgaW5pdGlhbEVycm9yTWVzc2FnZXM6IHN0cmluZ1tdID0gW10pIHtcbiAgICAgICAgXG4gICAgICAgIHRoaXMuZXJyb3JNZXNzYWdlcyA9IGluaXRpYWxFcnJvck1lc3NhZ2VzO1xuICAgICAgICB0aGlzLnNldFJlZ2lvblJvb3RFbGVtZW50KHJvb3RFbGVtZW50KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYWRkRXJyb3JNZXNzYWdlKGVycm9yU3RyaW5nOiBzdHJpbmcpIHtcblxuICAgICAgICB0aGlzLmVycm9yTWVzc2FnZXMucHVzaChlcnJvclN0cmluZyk7XG4gICAgICAgIHRoaXMudXBkYXRlRXJyb3JWaWV3KClcbiAgICB9XG5cbiAgICBwdWJsaWMgYWRkV2FybmluZ01lc3NhZ2Uod2FybmluZ1N0cmluZzogc3RyaW5nKSB7XG4gICAgICAgIHRoaXMud2FybmluZ01lc3NhZ2VzLnB1c2god2FybmluZ1N0cmluZyk7XG4gICAgICAgIHRoaXMudXBkYXRlRXJyb3JWaWV3KClcbiAgICB9XG5cbiAgICBwdWJsaWMgc2V0UmVnaW9uUm9vdEVsZW1lbnQocm9vdEVsZW1lbnQ6IEhUTUxFbGVtZW50KSB7XG5cbiAgICAgICAgdGhpcy5lcnJvclBhcmVudEVsZW1lbnQgPSByb290RWxlbWVudC5jcmVhdGVEaXYoe1xuICAgICAgICAgICAgY2xzOiBgJHtNdWx0aUNvbHVtbkxheW91dENTUy5SZWdpb25FcnJvckNvbnRhaW5lckRpdn1gLFxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy50aXRsZVJlZ2lvbiA9IHRoaXMuZXJyb3JQYXJlbnRFbGVtZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICBjbHM6IGAke011bHRpQ29sdW1uTGF5b3V0Q1NTLkVycm9yUmVnaW9uUGFkZGluZ31gXG4gICAgICAgIH0pXG4gICAgICAgIHRoaXMuY29udGVudEVsID0gdGhpcy5lcnJvclBhcmVudEVsZW1lbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgIGNsczogYCR7TXVsdGlDb2x1bW5MYXlvdXRDU1MuRXJyb3JSZWdpb25QYWRkaW5nfSBtY20tbWVzc2FnZS1yZWdpb25gXG4gICAgICAgIH0pXG4gICAgICAgIHRoaXMudXBkYXRlRXJyb3JWaWV3KClcbiAgICB9XG5cbiAgICBwcml2YXRlIHNldHVwRXJyb3JIZWFkZXIoKSB7XG4gICAgICAgIGlmKHRoaXMuZXJyb3JNZXNzYWdlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBsZXQgdGV4dCA9IFwiRXJyb3JcIlxuICAgICAgICAgICAgaWYodGhpcy5lcnJvck1lc3NhZ2VzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICB0ZXh0ID0gdGV4dCArIFwic1wiXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMudGl0bGVSZWdpb24uY3JlYXRlU3Bhbih7XG4gICAgICAgICAgICAgICAgYXR0cjoge1wic3R5bGVcIjogXCJjb2xvcjogdmFyKC0tdGV4dC1lcnJvcik7IHBhZGRpbmc6IDVweDtcIn0sXG4gICAgICAgICAgICAgICAgdGV4dDogXCJcXHUyQTAyXCJcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB0aGlzLnRpdGxlUmVnaW9uLmNyZWF0ZVNwYW4oe1xuICAgICAgICAgICAgICAgIHRleHQ6IGAke3RoaXMuZXJyb3JNZXNzYWdlcy5sZW5ndGh9ICR7dGV4dH1gXG4gICAgICAgICAgICB9KVxuICAgICAgICB9XG5cbiAgICAgICAgaWYodGhpcy5lcnJvck1lc3NhZ2VzLmxlbmd0aCA+IDAgJiYgdGhpcy53YXJuaW5nTWVzc2FnZXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgdGhpcy50aXRsZVJlZ2lvbi5jcmVhdGVTcGFuKHtcbiAgICAgICAgICAgICAgICB0ZXh0OiBgIGFuZCBgXG4gICAgICAgICAgICB9KVxuICAgICAgICB9XG5cbiAgICAgICAgaWYodGhpcy53YXJuaW5nTWVzc2FnZXMubGVuZ3RoID4gMCkge1xuXG4gICAgICAgICAgICBsZXQgdGV4dCA9IFwiV2FybmluZ1wiXG4gICAgICAgICAgICBpZih0aGlzLndhcm5pbmdNZXNzYWdlcy5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICAgICAgdGV4dCA9IHRleHQgKyBcInNcIlxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLnRpdGxlUmVnaW9uLmNyZWF0ZVNwYW4oe1xuICAgICAgICAgICAgICAgIGF0dHI6IHtcInN0eWxlXCI6IFwiY29sb3I6IHZhcigtLWNvbG9yLXllbGxvdyk7IHBhZGRpbmc6IDVweDtcIn0sXG4gICAgICAgICAgICAgICAgdGV4dDogXCJcXHUyNkEwXCJcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB0aGlzLnRpdGxlUmVnaW9uLmNyZWF0ZVNwYW4oe1xuICAgICAgICAgICAgICAgIHRleHQ6IGAke3RoaXMud2FybmluZ01lc3NhZ2VzLmxlbmd0aH0gJHt0ZXh0fWBcbiAgICAgICAgICAgIH0pXG4gICAgICAgIH1cbiAgICAgICAgdGhpcy50aXRsZVJlZ2lvbi5jcmVhdGVTcGFuKHtcbiAgICAgICAgICAgIHRleHQ6IGAgaW4gcmVnaW9uYFxuICAgICAgICB9KVxuXG4gICAgICAgIGxldCByZWdpb25PcGVuZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy50aXRsZVJlZ2lvbi5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgKGV2KSA9PiB7XG4gICAgICAgICAgICB0aGlzLnRpdGxlUmVnaW9uLmNsYXNzTGlzdC50b2dnbGUoXCJtY20tZXJyb3ItaGVhZGluZy1vcGVuXCIpO1xuICAgICAgICAgICAgcmVnaW9uT3BlbmVkID0gIXJlZ2lvbk9wZW5lZFxuICAgICAgICAgICAgaWYocmVnaW9uT3BlbmVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jb250ZW50RWwuc3R5bGUubWF4SGVpZ2h0ID0gdGhpcy5jb250ZW50RWwuc2Nyb2xsSGVpZ2h0ICsgXCJweFwiO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbnRlbnRFbC5zdHlsZS5tYXhIZWlnaHQgPSBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KVxuICAgIH1cblxuICAgIHB1YmxpYyB1cGRhdGVFcnJvclZpZXcoKSB7XG5cbiAgICAgICAgdGhpcy5yZXNldEVycm9yVmlldygpXG5cbiAgICAgICAgaWYodGhpcy50b3RhbE51bU1lc3NhZ2VzID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy50aXRsZVJlZ2lvbi5hZGRDbGFzcyhgbWNtLWVycm9yLWhlYWRpbmdgKSAvL1RPRE86IG1vdmUgdG8gY29uc3QuXG4gICAgICAgIHRoaXMuZXJyb3JQYXJlbnRFbGVtZW50LmNsYXNzTGlzdC5hZGQoTXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5Cb3JkZXIpXG4gICAgICAgIHRoaXMuc2V0dXBFcnJvckhlYWRlcigpXG4gICAgICAgIHRoaXMuYXBwZW5kQ29udGVudFRvRWwoKVxuICAgIH1cblxuXG4gICAgcHJpdmF0ZSBhcHBlbmRDb250ZW50VG9FbCgpIHtcblxuICAgICAgICBmb3IobGV0IGkgPSAwOyBpIDwgdGhpcy5lcnJvck1lc3NhZ2VzLmxlbmd0aDsgaSsrKSB7XG5cbiAgICAgICAgICAgIGxldCBwID0gdGhpcy5jb250ZW50RWwuY3JlYXRlRWwoXCJwXCIpXG4gICAgICAgICAgICBwLmlubmVySFRNTCA9IGA8c3BhbiBjbGFzcz1cIm1jbS1lcnJvci1pY29uXCI+XFx1MkEwMjwvc3Bhbj4ke3RoaXMuZXJyb3JNZXNzYWdlc1swXX1gXG4gICAgICAgIH1cblxuICAgICAgICBmb3IobGV0IGkgPSAwOyBpIDwgdGhpcy53YXJuaW5nTWVzc2FnZXMubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICAgICAgbGV0IHAgPSB0aGlzLmNvbnRlbnRFbC5jcmVhdGVFbChcInBcIilcbiAgICAgICAgICAgIHAuaW5uZXJIVE1MID0gYDxzcGFuIGNsYXNzPVwibWNtLXdhcm5pbmctaWNvblwiPlxcdTI2QTA8L3NwYW4+JHt0aGlzLndhcm5pbmdNZXNzYWdlc1swXX1gXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHJlc2V0RXJyb3JWaWV3KCkge1xuXG4gICAgICAgIHRoaXMuZXJyb3JQYXJlbnRFbGVtZW50LmNsYXNzTGlzdC5yZW1vdmUoTXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5Cb3JkZXIpXG4gICAgICAgIHRoaXMudGl0bGVSZWdpb24ucmVtb3ZlQ2xhc3MoYG1jbS1lcnJvci1oZWFkaW5nYCkgLy9UT0RPOiBtb3ZlIHRvIGNvbnN0LlxuXG4gICAgICAgIHdoaWxlKHRoaXMudGl0bGVSZWdpb24uY2hpbGRyZW4ubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgdGhpcy50aXRsZVJlZ2lvbi5jaGlsZE5vZGVzLmZvckVhY2goY2hpbGQgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMudGl0bGVSZWdpb24ucmVtb3ZlQ2hpbGQoY2hpbGQpXG4gICAgICAgICAgICB9KVxuICAgICAgICB9XG5cbiAgICAgICAgaWYodGhpcy5jb250ZW50RWwgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBjaGlsZHJlbiA9IHRoaXMuY29udGVudEVsPy5jaGlsZE5vZGVzO1xuICAgICAgICBjaGlsZHJlbi5mb3JFYWNoKGNoaWxkID0+IHtcbiAgICAgICAgICAgIGlmKGNoaWxkICE9PSBudWxsICYmIGNoaWxkLnBhcmVudEVsZW1lbnQgPT09IHRoaXMuY29udGVudEVsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jb250ZW50RWwucmVtb3ZlQ2hpbGQoY2hpbGQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG59IiwiaW1wb3J0IHsgRE9NT2JqZWN0VGFnLCBFbGVtZW50Q29sdW1uQnJlYWtUeXBlIH0gZnJvbSBcInNyYy9kb21fbWFuYWdlci9kb21PYmplY3RcIlxuaW1wb3J0IHsgUmVnaW9uRXJyb3JNYW5hZ2VyIH0gZnJvbSBcInNyYy9kb21fbWFuYWdlci9yZWdpb25FcnJvck1hbmFnZXJcIlxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQ29sQnJlYWtXYXJuaW5nKHR5cGU6IEVsZW1lbnRDb2x1bW5CcmVha1R5cGUsIGVycm9yTWFuYWdlcjogUmVnaW9uRXJyb3JNYW5hZ2VyKSB7XG5cbiAgICBsZXQgdHlwZUVycm9yU3RyID0gXCJcIlxuICAgIGlmKHR5cGUgPT09IEVsZW1lbnRDb2x1bW5CcmVha1R5cGUucHJlQnJlYWspIHtcbiAgICAgICAgdHlwZUVycm9yU3RyID0gXCJhdCB0aGUgYmVnaW5pbmcgb2YgYW5vdGhlciBlbGVtZW50XCJcbiAgICB9XG4gICAgaWYodHlwZSA9PT0gRWxlbWVudENvbHVtbkJyZWFrVHlwZS5wb3N0QnJlYWspIHtcbiAgICAgICAgdHlwZUVycm9yU3RyID0gXCJhdCB0aGUgZW5kIG9mIGFub3RoZXIgZWxlbWVudFwiXG4gICAgfVxuICAgIGlmKHR5cGUgPT09IEVsZW1lbnRDb2x1bW5CcmVha1R5cGUubWlkQnJlYWspIHtcbiAgICAgICAgdHlwZUVycm9yU3RyID0gXCJpbiB0aGUgbWlkZGxlIG9mIHR3byBlbGVtZW50c1wiXG4gICAgfVxuXG4gICAgZXJyb3JNYW5hZ2VyLmFkZFdhcm5pbmdNZXNzYWdlKGBEZXRlY3RlZCBhIGNvbHVtbiBicmVhayB0YWcgJHt0eXBlRXJyb3JTdHJ9LiBQbGVhc2UgbWFrZSBzdXJlIHRvIHN1cnJvdW5kIGNvbHVtbiBicmVha3Mgd2l0aCBlbXB0eSBsaW5lcyBvbiBib3RoIHNpZGVzLCBvciByZW5kZXIgaXNzdWVzIG1heSBvY2N1ci5gKVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIENvbEJyZWFrVHlwZUluZm8ge1xuICAgIGxpbmVBYm92ZTogc3RyaW5nO1xuICAgIGxpbmVCZWxvdzogc3RyaW5nO1xuICAgIG9iamVjdFRhZzogRE9NT2JqZWN0VGFnO1xuICAgIGNvbEJyZWFrVHlwZTogRWxlbWVudENvbHVtbkJyZWFrVHlwZVxufVxuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlQ29sQnJlYWtFcnJvclR5cGUoZWxlbWVudEluZm86IENvbEJyZWFrVHlwZUluZm8sIGVycm9yTWFuYWdlcjogUmVnaW9uRXJyb3JNYW5hZ2VyKSB7XG5cbiAgICBpZihlbGVtZW50SW5mby5vYmplY3RUYWcgIT09IERPTU9iamVjdFRhZy5jb2x1bW5CcmVhayAmJlxuICAgICAgIGVsZW1lbnRJbmZvLmNvbEJyZWFrVHlwZSA9PT0gRWxlbWVudENvbHVtbkJyZWFrVHlwZS5ub25lKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBsZXQgZXJyb3JUeXBlOiBFbGVtZW50Q29sdW1uQnJlYWtUeXBlID0gZWxlbWVudEluZm8uY29sQnJlYWtUeXBlO1xuICAgIGlmKGVsZW1lbnRJbmZvLm9iamVjdFRhZyA9PT0gRE9NT2JqZWN0VGFnLmNvbHVtbkJyZWFrKSB7XG5cbiAgICAgICAgaWYoZWxlbWVudEluZm8ubGluZUFib3ZlID09PSBcIlwiICYmXG4gICAgICAgICAgIGVsZW1lbnRJbmZvLmxpbmVCZWxvdyA9PT0gXCJcIikge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGxpbmVBYm92ZSA9IGVsZW1lbnRJbmZvLmxpbmVBYm92ZVxuICAgICAgICBsZXQgbGluZUJlbG93ID0gZWxlbWVudEluZm8ubGluZUJlbG93XG4gICAgICAgIGlmKGxpbmVBYm92ZSAhPT0gXCJcIiAmJiBsaW5lQmVsb3cgPT09IFwiXCIpIHtcbiAgICAgICAgICAgIGVycm9yVHlwZSA9IEVsZW1lbnRDb2x1bW5CcmVha1R5cGUucG9zdEJyZWFrXG4gICAgICAgIH1cbiAgICAgICAgaWYobGluZUFib3ZlID09PSBcIlwiICYmIGxpbmVCZWxvdyAhPT0gXCJcIikge1xuICAgICAgICAgICAgZXJyb3JUeXBlID0gRWxlbWVudENvbHVtbkJyZWFrVHlwZS5wcmVCcmVha1xuICAgICAgICB9XG4gICAgICAgIGlmKGxpbmVBYm92ZSAhPT0gXCJcIiAmJiBsaW5lQmVsb3cgIT09IFwiXCIpIHtcbiAgICAgICAgICAgIGVycm9yVHlwZSA9IEVsZW1lbnRDb2x1bW5CcmVha1R5cGUubWlkQnJlYWtcbiAgICAgICAgfVxuICAgIH1cbiAgICBjcmVhdGVDb2xCcmVha1dhcm5pbmcoZXJyb3JUeXBlLCBlcnJvck1hbmFnZXIpXG59IiwiaW1wb3J0IHsgV29ya3NwYWNlLCBXb3Jrc3BhY2VMZWFmIH0gZnJvbSBcIm9ic2lkaWFuXCI7XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRMZWFmRnJvbUZpbGVQYXRoKHdvcmtzcGFjZTogV29ya3NwYWNlLCBmaWxlUGF0aDogc3RyaW5nKTogV29ya3NwYWNlTGVhZiB8IG51bGwge1xuXG4gICAgZnVuY3Rpb24gY2hlY2tTdGF0ZShzdGF0ZTogYW55KSB7XG5cbiAgICAgICAgaWYoc3RhdGVbXCJ0eXBlXCJdID09PSB1bmRlZmluZWQgfHxcbiAgICAgICAgICAgc3RhdGVbXCJ0eXBlXCJdICE9PSBcIm1hcmtkb3duXCIpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHN0YXRlW1wic3RhdGVcIl0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlXG4gICAgICAgIH1cblxuICAgICAgICBpZihzdGF0ZVtcInN0YXRlXCJdW1wiZmlsZVwiXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgc3RhdGVGaWxlUGF0aCA9IHN0YXRlW1wic3RhdGVcIl1bXCJmaWxlXCJdO1xuICAgICAgICByZXR1cm4gc3RhdGVGaWxlUGF0aCA9PT0gZmlsZVBhdGg7XG4gICAgfVxuXG4gICAgaWYod29ya3NwYWNlID09PSBudWxsKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGxldCBlbnRyaWVzID0gT2JqZWN0LmVudHJpZXMod29ya3NwYWNlLmdldExheW91dCgpKTtcbiAgICBsZXQgaXRlbXMgPSBBcnJheS5mcm9tKGVudHJpZXMpLm1hcCgodmFsKSA9PiB7XG4gICAgICAgIHJldHVybiB2YWxbMV1cbiAgICB9KVxuICAgIHdoaWxlKGl0ZW1zLmxlbmd0aCA+IDApIHtcblxuICAgICAgICBsZXQgZW50cnlPYmogPSBpdGVtcy5zaGlmdCgpIGFzIGFueTtcbiAgICAgICAgaWYoZW50cnlPYmpbXCJpZFwiXSAhPT0gdW5kZWZpbmVkICYmIGVudHJ5T2JqW1widHlwZVwiXSAhPT0gdW5kZWZpbmVkKSB7XG5cbiAgICAgICAgICAgIGlmKGVudHJ5T2JqW1widHlwZVwiXSA9PT0gXCJzcGxpdFwiIHx8XG4gICAgICAgICAgICAgICBlbnRyeU9ialtcInR5cGVcIl0gPT09IFwidGFic1wiICkge1xuICAgICAgICAgICAgICAgIGl0ZW1zID0gaXRlbXMuY29uY2F0KGVudHJ5T2JqWydjaGlsZHJlbiddKTtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoZW50cnlPYmpbXCJ0eXBlXCJdID09PSBcImxlYWZcIiAmJiBcbiAgICAgICAgICAgICAgIGVudHJ5T2JqW1wiaWRcIl0gIT09IHVuZGVmaW5lZCAmJlxuICAgICAgICAgICAgICAgZW50cnlPYmpbXCJzdGF0ZVwiXSAhPT0gdW5kZWZpbmVkKSB7XG5cbiAgICAgICAgICAgICAgICBsZXQgaWQgPSBlbnRyeU9ialtcImlkXCJdO1xuICAgICAgICAgICAgICAgIGxldCBzdGF0ZSA9IGVudHJ5T2JqW1wic3RhdGVcIl07XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coc3RhdGUpXG5cbiAgICAgICAgICAgICAgICBsZXQgdmFsaWQgPSBjaGVja1N0YXRlKHN0YXRlKTtcbiAgICAgICAgICAgICAgICBpZih2YWxpZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gd29ya3NwYWNlLmdldExlYWZCeUlkKGlkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRQcmV2aWV3TGVhZkZyb21GaWxlUGF0aCh3b3Jrc3BhY2U6IFdvcmtzcGFjZSwgZmlsZVBhdGg6IHN0cmluZyk6IFdvcmtzcGFjZUxlYWYgfCBudWxsIHtcblxuICAgIGZ1bmN0aW9uIGNoZWNrU3RhdGUoc3RhdGU6IGFueSkge1xuXG4gICAgICAgIGlmKHN0YXRlW1widHlwZVwiXSA9PT0gdW5kZWZpbmVkIHx8XG4gICAgICAgICAgIHN0YXRlW1widHlwZVwiXSAhPT0gXCJtYXJrZG93blwiKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICBpZihzdGF0ZVtcInN0YXRlXCJdID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZVxuICAgICAgICB9XG5cbiAgICAgICAgaWYoc3RhdGVbXCJzdGF0ZVwiXVtcImZpbGVcIl0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHN0YXRlRmlsZVBhdGggPSBzdGF0ZVtcInN0YXRlXCJdW1wiZmlsZVwiXTtcbiAgICAgICAgcmV0dXJuIHN0YXRlRmlsZVBhdGggPT09IGZpbGVQYXRoO1xuICAgIH1cblxuICAgIGxldCBlbnRyaWVzID0gT2JqZWN0LmVudHJpZXMod29ya3NwYWNlLmdldExheW91dCgpKTtcbiAgICBsZXQgaXRlbXMgPSBBcnJheS5mcm9tKGVudHJpZXMpLm1hcCgodmFsKSA9PiB7XG4gICAgICAgIHJldHVybiB2YWxbMV1cbiAgICB9KVxuICAgIHdoaWxlKGl0ZW1zLmxlbmd0aCA+IDApIHtcblxuICAgICAgICBsZXQgZW50cnlPYmogPSBpdGVtcy5zaGlmdCgpIGFzIGFueTtcbiAgICAgICAgaWYoZW50cnlPYmpbXCJpZFwiXSAhPT0gdW5kZWZpbmVkICYmIGVudHJ5T2JqW1widHlwZVwiXSAhPT0gdW5kZWZpbmVkKSB7XG5cbiAgICAgICAgICAgIGlmKGVudHJ5T2JqW1widHlwZVwiXSA9PT0gXCJzcGxpdFwiIHx8XG4gICAgICAgICAgICAgICBlbnRyeU9ialtcInR5cGVcIl0gPT09IFwidGFic1wiICkge1xuICAgICAgICAgICAgICAgIGl0ZW1zID0gaXRlbXMuY29uY2F0KGVudHJ5T2JqWydjaGlsZHJlbiddKTtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoZW50cnlPYmpbXCJ0eXBlXCJdID09PSBcImxlYWZcIiAmJiBcbiAgICAgICAgICAgICAgIGVudHJ5T2JqW1wiaWRcIl0gIT09IHVuZGVmaW5lZCAmJlxuICAgICAgICAgICAgICAgZW50cnlPYmpbXCJzdGF0ZVwiXSAhPT0gdW5kZWZpbmVkKSB7XG5cbiAgICAgICAgICAgICAgICBsZXQgaWQgPSBlbnRyeU9ialtcImlkXCJdO1xuICAgICAgICAgICAgICAgIGxldCBzdGF0ZSA9IGVudHJ5T2JqW1wic3RhdGVcIl07XG5cbiAgICAgICAgICAgICAgICBsZXQgaXNQcmV2aWV3ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgaWYoc3RhdGVbXCJzdGF0ZVwiXSAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAgICAgICAgICAgICAgIHN0YXRlW1wic3RhdGVcIl1bXCJtb2RlXCJdICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IG1vZGUgPSBzdGF0ZVtcInN0YXRlXCJdW1wibW9kZVwiXVxuICAgICAgICAgICAgICAgICAgICBpc1ByZXZpZXcgPSBtb2RlID09PSBcInByZXZpZXdcIlxuICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBsZXQgdmFsaWRGaWxlUGF0aCA9IGNoZWNrU3RhdGUoc3RhdGUpO1xuICAgICAgICAgICAgICAgIGlmKHZhbGlkRmlsZVBhdGggJiYgaXNQcmV2aWV3KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB3b3Jrc3BhY2UuZ2V0TGVhZkJ5SWQoaWQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbn0iLCIvKlxuICogRmlsZW5hbWU6IG11bHRpLWNvbHVtbi1tYXJrZG93bi9zcmMvbGl2ZV9wcmV2aWV3L011bHRpQ29sdW1uTWFya2Rvd25fV2lkZ2V0LnRzXG4gKiBDcmVhdGVkIERhdGU6IFR1ZXNkYXksIEF1Z3VzdCAxNnRoIDIwMjIsIDQ6Mzg6NDMgcG1cbiAqIEF1dGhvcjogQ2FtZXJvbiBSb2JpbnNvblxuICogXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjIgQ2FtZXJvbiBSb2JpbnNvblxuICovXG5cbmltcG9ydCB7IE1hcmtkb3duUmVuZGVyQ2hpbGQsIE1hcmtkb3duUmVuZGVyZXIsIFRGaWxlLCBXb3Jrc3BhY2VMZWFmIH0gZnJvbSBcIm9ic2lkaWFuXCI7XG5pbXBvcnQgeyBXaWRnZXRUeXBlIH0gZnJvbSBcIkBjb2RlbWlycm9yL3ZpZXdcIjtcbmltcG9ydCB7IGdldERlZmF1bHRNdWx0aUNvbHVtblNldHRpbmdzLCBNQ1NldHRpbmdzX2lzRXF1YWwsIE11bHRpQ29sdW1uU2V0dGluZ3MgfSBmcm9tIFwiLi4vcmVnaW9uU2V0dGluZ3NcIjtcbmltcG9ydCB7IHBhcnNlU2luZ2xlQ29sdW1uU2V0dGluZ3MgfSBmcm9tIFwiLi4vdXRpbGl0aWVzL3NldHRpbmdzUGFyc2VyXCI7XG5pbXBvcnQgeyBTdGFuZGFyZE11bHRpQ29sdW1uUmVnaW9uTWFuYWdlciB9IGZyb20gXCIuLi9kb21fbWFuYWdlci9yZWdpb25hbF9tYW5hZ2Vycy9zdGFuZGFyZE11bHRpQ29sdW1uUmVnaW9uTWFuYWdlclwiO1xuaW1wb3J0IHsgUmVnaW9uTWFuYWdlckRhdGEgfSBmcm9tIFwiLi4vZG9tX21hbmFnZXIvcmVnaW9uYWxfbWFuYWdlcnMvcmVnaW9uTWFuYWdlckNvbnRhaW5lclwiO1xuaW1wb3J0IHsgZ2V0VUlEIH0gZnJvbSBcIi4uL3V0aWxpdGllcy91dGlsc1wiO1xuaW1wb3J0IHsgRE9NT2JqZWN0LCBET01PYmplY3RUYWcsIEVsZW1lbnRDb2x1bW5CcmVha1R5cGUgfSBmcm9tIFwiLi4vZG9tX21hbmFnZXIvZG9tT2JqZWN0XCI7XG5pbXBvcnQgeyBSZWdpb25NYW5hZ2VyIH0gZnJvbSBcIi4uL2RvbV9tYW5hZ2VyL3JlZ2lvbmFsX21hbmFnZXJzL3JlZ2lvbk1hbmFnZXJcIjtcbmltcG9ydCB7IFNpbmdsZUNvbHVtblJlZ2lvbk1hbmFnZXIgfSBmcm9tIFwiLi4vZG9tX21hbmFnZXIvcmVnaW9uYWxfbWFuYWdlcnMvc2luZ2xlQ29sdW1uUmVnaW9uTWFuYWdlclwiO1xuaW1wb3J0IHsgQXV0b0xheW91dFJlZ2lvbk1hbmFnZXIgfSBmcm9tIFwiLi4vZG9tX21hbmFnZXIvcmVnaW9uYWxfbWFuYWdlcnMvYXV0b0xheW91dFJlZ2lvbk1hbmFnZXJcIjtcbmltcG9ydCB7IE11bHRpQ29sdW1uU3R5bGVDU1MsIE9ic2lkaWFuU3R5bGVDU1MgfSBmcm9tIFwic3JjL3V0aWxpdGllcy9jc3NEZWZpbml0aW9uc1wiO1xuaW1wb3J0IHsgaXNUYXNrc1BsdWdpbiB9IGZyb20gXCJzcmMvdXRpbGl0aWVzL2VsZW1lbnRSZW5kZXJUeXBlUGFyc2VyXCI7XG5pbXBvcnQgeyBSZWdpb25FcnJvck1hbmFnZXIgfSBmcm9tIFwic3JjL2RvbV9tYW5hZ2VyL3JlZ2lvbkVycm9yTWFuYWdlclwiO1xuaW1wb3J0IHsgUmVnaW9uVHlwZSB9IGZyb20gXCJzcmMvdXRpbGl0aWVzL2ludGVyZmFjZXNcIjtcbmltcG9ydCB7IHBhcnNlQ29sQnJlYWtFcnJvclR5cGUgfSBmcm9tIFwic3JjL3V0aWxpdGllcy9lcnJvck1lc3NhZ2VcIjtcbmltcG9ydCB7IGNoZWNrRm9yUGFyYWdyYXBoSW5uZXJDb2xFbmRUYWcsIGNvbnRhaW5zQ29sRW5kVGFnLCBmaW5kRW5kVGFnQ2xvc2VzdFRvRW5kIH0gZnJvbSBcInNyYy91dGlsaXRpZXMvdGV4dFBhcnNlclwiO1xuaW1wb3J0IHsgZ2V0UHJldmlld0xlYWZGcm9tRmlsZVBhdGggfSBmcm9tIFwic3JjL3V0aWxpdGllcy9vYnNpVXRpbHNcIjtcbmltcG9ydCB7IE1DTV9TZXR0aW5nc01hbmFnZXIgfSBmcm9tIFwic3JjL3BsdWdpblNldHRpbmdzXCI7XG5cbmNvbnN0IENBQ0hFX01BWF9ERUxUQV9USU1FX01TID0gMiAqIDYwICogMTAwMDsgLy8gMm1cblxuaW50ZXJmYWNlIGNhY2hlRGF0YSB7XG4gICAgdGltZXN0YW1wOiBudW1iZXIsXG4gICAgZWxlbWVudDogSFRNTEVsZW1lbnQsXG4gICAgcmVnaW9uTWFuYWdlcjogUmVnaW9uTWFuYWdlcixcbiAgICBlcnJvclJvb3RFbDogSFRNTERpdkVsZW1lbnQsXG4gICAgY2FjaGVTZXR0aW5nczogTXVsdGlDb2x1bW5TZXR0aW5ncyxcbiAgICBwbHVnaW5TZXR0aW5nc1VwZGF0ZVRpbWVzdGFtcDogbnVtYmVyXG59XG5cbmxldCBsaXZlUHJldmlld0VsZW1lbnRDYWNoZTogTWFwPHN0cmluZywgY2FjaGVEYXRhPiA9IG5ldyBNYXAoKVxuYXN5bmMgZnVuY3Rpb24gY2xlYXJDYWNoZShza2lwS2V5OiBzdHJpbmcgPSBcIlwiKSB7XG5cbiAgICBsZXQgaW5kZXggPSAtMTtcbiAgICBsZXQga2V5cyA9IEFycmF5LmZyb20obGl2ZVByZXZpZXdFbGVtZW50Q2FjaGUua2V5cygpKVxuICAgIGZvcihsZXQga2V5IG9mIGtleXMpIHtcbiAgICAgICAgaW5kZXgrK1xuXG4gICAgICAgIGlmKGtleSA9PT0gc2tpcEtleSkge1xuICAgICAgICAgICAgLy8gY29uc29sZS5kZWJ1ZyhgRWxlbWVudDogJHtpbmRleH0gfCBTa2lwcGluZyBrZXk6ICR7a2V5LnNwbGl0KFwiIDogXCIpWzBdfWApXG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGxpdmVQcmV2aWV3RWxlbWVudENhY2hlLmhhcyhrZXkpID09PSBmYWxzZSkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH0gXG5cbiAgICAgICAgbGV0IHZhbCA9IGxpdmVQcmV2aWV3RWxlbWVudENhY2hlLmdldChrZXkpXG5cbiAgICAgICAgbGV0IGRlbHRhVGltZU1TID0gRGF0ZS5ub3coKSAtIHZhbC50aW1lc3RhbXBcbiAgICAgICAgaWYoKHZhbC5lbGVtZW50LnBhcmVudE5vZGUgPT09IG51bGwgfHwgdmFsLmVsZW1lbnQucGFyZW50Tm9kZS5wYXJlbnROb2RlID09PSBudWxsKSAmJiBkZWx0YVRpbWVNUyA+IENBQ0hFX01BWF9ERUxUQV9USU1FX01TKSB7XG4gICAgICAgICAgICAvLyBjb25zb2xlLmRlYnVnKGBjYWNoZSBkZWx0YTogJHtkZWx0YVRpbWVNU30gPiAke0NBQ0hFX01BWF9ERUxUQV9USU1FX01TfSBvciAyIG1pbnV0ZXMuYClcbiAgICAgICAgICAgIGxpdmVQcmV2aWV3RWxlbWVudENhY2hlLmRlbGV0ZShrZXkpXG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZih2YWwuZWxlbWVudC5wYXJlbnROb2RlID09IG51bGwgfHwgdmFsLmVsZW1lbnQucGFyZW50Tm9kZS5wYXJlbnROb2RlID09PSBudWxsKSB7XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIC8vIGNvbnNvbGUuZGVidWcoYEVsZW1lbnQgJHtpbmRleH0gbnVsbCBidXQgbm90IHJlbW92aW5nIGZyb20gY2FjaGUgeWV0LiBcXG5FbGVtZW50IGZpbGUgcGF0aDogJHtrZXkuc3BsaXQoXCIgOiBcIilbMF19IFxcblBhdGggRWxhcHNlZCB0aW1lOiAke01hdGguZmxvb3IoZGVsdGFUaW1lTVMgLyAxMDAwKX1gKVxuICAgICAgICB9XG4gICAgfVxufVxuZXhwb3J0IGZ1bmN0aW9uIGNsZWFyTGl2ZVByZXZpZXdDYWNoZSgpIHtcbiAgICBjbGVhckNhY2hlKClcbn1cblxuZXhwb3J0IGNsYXNzIE11bHRpQ29sdW1uTWFya2Rvd25fTGl2ZVByZXZpZXdfV2lkZ2V0IGV4dGVuZHMgV2lkZ2V0VHlwZSB7XG5cbiAgICBjb250ZW50RGF0YTogc3RyaW5nO1xuICAgIHRlbXBQYXJlbnQ6IEhUTUxEaXZFbGVtZW50O1xuICAgIGRvbUxpc3Q6IERPTU9iamVjdFtdID0gW107XG4gICAgc2V0dGluZ3NUZXh0OiBzdHJpbmc7XG4gICAgcmVnaW9uU2V0dGluZ3M6IE11bHRpQ29sdW1uU2V0dGluZ3MgPSBnZXREZWZhdWx0TXVsdGlDb2x1bW5TZXR0aW5ncygpO1xuICAgIHJlZ2lvbk1hbmFnZXI6IFJlZ2lvbk1hbmFnZXI7XG4gICAgc291cmNlRmlsZTogVEZpbGU7XG4gICAgc291cmNlUGF0aDogc3RyaW5nID0gXCJcIjtcbiAgICBlbGVtZW50Q2FjaGVJRDogc3RyaW5nO1xuICAgIGVycm9yUm9vdEVsOiBIVE1MRGl2RWxlbWVudDtcbiAgICBcbiAgICBjb25zdHJ1Y3RvcihvcmlnaW5hbFRleHQ6IHN0cmluZywgY29udGVudERhdGE6IHN0cmluZywgdXNlclNldHRpbmdzOiBNdWx0aUNvbHVtblNldHRpbmdzLCBzb3VyY2VGaWxlOiBURmlsZSwgc2V0dGluZ3NUZXh0OiBzdHJpbmcgPSBcIlwiLCByZWdpb25UeXBlOiBSZWdpb25UeXBlKSB7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIHRoaXMuY29udGVudERhdGEgPSBjb250ZW50RGF0YTtcbiAgICAgICAgdGhpcy5zZXR0aW5nc1RleHQgPSBzZXR0aW5nc1RleHQ7XG4gICAgICAgIHRoaXMuc291cmNlRmlsZSA9IHNvdXJjZUZpbGU7XG5cbiAgICAgICAgaWYodGhpcy5zb3VyY2VGaWxlID09PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm5cbiAgICAgICAgfVxuICAgICAgICB0aGlzLmVsZW1lbnRDYWNoZUlEID0gYCR7dGhpcy5zb3VyY2VGaWxlLnBhdGh9IDogJHt0aGlzLmNvbnRlbnREYXRhfWA7XG5cbiAgICAgICAgaWYodGhpcy5zb3VyY2VGaWxlKSB7XG4gICAgICAgICAgICB0aGlzLnNvdXJjZVBhdGggPSBzb3VyY2VGaWxlLnBhdGg7XG4gICAgICAgIH1cblxuICAgICAgICBpZih1c2VyU2V0dGluZ3MgIT09IG51bGwpIHtcbiAgICAgICAgICAgIHRoaXMucmVnaW9uU2V0dGluZ3MgPSB1c2VyU2V0dGluZ3M7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgZXJyb3JNYW5hZ2VyID0gbmV3IFJlZ2lvbkVycm9yTWFuYWdlcihjcmVhdGVEaXYoKSk7XG4gICAgICAgIGlmKHJlZ2lvblR5cGUgPT09IFwiQ09ERUJMT0NLXCIpIHtcbiAgICAgICAgICAgIGVycm9yTWFuYWdlci5hZGRFcnJvck1lc3NhZ2UoXCJUaGUgY29kZWJsb2NrIHJlZ2lvbiBzdGFydCBzeW50YXggaGFzIGJlZW4gZGVwcmljYXRlZC4gUGxlYXNlIG1hbnVhbGx5IHVwZGF0ZSB0byB0aGUgY3VycmVudCBzeW50YXggZGVmaW5lZCBpbiB0aGUgUmVhZE1lLCBydW4gdGhlIFxcXCJGaXggTXVsdGktQ29sdW1uIFN5bnRheCBpbiBDdXJyZW50IEZpbGVcXFwiIGZyb20gdGhlIENvbW1hbmQgUGFsZXR0ZSwgb3IgdXNlIHRoZSBcXFwiVXBkYXRlIERlcHJpY2F0ZWQgU3ludGF4XFxcIiBjb21tYW5kIGZvdW5kIGluIHRoZSBwbHVnaW4gc2V0dGluZ3Mgd2luZG93LiBZb3UgbXVzdCByZWxvYWQgdGhlIGZpbGUgZm9yIGNoYW5nZXMgdG8gdGFrZSBlZmZlY3QuXCIpXG4gICAgICAgIH1cblxuICAgICAgICAoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgZnVuY3Rpb24gaGFzQmFkQ29udGVudEJldHdlZW4oY29udGVudEJldHdlZW46IHN0cmluZyk6IGJvb2xlYW4ge1xuXG4gICAgICAgICAgICAgICAgbGV0IHJlZ2V4UmVzdWx0ID0gbmV3IFJlZ0V4cChcIigoPzogKlxcbil7Nix9KVwiKS5leGVjKGNvbnRlbnRCZXR3ZWVuKVxuICAgICAgICAgICAgICAgIGlmKHJlZ2V4UmVzdWx0ICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKFwiRm91bmQgYXQgbGVhc3QgNiBlbXB0eSBsaW5lcy5cIilcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJlZ2V4UmVzdWx0ID0gL14oPzooPyEgKiQpKD8hICotLS0gKiQpKS4rJC9tZy5leGVjKGNvbnRlbnRCZXR3ZWVuKTtcbiAgICAgICAgICAgICAgICBpZihyZWdleFJlc3VsdCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxldCBmaWxlVGV4dCA9IGF3YWl0IHNvdXJjZUZpbGUudmF1bHQuY2FjaGVkUmVhZChzb3VyY2VGaWxlKTtcbiAgICAgICAgICAgIGZpbGVUZXh0ID0gZmlsZVRleHQucmVwbGFjZShvcmlnaW5hbFRleHQsIFwiIyMjLS1TVEFSVF9IRVJFLS0jIyNcIilcblxuICAgICAgICAgICAgbGV0IHJlZ2V4UmVzdWx0ID0gbmV3IFJlZ0V4cChcIiMjIy0tU1RBUlRfSEVSRS0tIyMjXCIpLmV4ZWMoZmlsZVRleHQpXG4gICAgICAgICAgICBpZihyZWdleFJlc3VsdCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZmlsZVRleHQgPSBmaWxlVGV4dC5zbGljZSgwLCByZWdleFJlc3VsdC5pbmRleCk7XG5cbiAgICAgICAgICAgIGxldCBuZXh0U3RhcnRUYWcgPSBmaW5kRW5kVGFnQ2xvc2VzdFRvRW5kKGZpbGVUZXh0KTtcbiAgICAgICAgICAgIGlmKG5leHRTdGFydFRhZy5mb3VuZCA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxldCBlcnJvclN0cmluZyA9IGhhc0JhZENvbnRlbnRCZXR3ZWVuKGZpbGVUZXh0LnNsaWNlKG5leHRTdGFydFRhZy5lbmRQb3NpdGlvbikpXG4gICAgICAgICAgICBpZihlcnJvclN0cmluZyA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGVycm9yTWFuYWdlci5hZGRXYXJuaW5nTWVzc2FnZShcIkRldGVjdGVkIHBvc3NpYmxlIGlzc3VlIHdpdGggdGhlIGNvbnRlbnQgYmV0d2VlbiB0aGlzIHJlZ2lvbiBhbmQgdGhlIHJlZ2lvbiBhYm92ZS4gXFxcbiAgICAgICAgICAgIElmIHlvdSBleHBlcmllbmNlIHBhZ2UganVtcGluZyB3aGVuIGNsaWNraW5nIHdpdGhpbiB0aGlzIGRvY3VtZW50LCBwbGVhc2UgbWFrZSBzdXJlIHRoZXJlIGFyZSBhdCBsZWFzdCA2IGJsYW5rIFxcXG4gICAgICAgICAgICBsaW5lcyBvciBzb21lIGZvcm0gb2YgdGV4dCBjb250ZW50IGJldHdlZW4gdGhlIHR3byByZWdpb25zLiBUaGlzIGlzIGEga25vd24gaXNzdWUgdGhhdCBpcyB1bmRlciBpbnZlc3RpZ2F0aW9uLiBTb3JyeSBmb3IgdGhlIGluY29udmVuaWVuY2UuXCIpXG4gICAgICAgIH0pKCk7XG5cbiAgICAgICAgaWYobGl2ZVByZXZpZXdFbGVtZW50Q2FjaGUuaGFzKHRoaXMuZWxlbWVudENhY2hlSUQpKSB7XG4gICAgICAgICAgICBsZXQgY2FjaGUgPSBsaXZlUHJldmlld0VsZW1lbnRDYWNoZS5nZXQodGhpcy5lbGVtZW50Q2FjaGVJRClcbiAgICAgICAgICAgIGxldCByZWdpb25NYW5hZ2VyID0gY2FjaGUucmVnaW9uTWFuYWdlclxuICAgICAgICAgICAgbGV0IHJlZ2lvblNldHRpbmdzRXF1YWwgPSBNQ1NldHRpbmdzX2lzRXF1YWwodXNlclNldHRpbmdzLCBjYWNoZS5jYWNoZVNldHRpbmdzKVxuICAgICAgICAgICAgbGV0IHBsdWdpblNldHRpbmdzVXBkYXRlZCA9IE1DTV9TZXR0aW5nc01hbmFnZXIuc2hhcmVkLmxhc3RVcGRhdGVUaW1lc3RhbXAgPiBjYWNoZS5wbHVnaW5TZXR0aW5nc1VwZGF0ZVRpbWVzdGFtcFxuICAgICAgICAgICAgaWYocmVnaW9uTWFuYWdlciAmJiByZWdpb25TZXR0aW5nc0VxdWFsID09PSB0cnVlICYmIHBsdWdpblNldHRpbmdzVXBkYXRlZCA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICByZWdpb25NYW5hZ2VyLnVwZGF0ZUVycm9yTWFuYWdlcihlcnJvck1hbmFnZXIsIGNhY2hlLmVycm9yUm9vdEVsKTtcblxuICAgICAgICAgICAgICAgIGxldCB1c2VMaXZlUHJldmlld0NhY2hlID0gTUNNX1NldHRpbmdzTWFuYWdlci5zaGFyZWQudXNlTGl2ZVByZXZpZXdDYWNoZTtcbiAgICAgICAgICAgICAgICBsZXQgZmlsZUxlYWYgPSBnZXRQcmV2aWV3TGVhZkZyb21GaWxlUGF0aChhcHAud29ya3NwYWNlLCB0aGlzLnNvdXJjZUZpbGUucGF0aClcbiAgICAgICAgICAgICAgICBpZih1c2VMaXZlUHJldmlld0NhY2hlICYmIGZpbGVMZWFmID09PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVyblxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGxpdmVQcmV2aWV3RWxlbWVudENhY2hlLmRlbGV0ZSh0aGlzLmVsZW1lbnRDYWNoZUlEKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFJlbmRlciB0aGUgbWFya2Rvd24gY29udGVudCB0byBvdXIgdGVtcCBwYXJlbnQgZWxlbWVudC5cbiAgICAgICAgdGhpcy50ZW1wUGFyZW50ID0gY3JlYXRlRGl2KCk7XG4gICAgICAgIGxldCBlbGVtZW50TWFya2Rvd25SZW5kZXJlciA9IG5ldyBNYXJrZG93blJlbmRlckNoaWxkKHRoaXMudGVtcFBhcmVudCk7XG4gICAgICAgIE1hcmtkb3duUmVuZGVyZXIucmVuZGVyTWFya2Rvd24odGhpcy5jb250ZW50RGF0YSwgdGhpcy50ZW1wUGFyZW50LCB0aGlzLnNvdXJjZVBhdGgsIGVsZW1lbnRNYXJrZG93blJlbmRlcmVyKTtcblxuICAgICAgICBsZXQgcHJldmlvdXNUZXh0ID0gXCJcIjtcbiAgICAgICAgbGV0IHdvcmtpbmdUZXh0ID0gb3JpZ2luYWxUZXh0O1xuICAgICAgICAvLyB0YWtlIGFsbCBlbGVtZW50cywgaW4gb3JkZXIsIGFuZCBjcmVhdGUgb3VyIERPTSBsaXN0LlxuICAgICAgICBsZXQgYXJyID0gQXJyYXkuZnJvbSh0aGlzLnRlbXBQYXJlbnQuY2hpbGRyZW4pO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGFyci5sZW5ndGg7IGkrKykge1xuXG4gICAgICAgICAgICBsZXQgZWwgPSB0aGlzLmZpeEVsZW1lbnRSZW5kZXIoYXJyW2ldKTtcblxuICAgICAgICAgICAgbGV0IGRvbU9iamVjdCA9IG5ldyBET01PYmplY3QoZWwgYXMgSFRNTEVsZW1lbnQsIFtcIlwiXSlcbiAgICAgICAgICAgIHRoaXMuZG9tTGlzdC5wdXNoKGRvbU9iamVjdCk7XG5cbiAgICAgICAgICAgIGxldCBuZXdEYXRhID0gc2xpY2VXb3JraW5nVGV4dFRvRWwoZG9tT2JqZWN0LCBwcmV2aW91c1RleHQsIHdvcmtpbmdUZXh0KVxuICAgICAgICAgICAgcHJldmlvdXNUZXh0ID0gbmV3RGF0YS5wcmV2aW91c1RleHQ7XG4gICAgICAgICAgICB3b3JraW5nVGV4dCA9IG5ld0RhdGEud29ya2luZ1RleHQ7XG5cbiAgICAgICAgICAgIG5ld0RhdGEgPSBhdHRlbXB0VG9GaXhDaGVja2JveGVzKGRvbU9iamVjdCwgcHJldmlvdXNUZXh0LCB3b3JraW5nVGV4dCwgc291cmNlRmlsZSwgdGhpcy5lbGVtZW50Q2FjaGVJRClcbiAgICAgICAgICAgIHByZXZpb3VzVGV4dCA9IG5ld0RhdGEucHJldmlvdXNUZXh0O1xuICAgICAgICAgICAgd29ya2luZ1RleHQgPSBuZXdEYXRhLndvcmtpbmdUZXh0O1xuXG4gICAgICAgICAgICB3b3JraW5nVGV4dCA9IGNoZWNrRm9yQ29sdW1uQnJlYWtFcnJvcnMoZG9tT2JqZWN0LCBwcmV2aW91c1RleHQsIHdvcmtpbmdUZXh0LCBlcnJvck1hbmFnZXIpXG4gICAgICAgIH1cblxuICAgICAgICAvLyBTZXQgdXAgdGhlIHJlZ2lvbiBtYW5hZ2VyIGRhdGEgYmVmb3JlIHRoZW4gY3JlYXRpbmcgb3VyIHJlZ2lvbiBtYW5hZ2VyLlxuICAgICAgICBsZXQgcmVnaW9uRGF0YTogUmVnaW9uTWFuYWdlckRhdGEgPSB7XG4gICAgICAgICAgICBkb21MaXN0OiB0aGlzLmRvbUxpc3QsXG4gICAgICAgICAgICBkb21PYmplY3RNYXA6IG5ldyBNYXA8c3RyaW5nLCBET01PYmplY3Q+KCksXG4gICAgICAgICAgICByZWdpb25QYXJlbnQ6IGNyZWF0ZURpdigpLFxuICAgICAgICAgICAgZmlsZU1hbmFnZXI6IG51bGwsXG4gICAgICAgICAgICByZWdpb25hbFNldHRpbmdzOiB0aGlzLnJlZ2lvblNldHRpbmdzLFxuICAgICAgICAgICAgcmVnaW9uS2V5OiBnZXRVSUQoKSxcbiAgICAgICAgICAgIHJvb3RFbGVtZW50OiBjcmVhdGVEaXYoKSxcbiAgICAgICAgICAgIGVycm9yTWFuYWdlcjogZXJyb3JNYW5hZ2VyXG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gRmluYWxseSBzZXR1cCB0aGUgdHlwZSBvZiByZWdpb24gbWFuYWdlciByZXF1aXJlZC5cbiAgICAgICAgaWYgKHRoaXMucmVnaW9uU2V0dGluZ3MubnVtYmVyT2ZDb2x1bW5zID09PSAxKSB7XG4gICAgICAgICAgICB0aGlzLnJlZ2lvblNldHRpbmdzID0gcGFyc2VTaW5nbGVDb2x1bW5TZXR0aW5ncyh0aGlzLnNldHRpbmdzVGV4dCwgdGhpcy5yZWdpb25TZXR0aW5ncyk7XG4gICAgICAgICAgICB0aGlzLnJlZ2lvbk1hbmFnZXIgPSBuZXcgU2luZ2xlQ29sdW1uUmVnaW9uTWFuYWdlcihyZWdpb25EYXRhKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0aGlzLnJlZ2lvblNldHRpbmdzLmF1dG9MYXlvdXQgPT09IHRydWUpIHtcbiAgICAgICAgICAgIHRoaXMucmVnaW9uTWFuYWdlciA9IG5ldyBBdXRvTGF5b3V0UmVnaW9uTWFuYWdlcihyZWdpb25EYXRhLCB0cnVlKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMucmVnaW9uTWFuYWdlciA9IG5ldyBTdGFuZGFyZE11bHRpQ29sdW1uUmVnaW9uTWFuYWdlcihyZWdpb25EYXRhKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNsZWFyQ2FjaGUodGhpcy5lbGVtZW50Q2FjaGVJRClcbiAgICB9XG5cbiAgICBmaXhFbGVtZW50UmVuZGVyKGVsOiBFbGVtZW50KTogRWxlbWVudCB7XG5cbiAgICAgICAgbGV0IGZpeGVkRWwgPSBmaXhJbWFnZVJlbmRlcihlbCwgdGhpcy5zb3VyY2VQYXRoKTtcbiAgICAgICAgZml4ZWRFbCA9IGZpeFBERlJlbmRlcihmaXhlZEVsLCB0aGlzLnNvdXJjZVBhdGgpO1xuICAgICAgICBmaXhlZEVsID0gZml4RmlsZUVtYmVkKGZpeGVkRWwsIHRoaXMuc291cmNlUGF0aCk7XG4gICAgICAgIGZpeGVkRWwgPSBmaXhUYWJsZVJlbmRlcihmaXhlZEVsKTtcbiAgICAgICAgZml4ZWRFbCA9IGZpeFVuU3VwcG9ydGVkUmVuZGVyKGZpeGVkRWwpO1xuICAgICAgICByZXR1cm4gZml4ZWRFbDtcbiAgICB9XG5cbiAgICB0b0RPTSgpIHtcblxuICAgICAgICBsZXQgdXNlTGl2ZVByZXZpZXdDYWNoZSA9IE1DTV9TZXR0aW5nc01hbmFnZXIuc2hhcmVkLnVzZUxpdmVQcmV2aWV3Q2FjaGU7XG4gICAgICAgIGxldCBmaWxlTGVhZiA9IGdldFByZXZpZXdMZWFmRnJvbUZpbGVQYXRoKGFwcC53b3Jrc3BhY2UsIHRoaXMuc291cmNlRmlsZS5wYXRoKVxuICAgICAgICBpZih1c2VMaXZlUHJldmlld0NhY2hlICYmIFxuICAgICAgICAgICAgbGl2ZVByZXZpZXdFbGVtZW50Q2FjaGUuaGFzKHRoaXMuZWxlbWVudENhY2hlSUQpICYmXG4gICAgICAgICAgICBmaWxlTGVhZiA9PT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIGxpdmVQcmV2aWV3RWxlbWVudENhY2hlLmdldCh0aGlzLmVsZW1lbnRDYWNoZUlEKS5lbGVtZW50XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDcmVhdGUgb3VyIGVsZW1lbnQgdG8gaG9sZCBhbGwgb2YgdGhlIGxpdmUgcHJldmlldyBlbGVtZW50cy5cbiAgICAgICAgbGV0IGVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcbiAgICAgICAgZWwuY2xhc3NOYW1lID0gXCJtY20tY20tcHJldmlld1wiO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBGb3Igc2l0dWF0aW9ucyB3aGVyZSB3ZSBuZWVkIHRvIGtub3cgdGhlIHJlbmRlcmVkIGhlaWdodCwgQXV0b0xheW91dCwgXG4gICAgICAgICAqIHRoZSBlbGVtZW50IG11c3QgYmUgcmVuZGVyZWQgb250byB0aGUgc2NyZWVuIHRvIGdldCB0aGUgaW5mbywgZXZlbiBpZiBcbiAgICAgICAgICogb25seSBmb3IgYSBtb21lbnQuIEhlcmUgd2UgYXR0ZW1wdCB0byBnZXQgYSBsZWFmIGZyb20gdGhlIGFwcCBzbyB3ZSBcbiAgICAgICAgICogY2FuIGJyaWVmbHkgYXBwZW5kIG91ciBlbGVtZW50LCBjaGVjayBhbnkgZGF0YSBpZiByZXF1aXJlZCwgYW5kIHRoZW5cbiAgICAgICAgICogcmVtb3ZlIGl0LlxuICAgICAgICAgKi9cbiAgICAgICAgbGV0IGF1dG9sYXlvdXRMZWFmOiBXb3Jrc3BhY2VMZWFmID0gbnVsbDtcbiAgICAgICAgaWYgKGFwcCkge1xuICAgICAgICAgICAgbGV0IGxlYXZlcyA9IGFwcC53b3Jrc3BhY2UuZ2V0TGVhdmVzT2ZUeXBlKFwibWFya2Rvd25cIik7XG4gICAgICAgICAgICBpZiAobGVhdmVzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBhdXRvbGF5b3V0TGVhZiA9IGxlYXZlc1swXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLnJlZ2lvbk1hbmFnZXIpIHtcblxuICAgICAgICAgICAgdGhpcy5lcnJvclJvb3RFbCA9IGVsLmNyZWF0ZURpdigpXG4gICAgICAgICAgICBsZXQgY29udGVudEVsZW1lbnQgPSBlbC5jcmVhdGVEaXYoKVxuICAgICAgICAgICAgdGhpcy5yZWdpb25NYW5hZ2VyLmdldFJlZ2lvbkRhdGEoKS5lcnJvck1hbmFnZXIuc2V0UmVnaW9uUm9vdEVsZW1lbnQodGhpcy5lcnJvclJvb3RFbClcblxuICAgICAgICAgICAgbGV0IHJlcXVpcmVVbmxvYWQgPSBmYWxzZVxuICAgICAgICAgICAgaWYgKGF1dG9sYXlvdXRMZWFmICYmIHRoaXMucmVnaW9uTWFuYWdlciBpbnN0YW5jZW9mIEF1dG9MYXlvdXRSZWdpb25NYW5hZ2VyKSB7XG4gICAgICAgICAgICAgICAgYXV0b2xheW91dExlYWYudmlldy5jb250YWluZXJFbC5hcHBlbmRDaGlsZChlbCk7XG4gICAgICAgICAgICAgICAgcmVxdWlyZVVubG9hZCA9IHRydWVcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5yZWdpb25NYW5hZ2VyLnJlbmRlclJlZ2lvbkVsZW1lbnRzVG9MaXZlUHJldmlldyhjb250ZW50RWxlbWVudCk7XG4gICAgICAgICAgICBmb3IobGV0IGRvbU9iaiBvZiB0aGlzLnJlZ2lvbk1hbmFnZXIuZ2V0UmVnaW9uRGF0YSgpLmRvbUxpc3QpIHtcbiAgICAgICAgICAgICAgICBmaXhMaXN0Q1NTKGRvbU9iai5vcmlnaW5hbEVsZW1lbnQpXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChyZXF1aXJlVW5sb2FkKSB7XG4gICAgICAgICAgICAgICAgYXV0b2xheW91dExlYWYudmlldy5jb250YWluZXJFbC5yZW1vdmVDaGlsZChlbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBmaXhFeHRlcm5hbExpbmtzKGVsKVxuXG4gICAgICAgIGxpdmVQcmV2aWV3RWxlbWVudENhY2hlLnNldCh0aGlzLmVsZW1lbnRDYWNoZUlELCB7XG4gICAgICAgICAgICB0aW1lc3RhbXA6IERhdGUubm93KCksXG4gICAgICAgICAgICBlbGVtZW50OiBlbCxcbiAgICAgICAgICAgIHJlZ2lvbk1hbmFnZXI6IHRoaXMucmVnaW9uTWFuYWdlcixcbiAgICAgICAgICAgIGVycm9yUm9vdEVsOiB0aGlzLmVycm9yUm9vdEVsLFxuICAgICAgICAgICAgY2FjaGVTZXR0aW5nczogdGhpcy5yZWdpb25TZXR0aW5ncyxcbiAgICAgICAgICAgIHBsdWdpblNldHRpbmdzVXBkYXRlVGltZXN0YW1wOiBNQ01fU2V0dGluZ3NNYW5hZ2VyLnNoYXJlZC5sYXN0VXBkYXRlVGltZXN0YW1wXG4gICAgICAgIH0pXG5cbiAgICAgICAgcmV0dXJuIGVsO1xuICAgIH1cblxuICAgIGZpeEVsZW1lbnRDU1MoZG9tT2JqZWN0OiBET01PYmplY3QpIHtcbiAgICAgICAgZml4TGlzdENTUyhkb21PYmplY3Qub3JpZ2luYWxFbGVtZW50KTtcbiAgICB9XG59XG5cbmV4cG9ydCBjbGFzcyBNdWx0aUNvbHVtbk1hcmtkb3duX0RlZmluZWRTZXR0aW5nc19MaXZlUHJldmlld19XaWRnZXQgZXh0ZW5kcyBXaWRnZXRUeXBlIHtcblxuICAgIGNvbnRlbnREYXRhOiBzdHJpbmc7XG5cbiAgICBjb25zdHJ1Y3Rvcihjb250ZW50RGF0YTogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKCk7XG5cbiAgICAgICAgdGhpcy5jb250ZW50RGF0YSA9IGNvbnRlbnREYXRhO1xuICAgIH1cblxuICAgIHRvRE9NKCkge1xuICAgICAgICAvLyBDcmVhdGUgb3VyIGVsZW1lbnQgdG8gaG9sZCBhbGwgb2YgdGhlIGxpdmUgcHJldmlldyBlbGVtZW50cy5cbiAgICAgICAgbGV0IGVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcbiAgICAgICAgZWwuY2xhc3NOYW1lID0gXCJtY20tY20tc2V0dGluZ3MtcHJldmlld1wiO1xuXG4gICAgICAgIGxldCBsYWJlbERpdiA9IGVsLmNyZWF0ZURpdigpXG4gICAgICAgIGxldCBsYWJlbCA9IGxhYmVsRGl2LmNyZWF0ZVNwYW4oe1xuICAgICAgICAgICAgY2xzOiBcIm1jbS1jb2wtc2V0dGluZ3MtcHJldmlld1wiXG4gICAgICAgIH0pXG4gICAgICAgIGxhYmVsLnRleHRDb250ZW50ID0gXCJDb2x1bW4gU2V0dGluZ3M6XCI7XG5cbiAgICAgICAgbGV0IGxpc3QgPSBlbC5jcmVhdGVFbChcInVsXCIpXG4gICAgICAgIGxldCBsaW5lcyA9IHRoaXMuY29udGVudERhdGEuc3BsaXQoXCJcXG5cIilcbiAgICAgICAgZm9yKGxldCBpID0gMTsgaSA8IGxpbmVzLmxlbmd0aCAtIDE7IGkrKykge1xuICAgICAgICAgICAgbGV0IGl0ZW0gPSBsaXN0LmNyZWF0ZUVsKFwibGlcIilcbiAgICAgICAgICAgIGl0ZW0udGV4dENvbnRlbnQgPSBsaW5lc1tpXVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGVsO1xuICAgIH1cbn1cblxuY29uc3QgT0JTSURJQU5fTElWRVBSRVZJRVdfVEFCTEVfQ0xBU1NFUyA9IFwiY20tZW1iZWQtYmxvY2sgbWFya2Rvd24tcmVuZGVyZWQgY20tdGFibGUtd2lkZ2V0IHNob3ctaW5kZW50YXRpb24tZ3VpZGVcIlxuZnVuY3Rpb24gZml4VGFibGVSZW5kZXIoZWw6IEVsZW1lbnQpOiBFbGVtZW50IHtcblxuICAgIGlmKGVsLnRhZ05hbWUgIT09IFwiVEFCTEVcIikge1xuICAgICAgICByZXR1cm4gZWw7XG4gICAgfVxuXG4gICAgbGV0IHBhcmVudERpdiA9IGNyZWF0ZURpdih7XG4gICAgICAgIFwiY2xzXCI6IE9CU0lESUFOX0xJVkVQUkVWSUVXX1RBQkxFX0NMQVNTRVNcbiAgICB9KVxuICAgIHBhcmVudERpdi5hcHBlbmRDaGlsZChlbCk7XG4gICAgcmV0dXJuIHBhcmVudERpdjtcbn1cblxuZnVuY3Rpb24gZml4RmlsZUVtYmVkKGVsOiBFbGVtZW50LCBzb3VyY2U6IHN0cmluZyk6IEVsZW1lbnQge1xuXG4gICAgbGV0IGVtYmVkID0gZ2V0RW1iZWQoZWwpO1xuICAgIGlmKGVtYmVkID09PSBudWxsKSB7XG4gICAgICAgIHJldHVybiBlbDtcbiAgICB9XG5cbiAgICBsZXQgYWx0ID0gZW1iZWQuZ2V0QXR0cihcImFsdFwiKVxuICAgIGxldCBzcmMgPSBlbWJlZC5nZXRBdHRyKFwic3JjXCIpXG4gICAgaWYoc3JjID09PSBudWxsKSB7XG4gICAgICAgIHJldHVybiBlbDtcbiAgICB9XG5cbiAgICBsZXQgZmlsZTogVEZpbGUgPSBhcHAubWV0YWRhdGFDYWNoZS5nZXRGaXJzdExpbmtwYXRoRGVzdChzcmMsIHNvdXJjZSk7XG4gICAgaWYoZmlsZSA9PT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gZWw7XG4gICAgfVxuICAgIFxuICAgIGlmKGlzTURFeHRlbnNpb24oZmlsZS5leHRlbnNpb24pID09PSBmYWxzZSkge1xuICAgICAgICByZXR1cm4gZWw7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNyZWF0ZUxQRXJyb3JFbGVtZW50KFwiRmlsZSBlbWJlZHMgYXJlIG5vdCBzdXBwb3J0ZWQgaW4gTGl2ZSBQcmV2aWV3LlxcblBsZWFzZSB1c2UgcmVhZGluZyBtb2RlIHRvIHZpZXcuXCIsIGFsdCwgc3JjKTtcbn1cblxuZnVuY3Rpb24gY3JlYXRlTFBFcnJvckVsZW1lbnQoZXJyb3JUZXh0OiBzdHJpbmcsIGFsdDogc3RyaW5nID0gXCJcIiwgc3JjOiBzdHJpbmcgPSBcIlwiKTogSFRNTERpdkVsZW1lbnQge1xuICAgIGxldCBlcnJvckVsID0gY3JlYXRlRGl2KHtcbiAgICAgICAgY2xzOiBcImludGVybmFsLWVtYmVkIG1hcmtkb3duLWVtYmVkIGlubGluZS1lbWJlZCBpcy1sb2FkZWRcIixcbiAgICAgICAgYXR0cjoge1xuICAgICAgICAgICAgXCJ0YWJpbmRleFwiOiBcIi0xXCIsXG4gICAgICAgICAgICBcImNvbnRlbnRlZGl0YWJsZVwiOiBcImZhbHNlXCJcbiAgICAgICAgfVxuICAgIH0pXG4gICAgZXJyb3JFbC5zZXRBdHRyKFwiYWx0XCIsIGFsdCk7XG4gICAgZXJyb3JFbC5zZXRBdHRyKFwic3JjXCIsIGBhcHA6Ly9vYnNpZGlhbi5tZC8ke3NyY31gKVxuICAgIGVycm9yRWwuYXBwZW5kQ2hpbGQoY3JlYXRlRGl2KFxuICAgICAgICB7XG4gICAgICAgICAgICBcImNsc1wiOiBcImVtYmVkLXRpdGxlIG1hcmtkb3duLWVtYmVkLXRpdGxlXCIsXG4gICAgICAgIH1cbiAgICApKTtcbiAgICBsZXQgY29udGVudEVsID0gZXJyb3JFbC5jcmVhdGVEaXYoe1xuICAgICAgICBcImNsc1wiOiBgbWFya2Rvd24tZW1iZWQtY29udGVudGAsXG4gICAgfSk7XG4gICAgbGV0IHBhcmFncmFwaCA9IGNvbnRlbnRFbC5jcmVhdGVFbChcInBcIiwge1xuICAgICAgICBcImNsc1wiOiBgJHtNdWx0aUNvbHVtblN0eWxlQ1NTLlJlZ2lvbkVycm9yTWVzc2FnZX0sICR7TXVsdGlDb2x1bW5TdHlsZUNTUy5TbWFsbEZvbnR9YFxuICAgIH0pO1xuICAgIHBhcmFncmFwaC5pbm5lclRleHQgPSBlcnJvclRleHQ7XG5cbiAgICByZXR1cm4gZXJyb3JFbFxufVxuXG5mdW5jdGlvbiBmaXhQREZSZW5kZXIoZWw6IEVsZW1lbnQsIHNvdXJjZTogc3RyaW5nKTogRWxlbWVudCB7XG5cbiAgICBsZXQgZW1iZWQgPSBnZXRFbWJlZChlbCk7XG4gICAgaWYoZW1iZWQgPT09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIGVsO1xuICAgIH1cblxuICAgIGxldCBhbHQgPSBlbWJlZC5nZXRBdHRyKFwiYWx0XCIpXG4gICAgbGV0IHNyYyA9IGVtYmVkLmdldEF0dHIoXCJzcmNcIilcbiAgICBpZihzcmMgPT09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIGVsO1xuICAgIH1cblxuICAgIGxldCBmaWxlOiBURmlsZSA9IGFwcC5tZXRhZGF0YUNhY2hlLmdldEZpcnN0TGlua3BhdGhEZXN0KHNyYywgc291cmNlKTtcbiAgICBpZihmaWxlID09PSBudWxsKSB7XG4gICAgICAgIHJldHVybiBlbDtcbiAgICB9XG4gICAgXG4gICAgaWYoaXNQREZFeHRlbnNpb24oZmlsZS5leHRlbnNpb24pID09PSBmYWxzZSkge1xuICAgICAgICByZXR1cm4gZWw7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNyZWF0ZUxQRXJyb3JFbGVtZW50KFwiRHVlIHRvIGFuIHVwZGF0ZSB0byBPYnNpZGlhbidzIFBERiB2aWV3ZXIsIFBERiBlbWJlZHMgYXJlIGN1cnJlbnRseSBub3Qgc3VwcG9ydGVkLlxcblNvcnJ5IGZvciB0aGUgaW5jb252aWVuZW5jZS5cIiwgYWx0LCBzcmMpO1xufVxuXG5mdW5jdGlvbiBmaXhJbWFnZVJlbmRlcihlbDogRWxlbWVudCwgc291cmNlOiBzdHJpbmcpOiBFbGVtZW50IHtcblxuICAgIGxldCBlbWJlZCA9IGdldEVtYmVkKGVsKTtcbiAgICBpZihlbWJlZCA9PT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gZWw7XG4gICAgfVxuXG4gICAgbGV0IGN1c3RvbVdpZHRoID0gZW1iZWQuYXR0cmlidXRlcy5nZXROYW1lZEl0ZW0oXCJ3aWR0aFwiKVxuICAgIGxldCBhbHQgPSBlbWJlZC5nZXRBdHRyKFwiYWx0XCIpXG4gICAgbGV0IHNyYyA9IGVtYmVkLmdldEF0dHIoXCJzcmNcIilcbiAgICBpZihzcmMgPT09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIGVsO1xuICAgIH1cblxuICAgIGxldCBmaWxlOiBURmlsZSA9IGFwcC5tZXRhZGF0YUNhY2hlLmdldEZpcnN0TGlua3BhdGhEZXN0KHNyYywgc291cmNlKTtcbiAgICBpZihmaWxlID09PSBudWxsKSB7XG4gICAgICAgIHJldHVybiBlbDtcbiAgICB9XG4gICAgXG4gICAgLy8gSWYgdGhlIGxpbmsgc291cmNlIGlzIG5vdCBhbiBpbWFnZSB3ZSBkb250IHdhbnQgdG8gbWFrZSBhbnkgYWRqdXN0bWVudHMuXG4gICAgaWYoaXNJbWFnZUV4dGVuc2lvbihmaWxlLmV4dGVuc2lvbikgPT09IGZhbHNlKSB7XG4gICAgICAgIHJldHVybiBlbDtcbiAgICB9XG5cbiAgICBsZXQgZml4ZWRFbCA9IGNyZWF0ZURpdih7XG4gICAgICAgIGNsczogXCJpbnRlcm5hbC1lbWJlZCBpbWFnZS1lbWJlZCBpcy1sb2FkZWRcIixcbiAgICB9KVxuICAgIGZpeGVkRWwuc2V0QXR0cihcImFsdFwiLCBhbHQpO1xuXG4gICAgbGV0IHJlc291cmNlUGF0aCA9IGFwcC52YXVsdC5nZXRSZXNvdXJjZVBhdGgoZmlsZSk7XG4gICAgbGV0IGltYWdlID0gZml4ZWRFbC5jcmVhdGVFbChcImltZ1wiKTtcbiAgICBpbWFnZS5zZXRBdHRyKFwic3JjXCIsIHJlc291cmNlUGF0aCk7XG5cbiAgICBpZihjdXN0b21XaWR0aCAhPT0gbnVsbCkge1xuICAgICAgICBpbWFnZS5zZXRBdHRyKFwid2lkdGhcIiwgY3VzdG9tV2lkdGgudmFsdWUpO1xuICAgIH1cblxuICAgIHJldHVybiBmaXhlZEVsO1xufVxuXG5mdW5jdGlvbiBmaXhFeHRlcm5hbExpbmtzKGVsOiBFbGVtZW50KTogRWxlbWVudCB7XG5cbiAgICBsZXQgaXRlbXMgPSBlbC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKFwiZXh0ZXJuYWwtbGlua1wiKTtcbiAgICBmb3IobGV0IGxpbmtFbCBvZiBBcnJheS5mcm9tKGl0ZW1zKSkge1xuXG4gICAgICAgIGxldCBsaW5rID0gbGlua0VsIGFzIEhUTUxFbGVtZW50O1xuICAgICAgICBpZihsaW5rID09PSB1bmRlZmluZWQgfHxcbiAgICAgICAgICAgbGluayA9PT0gbnVsbCApIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVtb3ZlIHRoZSBocmVmIGZyb20gdGhlIGxpbmsgYW5kIHNldHVwIGFuIGV2ZW50IGxpc3RlbmVyIHRvIG9wZW4gdGhlIGxpbmsgaW4gdGhlIGRlZmF1bHQgYnJvd3Nlci5cbiAgICAgICAgbGV0IGhyZWYgPSBsaW5rLmdldEF0dHIoXCJocmVmXCIpXG4gICAgICAgIGxpbmsucmVtb3ZlQXR0cmlidXRlKFwiaHJlZlwiKTtcblxuICAgICAgICBsaW5rLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCAoZXYpID0+IHtcblxuICAgICAgICAgICAgd2luZG93Lm9wZW4oaHJlZik7IFxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBpdGVtcyA9IGVsLmdldEVsZW1lbnRzQnlDbGFzc05hbWUoXCJpbnRlcm5hbC1saW5rXCIpO1xuICAgIGZvcihsZXQgbGlua0VsIG9mIEFycmF5LmZyb20oaXRlbXMpKSB7XG5cbiAgICAgICAgbGV0IGxpbmsgPSBsaW5rRWwgYXMgSFRNTEVsZW1lbnQ7XG4gICAgICAgIGlmKGxpbmsgPT09IHVuZGVmaW5lZCB8fFxuICAgICAgICAgICBsaW5rID09PSBudWxsICkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBSZW1vdmluZyB0aGUgaHJlZiBmcm9tIGludGVybmFsIGxpbmtzIGlzIGFsbCB0aGF0IHNlZW1zIHRvIGJlIHJlcXVpcmVkIHRvIGZpeCB0aGUgb25jbGljay5cbiAgICAgICAgbGluay5yZW1vdmVBdHRyaWJ1dGUoXCJocmVmXCIpO1xuICAgIH1cblxuICAgIHJldHVybiBlbDtcbn1cblxuZnVuY3Rpb24gZ2V0RW1iZWQoZWw6IEVsZW1lbnQpOiBFbGVtZW50IHwgbnVsbCB7XG5cbiAgICAvLyBlbWJlZHMgY2FuIGVpdGhlciBiZSBhIDxkaXYgY2xhc3M9XCJpbnRlcm5hbC1lbWJlZFwiIG9yIDxwPjxkaXYgY2xhc3M9XCJpbnRlcm5hbC1lbWJlZFwiXG4gICAgLy8gZGVwZW5kaW5nIG9uIHRoZSBzeW50YXggdGhpcyBhZGRpdGlvbmFsIGNoZWNrIGlzIHRvIGZpeCBmYWxzZSBuZWdhdGl2ZXMgd2hlbiBlbWJlZCBpc1xuICAgIC8vIHRoZSBmaXJzdCBjYXNlLlxuICAgIGlmKGVsLmhhc0NsYXNzKFwiaW50ZXJuYWwtZW1iZWRcIikpIHtcbiAgICAgICAgcmV0dXJuIGVsO1xuICAgIH1cbiAgICBlbHNlIHtcblxuICAgICAgICBsZXQgaXRlbXMgPSBlbC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKFwiaW50ZXJuYWwtZW1iZWRcIik7XG4gICAgICAgIGlmKGl0ZW1zLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgICAgcmV0dXJuIGl0ZW1zWzBdO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG59XG5cbmZ1bmN0aW9uIGlzSW1hZ2VFeHRlbnNpb24oZXh0ZW5zaW9uOiBzdHJpbmcpOiBib29sZWFuIHtcblxuICAgIGV4dGVuc2lvbiA9IGV4dGVuc2lvbi50b0xvd2VyQ2FzZSgpO1xuICAgIHN3aXRjaChleHRlbnNpb24pIHtcbiAgICAgICAgY2FzZSBcInBuZ1wiOlxuICAgICAgICBjYXNlIFwianBnXCI6XG4gICAgICAgIGNhc2UgXCJqcGVnXCI6XG4gICAgICAgIGNhc2UgXCJnaWZcIjpcbiAgICAgICAgY2FzZSBcImJtcFwiOlxuICAgICAgICBjYXNlIFwic3ZnXCI6XG4gICAgICAgIGNhc2UgXCJ3ZWJwXCI6XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBpc1BERkV4dGVuc2lvbihleHRlbnNpb246IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBleHRlbnNpb24udG9Mb3dlckNhc2UoKSA9PT0gXCJwZGZcIjtcbn1cblxuZnVuY3Rpb24gaXNNREV4dGVuc2lvbihleHRlbnNpb246IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBleHRlbnNpb24udG9Mb3dlckNhc2UoKSA9PT0gXCJtZFwiO1xufVxuXG5mdW5jdGlvbiBmaXhMaXN0Q1NTKGVsOiBFbGVtZW50KTogRWxlbWVudCB7XG4gICAgaWYoZWwudGFnTmFtZSAhPT0gXCJVTFwiICYmIGVsLnRhZ05hbWUgIT09IFwiT0xcIikge1xuICAgICAgICByZXR1cm4gZWxcbiAgICB9XG4gICAgZWwucGFyZW50RWxlbWVudD8uYWRkQ2xhc3MoT2JzaWRpYW5TdHlsZUNTUy5SZW5kZXJlZE1hcmtkb3duKVxuICAgIHJldHVybiBlbDtcbn1cblxuZnVuY3Rpb24gZml4VW5TdXBwb3J0ZWRSZW5kZXIoZWw6IEVsZW1lbnQpOiBFbGVtZW50IHtcblxuICAgIGlmKGlzVGFza3NQbHVnaW4oZWwgYXMgSFRNTEVsZW1lbnQpKSB7XG5cbiAgICAgICAgaWYoTUNNX1NldHRpbmdzTWFuYWdlci5zaGFyZWQucmVuZGVySW5saW5lRWxFcnJvcnMgPT09IHRydWUpIHtcbiAgICAgICAgICAgIGxldCBmaXhlZEVsID0gY3JlYXRlRGl2KClcbiAgICAgICAgICAgIGxldCBwYXJhZ3JhcGggPSBmaXhlZEVsLmNyZWF0ZUVsKFwicFwiLCB7XG4gICAgICAgICAgICAgICAgXCJjbHNcIjogYCR7TXVsdGlDb2x1bW5TdHlsZUNTUy5SZWdpb25FcnJvck1lc3NhZ2V9ICR7TXVsdGlDb2x1bW5TdHlsZUNTUy5TbWFsbEZvbnR9YFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBwYXJhZ3JhcGguaW5uZXJUZXh0ID0gXCJUaGUgVGFza3MgcGx1Z2luIGlzIG5vdCBzdXBwb3J0ZWQgaW4gTGl2ZSBQcmV2aWV3LlxcblBsZWFzZSB1c2UgcmVhZGluZyBtb2RlLlwiXG4gICAgICAgICAgICByZXR1cm4gZml4ZWRFbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZWw7XG4gICAgfVxuXG4gICAgcmV0dXJuIGVsO1xufVxuXG5mdW5jdGlvbiBjaGVja0ZvckNvbHVtbkJyZWFrRXJyb3JzKGRvbU9iamVjdDogRE9NT2JqZWN0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmV2aW91c1RleHQ6IHN0cmluZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd29ya2luZ1RleHQ6IHN0cmluZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNYW5hZ2VyOiBSZWdpb25FcnJvck1hbmFnZXIpOiBzdHJpbmcge1xuXG4gICAgaWYoZG9tT2JqZWN0LnRhZyAhPT0gRE9NT2JqZWN0VGFnLmNvbHVtbkJyZWFrICYmXG4gICAgICAgIGRvbU9iamVjdC5lbGVtZW50SXNDb2x1bW5CcmVhayA9PT0gRWxlbWVudENvbHVtbkJyZWFrVHlwZS5ub25lKSB7XG4gICAgICAgIHJldHVybiB3b3JraW5nVGV4dDtcbiAgICB9XG5cbiAgICBsZXQgcHJldkxpbmUgPSBwcmV2aW91c1RleHQuc3BsaXQoXCJcXG5cIikuc2xpY2UoLTIpLmpvaW4oXCJcXG5cIilcbiAgICBsZXQgY2hlY2tUZXh0ID0gd29ya2luZ1RleHQ7XG4gICAgaWYoY2hlY2tGb3JQYXJhZ3JhcGhJbm5lckNvbEVuZFRhZyhwcmV2TGluZSkpIHtcbiAgICAgICAgY2hlY2tUZXh0ID0gcHJldkxpbmUgKyB3b3JraW5nVGV4dFxuICAgIH1cblxuICAgIGxldCBuZXh0Q29sQnJlYWsgPSBjaGVja0ZvclBhcmFncmFwaElubmVyQ29sRW5kVGFnKGNoZWNrVGV4dClcbiAgICBpZihuZXh0Q29sQnJlYWsgPT09IG51bGwpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihcIkVycm9yLiBTb21ldGhpbmcgd2VudCB3cm9uZyBwYXJzaW5nIGNvbHVtbiBicmVhayBvdXQgb2YgdGV4dC5cIilcbiAgICAgICAgcmV0dXJuIHdvcmtpbmdUZXh0O1xuICAgIH1cblxuICAgIGxldCBzdGFydEluZGV4ID0gbmV4dENvbEJyZWFrLmluZGV4XG4gICAgbGV0IG1hdGNoTGVuZ3RoID0gbmV4dENvbEJyZWFrWzBdLmxlbmd0aFxuICAgIGxldCBlbmRJbmRleCA9IHN0YXJ0SW5kZXggKyBtYXRjaExlbmd0aFxuICAgIGxldCBtYXRjaFRleHQgPSBuZXh0Q29sQnJlYWtbMF0udHJpbSgpO1xuXG4gICAgbGV0IG5ld1dvcmtpbmdUZXh0ID0gY2hlY2tUZXh0LnNsaWNlKGVuZEluZGV4KVxuXG4gICAgLy8gQWxyZWFkeSBwYXJzZWQgY29sdW1uIGJyZWFrIHdhcm5pbmcuXG4gICAgaWYoZG9tT2JqZWN0LmVsZW1lbnRJc0NvbHVtbkJyZWFrICE9PSBFbGVtZW50Q29sdW1uQnJlYWtUeXBlLm5vbmUpIHtcblxuICAgICAgICBwYXJzZUNvbEJyZWFrRXJyb3JUeXBlKHtcbiAgICAgICAgICAgIGxpbmVBYm92ZTogXCJcIixcbiAgICAgICAgICAgIGxpbmVCZWxvdzogXCJcIixcbiAgICAgICAgICAgIG9iamVjdFRhZzogRE9NT2JqZWN0VGFnLm5vbmUsXG4gICAgICAgICAgICBjb2xCcmVha1R5cGU6IGRvbU9iamVjdC5lbGVtZW50SXNDb2x1bW5CcmVha1xuICAgICAgICB9LCBlcnJvck1hbmFnZXIpXG5cbiAgICAgICAgcmV0dXJuIG5ld1dvcmtpbmdUZXh0O1xuICAgIH1cblxuICAgIC8vIE5vdyB3ZSBoYXZlIGEgc3RhbmRhcmQgY29sdW1uIGJyZWFrIGJ1dCBkdWUgdG8gY2hhbmdlcyBpbiBvYnNpZGlhbiBwYXJzaW5nIG1heSBzdGlsbCBcbiAgICAvLyByZXF1aXJlIGRpc3BsYXlpbmcgYW4gZXJyb3IgbWVzc2FnZS5cbiAgICBsZXQgZW5kVGFnVGV4dCA9IGRvbU9iamVjdC5vcmlnaW5hbEVsZW1lbnQuaW5uZXJUZXh0XG5cbiAgICAvLyBtYWtlIHN1cmUgdGhlIGVsZW1lbnQgdGV4dCBpcyBhIGNvbHVtbiBicmVhayBqdXN0IHRvIGJlIHN1cmUuIFRoaXMgcmVhbGx5IHNob3VsZCBuZXZlciBmYWlsLlxuICAgIGlmKGNvbnRhaW5zQ29sRW5kVGFnKGVuZFRhZ1RleHQpID09PSBmYWxzZSkge1xuICAgICAgICAvLyBJZiBzb21ldGhpbmcgd2VudCB3cm9uZyBoZXJlIHdlIGNhbiBub3QgcHJvY2VlZCB3aXRoIHRoZSBuZXh0IHJlZ2V4IHVubGVzcyB0aGlzIHBhc3Nlcy5cbiAgICAgICAgY29uc29sZS5lcnJvcihcIkVycm9yIHBhcnNpbmcgY29sdW1uLWJyZWFrIHRhZyBiYWNrIG91dCBvZiBlbGVtZW50IHRleHQuXCIsIGVuZFRhZ1RleHQpXG4gICAgICAgIHJldHVybiB3b3JraW5nVGV4dDtcbiAgICB9XG5cbiAgICAvLyBtYWtlIHN1cmUgdGhlIHRleHQgb2YgdGhlIGVsZW1lbnQgbWF0Y2hlIHRoZSBzeW50YXggb2Ygd2hhdCB3ZSBwYXJzZWQgZnJvbSB0aGUgdGV4dC5cbiAgICBpZihtYXRjaFRleHQgIT09IGVuZFRhZ1RleHQpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihcIkVycm9yIG1hdGNoaW5nIG5leHQgY29sLWJyZWFrIHRvIGN1cnJlbnQgZWxlbWVudC4gQ2FuIG5vdCBjb250aW51ZS5cIilcbiAgICAgICAgcmV0dXJuIHdvcmtpbmdUZXh0O1xuICAgIH1cblxuICAgIC8vIFNsaWNlIG91dCB0aGUgMjAgY2hhcmFjdGVycyBiZWZvcmUgYW5kIGFmdGVyIHRoZSBjb2x1bW4gYnJlYWsgYW5kIHRoZW4gZ2V0IGp1c3RcbiAgICAvLyB0aGUgb25lIGxpbmUgYmVmb3JlIGFuZCBhZnRlciB0byBjaGVjayBpZiBlcnJvciBtZXNzYWdlIHJlcXVpcmVkLlxuICAgIGxldCBzdGFydEluZGV4T2Zmc2V0ID0gTWF0aC5jbGFtcChzdGFydEluZGV4IC0gMjAsIDAsIHN0YXJ0SW5kZXgpO1xuICAgIGxldCBlbmRJbmRleE9mZnNldCA9IE1hdGguY2xhbXAoZW5kSW5kZXggKyAyMCwgZW5kSW5kZXgsIGNoZWNrVGV4dC5sZW5ndGggLSAxKTtcbiAgICBcbiAgICBsZXQgYWRkaXRpb25hbFRleHQgPSBjaGVja1RleHQuc2xpY2Uoc3RhcnRJbmRleE9mZnNldCwgZW5kSW5kZXhPZmZzZXQpO1xuICAgIGxldCB0ZXh0QmVmb3JlID0gYWRkaXRpb25hbFRleHQuc2xpY2UoMCwgMjApO1xuICAgIGxldCB0ZXh0QWZ0ZXIgPSBhZGRpdGlvbmFsVGV4dC5zbGljZSgyMCArIG1hdGNoTGVuZ3RoKVxuICAgIHRleHRCZWZvcmUgPSB0ZXh0QmVmb3JlLnJlcGxhY2UoZW5kVGFnVGV4dCwgXCJcIilcblxuICAgIGxldCBsaW5lc0Fib3ZlID0gdGV4dEJlZm9yZS5zcGxpdChcIlxcblwiKS5maWx0ZXIoKHZhbCkgPT4ge1xuICAgICAgICByZXR1cm4gdmFsICE9PSBcIlwiXG4gICAgfSlcbiAgICBsZXQgbGluZXNCZWxvdyA9IHRleHRBZnRlci5zcGxpdChcIlxcblwiKS5maWx0ZXIoKHZhbCkgPT4ge1xuICAgICAgICByZXR1cm4gdmFsICE9PSBcIlwiXG4gICAgfSlcbiAgICBpZihsaW5lc0Fib3ZlLmxlbmd0aCA9PT0gMCAmJiBsaW5lc0JlbG93Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgICByZXR1cm4gd29ya2luZ1RleHRcbiAgICB9XG5cbiAgICBsZXQgbGluZUFib3ZlID0gbGluZXNBYm92ZS5sYXN0KClcbiAgICBsZXQgbGluZUJlbG93ID0gbGluZXNCZWxvdy5maXJzdCgpXG4gICAgcGFyc2VDb2xCcmVha0Vycm9yVHlwZSh7XG4gICAgICAgIGxpbmVBYm92ZTogbGluZUFib3ZlLFxuICAgICAgICBsaW5lQmVsb3c6IGxpbmVCZWxvdyxcbiAgICAgICAgb2JqZWN0VGFnOiBET01PYmplY3RUYWcuY29sdW1uQnJlYWssXG4gICAgICAgIGNvbEJyZWFrVHlwZTogRWxlbWVudENvbHVtbkJyZWFrVHlwZS5ub25lXG4gICAgfSwgZXJyb3JNYW5hZ2VyKVxuXG4gICAgcmV0dXJuIG5ld1dvcmtpbmdUZXh0XG59XG5cbmZ1bmN0aW9uIHNsaWNlV29ya2luZ1RleHRUb0VsKGRvbU9iamVjdDogRE9NT2JqZWN0LCBwcmV2aW91c1RleHQ6IHN0cmluZywgd29ya2luZ1RleHQ6IHN0cmluZyk6IHtwcmV2aW91c1RleHQ6IHN0cmluZywgd29ya2luZ1RleHQ6IHN0cmluZ30ge1xuXG4gICAgZnVuY3Rpb24gcHJvY2Vzc1BhcmFncmFwaCgpIHtcbiAgICAgICAgbGV0IHJlZ2V4ID0gbmV3IFJlZ0V4cChgXiAqJHtlc2NhcGVSZWdFeHAoZG9tT2JqZWN0Lm9yaWdpbmFsRWxlbWVudC50ZXh0Q29udGVudCl9ICokYCwgXCJtXCIpXG4gICAgICAgIGxldCByZXN1bHQgPSByZWdleC5leGVjKHdvcmtpbmdUZXh0KVxuICAgICAgICBpZihyZXN1bHQpIHtcbiAgICAgICAgICAgIGxldCB1cGRhdGVkUHJldmlvdXMgPSBwcmV2aW91c1RleHQgKyB3b3JraW5nVGV4dC5zbGljZSgwLCByZXN1bHQuaW5kZXgpO1xuICAgICAgICAgICAgbGV0IHVwZGF0ZWRJdGVtVGV4dCA9IHdvcmtpbmdUZXh0LnNsaWNlKHJlc3VsdC5pbmRleCwgcmVzdWx0LmluZGV4ICsgcmVzdWx0WzBdLmxlbmd0aClcbiAgICAgICAgICAgIGxldCB1cGRhdGVkV29ya2luZ1RleHQgPSB3b3JraW5nVGV4dC5zbGljZShyZXN1bHQuaW5kZXgpXG4gICAgICAgICAgICByZXR1cm4geyBcbiAgICAgICAgICAgICAgICBwcmV2aW91c1RleHQ6IHVwZGF0ZWRQcmV2aW91cyxcbiAgICAgICAgICAgICAgICB3b3JraW5nVGV4dDogdXBkYXRlZFdvcmtpbmdUZXh0XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7IFxuICAgICAgICAgICAgcHJldmlvdXNUZXh0OiBwcmV2aW91c1RleHQsXG4gICAgICAgICAgICB3b3JraW5nVGV4dDogd29ya2luZ1RleHRcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwcm9jZXNzSGVhZGVyKCkge1xuICAgICAgICBsZXQgY291bnQgPSBwYXJzZUludChkb21PYmplY3Qub3JpZ2luYWxFbGVtZW50LnRhZ05hbWUuc2xpY2UoMSkpXG4gICAgICAgIGxldCB0ZXh0ID0gJyMnLnJlcGVhdChjb3VudCk7XG5cbiAgICAgICAgbGV0IHJlZ2V4ID0gbmV3IFJlZ0V4cChgXiR7dGV4dH0gKyR7ZXNjYXBlUmVnRXhwKGRvbU9iamVjdC5vcmlnaW5hbEVsZW1lbnQudGV4dENvbnRlbnQpfSAqJGAsIFwibVwiKVxuXG4gICAgICAgIGxldCByZXN1bHQgPSByZWdleC5leGVjKHdvcmtpbmdUZXh0KVxuICAgICAgICBpZihyZXN1bHQpIHtcbiAgICAgICAgICAgIGxldCB1cGRhdGVkUHJldmlvdXMgPSBwcmV2aW91c1RleHQgKyB3b3JraW5nVGV4dC5zbGljZSgwLCByZXN1bHQuaW5kZXgpO1xuICAgICAgICAgICAgbGV0IHVwZGF0ZWRJdGVtVGV4dCA9IHdvcmtpbmdUZXh0LnNsaWNlKHJlc3VsdC5pbmRleCwgcmVzdWx0LmluZGV4ICsgcmVzdWx0WzBdLmxlbmd0aClcbiAgICAgICAgICAgIGxldCB1cGRhdGVkV29ya2luZ1RleHQgPSB3b3JraW5nVGV4dC5zbGljZShyZXN1bHQuaW5kZXgpXG4gICAgICAgICAgICByZXR1cm4geyBcbiAgICAgICAgICAgICAgICBwcmV2aW91c1RleHQ6IHVwZGF0ZWRQcmV2aW91cyxcbiAgICAgICAgICAgICAgICB3b3JraW5nVGV4dDogdXBkYXRlZFdvcmtpbmdUZXh0XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7IFxuICAgICAgICAgICAgcHJldmlvdXNUZXh0OiBwcmV2aW91c1RleHQsXG4gICAgICAgICAgICB3b3JraW5nVGV4dDogd29ya2luZ1RleHRcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBpZihkb21PYmplY3Qub3JpZ2luYWxFbGVtZW50LnRhZ05hbWUgPT09IFwiUFwiKSB7XG4gICAgICAgIHJldHVybiBwcm9jZXNzUGFyYWdyYXBoKCk7XG4gICAgfVxuXG4gICAgaWYoZG9tT2JqZWN0Lm9yaWdpbmFsRWxlbWVudC50YWdOYW1lID09PSBcIkgxXCIgfHxcbiAgICAgICBkb21PYmplY3Qub3JpZ2luYWxFbGVtZW50LnRhZ05hbWUgPT09IFwiSDJcIiB8fFxuICAgICAgIGRvbU9iamVjdC5vcmlnaW5hbEVsZW1lbnQudGFnTmFtZSA9PT0gXCJIM1wiIHx8XG4gICAgICAgZG9tT2JqZWN0Lm9yaWdpbmFsRWxlbWVudC50YWdOYW1lID09PSBcIkg0XCIgfHxcbiAgICAgICBkb21PYmplY3Qub3JpZ2luYWxFbGVtZW50LnRhZ05hbWUgPT09IFwiSDVcIikge1xuICAgICAgICByZXR1cm4gcHJvY2Vzc0hlYWRlcigpO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAgIHByZXZpb3VzVGV4dDogcHJldmlvdXNUZXh0LFxuICAgICAgICB3b3JraW5nVGV4dDogd29ya2luZ1RleHRcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGF0dGVtcHRUb0ZpeENoZWNrYm94ZXMoZG9tT2JqZWN0OiBET01PYmplY3QsIHRleHRCZWZvcmVFbGVtZW50OiBzdHJpbmcsIHRleHRPZkVsZW1lbnRBbmRBZnRlcjogc3RyaW5nLCBzb3VyY2VGaWxlOiBURmlsZSwgY2FjaGVJRDogc3RyaW5nKSB7XG5cbiAgICBpZihkb21PYmplY3Qub3JpZ2luYWxFbGVtZW50LnRhZ05hbWUgIT09IFwiVUxcIikge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgcHJldmlvdXNUZXh0OiB0ZXh0QmVmb3JlRWxlbWVudCxcbiAgICAgICAgICAgIHdvcmtpbmdUZXh0OiB0ZXh0T2ZFbGVtZW50QW5kQWZ0ZXJcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZihkb21PYmplY3Qub3JpZ2luYWxFbGVtZW50Lmhhc0NsYXNzKFwiY29udGFpbnMtdGFzay1saXN0XCIpID09PSBmYWxzZSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgcHJldmlvdXNUZXh0OiB0ZXh0QmVmb3JlRWxlbWVudCxcbiAgICAgICAgICAgIHdvcmtpbmdUZXh0OiB0ZXh0T2ZFbGVtZW50QW5kQWZ0ZXJcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGxldCBsaXN0SXRlbXMgPSBBcnJheS5mcm9tKGRvbU9iamVjdC5vcmlnaW5hbEVsZW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoXCJsaVwiKSkuZmlsdGVyKChpdGVtKSA9PiB7XG4gICAgICAgIHJldHVybiBpdGVtLmhhc0NsYXNzKFwidGFzay1saXN0LWl0ZW1cIilcbiAgICB9KVxuXG4gICAgbGV0IHdvcmtpbmdUZXh0QmVmb3JlID0gdGV4dEJlZm9yZUVsZW1lbnQ7XG4gICAgbGV0IHdvcmtpbmdUZXh0ID0gdGV4dE9mRWxlbWVudEFuZEFmdGVyO1xuICAgIGZvcihsZXQgbGlzdEVsZW1lbnQgb2YgbGlzdEl0ZW1zKSB7XG5cbiAgICAgICAgbGV0IHBvc3NpYmxlQ2hlY2tib3ggPSBsaXN0RWxlbWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZShcImlucHV0XCIpO1xuICAgICAgICBpZihwb3NzaWJsZUNoZWNrYm94Lmxlbmd0aCAhPT0gMSkge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkVycm9yOiBDb3VsZCBub3QgZ2V0IGlucHV0IGZvciB0YXNrIGl0ZW0uXCIpXG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBjaGVja2JveCA9IHBvc3NpYmxlQ2hlY2tib3hbMF07XG4gICAgICAgIGlmKGNoZWNrYm94LmdldEF0dHIoXCJ0eXBlXCIpICE9PSBcImNoZWNrYm94XCIpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJFcnJvcjogQ2hlY2tib3ggbm90IG9mIHByb3BlciB0eXBlXCIpO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZihjaGVja2JveC5oYXNDbGFzcyhcInRhc2stbGlzdC1pdGVtLWNoZWNrYm94XCIpID09PSBmYWxzZSkge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkVycm9yOiBDaGVja2JveCBpcyBtaXNzaW5nIHByb3BlciBjbGFzcy5cIilcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoY2hlY2tib3gub25jbGljayAhPT0gbnVsbCkge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkVycm9yOiBPbkNsaWNrIGFyZWFkeSBkZWZpbmVkLCBub3Qgb3ZlcndyaXRpbmcgbWV0aG9kLlwiKTtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGNoZWNrYm94SXNDaGVja2VkID0gbGlzdEVsZW1lbnQuZ2V0QXR0cihcImRhdGEtdGFza1wiKSA9PT0gXCJ4XCIgfHwgbGlzdEVsZW1lbnQuZ2V0QXR0cihcImRhdGEtdGFza1wiKSA9PT0gXCJYXCJcblxuICAgICAgICBsZXQgY2hlY2tib3hUZXh0UmVnZXhTZWFyY2ggPSBSZWdFeHAoYF4oICopLSggKylcXFxcWyR7Y2hlY2tib3hJc0NoZWNrZWQgPyBcIlt4WF1cIiA6IFwiICpcIn1cXFxcXSggKykke2VzY2FwZVJlZ0V4cChsaXN0RWxlbWVudC5pbm5lclRleHQpfSggKikkYCwgXCJtXCIpO1xuICAgICAgICBsZXQgY2hlY2tib3hUZXh0UmVnZXhSZXN1bHQgPSBjaGVja2JveFRleHRSZWdleFNlYXJjaC5leGVjKHdvcmtpbmdUZXh0KTtcbiAgICAgICAgaWYoY2hlY2tib3hUZXh0UmVnZXhSZXN1bHQgPT09IG51bGwpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJDb3VsZCBub3QgZmluZCB0ZXh0IGluIHByb3ZpZGVkIGRvY3VtZW50LlwiKTtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHN0YXJ0T2ZFbGVtZW50SW5kZXggPSBjaGVja2JveFRleHRSZWdleFJlc3VsdC5pbmRleFxuICAgICAgICBsZXQgZW5kT2ZFbGVtZW50SW5kZXggPSBzdGFydE9mRWxlbWVudEluZGV4ICsgY2hlY2tib3hUZXh0UmVnZXhSZXN1bHRbMF0ubGVuZ3RoXG4gICAgICAgIGxldCBuZXdUZXh0QWZ0ZXIgPSB3b3JraW5nVGV4dC5zbGljZShlbmRPZkVsZW1lbnRJbmRleCk7XG4gICAgICAgIGxldCBvbkNsaWNrTmV3VGV4dEFmdGVyID0gbmV3VGV4dEFmdGVyO1xuXG4gICAgICAgIHdvcmtpbmdUZXh0QmVmb3JlID0gd29ya2luZ1RleHRCZWZvcmUgKyB3b3JraW5nVGV4dC5zbGljZSgwLCBzdGFydE9mRWxlbWVudEluZGV4KTtcbiAgICAgICAgbGV0IG9uQ2xpY2tOZXdUZXh0QmVmb3JlID0gd29ya2luZ1RleHRCZWZvcmU7XG5cbiAgICAgICAgd29ya2luZ1RleHQgPSB3b3JraW5nVGV4dC5zbGljZShzdGFydE9mRWxlbWVudEluZGV4KVxuICAgICAgICBsZXQgb25DbGlja05ld1dvcmtpbmdUZXh0ID0gd29ya2luZ1RleHQ7XG5cbiAgICAgICAgbGV0IHNwYWNlQmVmb3JlRGFzaCA9IGNoZWNrYm94VGV4dFJlZ2V4UmVzdWx0WzFdXG4gICAgICAgIGxldCBzcGFjZUFmdGVyRGFzaCA9IGNoZWNrYm94VGV4dFJlZ2V4UmVzdWx0WzJdXG4gICAgICAgIGxldCBzcGFjZUFmdGVyQ2hlY2sgPSBjaGVja2JveFRleHRSZWdleFJlc3VsdFszXVxuICAgICAgICBsZXQgc3BhY2VBZnRlckNvbnRlbnQgPSBjaGVja2JveFRleHRSZWdleFJlc3VsdFs0XVxuXG4gICAgICAgIGxldCBjdXJyZW50Q2FjaGVJRCA9IGNhY2hlSURcbiAgICAgICAgbGV0IHNvdXJjZUZpbGVQYXRoID0gc291cmNlRmlsZS5wYXRoXG4gICAgICAgIGNoZWNrYm94Lm9uY2xpY2sgPSAoKSA9PiB7XG5cbiAgICAgICAgICAgIGxldCByZXBsYWNlbWVudExpbmUgPSBgJHtzcGFjZUJlZm9yZURhc2h9LSR7c3BhY2VBZnRlckRhc2h9WyR7Y2hlY2tib3hJc0NoZWNrZWQgPyBcIiBcIiA6IFwiWFwifV0ke3NwYWNlQWZ0ZXJDaGVja30ke2xpc3RFbGVtZW50LmlubmVyVGV4dH0ke3NwYWNlQWZ0ZXJDb250ZW50fWBcblxuICAgICAgICAgICAgbGV0IG9yaWdpbmFsVGV4dFRvUmVwbGFjZSA9IG9uQ2xpY2tOZXdUZXh0QmVmb3JlICsgb25DbGlja05ld1dvcmtpbmdUZXh0XG4gICAgICAgICAgICBsZXQgbmV3UmVwbGFjZW1lbnRUZXh0ID0gb25DbGlja05ld1RleHRCZWZvcmUgKyByZXBsYWNlbWVudExpbmUgKyBvbkNsaWNrTmV3VGV4dEFmdGVyXG5cbiAgICAgICAgICAgIGlmKGxpdmVQcmV2aWV3RWxlbWVudENhY2hlLmhhcyhjdXJyZW50Q2FjaGVJRCkpIHtcbiAgICAgICAgICAgICAgICBsZXQgbmV3Q2FjaGVJRCA9IGAke3NvdXJjZUZpbGVQYXRofSA6ICR7bmV3UmVwbGFjZW1lbnRUZXh0fWA7XG4gICAgICAgICAgICAgICAgbGV0IGN1cnJlbnREYXRhID0gbGl2ZVByZXZpZXdFbGVtZW50Q2FjaGUuZ2V0KGN1cnJlbnRDYWNoZUlEKTtcbiAgICAgICAgICAgICAgICBsaXZlUHJldmlld0VsZW1lbnRDYWNoZS5zZXQobmV3Q2FjaGVJRCwgY3VycmVudERhdGEpXG4gICAgICAgICAgICAgICAgY3VycmVudENhY2hlSUQgPSBuZXdDYWNoZUlEXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAgICAgbGV0IGZpbGVUZXh0ID0gYXdhaXQgc291cmNlRmlsZS52YXVsdC5yZWFkKHNvdXJjZUZpbGUpO1xuICAgICAgICAgICAgICAgIGlmKGZpbGVUZXh0LmNvbnRhaW5zKG9yaWdpbmFsVGV4dFRvUmVwbGFjZSkgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJDb3VsZCBub3QgdXBkYXRlIGZpbGUuIEZpbGUgZG9lcyBub3QgY29udGFpbiByZWdpb24gdGV4dC5cIilcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGxldCBuZXdGaWxlVGV4dCA9IGZpbGVUZXh0LnJlcGxhY2Uob3JpZ2luYWxUZXh0VG9SZXBsYWNlLCBuZXdSZXBsYWNlbWVudFRleHQpXG4gICAgICAgICAgICAgICAgc291cmNlRmlsZS52YXVsdC5tb2RpZnkoc291cmNlRmlsZSwgbmV3RmlsZVRleHQpXG4gICAgICAgICAgICB9KSgpO1xuXG4gICAgICAgICAgICBsaXN0RWxlbWVudC5jbGFzc0xpc3QudG9nZ2xlKFwiaXMtY2hlY2tlZFwiKVxuICAgICAgICAgICAgaWYoY2hlY2tib3hJc0NoZWNrZWQpIHtcbiAgICAgICAgICAgICAgICBsaXN0RWxlbWVudC5yZW1vdmVBdHRyaWJ1dGUoXCJkYXRhLXRhc2tcIilcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGxpc3RFbGVtZW50LnNldEF0dHJpYnV0ZShcImRhdGEtdGFza1wiLCBcInhcIilcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNoZWNrYm94SXNDaGVja2VkID0gIWNoZWNrYm94SXNDaGVja2VkXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBwcmV2aW91c1RleHQ6IHdvcmtpbmdUZXh0QmVmb3JlLFxuICAgICAgICB3b3JraW5nVGV4dDogd29ya2luZ1RleHRcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGVzY2FwZVJlZ0V4cChzdHI6IHN0cmluZykge1xuICAgIHJldHVybiBzdHIucmVwbGFjZSgvWy4qKz9eJHt9KCl8W1xcXVxcXFxdL2csICdcXFxcJCYnKTsgLy8gJCYgbWVhbnMgdGhlIHdob2xlIG1hdGNoZWQgc3RyaW5nXG59XG4iLCIvKlxuICogRmlsZW5hbWU6IG11bHRpLWNvbHVtbi1tYXJrZG93bi9zcmMvbGl2ZV9wcmV2aWV3L2NtNl9saXZlUHJldmlldy50c1xuICogQ3JlYXRlZCBEYXRlOiBNb25kYXksIEF1Z3VzdCAxc3QgMjAyMiwgMTo1MToxNiBwbVxuICogQXV0aG9yOiBDYW1lcm9uIFJvYmluc29uXG4gKiBcbiAqIENvcHlyaWdodCAoYykgMjAyMiBDYW1lcm9uIFJvYmluc29uXG4gKi9cblxuaW1wb3J0IHsgRXh0ZW5zaW9uLCBMaW5lLCBSYW5nZVNldEJ1aWxkZXIsIFN0YXRlRmllbGQsIFRyYW5zYWN0aW9uIH0gZnJvbSBcIkBjb2RlbWlycm9yL3N0YXRlXCI7XG5pbXBvcnQgeyBEZWNvcmF0aW9uLCBEZWNvcmF0aW9uU2V0LCBFZGl0b3JWaWV3IH0gZnJvbSBcIkBjb2RlbWlycm9yL3ZpZXdcIjtcbmltcG9ydCB7IHN5bnRheFRyZWUsIHRva2VuQ2xhc3NOb2RlUHJvcCB9IGZyb20gXCJAY29kZW1pcnJvci9sYW5ndWFnZVwiO1xuaW1wb3J0IHsgY29udGFpbnNSZWdpb25TdGFydCwgZmluZEVuZFRhZywgZmluZFNldHRpbmdzQ29kZWJsb2NrLCBmaW5kU3RhcnRDb2RlYmxvY2ssIGZpbmRTdGFydFRhZyB9IGZyb20gXCIuLi91dGlsaXRpZXMvdGV4dFBhcnNlclwiO1xuaW1wb3J0IHsgUGFuZG9jUmVnZXhEYXRhLCBmaW5kUGFuZG9jLCBwYXJzZVBhbmRvY1NldHRpbmdzIH0gZnJvbSBcInNyYy91dGlsaXRpZXMvcGFuZG9jUGFyc2VyXCI7XG5pbXBvcnQgeyBNdWx0aUNvbHVtbk1hcmtkb3duX0RlZmluZWRTZXR0aW5nc19MaXZlUHJldmlld19XaWRnZXQsIE11bHRpQ29sdW1uTWFya2Rvd25fTGl2ZVByZXZpZXdfV2lkZ2V0IH0gZnJvbSBcIi4vbWNtX2xpdmVQcmV2aWV3X3dpZGdldFwiO1xuaW1wb3J0IHsgZWRpdG9ySW5mb0ZpZWxkLCBlZGl0b3JMaXZlUHJldmlld0ZpZWxkIH0gZnJvbSBcIm9ic2lkaWFuXCI7XG5pbXBvcnQgeyBSZWdpb25UeXBlLCBTdGFydFRhZ1JlZ2V4TWF0Y2gsIG1vdXNlU3RhdGUgfSBmcm9tIFwic3JjL3V0aWxpdGllcy9pbnRlcmZhY2VzXCI7XG5pbXBvcnQgeyBNdWx0aUNvbHVtblNldHRpbmdzIH0gZnJvbSBcInNyYy9yZWdpb25TZXR0aW5nc1wiO1xuaW1wb3J0IHsgcGFyc2VDb2x1bW5TZXR0aW5ncyB9IGZyb20gXCJzcmMvdXRpbGl0aWVzL3NldHRpbmdzUGFyc2VyXCI7XG5cbmxldCBzZWxlY3RpbmcgPSBmYWxzZTtcbmV4cG9ydCBjb25zdCBtdWx0aUNvbHVtbk1hcmtkb3duX1N0YXRlRmllbGQgPSBTdGF0ZUZpZWxkLmRlZmluZTxEZWNvcmF0aW9uU2V0Pih7XG5cdGNyZWF0ZShzdGF0ZSk6IERlY29yYXRpb25TZXQge1xuXHRcdHJldHVybiBEZWNvcmF0aW9uLm5vbmU7XG5cdH0sXG5cdHVwZGF0ZShvbGRTdGF0ZTogRGVjb3JhdGlvblNldCwgdHJhbnNhY3Rpb246IFRyYW5zYWN0aW9uKTogRGVjb3JhdGlvblNldCB7XG5cdFx0Y29uc3QgYnVpbGRlciA9IG5ldyBSYW5nZVNldEJ1aWxkZXI8RGVjb3JhdGlvbj4oKTtcbiAgICAgICAgbGV0IGlnbm9yZUZ1cnRoZXJJdGVyYXRpb25zID0gZmFsc2U7XG5cblx0XHQvLyBDaGVjayBpZiB2aWV3IGlzIGluIGxpdmUgcHJldmlldyBzdGF0ZS5cblx0XHRpZih0cmFuc2FjdGlvbi5zdGF0ZS5maWVsZChlZGl0b3JMaXZlUHJldmlld0ZpZWxkKSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIHJldHVybiBidWlsZGVyLmZpbmlzaCgpO1xuXHRcdH1cblxuICAgICAgICAvKipcbiAgICAgICAgICogV2hlbiB3ZSBoYXZlIHRoZSB3aGlsZSBmaWxlIHdlIHRoZW4gZ2V0IHRoZSBlbnRpcmUgZG9jIHRleHQgYW5kIGNoZWNrIGlmIGl0IFxuICAgICAgICAgKiBjb250YWlucyBhIE1DTSByZWdpb24gc28gd2Uga25vdyB0byBicmVhayBvciBub3QuXG4gICAgICAgICAqL1xuICAgICAgICBsZXQgZG9jTGVuZ3RoID0gdHJhbnNhY3Rpb24uc3RhdGUuZG9jLmxlbmd0aFxuICAgICAgICBsZXQgZG9jVGV4dCA9IHRyYW5zYWN0aW9uLnN0YXRlLmRvYy5zbGljZVN0cmluZygwLCBkb2NMZW5ndGgpO1xuICAgICAgICBpZiAoY29udGFpbnNSZWdpb25TdGFydChkb2NUZXh0KSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIHJldHVybiBidWlsZGVyLmZpbmlzaCgpO1xuICAgICAgICB9XG5cblx0XHRzeW50YXhUcmVlKHRyYW5zYWN0aW9uLnN0YXRlKS5pdGVyYXRlKHtcblx0XHRcdGVudGVyKG5vZGUpIHtcblxuXHRcdFx0XHQvLyBJZiB3ZSBmaW5kIHRoYXQgdGhlIGZpbGUgZG9lcyBub3QgY29udGFpbiBhbnkgTUNNIHJlZ2lvbnMgd2UgY2FuIGZsaXAgdGhpc1xuXHRcdFx0XHQvLyBmbGFnIGFuZCBza2lwIGFsbCBvdGhlciBub2RlIGl0ZXJhdGlvbnMsIHBvdGVudGlhbGx5IHNhdmluZyBhIGxvdCBvZiBjb21wdXRlIHRpbWUuXG5cdFx0XHRcdC8vIFxuICAgICAgICAgICAgICAgIC8vIFdlIG9ubHkgd2FudCB0byBydW4gdGhlIGdlbmVyYXRpb24gb25jZSBwZXIgc3RhdGUgY2hhbmdlLiBJZlxuICAgICAgICAgICAgICAgIC8vIGEgcHJldmlvdXMgbm9kZSBoYXMgc3VjZXNzZnVsbHkgZ2VuZXJhdGVkIHJlZ2lvbnMgd2UgaWdub3JlIGFsbFxuICAgICAgICAgICAgICAgIC8vIG90aGVyIG5vZGVzIGluIHRoZSBzdGF0ZS5cbiAgICAgICAgICAgICAgICBpZihpZ25vcmVGdXJ0aGVySXRlcmF0aW9ucyA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG5cdFx0XHRcdC8vIFdlIHdhbnQgdG8gcnVuIG9uIHRoZSB3aG9sZSBmaWxlIHNvIHdlIGRvbnQganVzdCBsb29rIGZvciBhIHNpbmdsZSB0b2tlbi5cblx0XHRcdFx0Y29uc3QgdG9rZW5Qcm9wcyA9IG5vZGUudHlwZS5wcm9wPHN0cmluZz4odG9rZW5DbGFzc05vZGVQcm9wKTtcblx0XHRcdFx0aWYgKHRva2VuUHJvcHMgIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIFdlIHdhbnQgdG8ga25vdyB3aGVyZSB0aGUgdXNlcidzIGN1cnNvciBpcywgaXQgY2FuIGJlXG5cdFx0XHRcdC8vIHNlbGVjdGluZyBtdWx0aXBsZSByZWdpb25zIG9mIHRleHQgYXMgd2VsbCBzbyB3ZSBuZWVkIHRvIGtub3dcblx0XHRcdFx0Ly8gYWxsIGxvY2F0aW9ucy4gVXNlZCB0byBrbm93IGlmIHdlIHNob3VsZCByZW5kZXIgcmVnaW9uIGFzIHRleHQgb3IgYXMgcHJldmlldy5cblx0XHRcdFx0bGV0IHJhbmdlcyA9IGdldEN1cnNvckxpbmVMb2NhdGlvbnMoKTtcblxuXHRcdFx0XHQvLyBTZXR1cCBvdXIgbG9vcCB0byByZW5kZXIgdGhlIHJlZ2lvbnMgYXMgTUNNLiBcblx0XHRcdFx0bGV0IHdvcmtpbmdGaWxlVGV4dCA9IGRvY1RleHQ7XG5cblx0XHRcdFx0bGV0IGxvb3BJbmRleCA9IDA7XG5cdFx0XHRcdGxldCBzdGFydEluZGV4T2Zmc2V0ID0gMDtcblx0XHRcdFx0d2hpbGUgKHRydWUpIHtcblxuXHRcdFx0XHRcdGxldCByZWdpb25EYXRhOiBSZWdpb25EYXRhID0gZ2V0TmV4dFJlZ2lvbih3b3JraW5nRmlsZVRleHQsIHN0YXJ0SW5kZXhPZmZzZXQsIGRvY1RleHQpO1xuXHRcdFx0XHRcdGlmKHJlZ2lvbkRhdGEgPT09IG51bGwpIHtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGxldCBlbGVtZW50VGV4dCAgPSByZWdpb25EYXRhLnJlZ2lvblRleHQ7XG5cdFx0XHRcdFx0d29ya2luZ0ZpbGVUZXh0ICA9IHJlZ2lvbkRhdGEucmVtYWluaW5nVGV4dDtcblx0XHRcdFx0XHRsZXQgc3RhcnRJbmRleCAgID0gcmVnaW9uRGF0YS5zdGFydEluZGV4O1xuXHRcdFx0XHRcdGxldCBlbmRJbmRleCAgICAgPSByZWdpb25EYXRhLmVuZEluZGV4O1xuXHRcdFx0XHRcdHN0YXJ0SW5kZXhPZmZzZXQgPSBlbmRJbmRleDtcblxuXHRcdFx0XHRcdC8vIEhlcmUgd2UgY2hlY2sgaWYgdGhlIGN1cnNvciBpcyBpbiB0aGlzIHNwZWNpZmljIHJlZ2lvbi5cblx0XHRcdFx0XHRsZXQgY3Vyc29ySW5SZWdpb24gPSBjaGVja0N1cnNvckluUmVnaW9uKHN0YXJ0SW5kZXgsIGVuZEluZGV4LCByYW5nZXMpO1xuXHRcdFx0XHRcdGlmKGN1cnNvckluUmVnaW9uID09PSB0cnVlKSB7XG5cdFx0XHRcdFx0XHRcblx0XHRcdFx0XHRcdC8vIC8vIElmIHRoZSBjdXJzb3IgaXMgd2l0aGluIHRoZSByZWdpb24gd2UgdGhlbiBuZWVkIHRvIGtub3cgaWZcblx0XHRcdFx0XHRcdC8vIC8vIGl0IGlzIHdpdGhpbiBvdXIgc2V0dGluZ3MgYmxvY2sgKGlmIGl0IGV4aXN0cy4pXG5cdFx0XHRcdFx0XHQvLyBsZXQgc2V0dGluZ3NTdGFydERhdGEgPSBmaW5kU3RhcnRDb2RlYmxvY2soZWxlbWVudFRleHQpO1xuXHRcdFx0XHRcdFx0Ly8gaWYoc2V0dGluZ3NTdGFydERhdGEuZm91bmQgPT09IGZhbHNlKSB7XG5cdFx0XHRcdFx0XHQvLyBcdHNldHRpbmdzU3RhcnREYXRhID0gZmluZFNldHRpbmdzQ29kZWJsb2NrKGVsZW1lbnRUZXh0KTtcblx0XHRcdFx0XHRcdC8vIH1cblxuXHRcdFx0XHRcdFx0Ly8gaWYoc2V0dGluZ3NTdGFydERhdGEuZm91bmQgPT09IHRydWUpIHtcblxuXHRcdFx0XHRcdFx0Ly8gXHQvLyBTaW5jZSB0aGUgc2V0dGluZ3MgYmxvY2sgZXhpc3RzIGNoZWNrIGlmIHRoZSBjdXJzb3IgaXMgd2l0aGluIHRoYXQgcmVnaW9uLlxuXHRcdFx0XHRcdFx0Ly8gXHRsZXQgY29kZWJsb2NrU3RhcnRJbmRleCA9IHN0YXJ0SW5kZXggKyBzZXR0aW5nc1N0YXJ0RGF0YS5zdGFydFBvc2l0aW9uO1xuXHRcdFx0XHRcdFx0Ly8gXHRsZXQgY29kZWJsb2NrRW5kSW5kZXggPSBzdGFydEluZGV4ICsgc2V0dGluZ3NTdGFydERhdGEuZW5kUG9zaXRpb247XG5cdFx0XHRcdFx0XHQvLyBcdGxldCBzZXR0aW5nc1RleHQgPSBkb2NUZXh0LnNsaWNlKGNvZGVibG9ja1N0YXJ0SW5kZXgsIGNvZGVibG9ja0VuZEluZGV4IClcblxuXHRcdFx0XHRcdFx0Ly8gXHRsZXQgY3Vyc29ySW5Db2RlYmxvY2sgPSBjaGVja0N1cnNvckluUmVnaW9uKGNvZGVibG9ja1N0YXJ0SW5kZXgsIGNvZGVibG9ja0VuZEluZGV4LCByYW5nZXMpO1xuXHRcdFx0XHRcdFx0Ly8gXHRpZihjdXJzb3JJbkNvZGVibG9jayA9PT0gZmFsc2UpIHtcblx0XG5cdFx0XHRcdFx0XHQvLyBcdFx0Ly8gSWYgdGhlIGN1cnNvciBpcyBub3Qgd2l0aGluIHRoZSByZWdpb24gd2UgcGFzcyB0aGUgZGF0YSB0byB0aGVcblx0XHRcdFx0XHRcdC8vIFx0XHQvLyBzZXR0aW5ncyB2aWV3IHNvIGl0IGNhbiBiZSBkaXNwbGF5ZWQgaW4gdGhlIHJlZ2lvbi5cblx0XHRcdFx0XHRcdC8vIFx0XHRidWlsZGVyLmFkZChcblx0XHRcdFx0XHRcdC8vIFx0XHRcdGNvZGVibG9ja1N0YXJ0SW5kZXgsXG5cdFx0XHRcdFx0XHQvLyBcdFx0XHRjb2RlYmxvY2tFbmRJbmRleCxcblx0XHRcdFx0XHRcdC8vIFx0XHRcdERlY29yYXRpb24ucmVwbGFjZSh7XG5cdFx0XHRcdFx0XHQvLyBcdFx0XHRcdHdpZGdldDogbmV3IE11bHRpQ29sdW1uTWFya2Rvd25fRGVmaW5lZFNldHRpbmdzX0xpdmVQcmV2aWV3X1dpZGdldChzZXR0aW5nc1RleHQpLFxuXHRcdFx0XHRcdFx0Ly8gXHRcdFx0fSlcblx0XHRcdFx0XHRcdC8vIFx0XHQpO1xuXHRcdFx0XHRcdFx0Ly8gXHR9XG5cdFx0XHRcdFx0XHQvLyB9XHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGVsc2Uge1xuXG5cdFx0XHRcdFx0XHRsZXQgZm91bmRTZXR0aW5ncyA9IGdldFNldHRpbmdzRGF0YShyZWdpb25EYXRhKTtcblx0XHRcdFx0XHRcdGxldCB1c2VyU2V0dGluZ3MgPSBudWxsO1xuXHRcdFx0XHRcdFx0bGV0IHNldHRpbmdzVGV4dCA9IFwiXCJcblx0XHRcdFx0XHRcdGxldCBvcmlnaW5hbFRleHQgPSBlbGVtZW50VGV4dFxuXHRcdFx0XHRcdFx0aWYoZm91bmRTZXR0aW5ncyAhPT0gbnVsbCkge1xuXHRcdFx0XHRcdFx0XHRcblx0XHRcdFx0XHRcdFx0ZWxlbWVudFRleHQgPSBmb3VuZFNldHRpbmdzLmNvbnRlbnREYXRhO1xuXHRcdFx0XHRcdFx0XHR1c2VyU2V0dGluZ3MgPSBmb3VuZFNldHRpbmdzLnNldHRpbmdzO1xuXHRcdFx0XHRcdFx0XHRzZXR0aW5nc1RleHQgPSBmb3VuZFNldHRpbmdzLnNldHRpbmdzVGV4dDtcblx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0Y29uc3QgZWRpdG9ySW5mbyA9IHRyYW5zYWN0aW9uLnN0YXRlLmZpZWxkKGVkaXRvckluZm9GaWVsZCk7XG5cblx0XHRcdFx0XHRcdC8vIEF0IHRoaXMgcG9pbnQgaWYgdGhlIGN1cnNvciBpc250IGluIHRoZSByZWdpb24gd2UgcGFzcyB0aGUgZGF0YSB0byB0aGVcblx0XHRcdFx0XHRcdC8vIGVsZW1lbnQgdG8gYmUgcmVuZGVyZWQuXG5cdFx0XHRcdFx0XHRidWlsZGVyLmFkZChcblx0XHRcdFx0XHRcdFx0c3RhcnRJbmRleCxcblx0XHRcdFx0XHRcdFx0ZW5kSW5kZXgsXG5cdFx0XHRcdFx0XHRcdERlY29yYXRpb24ucmVwbGFjZSh7XG5cdFx0XHRcdFx0XHRcdFx0d2lkZ2V0OiBuZXcgTXVsdGlDb2x1bW5NYXJrZG93bl9MaXZlUHJldmlld19XaWRnZXQob3JpZ2luYWxUZXh0LCBlbGVtZW50VGV4dCwgdXNlclNldHRpbmdzLCBlZGl0b3JJbmZvLmZpbGUsIHNldHRpbmdzVGV4dCwgcmVnaW9uRGF0YS5yZWdpb25UeXBlKSxcblx0XHRcdFx0XHRcdFx0fSlcblx0XHRcdFx0XHRcdCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGlnbm9yZUZ1cnRoZXJJdGVyYXRpb25zID0gdHJ1ZTtcblxuXHRcdFx0XHRcdC8vIEluZmluaXRlIGxvb3AgcHJvdGVjdGlvbi5cblx0XHRcdFx0XHRsb29wSW5kZXgrKztcblx0XHRcdFx0XHRpZihsb29wSW5kZXggPiAxMDApIHtcblx0XHRcdFx0XHRcdGNvbnNvbGUud2FybihcIlBvdGVudGlhbCBpc3N1ZSB3aXRoIHJlbmRlcmluZyBNdWx0aS1Db2x1bW4gTWFya2Rvd24gbGl2ZSBwcmV2aWV3IHJlZ2lvbnMuIElmIHByb2JsZW0gcGVyc2lzdHMgcGxlYXNlIGZpbGUgYSBidWcgcmVwb3J0IHdpdGggZGV2ZWxvcGVyLlwiKVxuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXHRcdH0pO1xuIFxuXHRcdHJldHVybiBidWlsZGVyLmZpbmlzaCgpO1xuXG5cdFx0ZnVuY3Rpb24gZ2V0Q3Vyc29yTGluZUxvY2F0aW9ucygpOiB7IGxpbmU6IExpbmUsIHBvc2l0aW9uOiBudW1iZXIgfVtdIHtcblxuXHRcdFx0bGV0IHJhbmdlczogeyBsaW5lOiBMaW5lLCBwb3NpdGlvbjogbnVtYmVyIH1bXSA9IFtdO1xuXG5cdFx0XHRpZiAodHJhbnNhY3Rpb24uc3RhdGUuc2VsZWN0aW9uLnJhbmdlcykge1xuXG5cdFx0XHRcdHJhbmdlcyA9IHRyYW5zYWN0aW9uLnN0YXRlLnNlbGVjdGlvbi5yYW5nZXMuZmlsdGVyKChyYW5nZSkgPT4ge1xuXG5cdFx0XHRcdFx0cmV0dXJuIHJhbmdlLmVtcHR5O1xuXHRcdFx0XHR9KS5tYXAoKHJhbmdlKSA9PiB7XG5cblx0XHRcdFx0XHRsZXQgbGluZSA9IHRyYW5zYWN0aW9uLnN0YXRlLmRvYy5saW5lQXQocmFuZ2UuaGVhZCk7XG5cdFx0XHRcdFx0bGV0IHRleHQgPSBgJHtsaW5lLm51bWJlcn06JHtyYW5nZS5oZWFkIC0gbGluZS5mcm9tfWA7XG5cblx0XHRcdFx0XHRyZXR1cm4ge1xuXHRcdFx0XHRcdFx0bGluZTogbGluZSxcblx0XHRcdFx0XHRcdHBvc2l0aW9uOiByYW5nZS5oZWFkXG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9KTtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIHJhbmdlcztcblx0XHR9XG5cbiAgICAgICAgZnVuY3Rpb24gdmFsdWVJc0luUmFuZ2UodmFsdWU6IG51bWJlciwgbWluVmFsOiBudW1iZXIsIG1heFZhbDogbnVtYmVyLCBpbmNsdXNpdmU6IGJvb2xlYW4gPSB0cnVlKSB7XG5cbiAgICAgICAgICAgIGlmKGluY2x1c2l2ZSA9PT0gdHJ1ZSAmJiAodmFsdWUgPT09IG1pblZhbCB8fCB2YWx1ZSA9PT0gbWF4VmFsKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAobWluVmFsIDwgdmFsdWUgJiYgdmFsdWUgPCBtYXhWYWwpIHtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuXHRcdGZ1bmN0aW9uIGNoZWNrQ3Vyc29ySW5SZWdpb24oc3RhcnRJbmRleDogbnVtYmVyLFxuXHRcdFx0XHRcdFx0XHRcdGVuZEluZGV4OiBudW1iZXIsIFxuXHRcdFx0XHRcdFx0XHRcdHJhbmdlczogeyBsaW5lOiBMaW5lLCBwb3NpdGlvbjogbnVtYmVyIH1bXSApOiBib29sZWFuIHtcblxuXHRcdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCByYW5nZXMubGVuZ3RoOyBpKyspIHtcblxuXHRcdFx0XHQvLyBUT0RPOiBNYXliZSBsb29rIGludG8gbGltaXRpbmcgdGhpcyB0byB0aGUgc2Vjb25kIGFuZCBzZWNvbmQgdG8gbGFzdCBsaW5lXG5cdFx0XHRcdC8vIG9mIHRoZSByZWdpb24gYXMgY2xpY2tpbmcgcmlnaHQgYXQgdGhlIHRvcCBvciBib3R0b20gb2YgdGhlIHJlZ2lvblxuXHRcdFx0XHQvLyBzd2FwcyBpdCB0byB1bnJlbmRlcmVkLlxuXHRcdFx0XHRsZXQgcmFuZ2UgPSByYW5nZXNbaV07XG5cdFx0XHRcdGlmKHZhbHVlSXNJblJhbmdlKHJhbmdlLnBvc2l0aW9uLCBzdGFydEluZGV4LCBlbmRJbmRleCkgPT09IHRydWUpIHtcblx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHRpZih0cmFuc2FjdGlvbi5zdGF0ZS5zZWxlY3Rpb24pe1xuXHRcdFx0XHRmb3IgKGxldCBpID0gMDsgaSA8IHRyYW5zYWN0aW9uLnN0YXRlLnNlbGVjdGlvbi5yYW5nZXMubGVuZ3RoOyBpKyspIHtcblxuXHRcdFx0XHRcdGxldCByYW5nZSA9IHRyYW5zYWN0aW9uLnN0YXRlLnNlbGVjdGlvbi5yYW5nZXNbaV07XG5cblx0XHRcdFx0XHQvLyBJZiBlaXRoZXIgdGhlIHN0YXJ0IG9yIGVuZCBvZiB0aGUgc2VsZWN0aW9uIGlzIHdpdGhpbiB0aGVcblx0XHRcdFx0XHQvLyByZWdpb24gcmFuZ2Ugd2UgZG8gbm90IHJlbmRlciBsaXZlIHByZXZpZXcuXG5cdFx0XHRcdFx0aWYodmFsdWVJc0luUmFuZ2UocmFuZ2UuZnJvbSwgc3RhcnRJbmRleCwgZW5kSW5kZXgpIHx8IFxuXHRcdFx0XHRcdCAgIHZhbHVlSXNJblJhbmdlKHJhbmdlLnRvLCBzdGFydEluZGV4LCBlbmRJbmRleCkpIHtcblx0XHRcdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdC8vIC8vIE9yIGlmIHRoZSBlbnRpcmUgcmVnaW9uIGlzIHdpdGhpbiB0aGUgc2VsZWN0aW9uIHJhbmdlXG5cdFx0XHRcdFx0Ly8gd2UgZG8gbm90IHJlbmRlciB0aGUgbGl2ZSBwcmV2aWV3LlxuXHRcdFx0XHRcdGlmKHZhbHVlSXNJblJhbmdlKHN0YXJ0SW5kZXgsIHJhbmdlLmZyb20sIHJhbmdlLnRvKSAmJiBcblx0XHRcdFx0XHQgICB2YWx1ZUlzSW5SYW5nZShlbmRJbmRleCwgcmFuZ2UuZnJvbSwgcmFuZ2UudG8pKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblx0fSxcblx0cHJvdmlkZShmaWVsZDogU3RhdGVGaWVsZDxEZWNvcmF0aW9uU2V0Pik6IEV4dGVuc2lvbiB7XG5cdFx0cmV0dXJuIEVkaXRvclZpZXcuZGVjb3JhdGlvbnMuZnJvbShmaWVsZCk7XG5cdH0sXG59KTtcblxuaW50ZXJmYWNlIFJlZ2lvbkRhdGEge1xuXHRyZWdpb25UeXBlOiBSZWdpb25UeXBlO1xuXHRyZWdpb25UZXh0OiBzdHJpbmc7XG5cdHJlbWFpbmluZ1RleHQ6IHN0cmluZztcblx0c3RhcnRJbmRleDogbnVtYmVyO1xuXHRlbmRJbmRleDogbnVtYmVyO1xufVxuaW50ZXJmYWNlIFBhbmRvY1JlZ2lvbkRhdGEgZXh0ZW5kcyBSZWdpb25EYXRhIHtcblx0Y29sdW1uQ291bnQ6IHN0cmluZztcblx0dXNlclNldHRpbmdzOiBzdHJpbmc7XG59XG5cbmZ1bmN0aW9uIGdldE5leHRSZWdpb24od29ya2luZ0ZpbGVUZXh0OiBzdHJpbmcsIHN0YXJ0SW5kZXhPZmZzZXQ6IG51bWJlciwgd2hvbGVEb2M6IHN0cmluZyk6IFJlZ2lvbkRhdGEgfCBudWxsIHtcblxuXHRsZXQgcmVnaW9uID0gZmluZE5leHRSZWdpb24od29ya2luZ0ZpbGVUZXh0KTtcblx0aWYocmVnaW9uID09PSBudWxsKSB7XG5cdFx0cmV0dXJuIG51bGw7XG5cdH1cblxuXHRpZihyZWdpb24uZGF0YVR5cGUgPT09IFwiQ09ERUJMT0NLXCIgfHwgcmVnaW9uLmRhdGFUeXBlID09PSBcIk9SSUdJTkFMXCIpIHtcblxuXHRcdC8vIFNlYXJjaCBmb3IgdGhlIGZpcnN0IGVuZCB0YWcgYWZ0ZXIgYSBzdGFydCBibG9jay4gKE5vIHJlY3Vyc2l2ZSBjb2x1bW5zLilcblx0XHRsZXQgZW5kVGFnRGF0YSA9IGZpbmRFbmRUYWcod29ya2luZ0ZpbGVUZXh0LnNsaWNlKHJlZ2lvbi5kYXRhLnN0YXJ0UG9zaXRpb24pKTtcblx0XHRpZihlbmRUYWdEYXRhLmZvdW5kID09PSBmYWxzZSkge1xuXHRcdFx0cmV0dXJuIG51bGw7XG5cdFx0fVxuXG5cdFx0LyoqXG5cdFx0ICogRm9yIHRoZSByZWdpb24gd2UgZm91bmQgZ2V0IHRoZSBzdGFydCBhbmQgZW5kIHBvc2l0aW9uIG9mIHRoZSB0YWdzIHNvIHdlIFxuXHRcdCAqIGNhbiBzbGljZSBpdCBvdXQgb2YgdGhlIGRvY3VtZW50LlxuXHRcdCAqL1xuXHRcdGxldCBzdGFydEluZGV4ID0gc3RhcnRJbmRleE9mZnNldCArIHJlZ2lvbi5kYXRhLnN0YXJ0UG9zaXRpb247XG5cdFx0bGV0IGVuZEluZGV4ID0gc3RhcnRJbmRleCArIGVuZFRhZ0RhdGEuc3RhcnRQb3NpdGlvbiArIGVuZFRhZ0RhdGEubWF0Y2hMZW5ndGggLy8gV2l0aG91dCB0aGUgbWF0Y2hMZW5ndGggd2lsbCBsZWF2ZSB0aGUgZW5kIHRhZyBvbiB0aGUgc2NyZWVuLlxuXG5cdFx0Ly8gVGhpcyB0ZXh0IGlzIHRoZSBlbnRpcmUgcmVnaW9uIGRhdGEgaW5jbHVkaW5nIHRoZSBzdGFydCBhbmQgZW5kIHRhZ3MuXG5cdFx0bGV0IGVsZW1lbnRUZXh0ID0gd2hvbGVEb2Muc2xpY2Uoc3RhcnRJbmRleCwgZW5kSW5kZXgpXG5cdFx0d29ya2luZ0ZpbGVUZXh0ID0gd2hvbGVEb2Muc2xpY2UoZW5kSW5kZXgpO1xuXG5cdFx0LyoqXG5cdFx0ICogVXBkYXRlIG91ciBzdGFydCBvZmZzZXQgYW5kIHRoZSB3b3JraW5nIHRleHQgb2YgdGhlIGZpbGUgc28gb3VyIG5leHQgXG5cdFx0ICogaXRlcmF0aW9uIGtub3dzIHdoZXJlIHdlIGxlZnQgb2ZmXG5cdFx0ICovXG5cdFx0bGV0IGRhdGE6IFJlZ2lvbkRhdGEgPSB7XG5cdFx0XHRyZWdpb25UeXBlOiByZWdpb24uZGF0YVR5cGUsXG5cdFx0XHRyZWdpb25UZXh0OiBlbGVtZW50VGV4dCxcblx0XHRcdHJlbWFpbmluZ1RleHQ6IHdvcmtpbmdGaWxlVGV4dCxcblx0XHRcdHN0YXJ0SW5kZXg6IHN0YXJ0SW5kZXgsXG5cdFx0XHRlbmRJbmRleDogZW5kSW5kZXhcblx0XHR9XG5cdFx0cmV0dXJuIGRhdGE7XG5cdH1cblxuXHRpZihyZWdpb24uZGF0YVR5cGUgPT09IFwiUEFET0NcIikge1xuXG5cdFx0bGV0IHBhbmRvY0RhdGE6IFBhbmRvY1JlZ2V4RGF0YSA9IHJlZ2lvbi5kYXRhIGFzIFBhbmRvY1JlZ2V4RGF0YTtcblx0XHRsZXQgc3RhcnRJbmRleCA9IHN0YXJ0SW5kZXhPZmZzZXQgKyBwYW5kb2NEYXRhLnN0YXJ0UG9zaXRpb247XG5cdFx0bGV0IGVuZEluZGV4ID0gc3RhcnRJbmRleE9mZnNldCArIHBhbmRvY0RhdGEuZW5kUG9zaXRpb247XG5cdFx0d29ya2luZ0ZpbGVUZXh0ID0gd2hvbGVEb2Muc2xpY2UoZW5kSW5kZXgpO1xuXHRcdGxldCBkYXRhOiBQYW5kb2NSZWdpb25EYXRhID0ge1xuXHRcdFx0cmVnaW9uVHlwZTogcmVnaW9uLmRhdGFUeXBlLFxuXHRcdFx0cmVnaW9uVGV4dDogcGFuZG9jRGF0YS5jb250ZW50LFxuXHRcdFx0cmVtYWluaW5nVGV4dDogd29ya2luZ0ZpbGVUZXh0LFxuXHRcdFx0c3RhcnRJbmRleDogc3RhcnRJbmRleCxcblx0XHRcdGVuZEluZGV4OiBlbmRJbmRleCxcblx0XHRcdGNvbHVtbkNvdW50OiBwYW5kb2NEYXRhLmNvbHVtbkNvdW50LFxuXHRcdFx0dXNlclNldHRpbmdzOiBwYW5kb2NEYXRhLnVzZXJTZXR0aW5nc1xuXHRcdH1cblx0XHRyZXR1cm4gZGF0YTtcblx0fVxufVxuXG5mdW5jdGlvbiBmaW5kTmV4dFJlZ2lvbih3b3JraW5nRmlsZVRleHQ6IHN0cmluZyk6IHsgZGF0YVR5cGU6IFJlZ2lvblR5cGUsIGRhdGE6IFN0YXJ0VGFnUmVnZXhNYXRjaCB8IFBhbmRvY1JlZ2V4RGF0YSB9IHtcblxuXHQvLyBJZiB0aGVyZSBhcmUgbXVsdGlwbGUga2luZHMgb2Ygc3RhcnQgYmxvY2tzLCB0aGUgb2xkIHdheSBvZiBwYXJzaW5nIHdvdWxkIGNhdXNlIGlzc3Vlcy5cblx0Ly8gTm93IHNlYXJjaCBmb3IgYm90aCBraW5kcyBhbmQgZGV0ZXJtaW5lIHdoYXQgdG8gZG8gYWZ0ZXIgc2VhcmNoLlxuXHRsZXQgc3RhcnRUYWdEYXRhX2NvZGVibG9ja1N0YXJ0OiB7IGRhdGFUeXBlOiBSZWdpb25UeXBlLCBkYXRhOiBTdGFydFRhZ1JlZ2V4TWF0Y2ggfSA9IHtkYXRhVHlwZTogXCJDT0RFQkxPQ0tcIiwgZGF0YTogZmluZFN0YXJ0Q29kZWJsb2NrKHdvcmtpbmdGaWxlVGV4dCkgfTtcblx0bGV0IHN0YXJ0VGFnRGF0YV9vcmlnaW5hbFN0YXJ0OiB7IGRhdGFUeXBlOiBSZWdpb25UeXBlLCBkYXRhOiBTdGFydFRhZ1JlZ2V4TWF0Y2ggfSA9IHtkYXRhVHlwZTogXCJPUklHSU5BTFwiLCBkYXRhOiBmaW5kU3RhcnRUYWcod29ya2luZ0ZpbGVUZXh0KSB9O1xuXHRsZXQgcGFuZG9jRGF0YTogeyBkYXRhVHlwZTogUmVnaW9uVHlwZSwgZGF0YTogUGFuZG9jUmVnZXhEYXRhIH0gPSB7ZGF0YVR5cGU6IFwiUEFET0NcIiwgZGF0YTogZmluZFBhbmRvYyh3b3JraW5nRmlsZVRleHQpIH1cblxuXHRpZihzdGFydFRhZ0RhdGFfY29kZWJsb2NrU3RhcnQuZGF0YS5mb3VuZCA9PT0gZmFsc2UgJiYgXG5cdCAgIHN0YXJ0VGFnRGF0YV9vcmlnaW5hbFN0YXJ0LmRhdGEuZm91bmQgPT09IGZhbHNlICYmXG5cdCAgIHBhbmRvY0RhdGEuZGF0YS5mb3VuZCA9PT0gZmFsc2UpIHtcblx0XHRyZXR1cm4gbnVsbDtcblx0fVxuXG5cdGxldCByZWdpb25zRm91bmQgPSBbc3RhcnRUYWdEYXRhX2NvZGVibG9ja1N0YXJ0LCBzdGFydFRhZ0RhdGFfb3JpZ2luYWxTdGFydCwgcGFuZG9jRGF0YV0uZmlsdGVyKCh2YWwpID0+IHsgcmV0dXJuIHZhbC5kYXRhLmZvdW5kID09PSB0cnVlIH0pO1xuXHRpZihyZWdpb25zRm91bmQubGVuZ3RoID4gMSkge1xuXG5cdFx0bGV0IHNvcnRlZCA9IHJlZ2lvbnNGb3VuZC5zb3J0KChhLCBiKSA9PiB7XG5cdFx0XHRyZXR1cm4gYS5kYXRhLnN0YXJ0UG9zaXRpb24gLSBiLmRhdGEuZW5kUG9zaXRpb247XG5cdFx0fSlcblx0XHRyZXR1cm4gc29ydGVkLmZpcnN0KCk7XG5cdH1cblx0XG5cdGlmKHN0YXJ0VGFnRGF0YV9jb2RlYmxvY2tTdGFydC5kYXRhLmZvdW5kID09PSB0cnVlKSB7XG5cdFx0cmV0dXJuIHN0YXJ0VGFnRGF0YV9jb2RlYmxvY2tTdGFydDtcblx0fVxuXHRcblx0aWYoc3RhcnRUYWdEYXRhX29yaWdpbmFsU3RhcnQuZGF0YS5mb3VuZCA9PT0gdHJ1ZSl7XG5cdFx0cmV0dXJuIHN0YXJ0VGFnRGF0YV9vcmlnaW5hbFN0YXJ0O1xuXHR9XG5cdFxuXHRpZihwYW5kb2NEYXRhLmRhdGEuZm91bmQgPT09IHRydWUpIHtcblx0XHRyZXR1cm4gcGFuZG9jRGF0YTtcblx0fVxuXG5cdHRocm93KFwiVW5rbm93biB0eXBlIGZvdW5kIHdoZW4gcGFyc2luZyByZWdpb24uXCIpXG59XG5cbmZ1bmN0aW9uIGdldFNldHRpbmdzRGF0YShyZWdpb25EYXRhOiBSZWdpb25EYXRhKToge3NldHRpbmdzOiBNdWx0aUNvbHVtblNldHRpbmdzLCBzZXR0aW5nc1RleHQ6IHN0cmluZywgY29udGVudERhdGE6IHN0cmluZ30ge1xuXG5cdGxldCBjb250ZW50RGF0YSA9IHJlZ2lvbkRhdGEucmVnaW9uVGV4dFxuXHRmdW5jdGlvbiBwYXJzZUNvZGVCbG9ja1NldHRpbmdzKHNldHRpbmdzU3RhcnREYXRhOiBTdGFydFRhZ1JlZ2V4TWF0Y2gpIHtcblxuXHRcdGxldCBzZXR0aW5nc1RleHQgPSBjb250ZW50RGF0YS5zbGljZShzZXR0aW5nc1N0YXJ0RGF0YS5zdGFydFBvc2l0aW9uLCBzZXR0aW5nc1N0YXJ0RGF0YS5lbmRQb3NpdGlvbik7XG5cdFx0Y29udGVudERhdGEgPSBjb250ZW50RGF0YS5yZXBsYWNlKHNldHRpbmdzVGV4dCwgXCJcIik7XG5cblx0XHRsZXQgc2V0dGluZ3MgPSBwYXJzZUNvbHVtblNldHRpbmdzKHNldHRpbmdzVGV4dCk7XG5cblx0XHRyZXR1cm4ge1xuXHRcdFx0c2V0dGluZ3M6IHNldHRpbmdzLFxuXHRcdFx0c2V0dGluZ3NUZXh0OiBzZXR0aW5nc1RleHQsXG5cdFx0XHRjb250ZW50RGF0YTogY29udGVudERhdGFcblx0XHR9XG5cdH1cblxuXHRpZihyZWdpb25EYXRhLnJlZ2lvblR5cGUgPT09IFwiQ09ERUJMT0NLXCIpIHtcblx0XHRsZXQgc2V0dGluZ3NTdGFydERhdGEgPSBmaW5kU3RhcnRDb2RlYmxvY2soY29udGVudERhdGEpO1xuXHRcdGlmIChzZXR0aW5nc1N0YXJ0RGF0YS5mb3VuZCA9PT0gZmFsc2UpIHtcblx0XHRcdHJldHVybiBudWxsO1xuXHRcdH1cblxuXHRcdHJldHVybiBwYXJzZUNvZGVCbG9ja1NldHRpbmdzKHNldHRpbmdzU3RhcnREYXRhKVxuXHR9XG5cblx0aWYocmVnaW9uRGF0YS5yZWdpb25UeXBlID09PSBcIk9SSUdJTkFMXCIpIHtcblx0XHRsZXQgc2V0dGluZ3NTdGFydERhdGEgPSBmaW5kU2V0dGluZ3NDb2RlYmxvY2soY29udGVudERhdGEpO1xuXHRcdGlmIChzZXR0aW5nc1N0YXJ0RGF0YS5mb3VuZCA9PT0gZmFsc2UpIHtcblx0XHRcdHJldHVybiBudWxsO1xuXHRcdH1cblx0XHRyZXR1cm4gcGFyc2VDb2RlQmxvY2tTZXR0aW5ncyhzZXR0aW5nc1N0YXJ0RGF0YSlcblx0fVxuXG5cdGlmKHJlZ2lvbkRhdGEucmVnaW9uVHlwZSA9PT0gXCJQQURPQ1wiKSB7XG5cblx0XHRsZXQgcGFuZG9jRGF0YSA9IHJlZ2lvbkRhdGEgYXMgUGFuZG9jUmVnaW9uRGF0YVxuXHRcdHJldHVybiB7XG5cdFx0XHRzZXR0aW5nczogcGFyc2VQYW5kb2NTZXR0aW5ncyhwYW5kb2NEYXRhLnVzZXJTZXR0aW5ncywgcGFuZG9jRGF0YS5jb2x1bW5Db3VudCksXG5cdFx0XHRzZXR0aW5nc1RleHQ6IFwiXCIsXG5cdFx0XHRjb250ZW50RGF0YTogcmVnaW9uRGF0YS5yZWdpb25UZXh0XG5cdFx0fVxuXHR9XG59XG5cbmZ1bmN0aW9uIGNoZWNrVXNlclNlbGVjdGluZyh0cmFuc2FjdGlvbjogVHJhbnNhY3Rpb24pOiBib29sZWFuIHtcblx0XG5cdGxldCBpc1NlbGVjdGluZyA9IGZhbHNlO1xuXHRpZih0cmFuc2FjdGlvbi5pc1VzZXJFdmVudChcInNlbGVjdC5wb2ludGVyXCIpICYmIFxuXHRcdHRyYW5zYWN0aW9uLnN0YXRlLnNlbGVjdGlvbi5yYW5nZXMgJiYgXG5cdFx0dHJhbnNhY3Rpb24uc3RhdGUuc2VsZWN0aW9uLnJhbmdlcy5sZW5ndGggPiAwKSB7XG5cblx0XHRmb3IobGV0IHJhbmdlIG9mIHRyYW5zYWN0aW9uLnN0YXRlLnNlbGVjdGlvbi5yYW5nZXMpIHtcblxuXHRcdFx0aWYocmFuZ2UudG8gLSByYW5nZS5mcm9tID4gMSkge1xuXG5cdFx0XHRcdGlzU2VsZWN0aW5nID0gdHJ1ZTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIGlzU2VsZWN0aW5nXG59IiwiLyoqXG4gKiBGaWxlOiAvc3JjL2xpdmVfcHJldmlldy9jbTZfbGl2ZVByZWl2ZXdfb25DbGlja0ZpeC50cyAgICAgICAgICAgICAgICAgICAgICAgKlxuICogQ3JlYXRlZCBEYXRlOiBGcmlkYXksIE1hcmNoIDI0dGggMjAyMywgNjoxMCBwbSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAqIEF1dGhvcjogQ2FtZXJvbiBSb2JpbnNvbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICogQ29weXJpZ2h0IChjKSAyMDIzIENhbWVyb24gUm9iaW5zb24gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAqL1xuXG4vKipcbiAqIFRoaXMgbW9kdWxlIGlzIG1vc3RseSBhIGJvZGdlZCBmaXggZm9yIHRoZSBMaXZlIFByZXZpZXcgc2Nyb2xsaW5nIGlzc3VlIGNyZWF0ZWQgd2hlblxuICogbGFyZ2UgLyBsb25nIGNvbnRlbnQgKHN1Y2ggYXMgTUNNKSBpcyBiZWluZyByZW5kZXJlZCB0aHJvdWdoIGEgQ002IFN0YXRlRmllbGQuXG4gKiBUaGUgY29yZSBwcm9ibGVtIHRoaXMgbW9kdWxlIGFpbXMgdG8gXCJmaXhcIiBpcyBPYnNpZGlhbidzIHJlZHJhdyBhbmQgbWVtb3J5XG4gKiBtYW5hZ2VtZW50IHdoaWNoIGNhdXNlcyB0aGUgdmlld3BvcnQgdG8gc25hcCB0byB0aGUgYm90dG9tIG9mIHRoZSBkb2N1bWVudFxuICogb24gdXNlciBjbGljayBpbnRlcmFjdGlvbi4gXG4gKiBcbiAqIFRoaXMgQ002IHBsdWdpbiBtYWtlIHRoZSBlZGl0aW5nIGV4cGVyaWVuY2Ugd2l0aCBNQ00gbW9yZSB1c2VyIGZpZW5kbHkgYnkgc25hcHBpbmcgXG4gKiB0aGUgdmlldyBiYWNrIHRvIHRoZSBjdXJzb3IgYWZ0ZXIgT2JzaWRpYW4gaGFzIHBlcmZvcm1lZCBpdCdzIGZ1bGwgTFAgcmVkcmF3LCBhbmQgXG4gKiBjdWxsZWQgb3V0IHVubmVlZGVkIGVsZW1lbnRzIGZyb20gdGhlIExQIHZpZXcuXG4gKiBcbiAqIElmIHRoZSBjb3JlIHByb2JsZW0gaXMgZXZlciBmaXhlZCBieSBPYnNpZGlhbiwgdGhpcyBtb2R1bGUgd2lsbCBiZWNvbWUgb2Jzb2xldGVcbiAqIGFuZCBiZSByZW1vdmVkLlxuICovXG5cbmltcG9ydCB7IEVkaXRvclNlbGVjdGlvbiwgRXh0ZW5zaW9uLCBSYW5nZVNldEJ1aWxkZXIsIFNlbGVjdGlvblJhbmdlLCBTdGF0ZUZpZWxkLCBUcmFuc2FjdGlvbiwgVHJhbnNhY3Rpb25TcGVjLCBUZXh0IH0gZnJvbSBcIkBjb2RlbWlycm9yL3N0YXRlXCI7XG5pbXBvcnQgeyBEZWNvcmF0aW9uLCBEZWNvcmF0aW9uU2V0LCBFZGl0b3JWaWV3IH0gZnJvbSBcIkBjb2RlbWlycm9yL3ZpZXdcIjtcbmltcG9ydCB7IGNvbnRhaW5zRW5kVGFnLCBjb250YWluc1JlZ2lvblN0YXJ0IH0gZnJvbSBcIi4uL3V0aWxpdGllcy90ZXh0UGFyc2VyXCI7XG5pbXBvcnQgeyBlZGl0b3JFZGl0b3JGaWVsZCwgZWRpdG9yTGl2ZVByZXZpZXdGaWVsZCB9IGZyb20gXCJvYnNpZGlhblwiO1xuaW1wb3J0IHsgTW91c2VTdGF0ZSwgbW91c2VTdGF0ZSB9IGZyb20gXCJzcmMvdXRpbGl0aWVzL2ludGVyZmFjZXNcIjtcblxuY29uc3QgRURJVE9SX1ZJRVdfR0NfVElNRU9VVF9NUyA9IDE1MDAwMCAvLyAyLjVtIGluIG1zXG5cbmFic3RyYWN0IGNsYXNzIEVkaXRvckNhbGxiYWNrTWFuYWdlciB7XG5cdHByb3RlY3RlZCBfcmVnYWluZWRGb2N1czogYm9vbGVhbiA9IHRydWU7XG5cdHB1YmxpYyBnZXQgcmVnYWluZWRGb2N1cygpOiBib29sZWFuIHtcblx0XHRyZXR1cm4gdGhpcy5fcmVnYWluZWRGb2N1cztcblx0fVxuXG5cdHByb3RlY3RlZCBfbG9zdEZvY3VzOiBib29sZWFuID0gdHJ1ZTtcblx0cHVibGljIGdldCBsb3N0Rm9jdXMoKTogYm9vbGVhbiB7XG5cdFx0cmV0dXJuIHRoaXMuX2xvc3RGb2N1cztcblx0fVxuXG5cdHByb3RlY3RlZCBfaGFzRm9jdXM6IGJvb2xlYW47XG5cdHB1YmxpYyBnZXQgaGFzRm9jdXMoKTogYm9vbGVhbiB7XG5cdFx0cmV0dXJuIHRoaXMuX2hhc0ZvY3VzO1xuXHR9XG5cdHB1YmxpYyBzZXQgaGFzRm9jdXModmFsdWU6IGJvb2xlYW4pIHtcblxuXHRcdGlmKHZhbHVlID09PSB0cnVlKSB7XG5cdFx0XHRpZih0aGlzLl9oYXNGb2N1cyA9PT0gZmFsc2UpIHtcblx0XHRcdFx0dGhpcy5fcmVnYWluZWRGb2N1cyA9IHRydWU7XG5cdFx0XHR9XG5cdFx0XHRlbHNlIHtcblx0XHRcdFx0dGhpcy5fcmVnYWluZWRGb2N1cyA9IGZhbHNlO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRlbHNlIHtcblx0XHRcdGlmKHRoaXMuX2hhc0ZvY3VzID09PSB0cnVlKSB7XG5cdFx0XHRcdHRoaXMuX2xvc3RGb2N1cyA9IHRydWU7XG5cdFx0XHR9XG5cdFx0XHRlbHNlIHtcblx0XHRcdFx0dGhpcy5fbG9zdEZvY3VzID0gZmFsc2U7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0dGhpcy5faGFzRm9jdXMgPSB2YWx1ZTtcblx0fVxufVxuXG5jbGFzcyBFZGl0b3JWaWV3U2Nyb2xsU3RhdGVNYW5hZ2VyIGV4dGVuZHMgRWRpdG9yQ2FsbGJhY2tNYW5hZ2Vye1xuXG5cdHByaXZhdGUgbGFzdFVzZVRpbWVzdGFtcDogbnVtYmVyID0gRGF0ZS5ub3coKTtcblxuXHQvLyBUT0RPOiBGaW5kIGEgd2F5IHRvIG5vdCByZXF1aXJlIHRoZSBlZGl0b3Igdmlldz8/XG5cdHByaXZhdGUgX2VkaXRvclZpZXc6IEVkaXRvclZpZXc7XG5cdHB1YmxpYyBnZXQgZWRpdG9yVmlldygpOiBFZGl0b3JWaWV3IHtcblx0XHRyZXR1cm4gdGhpcy5fZWRpdG9yVmlldztcblx0fVxuXG5cdHByaXZhdGUgX2xhc3REb2NTdGF0ZTogVGV4dDtcblx0cHVibGljIGdldCBsYXN0RG9jU3RhdGUoKTogVGV4dCB7XG5cdFx0cmV0dXJuIHRoaXMuX2xhc3REb2NTdGF0ZTtcblx0fVxuXHRwdWJsaWMgc2V0IGxhc3REb2NTdGF0ZSh2YWx1ZTogVGV4dCkge1xuXHRcdHRoaXMuX2xhc3REb2NTdGF0ZSA9IHZhbHVlO1xuXHR9XG5cblx0Ly8gQ3VycmVudGx5IHVudXNlZC4gS2VlcGluZyBzdG9yZWQgZm9yIGVhc3kgYWNjZXNzIGluIGZ1dHVyZS5cblx0cHJpdmF0ZSBfZG9jVGl0bGU6IHN0cmluZ1xuXHRwdWJsaWMgZ2V0IGRvY1RpdGxlKCk6IHN0cmluZyB7XG5cdFx0cmV0dXJuIHRoaXMuX2RvY1RpdGxlXG5cdH1cblx0cHVibGljIHNldCBkb2NUaXRsZSh2YWx1ZTogc3RyaW5nKSB7XG5cblx0XHRsZXQgcGFyc2VkRG9jVGl0bGUgPSBhdHRlbXB0UGFyc2VEb2NUaXRsZSh2YWx1ZSlcblx0XHRpZihwYXJzZWREb2NUaXRsZSAhPT0gXCJcIikge1xuXG5cdFx0XHR0aGlzLl9kb2NUaXRsZSA9IHBhcnNlZERvY1RpdGxlO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHR0aGlzLl9kb2NUaXRsZSA9IHZhbHVlO1xuXHR9XG5cblx0Y29uc3RydWN0b3IoZWRpdG9yVmlldzogRWRpdG9yVmlldykge1xuXHRcdHN1cGVyKCk7XG5cblx0XHR0aGlzLl9lZGl0b3JWaWV3ID0gZWRpdG9yVmlldztcblx0XHR0aGlzLmhhc0ZvY3VzID0gdHJ1ZTtcblx0fVxuXG5cdHB1YmxpYyBoYXNCZWVuQWNjZXNzZWQoKSB7XG5cdFx0dGhpcy5sYXN0VXNlVGltZXN0YW1wID0gRGF0ZS5ub3coKTtcblx0fVxuXG5cdGdldCBpc1JlYWR5Rm9yR0MoKTogYm9vbGVhbiB7XG5cblx0XHRpZih0aGlzLl9lZGl0b3JWaWV3ID09PSBudWxsKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHRsZXQgZGVsdGEgPSBEYXRlLm5vdygpIC0gdGhpcy5sYXN0VXNlVGltZXN0YW1wO1xuXHRcdGlmKCB0aGlzLl9lZGl0b3JWaWV3LmluVmlldyA9PT0gZmFsc2UgJiZcblx0XHQgICAgdGhpcy5fZWRpdG9yVmlldy5oYXNGb2N1cyA9PT0gZmFsc2UgJiYgXG5cdFx0XHRkZWx0YSA+IEVESVRPUl9WSUVXX0dDX1RJTUVPVVRfTVMpIHtcblxuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG59XG5cbmNsYXNzIEVkaXRvckRlbGF5Q2FsbGJhY2sgZXh0ZW5kcyBFZGl0b3JDYWxsYmFja01hbmFnZXIge1xuXG5cdHB1YmxpYyBjYWxsYmFjazogKCkgPT4gdm9pZFxuXHRwcml2YXRlIGNyZWF0aW9uVGltZXN0YW1wOiBudW1iZXIgPSBEYXRlLm5vdygpO1xuXG5cdGdldCBjYWxsYmFja1Nob3VsZFRpbWVvdXQoKTogYm9vbGVhbiB7XG5cdFxuXHRcdGxldCBjdXJyZW50VGltZU1TID0gRGF0ZS5ub3coKTtcblx0XG5cdFx0bGV0IGRlbHRhID0gY3VycmVudFRpbWVNUyAtIHRoaXMuY3JlYXRpb25UaW1lc3RhbXBcblx0XG5cdFx0bGV0IG1heERlbHRhVGltZU1TID0gMjAwXG5cdFx0aWYoZGVsdGEgPiBtYXhEZWx0YVRpbWVNUykge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXHRcdHJldHVybiBmYWxzZTtcblx0fVxufVxuXG5jb25zdCBjbGlja0RlbGF5Q2FsbGJhY2tzOiBNYXA8c3RyaW5nLCBFZGl0b3JEZWxheUNhbGxiYWNrPiA9IG5ldyBNYXAoKTtcbmNvbnN0IG9wZW5FZGl0b3JWaWV3czogTWFwPEVkaXRvclZpZXcsIEVkaXRvclZpZXdTY3JvbGxTdGF0ZU1hbmFnZXI+ID0gbmV3IE1hcCgpO1xubGV0IGxhc3RHQ1Bhc3MgPSBEYXRlLm5vdygpO1xubGV0IGVkaXRvck1vdXNlU3RhdGU6IE1vdXNlU3RhdGUgPSBcInVwXCI7XG5cbmV4cG9ydCBjb25zdCBNdWx0aUNvbHVtbk1hcmtkb3duX09uQ2xpY2tGaXggPSBTdGF0ZUZpZWxkLmRlZmluZTxEZWNvcmF0aW9uU2V0Pih7XG5cdGNyZWF0ZShzdGF0ZSk6IERlY29yYXRpb25TZXQge1xuXHRcdHJldHVybiBEZWNvcmF0aW9uLm5vbmU7XG5cdH0sXG5cdHVwZGF0ZShvbGRTdGF0ZTogRGVjb3JhdGlvblNldCwgdHJhbnNhY3Rpb246IFRyYW5zYWN0aW9uKTogRGVjb3JhdGlvblNldCB7XG5cdFx0Y29uc3QgYnVpbGRlciA9IG5ldyBSYW5nZVNldEJ1aWxkZXI8RGVjb3JhdGlvbj4oKTtcblx0XHRyZXR1cm4gYnVpbGRlci5maW5pc2goKTtcblxuXHRcdGlmKCBzaG91bGRSdW5HQ09uRWRpdG9yTWFwKCkgKSB7XG5cblx0XHRcdGZvcihsZXQgW2VkaXRvclZpZXcsIHNjcm9sbFN0YXRlTWFuYWdlcl0gb2Ygb3BlbkVkaXRvclZpZXdzKSB7XG5cblx0XHRcdFx0aWYoc2Nyb2xsU3RhdGVNYW5hZ2VyLmlzUmVhZHlGb3JHQykge1xuXHRcdFx0XHRcdG9wZW5FZGl0b3JWaWV3cy5kZWxldGUoZWRpdG9yVmlldyk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cbiAgICAgICAgaWYodHJhbnNhY3Rpb24uc3RhdGUuZmllbGQoZWRpdG9yTGl2ZVByZXZpZXdGaWVsZCkgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICByZXR1cm4gYnVpbGRlci5maW5pc2goKTtcbiAgICAgICAgfVxuXG5cdFx0aWYoIGlzVHJhbnNhY3Rpb25SYW5nZVNlbGVjdGlvbih0cmFuc2FjdGlvbikgPT09IHRydWUgKSB7XG5cdFx0XHRyZXR1cm4gYnVpbGRlci5maW5pc2goKTtcblx0XHR9XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFdoZW4gd2UgaGF2ZSB0aGUgd2hpbGUgZmlsZSB3ZSB0aGVuIGdldCB0aGUgZW50aXJlIGRvYyB0ZXh0IGFuZCBjaGVjayBpZiBpdCBcbiAgICAgICAgICogY29udGFpbnMgYSBNQ00gcmVnaW9uIHNvIHdlIGtub3cgdG8gYnJlYWsgb3Igbm90LlxuICAgICAgICAgKi9cbiAgICAgICAgbGV0IGRvY0xlbmd0aCA9IHRyYW5zYWN0aW9uLnN0YXRlLmRvYy5sZW5ndGhcbiAgICAgICAgbGV0IGRvY1RleHQgPSB0cmFuc2FjdGlvbi5zdGF0ZS5kb2Muc2xpY2VTdHJpbmcoMCwgZG9jTGVuZ3RoKTtcbiAgICAgICAgaWYgKGNvbnRhaW5zUmVnaW9uU3RhcnQoZG9jVGV4dCkgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICByZXR1cm4gYnVpbGRlci5maW5pc2goKTtcbiAgICAgICAgfVxuXG5cdFx0aWYobW91c2VTdGF0ZSA9PT0gXCJkb3duXCIpIHtcblx0XHRcdGVkaXRvck1vdXNlU3RhdGUgPSBtb3VzZVN0YXRlO1xuXHRcdH1cblxuXHRcdGNvbnN0IGVkaXRvclZpZXcgPSB0cmFuc2FjdGlvbi5zdGF0ZS5maWVsZChlZGl0b3JFZGl0b3JGaWVsZCk7XG5cdFx0XG5cdFx0bGV0IHNjcm9sbFN0YXRlTWFuYWdlcjogRWRpdG9yVmlld1Njcm9sbFN0YXRlTWFuYWdlciA9IGdldFNjcm9sbFN0YXRlTWFuYWdlcihlZGl0b3JWaWV3LCB0cmFuc2FjdGlvbik7XG5cdFx0c2Nyb2xsU3RhdGVNYW5hZ2VyLmxhc3REb2NTdGF0ZSA9IHRyYW5zYWN0aW9uLm5ld0RvY1xuXHRcdHNjcm9sbFN0YXRlTWFuYWdlci5kb2NUaXRsZSA9IGVkaXRvclZpZXcuZG9tLm93bmVyRG9jdW1lbnQudGl0bGU7XG5cblx0XHRpZihlZGl0b3JWaWV3Lmhhc0ZvY3VzID09PSB0cnVlKSB7XG5cdFx0XHRzY3JvbGxTdGF0ZU1hbmFnZXIuaGFzRm9jdXMgPSB0cnVlO1xuXHRcdH1cblxuXHRcdGxldCBjdXJzb3JMb2NhdGlvbjogU2VsZWN0aW9uUmFuZ2UgPSBnZXRNYWluQ3Vyc29yTG9jYXRpb24odHJhbnNhY3Rpb24pO1xuXHRcdGlmKGN1cnNvckxvY2F0aW9uICE9PSBudWxsKSB7XG5cdFx0XHRsZXQgdGV4dEFib3ZlQ3Vyc29yID0gZG9jVGV4dC5zbGljZSgwLCBjdXJzb3JMb2NhdGlvbi5mcm9tKTtcblxuXHRcdFx0bGV0IGVuZFRhZ0Fib3ZlQ3Vyc29yID0gY29udGFpbnNFbmRUYWcodGV4dEFib3ZlQ3Vyc29yKTtcblx0XHRcdGlmKGVuZFRhZ0Fib3ZlQ3Vyc29yID09PSBmYWxzZSkge1xuXHRcdFx0XHRyZXR1cm4gYnVpbGRlci5maW5pc2goKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRpZiggdHJhbnNhY3Rpb25Jc1ZhbGlkTW91c2VEb3duRXZlbnQodHJhbnNhY3Rpb24sIGN1cnNvckxvY2F0aW9uKSApIHtcblx0XHRcdFxuXHRcdFx0aGFuZGxlTW91c2VEb3duRXZlbnQodHJhbnNhY3Rpb24sIGVkaXRvclZpZXcsIGN1cnNvckxvY2F0aW9uKTtcblx0XHR9XG5cdFx0ZWxzZSBpZiggdHJhbnNhY3Rpb25Jc01vdXNlVXBFdmVudCh0cmFuc2FjdGlvbikgKSB7XG5cblx0XHRcdGhhbmRsZU1vdXNlVXBFdmVudCh0cmFuc2FjdGlvbik7XG5cdFx0fVxuXHRcdGVsc2UgaWYoZWRpdG9ySGFzQmVlbkNsaWNrZWRBd2F5RnJvbSh0cmFuc2FjdGlvbiwgZWRpdG9yVmlldywgc2Nyb2xsU3RhdGVNYW5hZ2VyKSkge1xuXG5cdFx0XHRsZXQgcmVmb2N1c0xvY2F0aW9uID0gc2hvdWxkUmVmb2N1c09uQ3Vyc29yT3JWaWV3cG9ydChlZGl0b3JWaWV3LCBjdXJzb3JMb2NhdGlvbiwgZG9jTGVuZ3RoKTtcblx0XHRcdHJlZm9jdXNPbkN1cnNvckFyZWEocmVmb2N1c0xvY2F0aW9uLCBlZGl0b3JWaWV3KTtcblx0XHRcdHNjcm9sbFN0YXRlTWFuYWdlci5oYXNGb2N1cyA9IGZhbHNlO1xuXHRcdH1cblx0XHQvLyBlbHNlIGlmKCBlZGl0b3JIYXNCZWVuQ2xpY2tlZEJhY2tJbnRvKHRyYW5zYWN0aW9uLCBzY3JvbGxTdGF0ZU1hbmFnZXIsIGVkaXRvclZpZXcpICl7XG5cdFx0Ly8gIC8vIFRPRE86IEJ1ZyB3aGVyZSBjbGlja2luZyBiYWNrIGludG8gZWRpdG9yIHdpdGhvdXQgc2VsZWN0aW5nIGEgbmV3IGN1cnNvciBsb2NhdGlvbiBcblx0XHQvLyAgLy8gd2lsbCBjYXVzZSBlZGl0b3IgdG8ganVtcCB0byB0b3Agb2YgZG9jLiBEbyBub3QgaGF2ZSB3YXkgdG8gcHJldmVudCB0aGlzIGFzIG9mIG5vdy5cblx0XHQvLyBcdGNvbnNvbGUubG9nKFwiRWRpdG9yIGhhcyBiZWVuIHJlZm9jdXNlZCB3aXRoIG51bGwgY3Vyc29yIGxvY2F0aW9uLlwiKVxuXHRcdC8vIH1cblx0XHRlbHNlIGlmKCBlZGl0b3JNb3VzZVN0YXRlID09PSBcImRvd25cIiAmJiBtb3VzZVN0YXRlID09PSBcInVwXCIgJiZcblx0XHRcdFx0IHRyYW5zYWN0aW9uLnN0YXRlLnNlbGVjdGlvbi5yYW5nZXMgJiYgXG5cdFx0XHRcdCB0cmFuc2FjdGlvbi5zdGF0ZS5zZWxlY3Rpb24ucmFuZ2VzLmxlbmd0aCA+IDAgKSB7XG5cblx0XHRcdGVkaXRvck1vdXNlU3RhdGUgPSBtb3VzZVN0YXRlO1xuXHRcdFx0bGV0IHJlZm9jdXNMb2NhdGlvbiA9IHNob3VsZFJlZm9jdXNPbkN1cnNvck9yVmlld3BvcnQoZWRpdG9yVmlldywgY3Vyc29yTG9jYXRpb24sIGRvY0xlbmd0aCk7XG5cdFx0XHRyZWZvY3VzT25DdXJzb3JBcmVhKHJlZm9jdXNMb2NhdGlvbiwgZWRpdG9yVmlldyk7XG5cdFx0fVxuXHRcdGVsc2Uge1xuXG5cdFx0XHRjbGVhclVuVXNlZEVudHJpZXModHJhbnNhY3Rpb24pO1xuXHRcdH1cblxuICAgICAgICByZXR1cm4gYnVpbGRlci5maW5pc2goKTtcblx0fSxcblx0cHJvdmlkZShmaWVsZDogU3RhdGVGaWVsZDxEZWNvcmF0aW9uU2V0Pik6IEV4dGVuc2lvbiB7XG5cdFx0cmV0dXJuIEVkaXRvclZpZXcuZGVjb3JhdGlvbnMuZnJvbShmaWVsZCk7XG5cdH0sXG59KTtcblxuZnVuY3Rpb24gZWRpdG9ySGFzQmVlbkNsaWNrZWRCYWNrSW50byh0cmFuc2FjdGlvbjogVHJhbnNhY3Rpb24sIHNjcm9sbFN0YXRlTWFuYWdlcjogRWRpdG9yVmlld1Njcm9sbFN0YXRlTWFuYWdlciwgZWRpdG9yVmlldzogRWRpdG9yVmlldyk6IGJvb2xlYW4ge1xuXG5cdGlmKHRyYW5zYWN0aW9uLmlzVXNlckV2ZW50KFwic2VsZWN0LnBvaW50ZXJcIikgPT09IGZhbHNlICYmXG5cdCAgIHNjcm9sbFN0YXRlTWFuYWdlci5oYXNGb2N1cyA9PT0gZmFsc2UgJiZcblx0ICAgc2Nyb2xsU3RhdGVNYW5hZ2VyLnJlZ2FpbmVkRm9jdXMgPT09IGZhbHNlICYmIFxuXHQgICBzY3JvbGxTdGF0ZU1hbmFnZXIubG9zdEZvY3VzID09PSBmYWxzZSAmJiBcblx0ICAgZWRpdG9yVmlldy5pblZpZXcpIHtcblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxuXG5cdHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gZ2V0TWFpbkN1cnNvckxvY2F0aW9uKHRyYW5zYWN0aW9uOiBUcmFuc2FjdGlvbik6IFNlbGVjdGlvblJhbmdlIHtcblxuXHRsZXQgY3Vyc29yTG9jYXRpb246IFNlbGVjdGlvblJhbmdlID0gbnVsbDtcblx0aWYgKHRyYW5zYWN0aW9uLnN0YXRlLnNlbGVjdGlvbi5yYW5nZXMgJiZcblx0XHR0cmFuc2FjdGlvbi5zdGF0ZS5zZWxlY3Rpb24ucmFuZ2VzLmxlbmd0aCA+IDApIHtcblxuXHRcdGN1cnNvckxvY2F0aW9uID0gdHJhbnNhY3Rpb24uc3RhdGUuc2VsZWN0aW9uLnJhbmdlc1swXTtcblx0fVxuXG5cdHJldHVybiBjdXJzb3JMb2NhdGlvbjtcbn1cblxuZnVuY3Rpb24gaGFuZGxlTW91c2VEb3duRXZlbnQodHJhbnNhY3Rpb246IFRyYW5zYWN0aW9uLCBlZGl0b3JWaWV3OiBFZGl0b3JWaWV3LCBjdXJzb3JMb2NhdGlvbjogU2VsZWN0aW9uUmFuZ2UpIHtcblxuXHRsZXQgeDogVHJhbnNhY3Rpb25TcGVjID0ge1xuXHRcdGVmZmVjdHM6IEVkaXRvclZpZXcuc2Nyb2xsSW50b1ZpZXcoY3Vyc29yTG9jYXRpb24sIHtcblx0XHRcdHk6IFwiY2VudGVyXCJcblx0XHR9KVxuXHR9O1xuXG5cdGFzeW5jIGZ1bmN0aW9uIGRlbGF5KCkge1xuXHRcdGF3YWl0IHNsZWVwKDE1KTtcblx0XHRlZGl0b3JWaWV3LmRpc3BhdGNoKHgpO1xuXHR9XG5cdGxldCBkZWxheUNhbGxiYWNrRGF0YSA9IG5ldyBFZGl0b3JEZWxheUNhbGxiYWNrKCk7XG5cdGRlbGF5Q2FsbGJhY2tEYXRhLmNhbGxiYWNrID0gZGVsYXk7XG5cdGNsaWNrRGVsYXlDYWxsYmFja3Muc2V0KHRyYW5zYWN0aW9uLnN0YXRlLnNsaWNlRG9jKCksIGRlbGF5Q2FsbGJhY2tEYXRhKTtcblxuXHRpZiAoaXNSYW5nZWRTZWxlY3Rpb24oW2N1cnNvckxvY2F0aW9uXSkgPT09IGZhbHNlIHx8XG5cdFx0ZGVsYXlDYWxsYmFja0RhdGEucmVnYWluZWRGb2N1cyA9PT0gdHJ1ZSkge1xuXHRcdGRlbGF5KCk7XG5cdH1cbn1cblxuZnVuY3Rpb24gdHJhbnNhY3Rpb25Jc1ZhbGlkTW91c2VEb3duRXZlbnQodHJhbnNhY3Rpb246IFRyYW5zYWN0aW9uLCBjdXJzb3JMb2NhdGlvbjogU2VsZWN0aW9uUmFuZ2UpIHtcblx0cmV0dXJuIHRyYW5zYWN0aW9uLmlzVXNlckV2ZW50KFwic2VsZWN0LnBvaW50ZXJcIikgJiZcblx0XHRjdXJzb3JMb2NhdGlvbiAhPT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gdHJhbnNhY3Rpb25Jc01vdXNlVXBFdmVudCh0cmFuc2FjdGlvbjogVHJhbnNhY3Rpb24pOiBib29sZWFuIHtcblxuXHRpZiggdHJhbnNhY3Rpb24uZG9jQ2hhbmdlZCA9PT0gZmFsc2UgJiYgXG5cdCAgICBjbGlja0RlbGF5Q2FsbGJhY2tzLmhhcyh0cmFuc2FjdGlvbi5zdGF0ZS5zbGljZURvYygpKSApIHtcblxuXHRcdFx0ZWRpdG9yTW91c2VTdGF0ZSA9IG1vdXNlU3RhdGU7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxuXHRyZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGdldFNjcm9sbFN0YXRlTWFuYWdlcihlZGl0b3JWaWV3OiBFZGl0b3JWaWV3LCB0cmFuc2FjdGlvbjogVHJhbnNhY3Rpb24pIHtcblx0XG5cdGlmIChvcGVuRWRpdG9yVmlld3MuaGFzKGVkaXRvclZpZXcpID09PSBmYWxzZSkge1xuXG5cdFx0bGV0IHNjcm9sbFN0YXRlTWFuYWdlcjogRWRpdG9yVmlld1Njcm9sbFN0YXRlTWFuYWdlciA9IG5ldyBFZGl0b3JWaWV3U2Nyb2xsU3RhdGVNYW5hZ2VyKGVkaXRvclZpZXcpO1xuXHRcdG9wZW5FZGl0b3JWaWV3cy5zZXQoZWRpdG9yVmlldywgc2Nyb2xsU3RhdGVNYW5hZ2VyKTtcblxuXHRcdHJldHVybiBzY3JvbGxTdGF0ZU1hbmFnZXI7XG5cdH1cblxuXHRsZXQgc2Nyb2xsU3RhdGVNYW5hZ2VyOiBFZGl0b3JWaWV3U2Nyb2xsU3RhdGVNYW5hZ2VyID0gb3BlbkVkaXRvclZpZXdzLmdldChlZGl0b3JWaWV3KTtcblx0aWYgKHRyYW5zYWN0aW9uU3dhcHBlZEVkaXRvckZpbGUodHJhbnNhY3Rpb24sIHNjcm9sbFN0YXRlTWFuYWdlcikpIHtcblxuXHRcdHNjcm9sbFN0YXRlTWFuYWdlciA9IG5ldyBFZGl0b3JWaWV3U2Nyb2xsU3RhdGVNYW5hZ2VyKGVkaXRvclZpZXcpO1xuXHRcdG9wZW5FZGl0b3JWaWV3cy5zZXQoZWRpdG9yVmlldywgc2Nyb2xsU3RhdGVNYW5hZ2VyKTtcblx0XHRyZXR1cm4gc2Nyb2xsU3RhdGVNYW5hZ2VyO1xuXHR9XG5cblx0c2Nyb2xsU3RhdGVNYW5hZ2VyLmhhc0JlZW5BY2Nlc3NlZCgpO1x0XG5cdHJldHVybiBzY3JvbGxTdGF0ZU1hbmFnZXI7XG59XG5cbmZ1bmN0aW9uIGhhbmRsZU1vdXNlVXBFdmVudCh0cmFuc2FjdGlvbjogVHJhbnNhY3Rpb24pIHtcblxuXHRsZXQgZGVsYXlDYWxsYmFja0RhdGEgPSBjbGlja0RlbGF5Q2FsbGJhY2tzLmdldCh0cmFuc2FjdGlvbi5zdGF0ZS5zbGljZURvYygpKTtcblx0ZGVsYXlDYWxsYmFja0RhdGEuY2FsbGJhY2soKTtcblx0aWYgKGRlbGF5Q2FsbGJhY2tEYXRhLmNhbGxiYWNrU2hvdWxkVGltZW91dCA9PT0gdHJ1ZSkge1xuXHRcdGNsaWNrRGVsYXlDYWxsYmFja3MuZGVsZXRlKHRyYW5zYWN0aW9uLnN0YXRlLnNsaWNlRG9jKCkpO1xuXHR9XG59XG5cbmZ1bmN0aW9uIGNsZWFyVW5Vc2VkRW50cmllcyh0cmFuc2FjdGlvbjogVHJhbnNhY3Rpb24pIHtcblxuXHRmb3IgKGxldCBba2V5LCB2YWx1ZV0gb2YgY2xpY2tEZWxheUNhbGxiYWNrcykge1xuXHRcdGlmICh2YWx1ZS5jYWxsYmFja1Nob3VsZFRpbWVvdXQgPT09IHRydWUpIHtcblx0XHRcdGNsaWNrRGVsYXlDYWxsYmFja3MuZGVsZXRlKHRyYW5zYWN0aW9uLnN0YXRlLnNsaWNlRG9jKCkpO1xuXHRcdH1cblx0fVxufVxuXG5mdW5jdGlvbiBzaG91bGRSZWZvY3VzT25DdXJzb3JPclZpZXdwb3J0KGVkaXRvclZpZXc6IEVkaXRvclZpZXcsIGN1cnNvckxvY2F0aW9uOiBTZWxlY3Rpb25SYW5nZSwgZG9jTGVuZ3RoOiBudW1iZXIpOiBTZWxlY3Rpb25SYW5nZSB7XG5cblx0Y29uc3QgVklFV1BPUlRfQ1VSU09SX1JFRk9DVVNfUkFOR0UgPSAzMDA7XG5cblx0bGV0IHZpZXdwb3J0UmFuZ2UgPSBlZGl0b3JWaWV3LnZpZXdwb3J0O1xuXHRpZih2aWV3cG9ydFJhbmdlLmZyb20gKyBWSUVXUE9SVF9DVVJTT1JfUkVGT0NVU19SQU5HRSA8PSBjdXJzb3JMb2NhdGlvbi5mcm9tICYmIGN1cnNvckxvY2F0aW9uLmZyb20gPD0gdmlld3BvcnRSYW5nZS50byAtIFZJRVdQT1JUX0NVUlNPUl9SRUZPQ1VTX1JBTkdFKSB7XG5cdFx0cmV0dXJuIGN1cnNvckxvY2F0aW9uO1xuXHR9XG5cblx0aWYodmlld3BvcnRSYW5nZS5mcm9tID09PSAwKSB7XG5cdFx0cmV0dXJuIEVkaXRvclNlbGVjdGlvbi5jdXJzb3IoMCk7XG5cdH1cblxuXHRpZih2aWV3cG9ydFJhbmdlLnRvID49IGRvY0xlbmd0aCkge1xuXHRcdHJldHVybiBFZGl0b3JTZWxlY3Rpb24uY3Vyc29yKGRvY0xlbmd0aCk7XG5cdH1cblxuXHRsZXQgbG9jYXRpb24gPSB2aWV3cG9ydFJhbmdlLmZyb20gKyBNYXRoLmZsb29yKCh2aWV3cG9ydFJhbmdlLnRvIC0gdmlld3BvcnRSYW5nZS5mcm9tKSAvIDIpO1xuXHRyZXR1cm4gRWRpdG9yU2VsZWN0aW9uLmN1cnNvcihsb2NhdGlvbilcbn1cblxuZnVuY3Rpb24gcmVmb2N1c09uQ3Vyc29yQXJlYShjdXJzb3JMb2NhdGlvbjogU2VsZWN0aW9uUmFuZ2UsIGVkaXRvclZpZXc6IEVkaXRvclZpZXcpIHtcblxuXHRsZXQgeDogVHJhbnNhY3Rpb25TcGVjID0ge1xuXHRcdGVmZmVjdHM6IEVkaXRvclZpZXcuc2Nyb2xsSW50b1ZpZXcoY3Vyc29yTG9jYXRpb24sIHtcblx0XHRcdHk6IFwiY2VudGVyXCJcblx0XHR9KVxuXHR9XG5cblx0YXN5bmMgZnVuY3Rpb24gZGVsYXkoKSB7XG5cdFx0YXdhaXQgc2xlZXAoMTAwKTtcblx0XHRlZGl0b3JWaWV3LmRpc3BhdGNoKHgpXG5cdH1cblx0ZGVsYXkoKVxufVxuXG5mdW5jdGlvbiBlZGl0b3JIYXNCZWVuQ2xpY2tlZEF3YXlGcm9tKHRyYW5zYWN0aW9uOiBUcmFuc2FjdGlvbiwgZWRpdG9yVmlldzogRWRpdG9yVmlldywgc2Nyb2xsU3RhdGVNYW5hZ2VyOiBFZGl0b3JWaWV3U2Nyb2xsU3RhdGVNYW5hZ2VyKTogYm9vbGVhbiB7XG5cblx0aWYoIHRyYW5zYWN0aW9uLmRvY0NoYW5nZWQgPT09IGZhbHNlICYmIFxuXHRcdGVkaXRvclZpZXcuaGFzRm9jdXMgICAgPT09IGZhbHNlICYmIFxuXHRcdGVkaXRvclZpZXcuaW5WaWV3ICAgICAgPT09IHRydWUgICYmXG5cdFx0c2Nyb2xsU3RhdGVNYW5hZ2VyLmhhc0ZvY3VzICA9PT0gdHJ1ZSAgJiZcblx0XHRzY3JvbGxTdGF0ZU1hbmFnZXIubG9zdEZvY3VzID09PSB0cnVlICAgICkge1xuXHRcdHJldHVybiB0cnVlO1xuXHR9XG5cdHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNSYW5nZWRTZWxlY3Rpb24oY3Vyc29yTG9jYXRpb25zOiBTZWxlY3Rpb25SYW5nZVtdKSB7XG5cblx0Zm9yKGxldCByYW5nZSBvZiBjdXJzb3JMb2NhdGlvbnMpIHtcblx0XHRpZihyYW5nZS50byAtIHJhbmdlLmZyb20gPiAxKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cdH1cblx0cmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBpc1RyYW5zYWN0aW9uUmFuZ2VTZWxlY3Rpb24odHJhbnNhY3Rpb246IFRyYW5zYWN0aW9uKTogYm9vbGVhbiB7XG5cblx0aWYodHJhbnNhY3Rpb24uaXNVc2VyRXZlbnQoXCJzZWxlY3QucG9pbnRlclwiKSAmJiBcblx0ICAgdHJhbnNhY3Rpb24uc3RhdGUuc2VsZWN0aW9uLnJhbmdlcyAmJiBcblx0ICAgdHJhbnNhY3Rpb24uc3RhdGUuc2VsZWN0aW9uLnJhbmdlcy5sZW5ndGggPiAwICYmXG5cdCAgIGlzUmFuZ2VkU2VsZWN0aW9uKHRyYW5zYWN0aW9uLnN0YXRlLnNlbGVjdGlvbi5yYW5nZXMuc2xpY2UoKSkpIHtcblxuXHRcdHJldHVybiB0cnVlO1xuXHR9XG5cdHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gdHJhbnNhY3Rpb25Td2FwcGVkRWRpdG9yRmlsZSh0cmFuc2FjdGlvbjogVHJhbnNhY3Rpb24sIHNjcm9sbFN0YXRlTWFuYWdlcjogRWRpdG9yVmlld1Njcm9sbFN0YXRlTWFuYWdlcik6IGJvb2xlYW4ge1xuXG5cdC8vIElmIG9uIHRoaXMgdHJhbnNhY3Rpb24gdGhlcmUgYXJlIG11bHRpcGxlIHNlbGVjdGlvbiByYW5nZXMgd2Uga25vd1xuXHQvLyB0aGUgdXNlciBjYW4gbm90IGhhdmUgc3dhcHBlZCB0byBhIG5ldyBmaWxlIHRoaXMgdHJhbnNhY3Rpb24uXG5cdGlmKHRyYW5zYWN0aW9uLnN0YXRlLnNlbGVjdGlvbi5yYW5nZXMubGVuZ3RoICE9PSAxKSB7XG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG5cblx0Ly8gT24gbmV3IGRvY3VtZW50IGxvYWQgdGhlIGN1cnNvciBpcyBwbGFjZWQgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgZmlsZS5cblx0Ly8gSWYgY3Vyc29yIGlzIG5vdCBhdCB0aGlzIGxvY2F0aW9uIHdlIGtub3cgaXQgaXNudCBkb2N1bWVudCBsb2FkLlxuXHRpZih0cmFuc2FjdGlvbi5zdGF0ZS5zZWxlY3Rpb24ucmFuZ2VzWzBdLmZyb20gIT09IDAgJiZcblx0ICAgdHJhbnNhY3Rpb24uc3RhdGUuc2VsZWN0aW9uLnJhbmdlc1swXS50byAgICE9PSAwKSB7XG5cdCAgIHJldHVybiBmYWxzZTtcblx0fVxuXG5cdC8vIE1ha2Ugc3VyZSB0cmFuc2FjdGlvbiBpcyBub3QgYWxzbyBhIHVzZXIgZXZlbnQuIEF0IHRoaXMgcG9pbnQgc2hvdWxkIHdlIGJlIGZhaXJseVxuXHQvLyBjZXJ0YWluIHRoYXQgdGhpcyBpcyBhIGRvY3VtZW50IGxvYWQ/XG5cdGlmKHRyYW5zYWN0aW9uLmlzVXNlckV2ZW50KFwiaW5wdXRcIikgIHx8IFxuXHQgICB0cmFuc2FjdGlvbi5pc1VzZXJFdmVudChcImRlbGV0ZVwiKSB8fFxuXHQgICB0cmFuc2FjdGlvbi5pc1VzZXJFdmVudChcIm1vdmVcIikgICB8fCBcblx0ICAgdHJhbnNhY3Rpb24uaXNVc2VyRXZlbnQoXCJzZWxlY3RcIikgfHxcblx0ICAgdHJhbnNhY3Rpb24uaXNVc2VyRXZlbnQoXCJ1bmRvXCIpICAgfHxcblx0ICAgdHJhbnNhY3Rpb24uaXNVc2VyRXZlbnQoXCJyZWRvXCIpKSB7XG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG5cblx0aWYoc2Nyb2xsU3RhdGVNYW5hZ2VyLmxhc3REb2NTdGF0ZSA9PT0gdHJhbnNhY3Rpb24ubmV3RG9jKSB7XG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG5cblx0cmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIHNob3VsZFJ1bkdDT25FZGl0b3JNYXAoKTogYm9vbGVhbiB7XG5cdFxuXHRjb25zdCBHQ19ERUxUQV9USU1FUiA9IDMwMDAwIC8vIDMwc1xuXG5cdGxldCBkZWx0YSA9IERhdGUubm93KCkgLSBsYXN0R0NQYXNzO1xuXHRpZihkZWx0YSA+IEdDX0RFTFRBX1RJTUVSKSB7XG5cblx0XHRsYXN0R0NQYXNzID0gRGF0ZS5ub3coKTtcblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxuXHRyZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGF0dGVtcHRQYXJzZURvY1RpdGxlKHZhbHVlOiBzdHJpbmcpIHtcblxuXHRmb3IobGV0IGkgPSAwOyBpIDwgMjsgaSsrKSB7XG5cblx0XHRsZXQgcmVzdWx0ID0gLyguKikgLSAuKi8uZXhlYyh2YWx1ZSlcblx0XHRpZihyZXN1bHQgIT09IG51bGwgJiYgcmVzdWx0Lmxlbmd0aCA+IDEpIHtcblx0XHRcdHZhbHVlID0gcmVzdWx0WzFdO1xuXHRcdH1cblx0XHRlbHNlIHtcblx0XHRcdHJldHVybiBcIlwiXG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIHZhbHVlO1xufSIsImV4cG9ydCB0eXBlIFN5bnRheFJlc3VsdCA9IHtcbiAgICBmaWxlQ291bnQ6IG51bWJlcjtcbiAgICByZWdpb25TdGFydENvdW50OiBudW1iZXI7XG4gICAgY29sdW1uQnJlYWtDb3VudDogbnVtYmVyXG4gICAgY29sdW1uRW5kQ291bnQ6IG51bWJlcjtcbiAgICB1cGRhdGVkRmlsZUNvbnRlbnQ6IHN0cmluZztcbiAgICBmaWxlV2FzVXBkYXRlZDogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHVwZGF0ZUFsbFN5bnRheChvcmlnaW5hbEZpbGVDb250ZW50OiBzdHJpbmcpOiBTeW50YXhSZXN1bHQge1xuXG4gICAgbGV0IGZpbGVDb3VudCA9IDBcbiAgICBsZXQgcmVnaW9uU3RhcnRDb3VudCA9IDA7XG4gICAgbGV0IGNvbHVtbkJyZWFrQ291bnQgPSAwO1xuICAgIGxldCBjb2x1bW5FbmRDb3VudCA9IDA7XG5cbiAgICBsZXQgZmlsZVVwZGF0ZWQgPSBmYWxzZTtcbiAgICBsZXQgeyB1cGRhdGVkRmlsZUNvbnRlbnQsIG51bVJlZ2lvbnNVcGRhdGVkIH0gPSB1cGRhdGVDb2x1bW5Db2RlYmxvY2tTdGFydFN5bnRheChvcmlnaW5hbEZpbGVDb250ZW50KTtcbiAgICBpZihudW1SZWdpb25zVXBkYXRlZCA+IDApIHtcbiAgICAgICAgZmlsZUNvdW50Kys7XG4gICAgICAgIGZpbGVVcGRhdGVkID0gdHJ1ZTtcbiAgICAgICAgcmVnaW9uU3RhcnRDb3VudCArPSBudW1SZWdpb25zVXBkYXRlZFxuICAgIH1cblxuICAgIGxldCBjb2xTdGFydCA9IHVwZGF0ZUNvbHVtblN0YXJ0U3ludGF4KHVwZGF0ZWRGaWxlQ29udGVudClcbiAgICBpZihjb2xTdGFydC5udW1SZWdpb25zVXBkYXRlZCkge1xuICAgICAgICBpZihmaWxlVXBkYXRlZCA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIGZpbGVVcGRhdGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIGZpbGVDb3VudCsrO1xuICAgICAgICB9XG4gICAgICAgIHVwZGF0ZWRGaWxlQ29udGVudCA9IGNvbFN0YXJ0LnVwZGF0ZWRGaWxlQ29udGVudFxuICAgICAgICByZWdpb25TdGFydENvdW50ICs9IGNvbFN0YXJ0Lm51bVJlZ2lvbnNVcGRhdGVkXG4gICAgfVxuXG4gICAgbGV0IGNvbEJyZWFrID0gdXBkYXRlQ29sdW1uQnJlYWtTeW50YXgodXBkYXRlZEZpbGVDb250ZW50KVxuICAgIGlmKGNvbEJyZWFrLm51bVJlZ2lvbnNVcGRhdGVkKSB7XG4gICAgICAgIGlmKGZpbGVVcGRhdGVkID09PSBmYWxzZSkge1xuICAgICAgICAgICAgZmlsZVVwZGF0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgZmlsZUNvdW50Kys7XG4gICAgICAgIH1cbiAgICAgICAgdXBkYXRlZEZpbGVDb250ZW50ID0gY29sQnJlYWsudXBkYXRlZEZpbGVDb250ZW50XG4gICAgICAgIGNvbHVtbkJyZWFrQ291bnQgKz0gY29sQnJlYWsubnVtUmVnaW9uc1VwZGF0ZWRcbiAgICB9XG5cbiAgICBsZXQgY29sRW5kID0gdXBkYXRlQ29sdW1uRW5kU3ludGF4KHVwZGF0ZWRGaWxlQ29udGVudClcbiAgICBpZihjb2xFbmQubnVtUmVnaW9uc1VwZGF0ZWQpIHtcbiAgICAgICAgaWYoZmlsZVVwZGF0ZWQgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICBmaWxlVXBkYXRlZCA9IHRydWU7XG4gICAgICAgICAgICBmaWxlQ291bnQrKztcbiAgICAgICAgfVxuICAgICAgICB1cGRhdGVkRmlsZUNvbnRlbnQgPSBjb2xFbmQudXBkYXRlZEZpbGVDb250ZW50XG4gICAgICAgIGNvbHVtbkVuZENvdW50ICs9IGNvbEVuZC5udW1SZWdpb25zVXBkYXRlZDsgICBcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBmaWxlQ291bnQ6IGZpbGVDb3VudCxcbiAgICAgICAgcmVnaW9uU3RhcnRDb3VudDogcmVnaW9uU3RhcnRDb3VudCxcbiAgICAgICAgY29sdW1uQnJlYWtDb3VudDogY29sdW1uQnJlYWtDb3VudCxcbiAgICAgICAgY29sdW1uRW5kQ291bnQ6IGNvbHVtbkVuZENvdW50LFxuICAgICAgICB1cGRhdGVkRmlsZUNvbnRlbnQ6IHVwZGF0ZWRGaWxlQ29udGVudCxcbiAgICAgICAgZmlsZVdhc1VwZGF0ZWQ6IHVwZGF0ZWRGaWxlQ29udGVudCAhPT0gb3JpZ2luYWxGaWxlQ29udGVudFxuICAgIH1cbn1cblxuY29uc3QgT0xEX0NPTF9FTkRfU1lOVEFYX1JFR0VYID0gLz09PSAqKGVuZC1tdWx0aS1jb2x1bW58bXVsdGktY29sdW1uLWVuZCkvZ1xuZnVuY3Rpb24gdXBkYXRlQ29sdW1uRW5kU3ludGF4KG9yaWdpbmFsRmlsZUNvbnRlbnQ6IHN0cmluZyk6IHsgdXBkYXRlZEZpbGVDb250ZW50OiBzdHJpbmcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG51bVJlZ2lvbnNVcGRhdGVkOiBudW1iZXIgfSB7XG4gICAgbGV0IG1hdGNoZXMgPSBBcnJheS5mcm9tKG9yaWdpbmFsRmlsZUNvbnRlbnQubWF0Y2hBbGwoT0xEX0NPTF9FTkRfU1lOVEFYX1JFR0VYKSlcblxuICAgIGxldCB1cGRhdGVkRmlsZUNvbnRlbnQgPSBvcmlnaW5hbEZpbGVDb250ZW50O1xuICAgIGxldCBvZmZzZXQgPSAwO1xuICAgIFxuICAgIGZvcihsZXQgbWF0Y2ggb2YgbWF0Y2hlcykgeyAgICBcbiAgICAgICAgbGV0IHN0YXJ0SW5kZXggPSBtYXRjaC5pbmRleCArIG9mZnNldFxuICAgICAgICBsZXQgbWF0Y2hMZW5ndGggPSBtYXRjaFswXS5sZW5ndGhcbiAgICAgICAgbGV0IGVuZEluZGV4ID0gc3RhcnRJbmRleCArIG1hdGNoTGVuZ3RoO1xuXG4gICAgICAgIGxldCBjb2x1bW5FbmRTeW50YXggPSBtYXRjaFsxXSAgICAgICAgXG4gICAgICAgIGxldCByZXBsYWNlbWVudFRleHQgPSBgLS0tICR7Y29sdW1uRW5kU3ludGF4fWBcbiAgICAgICAgb2Zmc2V0ICs9IHJlcGxhY2VtZW50VGV4dC5sZW5ndGggLSBtYXRjaExlbmd0aFxuXG4gICAgICAgIHVwZGF0ZWRGaWxlQ29udGVudCA9IHVwZGF0ZWRGaWxlQ29udGVudC5zbGljZSgwLCBzdGFydEluZGV4KSArIHJlcGxhY2VtZW50VGV4dCArIHVwZGF0ZWRGaWxlQ29udGVudC5zbGljZShlbmRJbmRleClcbiAgICAgICAgY29uc29sZS5ncm91cENvbGxhcHNlZCgpXG4gICAgICAgIGNvbnNvbGUubG9nKFwiT3JpZ2luYWwgRmlsZTpcXG5cXG5cIiwgb3JpZ2luYWxGaWxlQ29udGVudClcbiAgICAgICAgY29uc29sZS5sb2coXCJVcGRhdGVkIEZpbGU6XFxuXFxuXCIsIHVwZGF0ZWRGaWxlQ29udGVudClcbiAgICAgICAgY29uc29sZS5ncm91cEVuZCgpICAgICAgXG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICAgIHVwZGF0ZWRGaWxlQ29udGVudDogdXBkYXRlZEZpbGVDb250ZW50LFxuICAgICAgICBudW1SZWdpb25zVXBkYXRlZDogbWF0Y2hlcy5sZW5ndGhcbiAgICB9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxufVxuXG5jb25zdCBPTERfQ09MX0JSRUFLX1NZTlRBWF9SRUdFWCA9IC89PT1cXHMqPyhjb2x1bW4tZW5kfGVuZC1jb2x1bW58Y29sdW1uLWJyZWFrfGJyZWFrLWNvbHVtbilcXHMqPz09PVxccyo/L2dcbmZ1bmN0aW9uIHVwZGF0ZUNvbHVtbkJyZWFrU3ludGF4KG9yaWdpbmFsRmlsZUNvbnRlbnQ6IHN0cmluZyk6IHsgdXBkYXRlZEZpbGVDb250ZW50OiBzdHJpbmcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG51bVJlZ2lvbnNVcGRhdGVkOiBudW1iZXIgfSB7XG4gICAgbGV0IG1hdGNoZXMgPSBBcnJheS5mcm9tKG9yaWdpbmFsRmlsZUNvbnRlbnQubWF0Y2hBbGwoT0xEX0NPTF9CUkVBS19TWU5UQVhfUkVHRVgpKVxuXG4gICAgbGV0IHVwZGF0ZWRGaWxlQ29udGVudCA9IG9yaWdpbmFsRmlsZUNvbnRlbnQ7XG4gICAgbGV0IG9mZnNldCA9IDA7XG4gICAgXG4gICAgZm9yKGxldCBtYXRjaCBvZiBtYXRjaGVzKSB7ICAgIFxuICAgICAgICBsZXQgc3RhcnRJbmRleCA9IG1hdGNoLmluZGV4ICsgb2Zmc2V0XG4gICAgICAgIGxldCBtYXRjaExlbmd0aCA9IG1hdGNoWzBdLmxlbmd0aFxuICAgICAgICBsZXQgZW5kSW5kZXggPSBzdGFydEluZGV4ICsgbWF0Y2hMZW5ndGg7XG5cbiAgICAgICAgbGV0IGNvbHVtbkJyZWFrU3ludGF4ID0gbWF0Y2hbMV0gICAgICAgIFxuICAgICAgICBsZXQgcmVwbGFjZW1lbnRUZXh0ID0gYC0tLSAke2NvbHVtbkJyZWFrU3ludGF4fSAtLS1gXG4gICAgICAgIG9mZnNldCArPSByZXBsYWNlbWVudFRleHQubGVuZ3RoIC0gbWF0Y2hMZW5ndGhcblxuICAgICAgICB1cGRhdGVkRmlsZUNvbnRlbnQgPSB1cGRhdGVkRmlsZUNvbnRlbnQuc2xpY2UoMCwgc3RhcnRJbmRleCkgKyByZXBsYWNlbWVudFRleHQgKyB1cGRhdGVkRmlsZUNvbnRlbnQuc2xpY2UoZW5kSW5kZXgpXG4gICAgICAgIGNvbnNvbGUuZ3JvdXBDb2xsYXBzZWQoKVxuICAgICAgICBjb25zb2xlLmxvZyhcIk9yaWdpbmFsIEZpbGU6XFxuXFxuXCIsIG9yaWdpbmFsRmlsZUNvbnRlbnQpXG4gICAgICAgIGNvbnNvbGUubG9nKFwiVXBkYXRlZCBGaWxlOlxcblxcblwiLCB1cGRhdGVkRmlsZUNvbnRlbnQpXG4gICAgICAgIGNvbnNvbGUuZ3JvdXBFbmQoKSAgICAgIFxuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgICB1cGRhdGVkRmlsZUNvbnRlbnQ6IHVwZGF0ZWRGaWxlQ29udGVudCxcbiAgICAgICAgbnVtUmVnaW9uc1VwZGF0ZWQ6IG1hdGNoZXMubGVuZ3RoXG4gICAgfSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbn1cblxuY29uc3QgT0xEX0NPTF9TVEFSVF9TWU5UQVhfUkVHRVggPSAvPT09ICooc3RhcnQtbXVsdGktY29sdW1ufG11bHRpLWNvbHVtbi1zdGFydCkvZ1xuZnVuY3Rpb24gdXBkYXRlQ29sdW1uU3RhcnRTeW50YXgob3JpZ2luYWxGaWxlQ29udGVudDogc3RyaW5nKTogeyB1cGRhdGVkRmlsZUNvbnRlbnQ6IHN0cmluZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbnVtUmVnaW9uc1VwZGF0ZWQ6IG51bWJlciB9IHtcbiAgICBsZXQgbWF0Y2hlcyA9IEFycmF5LmZyb20ob3JpZ2luYWxGaWxlQ29udGVudC5tYXRjaEFsbChPTERfQ09MX1NUQVJUX1NZTlRBWF9SRUdFWCkpXG5cbiAgICBsZXQgdXBkYXRlZEZpbGVDb250ZW50ID0gb3JpZ2luYWxGaWxlQ29udGVudDtcbiAgICBsZXQgb2Zmc2V0ID0gMDtcbiAgICBcbiAgICBmb3IobGV0IG1hdGNoIG9mIG1hdGNoZXMpIHsgICAgXG4gICAgICAgIGxldCBzdGFydEluZGV4ID0gbWF0Y2guaW5kZXggKyBvZmZzZXRcbiAgICAgICAgbGV0IG1hdGNoTGVuZ3RoID0gbWF0Y2hbMF0ubGVuZ3RoXG4gICAgICAgIGxldCBlbmRJbmRleCA9IHN0YXJ0SW5kZXggKyBtYXRjaExlbmd0aDtcblxuICAgICAgICBsZXQgY29sdW1uU3RhcnRTeW50YXggPSBtYXRjaFsxXSAgICAgICAgXG4gICAgICAgIGxldCByZXBsYWNlbWVudFRleHQgPSBgLS0tICR7Y29sdW1uU3RhcnRTeW50YXh9YFxuICAgICAgICBvZmZzZXQgKz0gcmVwbGFjZW1lbnRUZXh0Lmxlbmd0aCAtIG1hdGNoTGVuZ3RoXG5cbiAgICAgICAgdXBkYXRlZEZpbGVDb250ZW50ID0gdXBkYXRlZEZpbGVDb250ZW50LnNsaWNlKDAsIHN0YXJ0SW5kZXgpICsgcmVwbGFjZW1lbnRUZXh0ICsgdXBkYXRlZEZpbGVDb250ZW50LnNsaWNlKGVuZEluZGV4KVxuICAgICAgICBjb25zb2xlLmdyb3VwQ29sbGFwc2VkKClcbiAgICAgICAgY29uc29sZS5sb2coXCJPcmlnaW5hbCBGaWxlOlxcblxcblwiLCBvcmlnaW5hbEZpbGVDb250ZW50KVxuICAgICAgICBjb25zb2xlLmxvZyhcIlVwZGF0ZWQgRmlsZTpcXG5cXG5cIiwgdXBkYXRlZEZpbGVDb250ZW50KVxuICAgICAgICBjb25zb2xlLmdyb3VwRW5kKCkgICAgICBcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgdXBkYXRlZEZpbGVDb250ZW50OiB1cGRhdGVkRmlsZUNvbnRlbnQsXG4gICAgICAgIG51bVJlZ2lvbnNVcGRhdGVkOiBtYXRjaGVzLmxlbmd0aFxuICAgIH0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG59XG5cbmNvbnN0IE9MRF9DT0RFQkxPQ0tfQ09MX1NUQVJUX1NZTlRBWF9SRUdFWCA9IC9gYGAoc3RhcnQtbXVsdGktY29sdW1ufG11bHRpLWNvbHVtbi1zdGFydCkuKj9gYGAvc2c7XG5mdW5jdGlvbiB1cGRhdGVDb2x1bW5Db2RlYmxvY2tTdGFydFN5bnRheChvcmlnaW5hbEZpbGVDb250ZW50OiBzdHJpbmcpOiB7IHVwZGF0ZWRGaWxlQ29udGVudDogc3RyaW5nLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBudW1SZWdpb25zVXBkYXRlZDogbnVtYmVyIH0ge1xuICAgIGxldCBtYXRjaGVzID0gQXJyYXkuZnJvbShvcmlnaW5hbEZpbGVDb250ZW50Lm1hdGNoQWxsKE9MRF9DT0RFQkxPQ0tfQ09MX1NUQVJUX1NZTlRBWF9SRUdFWCkpXG5cbiAgICBsZXQgdXBkYXRlZEZpbGVDb250ZW50ID0gb3JpZ2luYWxGaWxlQ29udGVudDtcbiAgICBsZXQgb2Zmc2V0ID0gMDtcbiAgICBcbiAgICBmb3IobGV0IG1hdGNoIG9mIG1hdGNoZXMpIHtcblxuICAgICAgICBsZXQgc3RhcnRJbmRleCA9IG1hdGNoLmluZGV4ICsgb2Zmc2V0XG4gICAgICAgIGxldCBtYXRjaExlbmd0aCA9IG1hdGNoWzBdLmxlbmd0aFxuICAgICAgICBsZXQgZW5kSW5kZXggPSBzdGFydEluZGV4ICsgbWF0Y2hMZW5ndGg7XG5cbiAgICAgICAgbGV0IG9yaWdpbmFsU2V0dGluZ3NUZXh0ID0gbWF0Y2hbMF1cbiAgICAgICAgbGV0IHNldHRpbmdzVGV4dCA9IG9yaWdpbmFsU2V0dGluZ3NUZXh0XG4gICAgICAgIGxldCBjb2x1bW5TdGFydFN5bnRheCA9IG1hdGNoWzFdXG4gICAgICAgIGxldCBjb2x1bW5TdGFydExpbmUgPSBgLS0tICR7Y29sdW1uU3RhcnRTeW50YXh9YFxuXG4gICAgICAgIFxuICAgICAgICBsZXQgaWRSZXN1bHQgPSAvSUQ6KC4qKS9pLmV4ZWMob3JpZ2luYWxTZXR0aW5nc1RleHQpXG4gICAgICAgIGlmKGlkUmVzdWx0ICE9PSBudWxsKSB7XG4gICAgICAgICAgICBsZXQgaWQgPSBpZFJlc3VsdFsxXS50cmltKClcbiAgICAgICAgICAgIGNvbHVtblN0YXJ0TGluZSA9IGAke2NvbHVtblN0YXJ0TGluZX06ICR7aWR9YFxuXG4gICAgICAgICAgICBsZXQgc3RhcnRJbmRleCA9IGlkUmVzdWx0LmluZGV4XG4gICAgICAgICAgICBsZXQgZW5kSW5kZXggPSBzdGFydEluZGV4ICsgaWRSZXN1bHRbMF0ubGVuZ3RoXG5cbiAgICAgICAgICAgIHNldHRpbmdzVGV4dCA9IG9yaWdpbmFsU2V0dGluZ3NUZXh0LnNsaWNlKDAsIHN0YXJ0SW5kZXgpXG4gICAgICAgICAgICBzZXR0aW5nc1RleHQgKz0gb3JpZ2luYWxTZXR0aW5nc1RleHQuc2xpY2UoZW5kSW5kZXggKyAxKVxuICAgICAgICB9XG4gICAgICAgIHNldHRpbmdzVGV4dCA9IHNldHRpbmdzVGV4dC5yZXBsYWNlKGNvbHVtblN0YXJ0U3ludGF4LCBcImNvbHVtbi1zZXR0aW5nc1wiKVxuICAgICAgICBcbiAgICAgICAgbGV0IHJlcGxhY2VtZW50VGV4dCA9IGAke2NvbHVtblN0YXJ0TGluZX1cXG4ke3NldHRpbmdzVGV4dH1gXG5cbiAgICAgICAgb2Zmc2V0ICs9IHJlcGxhY2VtZW50VGV4dC5sZW5ndGggLSBtYXRjaExlbmd0aFxuXG4gICAgICAgIHVwZGF0ZWRGaWxlQ29udGVudCA9IHVwZGF0ZWRGaWxlQ29udGVudC5zbGljZSgwLCBzdGFydEluZGV4KSArIHJlcGxhY2VtZW50VGV4dCArIHVwZGF0ZWRGaWxlQ29udGVudC5zbGljZShlbmRJbmRleClcbiAgICAgICAgY29uc29sZS5ncm91cENvbGxhcHNlZCgpXG4gICAgICAgIGNvbnNvbGUubG9nKFwiT3JpZ2luYWwgRmlsZTpcXG5cXG5cIiwgb3JpZ2luYWxGaWxlQ29udGVudClcbiAgICAgICAgY29uc29sZS5sb2coXCJVcGRhdGVkIEZpbGU6XFxuXFxuXCIsIHVwZGF0ZWRGaWxlQ29udGVudClcbiAgICAgICAgY29uc29sZS5ncm91cEVuZCgpXG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgdXBkYXRlZEZpbGVDb250ZW50OiB1cGRhdGVkRmlsZUNvbnRlbnQsXG4gICAgICAgIG51bVJlZ2lvbnNVcGRhdGVkOiBtYXRjaGVzLmxlbmd0aFxuICAgIH1cbn0iLCJpbXBvcnQgeyBBcHAsIEJ1dHRvbkNvbXBvbmVudCwgTW9kYWwsIE5vdGljZSwgUGxhdGZvcm0sIFBsdWdpblNldHRpbmdUYWIsIFNldHRpbmcgfSBmcm9tIFwib2JzaWRpYW5cIjtcbmltcG9ydCBNdWx0aUNvbHVtbk1hcmtkb3duIGZyb20gXCJzcmMvbWFpblwiO1xuaW1wb3J0ICogYXMgbXVsdGlDb2x1bW5QYXJzZXIgZnJvbSAnLi4vdXRpbGl0aWVzL3RleHRQYXJzZXInO1xuaW1wb3J0IHsgZ2V0VUlEIH0gZnJvbSBcInNyYy91dGlsaXRpZXMvdXRpbHNcIjtcbmltcG9ydCB7IHVwZGF0ZUFsbFN5bnRheCB9IGZyb20gXCJzcmMvdXRpbGl0aWVzL3N5bnRheFVwZGF0ZVwiO1xuaW1wb3J0IHsgTUNNX1NldHRpbmdzTWFuYWdlciB9IGZyb20gXCJzcmMvcGx1Z2luU2V0dGluZ3NcIjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTXVsdGlDb2x1bW5TZXR0aW5nc1ZpZXcgZXh0ZW5kcyBQbHVnaW5TZXR0aW5nVGFiIHtcblxuICAgIGNvbnN0cnVjdG9yKGFwcDogQXBwLCBwdWJsaWMgcGx1Z2luOiBNdWx0aUNvbHVtbk1hcmtkb3duKSB7XG4gICAgICAgIHN1cGVyKGFwcCwgcGx1Z2luKTtcbiAgICB9XG4gICAgXG4gICAgZGlzcGxheSgpIHtcbiAgICAgICAgdGhpcy5jb250YWluZXJFbC5lbXB0eSgpO1xuICAgICAgICB0aGlzLmNvbnRhaW5lckVsLmNyZWF0ZUVsKFwiaDJcIiwgeyB0ZXh0OiBcIk11bHRpLUNvbHVtbiBNYXJrZG93biAtIFNldHRpbmdzXCIgfSk7XG5cbiAgICAgICAgY29uc3Qgc2V0dGluZ3NDb250YWluZXJFbCA9IHRoaXMuY29udGFpbmVyRWwuY3JlYXRlRGl2KCk7XG5cbiAgICAgICAgbmV3IFNldHRpbmcoc2V0dGluZ3NDb250YWluZXJFbClcbiAgICAgICAgICAgIC5zZXROYW1lKFwiTnVtYmVyIG9mIGF1dG8tbGF5b3V0IGJhbGFuY2UgaXRlcmF0aW9uc1wiKVxuICAgICAgICAgICAgLnNldERlc2MoXCJUaGUgbWF4aW11bSBudW1iZXIgb2YgdGltZXMgYXV0by1sYXlvdXQgd2lsbCB0cnkgdG8gYmFsYW5jZSBlbGVtZW50cyBiZXR3ZWVuIGFsbCBvZiB0aGUgY29sdW1ucy4gU2V0dGluZyB0aGlzIHRvbyBoaWdoIG1heSBjYXVzZSBPYnNpZGlhbiB0byBzbG93IGRvd24gZHVyaW5nIGxvYWRpbmcgYW5kIHJlZnJlc2hpbmcgb2YgQXV0by1MYXlvdXQgY29sdW1ucy5cIilcbiAgICAgICAgICAgIC5hZGRTbGlkZXIoKHNsaWRlcikgPT4ge1xuICAgICAgICAgICAgICAgIHNsaWRlci5zZXRMaW1pdHMoMSwgMTUsIDIpXG4gICAgICAgICAgICAgICAgc2xpZGVyLnNldFZhbHVlKE1DTV9TZXR0aW5nc01hbmFnZXIuc2hhcmVkLmF1dG9MYXlvdXRCYWxhbmNlSXRlcmF0aW9ucylcbiAgICAgICAgICAgICAgICBzbGlkZXIuc2V0RHluYW1pY1Rvb2x0aXAoKVxuICAgICAgICAgICAgICAgIHNsaWRlci5vbkNoYW5nZSgodmFsKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIE1DTV9TZXR0aW5nc01hbmFnZXIuc2hhcmVkLmF1dG9MYXlvdXRCYWxhbmNlSXRlcmF0aW9ucyA9IHZhbDtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKClcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgfSlcblxuICAgICAgICBuZXcgU2V0dGluZyhzZXR0aW5nc0NvbnRhaW5lckVsKVxuICAgICAgICAuc2V0TmFtZShcIkFsaWduIHRhYmxlcyB3aXRoIHRleHQgYWxpZ25tZW50IGJ5IGRlZmF1bHRcIilcbiAgICAgICAgLnNldERlc2ModGhpcy5idWlsZFRhYmxlQWxpZ25Eb2NGcmFnKCkpXG4gICAgICAgIC5hZGRUb2dnbGUoKHQpID0+XG4gICAgICAgICAgICB0LnNldFZhbHVlKE1DTV9TZXR0aW5nc01hbmFnZXIuc2hhcmVkLmFsaWduVGFibGVzVG9Db250ZW50QWxpZ25tZW50KVxuICAgICAgICAgICAgLm9uQ2hhbmdlKCh2KSA9PiB7XG4gICAgICAgICAgICAgICAgTUNNX1NldHRpbmdzTWFuYWdlci5zaGFyZWQuYWxpZ25UYWJsZXNUb0NvbnRlbnRBbGlnbm1lbnQgPSB2XG4gICAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKClcbiAgICAgICAgICAgIH0pXG4gICAgICAgIClcblxuICAgICAgICBuZXcgU2V0dGluZyhzZXR0aW5nc0NvbnRhaW5lckVsKVxuICAgICAgICAuc2V0TmFtZShcIlVzZSBMaXZlIFByZXZpZXcgcmVuZGVyIGNhY2hlXCIpXG4gICAgICAgIC5zZXREZXNjKHRoaXMuYnVpbGRSZW5kZXJDYWNoZURvY0ZyYWcoKSlcbiAgICAgICAgLmFkZFRvZ2dsZSgodCkgPT5cbiAgICAgICAgICAgIHQuc2V0VmFsdWUoTUNNX1NldHRpbmdzTWFuYWdlci5zaGFyZWQudXNlTGl2ZVByZXZpZXdDYWNoZSlcbiAgICAgICAgICAgIC5vbkNoYW5nZSgodikgPT4ge1xuICAgICAgICAgICAgICAgIE1DTV9TZXR0aW5nc01hbmFnZXIuc2hhcmVkLnVzZUxpdmVQcmV2aWV3Q2FjaGUgPSB2XG4gICAgICAgICAgICAgICAgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKClcbiAgICAgICAgICAgIH0pXG4gICAgICAgIClcblxuICAgICAgICBpZihQbGF0Zm9ybS5pc01vYmlsZSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgbmV3IFNldHRpbmcoc2V0dGluZ3NDb250YWluZXJFbClcbiAgICAgICAgICAgICAgICAuc2V0TmFtZShcIlJlbmRlciBjb2x1bW4gcmVnaW9ucyBvbiBtb2JpbGUgZGV2aWNlc1wiKVxuICAgICAgICAgICAgICAgIC5hZGRUb2dnbGUoKHQpID0+XG4gICAgICAgICAgICAgICAgICAgIHQuc2V0VmFsdWUoTUNNX1NldHRpbmdzTWFuYWdlci5zaGFyZWQucmVuZGVyT25Nb2JpbGUpLm9uQ2hhbmdlKCh2KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBNQ01fU2V0dGluZ3NNYW5hZ2VyLnNoYXJlZC5yZW5kZXJPbk1vYmlsZSA9IHZcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpXG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuY29udGFpbmVyRWwuY3JlYXRlRWwoXCJoNVwiLCB7IGF0dHI6IHtcInN0eWxlXCI6IFwiY29sb3I6IHZhcigtLXRleHQtZXJyb3IpOyBtYXJnaW4tYm90dG9tOiAwcHg7XCJ9LCB0ZXh0OiBcIkRBTkdFUiBaT05FXCIgfSk7XG4gICAgICAgIHRoaXMuY29udGFpbmVyRWwuY3JlYXRlRWwoXCJoclwiLCB7IGF0dHI6IHtcInN0eWxlXCI6IFwibWFyZ2luLXRvcDogMXB4OyBtYXJnaW4tYm90dG9tOiAwLjc1ZW07XCJ9IH0pXG4gICAgICAgIGNvbnN0IGRhbmdlclpvbmVDb250YWluZXJFbCA9IHRoaXMuY29udGFpbmVyRWwuY3JlYXRlRGl2KCk7XG5cbiAgICAgICAgdGhpcy5idWlsZFVwZGF0ZURlcHJpY2F0ZWQoZGFuZ2VyWm9uZUNvbnRhaW5lckVsKTtcbiAgICAgICAgdGhpcy5idWlsZEZpeE1pc3NpbmdJRHMoZGFuZ2VyWm9uZUNvbnRhaW5lckVsKTtcblxuICAgICAgICB0aGlzLmNvbnRhaW5lckVsLmNyZWF0ZUVsKFwiYnJcIilcblxuICAgICAgICBsZXQgeyBiZ0NvbG9yLCBmb250Q29sb3IsIGNvZmZlZUNvbG9yIH0gPSBnZXREb25hdGVCdXR0b25Db2xvcnModGhpcy5jb250YWluZXJFbCk7XG4gICAgICAgIG5ldyBTZXR0aW5nKHRoaXMuY29udGFpbmVyRWwpXG4gICAgICAgIC5zZXROYW1lKFwiRG9uYXRlXCIpXG4gICAgICAgIC5zZXREZXNjKGBJZiB5b3UgbGlrZSB0aGlzIFBsdWdpbiwgcGxlYXNlIGNvbnNpZGVyIHByb3ZpZGluZyBhIG9uZSB0aW1lIGRvbmF0aW9uIHRvIHN1cHBvcnQgaXQncyBkZXZlbG9wbWVudC5gKVxuICAgICAgICAuYWRkQnV0dG9uKChiKSA9PiB7XG4gICAgICAgICAgICBiLmJ1dHRvbkVsLnNldEF0dHIoXCJzdHlsZVwiLCBcImJhY2tncm91bmQtY29sb3I6IHRyYW5zcGFyZW50OyBoZWlnaHQ6IDMwcHQ7IHBhZGRpbmc6IDBweDtcIilcbiAgICAgICAgICAgIGNvbnN0IGRpdiA9IGIuYnV0dG9uRWwuY3JlYXRlRGl2KHthdHRyOiB7XCJzdHlsZVwiOiBcIndpZHRoOiAxMDAlOyBoZWlnaHQ6IDEwMCVcIn19KTtcbiAgICAgICAgICAgIGRpdi5jcmVhdGVFbChcImFcIiwge1xuICAgICAgICAgICAgICAgIGhyZWY6IFwiaHR0cHM6Ly93d3cuYnV5bWVhY29mZmVlLmNvbS9ja3JvYmluc29uXCJcbiAgICAgICAgICAgIH0pLmNyZWF0ZUVsKFwiaW1nXCIsIHtcbiAgICAgICAgICAgICAgICBhdHRyOiB7XG4gICAgICAgICAgICAgICAgICAgIHN0eWxlOiBcIndpZHRoOiAxMDAlOyBoZWlnaHQ6IDEwMCVcIixcbiAgICAgICAgICAgICAgICAgICAgc3JjOiBgaHR0cHM6Ly9pbWcuYnV5bWVhY29mZmVlLmNvbS9idXR0b24tYXBpLz90ZXh0PUJ1eSBtZSBhIGNvZmZlZSZlbW9qaT0mc2x1Zz1ja3JvYmluc29uJmJ1dHRvbl9jb2xvdXI9JHtiZ0NvbG9yfSZmb250X2NvbG91cj0ke2ZvbnRDb2xvcn0mZm9udF9mYW1pbHk9Q29va2llJm91dGxpbmVfY29sb3VyPTAwMDAwMCZjb2ZmZWVfY29sb3VyPSR7Y29mZmVlQ29sb3J9YFxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgIH0pXG4gICAgfVxuXG4gICAgcHJpdmF0ZSBidWlsZFJlbmRlckNhY2hlRG9jRnJhZygpOiBEb2N1bWVudEZyYWdtZW50IHtcbiAgICAgICAgbGV0IGRvY0ZyYWcgPSBuZXcgRG9jdW1lbnRGcmFnbWVudCgpO1xuICAgICAgICBkb2NGcmFnLmNyZWF0ZURpdih7fSwgZGl2ID0+IHtcbiAgICAgICAgICAgIGRpdi5jcmVhdGVTcGFuKHt9LCBzcGFuID0+IHtcbiAgICAgICAgICAgICAgICBzcGFuLmlubmVyVGV4dCA9IFwiQ2FjaGVzIHJlbmRlcmVkIGNvbnRlbnQgaW4gTGl2ZSBQcmV2aWV3IHRvIHJlZHVjZSByZW5kZXIgY3ljbGVzIGFuZCBlbGVtZW50IGZsYXNoaW5nIG9uIG5vdGUgaW50ZXJhY3Rpb24uXCI7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGRpdi5jcmVhdGVFbChcImJyXCIpO1xuICAgICAgICAgICAgZGl2LmNyZWF0ZUVsKFwiYnJcIik7XG4gICAgICAgICAgICBkaXYuY3JlYXRlU3Bhbih7fSwgc3BhbiA9PiB7XG4gICAgICAgICAgICAgICAgc3Bhbi5pbm5lclRleHQgPSBcIk9ubHkgdXNlcyBjYWNoZSB3aGVuIGEgZmlsZSBMaXZlIFByZXZpZXcgdGFiIGlzIG9wZW4uIElmIGJvdGggcmVhZGluZyB2aWV3IGFuZCBMaXZlIFByZXZpZXcgYXJlIG9wZW5lZCB0aGlzIGZlYXR1cmUgaXMgZGlzYWJsZWQuXCI7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGRpdi5jcmVhdGVFbChcImJyXCIpO1xuICAgICAgICAgICAgZGl2LmNyZWF0ZUVsKFwiYnJcIik7XG4gICAgICAgICAgICBkaXYuY3JlYXRlRWwoXCJoNVwiLCB7fSwgc3BhbiA9PiB7XG4gICAgICAgICAgICAgICAgc3Bhbi5zZXRBdHRyKFwic3R5bGVcIiwgXCJjb2xvcjogdmFyKC0tdGV4dC1lcnJvcik7IG1hcmdpbi1ib3R0b206IDBweDsgbWFyZ2luLXRvcDogM3B4O1wiKTtcbiAgICAgICAgICAgICAgICBzcGFuLmlubmVyVGV4dCA9IFwiRVhQRVJJTUVOVEFMOlwiO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBkaXYuY3JlYXRlU3Bhbih7fSwgc3BhbiA9PiB7XG4gICAgICAgICAgICAgICAgc3Bhbi5zZXRBdHRyKFwic3R5bGVcIiwgXCJjb2xvcjogdmFyKC0tdGV4dC1lcnJvcik7XCIpO1xuICAgICAgICAgICAgICAgIHNwYW4uaW5uZXJUZXh0ID0gXCJUaGlzIGZlYXR1cmUgaXMgZXhwZXJpbWVudGFsIG9ubHkgYW5kIGhhcyBpbnRlcm1pdHRlbnRseSBjYXVzZWQgbm90ZXMgdG8gZXJhc2UgY29sdW1uIGNvbnRlbnQgZHVyaW5nIGRldmVsb3BtZW50LiBBIGZpeCBoYXMgYmVlbiBpbXBsZW1lbnRlZCBcXFxuICAgICAgICAgICAgICAgIGJ1dCBkdWUgdG8gdGhlIHBvdGVudGlhbCBkYXRhIGxvc3MgeW91IG11c3Qgb3B0LWluIHRvIHVzaW5nIHRoaXMgZmVhdHVyZS4gSWYgY29udGVudCBpcyBlcmFzZWQgeW91IGNhbiB1c2UgVW5kbyB0byByZXN0b3JlIHRoZSBmaWxlIGRhdGEuIFxcXG4gICAgICAgICAgICAgICAgUGxlYXNlIG1ha2UgYmFja3VwcyBhbmQgZGlzYWJsZSBpZiB5b3UgZXhwZXJpZW5jZSBhbnkgZGF0YSBsb3NzLlwiO1xuICAgICAgICAgICAgfSk7XG5cblxuICAgICAgICB9KVxuICAgICAgICByZXR1cm4gZG9jRnJhZztcbiAgICB9XG5cbiAgICBwcml2YXRlIGJ1aWxkVGFibGVBbGlnbkRvY0ZyYWcoKTogRG9jdW1lbnRGcmFnbWVudCB7XG4gICAgICAgIGxldCBkb2NGcmFnID0gbmV3IERvY3VtZW50RnJhZ21lbnQoKTtcbiAgICAgICAgZG9jRnJhZy5jcmVhdGVEaXYoe30sIGRpdiA9PiB7XG4gICAgICAgICAgICBkaXYuY3JlYXRlU3Bhbih7fSwgc3BhbiA9PiB7XG4gICAgICAgICAgICAgICAgc3Bhbi5pbm5lclRleHQgPSBcIlNldHMgdGhlIGRlZmFsdXQgYmVoYXZpb3Igd2hlbiBkZXRlcm1pbmluZyB3aGV0aGVyIHRvIGFsaWduIHRhYmxlIHRvIHRleHQgYWxpZ25tZW50LlwiO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBkaXYuY3JlYXRlRWwoXCJiclwiKTtcbiAgICAgICAgICAgIGRpdi5jcmVhdGVFbChcInVsXCIpLmNyZWF0ZUVsKFwibGlcIiwgeyB0ZXh0OiBcIlRoaXMgdmFsdWUgaXMgb3ZlcndyaXR0ZW4gd2hlbiBkZWZpbmluZyB0aGUgY29sdW1uIHNldHRpbmc6ICdBbGlnbiBUYWJsZXMgdG8gVGV4dCBBbGlnbm1lbnQ6IHRydWUvZmFsc2UnXCIgfSlcbiAgICAgICAgfSlcbiAgICAgICAgcmV0dXJuIGRvY0ZyYWc7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBidWlsZFVwZGF0ZURlcHJpY2F0ZWQoZGFuZ2VyWm9uZUNvbnRhaW5lckVsOiBIVE1MRGl2RWxlbWVudCkge1xuXG4gICAgICAgIGxldCBkb2NGcmFnID0gbmV3IERvY3VtZW50RnJhZ21lbnQoKTtcbiAgICAgICAgZG9jRnJhZy5jcmVhdGVEaXYoe30sIGRpdiA9PiB7XG4gICAgICAgICAgICBkaXYuY3JlYXRlU3Bhbih7fSwgc3BhbiA9PiB7XG4gICAgICAgICAgICAgICAgc3Bhbi5pbm5lclRleHQgPSBcIlRoaXMgbWF5IHRha2UgYSB3aGlsZSBmb3IgbGFyZ2UgdmF1bHRzLCB5b3UgY2FuIGNvbnRpbnVlIHRvIHVzZSBPYnNpZGlhbiBidXQgYXBwbGljYXRpb24gbWF5IHNsb3cgZG93biBkdXJpbmcgcHJvY2Vzcy5cIjtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgZGl2LmNyZWF0ZUVsKFwiYnJcIik7XG4gICAgICAgICAgICBkaXYuY3JlYXRlRWwoXCJiclwiKTtcbiAgICAgICAgICAgIGRpdi5jcmVhdGVFbChcImg1XCIsIHt9LCBzcGFuID0+IHtcbiAgICAgICAgICAgICAgICBzcGFuLnNldEF0dHIoXCJzdHlsZVwiLCBcImNvbG9yOiB2YXIoLS10ZXh0LWVycm9yKTsgbWFyZ2luLWJvdHRvbTogMHB4OyBtYXJnaW4tdG9wOiAzcHg7XCIpO1xuICAgICAgICAgICAgICAgIHNwYW4uaW5uZXJUZXh0ID0gXCJXQVJOSU5HOlwiO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBkaXYuY3JlYXRlU3Bhbih7fSwgc3BhbiA9PiB7XG4gICAgICAgICAgICAgICAgc3Bhbi5zZXRBdHRyKFwic3R5bGVcIiwgXCJjb2xvcjogdmFyKC0tdGV4dC1lcnJvcik7XCIpO1xuICAgICAgICAgICAgICAgIHNwYW4uaW5uZXJUZXh0ID0gXCJUaGlzIGFjdGlvbiBtb2RpZmllcyBhbnkgbm90ZSBmaWxlIHdpdGggZGVwcmljYXRlZCBzeW50YXggYW5kIGNvdWxkIGxlYWQgdG8gY29ycnVwdGVkIGZpbGUgdGV4dC5cIjtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgZGl2LmNyZWF0ZUVsKFwiYnJcIik7XG4gICAgICAgICAgICBkaXYuY3JlYXRlU3Bhbih7fSwgc3BhbiA9PiB7XG4gICAgICAgICAgICAgICAgc3Bhbi5zZXRBdHRyKFwic3R5bGVcIiwgXCJjb2xvcjogdmFyKC0tdGV4dC1lcnJvcik7XCIpO1xuICAgICAgICAgICAgICAgIHNwYW4uaW5uZXJUZXh0ID0gXCJObyBndWFyZW50ZWUgaXMgZ2l2ZW4uIFBsZWFzZSBtYWtlIHN1cmUgdG8gYmFjayB5b3VyIHZhdWx0IHVwIGZpcnN0LlwiO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgICBsZXQgbW9kYWxEZXNjcmlwdGlvbkVsID0gY3JlYXRlRGl2KHt9LCBkaXYgPT4ge1xuICAgICAgICAgICAgZGl2LmNyZWF0ZVNwYW4oeyB0ZXh0OiBcIlRoaXMgYWN0aW9uIG1heSBjb3JydXB0IHZhdWx0IGRhdGEuXCIgfSk7XG4gICAgICAgICAgICBkaXYuY3JlYXRlRWwoXCJiclwiKTtcbiAgICAgICAgICAgIGRpdi5jcmVhdGVTcGFuKHsgdGV4dDogXCJQbGVhc2UgY29uZmlybSB5b3UgaGF2ZSBiYWNrZWQgdXAgeW91ciB2YXVsdC5cIiB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIG5ldyBTZXR0aW5nKGRhbmdlclpvbmVDb250YWluZXJFbClcbiAgICAgICAgICAgIC5zZXROYW1lKFwiVXBkYXRlIEFMTCBkZXByaWNhdGVkIE11bHRpLUNvbHVtbiBzeW50YXguXCIpXG4gICAgICAgICAgICAuc2V0RGVzYyhkb2NGcmFnKVxuICAgICAgICAgICAgLmFkZEJ1dHRvbigoYikgPT4gYi5zZXRCdXR0b25UZXh0KFwiVXBkYXRlIFN5bnRheFwiKS5vbkNsaWNrKCgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBtb2RhbCA9IENvbmZpcm1Nb2RhbC5jb25maXJtTW9kYWxXaXRoRWxlbWVudCh0aGlzLmFwcCwgbW9kYWxEZXNjcmlwdGlvbkVsLCB7IHByaW1hcnk6IFwiQ29uZmlybVwiLCBzZWNvbmRhcnk6IFwiQ2FuY2VsXCIgfSk7XG4gICAgICAgICAgICAgICAgbW9kYWwub25DbG9zZSA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG1vZGFsLmNvbmZpcm1lZCA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHVwZGF0ZUZpbGVTeW50YXgoKTtcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIG1vZGFsLm9wZW4oKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICApO1xuICAgIH1cblxuICAgIHByaXZhdGUgYnVpbGRGaXhNaXNzaW5nSURzKGRhbmdlclpvbmVDb250YWluZXJFbDogSFRNTERpdkVsZW1lbnQpIHtcbiAgICAgICAgXG4gICAgICAgIGxldCBkb2NGcmFnID0gbmV3IERvY3VtZW50RnJhZ21lbnQoKTtcbiAgICAgICAgZG9jRnJhZy5jcmVhdGVEaXYoe30sIGRpdiA9PiB7XG4gICAgICAgICAgICBkaXYuY3JlYXRlU3Bhbih7fSwgc3BhbiA9PiB7XG4gICAgICAgICAgICAgICAgc3Bhbi5pbm5lclRleHQgPSBcIlRoaXMgd2lsbCBvbmx5IG1vZGlmeSBjb2x1bW4gcmVnaW9ucyB3aXRob3V0IGEgcHJlLWRlZmluZWQgSUQsIGFuZCB3aGljaCB1c2UgdGhlIHVwIHRvIGRhdGUgY29yZSBzeW50YXguIFdpbGwgbm90IG1vZGlmeSBkZXByaWNhdGVkIHN5bnRheCBvciBmZW5jZWQtZGl2cy5cIjtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgZGl2LmNyZWF0ZUVsKFwiYnJcIik7XG4gICAgICAgICAgICBkaXYuY3JlYXRlRWwoXCJiclwiKTtcbiAgICAgICAgICAgIGRpdi5jcmVhdGVTcGFuKHt9LCBzcGFuID0+IHtcbiAgICAgICAgICAgICAgICBzcGFuLmlubmVyVGV4dCA9IFwiVGhpcyBtYXkgdGFrZSBhIHdoaWxlIGZvciBsYXJnZSB2YXVsdHMsIHlvdSBjYW4gY29udGludWUgdG8gdXNlIE9ic2lkaWFuIGJ1dCBhcHBsaWNhdGlvbiBtYXkgc2xvdyBkb3duIGR1cmluZyBwcm9jZXNzLlwiO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBkaXYuY3JlYXRlRWwoXCJiclwiKTtcbiAgICAgICAgICAgIGRpdi5jcmVhdGVFbChcImJyXCIpO1xuICAgICAgICAgICAgZGl2LmNyZWF0ZUVsKFwiaDVcIiwge30sIHNwYW4gPT4ge1xuICAgICAgICAgICAgICAgIHNwYW4uc2V0QXR0cihcInN0eWxlXCIsIFwiY29sb3I6IHZhcigtLXRleHQtZXJyb3IpOyBtYXJnaW4tYm90dG9tOiAwcHg7IG1hcmdpbi10b3A6IDNweDtcIik7XG4gICAgICAgICAgICAgICAgc3Bhbi5pbm5lclRleHQgPSBcIldBUk5JTkc6XCI7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGRpdi5jcmVhdGVTcGFuKHt9LCBzcGFuID0+IHtcbiAgICAgICAgICAgICAgICBzcGFuLnNldEF0dHIoXCJzdHlsZVwiLCBcImNvbG9yOiB2YXIoLS10ZXh0LWVycm9yKTtcIik7XG4gICAgICAgICAgICAgICAgc3Bhbi5pbm5lclRleHQgPSBcIlRoaXMgYWN0aW9uIG1vZGlmaWVzIGFueSBub3RlIGZpbGUgbWlzc2luZyBjb2x1bW4gSURzIGFuZCBjb3VsZCBsZWFkIHRvIGNvcnJ1cHRlZCBmaWxlIHRleHQuXCI7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGRpdi5jcmVhdGVFbChcImJyXCIpO1xuICAgICAgICAgICAgZGl2LmNyZWF0ZVNwYW4oe30sIHNwYW4gPT4ge1xuICAgICAgICAgICAgICAgIHNwYW4uc2V0QXR0cihcInN0eWxlXCIsIFwiY29sb3I6IHZhcigtLXRleHQtZXJyb3IpO1wiKTtcbiAgICAgICAgICAgICAgICBzcGFuLmlubmVyVGV4dCA9IFwiTm8gZ3VhcmVudGVlIGlzIGdpdmVuLiBQbGVhc2UgbWFrZSBzdXJlIHRvIGJhY2sgeW91ciB2YXVsdCB1cCBmaXJzdC5cIjtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgICAgbGV0IG1vZGFsRGVzY3JpcHRpb25FbCA9IGNyZWF0ZURpdih7fSwgZGl2ID0+IHtcbiAgICAgICAgICAgIGRpdi5jcmVhdGVTcGFuKHsgdGV4dDogXCJUaGlzIGFjdGlvbiBtYXkgY29ycnVwdCB2YXVsdCBkYXRhLlwiIH0pO1xuICAgICAgICAgICAgZGl2LmNyZWF0ZUVsKFwiYnJcIik7XG4gICAgICAgICAgICBkaXYuY3JlYXRlU3Bhbih7IHRleHQ6IFwiUGxlYXNlIGNvbmZpcm0geW91IGhhdmUgYmFja2VkIHVwIHlvdXIgdmF1bHQuXCIgfSk7XG4gICAgICAgIH0pO1xuICAgICAgICBuZXcgU2V0dGluZyhkYW5nZXJab25lQ29udGFpbmVyRWwpXG4gICAgICAgICAgICAuc2V0TmFtZShcIkFwcGVuZCBJRHMgdG8gYWxsIE11bHRpLUNvbHVtbiByZWdpb25zIGluIHZhdWx0LlwiKVxuICAgICAgICAgICAgLnNldERlc2MoZG9jRnJhZylcbiAgICAgICAgICAgIC5hZGRCdXR0b24oKGIpID0+IGIuc2V0QnV0dG9uVGV4dChcIkFkZCBJRHNcIikub25DbGljaygoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgbW9kYWwgPSBDb25maXJtTW9kYWwuY29uZmlybU1vZGFsV2l0aEVsZW1lbnQodGhpcy5hcHAsIG1vZGFsRGVzY3JpcHRpb25FbCwgeyBwcmltYXJ5OiBcIkNvbmZpcm1cIiwgc2Vjb25kYXJ5OiBcIkNhbmNlbFwiIH0pO1xuICAgICAgICAgICAgICAgIG1vZGFsLm9uQ2xvc2UgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChtb2RhbC5jb25maXJtZWQgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBmaW5kQW5kUmVwbGFjZU1pc3NpbmdJRHMoKTtcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIG1vZGFsLm9wZW4oKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICk7XG4gICAgfVxufVxuXG5leHBvcnQgY2xhc3MgQ29uZmlybU1vZGFsIGV4dGVuZHMgTW9kYWwge1xuXG4gICAgc3RhdGljIGNvbmZpcm1Nb2RhbFdpdGhUZXh0KGFwcDogQXBwLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0OiBzdHJpbmcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ1dHRvbnM6IHsgcHJpbWFyeTogc3RyaW5nOyBzZWNvbmRhcnk6IHN0cmluZyB9KTogQ29uZmlybU1vZGFsIHtcblxuICAgICAgICByZXR1cm4gbmV3IENvbmZpcm1Nb2RhbChhcHAsIGNyZWF0ZVNwYW4oe3RleHQ6IHRleHR9KSwgYnV0dG9ucylcbiAgICB9XG5cbiAgICBzdGF0aWMgY29uZmlybU1vZGFsV2l0aEVsZW1lbnQoYXBwOiBBcHAsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uRWw6IEhUTUxFbGVtZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBidXR0b25zOiB7IHByaW1hcnk6IHN0cmluZzsgc2Vjb25kYXJ5OiBzdHJpbmcgfSk6IENvbmZpcm1Nb2RhbCB7XG4gICAgICAgIHJldHVybiBuZXcgQ29uZmlybU1vZGFsKGFwcCwgZGVzY3JpcHRpb25FbCwgYnV0dG9ucylcbiAgICB9XG5cbiAgICBwdWJsaWMgZGVzY3JpcHRpb25FbDogSFRNTEVsZW1lbnRcbiAgICBwdWJsaWMgYnV0dG9uczogeyBwcmltYXJ5OiBzdHJpbmc7IHNlY29uZGFyeTogc3RyaW5nIH1cbiAgICBwcml2YXRlIGNvbnN0cnVjdG9yKGFwcDogQXBwLCBcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uRWw6IEhUTUxFbGVtZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgYnV0dG9uczogeyBwcmltYXJ5OiBzdHJpbmc7IHNlY29uZGFyeTogc3RyaW5nIH0pIHtcbiAgICAgICAgc3VwZXIoYXBwKTtcbiAgICAgICAgdGhpcy5kZXNjcmlwdGlvbkVsID0gZGVzY3JpcHRpb25FbDtcbiAgICAgICAgdGhpcy5idXR0b25zID0gYnV0dG9ucztcbiAgICB9XG4gICAgY29uZmlybWVkOiBib29sZWFuID0gZmFsc2U7XG4gICAgYXN5bmMgZGlzcGxheSgpIHtcbiAgICAgICAgdGhpcy5jb250ZW50RWwuZW1wdHkoKTtcbiAgICAgICAgdGhpcy5jb250ZW50RWwuYXBwZW5kQ2hpbGQodGhpcy5kZXNjcmlwdGlvbkVsKVxuXG4gICAgICAgIGNvbnN0IGJ1dHRvbkVsID0gdGhpcy5jb250ZW50RWwuY3JlYXRlRGl2KCk7XG4gICAgICAgIG5ldyBCdXR0b25Db21wb25lbnQoYnV0dG9uRWwpXG4gICAgICAgICAgICAuc2V0QnV0dG9uVGV4dCh0aGlzLmJ1dHRvbnMucHJpbWFyeSlcbiAgICAgICAgICAgIC5zZXRDdGEoKVxuICAgICAgICAgICAgLm9uQ2xpY2soKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuY29uZmlybWVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLmNsb3NlKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgbmV3IEJ1dHRvbkNvbXBvbmVudChidXR0b25FbClcbiAgICAgICAgICAgIC5zZXRCdXR0b25UZXh0KHRoaXMuYnV0dG9ucy5zZWNvbmRhcnkpXG4gICAgICAgICAgICAub25DbGljaygoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5jbG9zZSgpO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuICAgIG9uT3BlbigpIHtcbiAgICAgICAgdGhpcy5kaXNwbGF5KCk7XG4gICAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBmaW5kQW5kUmVwbGFjZU1pc3NpbmdJRHMoKSB7XG5cbiAgICBmdW5jdGlvbiBzZWFyY2hGaWxlRm9yTWlzc2luZ0lEKGRvY1RleHQ6IHN0cmluZyk6IHsgdXBkYXRlZEZpbGVDb250ZW50OiBzdHJpbmcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG51bVJlZ2lvbnNVcGRhdGVkOiBudW1iZXIgfSB7XG4gICAgICAgIGxldCBsaW5lcyA9IGRvY1RleHQuc3BsaXQoXCJcXG5cIik7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIExvb3AgdGhyb3VnaCBhbGwgb2YgdGhlIGxpbmVzIGNoZWNraW5nIGlmIHRoZSBsaW5lIGlzIGEgXG4gICAgICAgICAqIHN0YXJ0IHRhZyBhbmQgaWYgc28gaXMgaXQgbWlzc2luZyBhbiBJRC5cbiAgICAgICAgICovXG4gICAgICAgIGxldCBsaW5lc1dpdGhvdXRJRHMgPSAwXG4gICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCBsaW5lcy5sZW5ndGg7IGkrKykge1xuXG4gICAgICAgICAgICBsZXQgZGF0YSA9IG11bHRpQ29sdW1uUGFyc2VyLmlzU3RhcnRUYWdXaXRoSUQobGluZXNbaV0pO1xuICAgICAgICAgICAgaWYoZGF0YS5pc1N0YXJ0VGFnID09PSB0cnVlICYmIGRhdGEuaGFzS2V5ID09PSBmYWxzZSkge1xuXG4gICAgICAgICAgICAgICAgbGV0IG9yaWdpbmFsVGV4dCA9IGxpbmVzW2ldXG4gICAgICAgICAgICAgICAgbGV0IHRleHQgPSBvcmlnaW5hbFRleHQ7XG4gICAgICAgICAgICAgICAgdGV4dCA9IHRleHQudHJpbUVuZCgpO1xuICAgICAgICAgICAgICAgIGlmKHRleHQuY2hhckF0KHRleHQubGVuZ3RoIC0gMSkgPT09IFwiOlwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHRleHQgPSB0ZXh0LnNsaWNlKDAsIHRleHQubGVuZ3RoLTEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0ZXh0ID0gYCR7dGV4dH06IElEXyR7Z2V0VUlEKDQpfWA7XG5cbiAgICAgICAgICAgICAgICBsaW5lc1tpXSA9IHRleHQ7XG4gICAgICAgICAgICAgICAgbGluZXNXaXRob3V0SURzKys7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gICAgICAgICAgICAgICAgICAgIFxuXG4gICAgICAgIGlmKGxpbmVzV2l0aG91dElEcyA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICB1cGRhdGVkRmlsZUNvbnRlbnQ6IGRvY1RleHQsXG4gICAgICAgICAgICAgICAgbnVtUmVnaW9uc1VwZGF0ZWQ6IDBcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgbmV3RmlsZUNvbnRlbnQgPSBsaW5lcy5qb2luKFwiXFxuXCIpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgdXBkYXRlZEZpbGVDb250ZW50OiBuZXdGaWxlQ29udGVudCxcbiAgICAgICAgICAgIG51bVJlZ2lvbnNVcGRhdGVkOiBsaW5lc1dpdGhvdXRJRHNcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBsZXQgY291bnQgPSAwO1xuICAgIGxldCBmaWxlQ291bnQgPSAwO1xuICAgIGZvcihsZXQgbWRGaWxlIG9mIGFwcC52YXVsdC5nZXRNYXJrZG93bkZpbGVzKCkpIHtcbiAgICAgICAgbGV0IG9yaWdpbmFsRmlsZUNvbnRlbnQgPSBhd2FpdCBhcHAudmF1bHQucmVhZChtZEZpbGUpO1xuXG4gICAgICAgIGxldCByZXN1bHQgPSBzZWFyY2hGaWxlRm9yTWlzc2luZ0lEKG9yaWdpbmFsRmlsZUNvbnRlbnQpO1xuICAgICAgICBpZihyZXN1bHQubnVtUmVnaW9uc1VwZGF0ZWQgPiAwKSB7XG4gICAgICAgICAgICBjb3VudCArPSByZXN1bHQubnVtUmVnaW9uc1VwZGF0ZWQ7XG4gICAgICAgICAgICBmaWxlQ291bnQrKztcblxuICAgICAgICAgICAgbGV0IHVwZGF0ZWRGaWxlQ29udGVudCA9IHJlc3VsdC51cGRhdGVkRmlsZUNvbnRlbnQ7XG4gICAgICAgICAgICBpZih1cGRhdGVkRmlsZUNvbnRlbnQgIT09IG9yaWdpbmFsRmlsZUNvbnRlbnQpIHtcbiAgICAgICAgICAgICAgICBhcHAudmF1bHQubW9kaWZ5KG1kRmlsZSwgdXBkYXRlZEZpbGVDb250ZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiTm8gY2hhbmdlcywgbm90IHVwZGF0aW5nIGZpbGUuXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIG5ldyBOb3RpY2UoYEZpbmlzaGVkIHVwZGF0aW5nOlxcbiR7Y291bnR9IHJlZ2lvbiBJRHMsIGFjcm9zcyAke2ZpbGVDb3VudH0gZmlsZXMuYClcbn1cblxuYXN5bmMgZnVuY3Rpb24gdXBkYXRlRmlsZVN5bnRheCgpIHtcbiAgICBcbiAgICBsZXQgZmlsZUNvdW50ID0gMFxuICAgIGxldCByZWdpb25TdGFydENvdW50ID0gMDtcbiAgICBsZXQgY29sdW1uQnJlYWtDb3VudCA9IDA7XG4gICAgbGV0IGNvbHVtbkVuZENvdW50ID0gMDtcbiAgICBmb3IobGV0IG1kRmlsZSBvZiBhcHAudmF1bHQuZ2V0TWFya2Rvd25GaWxlcygpKSB7XG4gICAgICAgIGxldCBvcmlnaW5hbEZpbGVDb250ZW50ID0gYXdhaXQgYXBwLnZhdWx0LnJlYWQobWRGaWxlKTtcbiAgICAgICAgbGV0IHJlc3VsdCA9IHVwZGF0ZUFsbFN5bnRheChvcmlnaW5hbEZpbGVDb250ZW50KTtcblxuICAgICAgICBmaWxlQ291bnQgKz0gcmVzdWx0LmZpbGVDb3VudDtcbiAgICAgICAgcmVnaW9uU3RhcnRDb3VudCArPSByZXN1bHQucmVnaW9uU3RhcnRDb3VudDtcbiAgICAgICAgY29sdW1uQnJlYWtDb3VudCArPSByZXN1bHQuY29sdW1uQnJlYWtDb3VudDtcbiAgICAgICAgY29sdW1uRW5kQ291bnQgKz0gcmVzdWx0LmNvbHVtbkVuZENvdW50O1xuICAgICAgICBsZXQgdXBkYXRlZEZpbGVDb250ZW50ID0gcmVzdWx0LnVwZGF0ZWRGaWxlQ29udGVudDtcblxuICAgICAgICAvLyBUT0RPOiBBZGQgaW4gZmluYWwgZmlsZSBtb2RpZmljYXRpb24gd2hlbiBkb25lIHRlc3RpbmcuXG4gICAgICAgIGlmKHJlc3VsdC5maWxlV2FzVXBkYXRlZCkge1xuICAgICAgICAgICAgYXBwLnZhdWx0Lm1vZGlmeShtZEZpbGUsIHVwZGF0ZWRGaWxlQ29udGVudClcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIGNvbnNvbGUuZGVidWcoXCJObyBjaGFuZ2VzLCBub3QgdXBkYXRpbmcgZmlsZS5cIilcbiAgICAgICAgfVxuICAgIH1cblxuICAgIG5ldyBOb3RpY2UoYEZpbmlzaGVkIHVwZGF0aW5nOlxcbiR7cmVnaW9uU3RhcnRDb3VudH0gc3RhcnQgc3ludGF4ZXMsXFxuJHtjb2x1bW5CcmVha0NvdW50fSBjb2x1bW4gYnJlYWtzLCBhbmRcXG4ke2NvbHVtbkVuZENvdW50fSBjb2x1bW4gZW5kIHRhZ3MsXFxuYWNyb3NzICR7ZmlsZUNvdW50fSBmaWxlcy5gKVxufVxuXG5mdW5jdGlvbiBnZXREb25hdGVCdXR0b25Db2xvcnMoY29udGFpbmVyRWw6IEhUTUxFbGVtZW50KSB7XG4gICAgbGV0IGNvbXB1dGVkU3R5bGUgPSBnZXRDb21wdXRlZFN0eWxlKGNvbnRhaW5lckVsKTtcbiAgICBsZXQgZm9udENvbG9yID0gY29tcHV0ZWRTdHlsZS5nZXRQcm9wZXJ0eVZhbHVlKCctLXRleHQtbm9ybWFsJyk7XG4gICAgbGV0IGJnQ29sb3IgPSBjb21wdXRlZFN0eWxlLmdldFByb3BlcnR5VmFsdWUoJy0tYWNjZW50Jyk7XG4gICAgbGV0IGNvZmZlZUNvbG9yID0gXCJmZmZmZmZcIjtcbiAgICBpZiAoaXNWYWxpZEhleENvbG9yKGZvbnRDb2xvcikgJiZcbiAgICAgICAgaXNWYWxpZEhleENvbG9yKGJnQ29sb3IpKSB7XG4gICAgICAgIGZvbnRDb2xvciA9IGZvbnRDb2xvci5zbGljZSgxKTtcbiAgICAgICAgYmdDb2xvciA9IGJnQ29sb3Iuc2xpY2UoMSk7XG4gICAgICAgIGNvZmZlZUNvbG9yID0gZm9udENvbG9yO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgZm9udENvbG9yID0gXCIwMDAwMDBcIjtcbiAgICAgICAgYmdDb2xvciA9IFwiRkZERDAwXCI7XG4gICAgICAgIGNvZmZlZUNvbG9yID0gXCJmZmZmZmZcIjtcbiAgICB9XG4gICAgcmV0dXJuIHsgYmdDb2xvciwgZm9udENvbG9yLCBjb2ZmZWVDb2xvciB9O1xufVxuXG5mdW5jdGlvbiBpc1ZhbGlkSGV4Q29sb3IocG9zc2libGVDb2xvcjogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgXG4gICAgbGV0IGZpcnN0Q2hhciA9IHBvc3NpYmxlQ29sb3JbMF1cbiAgICBpZihmaXJzdENoYXIgIT09IFwiI1wiKSB7XG4gICAgICAgIHJldHVybiBmYWxzZVxuICAgIH1cblxuICAgIGlmKHBvc3NpYmxlQ29sb3IubGVuZ3RoICE9PSA3KSB7XG4gICAgICAgIHJldHVybiBmYWxzZVxuICAgIH1cblxuICAgIHJldHVybiAvXiNbMC05QS1GXXs2fSQvaS50ZXN0KHBvc3NpYmxlQ29sb3IpXG59IiwiLypcclxuICogRmlsZTogbXVsdGktY29sdW1uLW1hcmtkb3duL3NyYy9tYWluLnRzXHJcbiAqIENyZWF0ZWQgRGF0ZTogVHVlc2RheSwgT2N0b2JlciA1dGggMjAyMSwgMTowOSBwbVxyXG4gKiBBdXRob3I6IENhbWVyb24gUm9iaW5zb25cclxuICogXHJcbiAqIENvcHlyaWdodCAoYykgMjAyMiBDYW1lcm9uIFJvYmluc29uXHJcbiAqL1xyXG5cclxuaW1wb3J0IHsgTm90aWNlLCBQbHVnaW4sICBNYXJrZG93blJlbmRlckNoaWxkLCBNYXJrZG93blJlbmRlcmVyLCBURmlsZSwgUGxhdGZvcm0sIE1hcmtkb3duUG9zdFByb2Nlc3NvckNvbnRleHQsIE1hcmtkb3duU2VjdGlvbkluZm9ybWF0aW9uLCBwYXJzZUZyb250TWF0dGVyRW50cnksIFdvcmtzcGFjZSwgV29ya3NwYWNlTGVhZiwgRWRpdG9yUG9zaXRpb24gfSBmcm9tICdvYnNpZGlhbic7XHJcbmltcG9ydCAqIGFzIG11bHRpQ29sdW1uUGFyc2VyIGZyb20gJy4vdXRpbGl0aWVzL3RleHRQYXJzZXInO1xyXG5pbXBvcnQgKiBhcyBjb250YWluc1BhbmRvYyBmcm9tIFwiLi91dGlsaXRpZXMvcGFuZG9jUGFyc2VyXCI7XHJcbmltcG9ydCB7IEZpbGVET01NYW5hZ2VyLCBHbG9iYWxET01NYW5hZ2VyIH0gZnJvbSAnLi9kb21fbWFuYWdlci9kb21NYW5hZ2VyJztcclxuaW1wb3J0IHsgTXVsdGlDb2x1bW5SZW5kZXJEYXRhIH0gZnJvbSBcIi4vZG9tX21hbmFnZXIvcmVnaW9uYWxfbWFuYWdlcnMvcmVnaW9uTWFuYWdlclwiO1xyXG5pbXBvcnQgeyBSZWdpb25NYW5hZ2VyIH0gZnJvbSBcIi4vZG9tX21hbmFnZXIvcmVnaW9uYWxfbWFuYWdlcnMvcmVnaW9uTWFuYWdlclwiO1xyXG5pbXBvcnQgeyBSZWdpb25NYW5hZ2VyQ29udGFpbmVyIH0gZnJvbSBcIi4vZG9tX21hbmFnZXIvcmVnaW9uYWxfbWFuYWdlcnMvcmVnaW9uTWFuYWdlckNvbnRhaW5lclwiO1xyXG5pbXBvcnQgeyBET01PYmplY3QsIERPTU9iamVjdFRhZywgVGFza0xpc3RET01PYmplY3QgfSBmcm9tICcuL2RvbV9tYW5hZ2VyL2RvbU9iamVjdCc7XHJcbmltcG9ydCB7IGZpbGVTdGlsbEluVmlldywgZ2V0VUlEIH0gZnJvbSAnLi91dGlsaXRpZXMvdXRpbHMnO1xyXG5pbXBvcnQgeyBNdWx0aUNvbHVtbkxheW91dENTUywgTXVsdGlDb2x1bW5TdHlsZUNTUyB9IGZyb20gJy4vdXRpbGl0aWVzL2Nzc0RlZmluaXRpb25zJztcclxuaW1wb3J0IHsgbXVsdGlDb2x1bW5NYXJrZG93bl9TdGF0ZUZpZWxkIH0gZnJvbSAnLi9saXZlX3ByZXZpZXcvY202X2xpdmVQcmV2aWV3JztcclxuaW1wb3J0IHsgcGFyc2VDb2x1bW5TZXR0aW5ncywgcGFyc2VTdGFydFJlZ2lvbkNvZGVCbG9ja0lEIH0gZnJvbSAnLi91dGlsaXRpZXMvc2V0dGluZ3NQYXJzZXInO1xyXG5pbXBvcnQgeyBNdWx0aUNvbHVtbk1hcmtkb3duX09uQ2xpY2tGaXggfSBmcm9tICcuL2xpdmVfcHJldmlldy9jbTZfbGl2ZVByZWl2ZXdfb25DbGlja0ZpeCc7XHJcbmltcG9ydCB7IE11bHRpQ29sdW1uU2V0dGluZ3MsIGdldERlZmF1bHRNdWx0aUNvbHVtblNldHRpbmdzIH0gZnJvbSAnLi9yZWdpb25TZXR0aW5ncyc7XHJcbmltcG9ydCB7IEhUTUxTaXppbmcgfSBmcm9tICcuL3V0aWxpdGllcy9pbnRlcmZhY2VzJztcclxuaW1wb3J0IE11bHRpQ29sdW1uU2V0dGluZ3NWaWV3IGZyb20gJy4vc2V0dGluZ3MvTXVsdGlDb2x1bW5TZXR0aW5nc1ZpZXcnO1xyXG5pbXBvcnQgeyBERUZBVUxUX1NFVFRJTkdTLCBNQ01fU2V0dGluZ3NNYW5hZ2VyIH0gZnJvbSAnLi9wbHVnaW5TZXR0aW5ncyc7XHJcbmltcG9ydCB7IFJlZ2lvbkVycm9yTWFuYWdlciB9IGZyb20gJy4vZG9tX21hbmFnZXIvcmVnaW9uRXJyb3JNYW5hZ2VyJztcclxuaW1wb3J0IHsgcGFyc2VDb2xCcmVha0Vycm9yVHlwZSB9IGZyb20gJy4vdXRpbGl0aWVzL2Vycm9yTWVzc2FnZSc7XHJcbmltcG9ydCB7IHVwZGF0ZUFsbFN5bnRheCB9IGZyb20gJy4vdXRpbGl0aWVzL3N5bnRheFVwZGF0ZSc7XHJcbmltcG9ydCB7IGdldExlYWZGcm9tRmlsZVBhdGggfSBmcm9tICcuL3V0aWxpdGllcy9vYnNpVXRpbHMnO1xyXG5pbXBvcnQgeyBjbGVhckxpdmVQcmV2aWV3Q2FjaGUgfSBmcm9tICcuL2xpdmVfcHJldmlldy9tY21fbGl2ZVByZXZpZXdfd2lkZ2V0JztcclxuXHJcbmNvbnN0IENPREVCTE9DS19TVEFSVF9TVFJTID0gW1xyXG4gICAgXCJzdGFydC1tdWx0aS1jb2x1bW5cIixcclxuICAgIFwibXVsdGktY29sdW1uLXN0YXJ0XCJcclxuXVxyXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBNdWx0aUNvbHVtbk1hcmtkb3duIGV4dGVuZHMgUGx1Z2luIHtcclxuXHJcbiAgICBzZXR0aW5nc01hbmFnZXI6IE1DTV9TZXR0aW5nc01hbmFnZXIgPSBNQ01fU2V0dGluZ3NNYW5hZ2VyLnNoYXJlZDtcclxuICAgIGdsb2JhbE1hbmFnZXI6IEdsb2JhbERPTU1hbmFnZXIgPSBuZXcgR2xvYmFsRE9NTWFuYWdlcigpO1xyXG5cclxuXHRhc3luYyBvbmxvYWQoKSB7XHJcblxyXG4gICAgICAgIGNvbnNvbGUubG9nKFwiTG9hZGluZyBtdWx0aS1jb2x1bW4gbWFya2Rvd25cIik7XHJcblxyXG4gICAgICAgIGF3YWl0IHRoaXMubG9hZFNldHRpbmdzKCk7XHJcblxyXG4gICAgICAgIHRoaXMuZ2xvYmFsTWFuYWdlciA9IG5ldyBHbG9iYWxET01NYW5hZ2VyKCk7XHJcblxyXG4gICAgICAgIHRoaXMucmVnaXN0ZXJFZGl0b3JFeHRlbnNpb24obXVsdGlDb2x1bW5NYXJrZG93bl9TdGF0ZUZpZWxkKVxyXG4gICAgICAgIHRoaXMucmVnaXN0ZXJFZGl0b3JFeHRlbnNpb24oTXVsdGlDb2x1bW5NYXJrZG93bl9PbkNsaWNrRml4KTtcclxuXHJcbiAgICAgICAgZm9yKGxldCBpID0gMDsgaSA8IENPREVCTE9DS19TVEFSVF9TVFJTLmxlbmd0aDsgaSsrKSB7XHJcblxyXG4gICAgICAgICAgICBsZXQgc3RhcnRTdHIgPSBDT0RFQkxPQ0tfU1RBUlRfU1RSU1tpXVxyXG4gICAgICAgICAgICB0aGlzLnNldHVwTWFya2Rvd25Db2RlYmxvY2tQb3N0UHJvY2Vzc29yKHN0YXJ0U3RyKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy5zZXR1cE1hcmtkb3duUG9zdFByb2Nlc3NvcigpO1xyXG5cclxuICAgICAgICB0aGlzLmFkZFNldHRpbmdUYWIobmV3IE11bHRpQ29sdW1uU2V0dGluZ3NWaWV3KHRoaXMuYXBwLCB0aGlzKSlcclxuXHJcbiAgICAgICAgdGhpcy5hZGRDb21tYW5kKHsgICAgICAgICAgICBcclxuICAgICAgICAgICAgaWQ6IGB0b2dnbGUtbW9iaWxlLXJlbmRlcmluZy1tY21gLFxyXG4gICAgICAgICAgICBuYW1lOiBgVG9nZ2xlIE1vYmlsZSBSZW5kZXJpbmcgLSBNdWx0aS1Db2x1bW4gTWFya2Rvd25gLFxyXG4gICAgICAgICAgICBjYWxsYmFjazogYXN5bmMgKCkgPT4ge1xyXG5cclxuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3NNYW5hZ2VyLnJlbmRlck9uTW9iaWxlID0gIXRoaXMuc2V0dGluZ3NNYW5hZ2VyLnJlbmRlck9uTW9iaWxlO1xyXG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5zYXZlU2V0dGluZ3MoKTtcclxuXHJcbiAgICAgICAgICAgICAgICBsZXQgbm90aWNlU3RyaW5nID0gYFRvZ2dsZWQgbW9iaWxlIHJlbmRlcmluZyAke3RoaXMuc2V0dGluZ3NNYW5hZ2VyLnJlbmRlck9uTW9iaWxlID8gXCJvblwiIDogXCJvZmZcIn0uYFxyXG4gICAgICAgICAgICAgICAgaWYoUGxhdGZvcm0uaXNNb2JpbGUgPT09IHRydWUpIHtcclxuICAgICAgICAgICAgICAgICAgICBub3RpY2VTdHJpbmcgKz0gYCBQbGVhc2UgcmVsb2FkIGFueSBvcGVuIGZpbGVzIGZvciBjaGFuZ2UgdG8gdGFrZSBlZmZlY3QuYFxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgbmV3IE5vdGljZSAobm90aWNlU3RyaW5nKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgICAvL1RPRE86IFNldCB1cCB0aGlzIGFzIGEgbW9kYWwgdG8gc2V0IHNldHRpbmdzIGF1dG9tYXRpY2FsbHlcclxuICAgICAgICB0aGlzLmFkZENvbW1hbmQoeyAgICAgICAgICAgIFxyXG4gICAgICAgICAgICBpZDogYGluc2VydC1tdWx0aS1jb2x1bW4tcmVnaW9uYCxcclxuICAgICAgICAgICAgbmFtZTogYEluc2VydCBNdWx0aS1Db2x1bW4gUmVnaW9uYCxcclxuICAgICAgICAgICAgZWRpdG9yQ2FsbGJhY2s6IChlZGl0b3IsIHZpZXcpID0+IHtcclxuXHJcbiAgICAgICAgICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICAgICAgICAgIGxldCBjdXJzb3JTdGFydFBvc2l0aW9uID0gZWRpdG9yLmdldEN1cnNvcihcImZyb21cIik7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGVkaXRvci5nZXREb2MoKS5yZXBsYWNlU2VsZWN0aW9uKFxyXG5gXHJcbi0tLSBzdGFydC1tdWx0aS1jb2x1bW46IElEXyR7Z2V0VUlEKDQpfVxyXG5cXGBcXGBcXGBjb2x1bW4tc2V0dGluZ3NcclxuTnVtYmVyIG9mIENvbHVtbnM6IDJcclxuTGFyZ2VzdCBDb2x1bW46IHN0YW5kYXJkXHJcblxcYFxcYFxcYFxyXG5cclxuXHJcblxyXG4tLS0gY29sdW1uLWJyZWFrIC0tLVxyXG5cclxuXHJcblxyXG4tLS0gZW5kLW11bHRpLWNvbHVtblxyXG5cclxuJHtlZGl0b3IuZ2V0RG9jKCkuZ2V0U2VsZWN0aW9uKCl9YFxyXG4gICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICAgICAgXHJcbiAgICAgICAgICAgICAgICAgICAgY3Vyc29yU3RhcnRQb3NpdGlvbi5saW5lID0gY3Vyc29yU3RhcnRQb3NpdGlvbi5saW5lICsgN1xyXG4gICAgICAgICAgICAgICAgICAgIGN1cnNvclN0YXJ0UG9zaXRpb24uY2ggPSAwO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICBlZGl0b3Iuc2V0Q3Vyc29yKGN1cnNvclN0YXJ0UG9zaXRpb24pO1xyXG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIG5ldyBOb3RpY2UoXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFwiRW5jb3VudGVyZWQgYW4gZXJyb3IgaW5zZXJ0aW5nIGEgbXVsdGktY29sdW1uIHJlZ2lvbi4gUGxlYXNlIHRyeSBhZ2FpbiBsYXRlci5cIlxyXG4gICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgdGhpcy5hZGRDb21tYW5kKHsgICAgICAgICAgICBcclxuICAgICAgICAgICAgaWQ6IGBjbGVhci1scC1jYWNoZS1tY21gLFxyXG4gICAgICAgICAgICBuYW1lOiBgQ2xlYXIgTGl2ZSBQcmV2aWV3IENhY2hlIC0gTXVsdGktQ29sdW1uIE1hcmtkb3duYCxcclxuICAgICAgICAgICAgY2FsbGJhY2s6IGFzeW5jICgpID0+IHtcclxuICAgICAgICAgICAgICAgIGNsZWFyTGl2ZVByZXZpZXdDYWNoZSgpXHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgdGhpcy5hZGRDb21tYW5kKHsgICAgICAgICAgICBcclxuICAgICAgICAgICAgaWQ6IGBhZGQtSURzLVRvLW11bHRpLWNvbHVtbi1yZWdpb25gLFxyXG4gICAgICAgICAgICBuYW1lOiBgRml4IE1pc3NpbmcgSURzIGZvciBNdWx0aS1Db2x1bW4gUmVnaW9uc2AsXHJcbiAgICAgICAgICAgIGVkaXRvckNhbGxiYWNrOiAoZWRpdG9yLCB2aWV3KSA9PiB7XHJcblxyXG4gICAgICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICAgICAgICAgKiBOb3Qgc3VyZSBpZiB0aGVyZSBpcyBhbiBlYXNpZXIgd2F5IHRvIGRvIHRoaXMuXHJcbiAgICAgICAgICAgICAgICAgICAgICogXHJcbiAgICAgICAgICAgICAgICAgICAgICogR2V0IGFsbCBvZiB0aGUgbGluZXMgb2YgdGhlIGRvY3VtZW50IHNwbGl0IGJ5IG5ld2xpbmVzLlxyXG4gICAgICAgICAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICAgICAgICAgIGxldCBkb2NUZXh0ID0gZWRpdG9yLmdldFJhbmdlKHsgbGluZTogMCwgY2g6IDAgfSwgeyBsaW5lOiBlZGl0b3IuZ2V0RG9jKCkubGluZUNvdW50KCksIGNoOiAwfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IGxpbmVzID0gZG9jVGV4dC5zcGxpdChcIlxcblwiKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IHN0YXJ0Q29kZWJsb2NrID0gbXVsdGlDb2x1bW5QYXJzZXIuZmluZFN0YXJ0Q29kZWJsb2NrKGRvY1RleHQpO1xyXG4gICAgICAgICAgICAgICAgICAgIGxldCBsaW5lT2Zmc2V0ID0gMDtcclxuICAgICAgICAgICAgICAgICAgICBsZXQgbnVtQ29kZWJsb2Nrc1VwZGF0ZWQgPSAwO1xyXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlKHN0YXJ0Q29kZWJsb2NrLmZvdW5kID09PSB0cnVlKSB7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBHZXQgdGhlIHRleHQgb2YgdGhlIHNldHRpbmdzIGJsb2NrIHNvIHdlIGNhbiBjaGVjayBpZiBpdCBjb250YWlucyBhbiBJRCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYWxzbyBzbyB3ZSBjYW4gZ2V0IHRoZSBsZW5ndGggb2YgdGhlIGZpcnN0IGxpbmUsIHVzZWQgdG8gY2FsY3VsYXRlIHdoZXJlIHRvIGFwcGVuZCBhIG5ldyBJRCBpZiBuZWVkZWRcclxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHNldHRpbmdzVGV4dCA9IGRvY1RleHQuc2xpY2Uoc3RhcnRDb2RlYmxvY2suc3RhcnRQb3NpdGlvbiwgc3RhcnRDb2RlYmxvY2suZW5kUG9zaXRpb24pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgZmlyc3RMaW5lT2ZDb2RlYmxvY2tMZW5ndGggPSBzZXR0aW5nc1RleHQuc3BsaXQoXCJcXG5cIilbMF0ubGVuZ3RoO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBcclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2UgbmVlZCB0aGUgbGluZXMgYmVmb3JlIHRoZSBibG9jayB0byBrbm93IHdoZXJlIHRvIHN0YXJ0IHJlcGxhY2luZyB0ZXh0XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFuZCB0aGUgbGluZXMgaW5jbHVkaW5nIHRoZSBibG9jayB0byBrbm93IHdoZXJlIHRvIHNldCBvdXIgb2Zmc2V0IHRvIGFmdGVyIHRoaXMgaXRlcmF0aW9uLlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgbGluZXNCZWZvcmUgPSBkb2NUZXh0LnNsaWNlKDAsIHN0YXJ0Q29kZWJsb2NrLnN0YXJ0UG9zaXRpb24pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgc3RhcnRSZXBsYWNlbWVudExpbmVJbmRleCA9IChsaW5lc0JlZm9yZS5zcGxpdChcIlxcblwiKS5sZW5ndGggLSAxKSArIGxpbmVPZmZzZXQ7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBsaW5lc09mID0gZG9jVGV4dC5zbGljZSgwLCBzdGFydENvZGVibG9jay5lbmRQb3NpdGlvbik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBlbmRSZXBsYWNlbWVudExpbmVJbmRleCA9ICAobGluZXNPZi5zcGxpdChcIlxcblwiKS5sZW5ndGggLSAxKSArIGxpbmVPZmZzZXQ7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgc2V0dGluZ3NJRCA9IHBhcnNlU3RhcnRSZWdpb25Db2RlQmxvY2tJRChzZXR0aW5nc1RleHQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZihzZXR0aW5nc0lEID09PSBcIlwiKSB7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gY29weSB0aGUgZmlyc3QgbGluZSBvZiB0aGUgY29kZWJsb2NrIGFuZCBhcHBlbmQgYSBuZXcgSUQsIHRoZW4gcmVwbGFjZSB0aGUgZmlyc3QgbGluZSBvZiB0aGUgYmxvY2tcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCByZXBsYWNlbWVudFRleHQgPSBlZGl0b3IuZ2V0UmFuZ2UoeyBsaW5lOiBzdGFydFJlcGxhY2VtZW50TGluZUluZGV4LCBjaDogMCB9LCB7IGxpbmU6IHN0YXJ0UmVwbGFjZW1lbnRMaW5lSW5kZXgsIGNoOiBmaXJzdExpbmVPZkNvZGVibG9ja0xlbmd0aH0pICsgYFxcbklEOiBJRF8ke2dldFVJRCg0KX1gXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlZGl0b3IucmVwbGFjZVJhbmdlKHJlcGxhY2VtZW50VGV4dCwgeyBsaW5lOiBzdGFydFJlcGxhY2VtZW50TGluZUluZGV4LCBjaDogMCB9LCBcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7IGxpbmU6IHN0YXJ0UmVwbGFjZW1lbnRMaW5lSW5kZXgsIGNoOiBmaXJzdExpbmVPZkNvZGVibG9ja0xlbmd0aH0pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5kUmVwbGFjZW1lbnRMaW5lSW5kZXggKz0gMTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG51bUNvZGVibG9ja3NVcGRhdGVkICs9IDE7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxpbmVPZmZzZXQgPSBlbmRSZXBsYWNlbWVudExpbmVJbmRleFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBkb2NUZXh0ID0gZG9jVGV4dC5zbGljZShzdGFydENvZGVibG9jay5lbmRQb3NpdGlvbik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0YXJ0Q29kZWJsb2NrID0gbXVsdGlDb2x1bW5QYXJzZXIuZmluZFN0YXJ0Q29kZWJsb2NrKGRvY1RleHQpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAgICAgICAgICogTG9vcCB0aHJvdWdoIGFsbCBvZiB0aGUgbGluZXMgY2hlY2tpbmcgaWYgdGhlIGxpbmUgaXMgYSBcclxuICAgICAgICAgICAgICAgICAgICAgKiBzdGFydCB0YWcgYW5kIGlmIHNvIGlzIGl0IG1pc3NpbmcgYW4gSUQuXHJcbiAgICAgICAgICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IGxpbmVzV2l0aG91dElEcyA9IFtdXHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IHRleHRXaXRob3V0SURzID0gW11cclxuICAgICAgICAgICAgICAgICAgICBmb3IobGV0IGkgPSAwOyBpIDwgbGluZXMubGVuZ3RoOyBpKyspIHtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBkYXRhID0gbXVsdGlDb2x1bW5QYXJzZXIuaXNTdGFydFRhZ1dpdGhJRChsaW5lc1tpXSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKGRhdGEuaXNTdGFydFRhZyA9PT0gdHJ1ZSAmJiBkYXRhLmhhc0tleSA9PT0gZmFsc2UpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmVzV2l0aG91dElEcy5wdXNoKGkpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGV4dFdpdGhvdXRJRHMucHVzaChsaW5lc1tpXSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIH0gICAgICAgICAgICAgICAgICAgIFxyXG5cclxuICAgICAgICAgICAgICAgICAgICBpZihsaW5lc1dpdGhvdXRJRHMubGVuZ3RoID09PSAwICYmIG51bUNvZGVibG9ja3NVcGRhdGVkID09PSAwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ldyBOb3RpY2UgKFwiRm91bmQgMCBtaXNzaW5nIElEcyBpbiB0aGUgY3VycmVudCBkb2N1bWVudC5cIik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIC8qKlxyXG4gICAgICAgICAgICAgICAgICAgICAqIE5vdyBsb29wIHRocm91Z2ggZWFjaCBsaW5lIHRoYXQgaXMgbWlzc2luZyBhbiBJRCBhbmRcclxuICAgICAgICAgICAgICAgICAgICAgKiBnZW5lcmF0ZSBhIHJhbmRvbSBJRCBhbmQgcmVwbGFjZSB0aGUgb3JpZ2luYWwgdGV4dC5cclxuICAgICAgICAgICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgICAgICAgICBmb3IobGV0IGkgPSAwOyBpIDwgbGluZXNXaXRob3V0SURzLmxlbmd0aDsgaSsrKSB7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgb3JpZ2luYWxUZXh0ID0gdGV4dFdpdGhvdXRJRHNbaV1cclxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHRleHQgPSBvcmlnaW5hbFRleHQ7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRleHQgPSB0ZXh0LnRyaW1FbmQoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYodGV4dC5jaGFyQXQodGV4dC5sZW5ndGggLSAxKSA9PT0gXCI6XCIpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHQgPSB0ZXh0LnNsaWNlKDAsIHRleHQubGVuZ3RoLTEpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRleHQgPSBgJHt0ZXh0fTogSURfJHtnZXRVSUQoNCl9YDtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGVkaXRvci5yZXBsYWNlUmFuZ2UodGV4dCwgeyBsaW5lOiBsaW5lc1dpdGhvdXRJRHNbaV0sIGNoOiAwIH0sIFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHsgbGluZTogbGluZXNXaXRob3V0SURzW2ldLCBjaDogb3JpZ2luYWxUZXh0Lmxlbmd0aH0pO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgbmV3IE5vdGljZSAoYFJlcGxhY2VkICR7bGluZXNXaXRob3V0SURzLmxlbmd0aCArIG51bUNvZGVibG9ja3NVcGRhdGVkfSBtaXNzaW5nIElEKHMpIGluIHRoZSBjdXJyZW50IGRvY3VtZW50LmApO1xyXG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIG5ldyBOb3RpY2UoXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFwiRW5jb3VudGVyZWQgYW4gZXJyb3IgYWRkaWduIElEcyB0byBtdWx0aS1jb2x1bW4gcmVnaW9ucy4gUGxlYXNlIHRyeSBhZ2FpbiBsYXRlci5cIlxyXG4gICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9KTtcclxuICAgICAgICB0aGlzLmFkZENvbW1hbmQoeyAgICAgICAgICAgIFxyXG4gICAgICAgICAgICBpZDogYG1jbS1Ub2dnbGUtRG9jdW1lbnQtUmVmbG93YCxcclxuICAgICAgICAgICAgbmFtZTogYFNldHVwIE11bHRpLUNvbHVtbiBSZWZsb3cgLSBNdWx0aS1Db2x1bW4gTWFya2Rvd25gLFxyXG4gICAgICAgICAgICBlZGl0b3JDYWxsYmFjazogKGVkaXRvciwgdmlldykgPT4ge1xyXG5cclxuICAgICAgICAgICAgICAgIGFwcC5maWxlTWFuYWdlci5wcm9jZXNzRnJvbnRNYXR0ZXIodmlldy5maWxlLCAoZnJvbnRtYXR0ZXIpID0+IHtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IGlzUmVmbG93ID0gaXNNdWx0aUNvbHVtblJlZmxvdyhmcm9udG1hdHRlcik7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYoaXNSZWZsb3cpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgZnJvbnRtYXR0ZXJbXCJNdWx0aS1Db2x1bW4gTWFya2Rvd25cIl0gPSBbXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHtcIk51bWJlciBvZiBDb2x1bW5zXCI6IDJ9LFxyXG4gICAgICAgICAgICAgICAgICAgICAgICB7XCJDb2x1bW4gU2l6ZVwiOiBcIlN0YW5kYXJkXCJ9XHJcbiAgICAgICAgICAgICAgICAgICAgXVxyXG4gICAgICAgICAgICAgICAgICAgIHZpZXcuZWRpdG9yLnJlZnJlc2goKVxyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9KTtcclxuICAgICAgICB0aGlzLmFkZENvbW1hbmQoeyAgICAgICAgICAgIFxyXG4gICAgICAgICAgICBpZDogYG1jbS1maXgtZmlsZS1tdWx0aS1jb2x1bW4tc3ludGF4YCxcclxuICAgICAgICAgICAgbmFtZTogYEZpeCBNdWx0aS1Db2x1bW4gU3ludGF4IGluIEN1cnJlbnQgRmlsZS5gLFxyXG4gICAgICAgICAgICBlZGl0b3JDYWxsYmFjazogKGVkaXRvciwgdmlldykgPT4ge1xyXG5cclxuICAgICAgICAgICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IGZyb21Qb3NpdGlvbjogRWRpdG9yUG9zaXRpb24gPSB7IGxpbmU6IDAsIGNoOiAwIH1cclxuICAgICAgICAgICAgICAgICAgICBsZXQgdG9Qb3NpdGlvbjogRWRpdG9yUG9zaXRpb24gPSB7IGxpbmU6IGVkaXRvci5nZXREb2MoKS5saW5lQ291bnQoKSwgY2g6IDB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGxldCBkb2NUZXh0ID0gZWRpdG9yLmdldFJhbmdlKGZyb21Qb3NpdGlvbiwgdG9Qb3NpdGlvbik7XHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IHJlc3VsdCA9IHVwZGF0ZUFsbFN5bnRheChkb2NUZXh0KTtcclxuICAgICAgICAgICAgICAgICAgICBsZXQgcmVnaW9uU3RhcnRDb3VudCA9IHJlc3VsdC5yZWdpb25TdGFydENvdW50O1xyXG4gICAgICAgICAgICAgICAgICAgIGxldCBjb2x1bW5CcmVha0NvdW50ID0gcmVzdWx0LmNvbHVtbkJyZWFrQ291bnQ7XHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IGNvbHVtbkVuZENvdW50ID0gcmVzdWx0LmNvbHVtbkVuZENvdW50O1xyXG4gICAgICAgICAgICAgICAgICAgIGxldCB1cGRhdGVkRmlsZUNvbnRlbnQgPSByZXN1bHQudXBkYXRlZEZpbGVDb250ZW50O1xyXG5cclxuICAgICAgICAgICAgICAgICAgICBpZihyZXN1bHQuZmlsZVdhc1VwZGF0ZWQpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZWRpdG9yLnJlcGxhY2VSYW5nZSh1cGRhdGVkRmlsZUNvbnRlbnQsIGZyb21Qb3NpdGlvbiwgdG9Qb3NpdGlvbilcclxuICAgICAgICAgICAgICAgICAgICAgICAgbmV3IE5vdGljZShgRmluaXNoZWQgdXBkYXRpbmc6XFxuJHtyZWdpb25TdGFydENvdW50fSBzdGFydCBzeW50YXhlcyxcXG4ke2NvbHVtbkJyZWFrQ291bnR9IGNvbHVtbiBicmVha3MsIGFuZFxcbiR7Y29sdW1uRW5kQ291bnR9IGNvbHVtbiBlbmQgdGFncy5gKVxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbmV3IE5vdGljZShgRm91bmQgbm8gcmVnaW9uIHN5bnRheCB0byB1cGRhdGUuYClcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbmV3IE5vdGljZShcclxuICAgICAgICAgICAgICAgICAgICAgICAgXCJFbmNvdW50ZXJlZCBhbiBlcnJvciBmaXhpbmcgbXVsdGktY29sdW1uIHJlZ2lvbiBzeW50YXguIFBsZWFzZSB0cnkgYWdhaW4gbGF0ZXIuXCJcclxuICAgICAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSk7XHJcbiAgICAgICAgdGhpcy5yZWdpc3RlckludGVydmFsKHdpbmRvdy5zZXRJbnRlcnZhbCgoKSA9PiB7XHJcbiAgICAgICAgICAgIFxyXG4gICAgICAgICAgICB0aGlzLlVwZGF0ZU9wZW5GaWxlUHJldmlld3MoKTtcclxuICAgICAgICB9LCA1MDApKTtcclxuICAgIH1cclxuXHJcbiAgICBVcGRhdGVPcGVuRmlsZVByZXZpZXdzKCkge1xyXG5cclxuICAgICAgICBsZXQgZmlsZU1hbmFnZXJzID0gdGhpcy5nbG9iYWxNYW5hZ2VyLmdldEFsbEZpbGVNYW5hZ2VycygpO1xyXG4gICAgICAgIGZpbGVNYW5hZ2Vycy5mb3JFYWNoKGVsZW1lbnQgPT4ge1xyXG4gICAgICAgICAgICBcclxuICAgICAgICAgICAgbGV0IHJlZ2lvbmFsTWFuYWdlcnMgPSBlbGVtZW50LmdldEFsbFJlZ2lvbmFsTWFuYWdlcnMoKTtcclxuICAgICAgICAgICAgcmVnaW9uYWxNYW5hZ2Vycy5mb3JFYWNoKHJlZ2lvbk1hbmFnZXIgPT4ge1xyXG4gICAgICAgICAgICAgICAgXHJcbiAgICAgICAgICAgICAgICByZWdpb25NYW5hZ2VyLnVwZGF0ZVJlbmRlcmVkTWFya2Rvd24oKVxyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBzZXR1cE1hcmtkb3duUG9zdFByb2Nlc3NvcigpIHtcclxuICAgICAgICB0aGlzLnJlZ2lzdGVyTWFya2Rvd25Qb3N0UHJvY2Vzc29yKGFzeW5jIChlbCwgY3R4KSA9PiB7XHJcblxyXG4gICAgICAgICAgICBpZih0aGlzLnNldHRpbmdzTWFuYWdlci5yZW5kZXJPbk1vYmlsZSA9PT0gZmFsc2UgJiZcclxuICAgICAgICAgICAgICAgUGxhdGZvcm0uaXNNb2JpbGUgPT09IHRydWUpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgY29uc3Qgc291cmNlUGF0aCA9IGN0eC5zb3VyY2VQYXRoO1xyXG5cclxuICAgICAgICAgICAgbGV0IGZpbGVET01NYW5hZ2VyID0gdGhpcy5nbG9iYWxNYW5hZ2VyLmdldEZpbGVNYW5hZ2VyKHNvdXJjZVBhdGgpO1xyXG4gICAgICAgICAgICBpZihmaWxlRE9NTWFuYWdlciA9PT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKFwiRm91bmQgbnVsbCBET00gbWFuYWdlci4gQ291bGQgbm90IHByb2Nlc3MgbXVsdGktY29sdW1uIG1hcmtkb3duLlwiKVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICogSGVyZSB3ZSBjaGVjayBpZiB0aGUgZXhwb3J0IFwicHJpbnRcIiBmbGFnIGlzIGluIHRoZSBET00gc28gd2UgY2FuIGRldGVybWluZSBpZiB3ZVxyXG4gICAgICAgICAgICAgKiBhcmUgZXhwb3J0aW5nIGFuZCBoYW5kbGUgdGhhdCBjYXNlLlxyXG4gICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgaWYodGhpcy5jaGVja0V4cG9ydGluZyhlbCkpIHtcclxuXHJcbiAgICAgICAgICAgICAgICB0aGlzLmV4cG9ydERvY3VtZW50VG9QREYoZWwsIGZpbGVET01NYW5hZ2VyLCBzb3VyY2VQYXRoKTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgLy8gR2V0IHRoZSBpbmZvIGZvciBvdXIgY3VycmVudCBjb250ZXh0IGFuZCB0aGVuIGNoZWNrXHJcbiAgICAgICAgICAgIC8vIGlmIHRoZSBlbnRpcmUgdGV4dCBjb250YWlucyBhIHN0YXJ0IHRhZy4gSWYgdGhlcmUgaXNcclxuICAgICAgICAgICAgLy8gbm8gc3RhcnQgdGFnIGluIHRoZSBkb2N1bWVudCB3ZSBjYW4ganVzdCByZXR1cm4gYW5kXHJcbiAgICAgICAgICAgIC8vIGlnbm9yZSB0aGUgcmVzdCBvZiB0aGUgcGFyc2luZy5cclxuICAgICAgICAgICAgbGV0IGluZm8gPSBjdHguZ2V0U2VjdGlvbkluZm8oZWwpO1xyXG5cclxuICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAqIFdlIG5lZWQgdGhlIGNvbnRleHQgaW5mbyB0byBwcm9wZXJseSBwYXJzZSBzbyByZXR1cm5pbmcgaGVyZSBcclxuICAgICAgICAgICAgICogaW5mbyBpcyBudWxsLiBUT0RPOiBTZXQgZXJyb3IgaW4gdmlldyBpZiB0aGlzIG9jY3Vycy5cclxuICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgIGlmKCFpbmZvKSB7XHJcblxyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBsZXQgZG9jU3RyaW5nID0gaW5mby50ZXh0O1xyXG4gICAgICAgICAgICBsZXQgZG9jTGluZXMgPSBkb2NTdHJpbmcuc3BsaXQoXCJcXG5cIik7XHJcblxyXG4gICAgICAgICAgICBsZXQgcmVmbG93RnJvbnRtYXR0ZXIgPSBpc011bHRpQ29sdW1uUmVmbG93KGN0eC5mcm9udG1hdHRlcik7XHJcbiAgICAgICAgICAgIGlmKHJlZmxvd0Zyb250bWF0dGVyID09PSB0cnVlKSB7XHJcbiBcclxuICAgICAgICAgICAgICAgIHRoaXMucmVuZGVyRG9jUmVmbG93KGVsLCBjdHgsIHNvdXJjZVBhdGgsIGZpbGVET01NYW5hZ2VyLCBkb2NTdHJpbmcsIGluZm8pO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgZmlsZURPTU1hbmFnZXIucmVtb3ZlUmVnaW9uKFwiTXVsdGktQ29sdW1uIFJlZmxvdyBSZWdpb25cIik7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8qKlxyXG4gICAgICAgICAgICAgKiBJZiB3ZSBlbmNvdW50ZXIgYSBzdGFydCB0YWcgb24gdGhlIGRvY3VtZW50IHdlIHNldCB0aGUgZmxhZyB0byBzdGFydFxyXG4gICAgICAgICAgICAgKiBwYXJzaW5nIHRoZSByZXN0IG9mIHRoZSBkb2N1bWVudC5cclxuICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgIGlmKG11bHRpQ29sdW1uUGFyc2VyLmNvbnRhaW5zUmVnaW9uU3RhcnQoZG9jU3RyaW5nKSkge1xyXG5cclxuICAgICAgICAgICAgICAgIGZpbGVET01NYW5hZ2VyLnNldEhhc1N0YXJ0VGFnKCk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8qKiBcclxuICAgICAgICAgICAgICogSWYgdGhlIGRvY3VtZW50IGRvZXMgbm90IGNvbnRhaW4gYW55IHN0YXJ0IHRhZ3Mgd2UgaWdub3JlIHRoZVxyXG4gICAgICAgICAgICAgKiByZXN0IG9mIHRoZSBwYXJzaW5nLiBUaGlzIGlzIG9ubHkgc2V0IHRvIHRydWUgb25jZSB0aGUgZmlyc3RcclxuICAgICAgICAgICAgICogc3RhcnQgdGFnIGVsZW1lbnQgaXMgcGFyc2VkIGFib3ZlLlxyXG4gICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgaWYoZmlsZURPTU1hbmFnZXIuZ2V0SGFzU3RhcnRUYWcoKSA9PT0gZmFsc2UpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAqIFRha2UgdGhlIGluZm8gcHJvdmlkZWQgYW5kIGdlbmVyYXRlIHRoZSByZXF1aXJlZCB2YXJpYWJsZXMgZnJvbSBcclxuICAgICAgICAgICAgICogdGhlIGxpbmUgc3RhcnQgYW5kIGVuZCB2YWx1ZXMuXHJcbiAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICBsZXQgcmVsYXRpdmVUZXh0czogRWxlbWVudFJlbGF0aXZlTG9jYXRpb25EYXRhID0gZXh0cmFjdEVsZW1lbnRSZWxhdGl2ZUxvY2F0aW9uRGF0YShkb2NMaW5lcywgaW5mbyk7XHJcblxyXG4gICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICogSWYgdGhlIGN1cnJlbnQgbGluZSBpcyBhIHN0YXJ0IHRhZyB3ZSB3YW50IHRvIHNldCB1cCB0aGVcclxuICAgICAgICAgICAgICogcmVnaW9uIG1hbmFnZXIuIFRoZSByZWdpb25hbCBtYW5hZ2VyIHRha2VzIGNhcmVcclxuICAgICAgICAgICAgICogb2YgYWxsIGl0ZW1zIGJldHdlZW4gaXQncyBzdGFydCBhbmQgZW5kIHRhZ3Mgd2hpbGUgdGhlXHJcbiAgICAgICAgICAgICAqIGZpbGUgbWFuYWdlciB3ZSBnb3QgYWJvdmUgYWJvdmUgdGFrZXMgY2FyZSBvZiBhbGwgcmVnaW9uYWwgXHJcbiAgICAgICAgICAgICAqIG1hbmFnZXJzIGluIGVhY2ggZmlsZS5cclxuICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgIGlmKG11bHRpQ29sdW1uUGFyc2VyLmNvbnRhaW5zU3RhcnRUYWcocmVsYXRpdmVUZXh0cy50ZXh0T2ZFbGVtZW50KSkge1xyXG4gICAgICAgICAgICAgICAgXHJcbiAgICAgICAgICAgICAgICBjcmVhdGVTdGFydEVsZW1lbnQoZWwsIHJlbGF0aXZlVGV4dHMubGluZXNPZkVsZW1lbnQsIGN0eCwgZmlsZURPTU1hbmFnZXIsIGRvY1N0cmluZyk7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8vIFBhbmRvYyBTdGFydCBSZWdpb24gVGFnLlxyXG4gICAgICAgICAgICBpZihjb250YWluc1BhbmRvYy5jb250YWluc1BhbmRvY1N0YXJ0VGFnKHJlbGF0aXZlVGV4dHMudGV4dE9mRWxlbWVudCkpIHtcclxuXHJcbiAgICAgICAgICAgICAgICBjcmVhdGVQYW5kb2NTdGFydEVsZW1lbnQoZWwsIHJlbGF0aXZlVGV4dHMudGV4dE9mRWxlbWVudCwgY3R4LCBmaWxlRE9NTWFuYWdlciwgZG9jU3RyaW5nKTtcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAqIENoZWNrIGlmIGFueSBvZiB0aGUgbGluZXMgYWJvdmUgdXMgY29udGFpbiBhIHN0YXJ0IGJsb2NrLCBhbmQgaWZcclxuICAgICAgICAgICAgICogc28gZ2V0IHRoZSBsaW5lcyBmcm9tIG91ciBjdXJyZW50IGVsZW1lbnQgdG8gdGhlIHN0YXJ0IGJsb2NrLlxyXG4gICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgbGV0IHN0YXJ0Qm9ja0Fib3ZlID0gbXVsdGlDb2x1bW5QYXJzZXIuZ2V0U3RhcnREYXRhQWJvdmVMaW5lKHJlbGF0aXZlVGV4dHMubGluZXNBYm92ZUFycmF5KTtcclxuICAgICAgICAgICAgaWYoc3RhcnRCb2NrQWJvdmUgPT09IG51bGwpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICogV2Ugbm93IGtub3cgd2UncmUgd2l0aGluIGEgbXVsdGktY29sdW1uIHJlZ2lvbiwgc28gd2UgdXBkYXRlIG91clxyXG4gICAgICAgICAgICAgKiBsaXN0IG9mIGxpbmVzIGFib3ZlIHRvIGp1c3QgYmUgdGhlIGl0ZW1zIHdpdGhpbiB0aGlzIHJlZ2lvbi5cclxuICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgIHJlbGF0aXZlVGV4dHMubGluZXNBYm92ZUFycmF5ID0gc3RhcnRCb2NrQWJvdmUubGluZXNBYm92ZUFycmF5O1xyXG5cclxuICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAqIFdlIHVzZSB0aGUgc3RhcnQgYmxvY2sncyBrZXkgdG8gZ2V0IG91ciByZWdpb25hbCBtYW5hZ2VyLiBJZiB0aGlzXHJcbiAgICAgICAgICAgICAqIGxvb2t1cCBmYWlscyB3ZSBjYW4gbm90IGNvbnRpbnVlIHByb2Nlc3NpbmcgdGhpcyBlbGVtZW50LlxyXG4gICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgbGV0IHJlZ2lvbmFsQ29udGFpbmVyOiBSZWdpb25NYW5hZ2VyQ29udGFpbmVyID0gZmlsZURPTU1hbmFnZXIuZ2V0UmVnaW9uYWxDb250YWluZXIoc3RhcnRCb2NrQWJvdmUuc3RhcnRCbG9ja0tleSk7XHJcbiAgICAgICAgICAgIGlmKHJlZ2lvbmFsQ29udGFpbmVyID09PSBudWxsKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgbGV0IHJlZ2lvbmFsTWFuYWdlcjogUmVnaW9uTWFuYWdlciA9IHJlZ2lvbmFsQ29udGFpbmVyLmdldFJlZ2lvbigpO1xyXG5cclxuICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAqIFRvIG1ha2Ugc3VyZSB3ZSdyZSBwbGFjaW5nIHRoZSBpdGVtIGluIHRoZSByaWdodCBsb2NhdGlvbiAoYW5kIFxyXG4gICAgICAgICAgICAgKiBvdmVyd3JpdGUgZWxlbWVudHMgdGhhdCBhcmUgbm93IGdvbmUpIHdlIG5vdyB3YW50IGFsbCBvZiB0aGVcclxuICAgICAgICAgICAgICogbGluZXMgYWZ0ZXIgdGhpcyBlbGVtZW50IHVwIHRvIHRoZSBlbmQgdGFnLlxyXG4gICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgcmVsYXRpdmVUZXh0cy5saW5lc0JlbG93QXJyYXkgPSAgbXVsdGlDb2x1bW5QYXJzZXIuZ2V0RW5kQmxvY2tCZWxvdyhyZWxhdGl2ZVRleHRzLmxpbmVzQmVsb3dBcnJheSk7XHJcblxyXG4gICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICogTm93IHdlIHRha2UgdGhlIGxpbmVzIGFib3ZlIG91ciBjdXJyZW50IGVsZW1lbnQgdXAgdW50aWwgdGhlXHJcbiAgICAgICAgICAgICAqIHN0YXJ0IHJlZ2lvbiB0YWcgYW5kIHJlbmRlciB0aGF0IGludG8gYW4gSFRNTCBlbGVtZW50LiBXZSB3aWxsIFxyXG4gICAgICAgICAgICAgKiB1c2UgdGhlc2UgZWxlbWVudHMgdG8gZGV0ZXJtaW5lIHdoZXJlIHRvIHBsYWNlIG91ciBjdXJyZW50IGVsZW1lbnQuXHJcbiAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICByZWdpb25hbE1hbmFnZXIgPSB0aGlzLmFwcGVuZFRvUmVnaW9uYWxNYW5hZ2VyKGVsLCByZWdpb25hbENvbnRhaW5lciwgY3R4LCByZWxhdGl2ZVRleHRzLCBzb3VyY2VQYXRoLCBzdGFydEJvY2tBYm92ZSwgKGRvbU9iajogRE9NT2JqZWN0KSA9PiB7XHJcbiAgICAgICAgICAgICAgICBvblVubG9hZEVsZW1lbnQoZG9tT2JqLCByZWdpb25hbENvbnRhaW5lcik7XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBhcHBlbmRUb1JlZ2lvbmFsTWFuYWdlcihlbDogSFRNTEVsZW1lbnQsIHJlZ2lvbmFsQ29udGFpbmVyOiBSZWdpb25NYW5hZ2VyQ29udGFpbmVyLCBjdHg6IE1hcmtkb3duUG9zdFByb2Nlc3NvckNvbnRleHQsIHJlbGF0aXZlTGluZXM6IEVsZW1lbnRSZWxhdGl2ZUxvY2F0aW9uRGF0YSwgc291cmNlUGF0aDogc3RyaW5nLCBwYXJlbnRTdGFydEJsb2NrOiBtdWx0aUNvbHVtblBhcnNlci5TdGFydFRhZ0RhdGEsIG9uVW5sb2FkQ2FsbGJhY2s6IChkb21PYmo6IERPTU9iamVjdCkgPT4gdm9pZCkge1xyXG5cclxuICAgICAgICBsZXQgeyBsaW5lc0Fib3ZlQXJyYXksIGxpbmVzT2ZFbGVtZW50LCBsaW5lc0JlbG93QXJyYXksIHRleHRPZkVsZW1lbnQgfSA9IHJlbGF0aXZlTGluZXM7XHJcblxyXG4gICAgICAgIGxldCBzaWJsaW5nc0Fib3ZlOiBIVE1MRGl2RWxlbWVudCA9IHJlbmRlck1hcmtkb3duRnJvbUxpbmVzKGxpbmVzQWJvdmVBcnJheSwgc291cmNlUGF0aCk7XHJcblxyXG4gICAgICAgIGxldCBzaWJsaW5nc0JlbG93OiBIVE1MRGl2RWxlbWVudCA9IHJlbmRlck1hcmtkb3duRnJvbUxpbmVzKGxpbmVzQmVsb3dBcnJheSwgc291cmNlUGF0aCk7XHJcbiAgICAgICAgXHJcbiAgICAgICAgbGV0IHJlZ2lvbmFsTWFuYWdlcjogUmVnaW9uTWFuYWdlciA9IHJlZ2lvbmFsQ29udGFpbmVyLmdldFJlZ2lvbigpO1xyXG5cclxuICAgICAgICAvKipcclxuICAgICAgICAgKiBTZXQgdXAgb3VyIGRvbSBvYmplY3QgdG8gYmUgYWRkZWQgdG8gdGhlIG1hbmFnZXIuXHJcbiAgICAgICAgICovXHJcbiAgICAgICAgbGV0IGN1cnJlbnRPYmplY3Q6IERPTU9iamVjdCA9IG5ldyBET01PYmplY3QoZWwsIGxpbmVzT2ZFbGVtZW50KTtcclxuICAgICAgICBlbC5pZCA9IGN1cnJlbnRPYmplY3QuVUlEO1xyXG5cclxuICAgICAgICBjdXJyZW50T2JqZWN0ID0gVGFza0xpc3RET01PYmplY3QuY2hlY2tGb3JUYXNrTGlzdEVsZW1lbnQoY3VycmVudE9iamVjdCk7XHJcblxyXG4gICAgICAgIC8qKlxyXG4gICAgICAgICAqIE5vdyB3ZSBhZGQgdGhlIG9iamVjdCB0byB0aGUgbWFuYWdlciBhbmQgdGhlbiBzZXR1cCB0aGVcclxuICAgICAgICAgKiBjYWxsYmFjayBmb3Igd2hlbiB0aGUgb2JqZWN0IGlzIHJlbW92ZWQgZnJvbSB2aWV3IHRoYXQgd2lsbCByZW1vdmVcclxuICAgICAgICAgKiB0aGUgaXRlbSBmcm9tIHRoZSBtYW5hZ2VyLlxyXG4gICAgICAgICAqL1xyXG4gICAgICAgIGxldCBhZGRJbmRleCA9IHJlZ2lvbmFsTWFuYWdlci5hZGRPYmplY3Qoc2libGluZ3NBYm92ZSwgc2libGluZ3NCZWxvdywgY3VycmVudE9iamVjdCk7XHJcblxyXG4gICAgICAgIGxldCBlbGVtZW50TWFya2Rvd25SZW5kZXJlciA9IG5ldyBNYXJrZG93blJlbmRlckNoaWxkKGVsKTtcclxuICAgICAgICBlbGVtZW50TWFya2Rvd25SZW5kZXJlci5vbnVubG9hZCA9ICgpID0+IHtcclxuICAgICAgICAgICAgb25VbmxvYWRDYWxsYmFjayhjdXJyZW50T2JqZWN0KTtcclxuICAgICAgICB9XHJcbiAgICAgICAgY3R4LmFkZENoaWxkKGVsZW1lbnRNYXJrZG93blJlbmRlcmVyKTtcclxuXHJcbiAgICAgICAgLyoqXHJcbiAgICAgICAgICogTm93IHdlIGNoZWNrIGlmIG91ciBjdXJyZW50IGVsZW1lbnQgaXMgYSBzcGVjaWFsIGZsYWcgc28gd2UgY2FuXHJcbiAgICAgICAgICogcHJvcGVybHkgc2V0IHRoZSBlbGVtZW50IHRhZyB3aXRoaW4gdGhlIHJlZ2lvbmFsIG1hbmFnZXIuXHJcbiAgICAgICAgICovXHJcbiAgICAgICAgaWYgKG11bHRpQ29sdW1uUGFyc2VyLmNvbnRhaW5zRW5kVGFnKGVsLnRleHRDb250ZW50KSA9PT0gdHJ1ZSAmJlxyXG4gICAgICAgICAgICBwYXJlbnRTdGFydEJsb2NrLnN0YXJ0QmxvY2tUeXBlICE9PSBcIlBBRE9DXCIpIHtcclxuXHJcbiAgICAgICAgICAgIGN1cnJlbnRPYmplY3QuZWxlbWVudFR5cGUgPSBcInVuUmVuZGVyZWRcIjtcclxuICAgICAgICAgICAgcmVnaW9uYWxNYW5hZ2VyLnVwZGF0ZUVsZW1lbnRUYWcoY3VycmVudE9iamVjdC5VSUQsIERPTU9iamVjdFRhZy5lbmRSZWdpb24pO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAoY29udGFpbnNQYW5kb2MuaXNWYWxpZFBhbmRvY0VuZFRhZyhsaW5lc0Fib3ZlQXJyYXksIGVsLnRleHRDb250ZW50KSA9PT0gdHJ1ZSAmJlxyXG4gICAgICAgICAgICBwYXJlbnRTdGFydEJsb2NrLnN0YXJ0QmxvY2tUeXBlID09PSBcIlBBRE9DXCIpIHtcclxuXHJcbiAgICAgICAgICAgIGN1cnJlbnRPYmplY3QuZWxlbWVudFR5cGUgPSBcInVuUmVuZGVyZWRcIjtcclxuICAgICAgICAgICAgcmVnaW9uYWxNYW5hZ2VyLnVwZGF0ZUVsZW1lbnRUYWcoY3VycmVudE9iamVjdC5VSUQsIERPTU9iamVjdFRhZy5lbmRSZWdpb24pO1xyXG4gICAgICAgIH1cclxuICAgICAgICBlbHNlIGlmIChtdWx0aUNvbHVtblBhcnNlci5jb250YWluc0NvbEVuZFRhZyh0ZXh0T2ZFbGVtZW50KSA9PT0gdHJ1ZSkge1xyXG5cclxuICAgICAgICAgICAgY3VycmVudE9iamVjdC5lbGVtZW50VHlwZSA9IFwidW5SZW5kZXJlZFwiO1xyXG4gICAgICAgICAgICByZWdpb25hbE1hbmFnZXIudXBkYXRlRWxlbWVudFRhZyhjdXJyZW50T2JqZWN0LlVJRCwgRE9NT2JqZWN0VGFnLmNvbHVtbkJyZWFrKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSBpZiAobXVsdGlDb2x1bW5QYXJzZXIuY29udGFpbnNDb2xTZXR0aW5nc1RhZyh0ZXh0T2ZFbGVtZW50KSA9PT0gdHJ1ZSkge1xyXG5cclxuICAgICAgICAgICAgY3VycmVudE9iamVjdC5lbGVtZW50VHlwZSA9IFwidW5SZW5kZXJlZFwiO1xyXG4gICAgICAgICAgICByZWdpb25hbE1hbmFnZXIgPSByZWdpb25hbENvbnRhaW5lci5zZXRSZWdpb25TZXR0aW5ncyh0ZXh0T2ZFbGVtZW50KTtcclxuICAgICAgICAgICAgcmVnaW9uYWxNYW5hZ2VyLnVwZGF0ZUVsZW1lbnRUYWcoY3VycmVudE9iamVjdC5VSUQsIERPTU9iamVjdFRhZy5yZWdpb25TZXR0aW5ncyk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHNldEVsZW1lbnRDU1MoY3VycmVudE9iamVjdCwgZWwpO1xyXG5cclxuICAgICAgICBwYXJzZUNvbEJyZWFrRXJyb3JUeXBlKHtcclxuICAgICAgICAgICAgbGluZUFib3ZlOiBsaW5lc0Fib3ZlQXJyYXkubGFzdCgpLFxyXG4gICAgICAgICAgICBsaW5lQmVsb3c6IGxpbmVzQmVsb3dBcnJheS5maXJzdCgpLFxyXG4gICAgICAgICAgICBvYmplY3RUYWc6IGN1cnJlbnRPYmplY3QudGFnLFxyXG4gICAgICAgICAgICBjb2xCcmVha1R5cGU6IGN1cnJlbnRPYmplY3QuZWxlbWVudElzQ29sdW1uQnJlYWtcclxuICAgICAgICB9LCByZWdpb25hbE1hbmFnZXIuZXJyb3JNYW5hZ2VyKVxyXG5cclxuICAgICAgICByZWdpb25hbE1hbmFnZXIucmVuZGVyUmVnaW9uRWxlbWVudHNUb1NjcmVlbigpO1xyXG4gICAgICAgIHJldHVybiByZWdpb25hbE1hbmFnZXI7XHJcbiAgICB9XHJcblxyXG4gICAgc2V0dXBNYXJrZG93bkNvZGVibG9ja1Bvc3RQcm9jZXNzb3Ioc3RhcnRTdHI6IHN0cmluZykge1xyXG5cclxuICAgICAgICB0aGlzLnJlZ2lzdGVyTWFya2Rvd25Db2RlQmxvY2tQcm9jZXNzb3Ioc3RhcnRTdHIsIChzb3VyY2UsIGVsLCBjdHgpID0+IHtcclxuXHJcbiAgICAgICAgICAgIGlmKHRoaXMuc2V0dGluZ3NNYW5hZ2VyLnJlbmRlck9uTW9iaWxlID09PSBmYWxzZSAmJlxyXG4gICAgICAgICAgICAgICAgUGxhdGZvcm0uaXNNb2JpbGUgPT09IHRydWUpIHtcclxuIFxyXG4gICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgY29uc3Qgc291cmNlUGF0aCA9IGN0eC5zb3VyY2VQYXRoO1xyXG4gICAgICAgIFxyXG4gICAgICAgICAgICAvLyBTZXQgdXAgb3VyIENTUyBzbyB0aGF0IHRoZSBjb2RlYmxvY2sgb25seSByZW5kZXJzIHRoaXMgZGF0YSBpbiByZWFkaW5nIG1vZGVcclxuICAgICAgICAgICAgLy8gc291cmNlL2xpdmUgcHJldmlldyBtb2RlIGlzIGhhbmRsZWQgYnkgdGhlIENNNiBpbXBsZW1lbnRhdGlvbi5cclxuICAgICAgICAgICAgZWwucGFyZW50RWxlbWVudD8uYWRkQ2xhc3MoXCJwcmVpdmV3LW1jbS1zdGFydC1ibG9ja1wiKTtcclxuICAgICAgICBcclxuICAgICAgICAgICAgLy8gVG8gZGV0ZXJtaW5lIHdoYXQga2luZCBvZiB2aWV3IHdlIGFyZSByZW5kZXJpbmcgaW4gd2UgbmVlZCBhIG1hcmtkb3duIGxlYWYuXHJcbiAgICAgICAgICAgIC8vIFJlYWxseSB0aGlzIHNob3VsZCBuZXZlciByZXR1cm4gaGVyZSBzaW5jZSByZW5kZXJpbmcgaXMgb25seSBkb25lIGluIG1hcmtkb3duIGxlYXZlcy5cclxuICAgICAgICAgICAgbGV0IG1hcmtkb3duTGVhdmVzID0gYXBwLndvcmtzcGFjZS5nZXRMZWF2ZXNPZlR5cGUoXCJtYXJrZG93blwiKTtcclxuICAgICAgICAgICAgaWYobWFya2Rvd25MZWF2ZXMubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICBcclxuICAgICAgICAgICAgaWYodGhpcy5nbG9iYWxNYW5hZ2VyID09PSBudWxsIHx8IHRoaXMuZ2xvYmFsTWFuYWdlciA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIkdsb2JhbCBtYW5hZ2VyIGlzIHVuZGVmaW5lZD9cIik7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGxldCBmaWxlRE9NTWFuYWdlciA9IHRoaXMuZ2xvYmFsTWFuYWdlci5nZXRGaWxlTWFuYWdlcihzb3VyY2VQYXRoKTtcclxuICAgICAgICAgICAgaWYoZmlsZURPTU1hbmFnZXIgPT09IG51bGwpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBcclxuICAgICAgICAgICAgaWYoY3R4LmZyb250bWF0dGVyICYmIFxyXG4gICAgICAgICAgICAgICBjdHguZnJvbnRtYXR0ZXJbXCJNdWx0aS1Db2x1bW4gUmVmbG93XCJdICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGZpbGVET01NYW5hZ2VyLnJlbW92ZVJlZ2lvbihcIk11bHRpLUNvbHVtbiBSZWZsb3cgUmVnaW9uXCIpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvLyBTZXQgZmlsZSB0byBoYXZlIHN0YXJ0IHRhZy5cclxuICAgICAgICAgICAgZmlsZURPTU1hbmFnZXIuc2V0SGFzU3RhcnRUYWcoKTtcclxuICAgICAgICBcclxuICAgICAgICAgICAgLy8gR2V0IHRoZSBpbmZvIGZvciBvdXIgY3VycmVudCBjb250ZXh0IGFuZCB0aGVuIGNoZWNrXHJcbiAgICAgICAgICAgIC8vIGlmIHRoZSBlbnRpcmUgdGV4dCBjb250YWlucyBhIHN0YXJ0IHRhZy4gSWYgdGhlcmUgaXNcclxuICAgICAgICAgICAgLy8gbm8gc3RhcnQgdGFnIGluIHRoZSBkb2N1bWVudCB3ZSBjYW4ganVzdCByZXR1cm4gYW5kXHJcbiAgICAgICAgICAgIC8vIGlnbm9yZSB0aGUgcmVzdCBvZiB0aGUgcGFyc2luZy5cclxuICAgICAgICAgICAgbGV0IGluZm8gPSBjdHguZ2V0U2VjdGlvbkluZm8oZWwpO1xyXG4gICAgICAgIFxyXG4gICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICogV2UgbmVlZCB0aGUgY29udGV4dCBpbmZvIHRvIHByb3Blcmx5IHBhcnNlIHNvIHJldHVybmluZyBoZXJlIFxyXG4gICAgICAgICAgICAgKiBpbmZvIGlzIG51bGwuIFRPRE86IFNldCBlcnJvciBpbiB2aWV3IGlmIHRoaXMgb2NjdXJzLlxyXG4gICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgaWYoIWluZm8pIHtcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIFxyXG4gICAgICAgICAgICAvKiogXHJcbiAgICAgICAgICAgICAqIFNldCB1cCB0aGUgY3VycmVudCBlbGVtZW50IHRvIGFjdCBhcyB0aGUgcGFyZW50IGZvciB0aGUgXHJcbiAgICAgICAgICAgICAqIG11bHRpLWNvbHVtbiByZWdpb24uXHJcbiAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICBlbC5jbGFzc0xpc3QuYWRkKE11bHRpQ29sdW1uTGF5b3V0Q1NTLlJlZ2lvblJvb3RDb250YWluZXJEaXYpXHJcblxyXG4gICAgICAgICAgICBsZXQgZXJyb3JNYW5hZ2VyID0gbmV3IFJlZ2lvbkVycm9yTWFuYWdlcihlbCwgW1wiVGhlIGNvZGVibG9jayByZWdpb24gc3RhcnQgc3ludGF4IGhhcyBiZWVuIGRlcHJpY2F0ZWQuIFBsZWFzZSBtYW51YWxseSB1cGRhdGUgdG8gdGhlIGN1cnJlbnQgc3ludGF4IGRlZmluZWQgaW4gdGhlIFJlYWRNZSwgcnVuIHRoZSBcXFwiRml4IE11bHRpLUNvbHVtbiBTeW50YXggaW4gQ3VycmVudCBGaWxlXFxcIiBmcm9tIHRoZSBDb21tYW5kIFBhbGV0dGUsIG9yIHVzZSB0aGUgXFxcIlVwZGF0ZSBEZXByaWNhdGVkIFN5bnRheFxcXCIgY29tbWFuZCBmb3VuZCBpbiB0aGUgcGx1Z2luIHNldHRpbmdzIHdpbmRvdy4gWW91IG11c3QgcmVsb2FkIHRoZSBmaWxlIGZvciBjaGFuZ2VzIHRvIHRha2UgZWZmZWN0LlwiXSk7XHJcbiAgICAgICAgICAgIGxldCByZW5kZXJDb2x1bW5SZWdpb24gPSBlbC5jcmVhdGVEaXYoe1xyXG4gICAgICAgICAgICAgICAgY2xzOiBNdWx0aUNvbHVtbkxheW91dENTUy5SZWdpb25Db250ZW50Q29udGFpbmVyRGl2XHJcbiAgICAgICAgICAgIH0pXHJcbiAgICAgICAgXHJcbiAgICAgICAgICAgIGxldCByZWdpb25LZXkgPSBwYXJzZVN0YXJ0UmVnaW9uQ29kZUJsb2NrSUQoc291cmNlKTtcclxuICAgICAgICBcclxuICAgICAgICAgICAgbGV0IGNyZWF0ZU5ld1JlZ2lvbk1hbmFnZXIgPSB0cnVlO1xyXG4gICAgICAgICAgICBpZihmaWxlRE9NTWFuYWdlci5jaGVja0tleUV4aXN0cyhyZWdpb25LZXkpID09PSB0cnVlKSB7XHJcbiAgICAgICAgICAgICAgICBcclxuICAgICAgICAgICAgICAgIGNyZWF0ZU5ld1JlZ2lvbk1hbmFnZXIgPSBmYWxzZTtcclxuICAgICAgICAgICAgICAgIGxldCB7IG51bWJlck9mVGFncywga2V5cyB9ID0gbXVsdGlDb2x1bW5QYXJzZXIuY291bnRTdGFydFRhZ3MoaW5mby50ZXh0KTtcclxuICAgICAgICBcclxuICAgICAgICAgICAgICAgIGxldCBudW1NYXRjaGVzID0gMDtcclxuICAgICAgICAgICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCBudW1iZXJPZlRhZ3M7IGkrKykge1xyXG4gICAgICAgIFxyXG4gICAgICAgICAgICAgICAgICAgIC8vIEJlY2F1c2Ugd2UgY2hlY2tlZCBpZiBrZXkgZXhpc3RzIG9uZSBvZiB0aGVzZSBoYXMgdG8gbWF0Y2guXHJcbiAgICAgICAgICAgICAgICAgICAgaWYoa2V5c1tpXSA9PT0gcmVnaW9uS2V5KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG51bU1hdGNoZXMrKztcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgXHJcbiAgICAgICAgICAgICAgICAvLyBXZSBvbmx5IHdhbnQgdG8gZGlzcGxheSBhbiBlcnJvciBpZiB0aGVyZSBhcmUgbW9yZSB0aGFuIDIgb2YgdGhlIHNhbWUgaWQgYWNyb3NzXHJcbiAgICAgICAgICAgICAgICAvLyB0aGUgd2hvbGUgZG9jdW1lbnQuIFRoaXMgcHJldmVudHMgZXJyb3Mgd2hlbiBvYnNpZGlhbiByZWxvYWRzIHRoZSB3aG9sZSBkb2N1bWVudFxyXG4gICAgICAgICAgICAgICAgLy8gYW5kIHRoZXJlIGFyZSB0d28gb2YgdGhlIHNhbWUga2V5IGluIHRoZSBtYXAuXHJcbiAgICAgICAgICAgICAgICBpZihudW1NYXRjaGVzID49IDIpIHtcclxuICAgICAgICAgICAgICAgICAgICBpZihyZWdpb25LZXkgPT09IFwiXCIpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNYW5hZ2VyLmFkZEVycm9yTWVzc2FnZShcIkZvdW5kIG11bHRpcGxlIHJlZ2lvbnMgd2l0aCBlbXB0eSBJRHMuIFBsZWFzZSBzZXQgYSB1bmlxdWUgSUQgaW4gdGhlIGNvZGVibG9jay5cXG5FRzogJ0lEOiByYW5kb21JRCdcIik7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvck1hbmFnZXIuYWRkRXJyb3JNZXNzYWdlKFwiUmVnaW9uIElEIGFscmVhZHkgZXhpc3RzIGluIGRvY3VtZW50LCBwbGVhc2Ugc2V0IGEgdW5pcXVlIElELlwiKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGVsLmlkID0gYE11bHRpQ29sdW1uSUQ6JHtyZWdpb25LZXl9YFxyXG4gICAgICAgIFxyXG4gICAgICAgICAgICAvLyBJZiBzb21ldGhpbmcgY2hhbmdlcyBpbiB0aGUgY29kZWJsb2NrIHdlIGRvbnQgbmVjZXNzYXJpbHkgd2FudCB0byB1cGRhdGUgb3VyXHJcbiAgICAgICAgICAgIC8vIG9sZCByZWZlcmVuY2UgdG8gdGhlIHJlZ2lvbiBtYW5hZ2VyLiBUaGlzIGNvdWxkIGJlIGEgcG90ZW50aWFsIGJ1ZyBhcmVhLlxyXG4gICAgICAgICAgICBpZihjcmVhdGVOZXdSZWdpb25NYW5hZ2VyID09PSB0cnVlKSB7XHJcbiAgICAgICAgXHJcbiAgICAgICAgICAgICAgICAvLyBDcmVhdGUgYSBuZXcgcmVnaW9uYWwgbWFuYWdlci5cclxuICAgICAgICAgICAgICAgIGxldCBlbGVtZW50TWFya2Rvd25SZW5kZXJlciA9IG5ldyBNYXJrZG93blJlbmRlckNoaWxkKGVsKTtcclxuICAgICAgICAgICAgICAgIGZpbGVET01NYW5hZ2VyLmNyZWF0ZVJlZ2lvbmFsTWFuYWdlcihyZWdpb25LZXksIGVsLCBlcnJvck1hbmFnZXIsIHJlbmRlckNvbHVtblJlZ2lvbik7XHJcbiAgICAgICAgXHJcbiAgICAgICAgICAgICAgICAvLyBTZXQgdXAgdGhlIG9uIHVubG9hZCBjYWxsYmFjay4gVGhpcyBjYW4gYmUgY2FsbGVkIGlmIHRoZSB1c2VyIGNoYW5nZXNcclxuICAgICAgICAgICAgICAgIC8vIHRoZSBzdGFydC9zZXR0aW5ncyBjb2RlYmxvY2sgaW4gYW55IHdheS4gV2Ugb25seSB3YW50IHRvIHVubG9hZFxyXG4gICAgICAgICAgICAgICAgLy8gaWYgdGhlIGZpbGUgaXMgYmVpbmcgcmVtb3ZlZCBmcm9tIHZpZXcuXHJcbiAgICAgICAgICAgICAgICBlbGVtZW50TWFya2Rvd25SZW5kZXJlci5vbnVubG9hZCA9ICgpID0+IHtcclxuICAgICAgICBcclxuICAgICAgICAgICAgICAgICAgICBpZihmaWxlRE9NTWFuYWdlciAmJiBmaWxlU3RpbGxJblZpZXcoc291cmNlUGF0aCkgPT09IGZhbHNlKSB7XHJcbiAgICAgICAgXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGNvbnNvbGUuZGVidWcoXCJGaWxlIG5vdCBpbiBhbnkgbWFya2Rvd24gbGVhZi4gUmVtb3ZpbmcgcmVnaW9uIGZyb20gZG9tIG1hbmFnZXIuXCIpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbGVET01NYW5hZ2VyLnJlbW92ZVJlZ2lvbihyZWdpb25LZXkpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgICAgICBjdHguYWRkQ2hpbGQoZWxlbWVudE1hcmtkb3duUmVuZGVyZXIpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgXHJcbiAgICAgICAgICAgIGxldCByZWdpb25hbE1hbmFnZXJDb250YWluZXIgPSBmaWxlRE9NTWFuYWdlci5nZXRSZWdpb25hbENvbnRhaW5lcihyZWdpb25LZXkpO1xyXG4gICAgICAgICAgICBpZihyZWdpb25hbE1hbmFnZXJDb250YWluZXIgIT09IG51bGwpIHtcclxuICAgICAgICBcclxuICAgICAgICAgICAgICAgIGxldCByZWdpb25hbE1hbmFnZXIgPSByZWdpb25hbE1hbmFnZXJDb250YWluZXIuc2V0UmVnaW9uU2V0dGluZ3Moc291cmNlKTtcclxuICAgICAgICAgICAgICAgIHJlZ2lvbmFsTWFuYWdlci5yZWdpb25QYXJlbnQgPSByZW5kZXJDb2x1bW5SZWdpb247XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9KVxyXG4gICAgfVxyXG5cclxuICAgIGFzeW5jIGxvYWRTZXR0aW5ncygpIHtcclxuXHJcblx0XHR0aGlzLnNldHRpbmdzTWFuYWdlci5zZXR0aW5ncyA9IE9iamVjdC5hc3NpZ24oe30sIERFRkFVTFRfU0VUVElOR1MsIGF3YWl0IHRoaXMubG9hZERhdGEoKSk7XHJcblx0fVxyXG5cclxuXHRhc3luYyBzYXZlU2V0dGluZ3MoKSB7XHJcblx0XHRhd2FpdCB0aGlzLnNhdmVEYXRhKHRoaXMuc2V0dGluZ3NNYW5hZ2VyLnNldHRpbmdzKTtcclxuXHR9XHJcblxyXG4gICAgcmVuZGVyRG9jUmVmbG93KGVsOiBIVE1MRWxlbWVudCwgY3R4OiBNYXJrZG93blBvc3RQcm9jZXNzb3JDb250ZXh0LCBzb3VyY2VQYXRoOiBzdHJpbmcsIGZpbGVET01NYW5hZ2VyOiBGaWxlRE9NTWFuYWdlciwgZG9jU3RyaW5nOiBzdHJpbmcsIGluZm86IE1hcmtkb3duU2VjdGlvbkluZm9ybWF0aW9uKSB7XHJcblxyXG4gICAgICAgIGxldCByZWdpb25hbENvbnRhaW5lcjogUmVnaW9uTWFuYWdlckNvbnRhaW5lciA9IG51bGw7XHJcbiAgICAgICAgaWYoZmlsZURPTU1hbmFnZXIuY2hlY2tLZXlFeGlzdHMoXCJNdWx0aS1Db2x1bW4gUmVmbG93IFJlZ2lvblwiKSA9PT0gdHJ1ZSAmJlxyXG4gICAgICAgICAgIGVsLmdldEVsZW1lbnRzQnlDbGFzc05hbWUoXCJmcm9udG1hdHRlclwiKS5sZW5ndGggPT09IDApIHtcclxuICAgICAgICAgICAgcmVnaW9uYWxDb250YWluZXIgPSBmaWxlRE9NTWFuYWdlci5nZXRSZWdpb25hbENvbnRhaW5lcihcIk11bHRpLUNvbHVtbiBSZWZsb3cgUmVnaW9uXCIpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBlbHNlIGlmKGZpbGVET01NYW5hZ2VyLmNoZWNrS2V5RXhpc3RzKFwiTXVsdGktQ29sdW1uIFJlZmxvdyBSZWdpb25cIikgPT09IHRydWUgJiZcclxuICAgICAgICAgICAgICAgIGVsLmdldEVsZW1lbnRzQnlDbGFzc05hbWUoXCJmcm9udG1hdHRlclwiKS5sZW5ndGggPT09IDEpIHtcclxuXHJcbiAgICAgICAgICAgIGxldCBwYXJlbnRFbCA9IGNyZWF0ZURpdigpXHJcbiAgICAgICAgICAgIGVsLmFwcGVuZENoaWxkKHBhcmVudEVsKTtcclxuXHJcbiAgICAgICAgICAgIC8vIEdldCBjdXJyZW50IGRhdGEsIHJlbW92ZSBvbGQgcmVnaW9uLlxyXG4gICAgICAgICAgICByZWdpb25hbENvbnRhaW5lciA9IGZpbGVET01NYW5hZ2VyLmdldFJlZ2lvbmFsQ29udGFpbmVyKFwiTXVsdGktQ29sdW1uIFJlZmxvdyBSZWdpb25cIik7XHJcbiAgICAgICAgICAgIGxldCBkb21MaXN0ID0gcmVnaW9uYWxDb250YWluZXIuZ2V0UmVnaW9uKCkuZ2V0UmVnaW9uRGF0YSgpLmRvbUxpc3Quc2xpY2UoKTtcclxuICAgICAgICAgICAgZmlsZURPTU1hbmFnZXIucmVtb3ZlUmVnaW9uKFwiTXVsdGktQ29sdW1uIFJlZmxvdyBSZWdpb25cIik7XHJcblxyXG4gICAgICAgICAgICAvLyBDcmVhdGUgbmV3IHJlZ2lvbi5cclxuICAgICAgICAgICAgc2V0dXBTdGFydFRhZyhwYXJlbnRFbCwgY3R4LCBmaWxlRE9NTWFuYWdlciwgZG9jU3RyaW5nLCBcIk11bHRpLUNvbHVtbiBSZWZsb3cgUmVnaW9uXCIpO1xyXG4gICAgICAgICAgICByZWdpb25hbENvbnRhaW5lciA9IGZpbGVET01NYW5hZ2VyLmdldFJlZ2lvbmFsQ29udGFpbmVyKFwiTXVsdGktQ29sdW1uIFJlZmxvdyBSZWdpb25cIik7XHJcbiAgICAgICAgICAgIGxldCBzZXR0aW5ncyA9IGdldE11bHRpQ29sdW1uU2V0dGluZ3NGcm9tRnJvbnRtYXR0ZXIoY3R4KTtcclxuICAgICAgICAgICAgXHJcbiAgICAgICAgICAgIGxldCBsZWFmID0gZ2V0TGVhZkZyb21GaWxlUGF0aCh0aGlzLmFwcC53b3Jrc3BhY2UsIGN0eC5zb3VyY2VQYXRoKTtcclxuICAgICAgICAgICAgbGV0IGNsaWVudEhlaWdodCA9IGNhbGNWaXNpYmxlQ2xpZXRIZWlnaHQobGVhZiwgdGhpcy5hcHAud29ya3NwYWNlKTtcclxuICAgICAgICAgICAgaWYoc2V0dGluZ3MuY29sdW1uSGVpZ2h0ID09PSBudWxsKSB7XHJcbiAgICAgICAgICAgICAgICBzZXR0aW5ncy5jb2x1bW5IZWlnaHQgPSBIVE1MU2l6aW5nLmNyZWF0ZSgpLnNldFdpZHRoKGNsaWVudEhlaWdodCkuc2V0VW5pdHMoXCJweFwiKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgIHNldHRpbmdzLmNvbHVtbkhlaWdodCA9IHNldHRpbmdzLmNvbHVtbkhlaWdodC5jb252ZXJ0VG9QWCh0aGlzLmFwcC53b3Jrc3BhY2UuY29udGFpbmVyRWwpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHJlZ2lvbmFsQ29udGFpbmVyLnNldFJlZ2lvblBhcnNlZFNldHRpbmdzKHNldHRpbmdzKTtcclxuICAgICAgICAgICAgXHJcbiAgICAgICAgICAgIC8vIFJlLVJlbmRlciBhZnRlciBzbWFsbCBkZWxheS5cclxuICAgICAgICAgICAgLy8gRGVsYXkgaXMgc28gdGhlIGF1dG8gbGF5b3V0IGNoZWNrIGNhbiBwcm9wZXJseSByZWFkIHRoZSBjbGllbnQgaGVpZ2h0LlxyXG4gICAgICAgICAgICBhc3luYyBmdW5jdGlvbiBkZWxheVJlbmRlcigpIHtcclxuXHJcbiAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KCgpPT4geyAgICAgICAgICAgICAgICAgICAgXHJcblxyXG4gICAgICAgICAgICAgICAgICAgIC8vIEFwcGVuZCBhbGwgaXRlbXMgdG8gcmVnaW9uLlxyXG4gICAgICAgICAgICAgICAgICAgIGxldCByZWdpb25hbE1hbmFnZXIgPSByZWdpb25hbENvbnRhaW5lci5nZXRSZWdpb24oKTtcclxuICAgICAgICAgICAgICAgICAgICBsZXQgbGlzdExlbmd0aCA9IGRvbUxpc3QubGVuZ3RoO1xyXG4gICAgICAgICAgICAgICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCBsaXN0TGVuZ3RoOyBpKyspIHtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBkb21PYmogPSBkb21MaXN0LnNoaWZ0KClcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmVnaW9uYWxNYW5hZ2VyLmFkZE9iamVjdEF0SW5kZXgoZG9tT2JqLCBpKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldEVsZW1lbnRDU1MoZG9tT2JqLCBkb21PYmoub3JpZ2luYWxFbGVtZW50KTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIHJlZ2lvbmFsQ29udGFpbmVyLmdldFJlZ2lvbigpLnJlbmRlclJlZ2lvbkVsZW1lbnRzVG9TY3JlZW4oKTtcclxuICAgICAgICAgICAgICAgIH0sIDUwKVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGRlbGF5UmVuZGVyKCk7XHJcblxyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGVsc2Uge1xyXG5cclxuICAgICAgICAgICAgLy8gVGhlIGZpcnN0IGVsZW1lbnQgdG8gaGl0IHRoaXMgcG9pbnQgYXBwZWFycyB0byBiZSB0aGUgeWFtbCBpbmZvcm1hdGlvbiB3aGljaCB3ZSBjYW4gdXNlXHJcbiAgICAgICAgICAgIC8vIGFzIG91ciByb290IGRpdiBzaW5jZSB0aGUgd2hvbGUgZG9jIGlzIGdvaW5nIHRvIGJlIHJlLWZvcm1hdHRlZC5cclxuICAgICAgICAgICAgbGV0IHBhcmVudEVsID0gY3JlYXRlRGl2KClcclxuICAgICAgICAgICAgZWwuYXBwZW5kQ2hpbGQocGFyZW50RWwpO1xyXG5cclxuICAgICAgICAgICAgc2V0dXBTdGFydFRhZyhwYXJlbnRFbCwgY3R4LCBmaWxlRE9NTWFuYWdlciwgZG9jU3RyaW5nLCBcIk11bHRpLUNvbHVtbiBSZWZsb3cgUmVnaW9uXCIpO1xyXG4gICAgICAgICAgICByZWdpb25hbENvbnRhaW5lciA9IGZpbGVET01NYW5hZ2VyLmdldFJlZ2lvbmFsQ29udGFpbmVyKFwiTXVsdGktQ29sdW1uIFJlZmxvdyBSZWdpb25cIik7XHJcblxyXG4gICAgICAgICAgICBsZXQgc2V0dGluZ3MgPSBnZXRNdWx0aUNvbHVtblNldHRpbmdzRnJvbUZyb250bWF0dGVyKGN0eCk7XHJcbiAgICAgICAgICAgIGxldCBsZWFmID0gZ2V0TGVhZkZyb21GaWxlUGF0aCh0aGlzLmFwcC53b3Jrc3BhY2UsIGN0eC5zb3VyY2VQYXRoKTtcclxuXHJcbiAgICAgICAgICAgIGxldCBjbGllbnRIZWlnaHQgPSBjYWxjVmlzaWJsZUNsaWV0SGVpZ2h0KGxlYWYsIHRoaXMuYXBwLndvcmtzcGFjZSk7XHJcbiAgICAgICAgICAgIGlmKHNldHRpbmdzLmNvbHVtbkhlaWdodCA9PT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgc2V0dGluZ3MuY29sdW1uSGVpZ2h0ID0gSFRNTFNpemluZy5jcmVhdGUoKS5zZXRXaWR0aChjbGllbnRIZWlnaHQpLnNldFVuaXRzKFwicHhcIik7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBzZXR0aW5ncy5jb2x1bW5IZWlnaHQgPSBzZXR0aW5ncy5jb2x1bW5IZWlnaHQuY29udmVydFRvUFgodGhpcy5hcHAud29ya3NwYWNlLmNvbnRhaW5lckVsKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICByZWdpb25hbENvbnRhaW5lci5zZXRSZWdpb25QYXJzZWRTZXR0aW5ncyhzZXR0aW5ncyk7XHJcblxyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZihyZWdpb25hbENvbnRhaW5lciA9PT0gbnVsbCkge1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBsZXQgZG9jTGluZXMgPSBkb2NTdHJpbmcuc3BsaXQoXCJcXG5cIik7XHJcbiAgICAgICAgbGV0IHJlbGF0aXZlVGV4dHM6IEVsZW1lbnRSZWxhdGl2ZUxvY2F0aW9uRGF0YSA9IGV4dHJhY3RFbGVtZW50UmVsYXRpdmVMb2NhdGlvbkRhdGEoZG9jTGluZXMsIGluZm8pO1xyXG4gICAgICAgIHJlbGF0aXZlVGV4dHMubGluZXNCZWxvd0FycmF5ID0gIG11bHRpQ29sdW1uUGFyc2VyLmdldEVuZEJsb2NrQmVsb3cocmVsYXRpdmVUZXh0cy5saW5lc0JlbG93QXJyYXkpO1xyXG5cclxuICAgICAgICBpZihtdWx0aUNvbHVtblBhcnNlci5jb250YWluc1N0YXJ0VGFnKHJlbGF0aXZlVGV4dHMudGV4dE9mRWxlbWVudCkgfHxcclxuICAgICAgICAgICBtdWx0aUNvbHVtblBhcnNlci5jb250YWluc0NvbFNldHRpbmdzVGFnKHJlbGF0aXZlVGV4dHMudGV4dE9mRWxlbWVudCkpIHtcclxuXHJcbiAgICAgICAgICAgIGlmKG11bHRpQ29sdW1uUGFyc2VyLmNvbnRhaW5zU3RhcnRUYWcocmVsYXRpdmVUZXh0cy50ZXh0T2ZFbGVtZW50KSkge1xyXG4gICAgICAgICAgICAgICAgc2V0RWxlbWVudENTU0J5VGFnKERPTU9iamVjdFRhZy5zdGFydFJlZ2lvbiwgZWwpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGVsc2UgaWYobXVsdGlDb2x1bW5QYXJzZXIuY29udGFpbnNDb2xTZXR0aW5nc1RhZyhyZWxhdGl2ZVRleHRzLnRleHRPZkVsZW1lbnQpKSB7XHJcbiAgICAgICAgICAgICAgICBzZXRFbGVtZW50Q1NTQnlUYWcoRE9NT2JqZWN0VGFnLnJlZ2lvblNldHRpbmdzLCBlbCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgbGV0IHN0YXJ0Qm9ja0Fib3ZlOiBtdWx0aUNvbHVtblBhcnNlci5TdGFydFRhZ0RhdGEgPSB7XHJcbiAgICAgICAgICAgIGxpbmVzQWJvdmVBcnJheTogcmVsYXRpdmVUZXh0cy5saW5lc0Fib3ZlQXJyYXksXHJcbiAgICAgICAgICAgIHN0YXJ0QmxvY2tLZXk6IFwiTXVsdGktQ29sdW1uIFJlZmxvdyBSZWdpb25cIixcclxuICAgICAgICAgICAgc3RhcnRCbG9ja1R5cGU6IFwiT1JJR0lOQUxcIlxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy5hcHBlbmRUb1JlZ2lvbmFsTWFuYWdlcihlbCwgcmVnaW9uYWxDb250YWluZXIsIGN0eCwgcmVsYXRpdmVUZXh0cywgc291cmNlUGF0aCwgc3RhcnRCb2NrQWJvdmUsIChkb21PYmo6IERPTU9iamVjdCkgPT4ge1xyXG4gICAgICAgICAgICBvblVubG9hZEVsZW1lbnQoZG9tT2JqLCByZWdpb25hbENvbnRhaW5lcik7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8jcmVnaW9uIFBERiBFeHBvcnRpbmcuXHJcbiAgICBwcml2YXRlIGlzU3RhcnRDb2RlYmxvY2tJbkV4cG9ydChub2RlOiBIVE1MRWxlbWVudCk6IGJvb2xlYW4ge1xyXG5cclxuICAgICAgICBmb3IobGV0IGkgPSAwOyBpIDwgQ09ERUJMT0NLX1NUQVJUX1NUUlMubGVuZ3RoOyBpKyspIHtcclxuXHJcbiAgICAgICAgICAgIGlmKG5vZGUuaGFzQ2xhc3MoYGJsb2NrLWxhbmd1YWdlLSR7Q09ERUJMT0NLX1NUQVJUX1NUUlNbaV19YCkpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIGFzeW5jIGV4cG9ydERvY3VtZW50VG9QREYoZWw6IEhUTUxFbGVtZW50LCBmaWxlRE9NTWFuYWdlcjogRmlsZURPTU1hbmFnZXIsIHNvdXJjZVBhdGg6IHN0cmluZykge1xyXG5cclxuICAgICAgICAvLyBBIHRydWUgZXhwb3J0IHdpbGwgYmUgcGFzc2VkIGFuIGVsZW1lbnQgd2l0aCBhbGwgb3RoZXIgaXRlbXMgaW4gdGhlIGRvYyBhcyBjaGlsZHJlbi4gXHJcbiAgICAgICAgLy8gU28gaWYgdGhlcmUgYXJlIG5vIGNoaWxkcmVuIHdlIGNhbiBqdXN0IHJldHVyblxyXG4gICAgICAgIGxldCBkb2NDaGlsZHJlbiA9IEFycmF5LmZyb20oZWwuY2hpbGROb2Rlcyk7XHJcbiAgICAgICAgaWYoZG9jQ2hpbGRyZW4ubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGxldCBjaGlsZHJlblRvUmVtb3ZlID0gW107XHJcbiAgICAgICAgXHJcbiAgICAgICAgLy8gVG8gZXhwb3J0IGNvZGVibG9ja3Mgd2UgbmVlZCB0byBnZXQgdGhlIElEcyBzbyB3ZSBjYW4gZ2V0IHRoZSBkYXRhIGZyb20gb3VyIG1hbmFnZXJzLlxyXG4gICAgICAgIC8vIGhvd2V2ZXIgc2luY2UgdGhlIElEIGlzbnQgYmVpbmcgc3RvcmVkIGluIHRoZSBlbGVtZW50IHlldCB0aGlzIG1lYW5zIHdlIG5lZWQgdG8gcmVhZFxyXG4gICAgICAgIC8vIGFsbCBvZiB0aGUgSURzIG91dCBvZiB0aGUgZnVsbCBkb2N1bWVudC5cclxuICAgICAgICBsZXQgY29kZWJsb2NrU3RhcnRCbG9ja3MgPSBbXVxyXG4gICAgICAgIGxldCBhRmlsZSA9IHRoaXMuYXBwLnZhdWx0LmdldEFic3RyYWN0RmlsZUJ5UGF0aChzb3VyY2VQYXRoKTtcclxuICAgICAgICBpZihhRmlsZSBpbnN0YW5jZW9mIFRGaWxlKSB7XHJcblxyXG4gICAgICAgICAgICBsZXQgZmlsZSA9IGFGaWxlIGFzIFRGaWxlXHJcbiAgICAgICAgICAgIGxldCBmaWxlVGV4dCA9IGF3YWl0IHRoaXMuYXBwLnZhdWx0LmNhY2hlZFJlYWQoZmlsZSkgLy8gSXMgY2FjaGVkIHJlYWQgT2sgaGVyZT8gSXQgc2hvdWxkIGJlLlxyXG5cclxuICAgICAgICAgICAgLy8gT25jZSB3ZSBoYXZlIG91ciBkYXRhIHdlIHNlYXJjaCB0aGUgdGV4dCBmb3IgYWxsIGNvZGVibG9jayBzdGFydCB2YWx1ZXMuXHJcbiAgICAgICAgICAgIC8vIHN0b3JpbmcgdGhlbSBpbnRvIG91ciBxdWV1ZS5cclxuICAgICAgICAgICAgbGV0IGNvZGVCbG9ja0RhdGEgPSBtdWx0aUNvbHVtblBhcnNlci5maW5kU3RhcnRDb2RlYmxvY2soZmlsZVRleHQpO1xyXG4gICAgICAgICAgICB3aGlsZShjb2RlQmxvY2tEYXRhLmZvdW5kID09PSB0cnVlKSB7XHJcblxyXG4gICAgICAgICAgICAgICAgbGV0IGNvZGVibG9ja1RleHQgPSBmaWxlVGV4dC5zbGljZShjb2RlQmxvY2tEYXRhLnN0YXJ0UG9zaXRpb24sIGNvZGVCbG9ja0RhdGEuZW5kUG9zaXRpb24pO1xyXG4gICAgICAgICAgICAgICAgZmlsZVRleHQgPSBmaWxlVGV4dC5zbGljZShjb2RlQmxvY2tEYXRhLmVuZFBvc2l0aW9uKTtcclxuICAgICAgICAgICAgICAgIGNvZGVibG9ja1N0YXJ0QmxvY2tzLnB1c2goY29kZWJsb2NrVGV4dCk7XHJcblxyXG4gICAgICAgICAgICAgICAgY29kZUJsb2NrRGF0YSA9IG11bHRpQ29sdW1uUGFyc2VyLmZpbmRTdGFydENvZGVibG9jayhmaWxlVGV4dCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYEVycm9yIGdldHRpbmcgZmlsZSBmcm9tIHNvdXJjZSBwYXRoOiAke3NvdXJjZVBhdGh9YClcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGxldCBpbkJsb2NrID0gZmFsc2U7XHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBkb2NDaGlsZHJlbi5sZW5ndGg7IGkrKykge1xyXG5cclxuICAgICAgICAgICAgbGV0IGNoaWxkID0gZG9jQ2hpbGRyZW5baV07XHJcbiAgICAgICAgICAgIGlmIChjaGlsZCBpbnN0YW5jZW9mIEhUTUxFbGVtZW50KSB7XHJcbiAgICAgICAgICAgICAgICBsZXQgY2hpbGRFbCA9IGNoaWxkIGFzIEhUTUxFbGVtZW50O1xyXG4gICAgICAgICAgICAgICAgaWYgKGluQmxvY2sgPT09IGZhbHNlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgXHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IGZvdW5kQmxvY2tEYXRhID0gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IHJlZ2lvbktleSA9IFwiXCI7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGxldCBibG9ja0RhdGEgPSBtdWx0aUNvbHVtblBhcnNlci5pc1N0YXJ0VGFnV2l0aElEKGNoaWxkLnRleHRDb250ZW50KTtcclxuICAgICAgICAgICAgICAgICAgICBsZXQgcGFuZG9jRGF0YSA9IGNvbnRhaW5zUGFuZG9jLmdldFBhbmRvY1N0YXJ0RGF0YShjaGlsZC50ZXh0Q29udGVudClcclxuICAgICAgICAgICAgICAgICAgICBpZiAoYmxvY2tEYXRhLmlzU3RhcnRUYWcgPT09IHRydWUpIHtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIGFuIG9sZC1zdHlsZSBzdGFydCB0YWcuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvdW5kQmxvY2tEYXRhID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJsb2NrRGF0YS5oYXNLZXkgPT09IHRydWUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBmb3VuZEtleSA9IG11bHRpQ29sdW1uUGFyc2VyLmdldFN0YXJ0VGFnS2V5KGNoaWxkLnRleHRDb250ZW50KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmb3VuZEtleSAhPT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZ2lvbktleSA9IGZvdW5kS2V5O1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYoYmxvY2tEYXRhLmlzU3RhcnRUYWcgPT09IGZhbHNlICYmIHRoaXMuaXNTdGFydENvZGVibG9ja0luRXhwb3J0KGNoaWxkKSkge1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gSWYgdGhlIHN0YXJ0IHRhZyBmcm9tIHRoZSBvbGQgdmVyc2lvbiBpcyBudWxsIHdlIHRoZW4gY2hlY2sgdG8gc2VlIGlmIHRoZSBlbGVtZW50IGlzXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGEgY29kZWJsb2NrIHN0YXJ0LiBJZiBpdCBpcyB3ZSB1c2UgdGhlIG5leHQgYXZhaWxhYmxlIGNvZGVibG9jayBkYXRhIHRvIHJldHJpZXZlIG91ciBJRC5cclxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGNvZGVibG9ja1RleHQgPSBjb2RlYmxvY2tTdGFydEJsb2Nrcy5zaGlmdCgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZihjb2RlYmxvY2tUZXh0ID09PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJGb3VuZCB1bmRlZmluZWQgY29kZWJsb2NrIGRhdGEgd2hlbiBleHBvcnRpbmcuXCIpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBpZCA9IHBhcnNlU3RhcnRSZWdpb25Db2RlQmxvY2tJRChjb2RlYmxvY2tUZXh0KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYoaWQgIT09IFwiXCIpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvdW5kQmxvY2tEYXRhID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZ2lvbktleSA9IGlkO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYocGFuZG9jRGF0YS5mb3VuZCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3VuZEJsb2NrRGF0YSA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlZ2lvbktleSA9IHBhbmRvY0RhdGEudXNlclNldHRpbmdzLmNvbHVtbklEO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgaWYoZm91bmRCbG9ja0RhdGEgPT09IHRydWUgJiYgcmVnaW9uS2V5ICE9PSBcIlwiKSB7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBpbkJsb2NrID0gdHJ1ZTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSBjaGlsZC5jaGlsZHJlbi5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGQuY2hpbGRyZW5baV0uZGV0YWNoKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGQuaW5uZXJUZXh0ID0gXCJcIjtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkLmNsYXNzTGlzdC5hZGQoTXVsdGlDb2x1bW5MYXlvdXRDU1MuUmVnaW9uUm9vdENvbnRhaW5lckRpdik7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgZXJyb3JNYW5hZ2VyID0gbmV3IFJlZ2lvbkVycm9yTWFuYWdlcihlbCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCByZW5kZXJDb2x1bW5SZWdpb24gPSBjaGlsZC5jcmVhdGVEaXYoe1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xzOiBNdWx0aUNvbHVtbkxheW91dENTUy5SZWdpb25Db250ZW50Q29udGFpbmVyRGl2XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xyXG5cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCByZWdpb25hbENvbnRhaW5lcjogUmVnaW9uTWFuYWdlckNvbnRhaW5lciA9IGZpbGVET01NYW5hZ2VyLmdldFJlZ2lvbmFsQ29udGFpbmVyKHJlZ2lvbktleSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZWdpb25hbENvbnRhaW5lciA9PT0gbnVsbCB8fCByZWdpb25hbENvbnRhaW5lci5nZXRSZWdpb24oKS5udW1iZXJPZkNoaWxkcmVuID09PSAwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGUgbnVtYmVyIG9mIGNoaWxkcmVuIGlzIDAsIHdlIGFyZSBwcm9iYWJseSBpbiBMaXZlUHJldmlldywgd2hlcmUgdGhlIGNvZGVibG9jayBzdGFydCByZWdpb25zIGhhdmUgYmVlbiBwcm9jZXNzZWQgYnkgbmF0aXZlIG9ic2lkaWFuIGxpdmUgcHJldmlldyBidXQgZG8gbm90IGhhdmUgYW55IGNoaWxkcmVuIGxpbmtlZCB0byB0aGVtLlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JNYW5hZ2VyLmFkZEVycm9yTWVzc2FnZShcIkVycm9yIHJlbmRlcmluZyBtdWx0aS1jb2x1bW4gcmVnaW9uLlxcblBsZWFzZSBjbG9zZSBhbmQgcmVvcGVuIHRoZSBmaWxlLCB0aGVuIG1ha2Ugc3VyZSB5b3UgYXJlIGluIHJlYWRpbmcgbW9kZSBiZWZvcmUgZXhwb3J0aW5nLlwiKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCByZWdpb25hbE1hbmFnZXI6IFJlZ2lvbk1hbmFnZXIgPSByZWdpb25hbENvbnRhaW5lci5nZXRSZWdpb24oKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZ2lvbmFsTWFuYWdlci5leHBvcnRSZWdpb25FbGVtZW50c1RvUERGKHJlbmRlckNvbHVtblJlZ2lvbik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBlbHNlIHtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKG11bHRpQ29sdW1uUGFyc2VyLmNvbnRhaW5zRW5kVGFnKGNoaWxkLnRleHRDb250ZW50KSA9PT0gdHJ1ZSB8fFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb250YWluc1BhbmRvYy5jb250YWluc1BhbmRvY0VuZFRhZyhjaGlsZC50ZXh0Q29udGVudCkgPT09IHRydWUpIHtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGluQmxvY2sgPSBmYWxzZTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuVG9SZW1vdmUucHVzaChjaGlsZCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNoaWxkcmVuVG9SZW1vdmUuZm9yRWFjaChjaGlsZCA9PiB7XHJcbiAgICAgICAgICAgIGlmKGNoaWxkLnBhcmVudEVsZW1lbnQgPT09IGVsKSB7XHJcbiAgICAgICAgICAgICAgICBlbC5yZW1vdmVDaGlsZChjaGlsZCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBjaGVja0V4cG9ydGluZyhlbGVtZW50OiBIVE1MRWxlbWVudCk6IGJvb2xlYW4ge1xyXG5cclxuICAgICAgICBpZihlbGVtZW50ID09PSBudWxsKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmKGVsZW1lbnQuY2xhc3NMaXN0LmNvbnRhaW5zKFwicHJpbnRcIikpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZihlbGVtZW50LnBhcmVudE5vZGUgIT09IG51bGwpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY2hlY2tFeHBvcnRpbmcoZWxlbWVudC5wYXJlbnRFbGVtZW50KTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuICAgIC8vI2VuZHJlZ2lvbiBQREYgRXhwb3J0aW5nLlxyXG59XHJcblxyXG5mdW5jdGlvbiBzZXRFbGVtZW50Q1NTKGN1cnJlbnRPYmplY3Q6IERPTU9iamVjdCwgZWw6IEhUTUxFbGVtZW50KSB7XHJcbiAgICBzZXRFbGVtZW50Q1NTQnlUYWcoY3VycmVudE9iamVjdC50YWcsIGVsKTtcclxufVxyXG5mdW5jdGlvbiBzZXRFbGVtZW50Q1NTQnlUYWcodGFnOiBET01PYmplY3RUYWcsIGVsOiBIVE1MRWxlbWVudCkge1xyXG4gICAgaWYgKHRhZyA9PT0gRE9NT2JqZWN0VGFnLmVuZFJlZ2lvbikge1xyXG4gICAgICAgIGVsLmFkZENsYXNzKE11bHRpQ29sdW1uU3R5bGVDU1MuUmVnaW9uRW5kVGFnKTtcclxuICAgIH1cclxuICAgIGVsc2UgaWYgKHRhZyA9PT0gRE9NT2JqZWN0VGFnLmNvbHVtbkJyZWFrKSB7XHJcbiAgICAgICAgZWwuYWRkQ2xhc3MoTXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5FbmRUYWcpO1xyXG4gICAgfVxyXG4gICAgZWxzZSBpZiAodGFnID09PSBET01PYmplY3RUYWcucmVnaW9uU2V0dGluZ3MpIHtcclxuICAgICAgICBlbC5hZGRDbGFzcyhNdWx0aUNvbHVtblN0eWxlQ1NTLlJlZ2lvblNldHRpbmdzKTtcclxuICAgIH1cclxuICAgIGVsc2Uge1xyXG4gICAgICAgIGVsLmFkZENsYXNzKE11bHRpQ29sdW1uU3R5bGVDU1MuUmVnaW9uQ29udGVudCk7XHJcbiAgICB9XHJcbn1cclxuXHJcbmZ1bmN0aW9uIG9uVW5sb2FkRWxlbWVudChjdXJyZW50T2JqZWN0OiBET01PYmplY3QsIHJlZ2lvbmFsQ29udGFpbmVyOiBSZWdpb25NYW5hZ2VyQ29udGFpbmVyKTogdm9pZCB7XHJcblxyXG4gICAgaWYgKHJlZ2lvbmFsQ29udGFpbmVyID09PSBudWxsKSB7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIGxldCByZWdpb25hbE1hbmFnZXI6IFJlZ2lvbk1hbmFnZXIgPSByZWdpb25hbENvbnRhaW5lci5nZXRSZWdpb24oKTtcclxuICAgIGlmIChyZWdpb25hbE1hbmFnZXIpIHtcclxuXHJcbiAgICAgICAgLy8gV2UgY2FuIGF0dGVtcHQgdG8gdXBkYXRlIHRoZSB2aWV3IGhlcmUgYWZ0ZXIgdGhlIGl0ZW0gaXMgcmVtb3ZlZFxyXG4gICAgICAgIC8vIGJ1dCBuZWVkIHRvIGdldCB0aGUgaXRlbSdzIHBhcmVudCBlbGVtZW50IGJlZm9yZSByZW1vdmluZyBvYmplY3QgZnJvbSBtYW5hZ2VyLlxyXG4gICAgICAgIGxldCByZWdpb25SZW5kZXJEYXRhOiBNdWx0aUNvbHVtblJlbmRlckRhdGEgPSByZWdpb25hbE1hbmFnZXIuZ2V0UmVnaW9uUmVuZGVyRGF0YSgpO1xyXG5cclxuICAgICAgICByZWdpb25hbE1hbmFnZXIucmVtb3ZlT2JqZWN0KGN1cnJlbnRPYmplY3QuVUlEKTtcclxuXHJcbiAgICAgICAgLyoqXHJcbiAgICAgICAgICogTmVlZCB0byBjaGVjayBoZXJlIGlmIGVsZW1lbnQgaXMgbnVsbCBhcyB0aGlzIGNsb3N1cmUgd2lsbCBiZSBjYWxsZWRcclxuICAgICAgICAgKiByZXBlYXRlZGx5IG9uIGZpbGUgY2hhbmdlLlxyXG4gICAgICAgICAqL1xyXG4gICAgICAgIGlmIChyZWdpb25SZW5kZXJEYXRhLnBhcmVudFJlbmRlckVsZW1lbnQgPT09IG51bGwpIHtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZWdpb25hbE1hbmFnZXIucmVuZGVyUmVnaW9uRWxlbWVudHNUb1NjcmVlbigpO1xyXG4gICAgfVxyXG59O1xyXG5cclxuaW50ZXJmYWNlIEVsZW1lbnRSZWxhdGl2ZUxvY2F0aW9uRGF0YSB7XHJcbiAgICBsaW5lc0Fib3ZlQXJyYXk6IHN0cmluZ1tdO1xyXG4gICAgbGluZXNPZkVsZW1lbnQ6IHN0cmluZ1tdO1xyXG4gICAgbGluZXNCZWxvd0FycmF5OiBzdHJpbmdbXTtcclxuICAgIHRleHRPZkVsZW1lbnQ6IHN0cmluZztcclxufVxyXG5cclxuZXhwb3J0IHR5cGUgbmVhcmJ5U2libGluZ3MgPSB7IFxyXG4gICAgc2libGluZ3NBYm92ZTogSFRNTERpdkVsZW1lbnQsXHJcbiAgICBjdXJyZW50T2JqZWN0OiBET01PYmplY3QsIFxyXG59XHJcblxyXG5mdW5jdGlvbiBleHRyYWN0RWxlbWVudFJlbGF0aXZlTG9jYXRpb25EYXRhKGRvY0xpbmVzOiBzdHJpbmdbXSwgaW5mbzogTWFya2Rvd25TZWN0aW9uSW5mb3JtYXRpb24pOiBFbGVtZW50UmVsYXRpdmVMb2NhdGlvbkRhdGEge1xyXG5cclxuICAgIGxldCBsaW5lc0Fib3ZlQXJyYXkgPSBkb2NMaW5lcy5zbGljZSgwLCBpbmZvLmxpbmVTdGFydCk7XHJcbiAgICBsZXQgbGluZXNPZkVsZW1lbnQgPSBkb2NMaW5lcy5zbGljZShpbmZvLmxpbmVTdGFydCwgaW5mby5saW5lRW5kICsgMSk7XHJcbiAgICBsZXQgdGV4dE9mRWxlbWVudCA9IGxpbmVzT2ZFbGVtZW50LmpvaW4oXCJcXG5cIik7XHJcbiAgICBsZXQgbGluZXNCZWxvd0FycmF5ID0gZG9jTGluZXMuc2xpY2UoaW5mby5saW5lRW5kICsgMSk7XHJcblxyXG4gICAgcmV0dXJuIHtcclxuICAgICAgICBsaW5lc0Fib3ZlQXJyYXksXHJcbiAgICAgICAgbGluZXNPZkVsZW1lbnQsXHJcbiAgICAgICAgbGluZXNCZWxvd0FycmF5LFxyXG4gICAgICAgIHRleHRPZkVsZW1lbnRcclxuICAgIH07XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGNyZWF0ZVN0YXJ0RWxlbWVudChlbDogSFRNTEVsZW1lbnQsIGxpbmVzT2ZFbGVtZW50OiBzdHJpbmdbXSwgY3R4OiBNYXJrZG93blBvc3RQcm9jZXNzb3JDb250ZXh0LCBmaWxlRE9NTWFuYWdlcjogRmlsZURPTU1hbmFnZXIsIGRvY1N0cmluZzogc3RyaW5nKSB7XHJcblxyXG4gICAgZWwuY2hpbGRyZW5bMF0uZGV0YWNoKCk7XHJcblxyXG4gICAgbGV0IHN0YXJ0QmxvY2tEYXRhID0gbXVsdGlDb2x1bW5QYXJzZXIuZ2V0U3RhcnRCbG9ja0Fib3ZlTGluZShsaW5lc09mRWxlbWVudClcclxuICAgIGlmKHN0YXJ0QmxvY2tEYXRhID09PSBudWxsKSB7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIGxldCByZWdpb25JRCA9IHN0YXJ0QmxvY2tEYXRhLnN0YXJ0QmxvY2tLZXk7XHJcblxyXG4gICAgc2V0dXBTdGFydFRhZyhlbCwgY3R4LCBmaWxlRE9NTWFuYWdlciwgZG9jU3RyaW5nLCByZWdpb25JRCk7XHJcbiAgICByZXR1cm47XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGNyZWF0ZVBhbmRvY1N0YXJ0RWxlbWVudChlbDogSFRNTEVsZW1lbnQsIHRleHRPZkVsZW1lbnQ6IHN0cmluZywgY3R4OiBNYXJrZG93blBvc3RQcm9jZXNzb3JDb250ZXh0LCBmaWxlRE9NTWFuYWdlcjogRmlsZURPTU1hbmFnZXIsIGRvY1N0cmluZzogc3RyaW5nKSB7XHJcbiAgICBlbC5jaGlsZHJlblswXS5kZXRhY2goKTtcclxuXHJcbiAgICBsZXQgcGFuZG9jRGF0YSA9IGNvbnRhaW5zUGFuZG9jLmdldFBhbmRvY1N0YXJ0RGF0YSh0ZXh0T2ZFbGVtZW50KTtcclxuICAgIGxldCBzZXR0aW5ncyA9IHBhbmRvY0RhdGEudXNlclNldHRpbmdzO1xyXG5cclxuICAgIGxldCByZWdpb25NYW5hZ2VyID0gc2V0dXBTdGFydFRhZyhlbCwgY3R4LCBmaWxlRE9NTWFuYWdlciwgZG9jU3RyaW5nLCBzZXR0aW5ncy5jb2x1bW5JRCk7XHJcbiAgICByZWdpb25NYW5hZ2VyLnNldFJlZ2lvbmFsU2V0dGluZ3Moc2V0dGluZ3MpO1xyXG4gICAgcmV0dXJuO1xyXG59XHJcblxyXG5mdW5jdGlvbiByZW5kZXJNYXJrZG93bkZyb21MaW5lcyhtZExpbmVzOiBzdHJpbmdbXSwgc291cmNlUGF0aDogc3RyaW5nKTogSFRNTERpdkVsZW1lbnQge1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogV2UgcmUtcmVuZGVyIGFsbCBvZiB0aGUgaXRlbXMgYWJvdmUgb3VyIGVsZW1lbnQsIHVudGlsIHRoZSBzdGFydCB0YWcsIFxyXG4gICAgICogc28gd2UgY2FuIGRldGVybWluZSB3aGVyZSB0byBwbGFjZSB0aGUgbmV3IGl0ZW0gaW4gdGhlIG1hbmFnZXIuXHJcbiAgICAgKiBcclxuICAgICAqIFRPRE86IENhbiByZWR1Y2UgdGhlIGFtb3VudCBuZWVkaW5nIHRvIGJlIHJlbmRlcmVkIGJ5IG9ubHkgcmVuZGVyaW5nIHRvXHJcbiAgICAgKiB0aGUgc3RhcnQgdGFnIG9yIGEgY29sdW1uLWJyZWFrIHdoaWNoZXZlciBpcyBjbG9zZXIuXHJcbiAgICAgKi9cclxuICAgIGxldCBzaWJsaW5ncyA9IGNyZWF0ZURpdigpO1xyXG4gICAgbGV0IG1hcmtkb3duUmVuZGVyQ2hpbGQgPSBuZXcgTWFya2Rvd25SZW5kZXJDaGlsZChcclxuICAgICAgICBzaWJsaW5nc1xyXG4gICAgKTtcclxuICAgIE1hcmtkb3duUmVuZGVyZXIucmVuZGVyTWFya2Rvd24oXHJcbiAgICAgICAgbWRMaW5lcy5yZWR1Y2UoKHByZXYsIGN1cnJlbnQpID0+IHtcclxuICAgICAgICAgICAgcmV0dXJuIHByZXYgKyBcIlxcblwiICArIGN1cnJlbnQ7XHJcbiAgICAgICAgfSwgXCJcIiksXHJcbiAgICAgICAgc2libGluZ3MsXHJcbiAgICAgICAgc291cmNlUGF0aCxcclxuICAgICAgICBtYXJrZG93blJlbmRlckNoaWxkXHJcbiAgICApO1xyXG5cclxuICAgIHJldHVybiBzaWJsaW5ncztcclxufVxyXG5cclxuZnVuY3Rpb24gc2V0dXBTdGFydFRhZyhlbDogSFRNTEVsZW1lbnQsIGN0eDogTWFya2Rvd25Qb3N0UHJvY2Vzc29yQ29udGV4dCwgZmlsZURPTU1hbmFnZXI6IEZpbGVET01NYW5hZ2VyLCBkb2NTdHJpbmc6IHN0cmluZywgcmVnaW9uSUQ6IHN0cmluZykge1xyXG4gICAgLyoqIFxyXG4gICAgICogU2V0IHVwIHRoZSBjdXJyZW50IGVsZW1lbnQgdG8gYWN0IGFzIHRoZSBwYXJlbnQgZm9yIHRoZSBcclxuICAgICAqIG11bHRpLWNvbHVtbiByZWdpb24uXHJcbiAgICAgKi9cclxuICAgIGVsLmNsYXNzTGlzdC5hZGQoTXVsdGlDb2x1bW5MYXlvdXRDU1MuUmVnaW9uUm9vdENvbnRhaW5lckRpdilcclxuXHJcbiAgICBsZXQgZXJyb3JNYW5hZ2VyID0gbmV3IFJlZ2lvbkVycm9yTWFuYWdlcihlbCk7XHJcbiAgICBsZXQgcmVuZGVyQ29sdW1uUmVnaW9uID0gZWwuY3JlYXRlRGl2KHtcclxuICAgICAgICBjbHM6IE11bHRpQ29sdW1uTGF5b3V0Q1NTLlJlZ2lvbkNvbnRlbnRDb250YWluZXJEaXZcclxuICAgIH0pXHJcblxyXG4gICAgaWYoZmlsZURPTU1hbmFnZXIuY2hlY2tLZXlFeGlzdHMocmVnaW9uSUQpID09PSB0cnVlKSB7XHJcblxyXG4gICAgICAgIGxldCB7IG51bWJlck9mVGFncywga2V5cyB9ID0gbXVsdGlDb2x1bW5QYXJzZXIuY291bnRTdGFydFRhZ3MoZG9jU3RyaW5nKTtcclxuXHJcbiAgICAgICAgbGV0IG51bU1hdGNoZXMgPSAwO1xyXG4gICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCBudW1iZXJPZlRhZ3M7IGkrKykge1xyXG5cclxuICAgICAgICAgICAgLy8gQmVjYXVzZSB3ZSBjaGVja2VkIGlmIGtleSBleGlzdHMgb25lIG9mIHRoZXNlIGhhcyB0byBtYXRjaC5cclxuICAgICAgICAgICAgaWYoa2V5c1tpXSA9PT0gcmVnaW9uSUQpIHtcclxuICAgICAgICAgICAgICAgIG51bU1hdGNoZXMrKztcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gV2Ugb25seSB3YW50IHRvIGRpc3BsYXkgYW4gZXJyb3IgaWYgdGhlcmUgYXJlIG1vcmUgdGhhbiAyIG9mIHRoZSBzYW1lIGlkIGFjcm9zc1xyXG4gICAgICAgIC8vIHRoZSB3aG9sZSBkb2N1bWVudC4gVGhpcyBwcmV2ZW50cyBlcnJvcyB3aGVuIG9ic2lkaWFuIHJlbG9hZHMgdGhlIHdob2xlIGRvY3VtZW50XHJcbiAgICAgICAgLy8gYW5kIHRoZXJlIGFyZSB0d28gb2YgdGhlIHNhbWUga2V5IGluIHRoZSBtYXAuXHJcbiAgICAgICAgaWYobnVtTWF0Y2hlcyA+PSAyKSB7XHJcbiAgICAgICAgICAgIGlmKHJlZ2lvbklEID09PSBcIlwiKSB7XHJcbiAgICAgICAgICAgICAgICBlcnJvck1hbmFnZXIuYWRkRXJyb3JNZXNzYWdlKFwiRm91bmQgbXVsdGlwbGUgcmVnaW9ucyB3aXRoIGVtcHR5IElEcy4gUGxlYXNlIHNldCBhIHVuaXF1ZSBJRCBhZnRlciBlYWNoIHN0YXJ0IHRhZy5cXG5FRzogJy0tLSBtdWx0aS1jb2x1bW4tc3RhcnQ6IHJhbmRvbUlEJ1xcbk9yIHVzZSAnRml4IE1pc3NpbmcgSURzJyBpbiB0aGUgY29tbWFuZCBwYWxldHRlIGFuZCByZWxvYWQgdGhlIGRvY3VtZW50LlwiKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGVycm9yTWFuYWdlci5hZGRFcnJvck1lc3NhZ2UoXCJSZWdpb24gSUQgYWxyZWFkeSBleGlzdHMgaW4gZG9jdW1lbnQsIHBsZWFzZSBzZXQgYSB1bmlxdWUgSUQuXFxuRUc6ICctLS0gbXVsdGktY29sdW1uLXN0YXJ0OiByYW5kb21JRCdcIik7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuICAgIGVsLmlkID0gYE11bHRpQ29sdW1uSUQ6JHtyZWdpb25JRH1gXHJcblxyXG4gICAgbGV0IGVsZW1lbnRNYXJrZG93blJlbmRlcmVyID0gbmV3IE1hcmtkb3duUmVuZGVyQ2hpbGQoZWwpO1xyXG4gICAgbGV0IHJlZ2lvbk1hbmFnZXIgPSBmaWxlRE9NTWFuYWdlci5jcmVhdGVSZWdpb25hbE1hbmFnZXIocmVnaW9uSUQsIGVsLCBlcnJvck1hbmFnZXIsIHJlbmRlckNvbHVtblJlZ2lvbik7XHJcbiAgICBlbGVtZW50TWFya2Rvd25SZW5kZXJlci5vbnVubG9hZCA9ICgpID0+IHtcclxuICAgICAgICBpZihmaWxlRE9NTWFuYWdlcikge1xyXG5cclxuICAgICAgICAgICAgZmlsZURPTU1hbmFnZXIucmVtb3ZlUmVnaW9uKHJlZ2lvbklEKTtcclxuICAgICAgICB9XHJcbiAgICB9O1xyXG4gICAgY3R4LmFkZENoaWxkKGVsZW1lbnRNYXJrZG93blJlbmRlcmVyKTtcclxuXHJcbiAgICByZXR1cm4gcmVnaW9uTWFuYWdlclxyXG59XHJcblxyXG5jb25zdCBGUk9OVE1BVFRFUl9SRUdFWDogUmVnRXhwW10gPVxyXG5bXHJcbi9NdWx0aVstIF0qQ29sdW1uICpNYXJrZG93bi9pLFxyXG4vTXVsdGlbLSBdKkNvbHVtbiAqUmVmbG93L2lcclxuXVxyXG5mdW5jdGlvbiBpc011bHRpQ29sdW1uUmVmbG93KGZyb250bWF0dGVyOiBhbnkpOiBib29sZWFuIHtcclxuXHJcbiAgICBpZihmcm9udG1hdHRlciA9PT0gbnVsbCB8fFxyXG4gICAgICAgZnJvbnRtYXR0ZXIgPT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuXHJcbiAgICBmb3IobGV0IHJlZ2V4IG9mIEZST05UTUFUVEVSX1JFR0VYKSB7XHJcblxyXG4gICAgICAgIGxldCBmcm9udG1hdHRlclJlZmxvd0RhdGEgPSBwYXJzZUZyb250TWF0dGVyRW50cnkoZnJvbnRtYXR0ZXIsIHJlZ2V4KTtcclxuICAgICAgICBpZihmcm9udG1hdHRlclJlZmxvd0RhdGEgIT09IG51bGwpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGxldCBba2V5cywgdmFsdWVzXSA9IE9iamVjdC5lbnRyaWVzKGZyb250bWF0dGVyKTtcclxuICAgIGlmKGtleXMgPT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuXHJcbiAgICBmb3IobGV0IGtleSBvZiBrZXlzKSB7XHJcblxyXG4gICAgICAgIGlmKHR5cGVvZiBrZXkgIT09IFwic3RyaW5nXCIpIHtcclxuICAgICAgICAgICAgY29udGludWU7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBmb3IobGV0IHJlZ2V4IG9mIEZST05UTUFUVEVSX1JFR0VYKSB7XHJcblxyXG4gICAgICAgICAgICBsZXQgcmVnZXhSZXN1bHQgPSByZWdleC5leGVjKGtleSk7XHJcbiAgICAgICAgICAgIGlmKHJlZ2V4UmVzdWx0ICE9PSBudWxsKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gZmFsc2U7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGdldE11bHRpQ29sdW1uU2V0dGluZ3NGcm9tRnJvbnRtYXR0ZXIoY3R4OiBNYXJrZG93blBvc3RQcm9jZXNzb3JDb250ZXh0KTogTXVsdGlDb2x1bW5TZXR0aW5ncyB7XHJcblxyXG4gICAgbGV0IHNldHRpbmdzID0gZ2V0RGVmYXVsdE11bHRpQ29sdW1uU2V0dGluZ3MoKTtcclxuICAgIHNldHRpbmdzLmZ1bGxEb2NSZWZsb3cgPSB0cnVlO1xyXG4gICAgaWYoY3R4LmZyb250bWF0dGVyID09PSBudWxsIHx8XHJcbiAgICAgICBjdHguZnJvbnRtYXR0ZXIgPT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgIHJldHVybiBzZXR0aW5ncztcclxuICAgIH1cclxuXHJcbiAgICBmb3IobGV0IHJlZ2V4IG9mIEZST05UTUFUVEVSX1JFR0VYKSB7XHJcblxyXG4gICAgICAgIGxldCBmcm9udG1hdHRlclJlZmxvd0RhdGEgPSBwYXJzZUZyb250TWF0dGVyRW50cnkoY3R4LmZyb250bWF0dGVyLCByZWdleCk7XHJcbiAgICAgICAgaWYoZnJvbnRtYXR0ZXJSZWZsb3dEYXRhICE9PSBudWxsICYmXHJcbiAgICAgICAgICAgQXJyYXkuaXNBcnJheShmcm9udG1hdHRlclJlZmxvd0RhdGEpKSB7XHJcbiAgICAgICAgICAgIHNldHRpbmdzID0gcGFyc2VGcm9udG1hdHRlclNldHRpbmdzKGZyb250bWF0dGVyUmVmbG93RGF0YSk7XHJcbiAgICAgICAgICAgIHNldHRpbmdzLmZ1bGxEb2NSZWZsb3cgPSB0cnVlO1xyXG4gICAgICAgICAgICBicmVhaztcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHNldHRpbmdzO1xyXG59XHJcblxyXG5mdW5jdGlvbiBwYXJzZUZyb250bWF0dGVyU2V0dGluZ3MoZnJvbnRtYXR0ZXJSZWZsb3dEYXRhOiBhbnlbXSk6IE11bHRpQ29sdW1uU2V0dGluZ3Mge1xyXG5cclxuICAgIGxldCBzdHIgPSBcIlwiO1xyXG4gICAgZm9yKGxldCBvYmogb2YgZnJvbnRtYXR0ZXJSZWZsb3dEYXRhKSB7XHJcblxyXG4gICAgICAgIGxldCBba2V5LCB2YWx1ZV0gPSBPYmplY3QuZW50cmllcyhvYmopWzBdO1xyXG4gICAgICAgIHN0ciArPSBgJHtrZXl9OiBbJHt2YWx1ZX1dXFxuYDtcclxuICAgIH1cclxuXHJcbiAgICBsZXQgc2V0dGluZ3MgPSBwYXJzZUNvbHVtblNldHRpbmdzKHN0cik7XHJcblxyXG4gICAgcmV0dXJuIHNldHRpbmdzO1xyXG59XHJcblxyXG5mdW5jdGlvbiBnZXRDb250ZW50SGVpZ2h0RnJvbUxlYWYobGVhZjogV29ya3NwYWNlTGVhZik6IG51bWJlciB7XHJcblxyXG4gICAgbGV0IGNvbnRlbnRFbCA9IChsZWFmLnZpZXcgYXMgYW55KVtcImNvbnRlbnRFbFwiXSBhcyBIVE1MRWxlbWVudFxyXG4gICAgaWYoY29udGVudEVsICE9PSB1bmRlZmluZWQgJiZcclxuICAgICAgIGNvbnRlbnRFbC5jbGllbnRIZWlnaHQgPiAwKSB7XHJcbiAgICAgICAgcmV0dXJuIGNvbnRlbnRFbC5jbGllbnRIZWlnaHQ7XHJcbiAgICB9XHJcblxyXG4gICAgbGV0IGNsaWVudEhlaWdodCA9IGxlYWYudmlldy5jb250YWluZXJFbC5jbGllbnRIZWlnaHQ7XHJcbiAgICBsZXQgdGl0bGVDb250YWluZXIgPSAobGVhZi52aWV3IGFzIGFueSlbXCJ0aXRsZUNvbnRhaW5lckVsXCJdIGFzIEhUTUxFbGVtZW50IFxyXG4gICAgaWYodGl0bGVDb250YWluZXIgIT09IHVuZGVmaW5lZCAmJlxyXG4gICAgICAgdGl0bGVDb250YWluZXIuY2xpZW50SGVpZ2h0ID4gMCkge1xyXG4gICAgICAgIHJldHVybiBjbGllbnRIZWlnaHQgLSB0aXRsZUNvbnRhaW5lci5jbGllbnRIZWlnaHQ7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIGNsaWVudEhlaWdodCAtIDUwO1xyXG59XHJcblxyXG5mdW5jdGlvbiBjYWxjVmlzaWJsZUNsaWV0SGVpZ2h0KGxlYWY6IFdvcmtzcGFjZUxlYWYsIHdvcmtzcGFjZTogV29ya3NwYWNlKTogbnVtYmVyIHtcclxuXHJcbiAgICBsZXQgY2xpZW50SGVpZ2h0ID0gMDtcclxuICAgIGlmIChsZWFmKSB7XHJcbiAgICAgICAgY2xpZW50SGVpZ2h0ID0gZ2V0Q29udGVudEhlaWdodEZyb21MZWFmKGxlYWYpO1xyXG4gICAgfVxyXG4gICAgZWxzZSBpZiAoKHdvcmtzcGFjZSAhPT0gbnVsbCAmJiB3b3Jrc3BhY2UgIT09IHVuZGVmaW5lZCkgJiZcclxuICAgICAgICAgICAgICh3b3Jrc3BhY2UuY29udGFpbmVyRWwgIT09IG51bGwgJiYgd29ya3NwYWNlLmNvbnRhaW5lckVsICE9PSB1bmRlZmluZWQpICYmXHJcbiAgICAgICAgICAgICAgd29ya3NwYWNlLmNvbnRhaW5lckVsLmNsaWVudEhlaWdodCA+IDApIHtcclxuICAgICAgICBjbGllbnRIZWlnaHQgPSB3b3Jrc3BhY2UuY29udGFpbmVyRWwuY2xpZW50SGVpZ2h0IC0gMTAwO1xyXG4gICAgfVxyXG4gICAgZWxzZSB7XHJcbiAgICAgICAgY2xpZW50SGVpZ2h0ID0gMTAwMDtcclxuICAgIH1cclxuICAgIHJldHVybiBjbGllbnRIZWlnaHQ7XHJcbn0iXSwibmFtZXMiOlsiTWFya2Rvd25SZW5kZXJDaGlsZCIsIldpZGdldFR5cGUiLCJNYXJrZG93blJlbmRlcmVyIiwiU3RhdGVGaWVsZCIsIkRlY29yYXRpb24iLCJSYW5nZVNldEJ1aWxkZXIiLCJlZGl0b3JMaXZlUHJldmlld0ZpZWxkIiwic3ludGF4VHJlZSIsInRva2VuQ2xhc3NOb2RlUHJvcCIsImVkaXRvckluZm9GaWVsZCIsIkVkaXRvclZpZXciLCJQbHVnaW5TZXR0aW5nVGFiIiwiU2V0dGluZyIsIlBsYXRmb3JtIiwiTW9kYWwiLCJCdXR0b25Db21wb25lbnQiLCJtdWx0aUNvbHVtblBhcnNlci5pc1N0YXJ0VGFnV2l0aElEIiwiTm90aWNlIiwiUGx1Z2luIiwibXVsdGlDb2x1bW5QYXJzZXIuZmluZFN0YXJ0Q29kZWJsb2NrIiwibXVsdGlDb2x1bW5QYXJzZXIuY29udGFpbnNSZWdpb25TdGFydCIsIm11bHRpQ29sdW1uUGFyc2VyLmNvbnRhaW5zU3RhcnRUYWciLCJjb250YWluc1BhbmRvYy5jb250YWluc1BhbmRvY1N0YXJ0VGFnIiwibXVsdGlDb2x1bW5QYXJzZXIuZ2V0U3RhcnREYXRhQWJvdmVMaW5lIiwibXVsdGlDb2x1bW5QYXJzZXIuZ2V0RW5kQmxvY2tCZWxvdyIsIm11bHRpQ29sdW1uUGFyc2VyLmNvbnRhaW5zRW5kVGFnIiwiY29udGFpbnNQYW5kb2MuaXNWYWxpZFBhbmRvY0VuZFRhZyIsIm11bHRpQ29sdW1uUGFyc2VyLmNvbnRhaW5zQ29sRW5kVGFnIiwibXVsdGlDb2x1bW5QYXJzZXIuY29udGFpbnNDb2xTZXR0aW5nc1RhZyIsIm11bHRpQ29sdW1uUGFyc2VyLmNvdW50U3RhcnRUYWdzIiwiVEZpbGUiLCJjb250YWluc1BhbmRvYy5nZXRQYW5kb2NTdGFydERhdGEiLCJtdWx0aUNvbHVtblBhcnNlci5nZXRTdGFydFRhZ0tleSIsImNvbnRhaW5zUGFuZG9jLmNvbnRhaW5zUGFuZG9jRW5kVGFnIiwibXVsdGlDb2x1bW5QYXJzZXIuZ2V0U3RhcnRCbG9ja0Fib3ZlTGluZSIsInBhcnNlRnJvbnRNYXR0ZXJFbnRyeSJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQW9HQTtBQUNPLFNBQVMsU0FBUyxDQUFDLE9BQU8sRUFBRSxVQUFVLEVBQUUsQ0FBQyxFQUFFLFNBQVMsRUFBRTtBQUM3RCxJQUFJLFNBQVMsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLE9BQU8sS0FBSyxZQUFZLENBQUMsR0FBRyxLQUFLLEdBQUcsSUFBSSxDQUFDLENBQUMsVUFBVSxPQUFPLEVBQUUsRUFBRSxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRTtBQUNoSCxJQUFJLE9BQU8sS0FBSyxDQUFDLEtBQUssQ0FBQyxHQUFHLE9BQU8sQ0FBQyxFQUFFLFVBQVUsT0FBTyxFQUFFLE1BQU0sRUFBRTtBQUMvRCxRQUFRLFNBQVMsU0FBUyxDQUFDLEtBQUssRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsRUFBRSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUU7QUFDbkcsUUFBUSxTQUFTLFFBQVEsQ0FBQyxLQUFLLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsRUFBRSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUU7QUFDdEcsUUFBUSxTQUFTLElBQUksQ0FBQyxNQUFNLEVBQUUsRUFBRSxNQUFNLENBQUMsSUFBSSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLFFBQVEsQ0FBQyxDQUFDLEVBQUU7QUFDdEgsUUFBUSxJQUFJLENBQUMsQ0FBQyxT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VCxTQUFTLENBQUUsVUFBVSxDQUFDLEVBQUU7QUFDaEYsUUFBQSxPQUFPLEtBQUssQ0FBQTtBQUNmLEtBQUE7QUFDRCxJQUFBLElBQUcsQ0FBQSxTQUFTLEtBQUEsSUFBQSxJQUFULFNBQVMsS0FBQSxLQUFBLENBQUEsR0FBQSxLQUFBLENBQUEsR0FBVCxTQUFTLENBQUUsVUFBVSxPQUFLLFNBQVMsYUFBVCxTQUFTLEtBQUEsS0FBQSxDQUFBLEdBQUEsS0FBQSxDQUFBLEdBQVQsU0FBUyxDQUFFLFVBQVUsQ0FBQSxFQUFFO0FBQ2hELFFBQUEsT0FBTyxLQUFLLENBQUE7QUFDZixLQUFBO0FBQ0QsSUFBQSxJQUFHLENBQUEsU0FBUyxLQUFBLElBQUEsSUFBVCxTQUFTLEtBQUEsS0FBQSxDQUFBLEdBQUEsS0FBQSxDQUFBLEdBQVQsU0FBUyxDQUFFLFVBQVUsT0FBSyxTQUFTLGFBQVQsU0FBUyxLQUFBLEtBQUEsQ0FBQSxHQUFBLEtBQUEsQ0FBQSxHQUFULFNBQVMsQ0FBRSxVQUFVLENBQUEsRUFBRTtBQUNoRCxRQUFBLE9BQU8sS0FBSyxDQUFBO0FBQ2YsS0FBQTtJQUNELElBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxTQUFTLGFBQVQsU0FBUyxLQUFBLEtBQUEsQ0FBQSxHQUFBLEtBQUEsQ0FBQSxHQUFULFNBQVMsQ0FBRSxVQUFVLENBQUMsS0FBSyxJQUFJLENBQUMsU0FBUyxDQUFDLFNBQVMsS0FBQSxJQUFBLElBQVQsU0FBUyxLQUFBLEtBQUEsQ0FBQSxHQUFBLEtBQUEsQ0FBQSxHQUFULFNBQVMsQ0FBRSxVQUFVLENBQUMsRUFBRTtBQUNoRixRQUFBLE9BQU8sS0FBSyxDQUFBO0FBQ2YsS0FBQTtBQUNELElBQUEsSUFBRyxDQUFBLFNBQVMsS0FBQSxJQUFBLElBQVQsU0FBUyxLQUFBLEtBQUEsQ0FBQSxHQUFBLEtBQUEsQ0FBQSxHQUFULFNBQVMsQ0FBRSxjQUFjLE9BQUssU0FBUyxhQUFULFNBQVMsS0FBQSxLQUFBLENBQUEsR0FBQSxLQUFBLENBQUEsR0FBVCxTQUFTLENBQUUsY0FBYyxDQUFBLEVBQUU7QUFDeEQsUUFBQSxPQUFPLEtBQUssQ0FBQTtBQUNmLEtBQUE7SUFDRCxJQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsU0FBUyxhQUFULFNBQVMsS0FBQSxLQUFBLENBQUEsR0FBQSxLQUFBLENBQUEsR0FBVCxTQUFTLENBQUUsYUFBYSxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxTQUFTLEtBQUEsSUFBQSxJQUFULFNBQVMsS0FBQSxLQUFBLENBQUEsR0FBQSxLQUFBLENBQUEsR0FBVCxTQUFTLENBQUUsYUFBYSxDQUFDLEVBQUU7QUFDdEYsUUFBQSxPQUFPLEtBQUssQ0FBQTtBQUNmLEtBQUE7SUFDRCxJQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsU0FBUyxhQUFULFNBQVMsS0FBQSxLQUFBLENBQUEsR0FBQSxLQUFBLENBQUEsR0FBVCxTQUFTLENBQUUsZUFBZSxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxTQUFTLEtBQUEsSUFBQSxJQUFULFNBQVMsS0FBQSxLQUFBLENBQUEsR0FBQSxLQUFBLENBQUEsR0FBVCxTQUFTLENBQUUsZUFBZSxDQUFDLEVBQUU7QUFDMUYsUUFBQSxPQUFPLEtBQUssQ0FBQTtBQUNmLEtBQUE7SUFDRCxJQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsU0FBUyxhQUFULFNBQVMsS0FBQSxLQUFBLENBQUEsR0FBQSxLQUFBLENBQUEsR0FBVCxTQUFTLENBQUUsU0FBUyxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxTQUFTLEtBQUEsSUFBQSxJQUFULFNBQVMsS0FBQSxLQUFBLENBQUEsR0FBQSxLQUFBLENBQUEsR0FBVCxTQUFTLENBQUUsU0FBUyxDQUFDLEVBQUU7QUFDOUUsUUFBQSxPQUFPLEtBQUssQ0FBQTtBQUNmLEtBQUE7QUFDRCxJQUFBLElBQUcsQ0FBQSxTQUFTLEtBQUEsSUFBQSxJQUFULFNBQVMsS0FBQSxLQUFBLENBQUEsR0FBQSxLQUFBLENBQUEsR0FBVCxTQUFTLENBQUUsWUFBWSxPQUFLLFNBQVMsYUFBVCxTQUFTLEtBQUEs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 diff --git a/.obsidian/plugins/multi-column-markdown/manifest.json b/.obsidian/plugins/multi-column-markdown/manifest.json deleted file mode 100644 index 218e460..0000000 --- a/.obsidian/plugins/multi-column-markdown/manifest.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "id": "multi-column-markdown", - "name": "Multi-Column Markdown", - "version": "0.9.1", - "minAppVersion": "1.5.3", - "description": "This plugin adds functionality to create markdown documents with multiple columns of content viewable within Obsidian's preview mode", - "author": "Cameron Robinson", - "fundingUrl": "https://www.buymeacoffee.com/ckrobinson", - "authorUrl": "https://portfolio.ckrobinson.net", - "isDesktopOnly": false -} diff --git a/.obsidian/plugins/multi-column-markdown/styles.css b/.obsidian/plugins/multi-column-markdown/styles.css deleted file mode 100644 index 1eaa9aa..0000000 --- a/.obsidian/plugins/multi-column-markdown/styles.css +++ /dev/null @@ -1,249 +0,0 @@ -.mcm-single-column-layout-left { - left: 10px; -} -.mcm-single-column-layout-right { - right: 10px; -} -.mcm-single-column-small { - width: 25%; -} -.mcm-single-column-medium { - width: 50%; -} -.mcm-single-column-large { - width: 75%; -} -.mcm-single-column-full { - width: 100%; -} - -/* ----------------------------------- */ - -.mcm-singlecol-layout-right { - justify-content: right; -} -.mcm-singlecol-layout-left { - justify-content: left; -} -.mcm-singlecol-layout-center { - justify-content: center; -} - -/* ----------------------------------- */ - -.mcm-column-spacer { - margin-inline: 0.25%; -} - -/* ----------------------------------- */ - -.mcm-two-equal-columns { - width: 49.75%; -} - -.mcm-two-column-large { - width: 66.75%; -} - -.mcm-two-column-small { - width: 32.75%; -} - -/* ----------------------------------- */ - -.mcm-three-equal-columns { - width: 32.75%; -} - -/* ----------------------------------- */ - -.mcm-three-column-large { - width: 49.75%; -} -.mcm-three-column-small { - width: 24.5%; -} - -/* ----------------------------------- */ - -.mcm-column-div { - padding-inline: 10px; -} - -.mcm-column-border { - border: grey; - border-style: solid; - border-width: 0.5px; -} - -.mcm-column-shadow { - box-shadow: 0 0.2rem 0.5rem var(--background-modifier-box-shadow); -} - -.mcm-column-root-container { - margin: 1.5625em 0; -} - -.mcm-column-parent-container { - padding: 0; - color: var(--text-normal); - page-break-inside: avoid; - - border-radius: 0.1rem; - - display:flex; - flex-direction:row; -} - -.mcm-doc-reflow-container { - margin-top: 1.5625em; -} - -.mcm-region-shadow { - box-shadow: 0 0.2rem 0.5rem var(--background-modifier-box-shadow); -} - -.mcm-column-end-tag-wrapper, -.mcm-column-break-tag-wrapper, -.mcm-column-settings-wrapper, -.mcm-column-content-wrapper { - opacity: 0; -} - -.mcm-column-div .mcm-column-content-wrapper { - opacity: 100; -} - -.markdown-preview-section > .mcm-column-content-wrapper, - .mcm-column-break-tag-wrapper, - .mcm-column-end-tag-wrapper, - .mcm-column-settings-wrapper { - height: 0px !important; - overflow: hidden; -} - -.mcm-original-column-element + .mcm-cloned-column-element { - display: none; -} - -.mcm-cm-preview { - line-height: var(--lh); - white-space: normal; - word-break: keep-all; - word-wrap: normal; -} - -.mcm-no-flex-shrink { - flex-shrink: 0; -} - -.mcm-col-settings-preview { - color: var(--text-normal); -} - -.cm-preview-code-block.preivew-mcm-start-block { - height: 0pt !important; - padding: 0pt !important; -} - -.mcm-content-overflow-hidden-x { - overflow-x: hidden; -} - -.mcm-content-overflow-auto-scroll-x { - overflow-x: auto; -} - -.mcm-content-overflow-auto-scroll-y { - overflow-x: auto; -} -.mcm-content-overflow-hidden-y { - overflow-y: hidden; -} - -.mcm-content-alignment-left { - text-align: left; -} -.mcm-table-alignment.mcm-content-alignment-left table { - margin-right: auto; - margin-left: 0px; -} - -.mcm-content-alignment-center { - text-align: center; -} -.mcm-table-alignment.mcm-content-alignment-center table { - margin-right: auto; - margin-left: auto; -} - -.mcm-content-alignment-right { - text-align: right; -} -.mcm-table-alignment.mcm-content-alignment-right table { - margin-right: 0px; - margin-left: auto; -} - -.mcm-span-content-alignment-center { - display: block; - text-align: center; -} - -.mcm-small-font-message { - font-size: small -} - -/* ----------------------------------- */ - -.mcm-message-region { - max-height: 0; - overflow: hidden; - font-size: small; - transition: max-height 0.2s ease-out; -} - -.mcm-column-error-message { - color: var(--text-error); -} - -.mcm-column-error-padding { - padding: 0 10px; -} - -.mcm-error-heading { - background-color: var(--background-secondary); - user-select: none; -} - -.mcm-error-heading:after { - content: '\002B'; - color: white; - font-weight: bold; - float: right; - margin-left: 5px; -} - -.mcm-error-heading:hover { - background-color: var(--interactive-hover); -} - -.mcm-error-heading-open:after { - content: "\2212"; -} - -.mcm-error-message-color { - color: var(--text-error); -} - -.mcm-error-icon { - font-size: large; - margin-inline-end: 5px; - color: var(--text-error); -} - -.mcm-warning-icon { - font-size: large; - margin-inline-end: 5px; - color: var(--color-yellow) -} \ No newline at end of file diff --git a/.obsidian/plugins/obsidian-advanced-uri/main.js b/.obsidian/plugins/obsidian-advanced-uri/main.js index 0b48617..52be496 100644 --- a/.obsidian/plugins/obsidian-advanced-uri/main.js +++ b/.obsidian/plugins/obsidian-advanced-uri/main.js @@ -5,7 +5,7 @@ if you want to view the source visit the plugins github repository (https://gith var gt=Object.create;var ae=Object.defineProperty;var mt=Object.getOwnPropertyDescriptor;var xt=Object.getOwnPropertyNames;var vt=Object.getPrototypeOf,wt=Object.prototype.hasOwnProperty;var De=(o,n)=>()=>(n||o((n={exports:{}}).exports,n),n.exports),jt=(o,n)=>{for(var e in n)ae(o,e,{get:n[e],enumerable:!0})},Ve=(o,n,e,t)=>{if(n&&typeof n=="object"||typeof n=="function")for(let i of xt(n))!wt.call(o,i)&&i!==e&&ae(o,i,{get:()=>n[i],enumerable:!(t=mt(n,i))||t.enumerable});return o};var xe=(o,n,e)=>(e=o!=null?gt(vt(o)):{},Ve(n||!o||!o.__esModule?ae(e,"default",{value:o,enumerable:!0}):e,o)),bt=o=>Ve(ae({},"__esModule",{value:!0}),o);var Le=De((Y,ve)=>{(function(n,e){typeof Y=="object"&&typeof ve=="object"?ve.exports=e():typeof define=="function"&&define.amd?define([],e):typeof Y=="object"?Y.feather=e():n.feather=e()})(typeof self!="undefined"?self:Y,function(){return function(o){var n={};function e(t){if(n[t])return n[t].exports;var i=n[t]={i:t,l:!1,exports:{}};return o[t].call(i.exports,i,i.exports,e),i.l=!0,i.exports}return e.m=o,e.c=n,e.d=function(t,i,a){e.o(t,i)||Object.defineProperty(t,i,{configurable:!1,enumerable:!0,get:a})},e.r=function(t){Object.defineProperty(t,"__esModule",{value:!0})},e.n=function(t){var i=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(i,"a",i),i},e.o=function(t,i){return Object.prototype.hasOwnProperty.call(t,i)},e.p="",e(e.s=0)}({"./dist/icons.json":function(o){o.exports={activity:'',airplay:'',"alert-circle":'',"alert-octagon":'',"alert-triangle":'',"align-center":'',"align-justify":'',"align-left":'',"align-right":'',anchor:'',aperture:'',archive:'',"arrow-down-circle":'',"arrow-down-left":'',"arrow-down-right":'',"arrow-down":'',"arrow-left-circle":'',"arrow-left":'',"arrow-right-circle":'',"arrow-right":'',"arrow-up-circle":'',"arrow-up-left":'',"arrow-up-right":'',"arrow-up":'',"at-sign":'',award:'',"bar-chart-2":'',"bar-chart":'',"battery-charging":'',battery:'',"bell-off":'',bell:'',bluetooth:'',bold:'',"book-open":'',book:'',bookmark:'',box:'',briefcase:'',calendar:'',"camera-off":'',camera:'',cast:'',"check-circle":'',"check-square":'',check:'',"chevron-down":'',"chevron-left":'',"chevron-right":'',"chevron-up":'',"chevrons-down":'',"chevrons-left":'',"chevrons-right":'',"chevrons-up":'',chrome:'',circle:'',clipboard:'',clock:'',"cloud-drizzle":'',"cloud-lightning":'',"cloud-off":'',"cloud-rain":'',"cloud-snow":'',cloud:'',code:'',codepen:'',codesandbox:'',coffee:'',columns:'',command:'',compass:'',copy:'',"corner-down-left":'',"corner-down-right":'',"corner-left-down":'',"corner-left-up":'',"corner-right-down":'',"corner-right-up":'',"corner-up-left":'',"corner-up-right":'',cpu:'',"credit-card":'',crop:'',crosshair:'',database:'',delete:'',disc:'',"divide-circle":'',"divide-square":'',divide:'',"dollar-sign":'',"download-cloud":'',download:'',dribbble:'',droplet:'',"edit-2":'',"edit-3":'',edit:'',"external-link":'',"eye-off":'',eye:'',facebook:'',"fast-forward":'',feather:'',figma:'',"file-minus":'',"file-plus":'',"file-text":'',file:'',film:'',filter:'',flag:'',"folder-minus":'',"folder-plus":'',folder:'',framer:'',frown:'',gift:'',"git-branch":'',"git-commit":'',"git-merge":'',"git-pull-request":'',github:'',gitlab:'',globe:'',grid:'',"hard-drive":'',hash:'',headphones:'',heart:'',"help-circle":'',hexagon:'',home:'',image:'',inbox:'',info:'',instagram:'',italic:'',key:'',layers:'',layout:'',"life-buoy":'',"link-2":'',link:'',linkedin:'',list:'',loader:'',lock:'',"log-in":'',"log-out":'',mail:'',"map-pin":'',map:'',"maximize-2":'',maximize:'',meh:'',menu:'',"message-circle":'',"message-square":'',"mic-off":'',mic:'',"minimize-2":'',minimize:'',"minus-circle":'',"minus-square":'',minus:'',monitor:'',moon:'',"more-horizontal":'',"more-vertical":'',"mouse-pointer":'',move:'',music:'',"navigation-2":'',navigation:'',octagon:'',package:'',paperclip:'',"pause-circle":'',pause:'',"pen-tool":'',percent:'',"phone-call":'',"phone-forwarded":'',"phone-incoming":'',"phone-missed":'',"phone-off":'',"phone-outgoing":'',phone:'',"pie-chart":'',"play-circle":'',play:'',"plus-circle":'',"plus-square":'',plus:'',pocket:'',power:'',printer:'',radio:'',"refresh-ccw":'',"refresh-cw":'',repeat:'',rewind:'',"rotate-ccw":'',"rotate-cw":'',rss:'',save:'',scissors:'',search:'',send:'',server:'',settings:'',"share-2":'',share:'',"shield-off":'',shield:'',"shopping-bag":'',"shopping-cart":'',shuffle:'',sidebar:'',"skip-back":'',"skip-forward":'',slack:'',slash:'',sliders:'',smartphone:'',smile:'',speaker:'',square:'',star:'',"stop-circle":'',sun:'',sunrise:'',sunset:'',table:'',tablet:'',tag:'',target:'',terminal:'',thermometer:'',"thumbs-down":'',"thumbs-up":'',"toggle-left":'',"toggle-right":'',tool:'',"trash-2":'',trash:'',trello:'',"trending-down":'',"trending-up":'',triangle:'',truck:'',tv:'',twitch:'',twitter:'',type:'',umbrella:'',underline:'',unlock:'',"upload-cloud":'',upload:'',"user-check":'',"user-minus":'',"user-plus":'',"user-x":'',user:'',users:'',"video-off":'',video:'',voicemail:'',"volume-1":'',"volume-2":'',"volume-x":'',volume:'',watch:'',"wifi-off":'',wifi:'',wind:'',"x-circle":'',"x-octagon":'',"x-square":'',x:'',youtube:'',"zap-off":'',zap:'',"zoom-in":'',"zoom-out":''}},"./node_modules/classnames/dedupe.js":function(o,n,e){var t,i;(function(){"use strict";var a=function(){function l(){}l.prototype=Object.create(null);function r(f,y){for(var g=y.length,x=0;x1?arguments[1]:void 0,y=f!==void 0,g=0,x=s(h),b,M,A,P;if(y&&(f=t(f,m>2?arguments[2]:void 0,2)),x!=null&&!(u==Array&&l(x)))for(P=x.call(h),M=new u;!(A=P.next()).done;g++)c(M,g,y?a(P,f,[A.value,g],!0):A.value);else for(b=r(h.length),M=new u(b);b>g;g++)c(M,g,y?f(h[g],g):h[g]);return M.length=g,M}},"./node_modules/core-js/internals/array-includes.js":function(o,n,e){var t=e("./node_modules/core-js/internals/to-indexed-object.js"),i=e("./node_modules/core-js/internals/to-length.js"),a=e("./node_modules/core-js/internals/to-absolute-index.js");o.exports=function(l){return function(r,c,s){var d=t(r),p=i(d.length),h=a(s,p),u;if(l&&c!=c){for(;p>h;)if(u=d[h++],u!=u)return!0}else for(;p>h;h++)if((l||h in d)&&d[h]===c)return l||h||0;return!l&&-1}}},"./node_modules/core-js/internals/bind-context.js":function(o,n,e){var t=e("./node_modules/core-js/internals/a-function.js");o.exports=function(i,a,l){if(t(i),a===void 0)return i;switch(l){case 0:return function(){return i.call(a)};case 1:return function(r){return i.call(a,r)};case 2:return function(r,c){return i.call(a,r,c)};case 3:return function(r,c,s){return i.call(a,r,c,s)}}return function(){return i.apply(a,arguments)}}},"./node_modules/core-js/internals/call-with-safe-iteration-closing.js":function(o,n,e){var t=e("./node_modules/core-js/internals/an-object.js");o.exports=function(i,a,l,r){try{return r?a(t(l)[0],l[1]):a(l)}catch(s){var c=i.return;throw c!==void 0&&t(c.call(i)),s}}},"./node_modules/core-js/internals/check-correctness-of-iteration.js":function(o,n,e){var t=e("./node_modules/core-js/internals/well-known-symbol.js"),i=t("iterator"),a=!1;try{var l=0,r={next:function(){return{done:!!l++}},return:function(){a=!0}};r[i]=function(){return this},Array.from(r,function(){throw 2})}catch(c){}o.exports=function(c,s){if(!s&&!a)return!1;var d=!1;try{var p={};p[i]=function(){return{next:function(){return{done:d=!0}}}},c(p)}catch(h){}return d}},"./node_modules/core-js/internals/classof-raw.js":function(o,n){var e={}.toString;o.exports=function(t){return e.call(t).slice(8,-1)}},"./node_modules/core-js/internals/classof.js":function(o,n,e){var t=e("./node_modules/core-js/internals/classof-raw.js"),i=e("./node_modules/core-js/internals/well-known-symbol.js"),a=i("toStringTag"),l=t(function(){return arguments}())=="Arguments",r=function(c,s){try{return c[s]}catch(d){}};o.exports=function(c){var s,d,p;return c===void 0?"Undefined":c===null?"Null":typeof(d=r(s=Object(c),a))=="string"?d:l?t(s):(p=t(s))=="Object"&&typeof s.callee=="function"?"Arguments":p}},"./node_modules/core-js/internals/copy-constructor-properties.js":function(o,n,e){var t=e("./node_modules/core-js/internals/has.js"),i=e("./node_modules/core-js/internals/own-keys.js"),a=e("./node_modules/core-js/internals/object-get-own-property-descriptor.js"),l=e("./node_modules/core-js/internals/object-define-property.js");o.exports=function(r,c){for(var s=i(c),d=l.f,p=a.f,h=0;h",b="java"+g+":",M;for(m.style.display="none",r.appendChild(m),m.src=String(b),M=m.contentWindow.document,M.open(),M.write(y+g+x+"document.F=Object"+y+"/"+g+x),M.close(),u=M.F;f--;)delete u[p][a[f]];return u()};o.exports=Object.create||function(f,y){var g;return f!==null?(h[p]=t(f),g=new h,h[p]=null,g[d]=f):g=u(),y===void 0?g:i(g,y)},l[d]=!0},"./node_modules/core-js/internals/object-define-properties.js":function(o,n,e){var t=e("./node_modules/core-js/internals/descriptors.js"),i=e("./node_modules/core-js/internals/object-define-property.js"),a=e("./node_modules/core-js/internals/an-object.js"),l=e("./node_modules/core-js/internals/object-keys.js");o.exports=t?Object.defineProperties:function(c,s){a(c);for(var d=l(s),p=d.length,h=0,u;p>h;)i.f(c,u=d[h++],s[u]);return c}},"./node_modules/core-js/internals/object-define-property.js":function(o,n,e){var t=e("./node_modules/core-js/internals/descriptors.js"),i=e("./node_modules/core-js/internals/ie8-dom-define.js"),a=e("./node_modules/core-js/internals/an-object.js"),l=e("./node_modules/core-js/internals/to-primitive.js"),r=Object.defineProperty;n.f=t?r:function(s,d,p){if(a(s),d=l(d,!0),a(p),i)try{return r(s,d,p)}catch(h){}if("get"in p||"set"in p)throw TypeError("Accessors not supported");return"value"in p&&(s[d]=p.value),s}},"./node_modules/core-js/internals/object-get-own-property-descriptor.js":function(o,n,e){var t=e("./node_modules/core-js/internals/descriptors.js"),i=e("./node_modules/core-js/internals/object-property-is-enumerable.js"),a=e("./node_modules/core-js/internals/create-property-descriptor.js"),l=e("./node_modules/core-js/internals/to-indexed-object.js"),r=e("./node_modules/core-js/internals/to-primitive.js"),c=e("./node_modules/core-js/internals/has.js"),s=e("./node_modules/core-js/internals/ie8-dom-define.js"),d=Object.getOwnPropertyDescriptor;n.f=t?d:function(h,u){if(h=l(h),u=r(u,!0),s)try{return d(h,u)}catch(m){}if(c(h,u))return a(!i.f.call(h,u),h[u])}},"./node_modules/core-js/internals/object-get-own-property-names.js":function(o,n,e){var t=e("./node_modules/core-js/internals/object-keys-internal.js"),i=e("./node_modules/core-js/internals/enum-bug-keys.js"),a=i.concat("length","prototype");n.f=Object.getOwnPropertyNames||function(r){return t(r,a)}},"./node_modules/core-js/internals/object-get-own-property-symbols.js":function(o,n){n.f=Object.getOwnPropertySymbols},"./node_modules/core-js/internals/object-get-prototype-of.js":function(o,n,e){var t=e("./node_modules/core-js/internals/has.js"),i=e("./node_modules/core-js/internals/to-object.js"),a=e("./node_modules/core-js/internals/shared-key.js"),l=e("./node_modules/core-js/internals/correct-prototype-getter.js"),r=a("IE_PROTO"),c=Object.prototype;o.exports=l?Object.getPrototypeOf:function(s){return s=i(s),t(s,r)?s[r]:typeof s.constructor=="function"&&s instanceof s.constructor?s.constructor.prototype:s instanceof Object?c:null}},"./node_modules/core-js/internals/object-keys-internal.js":function(o,n,e){var t=e("./node_modules/core-js/internals/has.js"),i=e("./node_modules/core-js/internals/to-indexed-object.js"),a=e("./node_modules/core-js/internals/array-includes.js"),l=e("./node_modules/core-js/internals/hidden-keys.js"),r=a(!1);o.exports=function(c,s){var d=i(c),p=0,h=[],u;for(u in d)!t(l,u)&&t(d,u)&&h.push(u);for(;s.length>p;)t(d,u=s[p++])&&(~r(h,u)||h.push(u));return h}},"./node_modules/core-js/internals/object-keys.js":function(o,n,e){var t=e("./node_modules/core-js/internals/object-keys-internal.js"),i=e("./node_modules/core-js/internals/enum-bug-keys.js");o.exports=Object.keys||function(l){return t(l,i)}},"./node_modules/core-js/internals/object-property-is-enumerable.js":function(o,n,e){"use strict";var t={}.propertyIsEnumerable,i=Object.getOwnPropertyDescriptor,a=i&&!t.call({1:2},1);n.f=a?function(r){var c=i(this,r);return!!c&&c.enumerable}:t},"./node_modules/core-js/internals/object-set-prototype-of.js":function(o,n,e){var t=e("./node_modules/core-js/internals/validate-set-prototype-of-arguments.js");o.exports=Object.setPrototypeOf||("__proto__"in{}?function(){var i=!1,a={},l;try{l=Object.getOwnPropertyDescriptor(Object.prototype,"__proto__").set,l.call(a,[]),i=a instanceof Array}catch(r){}return function(c,s){return t(c,s),i?l.call(c,s):c.__proto__=s,c}}():void 0)},"./node_modules/core-js/internals/own-keys.js":function(o,n,e){var t=e("./node_modules/core-js/internals/global.js"),i=e("./node_modules/core-js/internals/object-get-own-property-names.js"),a=e("./node_modules/core-js/internals/object-get-own-property-symbols.js"),l=e("./node_modules/core-js/internals/an-object.js"),r=t.Reflect;o.exports=r&&r.ownKeys||function(s){var d=i.f(l(s)),p=a.f;return p?d.concat(p(s)):d}},"./node_modules/core-js/internals/path.js":function(o,n,e){o.exports=e("./node_modules/core-js/internals/global.js")},"./node_modules/core-js/internals/redefine.js":function(o,n,e){var t=e("./node_modules/core-js/internals/global.js"),i=e("./node_modules/core-js/internals/shared.js"),a=e("./node_modules/core-js/internals/hide.js"),l=e("./node_modules/core-js/internals/has.js"),r=e("./node_modules/core-js/internals/set-global.js"),c=e("./node_modules/core-js/internals/function-to-string.js"),s=e("./node_modules/core-js/internals/internal-state.js"),d=s.get,p=s.enforce,h=String(c).split("toString");i("inspectSource",function(u){return c.call(u)}),(o.exports=function(u,m,f,y){var g=y?!!y.unsafe:!1,x=y?!!y.enumerable:!1,b=y?!!y.noTargetGet:!1;if(typeof f=="function"&&(typeof m=="string"&&!l(f,"name")&&a(f,"name",m),p(f).source=h.join(typeof m=="string"?m:"")),u===t){x?u[m]=f:r(m,f);return}else g?!b&&u[m]&&(x=!0):delete u[m];x?u[m]=f:a(u,m,f)})(Function.prototype,"toString",function(){return typeof this=="function"&&d(this).source||c.call(this)})},"./node_modules/core-js/internals/require-object-coercible.js":function(o,n){o.exports=function(e){if(e==null)throw TypeError("Can't call method on "+e);return e}},"./node_modules/core-js/internals/set-global.js":function(o,n,e){var t=e("./node_modules/core-js/internals/global.js"),i=e("./node_modules/core-js/internals/hide.js");o.exports=function(a,l){try{i(t,a,l)}catch(r){t[a]=l}return l}},"./node_modules/core-js/internals/set-to-string-tag.js":function(o,n,e){var t=e("./node_modules/core-js/internals/object-define-property.js").f,i=e("./node_modules/core-js/internals/has.js"),a=e("./node_modules/core-js/internals/well-known-symbol.js"),l=a("toStringTag");o.exports=function(r,c,s){r&&!i(r=s?r:r.prototype,l)&&t(r,l,{configurable:!0,value:c})}},"./node_modules/core-js/internals/shared-key.js":function(o,n,e){var t=e("./node_modules/core-js/internals/shared.js"),i=e("./node_modules/core-js/internals/uid.js"),a=t("keys");o.exports=function(l){return a[l]||(a[l]=i(l))}},"./node_modules/core-js/internals/shared.js":function(o,n,e){var t=e("./node_modules/core-js/internals/global.js"),i=e("./node_modules/core-js/internals/set-global.js"),a=e("./node_modules/core-js/internals/is-pure.js"),l="__core-js_shared__",r=t[l]||i(l,{});(o.exports=function(c,s){return r[c]||(r[c]=s!==void 0?s:{})})("versions",[]).push({version:"3.1.3",mode:a?"pure":"global",copyright:"\xA9 2019 Denis Pushkarev (zloirock.ru)"})},"./node_modules/core-js/internals/string-at.js":function(o,n,e){var t=e("./node_modules/core-js/internals/to-integer.js"),i=e("./node_modules/core-js/internals/require-object-coercible.js");o.exports=function(a,l,r){var c=String(i(a)),s=t(l),d=c.length,p,h;return s<0||s>=d?r?"":void 0:(p=c.charCodeAt(s),p<55296||p>56319||s+1===d||(h=c.charCodeAt(s+1))<56320||h>57343?r?c.charAt(s):p:r?c.slice(s,s+2):(p-55296<<10)+(h-56320)+65536)}},"./node_modules/core-js/internals/to-absolute-index.js":function(o,n,e){var t=e("./node_modules/core-js/internals/to-integer.js"),i=Math.max,a=Math.min;o.exports=function(l,r){var c=t(l);return c<0?i(c+r,0):a(c,r)}},"./node_modules/core-js/internals/to-indexed-object.js":function(o,n,e){var t=e("./node_modules/core-js/internals/indexed-object.js"),i=e("./node_modules/core-js/internals/require-object-coercible.js");o.exports=function(a){return t(i(a))}},"./node_modules/core-js/internals/to-integer.js":function(o,n){var e=Math.ceil,t=Math.floor;o.exports=function(i){return isNaN(i=+i)?0:(i>0?t:e)(i)}},"./node_modules/core-js/internals/to-length.js":function(o,n,e){var t=e("./node_modules/core-js/internals/to-integer.js"),i=Math.min;o.exports=function(a){return a>0?i(t(a),9007199254740991):0}},"./node_modules/core-js/internals/to-object.js":function(o,n,e){var t=e("./node_modules/core-js/internals/require-object-coercible.js");o.exports=function(i){return Object(t(i))}},"./node_modules/core-js/internals/to-primitive.js":function(o,n,e){var t=e("./node_modules/core-js/internals/is-object.js");o.exports=function(i,a){if(!t(i))return i;var l,r;if(a&&typeof(l=i.toString)=="function"&&!t(r=l.call(i))||typeof(l=i.valueOf)=="function"&&!t(r=l.call(i))||!a&&typeof(l=i.toString)=="function"&&!t(r=l.call(i)))return r;throw TypeError("Can't convert object to primitive value")}},"./node_modules/core-js/internals/uid.js":function(o,n){var e=0,t=Math.random();o.exports=function(i){return"Symbol(".concat(i===void 0?"":i,")_",(++e+t).toString(36))}},"./node_modules/core-js/internals/validate-set-prototype-of-arguments.js":function(o,n,e){var t=e("./node_modules/core-js/internals/is-object.js"),i=e("./node_modules/core-js/internals/an-object.js");o.exports=function(a,l){if(i(a),!t(l)&&l!==null)throw TypeError("Can't set "+String(l)+" as a prototype")}},"./node_modules/core-js/internals/well-known-symbol.js":function(o,n,e){var t=e("./node_modules/core-js/internals/global.js"),i=e("./node_modules/core-js/internals/shared.js"),a=e("./node_modules/core-js/internals/uid.js"),l=e("./node_modules/core-js/internals/native-symbol.js"),r=t.Symbol,c=i("wks");o.exports=function(s){return c[s]||(c[s]=l&&r[s]||(l?r:a)("Symbol."+s))}},"./node_modules/core-js/modules/es.array.from.js":function(o,n,e){var t=e("./node_modules/core-js/internals/export.js"),i=e("./node_modules/core-js/internals/array-from.js"),a=e("./node_modules/core-js/internals/check-correctness-of-iteration.js"),l=!a(function(r){Array.from(r)});t({target:"Array",stat:!0,forced:l},{from:i})},"./node_modules/core-js/modules/es.string.iterator.js":function(o,n,e){"use strict";var t=e("./node_modules/core-js/internals/string-at.js"),i=e("./node_modules/core-js/internals/internal-state.js"),a=e("./node_modules/core-js/internals/define-iterator.js"),l="String Iterator",r=i.set,c=i.getterFor(l);a(String,"String",function(s){r(this,{type:l,string:String(s),index:0})},function(){var d=c(this),p=d.string,h=d.index,u;return h>=p.length?{value:void 0,done:!0}:(u=t(p,h,!0),d.index+=u.length,{value:u,done:!1})})},"./node_modules/webpack/buildin/global.js":function(o,n){var e;e=function(){return this}();try{e=e||Function("return this")()||(0,eval)("this")}catch(t){typeof window=="object"&&(e=window)}o.exports=e},"./src/default-attrs.json":function(o){o.exports={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":2,"stroke-linecap":"round","stroke-linejoin":"round"}},"./src/icon.js":function(o,n,e){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var t=Object.assign||function(u){for(var m=1;m2&&arguments[2]!==void 0?arguments[2]:[];d(this,u),this.name=m,this.contents=f,this.tags=y,this.attrs=t({},c.default,{class:"feather feather-"+m})}return i(u,[{key:"toSvg",value:function(){var f=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},y=t({},this.attrs,f,{class:(0,l.default)(this.attrs.class,f.class)});return""+this.contents+""}},{key:"toString",value:function(){return this.contents}}]),u}();function h(u){return Object.keys(u).map(function(m){return m+'="'+u[m]+'"'}).join(" ")}n.default=p},"./src/icons.js":function(o,n,e){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var t=e("./src/icon.js"),i=s(t),a=e("./dist/icons.json"),l=s(a),r=e("./src/tags.json"),c=s(r);function s(d){return d&&d.__esModule?d:{default:d}}n.default=Object.keys(l.default).map(function(d){return new i.default(d,l.default[d],c.default[d])}).reduce(function(d,p){return d[p.name]=p,d},{})},"./src/index.js":function(o,n,e){"use strict";var t=e("./src/icons.js"),i=s(t),a=e("./src/to-svg.js"),l=s(a),r=e("./src/replace.js"),c=s(r);function s(d){return d&&d.__esModule?d:{default:d}}o.exports={icons:i.default,toSvg:l.default,replace:c.default}},"./src/replace.js":function(o,n,e){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var t=Object.assign||function(h){for(var u=1;u0&&arguments[0]!==void 0?arguments[0]:{};if(typeof document=="undefined")throw new Error("`feather.replace()` only works in a browser environment.");var u=document.querySelectorAll("[data-feather]");Array.from(u).forEach(function(m){return d(m,h)})}function d(h){var u=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},m=p(h),f=m["data-feather"];delete m["data-feather"];var y=r.default[f].toSvg(t({},u,m,{class:(0,a.default)(u.class,m.class)})),g=new DOMParser().parseFromString(y,"image/svg+xml"),x=g.querySelector("svg");h.parentNode.replaceChild(x,h)}function p(h){return Array.from(h.attributes).reduce(function(u,m){return u[m.name]=m.value,u},{})}n.default=s},"./src/tags.json":function(o){o.exports={activity:["pulse","health","action","motion"],airplay:["stream","cast","mirroring"],"alert-circle":["warning","alert","danger"],"alert-octagon":["warning","alert","danger"],"alert-triangle":["warning","alert","danger"],"align-center":["text alignment","center"],"align-justify":["text alignment","justified"],"align-left":["text alignment","left"],"align-right":["text alignment","right"],anchor:[],archive:["index","box"],"at-sign":["mention","at","email","message"],award:["achievement","badge"],aperture:["camera","photo"],"bar-chart":["statistics","diagram","graph"],"bar-chart-2":["statistics","diagram","graph"],battery:["power","electricity"],"battery-charging":["power","electricity"],bell:["alarm","notification","sound"],"bell-off":["alarm","notification","silent"],bluetooth:["wireless"],"book-open":["read","library"],book:["read","dictionary","booklet","magazine","library"],bookmark:["read","clip","marker","tag"],box:["cube"],briefcase:["work","bag","baggage","folder"],calendar:["date"],camera:["photo"],cast:["chromecast","airplay"],"chevron-down":["expand"],"chevron-up":["collapse"],circle:["off","zero","record"],clipboard:["copy"],clock:["time","watch","alarm"],"cloud-drizzle":["weather","shower"],"cloud-lightning":["weather","bolt"],"cloud-rain":["weather"],"cloud-snow":["weather","blizzard"],cloud:["weather"],codepen:["logo"],codesandbox:["logo"],code:["source","programming"],coffee:["drink","cup","mug","tea","cafe","hot","beverage"],columns:["layout"],command:["keyboard","cmd","terminal","prompt"],compass:["navigation","safari","travel","direction"],copy:["clone","duplicate"],"corner-down-left":["arrow","return"],"corner-down-right":["arrow"],"corner-left-down":["arrow"],"corner-left-up":["arrow"],"corner-right-down":["arrow"],"corner-right-up":["arrow"],"corner-up-left":["arrow"],"corner-up-right":["arrow"],cpu:["processor","technology"],"credit-card":["purchase","payment","cc"],crop:["photo","image"],crosshair:["aim","target"],database:["storage","memory"],delete:["remove"],disc:["album","cd","dvd","music"],"dollar-sign":["currency","money","payment"],droplet:["water"],edit:["pencil","change"],"edit-2":["pencil","change"],"edit-3":["pencil","change"],eye:["view","watch"],"eye-off":["view","watch","hide","hidden"],"external-link":["outbound"],facebook:["logo","social"],"fast-forward":["music"],figma:["logo","design","tool"],"file-minus":["delete","remove","erase"],"file-plus":["add","create","new"],"file-text":["data","txt","pdf"],film:["movie","video"],filter:["funnel","hopper"],flag:["report"],"folder-minus":["directory"],"folder-plus":["directory"],folder:["directory"],framer:["logo","design","tool"],frown:["emoji","face","bad","sad","emotion"],gift:["present","box","birthday","party"],"git-branch":["code","version control"],"git-commit":["code","version control"],"git-merge":["code","version control"],"git-pull-request":["code","version control"],github:["logo","version control"],gitlab:["logo","version control"],globe:["world","browser","language","translate"],"hard-drive":["computer","server","memory","data"],hash:["hashtag","number","pound"],headphones:["music","audio","sound"],heart:["like","love","emotion"],"help-circle":["question mark"],hexagon:["shape","node.js","logo"],home:["house","living"],image:["picture"],inbox:["email"],instagram:["logo","camera"],key:["password","login","authentication","secure"],layers:["stack"],layout:["window","webpage"],"life-buoy":["help","life ring","support"],link:["chain","url"],"link-2":["chain","url"],linkedin:["logo","social media"],list:["options"],lock:["security","password","secure"],"log-in":["sign in","arrow","enter"],"log-out":["sign out","arrow","exit"],mail:["email","message"],"map-pin":["location","navigation","travel","marker"],map:["location","navigation","travel"],maximize:["fullscreen"],"maximize-2":["fullscreen","arrows","expand"],meh:["emoji","face","neutral","emotion"],menu:["bars","navigation","hamburger"],"message-circle":["comment","chat"],"message-square":["comment","chat"],"mic-off":["record","sound","mute"],mic:["record","sound","listen"],minimize:["exit fullscreen","close"],"minimize-2":["exit fullscreen","arrows","close"],minus:["subtract"],monitor:["tv","screen","display"],moon:["dark","night"],"more-horizontal":["ellipsis"],"more-vertical":["ellipsis"],"mouse-pointer":["arrow","cursor"],move:["arrows"],music:["note"],navigation:["location","travel"],"navigation-2":["location","travel"],octagon:["stop"],package:["box","container"],paperclip:["attachment"],pause:["music","stop"],"pause-circle":["music","audio","stop"],"pen-tool":["vector","drawing"],percent:["discount"],"phone-call":["ring"],"phone-forwarded":["call"],"phone-incoming":["call"],"phone-missed":["call"],"phone-off":["call","mute"],"phone-outgoing":["call"],phone:["call"],play:["music","start"],"pie-chart":["statistics","diagram"],"play-circle":["music","start"],plus:["add","new"],"plus-circle":["add","new"],"plus-square":["add","new"],pocket:["logo","save"],power:["on","off"],printer:["fax","office","device"],radio:["signal"],"refresh-cw":["synchronise","arrows"],"refresh-ccw":["arrows"],repeat:["loop","arrows"],rewind:["music"],"rotate-ccw":["arrow"],"rotate-cw":["arrow"],rss:["feed","subscribe"],save:["floppy disk"],scissors:["cut"],search:["find","magnifier","magnifying glass"],send:["message","mail","email","paper airplane","paper aeroplane"],settings:["cog","edit","gear","preferences"],"share-2":["network","connections"],shield:["security","secure"],"shield-off":["security","insecure"],"shopping-bag":["ecommerce","cart","purchase","store"],"shopping-cart":["ecommerce","cart","purchase","store"],shuffle:["music"],"skip-back":["music"],"skip-forward":["music"],slack:["logo"],slash:["ban","no"],sliders:["settings","controls"],smartphone:["cellphone","device"],smile:["emoji","face","happy","good","emotion"],speaker:["audio","music"],star:["bookmark","favorite","like"],"stop-circle":["media","music"],sun:["brightness","weather","light"],sunrise:["weather","time","morning","day"],sunset:["weather","time","evening","night"],tablet:["device"],tag:["label"],target:["logo","bullseye"],terminal:["code","command line","prompt"],thermometer:["temperature","celsius","fahrenheit","weather"],"thumbs-down":["dislike","bad","emotion"],"thumbs-up":["like","good","emotion"],"toggle-left":["on","off","switch"],"toggle-right":["on","off","switch"],tool:["settings","spanner"],trash:["garbage","delete","remove","bin"],"trash-2":["garbage","delete","remove","bin"],triangle:["delta"],truck:["delivery","van","shipping","transport","lorry"],tv:["television","stream"],twitch:["logo"],twitter:["logo","social"],type:["text"],umbrella:["rain","weather"],unlock:["security"],"user-check":["followed","subscribed"],"user-minus":["delete","remove","unfollow","unsubscribe"],"user-plus":["new","add","create","follow","subscribe"],"user-x":["delete","remove","unfollow","unsubscribe","unavailable"],user:["person","account"],users:["group"],"video-off":["camera","movie","film"],video:["camera","movie","film"],voicemail:["phone"],volume:["music","sound","mute"],"volume-1":["music","sound"],"volume-2":["music","sound"],"volume-x":["music","sound","mute"],watch:["clock","time"],"wifi-off":["disabled"],wifi:["connection","signal","wireless"],wind:["weather","air"],"x-circle":["cancel","close","delete","remove","times","clear"],"x-octagon":["delete","stop","alert","warning","times","clear"],"x-square":["cancel","close","delete","remove","times","clear"],x:["cancel","close","delete","remove","times","clear"],youtube:["logo","video","play"],"zap-off":["flash","camera","lightning"],zap:["flash","camera","lightning"],"zoom-in":["magnifying glass"],"zoom-out":["magnifying glass"]}},"./src/to-svg.js":function(o,n,e){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var t=e("./src/icons.js"),i=a(t);function a(r){return r&&r.__esModule?r:{default:r}}function l(r){var c=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};if(console.warn("feather.toSvg() is deprecated. Please use feather.icons[name].toSvg() instead."),!r)throw new Error("The required `key` (icon name) parameter is missing.");if(!i.default[r])throw new Error("No icon matching '"+r+"'. See the complete list of icons at https://feathericons.com");return i.default[r].toSvg(c)}n.default=l},0:function(o,n,e){e("./node_modules/core-js/es/array/from.js"),o.exports=e("./src/index.js")}})})});var Ie=De(v=>{"use strict";Object.defineProperty(v,"__esModule",{value:!0});var F=require("obsidian"),we="YYYY-MM-DD",je="gggg-[W]ww",ze="YYYY-MM",Ue="YYYY-[Q]Q",He="YYYY";function G(o){var e,t;let n=window.app.plugins.getPlugin("periodic-notes");return n&&((t=(e=n.settings)==null?void 0:e[o])==null?void 0:t.enabled)}function Q(){var o,n,e,t;try{let{internalPlugins:i,plugins:a}=window.app;if(G("daily")){let{format:s,folder:d,template:p}=((n=(o=a.getPlugin("periodic-notes"))==null?void 0:o.settings)==null?void 0:n.daily)||{};return{format:s||we,folder:(d==null?void 0:d.trim())||"",template:(p==null?void 0:p.trim())||""}}let{folder:l,format:r,template:c}=((t=(e=i.getPluginById("daily-notes"))==null?void 0:e.instance)==null?void 0:t.options)||{};return{format:r||we,folder:(l==null?void 0:l.trim())||"",template:(c==null?void 0:c.trim())||""}}catch(i){console.info("No custom daily note settings found!",i)}}function Z(){var o,n,e,t,i,a,l;try{let r=window.app.plugins,c=(o=r.getPlugin("calendar"))==null?void 0:o.options,s=(e=(n=r.getPlugin("periodic-notes"))==null?void 0:n.settings)==null?void 0:e.weekly;if(G("weekly"))return{format:s.format||je,folder:((t=s.folder)==null?void 0:t.trim())||"",template:((i=s.template)==null?void 0:i.trim())||""};let d=c||{};return{format:d.weeklyNoteFormat||je,folder:((a=d.weeklyNoteFolder)==null?void 0:a.trim())||"",template:((l=d.weeklyNoteTemplate)==null?void 0:l.trim())||""}}catch(r){console.info("No custom weekly note settings found!",r)}}function J(){var n,e,t,i;let o=window.app.plugins;try{let a=G("monthly")&&((e=(n=o.getPlugin("periodic-notes"))==null?void 0:n.settings)==null?void 0:e.monthly)||{};return{format:a.format||ze,folder:((t=a.folder)==null?void 0:t.trim())||"",template:((i=a.template)==null?void 0:i.trim())||""}}catch(a){console.info("No custom monthly note settings found!",a)}}function X(){var n,e,t,i;let o=window.app.plugins;try{let a=G("quarterly")&&((e=(n=o.getPlugin("periodic-notes"))==null?void 0:n.settings)==null?void 0:e.quarterly)||{};return{format:a.format||Ue,folder:((t=a.folder)==null?void 0:t.trim())||"",template:((i=a.template)==null?void 0:i.trim())||""}}catch(a){console.info("No custom quarterly note settings found!",a)}}function q(){var n,e,t,i;let o=window.app.plugins;try{let a=G("yearly")&&((e=(n=o.getPlugin("periodic-notes"))==null?void 0:n.settings)==null?void 0:e.yearly)||{};return{format:a.format||He,folder:((t=a.folder)==null?void 0:t.trim())||"",template:((i=a.template)==null?void 0:i.trim())||""}}catch(a){console.info("No custom yearly note settings found!",a)}}function We(...o){let n=[];for(let t=0,i=o.length;t{let x=t(),b=o.clone().set({hour:x.get("hour"),minute:x.get("minute"),second:x.get("second")});return m&&b.add(parseInt(f,10),y),g?b.format(g.substring(1).trim()):b.format(a)}).replace(/{{\s*yesterday\s*}}/gi,o.clone().subtract(1,"day").format(a)).replace(/{{\s*tomorrow\s*}}/gi,o.clone().add(1,"d").format(a)));return n.foldManager.save(p,c),p}catch(p){console.error(`Failed to create file: '${d}'`,p),new F.Notice("Unable to create new file.")}}function St(o,n){var e;return(e=n[O(o,"day")])!=null?e:null}function Ot(){let{vault:o}=window.app,{folder:n}=Q(),e=o.getAbstractFileByPath(F.normalizePath(n));if(!e)throw new be("Failed to find daily notes folder");let t={};return F.Vault.recurseChildren(e,i=>{if(i instanceof F.TFile){let a=W(i,"day");if(a){let l=O(a,"day");t[l]=i}}}),t}var Me=class extends Error{};function Ct(){let{moment:o}=window,n=o.localeData()._week.dow,e=["sunday","monday","tuesday","wednesday","thursday","friday","saturday"];for(;n;)e.push(e.shift()),n--;return e}function kt(o){return Ct().indexOf(o.toLowerCase())}async function Ke(o){let{vault:n}=window.app,{template:e,format:t,folder:i}=Z(),[a,l]=await H(e),r=o.format(t),c=await _(i,r);try{let s=await n.create(c,a.replace(/{{\s*(date|time)\s*(([+-]\d+)([yqmwdhs]))?\s*(:.+?)?}}/gi,(d,p,h,u,m,f)=>{let y=window.moment(),g=o.clone().set({hour:y.get("hour"),minute:y.get("minute"),second:y.get("second")});return h&&g.add(parseInt(u,10),m),f?g.format(f.substring(1).trim()):g.format(t)}).replace(/{{\s*title\s*}}/gi,r).replace(/{{\s*time\s*}}/gi,window.moment().format("HH:mm")).replace(/{{\s*(sunday|monday|tuesday|wednesday|thursday|friday|saturday)\s*:(.*?)}}/gi,(d,p,h)=>{let u=kt(p);return o.weekday(u).format(h.trim())}));return window.app.foldManager.save(s,l),s}catch(s){console.error(`Failed to create file: '${c}'`,s),new F.Notice("Unable to create new file.")}}function Tt(o,n){var e;return(e=n[O(o,"week")])!=null?e:null}function Et(){let o={};if(!Qe())return o;let{vault:n}=window.app,{folder:e}=Z(),t=n.getAbstractFileByPath(F.normalizePath(e));if(!t)throw new Me("Failed to find weekly notes folder");return F.Vault.recurseChildren(t,i=>{if(i instanceof F.TFile){let a=W(i,"week");if(a){let l=O(a,"week");o[l]=i}}}),o}var Ae=class extends Error{};async function Ge(o){let{vault:n}=window.app,{template:e,format:t,folder:i}=J(),[a,l]=await H(e),r=o.format(t),c=await _(i,r);try{let s=await n.create(c,a.replace(/{{\s*(date|time)\s*(([+-]\d+)([yqmwdhs]))?\s*(:.+?)?}}/gi,(d,p,h,u,m,f)=>{let y=window.moment(),g=o.clone().set({hour:y.get("hour"),minute:y.get("minute"),second:y.get("second")});return h&&g.add(parseInt(u,10),m),f?g.format(f.substring(1).trim()):g.format(t)}).replace(/{{\s*date\s*}}/gi,r).replace(/{{\s*time\s*}}/gi,window.moment().format("HH:mm")).replace(/{{\s*title\s*}}/gi,r));return window.app.foldManager.save(s,l),s}catch(s){console.error(`Failed to create file: '${c}'`,s),new F.Notice("Unable to create new file.")}}function Rt(o,n){var e;return(e=n[O(o,"month")])!=null?e:null}function Nt(){let o={};if(!Ze())return o;let{vault:n}=window.app,{folder:e}=J(),t=n.getAbstractFileByPath(F.normalizePath(e));if(!t)throw new Ae("Failed to find monthly notes folder");return F.Vault.recurseChildren(t,i=>{if(i instanceof F.TFile){let a=W(i,"month");if(a){let l=O(a,"month");o[l]=i}}}),o}var Fe=class extends Error{};async function Dt(o){let{vault:n}=window.app,{template:e,format:t,folder:i}=X(),[a,l]=await H(e),r=o.format(t),c=await _(i,r);try{let s=await n.create(c,a.replace(/{{\s*(date|time)\s*(([+-]\d+)([yqmwdhs]))?\s*(:.+?)?}}/gi,(d,p,h,u,m,f)=>{let y=window.moment(),g=o.clone().set({hour:y.get("hour"),minute:y.get("minute"),second:y.get("second")});return h&&g.add(parseInt(u,10),m),f?g.format(f.substring(1).trim()):g.format(t)}).replace(/{{\s*date\s*}}/gi,r).replace(/{{\s*time\s*}}/gi,window.moment().format("HH:mm")).replace(/{{\s*title\s*}}/gi,r));return window.app.foldManager.save(s,l),s}catch(s){console.error(`Failed to create file: '${c}'`,s),new F.Notice("Unable to create new file.")}}function Vt(o,n){var e;return(e=n[O(o,"quarter")])!=null?e:null}function Lt(){let o={};if(!Je())return o;let{vault:n}=window.app,{folder:e}=X(),t=n.getAbstractFileByPath(F.normalizePath(e));if(!t)throw new Fe("Failed to find quarterly notes folder");return F.Vault.recurseChildren(t,i=>{if(i instanceof F.TFile){let a=W(i,"quarter");if(a){let l=O(a,"quarter");o[l]=i}}}),o}var Pe=class extends Error{};async function zt(o){let{vault:n}=window.app,{template:e,format:t,folder:i}=q(),[a,l]=await H(e),r=o.format(t),c=await _(i,r);try{let s=await n.create(c,a.replace(/{{\s*(date|time)\s*(([+-]\d+)([yqmwdhs]))?\s*(:.+?)?}}/gi,(d,p,h,u,m,f)=>{let y=window.moment(),g=o.clone().set({hour:y.get("hour"),minute:y.get("minute"),second:y.get("second")});return h&&g.add(parseInt(u,10),m),f?g.format(f.substring(1).trim()):g.format(t)}).replace(/{{\s*date\s*}}/gi,r).replace(/{{\s*time\s*}}/gi,window.moment().format("HH:mm")).replace(/{{\s*title\s*}}/gi,r));return window.app.foldManager.save(s,l),s}catch(s){console.error(`Failed to create file: '${c}'`,s),new F.Notice("Unable to create new file.")}}function Ut(o,n){var e;return(e=n[O(o,"year")])!=null?e:null}function Ht(){let o={};if(!Xe())return o;let{vault:n}=window.app,{folder:e}=q(),t=n.getAbstractFileByPath(F.normalizePath(e));if(!t)throw new Pe("Failed to find yearly notes folder");return F.Vault.recurseChildren(t,i=>{if(i instanceof F.TFile){let a=W(i,"year");if(a){let l=O(a,"year");o[l]=i}}}),o}function Wt(){var t,i;let{app:o}=window,n=o.internalPlugins.plugins["daily-notes"];if(n&&n.enabled)return!0;let e=o.plugins.getPlugin("periodic-notes");return e&&((i=(t=e.settings)==null?void 0:t.daily)==null?void 0:i.enabled)}function Qe(){var e,t;let{app:o}=window;if(o.plugins.getPlugin("calendar"))return!0;let n=o.plugins.getPlugin("periodic-notes");return n&&((t=(e=n.settings)==null?void 0:e.weekly)==null?void 0:t.enabled)}function Ze(){var e,t;let{app:o}=window,n=o.plugins.getPlugin("periodic-notes");return n&&((t=(e=n.settings)==null?void 0:e.monthly)==null?void 0:t.enabled)}function Je(){var e,t;let{app:o}=window,n=o.plugins.getPlugin("periodic-notes");return n&&((t=(e=n.settings)==null?void 0:e.quarterly)==null?void 0:t.enabled)}function Xe(){var e,t;let{app:o}=window,n=o.plugins.getPlugin("periodic-notes");return n&&((t=(e=n.settings)==null?void 0:e.yearly)==null?void 0:t.enabled)}function Bt(o){let n={day:Q,week:Z,month:J,quarter:X,year:q}[o];return n()}function $t(o,n){return{day:Ye,month:Ge,week:Ke}[o](n)}v.DEFAULT_DAILY_NOTE_FORMAT=we;v.DEFAULT_MONTHLY_NOTE_FORMAT=ze;v.DEFAULT_QUARTERLY_NOTE_FORMAT=Ue;v.DEFAULT_WEEKLY_NOTE_FORMAT=je;v.DEFAULT_YEARLY_NOTE_FORMAT=He;v.appHasDailyNotesPluginLoaded=Wt;v.appHasMonthlyNotesPluginLoaded=Ze;v.appHasQuarterlyNotesPluginLoaded=Je;v.appHasWeeklyNotesPluginLoaded=Qe;v.appHasYearlyNotesPluginLoaded=Xe;v.createDailyNote=Ye;v.createMonthlyNote=Ge;v.createPeriodicNote=$t;v.createQuarterlyNote=Dt;v.createWeeklyNote=Ke;v.createYearlyNote=zt;v.getAllDailyNotes=Ot;v.getAllMonthlyNotes=Nt;v.getAllQuarterlyNotes=Lt;v.getAllWeeklyNotes=Et;v.getAllYearlyNotes=Ht;v.getDailyNote=St;v.getDailyNoteSettings=Q;v.getDateFromFile=W;v.getDateFromPath=It;v.getDateUID=O;v.getMonthlyNote=Rt;v.getMonthlyNoteSettings=J;v.getPeriodicNoteSettings=Bt;v.getQuarterlyNote=Vt;v.getQuarterlyNoteSettings=X;v.getTemplateInfo=H;v.getWeeklyNote=Tt;v.getWeeklyNoteSettings=Z;v.getYearlyNote=Ut;v.getYearlyNoteSettings=q});var Xt={};jt(Xt,{default:()=>ge});module.exports=bt(Xt);var j=require("obsidian");var Mt=xe(Le()),E=require("obsidian");var K=o=>o.match(/\.MD$|\.md$/m)?o.split(/\.MD$|\.md$/m).slice(0,-1).join(".md"):o;var R=xe(Ie());var qe=require("obsidian"),le=class o{static getBlock(n,e,t){var s,d;let i=e.getCursor("to"),a=n.metadataCache.getFileCache(t),l=a==null?void 0:a.sections;if(!l||l.length===0){console.log("error reading FileCache (empty file?)");return}let r=l.findIndex(p=>p.position.start.line>i.line),c=r>0?l[r-1]:l[l.length-1];return(c==null?void 0:c.type)=="list"&&(c=(d=(s=a.listItems)==null?void 0:s.find(p=>p.position.start.line<=i.line&&p.position.end.line>=i.line))!=null?d:c),c}static getIdOfBlock(n,e){let t=e.id;if(t)return t;let i=e.position.end,a={ch:i.col,line:i.line},l=Math.random().toString(36).substring(2,8),r=o.shouldInsertAfter(e)?` -`:" ";return n.replaceRange(`${r}^${l}`,a),l}static shouldInsertAfter(n){if(n.type)return["blockquote","code","table","heading","comment","footnoteDefinition"].includes(n.type)}static getBlockId(n){let e=n.workspace.getActiveViewOfType(qe.MarkdownView);if(e){let t=e.editor,i=e.file,a=this.getBlock(n,t,i);if(a)return this.getIdOfBlock(t,a)}}};var _e={openFileOnWrite:!0,openDailyInNewPane:!1,openFileOnWriteInNewPane:!1,openFileWithoutWriteInNewPane:!1,idField:"id",useUID:!1,addFilepathWhenUsingUID:!1,allowEval:!1,includeVaultName:!0,vaultParam:"name"};var et=require("obsidian"),tt=xe(Ie());function nt(...o){let n=[];for(let t=0,i=o.length;t{this.file?this.plugin.tools.copyURI({filepath:this.file,data:e,mode:i}):this.plugin.tools.copyURI({daily:"true",data:e,mode:i})}})}return t}renderSuggestion(e,t){t.innerText=e.display}onChooseSuggestion(e,t){e.func()}};var at=require("obsidian"),V=class extends at.FuzzySuggestModal{constructor(e,t,i=!0){super(e.app);this.placeHolder=t;this.allowNoFile=i;this.plugin=e,this.setPlaceholder(this.placeHolder)}getItems(){let e=[];this.allowNoFile&&e.push({display:"",source:void 0});let t=this.app.workspace.getActiveFile();return t&&e.push({display:"",source:t.path}),[...e,...this.app.vault.getFiles().map(i=>({display:i.path,source:i.path}))]}getItemText(e){return e.display}onChooseItem(e,t){}};var lt=require("obsidian");function Se(o){return o.viewmode?{state:{mode:o.viewmode,source:o.viewmode=="source"}}:void 0}function ee(o){return navigator.clipboard.writeText(o)}function re(o,n){var a;let e=(a=n.parent)==null?void 0:a.path,t=e==="/"?"":e,i=n.name;for(let l=1;l<100;l++){let r=K(i),c=t+(t==""?"":"/")+r+` ${l}.md`;if(!(o.vault.getAbstractFileByPath(c)!==null))return c}}function rt(o,n){let e=new URL(o.vault.getResourcePath(n));return e.host="localhosthostlocal",e.protocol="file",e.search="",e.pathname=decodeURIComponent(e.pathname),e.toString().replace("/localhosthostlocal/","/")}function Oe(o,n,e){var l,r;let t=o.metadataCache.getFileCache(n),i=t.sections,a=(l=t.headings)==null?void 0:l.find(c=>c.heading===e);if(a){let c=i.findIndex(u=>u.type==="heading"&&u.position.start.line===a.position.start.line),s=i.slice(c+1),d=s==null?void 0:s.findIndex(u=>u.type==="heading");return{lastLine:((r=s[(d!==-1?d:s.length)-1])!=null?r:i[c]).position.end.line+1,firstLine:i[c].position.end.line+1}}else new lt.Notice("Can't find heading")}var te=class{constructor(n){this.plugin=n;this.app=this.plugin.app}get tools(){return this.plugin.tools}handlePluginManagement(n){if(n["enable-plugin"]){let e=n["enable-plugin"];this.app.plugins.getPlugin(e)?(this.app.plugins.enablePluginAndSave(e),new w.Notice(`Enabled ${e}`)):this.app.internalPlugins.plugins[e]&&(this.app.internalPlugins.plugins[e].enable(!0),new w.Notice(`Enabled ${e}`))}else if(n["disable-plugin"]){let e=n["disable-plugin"];this.app.plugins.getPlugin(e)?(this.app.plugins.disablePluginAndSave(e),new w.Notice(`Disabled ${e}`)):this.app.internalPlugins.plugins[e]&&(this.app.internalPlugins.plugins[e].disable(!0),new w.Notice(`Disabled ${e}`))}}handleFrontmatterKey(n){var a;let e=n.frontmatterkey,t=this.app.vault.getAbstractFileByPath((a=n.filepath)!=null?a:this.app.workspace.getActiveFile().path);if(!(t instanceof w.TFile))return;let i=this.app.metadataCache.getFileCache(t).frontmatter;if(n.data){let l=n.data;try{l=JSON.parse(l)}catch(r){l=`"${l}"`,l=JSON.parse(l)}this.app.fileManager.processFrontMatter(t,r=>{if(e.startsWith("[")&&e.endsWith("]")){let c=e.substring(1,e.length-1).split(","),s=r;for(let d=0;du==p)),d==c.length-1?s[parseInt(p)]=l:s=s[parseInt(p)]}else d==c.length-1?s[p]=l:s=s[p]}}else r[e]=l})}else{let l;if(e.startsWith("[")&&e.endsWith("]")){let r=e.substring(1,e.length-1).split(","),c=i;for(let s of r)if(c instanceof Array){let d=parseInt(s);Number.isNaN(d)&&(c=c.find(p=>p==s)),c=c[parseInt(s)]}else c=c[s];l=c}else l=i[e];ee(l)}}handleWorkspace(n){let e=this.app.internalPlugins.getEnabledPluginById("workspaces");if(!e)new w.Notice("Workspaces plugin is not enabled"),this.plugin.failure(n);else{if(n.saveworkspace=="true"){let t=e.activeWorkspace;e.saveWorkspace(t),new w.Notice(`Saved current workspace to ${t}`)}n.clipboard&&n.clipboard!="false"?this.tools.copyURI({workspace:e.activeWorkspace}):n.workspace!=null&&e.loadWorkspace(n.workspace),this.plugin.success(n)}}async handleCommand(n){if(n.filepath)if(n.mode){if(n.mode=="new"){let t=this.app.metadataCache.getFirstLinkpathDest(n.filepath,"/");t instanceof w.TFile&&(n.filepath=re(this.app,t))}await this.plugin.open({file:n.filepath,mode:"source",parameters:n});let e=this.app.workspace.getActiveViewOfType(w.MarkdownView);if(e){let t=e.editor,i=t.getValue();if(n.mode==="append"){t.setValue(i+` +`:" ";return n.replaceRange(`${r}^${l}`,a),l}static shouldInsertAfter(n){if(n.type)return["blockquote","code","table","heading","comment","footnoteDefinition"].includes(n.type)}static getBlockId(n){let e=n.workspace.getActiveViewOfType(qe.MarkdownView);if(e){let t=e.editor,i=e.file,a=this.getBlock(n,t,i);if(a)return this.getIdOfBlock(t,a)}}};var _e={openFileOnWrite:!0,openDailyInNewPane:!1,openFileOnWriteInNewPane:!1,openFileWithoutWriteInNewPane:!1,idField:"id",useUID:!1,addFilepathWhenUsingUID:!1,allowEval:!1,includeVaultName:!0,vaultParam:"name"};var et=require("obsidian"),tt=xe(Ie());function nt(...o){let n=[];for(let t=0,i=o.length;t{this.file?this.plugin.tools.copyURI({filepath:this.file,data:e,mode:i}):this.plugin.tools.copyURI({daily:"true",data:e,mode:i})}})}return t}renderSuggestion(e,t){t.innerText=e.display}onChooseSuggestion(e,t){e.func()}};var at=require("obsidian"),V=class extends at.FuzzySuggestModal{constructor(e,t,i=!0){super(e.app);this.placeHolder=t;this.allowNoFile=i;this.plugin=e,this.setPlaceholder(this.placeHolder)}getItems(){let e=[];this.allowNoFile&&e.push({display:"",source:void 0});let t=this.app.workspace.getActiveFile();return t&&e.push({display:"",source:t.path}),[...e,...this.app.vault.getFiles().map(i=>({display:i.path,source:i.path}))]}getItemText(e){return e.display}onChooseItem(e,t){}};var lt=require("obsidian");function Se(o){return o.viewmode?{state:{mode:o.viewmode,source:o.viewmode=="source"}}:void 0}function ee(o){return navigator.clipboard.writeText(o)}function re(o,n){var a;let e=(a=n.parent)==null?void 0:a.path,t=e==="/"?"":e,i=n.name;for(let l=1;l<100;l++){let r=K(i),c=t+(t==""?"":"/")+r+` ${l}.md`;if(!(o.vault.getAbstractFileByPath(c)!==null))return c}}function rt(o,n){let e=new URL(o.vault.getResourcePath(n));return e.host="localhosthostlocal",e.protocol="file",e.search="",e.pathname=decodeURIComponent(e.pathname),e.toString().replace("/localhosthostlocal/","/")}function Oe(o,n,e){var l,r;let t=o.metadataCache.getFileCache(n),i=t.sections,a=(l=t.headings)==null?void 0:l.find(c=>c.heading===e);if(a){let c=i.findIndex(u=>u.type==="heading"&&u.position.start.line===a.position.start.line),s=i.slice(c+1),d=s==null?void 0:s.findIndex(u=>u.type==="heading");return{lastLine:((r=s[(d!==-1?d:s.length)-1])!=null?r:i[c]).position.end.line+1,firstLine:i[c].position.end.line+1}}else new lt.Notice("Can't find heading")}var te=class{constructor(n){this.plugin=n;this.app=this.plugin.app}get tools(){return this.plugin.tools}handlePluginManagement(n){if(n["enable-plugin"]){let e=n["enable-plugin"];e in this.app.plugins.manifests&&!this.app.plugins.getPlugin(e)?(this.app.plugins.enablePluginAndSave(e),new w.Notice(`Enabled ${e}`)):this.app.internalPlugins.plugins[e]&&(this.app.internalPlugins.plugins[e].enable(!0),new w.Notice(`Enabled ${e}`))}else if(n["disable-plugin"]){let e=n["disable-plugin"];this.app.plugins.getPlugin(e)?(this.app.plugins.disablePluginAndSave(e),new w.Notice(`Disabled ${e}`)):this.app.internalPlugins.plugins[e]&&(this.app.internalPlugins.plugins[e].disable(!0),new w.Notice(`Disabled ${e}`))}}handleFrontmatterKey(n){var a;let e=n.frontmatterkey,t=this.app.vault.getAbstractFileByPath((a=n.filepath)!=null?a:this.app.workspace.getActiveFile().path);if(!(t instanceof w.TFile))return;let i=this.app.metadataCache.getFileCache(t).frontmatter;if(n.data){let l=n.data;try{l=JSON.parse(l)}catch(r){l=`"${l}"`,l=JSON.parse(l)}this.app.fileManager.processFrontMatter(t,r=>{if(e.startsWith("[")&&e.endsWith("]")){let c=e.substring(1,e.length-1).split(","),s=r;for(let d=0;du==p)),d==c.length-1?s[parseInt(p)]=l:s=s[parseInt(p)]}else d==c.length-1?s[p]=l:s=s[p]}}else r[e]=l})}else{let l;if(e.startsWith("[")&&e.endsWith("]")){let r=e.substring(1,e.length-1).split(","),c=i;for(let s of r)if(c instanceof Array){let d=parseInt(s);Number.isNaN(d)&&(c=c.find(p=>p==s)),c=c[parseInt(s)]}else c=c[s];l=c}else l=i[e];ee(l)}}handleWorkspace(n){let e=this.app.internalPlugins.getEnabledPluginById("workspaces");if(!e)new w.Notice("Workspaces plugin is not enabled"),this.plugin.failure(n);else{if(n.saveworkspace=="true"){let t=e.activeWorkspace;e.saveWorkspace(t),new w.Notice(`Saved current workspace to ${t}`)}n.clipboard&&n.clipboard!="false"?this.tools.copyURI({workspace:e.activeWorkspace}):n.workspace!=null&&e.loadWorkspace(n.workspace),this.plugin.success(n)}}async handleCommand(n){if(n.filepath)if(n.mode){if(n.mode=="new"){let t=this.app.metadataCache.getFirstLinkpathDest(n.filepath,"/");t instanceof w.TFile&&(n.filepath=re(this.app,t))}await this.plugin.open({file:n.filepath,mode:"source",parameters:n});let e=this.app.workspace.getActiveViewOfType(w.MarkdownView);if(e){let t=e.editor,i=t.getValue();if(n.mode==="append"){t.setValue(i+` `);let a=t.lineCount();t.setCursor({ch:0,line:a})}else n.mode==="prepend"?(t.setValue(` `+i),t.setCursor({ch:0,line:0})):n.mode==="overwrite"&&t.setValue("")}}else n.line!=null||n.column!=null||n.offset!=null?(await this.plugin.open({file:n.filepath,mode:"source",parameters:n}),await this.plugin.setCursorInLine(n)):await this.plugin.open({file:n.filepath,setting:this.plugin.settings.openFileWithoutWriteInNewPane,parameters:n});else(n.openmode||n.viewmode)&&await this.plugin.open({parameters:n});if(n.commandid)this.app.commands.executeCommandById(n.commandid);else if(n.commandname){let e=this.app.commands.commands;for(let t in e)if(e[t].name===n.commandname){e[t].callback?await e[t].callback():e[t].checkCallback(!1);break}}if(n.confirm&&n.confirm!="false"){await new Promise(t=>setTimeout(t,750));let e=document.querySelector(".mod-cta:not([style*='display: none'])");e.click instanceof Function&&e.click()}this.plugin.success(n)}async handleEval(n){if(n.filepath)if(n.mode){if(n.mode=="new"){let t=this.app.metadataCache.getFirstLinkpathDest(n.filepath,"/");t instanceof w.TFile&&(n.filepath=re(this.app,t))}await this.plugin.open({file:n.filepath,mode:"source",parameters:n});let e=this.app.workspace.getActiveViewOfType(w.MarkdownView);if(e){let t=e.editor,i=t.getValue();if(n.mode==="append"){t.setValue(i+` `);let a=t.lineCount();t.setCursor({ch:0,line:a})}else n.mode==="prepend"?(t.setValue(` @@ -33,3 +33,5 @@ feather-icons/dist/feather.js: http://jedwatson.github.io/classnames *) */ + +/* nosourcemap */ \ No newline at end of file diff --git a/.obsidian/plugins/obsidian-advanced-uri/manifest.json b/.obsidian/plugins/obsidian-advanced-uri/manifest.json index c92d8e2..d51a111 100644 --- a/.obsidian/plugins/obsidian-advanced-uri/manifest.json +++ b/.obsidian/plugins/obsidian-advanced-uri/manifest.json @@ -5,7 +5,7 @@ "isDesktopOnly": false, "js": "main.js", "fundingUrl": "https://ko-fi.com/vinzent", - "version": "1.44.1", + "version": "1.44.2", "author": "Vinzent", "authorUrl": "https://github.com/Vinzent03" } diff --git a/.obsidian/plugins/obsidian-sort-and-permute-lines/main.js b/.obsidian/plugins/obsidian-sort-and-permute-lines/main.js deleted file mode 100644 index 3b5eb72..0000000 --- a/.obsidian/plugins/obsidian-sort-and-permute-lines/main.js +++ /dev/null @@ -1,392 +0,0 @@ -'use strict'; - -var obsidian = require('obsidian'); - -/****************************************************************************** -Copyright (c) Microsoft Corporation. - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THIS SOFTWARE. -***************************************************************************** */ -/* global Reflect, Promise */ - -var extendStatics = function(d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); -}; - -function __extends(d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); -} - -function __awaiter(thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -} - -function __generator(thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; - return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (g && (g = 0, op[0] && (_ = 0)), _) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -} - -/** @deprecated */ -function __spreadArrays() { - for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; - for (var r = Array(s), k = 0, i = 0; i < il; i++) - for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) - r[k] = a[j]; - return r; -} - -var checkboxRegex = /^(\s*)- \[[^ ]\]/gi; -var MyPlugin = /** @class */ (function (_super) { - __extends(MyPlugin, _super); - function MyPlugin() { - return _super !== null && _super.apply(this, arguments) || this; - } - MyPlugin.prototype.onload = function () { - return __awaiter(this, void 0, void 0, function () { - var compare, comp; - var _this = this; - return __generator(this, function (_a) { - console.log('loading ' + this.manifest.name); - compare = new Intl.Collator(navigator.language, { - usage: 'sort', - sensitivity: 'base', - numeric: true, - ignorePunctuation: true, - }).compare; - this.compare = compare; - this.addCommand({ - id: 'sort-alphabetically-with-checkboxes', - name: 'Sort alphabetically with checkboxes', - callback: (function () { return _this.sortAlphabetically(false, false); }), - }); - this.addCommand({ - id: 'sort-list-alphabetically-with-checkboxes', - name: 'Sort current list alphabetically with checkboxes', - callback: (function () { return _this.sortAlphabetically(true, false); }), - }); - this.addCommand({ - id: 'sort-alphabetically', - name: 'Sort alphabetically', - callback: (function () { return _this.sortAlphabetically(false, true); }), - }); - this.addCommand({ - id: 'sort-list-alphabetically', - name: 'Sort current list alphabetically', - callback: (function () { return _this.sortAlphabetically(true, true); }), - }); - this.addCommand({ - id: 'sort-checkboxes', - name: 'Sort current list by checkboxes', - callback: function () { return _this.sortListRecursively(true, function (a, b) { - if (checkboxRegex.test(a.title.source) && !checkboxRegex.test(b.title.source)) - return 1; - if (!checkboxRegex.test(a.title.source) && checkboxRegex.test(b.title.source)) - return -1; - return 0; - }); }, - }); - this.addCommand({ - id: 'sort-length', - name: 'Sort by length of line', - callback: (function () { return _this.sortLengthOfLine(); }), - }); - this.addCommand({ - id: 'sort-headings', - name: 'Sort headings', - callback: (function () { return _this.sortHeadings(); }), - }); - this.addCommand({ - id: 'permute-reverse', - name: 'Reverse lines', - callback: (function () { return _this.permuteReverse(); }), - }); - this.addCommand({ - id: 'permute-shuffle', - name: 'Shuffle lines', - callback: (function () { return _this.permuteShuffle(); }), - }); - comp = function (a, b) { return _this.compare(a.title.formatted.trim(), b.title.formatted.trim()); }; - this.addCommand({ - id: 'sort-list-recursively', - name: 'Sort current list recursively', - callback: (function () { return _this.sortListRecursively(true, comp); }), - }); - this.addCommand({ - id: 'sort-list-recursively-with-checkboxes', - name: 'Sort current list recursively with checkboxes', - callback: (function () { return _this.sortListRecursively(false, comp); }), - }); - return [2 /*return*/]; - }); - }); - }; - MyPlugin.prototype.onunload = function () { - console.log('unloading ' + this.manifest.name); - }; - MyPlugin.prototype.sortAlphabetically = function (fromCurrentList, ignoreCheckboxes) { - var _this = this; - if (fromCurrentList === void 0) { fromCurrentList = false; } - if (ignoreCheckboxes === void 0) { ignoreCheckboxes = true; } - var lines = this.getLines(fromCurrentList, ignoreCheckboxes); - if (lines.length === 0) - return; - var sortFunc = function (a, b) { return _this.compare(a.formatted.trim(), b.formatted.trim()); }; - lines.sort(sortFunc); - this.setLines(lines, fromCurrentList); - }; - MyPlugin.prototype.sortListRecursively = function (ignoreCheckboxes, compareFn) { - var _this = this; - var inputLines = this.getLines(true, ignoreCheckboxes); - if (inputLines.length === 0 || inputLines.find(function (line) { return line.source.trim() == ""; })) - return; - var firstLineNumber = inputLines.first().lineNumber; - var lines = __spreadArrays(new Array(firstLineNumber).fill(undefined), inputLines); - var index = firstLineNumber; - var cache = this.app.metadataCache.getFileCache(this.app.workspace.getActiveFile()); - var children = []; - while (index < lines.length) { - var newChild = this.getSortedListParts(lines, cache.listItems, index, compareFn); - children.push(newChild); - index = newChild.lastLine; - index++; - } - children.sort(compareFn); - var res = children.reduce(function (acc, cur) { return acc.concat(_this.listPartToList(cur)); }, []); - this.setLines(res, true); - }; - MyPlugin.prototype.getLineCacheFromLine = function (line, linesCache) { - return linesCache.find(function (cacheItem) { return cacheItem.position.start.line === line; }); - }; - MyPlugin.prototype.getSortedListParts = function (lines, linesCache, index, compareFn) { - var _a, _b, _c, _d, _e; - var children = []; - var startListCache = this.getLineCacheFromLine(index, linesCache); - var title = lines[index]; - while (startListCache.parent < ((_a = this.getLineCacheFromLine(index + 1, linesCache)) === null || _a === void 0 ? void 0 : _a.parent) || (startListCache.parent < 0 && ((_b = this.getLineCacheFromLine(index + 1, linesCache)) === null || _b === void 0 ? void 0 : _b.parent) >= 0)) { - index++; - var newChild = this.getSortedListParts(lines, linesCache, index, compareFn); - index = (_c = newChild.lastLine) !== null && _c !== void 0 ? _c : index; - children.push(newChild); - } - var lastLine = (_e = (_d = children.last()) === null || _d === void 0 ? void 0 : _d.lastLine) !== null && _e !== void 0 ? _e : index; - children.sort(compareFn); - return { - children: children, - title: title, - lastLine: lastLine, - }; - }; - MyPlugin.prototype.listPartToList = function (list) { - var _this = this; - return list.children.reduce(function (acc, cur) { return acc.concat(_this.listPartToList(cur)); }, [list.title]); - }; - MyPlugin.prototype.sortHeadings = function () { - var lines = this.getLines(); - var res = this.getSortedHeadings(lines, 0, { headingLevel: 0, formatted: "", source: "", lineNumber: -1 }); - this.setLines(this.headingsToString(res).slice(1)); - }; - MyPlugin.prototype.headingsToString = function (heading) { - var _this = this; - var list = __spreadArrays([ - heading.title - ], heading.lines); - heading.headings.forEach(function (e) { return list.push.apply(list, _this.headingsToString(e)); }); - return list; - }; - MyPlugin.prototype.getSortedHeadings = function (lines, from, heading) { - var _this = this; - var headings = []; - var contentLines = []; - var currentIndex = from; - while (currentIndex < lines.length) { - var current = lines[currentIndex]; - if (current.headingLevel <= heading.headingLevel) { - break; - } - if (current.headingLevel) { - headings.push(this.getSortedHeadings(lines, currentIndex + 1, current)); - currentIndex = headings.last().to; - } - else { - contentLines.push(current); - } - currentIndex++; - } - return { - lines: contentLines, - to: headings.length > 0 ? headings.last().to : (currentIndex - 1), - headings: headings.sort(function (a, b) { - //First sort by heading level then alphabetically - var res = a.title.headingLevel - b.title.headingLevel; - if (res == 0) { - return _this.compare(a.title.formatted.trim(), b.title.formatted.trim()); - } - else { - return res; - } - }), - title: heading, - }; - }; - MyPlugin.prototype.sortLengthOfLine = function () { - var lines = this.getLines(); - if (lines.length === 0) - return; - lines.sort(function (a, b) { return a.formatted.length - b.formatted.length; }); - this.setLines(lines); - }; - MyPlugin.prototype.permuteReverse = function () { - var lines = this.getLines(); - if (lines.length === 0) - return; - lines.reverse(); - this.setLines(lines); - }; - MyPlugin.prototype.permuteShuffle = function () { - var lines = this.getLines(); - if (lines.length === 0) - return; - lines.shuffle(); - this.setLines(lines); - }; - MyPlugin.prototype.getLines = function (fromCurrentList, ignoreCheckboxes) { - var _a, _b; - if (fromCurrentList === void 0) { fromCurrentList = false; } - if (ignoreCheckboxes === void 0) { ignoreCheckboxes = true; } - var view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView); - if (!view) - return; - var editor = view.editor; - var file = view.file; - var lines = editor.getValue().split("\n"); - var cache = this.app.metadataCache.getFileCache(file); - var _c = this.getPosition(view, fromCurrentList), start = _c.start, end = _c.end; - var headings = cache.headings; - var links = __spreadArrays((_a = cache === null || cache === void 0 ? void 0 : cache.links) !== null && _a !== void 0 ? _a : [], (_b = cache === null || cache === void 0 ? void 0 : cache.embeds) !== null && _b !== void 0 ? _b : []); - var myLines = lines.map(function (line, index) { - var myLine = { source: line, formatted: line, headingLevel: undefined, lineNumber: index }; - links.forEach(function (e) { - if (e.position.start.line != index) - return; - var start = e.position.start; - var end = e.position.end; - myLine.formatted = myLine.formatted.replace(line.substring(start.col, end.col), e.displayText); - }); - // Regex of cehckbox styles - if (ignoreCheckboxes) { - myLine.formatted = myLine.formatted.replace(checkboxRegex, "$1"); - } - else { - // Just a little bit dirty... - myLine.formatted = myLine.formatted.replace(checkboxRegex, "$1ZZZZZZZZZZZZZZZZZZZZZZZZZ"); - } - return myLine; - }); - headings === null || headings === void 0 ? void 0 : headings.map(function (heading) { return myLines[heading.position.start.line].headingLevel = heading.level; }); - if (start != end) { - return myLines.slice(start, end + 1); - } - else { - return myLines; - } - }; - MyPlugin.prototype.setLines = function (lines, fromCurrentList) { - if (fromCurrentList === void 0) { fromCurrentList = false; } - var view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView); - var res = this.getPosition(view, fromCurrentList); - var editor = view.editor; - if (res.start != res.end) { - editor.replaceRange(lines.map(function (e) { return e.source; }).join("\n"), { line: res.start, ch: 0 }, { line: res.end, ch: res.endLineLength }); - } - else { - editor.setValue(lines.map(function (e) { return e.source; }).join("\n")); - } - }; - MyPlugin.prototype.getPosition = function (view, fromCurrentList) { - var _a, _b, _c; - if (fromCurrentList === void 0) { fromCurrentList = false; } - var cache = this.app.metadataCache.getFileCache(view.file); - var editor = view.editor; - var cursorStart = editor.getCursor("from").line; - var cursorEnd = editor.getCursor("to").line; - if (fromCurrentList) { - var list = cache.sections.find(function (e) { - return e.position.start.line <= cursorStart && e.position.end.line >= cursorEnd; - }); - if (list) { - cursorStart = list.position.start.line; - cursorEnd = list.position.end.line; - } - } - var curserEndLineLength = editor.getLine(cursorEnd).length; - var frontStart = ((_c = (_b = (_a = cache.frontmatter) === null || _a === void 0 ? void 0 : _a.position) === null || _b === void 0 ? void 0 : _b.end) === null || _c === void 0 ? void 0 : _c.line) + 1; - if (isNaN(frontStart)) { - frontStart = 0; - } - var frontEnd = editor.lastLine(); - var frontEndLineLength = editor.getLine(frontEnd).length; - if (cursorStart != cursorEnd) { - return { - start: cursorStart, - end: cursorEnd, - endLineLength: curserEndLineLength, - }; - } - else { - return { - start: frontStart, - end: frontEnd, - endLineLength: frontEndLineLength, - }; - } - }; - return MyPlugin; -}(obsidian.Plugin)); - -module.exports = MyPlugin; -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZXMiOlsibm9kZV9tb2R1bGVzL3RzbGliL3RzbGliLmVzNi5qcyIsIm1haW4udHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG5Db3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi5cclxuXHJcblBlcm1pc3Npb24gdG8gdXNlLCBjb3B5LCBtb2RpZnksIGFuZC9vciBkaXN0cmlidXRlIHRoaXMgc29mdHdhcmUgZm9yIGFueVxyXG5wdXJwb3NlIHdpdGggb3Igd2l0aG91dCBmZWUgaXMgaGVyZWJ5IGdyYW50ZWQuXHJcblxyXG5USEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiIEFORCBUSEUgQVVUSE9SIERJU0NMQUlNUyBBTEwgV0FSUkFOVElFUyBXSVRIXHJcblJFR0FSRCBUTyBUSElTIFNPRlRXQVJFIElOQ0xVRElORyBBTEwgSU1QTElFRCBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWVxyXG5BTkQgRklUTkVTUy4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUiBCRSBMSUFCTEUgRk9SIEFOWSBTUEVDSUFMLCBESVJFQ1QsXHJcbklORElSRUNULCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVMgT1IgQU5ZIERBTUFHRVMgV0hBVFNPRVZFUiBSRVNVTFRJTkcgRlJPTVxyXG5MT1NTIE9GIFVTRSwgREFUQSBPUiBQUk9GSVRTLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgTkVHTElHRU5DRSBPUlxyXG5PVEhFUiBUT1JUSU9VUyBBQ1RJT04sIEFSSVNJTkcgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgVVNFIE9SXHJcblBFUkZPUk1BTkNFIE9GIFRISVMgU09GVFdBUkUuXHJcbioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqICovXHJcbi8qIGdsb2JhbCBSZWZsZWN0LCBQcm9taXNlICovXHJcblxyXG52YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uKGQsIGIpIHtcclxuICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcclxuICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XHJcbiAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTsgfTtcclxuICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xyXG59O1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZXh0ZW5kcyhkLCBiKSB7XHJcbiAgICBpZiAodHlwZW9mIGIgIT09IFwiZnVuY3Rpb25cIiAmJiBiICE9PSBudWxsKVxyXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDbGFzcyBleHRlbmRzIHZhbHVlIFwiICsgU3RyaW5nKGIpICsgXCIgaXMgbm90IGEgY29uc3RydWN0b3Igb3IgbnVsbFwiKTtcclxuICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XHJcbiAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cclxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcclxufVxyXG5cclxuZXhwb3J0IHZhciBfX2Fzc2lnbiA9IGZ1bmN0aW9uKCkge1xyXG4gICAgX19hc3NpZ24gPSBPYmplY3QuYXNzaWduIHx8IGZ1bmN0aW9uIF9fYXNzaWduKHQpIHtcclxuICAgICAgICBmb3IgKHZhciBzLCBpID0gMSwgbiA9IGFyZ3VtZW50cy5sZW5ndGg7IGkgPCBuOyBpKyspIHtcclxuICAgICAgICAgICAgcyA9IGFyZ3VtZW50c1tpXTtcclxuICAgICAgICAgICAgZm9yICh2YXIgcCBpbiBzKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHMsIHApKSB0W3BdID0gc1twXTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHQ7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gX19hc3NpZ24uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcmVzdChzLCBlKSB7XHJcbiAgICB2YXIgdCA9IHt9O1xyXG4gICAgZm9yICh2YXIgcCBpbiBzKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHMsIHApICYmIGUuaW5kZXhPZihwKSA8IDApXHJcbiAgICAgICAgdFtwXSA9IHNbcF07XHJcbiAgICBpZiAocyAhPSBudWxsICYmIHR5cGVvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzID09PSBcImZ1bmN0aW9uXCIpXHJcbiAgICAgICAgZm9yICh2YXIgaSA9IDAsIHAgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHMpOyBpIDwgcC5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICBpZiAoZS5pbmRleE9mKHBbaV0pIDwgMCAmJiBPYmplY3QucHJvdG90eXBlLnByb3BlcnR5SXNFbnVtZXJhYmxlLmNhbGwocywgcFtpXSkpXHJcbiAgICAgICAgICAgICAgICB0W3BbaV1dID0gc1twW2ldXTtcclxuICAgICAgICB9XHJcbiAgICByZXR1cm4gdDtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcclxuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XHJcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xyXG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcclxuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3BhcmFtKHBhcmFtSW5kZXgsIGRlY29yYXRvcikge1xyXG4gICAgcmV0dXJuIGZ1bmN0aW9uICh0YXJnZXQsIGtleSkgeyBkZWNvcmF0b3IodGFyZ2V0LCBrZXksIHBhcmFtSW5kZXgpOyB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2VzRGVjb3JhdGUoY3RvciwgZGVzY3JpcHRvckluLCBkZWNvcmF0b3JzLCBjb250ZXh0SW4sIGluaXRpYWxpemVycywgZXh0cmFJbml0aWFsaXplcnMpIHtcclxuICAgIGZ1bmN0aW9uIGFjY2VwdChmKSB7IGlmIChmICE9PSB2b2lkIDAgJiYgdHlwZW9mIGYgIT09IFwiZnVuY3Rpb25cIikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkZ1bmN0aW9uIGV4cGVjdGVkXCIpOyByZXR1cm4gZjsgfVxyXG4gICAgdmFyIGtpbmQgPSBjb250ZXh0SW4ua2luZCwga2V5ID0ga2luZCA9PT0gXCJnZXR0ZXJcIiA/IFwiZ2V0XCIgOiBraW5kID09PSBcInNldHRlclwiID8gXCJzZXRcIiA6IFwidmFsdWVcIjtcclxuICAgIHZhciB0YXJnZXQgPSAhZGVzY3JpcHRvckluICYmIGN0b3IgPyBjb250ZXh0SW5bXCJzdGF0aWNcIl0gPyBjdG9yIDogY3Rvci5wcm90b3R5cGUgOiBudWxsO1xyXG4gICAgdmFyIGRlc2NyaXB0b3IgPSBkZXNjcmlwdG9ySW4gfHwgKHRhcmdldCA/IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBjb250ZXh0SW4ubmFtZSkgOiB7fSk7XHJcbiAgICB2YXIgXywgZG9uZSA9IGZhbHNlO1xyXG4gICAgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcclxuICAgICAgICB2YXIgY29udGV4dCA9IHt9O1xyXG4gICAgICAgIGZvciAodmFyIHAgaW4gY29udGV4dEluKSBjb250ZXh0W3BdID0gcCA9PT0gXCJhY2Nlc3NcIiA/IHt9IDogY29udGV4dEluW3BdO1xyXG4gICAgICAgIGZvciAodmFyIHAgaW4gY29udGV4dEluLmFjY2VzcykgY29udGV4dC5hY2Nlc3NbcF0gPSBjb250ZXh0SW4uYWNjZXNzW3BdO1xyXG4gICAgICAgIGNvbnRleHQuYWRkSW5pdGlhbGl6ZXIgPSBmdW5jdGlvbiAoZikgeyBpZiAoZG9uZSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCBhZGQgaW5pdGlhbGl6ZXJzIGFmdGVyIGRlY29yYXRpb24gaGFzIGNvbXBsZXRlZFwiKTsgZXh0cmFJbml0aWFsaXplcnMucHVzaChhY2NlcHQoZiB8fCBudWxsKSk7IH07XHJcbiAgICAgICAgdmFyIHJlc3VsdCA9ICgwLCBkZWNvcmF0b3JzW2ldKShraW5kID09PSBcImFjY2Vzc29yXCIgPyB7IGdldDogZGVzY3JpcHRvci5nZXQsIHNldDogZGVzY3JpcHRvci5zZXQgfSA6IGRlc2NyaXB0b3Jba2V5XSwgY29udGV4dCk7XHJcbiAgICAgICAgaWYgKGtpbmQgPT09IFwiYWNjZXNzb3JcIikge1xyXG4gICAgICAgICAgICBpZiAocmVzdWx0ID09PSB2b2lkIDApIGNvbnRpbnVlO1xyXG4gICAgICAgICAgICBpZiAocmVzdWx0ID09PSBudWxsIHx8IHR5cGVvZiByZXN1bHQgIT09IFwib2JqZWN0XCIpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJPYmplY3QgZXhwZWN0ZWRcIik7XHJcbiAgICAgICAgICAgIGlmIChfID0gYWNjZXB0KHJlc3VsdC5nZXQpKSBkZXNjcmlwdG9yLmdldCA9IF87XHJcbiAgICAgICAgICAgIGlmIChfID0gYWNjZXB0KHJlc3VsdC5zZXQpKSBkZXNjcmlwdG9yLnNldCA9IF87XHJcbiAgICAgICAgICAgIGlmIChfID0gYWNjZXB0KHJlc3VsdC5pbml0KSkgaW5pdGlhbGl6ZXJzLnB1c2goXyk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGVsc2UgaWYgKF8gPSBhY2NlcHQocmVzdWx0KSkge1xyXG4gICAgICAgICAgICBpZiAoa2luZCA9PT0gXCJmaWVsZFwiKSBpbml0aWFsaXplcnMucHVzaChfKTtcclxuICAgICAgICAgICAgZWxzZSBkZXNjcmlwdG9yW2tleV0gPSBfO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuICAgIGlmICh0YXJnZXQpIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGNvbnRleHRJbi5uYW1lLCBkZXNjcmlwdG9yKTtcclxuICAgIGRvbmUgPSB0cnVlO1xyXG59O1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcnVuSW5pdGlhbGl6ZXJzKHRoaXNBcmcsIGluaXRpYWxpemVycywgdmFsdWUpIHtcclxuICAgIHZhciB1c2VWYWx1ZSA9IGFyZ3VtZW50cy5sZW5ndGggPiAyO1xyXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbml0aWFsaXplcnMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICB2YWx1ZSA9IHVzZVZhbHVlID8gaW5pdGlhbGl6ZXJzW2ldLmNhbGwodGhpc0FyZywgdmFsdWUpIDogaW5pdGlhbGl6ZXJzW2ldLmNhbGwodGhpc0FyZyk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdXNlVmFsdWUgPyB2YWx1ZSA6IHZvaWQgMDtcclxufTtcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3Byb3BLZXkoeCkge1xyXG4gICAgcmV0dXJuIHR5cGVvZiB4ID09PSBcInN5bWJvbFwiID8geCA6IFwiXCIuY29uY2F0KHgpO1xyXG59O1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fc2V0RnVuY3Rpb25OYW1lKGYsIG5hbWUsIHByZWZpeCkge1xyXG4gICAgaWYgKHR5cGVvZiBuYW1lID09PSBcInN5bWJvbFwiKSBuYW1lID0gbmFtZS5kZXNjcmlwdGlvbiA/IFwiW1wiLmNvbmNhdChuYW1lLmRlc2NyaXB0aW9uLCBcIl1cIikgOiBcIlwiO1xyXG4gICAgcmV0dXJuIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShmLCBcIm5hbWVcIiwgeyBjb25maWd1cmFibGU6IHRydWUsIHZhbHVlOiBwcmVmaXggPyBcIlwiLmNvbmNhdChwcmVmaXgsIFwiIFwiLCBuYW1lKSA6IG5hbWUgfSk7XHJcbn07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19tZXRhZGF0YShtZXRhZGF0YUtleSwgbWV0YWRhdGFWYWx1ZSkge1xyXG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0Lm1ldGFkYXRhID09PSBcImZ1bmN0aW9uXCIpIHJldHVybiBSZWZsZWN0Lm1ldGFkYXRhKG1ldGFkYXRhS2V5LCBtZXRhZGF0YVZhbHVlKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXdhaXRlcih0aGlzQXJnLCBfYXJndW1lbnRzLCBQLCBnZW5lcmF0b3IpIHtcclxuICAgIGZ1bmN0aW9uIGFkb3B0KHZhbHVlKSB7IHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFAgPyB2YWx1ZSA6IG5ldyBQKGZ1bmN0aW9uIChyZXNvbHZlKSB7IHJlc29sdmUodmFsdWUpOyB9KTsgfVxyXG4gICAgcmV0dXJuIG5ldyAoUCB8fCAoUCA9IFByb21pc2UpKShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XHJcbiAgICAgICAgZnVuY3Rpb24gZnVsZmlsbGVkKHZhbHVlKSB7IHRyeSB7IHN0ZXAoZ2VuZXJhdG9yLm5leHQodmFsdWUpKTsgfSBjYXRjaCAoZSkgeyByZWplY3QoZSk7IH0gfVxyXG4gICAgICAgIGZ1bmN0aW9uIHJlamVjdGVkKHZhbHVlKSB7IHRyeSB7IHN0ZXAoZ2VuZXJhdG9yW1widGhyb3dcIl0odmFsdWUpKTsgfSBjYXRjaCAoZSkgeyByZWplY3QoZSk7IH0gfVxyXG4gICAgICAgIGZ1bmN0aW9uIHN0ZXAocmVzdWx0KSB7IHJlc3VsdC5kb25lID8gcmVzb2x2ZShyZXN1bHQudmFsdWUpIDogYWRvcHQocmVzdWx0LnZhbHVlKS50aGVuKGZ1bGZpbGxlZCwgcmVqZWN0ZWQpOyB9XHJcbiAgICAgICAgc3RlcCgoZ2VuZXJhdG9yID0gZ2VuZXJhdG9yLmFwcGx5KHRoaXNBcmcsIF9hcmd1bWVudHMgfHwgW10pKS5uZXh0KCkpO1xyXG4gICAgfSk7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2dlbmVyYXRvcih0aGlzQXJnLCBib2R5KSB7XHJcbiAgICB2YXIgXyA9IHsgbGFiZWw6IDAsIHNlbnQ6IGZ1bmN0aW9uKCkgeyBpZiAodFswXSAmIDEpIHRocm93IHRbMV07IHJldHVybiB0WzFdOyB9LCB0cnlzOiBbXSwgb3BzOiBbXSB9LCBmLCB5LCB0LCBnO1xyXG4gICAgcmV0dXJuIGcgPSB7IG5leHQ6IHZlcmIoMCksIFwidGhyb3dcIjogdmVyYigxKSwgXCJyZXR1cm5cIjogdmVyYigyKSB9LCB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgKGdbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpczsgfSksIGc7XHJcbiAgICBmdW5jdGlvbiB2ZXJiKG4pIHsgcmV0dXJuIGZ1bmN0aW9uICh2KSB7IHJldHVybiBzdGVwKFtuLCB2XSk7IH07IH1cclxuICAgIGZ1bmN0aW9uIHN0ZXAob3ApIHtcclxuICAgICAgICBpZiAoZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkdlbmVyYXRvciBpcyBhbHJlYWR5IGV4ZWN1dGluZy5cIik7XHJcbiAgICAgICAgd2hpbGUgKGcgJiYgKGcgPSAwLCBvcFswXSAmJiAoXyA9IDApKSwgXykgdHJ5IHtcclxuICAgICAgICAgICAgaWYgKGYgPSAxLCB5ICYmICh0ID0gb3BbMF0gJiAyID8geVtcInJldHVyblwiXSA6IG9wWzBdID8geVtcInRocm93XCJdIHx8ICgodCA9IHlbXCJyZXR1cm5cIl0pICYmIHQuY2FsbCh5KSwgMCkgOiB5Lm5leHQpICYmICEodCA9IHQuY2FsbCh5LCBvcFsxXSkpLmRvbmUpIHJldHVybiB0O1xyXG4gICAgICAgICAgICBpZiAoeSA9IDAsIHQpIG9wID0gW29wWzBdICYgMiwgdC52YWx1ZV07XHJcbiAgICAgICAgICAgIHN3aXRjaCAob3BbMF0pIHtcclxuICAgICAgICAgICAgICAgIGNhc2UgMDogY2FzZSAxOiB0ID0gb3A7IGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgY2FzZSA0OiBfLmxhYmVsKys7IHJldHVybiB7IHZhbHVlOiBvcFsxXSwgZG9uZTogZmFsc2UgfTtcclxuICAgICAgICAgICAgICAgIGNhc2UgNTogXy5sYWJlbCsrOyB5ID0gb3BbMV07IG9wID0gWzBdOyBjb250aW51ZTtcclxuICAgICAgICAgICAgICAgIGNhc2UgNzogb3AgPSBfLm9wcy5wb3AoKTsgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcclxuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEodCA9IF8udHJ5cywgdCA9IHQubGVuZ3RoID4gMCAmJiB0W3QubGVuZ3RoIC0gMV0pICYmIChvcFswXSA9PT0gNiB8fCBvcFswXSA9PT0gMikpIHsgXyA9IDA7IGNvbnRpbnVlOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSAzICYmICghdCB8fCAob3BbMV0gPiB0WzBdICYmIG9wWzFdIDwgdFszXSkpKSB7IF8ubGFiZWwgPSBvcFsxXTsgYnJlYWs7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDYgJiYgXy5sYWJlbCA8IHRbMV0pIHsgXy5sYWJlbCA9IHRbMV07IHQgPSBvcDsgYnJlYWs7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAodCAmJiBfLmxhYmVsIDwgdFsyXSkgeyBfLmxhYmVsID0gdFsyXTsgXy5vcHMucHVzaChvcCk7IGJyZWFrOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRbMl0pIF8ub3BzLnBvcCgpO1xyXG4gICAgICAgICAgICAgICAgICAgIF8udHJ5cy5wb3AoKTsgY29udGludWU7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgb3AgPSBib2R5LmNhbGwodGhpc0FyZywgXyk7XHJcbiAgICAgICAgfSBjYXRjaCAoZSkgeyBvcCA9IFs2LCBlXTsgeSA9IDA7IH0gZmluYWxseSB7IGYgPSB0ID0gMDsgfVxyXG4gICAgICAgIGlmIChvcFswXSAmIDUpIHRocm93IG9wWzFdOyByZXR1cm4geyB2YWx1ZTogb3BbMF0gPyBvcFsxXSA6IHZvaWQgMCwgZG9uZTogdHJ1ZSB9O1xyXG4gICAgfVxyXG59XHJcblxyXG5leHBvcnQgdmFyIF9fY3JlYXRlQmluZGluZyA9IE9iamVjdC5jcmVhdGUgPyAoZnVuY3Rpb24obywgbSwgaywgazIpIHtcclxuICAgIGlmIChrMiA9PT0gdW5kZWZpbmVkKSBrMiA9IGs7XHJcbiAgICB2YXIgZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IobSwgayk7XHJcbiAgICBpZiAoIWRlc2MgfHwgKFwiZ2V0XCIgaW4gZGVzYyA/ICFtLl9fZXNNb2R1bGUgOiBkZXNjLndyaXRhYmxlIHx8IGRlc2MuY29uZmlndXJhYmxlKSkge1xyXG4gICAgICAgIGRlc2MgPSB7IGVudW1lcmFibGU6IHRydWUsIGdldDogZnVuY3Rpb24oKSB7IHJldHVybiBtW2tdOyB9IH07XHJcbiAgICB9XHJcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkobywgazIsIGRlc2MpO1xyXG59KSA6IChmdW5jdGlvbihvLCBtLCBrLCBrMikge1xyXG4gICAgaWYgKGsyID09PSB1bmRlZmluZWQpIGsyID0gaztcclxuICAgIG9bazJdID0gbVtrXTtcclxufSk7XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19leHBvcnRTdGFyKG0sIG8pIHtcclxuICAgIGZvciAodmFyIHAgaW4gbSkgaWYgKHAgIT09IFwiZGVmYXVsdFwiICYmICFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwobywgcCkpIF9fY3JlYXRlQmluZGluZyhvLCBtLCBwKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fdmFsdWVzKG8pIHtcclxuICAgIHZhciBzID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIFN5bWJvbC5pdGVyYXRvciwgbSA9IHMgJiYgb1tzXSwgaSA9IDA7XHJcbiAgICBpZiAobSkgcmV0dXJuIG0uY2FsbChvKTtcclxuICAgIGlmIChvICYmIHR5cGVvZiBvLmxlbmd0aCA9PT0gXCJudW1iZXJcIikgcmV0dXJuIHtcclxuICAgICAgICBuZXh0OiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIGlmIChvICYmIGkgPj0gby5sZW5ndGgpIG8gPSB2b2lkIDA7XHJcbiAgICAgICAgICAgIHJldHVybiB7IHZhbHVlOiBvICYmIG9baSsrXSwgZG9uZTogIW8gfTtcclxuICAgICAgICB9XHJcbiAgICB9O1xyXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihzID8gXCJPYmplY3QgaXMgbm90IGl0ZXJhYmxlLlwiIDogXCJTeW1ib2wuaXRlcmF0b3IgaXMgbm90IGRlZmluZWQuXCIpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19yZWFkKG8sIG4pIHtcclxuICAgIHZhciBtID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIG9bU3ltYm9sLml0ZXJhdG9yXTtcclxuICAgIGlmICghbSkgcmV0dXJuIG87XHJcbiAgICB2YXIgaSA9IG0uY2FsbChvKSwgciwgYXIgPSBbXSwgZTtcclxuICAgIHRyeSB7XHJcbiAgICAgICAgd2hpbGUgKChuID09PSB2b2lkIDAgfHwgbi0tID4gMCkgJiYgIShyID0gaS5uZXh0KCkpLmRvbmUpIGFyLnB1c2goci52YWx1ZSk7XHJcbiAgICB9XHJcbiAgICBjYXRjaCAoZXJyb3IpIHsgZSA9IHsgZXJyb3I6IGVycm9yIH07IH1cclxuICAgIGZpbmFsbHkge1xyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIGlmIChyICYmICFyLmRvbmUgJiYgKG0gPSBpW1wicmV0dXJuXCJdKSkgbS5jYWxsKGkpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBmaW5hbGx5IHsgaWYgKGUpIHRocm93IGUuZXJyb3I7IH1cclxuICAgIH1cclxuICAgIHJldHVybiBhcjtcclxufVxyXG5cclxuLyoqIEBkZXByZWNhdGVkICovXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3NwcmVhZCgpIHtcclxuICAgIGZvciAodmFyIGFyID0gW10sIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKVxyXG4gICAgICAgIGFyID0gYXIuY29uY2F0KF9fcmVhZChhcmd1bWVudHNbaV0pKTtcclxuICAgIHJldHVybiBhcjtcclxufVxyXG5cclxuLyoqIEBkZXByZWNhdGVkICovXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3NwcmVhZEFycmF5cygpIHtcclxuICAgIGZvciAodmFyIHMgPSAwLCBpID0gMCwgaWwgPSBhcmd1bWVudHMubGVuZ3RoOyBpIDwgaWw7IGkrKykgcyArPSBhcmd1bWVudHNbaV0ubGVuZ3RoO1xyXG4gICAgZm9yICh2YXIgciA9IEFycmF5KHMpLCBrID0gMCwgaSA9IDA7IGkgPCBpbDsgaSsrKVxyXG4gICAgICAgIGZvciAodmFyIGEgPSBhcmd1bWVudHNbaV0sIGogPSAwLCBqbCA9IGEubGVuZ3RoOyBqIDwgamw7IGorKywgaysrKVxyXG4gICAgICAgICAgICByW2tdID0gYVtqXTtcclxuICAgIHJldHVybiByO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19zcHJlYWRBcnJheSh0bywgZnJvbSwgcGFjaykge1xyXG4gICAgaWYgKHBhY2sgfHwgYXJndW1lbnRzLmxlbmd0aCA9PT0gMikgZm9yICh2YXIgaSA9IDAsIGwgPSBmcm9tLmxlbmd0aCwgYXI7IGkgPCBsOyBpKyspIHtcclxuICAgICAgICBpZiAoYXIgfHwgIShpIGluIGZyb20pKSB7XHJcbiAgICAgICAgICAgIGlmICghYXIpIGFyID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoZnJvbSwgMCwgaSk7XHJcbiAgICAgICAgICAgIGFyW2ldID0gZnJvbVtpXTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdG8uY29uY2F0KGFyIHx8IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGZyb20pKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXdhaXQodikge1xyXG4gICAgcmV0dXJuIHRoaXMgaW5zdGFuY2VvZiBfX2F3YWl0ID8gKHRoaXMudiA9IHYsIHRoaXMpIDogbmV3IF9fYXdhaXQodik7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2FzeW5jR2VuZXJhdG9yKHRoaXNBcmcsIF9hcmd1bWVudHMsIGdlbmVyYXRvcikge1xyXG4gICAgaWYgKCFTeW1ib2wuYXN5bmNJdGVyYXRvcikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN5bWJvbC5hc3luY0l0ZXJhdG9yIGlzIG5vdCBkZWZpbmVkLlwiKTtcclxuICAgIHZhciBnID0gZ2VuZXJhdG9yLmFwcGx5KHRoaXNBcmcsIF9hcmd1bWVudHMgfHwgW10pLCBpLCBxID0gW107XHJcbiAgICByZXR1cm4gaSA9IHt9LCB2ZXJiKFwibmV4dFwiKSwgdmVyYihcInRocm93XCIpLCB2ZXJiKFwicmV0dXJuXCIpLCBpW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0sIGk7XHJcbiAgICBmdW5jdGlvbiB2ZXJiKG4pIHsgaWYgKGdbbl0pIGlbbl0gPSBmdW5jdGlvbiAodikgeyByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKGEsIGIpIHsgcS5wdXNoKFtuLCB2LCBhLCBiXSkgPiAxIHx8IHJlc3VtZShuLCB2KTsgfSk7IH07IH1cclxuICAgIGZ1bmN0aW9uIHJlc3VtZShuLCB2KSB7IHRyeSB7IHN0ZXAoZ1tuXSh2KSk7IH0gY2F0Y2ggKGUpIHsgc2V0dGxlKHFbMF1bM10sIGUpOyB9IH1cclxuICAgIGZ1bmN0aW9uIHN0ZXAocikgeyByLnZhbHVlIGluc3RhbmNlb2YgX19hd2FpdCA/IFByb21pc2UucmVzb2x2ZShyLnZhbHVlLnYpLnRoZW4oZnVsZmlsbCwgcmVqZWN0KSA6IHNldHRsZShxWzBdWzJdLCByKTsgfVxyXG4gICAgZnVuY3Rpb24gZnVsZmlsbCh2YWx1ZSkgeyByZXN1bWUoXCJuZXh0XCIsIHZhbHVlKTsgfVxyXG4gICAgZnVuY3Rpb24gcmVqZWN0KHZhbHVlKSB7IHJlc3VtZShcInRocm93XCIsIHZhbHVlKTsgfVxyXG4gICAgZnVuY3Rpb24gc2V0dGxlKGYsIHYpIHsgaWYgKGYodiksIHEuc2hpZnQoKSwgcS5sZW5ndGgpIHJlc3VtZShxWzBdWzBdLCBxWzBdWzFdKTsgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19hc3luY0RlbGVnYXRvcihvKSB7XHJcbiAgICB2YXIgaSwgcDtcclxuICAgIHJldHVybiBpID0ge30sIHZlcmIoXCJuZXh0XCIpLCB2ZXJiKFwidGhyb3dcIiwgZnVuY3Rpb24gKGUpIHsgdGhyb3cgZTsgfSksIHZlcmIoXCJyZXR1cm5cIiksIGlbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0sIGk7XHJcbiAgICBmdW5jdGlvbiB2ZXJiKG4sIGYpIHsgaVtuXSA9IG9bbl0gPyBmdW5jdGlvbiAodikgeyByZXR1cm4gKHAgPSAhcCkgPyB7IHZhbHVlOiBfX2F3YWl0KG9bbl0odikpLCBkb25lOiBmYWxzZSB9IDogZiA/IGYodikgOiB2OyB9IDogZjsgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19hc3luY1ZhbHVlcyhvKSB7XHJcbiAgICBpZiAoIVN5bWJvbC5hc3luY0l0ZXJhdG9yKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiU3ltYm9sLmFzeW5jSXRlcmF0b3IgaXMgbm90IGRlZmluZWQuXCIpO1xyXG4gICAgdmFyIG0gPSBvW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSwgaTtcclxuICAgIHJldHVybiBtID8gbS5jYWxsKG8pIDogKG8gPSB0eXBlb2YgX192YWx1ZXMgPT09IFwiZnVuY3Rpb25cIiA/IF9fdmFsdWVzKG8pIDogb1tTeW1ib2wuaXRlcmF0b3JdKCksIGkgPSB7fSwgdmVyYihcIm5leHRcIiksIHZlcmIoXCJ0aHJvd1wiKSwgdmVyYihcInJldHVyblwiKSwgaVtTeW1ib2wuYXN5bmNJdGVyYXRvcl0gPSBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzOyB9LCBpKTtcclxuICAgIGZ1bmN0aW9uIHZlcmIobikgeyBpW25dID0gb1tuXSAmJiBmdW5jdGlvbiAodikgeyByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkgeyB2ID0gb1tuXSh2KSwgc2V0dGxlKHJlc29sdmUsIHJlamVjdCwgdi5kb25lLCB2LnZhbHVlKTsgfSk7IH07IH1cclxuICAgIGZ1bmN0aW9uIHNldHRsZShyZXNvbHZlLCByZWplY3QsIGQsIHYpIHsgUHJvbWlzZS5yZXNvbHZlKHYpLnRoZW4oZnVuY3Rpb24odikgeyByZXNvbHZlKHsgdmFsdWU6IHYsIGRvbmU6IGQgfSk7IH0sIHJlamVjdCk7IH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fbWFrZVRlbXBsYXRlT2JqZWN0KGNvb2tlZCwgcmF3KSB7XHJcbiAgICBpZiAoT2JqZWN0LmRlZmluZVByb3BlcnR5KSB7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eShjb29rZWQsIFwicmF3XCIsIHsgdmFsdWU6IHJhdyB9KTsgfSBlbHNlIHsgY29va2VkLnJhdyA9IHJhdzsgfVxyXG4gICAgcmV0dXJuIGNvb2tlZDtcclxufTtcclxuXHJcbnZhciBfX3NldE1vZHVsZURlZmF1bHQgPSBPYmplY3QuY3JlYXRlID8gKGZ1bmN0aW9uKG8sIHYpIHtcclxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvLCBcImRlZmF1bHRcIiwgeyBlbnVtZXJhYmxlOiB0cnVlLCB2YWx1ZTogdiB9KTtcclxufSkgOiBmdW5jdGlvbihvLCB2KSB7XHJcbiAgICBvW1wiZGVmYXVsdFwiXSA9IHY7XHJcbn07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19pbXBvcnRTdGFyKG1vZCkge1xyXG4gICAgaWYgKG1vZCAmJiBtb2QuX19lc01vZHVsZSkgcmV0dXJuIG1vZDtcclxuICAgIHZhciByZXN1bHQgPSB7fTtcclxuICAgIGlmIChtb2QgIT0gbnVsbCkgZm9yICh2YXIgayBpbiBtb2QpIGlmIChrICE9PSBcImRlZmF1bHRcIiAmJiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwobW9kLCBrKSkgX19jcmVhdGVCaW5kaW5nKHJlc3VsdCwgbW9kLCBrKTtcclxuICAgIF9fc2V0TW9kdWxlRGVmYXVsdChyZXN1bHQsIG1vZCk7XHJcbiAgICByZXR1cm4gcmVzdWx0O1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19pbXBvcnREZWZhdWx0KG1vZCkge1xyXG4gICAgcmV0dXJuIChtb2QgJiYgbW9kLl9fZXNNb2R1bGUpID8gbW9kIDogeyBkZWZhdWx0OiBtb2QgfTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fY2xhc3NQcml2YXRlRmllbGRHZXQocmVjZWl2ZXIsIHN0YXRlLCBraW5kLCBmKSB7XHJcbiAgICBpZiAoa2luZCA9PT0gXCJhXCIgJiYgIWYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIGFjY2Vzc29yIHdhcyBkZWZpbmVkIHdpdGhvdXQgYSBnZXR0ZXJcIik7XHJcbiAgICBpZiAodHlwZW9mIHN0YXRlID09PSBcImZ1bmN0aW9uXCIgPyByZWNlaXZlciAhPT0gc3RhdGUgfHwgIWYgOiAhc3RhdGUuaGFzKHJlY2VpdmVyKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCByZWFkIHByaXZhdGUgbWVtYmVyIGZyb20gYW4gb2JqZWN0IHdob3NlIGNsYXNzIGRpZCBub3QgZGVjbGFyZSBpdFwiKTtcclxuICAgIHJldHVybiBraW5kID09PSBcIm1cIiA/IGYgOiBraW5kID09PSBcImFcIiA/IGYuY2FsbChyZWNlaXZlcikgOiBmID8gZi52YWx1ZSA6IHN0YXRlLmdldChyZWNlaXZlcik7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KHJlY2VpdmVyLCBzdGF0ZSwgdmFsdWUsIGtpbmQsIGYpIHtcclxuICAgIGlmIChraW5kID09PSBcIm1cIikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgbWV0aG9kIGlzIG5vdCB3cml0YWJsZVwiKTtcclxuICAgIGlmIChraW5kID09PSBcImFcIiAmJiAhZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgYWNjZXNzb3Igd2FzIGRlZmluZWQgd2l0aG91dCBhIHNldHRlclwiKTtcclxuICAgIGlmICh0eXBlb2Ygc3RhdGUgPT09IFwiZnVuY3Rpb25cIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZiA6ICFzdGF0ZS5oYXMocmVjZWl2ZXIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHdyaXRlIHByaXZhdGUgbWVtYmVyIHRvIGFuIG9iamVjdCB3aG9zZSBjbGFzcyBkaWQgbm90IGRlY2xhcmUgaXRcIik7XHJcbiAgICByZXR1cm4gKGtpbmQgPT09IFwiYVwiID8gZi5jYWxsKHJlY2VpdmVyLCB2YWx1ZSkgOiBmID8gZi52YWx1ZSA9IHZhbHVlIDogc3RhdGUuc2V0KHJlY2VpdmVyLCB2YWx1ZSkpLCB2YWx1ZTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fY2xhc3NQcml2YXRlRmllbGRJbihzdGF0ZSwgcmVjZWl2ZXIpIHtcclxuICAgIGlmIChyZWNlaXZlciA9PT0gbnVsbCB8fCAodHlwZW9mIHJlY2VpdmVyICE9PSBcIm9iamVjdFwiICYmIHR5cGVvZiByZWNlaXZlciAhPT0gXCJmdW5jdGlvblwiKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCB1c2UgJ2luJyBvcGVyYXRvciBvbiBub24tb2JqZWN0XCIpO1xyXG4gICAgcmV0dXJuIHR5cGVvZiBzdGF0ZSA9PT0gXCJmdW5jdGlvblwiID8gcmVjZWl2ZXIgPT09IHN0YXRlIDogc3RhdGUuaGFzKHJlY2VpdmVyKTtcclxufVxyXG4iLCJpbXBvcnQgeyBMaXN0SXRlbUNhY2hlLCBNYXJrZG93blZpZXcsIFBsdWdpbiB9IGZyb20gJ29ic2lkaWFuJztcblxuaW50ZXJmYWNlIHNvcnRNZXRob2Qge1xuXHQoeDogc3RyaW5nLCB5OiBzdHJpbmcpOiBudW1iZXI7XG59XG5cbmludGVyZmFjZSBNeUxpbmUge1xuXHRzb3VyY2U6IHN0cmluZztcblx0Zm9ybWF0dGVkOiBzdHJpbmc7XG5cdGhlYWRpbmdMZXZlbDogbnVtYmVyIHwgdW5kZWZpbmVkO1xuXHRsaW5lTnVtYmVyOiBudW1iZXI7XG59XG5cbmludGVyZmFjZSBIZWFkaW5nUGFydCB7XG5cdHRvOiBudW1iZXI7XG5cdHRpdGxlOiBNeUxpbmU7XG5cdGxpbmVzOiBNeUxpbmVbXTtcblx0aGVhZGluZ3M6IEhlYWRpbmdQYXJ0W107XG59XG5cbmludGVyZmFjZSBMaXN0UGFydCB7XG5cdGNoaWxkcmVuOiBMaXN0UGFydFtdO1xuXHR0aXRsZTogTXlMaW5lO1xuXHRsYXN0TGluZTogbnVtYmVyO1xufVxuY29uc3QgY2hlY2tib3hSZWdleCA9IC9eKFxccyopLSBcXFtbXiBdXFxdL2dpO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBNeVBsdWdpbiBleHRlbmRzIFBsdWdpbiB7XG5cdGNvbXBhcmU6IHNvcnRNZXRob2Q7XG5cdGFzeW5jIG9ubG9hZCgpIHtcblx0XHRjb25zb2xlLmxvZygnbG9hZGluZyAnICsgdGhpcy5tYW5pZmVzdC5uYW1lKTtcblxuXHRcdGNvbnN0IHsgY29tcGFyZSB9ID0gbmV3IEludGwuQ29sbGF0b3IobmF2aWdhdG9yLmxhbmd1YWdlLCB7XG5cdFx0XHR1c2FnZTogJ3NvcnQnLFxuXHRcdFx0c2Vuc2l0aXZpdHk6ICdiYXNlJyxcblx0XHRcdG51bWVyaWM6IHRydWUsXG5cdFx0XHRpZ25vcmVQdW5jdHVhdGlvbjogdHJ1ZSxcblx0XHR9KTtcblx0XHR0aGlzLmNvbXBhcmUgPSBjb21wYXJlO1xuXHRcdHRoaXMuYWRkQ29tbWFuZCh7XG5cdFx0XHRpZDogJ3NvcnQtYWxwaGFiZXRpY2FsbHktd2l0aC1jaGVja2JveGVzJyxcblx0XHRcdG5hbWU6ICdTb3J0IGFscGhhYmV0aWNhbGx5IHdpdGggY2hlY2tib3hlcycsXG5cdFx0XHRjYWxsYmFjazogKCgpID0+IHRoaXMuc29ydEFscGhhYmV0aWNhbGx5KGZhbHNlLCBmYWxzZSkpLFxuXHRcdH0pO1xuXHRcdHRoaXMuYWRkQ29tbWFuZCh7XG5cdFx0XHRpZDogJ3NvcnQtbGlzdC1hbHBoYWJldGljYWxseS13aXRoLWNoZWNrYm94ZXMnLFxuXHRcdFx0bmFtZTogJ1NvcnQgY3VycmVudCBsaXN0IGFscGhhYmV0aWNhbGx5IHdpdGggY2hlY2tib3hlcycsXG5cdFx0XHRjYWxsYmFjazogKCgpID0+IHRoaXMuc29ydEFscGhhYmV0aWNhbGx5KHRydWUsIGZhbHNlKSksXG5cdFx0fSk7XG5cdFx0dGhpcy5hZGRDb21tYW5kKHtcblx0XHRcdGlkOiAnc29ydC1hbHBoYWJldGljYWxseScsXG5cdFx0XHRuYW1lOiAnU29ydCBhbHBoYWJldGljYWxseScsXG5cdFx0XHRjYWxsYmFjazogKCgpID0+IHRoaXMuc29ydEFscGhhYmV0aWNhbGx5KGZhbHNlLCB0cnVlKSksXG5cdFx0fSk7XG5cdFx0dGhpcy5hZGRDb21tYW5kKHtcblx0XHRcdGlkOiAnc29ydC1saXN0LWFscGhhYmV0aWNhbGx5Jyxcblx0XHRcdG5hbWU6ICdTb3J0IGN1cnJlbnQgbGlzdCBhbHBoYWJldGljYWxseScsXG5cdFx0XHRjYWxsYmFjazogKCgpID0+IHRoaXMuc29ydEFscGhhYmV0aWNhbGx5KHRydWUsIHRydWUpKSxcblx0XHR9KTtcblx0XHR0aGlzLmFkZENvbW1hbmQoe1xuXHRcdFx0aWQ6ICdzb3J0LWNoZWNrYm94ZXMnLFxuXHRcdFx0bmFtZTogJ1NvcnQgY3VycmVudCBsaXN0IGJ5IGNoZWNrYm94ZXMnLFxuXHRcdFx0Y2FsbGJhY2s6ICgpID0+IHRoaXMuc29ydExpc3RSZWN1cnNpdmVseSh0cnVlLCAoYTogTGlzdFBhcnQsIGI6IExpc3RQYXJ0KSA9PiB7XG5cdFx0XHRcdGlmIChjaGVja2JveFJlZ2V4LnRlc3QoYS50aXRsZS5zb3VyY2UpICYmICFjaGVja2JveFJlZ2V4LnRlc3QoYi50aXRsZS5zb3VyY2UpKSByZXR1cm4gMTtcblx0XHRcdFx0aWYgKCFjaGVja2JveFJlZ2V4LnRlc3QoYS50aXRsZS5zb3VyY2UpICYmIGNoZWNrYm94UmVnZXgudGVzdChiLnRpdGxlLnNvdXJjZSkpIHJldHVybiAtMTtcblx0XHRcdFx0cmV0dXJuIDA7XG5cdFx0XHR9KSxcblx0XHR9KTtcblx0XHR0aGlzLmFkZENvbW1hbmQoe1xuXHRcdFx0aWQ6ICdzb3J0LWxlbmd0aCcsXG5cdFx0XHRuYW1lOiAnU29ydCBieSBsZW5ndGggb2YgbGluZScsXG5cdFx0XHRjYWxsYmFjazogKCgpID0+IHRoaXMuc29ydExlbmd0aE9mTGluZSgpKSxcblx0XHR9KTtcblx0XHR0aGlzLmFkZENvbW1hbmQoe1xuXHRcdFx0aWQ6ICdzb3J0LWhlYWRpbmdzJyxcblx0XHRcdG5hbWU6ICdTb3J0IGhlYWRpbmdzJyxcblx0XHRcdGNhbGxiYWNrOiAoKCkgPT4gdGhpcy5zb3J0SGVhZGluZ3MoKSksXG5cdFx0fSk7XG5cdFx0dGhpcy5hZGRDb21tYW5kKHtcblx0XHRcdGlkOiAncGVybXV0ZS1yZXZlcnNlJyxcblx0XHRcdG5hbWU6ICdSZXZlcnNlIGxpbmVzJyxcblx0XHRcdGNhbGxiYWNrOiAoKCkgPT4gdGhpcy5wZXJtdXRlUmV2ZXJzZSgpKSxcblx0XHR9KTtcblx0XHR0aGlzLmFkZENvbW1hbmQoe1xuXHRcdFx0aWQ6ICdwZXJtdXRlLXNodWZmbGUnLFxuXHRcdFx0bmFtZTogJ1NodWZmbGUgbGluZXMnLFxuXHRcdFx0Y2FsbGJhY2s6ICgoKSA9PiB0aGlzLnBlcm11dGVTaHVmZmxlKCkpLFxuXHRcdH0pO1xuXG5cdFx0Y29uc3QgY29tcCA9IChhOiBMaXN0UGFydCwgYjogTGlzdFBhcnQpID0+IHRoaXMuY29tcGFyZShhLnRpdGxlLmZvcm1hdHRlZC50cmltKCksIGIudGl0bGUuZm9ybWF0dGVkLnRyaW0oKSk7XG5cdFx0dGhpcy5hZGRDb21tYW5kKHtcblx0XHRcdGlkOiAnc29ydC1saXN0LXJlY3Vyc2l2ZWx5Jyxcblx0XHRcdG5hbWU6ICdTb3J0IGN1cnJlbnQgbGlzdCByZWN1cnNpdmVseScsXG5cdFx0XHRjYWxsYmFjazogKCgpID0+IHRoaXMuc29ydExpc3RSZWN1cnNpdmVseSh0cnVlLCBjb21wKSksXG5cdFx0fSk7XG5cdFx0dGhpcy5hZGRDb21tYW5kKHtcblx0XHRcdGlkOiAnc29ydC1saXN0LXJlY3Vyc2l2ZWx5LXdpdGgtY2hlY2tib3hlcycsXG5cdFx0XHRuYW1lOiAnU29ydCBjdXJyZW50IGxpc3QgcmVjdXJzaXZlbHkgd2l0aCBjaGVja2JveGVzJyxcblx0XHRcdGNhbGxiYWNrOiAoKCkgPT4gdGhpcy5zb3J0TGlzdFJlY3Vyc2l2ZWx5KGZhbHNlLCBjb21wKSksXG5cdFx0fSk7XG5cblx0fVxuXG5cdG9udW5sb2FkKCkge1xuXHRcdGNvbnNvbGUubG9nKCd1bmxvYWRpbmcgJyArIHRoaXMubWFuaWZlc3QubmFtZSk7XG5cdH1cblxuXG5cdHNvcnRBbHBoYWJldGljYWxseShmcm9tQ3VycmVudExpc3QgPSBmYWxzZSwgaWdub3JlQ2hlY2tib3hlcyA9IHRydWUpIHtcblx0XHRjb25zdCBsaW5lcyA9IHRoaXMuZ2V0TGluZXMoZnJvbUN1cnJlbnRMaXN0LCBpZ25vcmVDaGVja2JveGVzKTtcblx0XHRpZiAobGluZXMubGVuZ3RoID09PSAwKSByZXR1cm47XG5cdFx0bGV0IHNvcnRGdW5jID0gKGE6IE15TGluZSwgYjogTXlMaW5lKSA9PiB0aGlzLmNvbXBhcmUoYS5mb3JtYXR0ZWQudHJpbSgpLCBiLmZvcm1hdHRlZC50cmltKCkpO1xuXG5cdFx0bGluZXMuc29ydChzb3J0RnVuYyk7XG5cdFx0dGhpcy5zZXRMaW5lcyhsaW5lcywgZnJvbUN1cnJlbnRMaXN0KTtcblx0fVxuXG5cdHNvcnRMaXN0UmVjdXJzaXZlbHkoaWdub3JlQ2hlY2tib3hlczogYm9vbGVhbiwgY29tcGFyZUZuOiAoYTogTGlzdFBhcnQsIGI6IExpc3RQYXJ0KSA9PiBudW1iZXIpIHtcblx0XHRjb25zdCBpbnB1dExpbmVzID0gdGhpcy5nZXRMaW5lcyh0cnVlLCBpZ25vcmVDaGVja2JveGVzKTtcblxuXHRcdGlmIChpbnB1dExpbmVzLmxlbmd0aCA9PT0gMCB8fCBpbnB1dExpbmVzLmZpbmQobGluZSA9PiBsaW5lLnNvdXJjZS50cmltKCkgPT0gXCJcIikpIHJldHVybjtcblx0XHRjb25zdCBmaXJzdExpbmVOdW1iZXIgPSBpbnB1dExpbmVzLmZpcnN0KCkubGluZU51bWJlcjtcblx0XHRjb25zdCBsaW5lcyA9IFsuLi5uZXcgQXJyYXkoZmlyc3RMaW5lTnVtYmVyKS5maWxsKHVuZGVmaW5lZCksIC4uLmlucHV0TGluZXNdO1xuXHRcdGxldCBpbmRleCA9IGZpcnN0TGluZU51bWJlcjtcblxuXHRcdGNvbnN0IGNhY2hlID0gdGhpcy5hcHAubWV0YWRhdGFDYWNoZS5nZXRGaWxlQ2FjaGUodGhpcy5hcHAud29ya3NwYWNlLmdldEFjdGl2ZUZpbGUoKSk7XG5cdFx0Y29uc3QgY2hpbGRyZW46IExpc3RQYXJ0W10gPSBbXTtcblxuXHRcdHdoaWxlIChpbmRleCA8IGxpbmVzLmxlbmd0aCkge1xuXHRcdFx0Y29uc3QgbmV3Q2hpbGQgPSB0aGlzLmdldFNvcnRlZExpc3RQYXJ0cyhsaW5lcywgY2FjaGUubGlzdEl0ZW1zLCBpbmRleCwgY29tcGFyZUZuKTtcblx0XHRcdGNoaWxkcmVuLnB1c2gobmV3Q2hpbGQpO1xuXHRcdFx0aW5kZXggPSBuZXdDaGlsZC5sYXN0TGluZTtcblxuXHRcdFx0aW5kZXgrKztcblx0XHR9XG5cdFx0Y2hpbGRyZW4uc29ydChjb21wYXJlRm4pO1xuXG5cdFx0Y29uc3QgcmVzID0gY2hpbGRyZW4ucmVkdWNlKChhY2MsIGN1cikgPT4gYWNjLmNvbmNhdCh0aGlzLmxpc3RQYXJ0VG9MaXN0KGN1cikpLCBbXSk7XG5cdFx0dGhpcy5zZXRMaW5lcyhyZXMsIHRydWUpO1xuXHR9XG5cblx0Z2V0TGluZUNhY2hlRnJvbUxpbmUobGluZTogbnVtYmVyLCBsaW5lc0NhY2hlOiBMaXN0SXRlbUNhY2hlW10pOiBMaXN0SXRlbUNhY2hlIHwgdW5kZWZpbmVkIHtcblx0XHRyZXR1cm4gbGluZXNDYWNoZS5maW5kKGNhY2hlSXRlbSA9PiBjYWNoZUl0ZW0ucG9zaXRpb24uc3RhcnQubGluZSA9PT0gbGluZSk7XG5cdH1cblxuXHRnZXRTb3J0ZWRMaXN0UGFydHMobGluZXM6IE15TGluZVtdLCBsaW5lc0NhY2hlOiBMaXN0SXRlbUNhY2hlW10sIGluZGV4OiBudW1iZXIsIGNvbXBhcmVGbjogKGE6IExpc3RQYXJ0LCBiOiBMaXN0UGFydCkgPT4gbnVtYmVyKTogTGlzdFBhcnQge1xuXHRcdGNvbnN0IGNoaWxkcmVuOiBMaXN0UGFydFtdID0gW107XG5cdFx0Y29uc3Qgc3RhcnRMaXN0Q2FjaGUgPSB0aGlzLmdldExpbmVDYWNoZUZyb21MaW5lKGluZGV4LCBsaW5lc0NhY2hlKTtcblxuXHRcdGNvbnN0IHRpdGxlID0gbGluZXNbaW5kZXhdO1xuXG5cdFx0d2hpbGUgKHN0YXJ0TGlzdENhY2hlLnBhcmVudCA8IHRoaXMuZ2V0TGluZUNhY2hlRnJvbUxpbmUoaW5kZXggKyAxLCBsaW5lc0NhY2hlKT8ucGFyZW50IHx8IChzdGFydExpc3RDYWNoZS5wYXJlbnQgPCAwICYmIHRoaXMuZ2V0TGluZUNhY2hlRnJvbUxpbmUoaW5kZXggKyAxLCBsaW5lc0NhY2hlKT8ucGFyZW50ID49IDApKSB7XG5cdFx0XHRpbmRleCsrO1xuXG5cdFx0XHRjb25zdCBuZXdDaGlsZCA9IHRoaXMuZ2V0U29ydGVkTGlzdFBhcnRzKGxpbmVzLCBsaW5lc0NhY2hlLCBpbmRleCwgY29tcGFyZUZuKTtcblxuXHRcdFx0aW5kZXggPSBuZXdDaGlsZC5sYXN0TGluZSA/PyBpbmRleDtcblx0XHRcdGNoaWxkcmVuLnB1c2gobmV3Q2hpbGQpO1xuXHRcdH07XG5cdFx0Y29uc3QgbGFzdExpbmUgPSBjaGlsZHJlbi5sYXN0KCk/Lmxhc3RMaW5lID8/IGluZGV4O1xuXG5cdFx0Y2hpbGRyZW4uc29ydChjb21wYXJlRm4pO1xuXHRcdHJldHVybiB7XG5cdFx0XHRjaGlsZHJlbjogY2hpbGRyZW4sXG5cdFx0XHR0aXRsZTogdGl0bGUsXG5cdFx0XHRsYXN0TGluZTogbGFzdExpbmUsXG5cdFx0fTtcblx0fVxuXG5cdGxpc3RQYXJ0VG9MaXN0KGxpc3Q6IExpc3RQYXJ0KTogTXlMaW5lW10ge1xuXHRcdHJldHVybiBsaXN0LmNoaWxkcmVuLnJlZHVjZSgoYWNjLCBjdXIpID0+IGFjYy5jb25jYXQodGhpcy5saXN0UGFydFRvTGlzdChjdXIpKSwgW2xpc3QudGl0bGVdKTtcblx0fVxuXG5cdHNvcnRIZWFkaW5ncygpIHtcblx0XHRjb25zdCBsaW5lcyA9IHRoaXMuZ2V0TGluZXMoKTtcblx0XHRjb25zdCByZXMgPSB0aGlzLmdldFNvcnRlZEhlYWRpbmdzKGxpbmVzLCAwLCB7IGhlYWRpbmdMZXZlbDogMCwgZm9ybWF0dGVkOiBcIlwiLCBzb3VyY2U6IFwiXCIsIGxpbmVOdW1iZXI6IC0xIH0pO1xuXHRcdHRoaXMuc2V0TGluZXModGhpcy5oZWFkaW5nc1RvU3RyaW5nKHJlcykuc2xpY2UoMSkpO1xuXHR9XG5cblx0aGVhZGluZ3NUb1N0cmluZyhoZWFkaW5nOiBIZWFkaW5nUGFydCk6IE15TGluZVtdIHtcblx0XHRjb25zdCBsaXN0ID0gW1xuXHRcdFx0aGVhZGluZy50aXRsZSxcblx0XHRcdC4uLmhlYWRpbmcubGluZXNcblx0XHRdO1xuXHRcdGhlYWRpbmcuaGVhZGluZ3MuZm9yRWFjaCgoZSkgPT4gbGlzdC5wdXNoKC4uLnRoaXMuaGVhZGluZ3NUb1N0cmluZyhlKSkpO1xuXHRcdHJldHVybiBsaXN0O1xuXHR9XG5cblx0Z2V0U29ydGVkSGVhZGluZ3MobGluZXM6IE15TGluZVtdLCBmcm9tOiBudW1iZXIsIGhlYWRpbmc6IE15TGluZSk6IEhlYWRpbmdQYXJ0IHtcblx0XHRsZXQgaGVhZGluZ3M6IEhlYWRpbmdQYXJ0W10gPSBbXTtcblx0XHRsZXQgY29udGVudExpbmVzOiBNeUxpbmVbXSA9IFtdO1xuXHRcdGxldCBjdXJyZW50SW5kZXggPSBmcm9tO1xuXHRcdHdoaWxlIChjdXJyZW50SW5kZXggPCBsaW5lcy5sZW5ndGgpIHtcblx0XHRcdGNvbnN0IGN1cnJlbnQgPSBsaW5lc1tjdXJyZW50SW5kZXhdO1xuXHRcdFx0aWYgKGN1cnJlbnQuaGVhZGluZ0xldmVsIDw9IGhlYWRpbmcuaGVhZGluZ0xldmVsKSB7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoY3VycmVudC5oZWFkaW5nTGV2ZWwpIHtcblxuXG5cdFx0XHRcdGhlYWRpbmdzLnB1c2godGhpcy5nZXRTb3J0ZWRIZWFkaW5ncyhsaW5lcywgY3VycmVudEluZGV4ICsgMSwgY3VycmVudCkpO1xuXHRcdFx0XHRjdXJyZW50SW5kZXggPSBoZWFkaW5ncy5sYXN0KCkudG87XG5cblxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0Y29udGVudExpbmVzLnB1c2goY3VycmVudCk7XG5cdFx0XHR9XG5cblx0XHRcdGN1cnJlbnRJbmRleCsrO1xuXHRcdH1cblxuXHRcdHJldHVybiB7XG5cdFx0XHRsaW5lczogY29udGVudExpbmVzLFxuXHRcdFx0dG86IGhlYWRpbmdzLmxlbmd0aCA+IDAgPyBoZWFkaW5ncy5sYXN0KCkudG8gOiAoY3VycmVudEluZGV4IC0gMSksXG5cdFx0XHRoZWFkaW5nczogaGVhZGluZ3Muc29ydCgoYSwgYikgPT4ge1xuXHRcdFx0XHQvL0ZpcnN0IHNvcnQgYnkgaGVhZGluZyBsZXZlbCB0aGVuIGFscGhhYmV0aWNhbGx5XG5cdFx0XHRcdGNvbnN0IHJlcyA9IGEudGl0bGUuaGVhZGluZ0xldmVsIC0gYi50aXRsZS5oZWFkaW5nTGV2ZWw7XG5cdFx0XHRcdGlmIChyZXMgPT0gMCkge1xuXHRcdFx0XHRcdHJldHVybiB0aGlzLmNvbXBhcmUoYS50aXRsZS5mb3JtYXR0ZWQudHJpbSgpLCBiLnRpdGxlLmZvcm1hdHRlZC50cmltKCkpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHJldHVybiByZXM7XG5cdFx0XHRcdH1cblx0XHRcdH0pLFxuXHRcdFx0dGl0bGU6IGhlYWRpbmcsXG5cdFx0fTtcblx0fVxuXG5cblx0c29ydExlbmd0aE9mTGluZSgpIHtcblx0XHRjb25zdCBsaW5lcyA9IHRoaXMuZ2V0TGluZXMoKTtcblx0XHRpZiAobGluZXMubGVuZ3RoID09PSAwKSByZXR1cm47XG5cdFx0bGluZXMuc29ydCgoYSwgYikgPT4gYS5mb3JtYXR0ZWQubGVuZ3RoIC0gYi5mb3JtYXR0ZWQubGVuZ3RoKTtcblxuXHRcdHRoaXMuc2V0TGluZXMobGluZXMpO1xuXHR9XG5cblx0cGVybXV0ZVJldmVyc2UoKSB7XG5cdFx0Y29uc3QgbGluZXMgPSB0aGlzLmdldExpbmVzKCk7XG5cdFx0aWYgKGxpbmVzLmxlbmd0aCA9PT0gMCkgcmV0dXJuO1xuXHRcdGxpbmVzLnJldmVyc2UoKTtcblx0XHR0aGlzLnNldExpbmVzKGxpbmVzKTtcblx0fVxuXG5cdHBlcm11dGVTaHVmZmxlKCkge1xuXHRcdGNvbnN0IGxpbmVzID0gdGhpcy5nZXRMaW5lcygpO1xuXHRcdGlmIChsaW5lcy5sZW5ndGggPT09IDApIHJldHVybjtcblx0XHRsaW5lcy5zaHVmZmxlKCk7XG5cdFx0dGhpcy5zZXRMaW5lcyhsaW5lcyk7XG5cdH1cblxuXHRnZXRMaW5lcyhmcm9tQ3VycmVudExpc3QgPSBmYWxzZSwgaWdub3JlQ2hlY2tib3hlcyA9IHRydWUpOiBNeUxpbmVbXSB7XG5cdFx0Y29uc3QgdmlldyA9IHRoaXMuYXBwLndvcmtzcGFjZS5nZXRBY3RpdmVWaWV3T2ZUeXBlKE1hcmtkb3duVmlldyk7XG5cdFx0aWYgKCF2aWV3KVxuXHRcdFx0cmV0dXJuO1xuXHRcdGNvbnN0IGVkaXRvciA9IHZpZXcuZWRpdG9yO1xuXHRcdGNvbnN0IGZpbGUgPSB2aWV3LmZpbGU7XG5cdFx0bGV0IGxpbmVzID0gZWRpdG9yLmdldFZhbHVlKCkuc3BsaXQoXCJcXG5cIik7XG5cdFx0Y29uc3QgY2FjaGUgPSB0aGlzLmFwcC5tZXRhZGF0YUNhY2hlLmdldEZpbGVDYWNoZShmaWxlKTtcblx0XHRjb25zdCB7IHN0YXJ0LCBlbmQgfSA9IHRoaXMuZ2V0UG9zaXRpb24odmlldywgZnJvbUN1cnJlbnRMaXN0KTtcblxuXHRcdGNvbnN0IGhlYWRpbmdzID0gY2FjaGUuaGVhZGluZ3M7XG5cdFx0Y29uc3QgbGlua3MgPSBbLi4uY2FjaGU/LmxpbmtzID8/IFtdLCAuLi5jYWNoZT8uZW1iZWRzID8/IFtdXTtcblx0XHRjb25zdCBteUxpbmVzID0gbGluZXMubWFwKChsaW5lLCBpbmRleCkgPT4ge1xuXHRcdFx0Y29uc3QgbXlMaW5lOiBNeUxpbmUgPSB7IHNvdXJjZTogbGluZSwgZm9ybWF0dGVkOiBsaW5lLCBoZWFkaW5nTGV2ZWw6IHVuZGVmaW5lZCwgbGluZU51bWJlcjogaW5kZXggfTtcblx0XHRcdGxpbmtzLmZvckVhY2goZSA9PiB7XG5cdFx0XHRcdGlmIChlLnBvc2l0aW9uLnN0YXJ0LmxpbmUgIT0gaW5kZXgpIHJldHVybjtcblx0XHRcdFx0Y29uc3Qgc3RhcnQgPSBlLnBvc2l0aW9uLnN0YXJ0O1xuXHRcdFx0XHRjb25zdCBlbmQgPSBlLnBvc2l0aW9uLmVuZDtcblx0XHRcdFx0bXlMaW5lLmZvcm1hdHRlZCA9IG15TGluZS5mb3JtYXR0ZWQucmVwbGFjZShsaW5lLnN1YnN0cmluZyhzdGFydC5jb2wsIGVuZC5jb2wpLCBlLmRpc3BsYXlUZXh0KTtcblx0XHRcdH0pO1xuXG5cdFx0XHQvLyBSZWdleCBvZiBjZWhja2JveCBzdHlsZXNcblx0XHRcdGlmIChpZ25vcmVDaGVja2JveGVzKSB7XG5cdFx0XHRcdG15TGluZS5mb3JtYXR0ZWQgPSBteUxpbmUuZm9ybWF0dGVkLnJlcGxhY2UoY2hlY2tib3hSZWdleCwgXCIkMVwiKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdC8vIEp1c3QgYSBsaXR0bGUgYml0IGRpcnR5Li4uXG5cdFx0XHRcdG15TGluZS5mb3JtYXR0ZWQgPSBteUxpbmUuZm9ybWF0dGVkLnJlcGxhY2UoY2hlY2tib3hSZWdleCwgXCIkMVpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpcIik7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBteUxpbmU7XG5cdFx0fSk7XG5cblx0XHRoZWFkaW5ncz8ubWFwKChoZWFkaW5nKSA9PiBteUxpbmVzW2hlYWRpbmcucG9zaXRpb24uc3RhcnQubGluZV0uaGVhZGluZ0xldmVsID0gaGVhZGluZy5sZXZlbCk7XG5cblx0XHRpZiAoc3RhcnQgIT0gZW5kKSB7XG5cdFx0XHRyZXR1cm4gbXlMaW5lcy5zbGljZShzdGFydCwgZW5kICsgMSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJldHVybiBteUxpbmVzO1xuXHRcdH1cblx0fVxuXG5cdHNldExpbmVzKGxpbmVzOiBNeUxpbmVbXSwgZnJvbUN1cnJlbnRMaXN0OiBib29sZWFuID0gZmFsc2UpIHtcblx0XHRjb25zdCB2aWV3ID0gdGhpcy5hcHAud29ya3NwYWNlLmdldEFjdGl2ZVZpZXdPZlR5cGUoTWFya2Rvd25WaWV3KTtcblx0XHRjb25zdCByZXMgPSB0aGlzLmdldFBvc2l0aW9uKHZpZXcsIGZyb21DdXJyZW50TGlzdCk7XG5cblx0XHRjb25zdCBlZGl0b3IgPSB2aWV3LmVkaXRvcjtcblx0XHRpZiAocmVzLnN0YXJ0ICE9IHJlcy5lbmQpIHtcblx0XHRcdGVkaXRvci5yZXBsYWNlUmFuZ2UobGluZXMubWFwKGUgPT4gZS5zb3VyY2UpLmpvaW4oXCJcXG5cIiksIHsgbGluZTogcmVzLnN0YXJ0LCBjaDogMCB9LCB7IGxpbmU6IHJlcy5lbmQsIGNoOiByZXMuZW5kTGluZUxlbmd0aCB9KTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0ZWRpdG9yLnNldFZhbHVlKGxpbmVzLm1hcChlID0+IGUuc291cmNlKS5qb2luKFwiXFxuXCIpKTtcblx0XHR9XG5cdH1cblxuXHRnZXRQb3NpdGlvbih2aWV3OiBNYXJrZG93blZpZXcsIGZyb21DdXJyZW50TGlzdDogYm9vbGVhbiA9IGZhbHNlKTogeyBzdGFydDogbnVtYmVyOyBlbmQ6IG51bWJlcjsgZW5kTGluZUxlbmd0aDogbnVtYmVyOyB9IHwgdW5kZWZpbmVkIHtcblx0XHRjb25zdCBjYWNoZSA9IHRoaXMuYXBwLm1ldGFkYXRhQ2FjaGUuZ2V0RmlsZUNhY2hlKHZpZXcuZmlsZSk7XG5cdFx0Y29uc3QgZWRpdG9yID0gdmlldy5lZGl0b3I7XG5cblx0XHRsZXQgY3Vyc29yU3RhcnQgPSBlZGl0b3IuZ2V0Q3Vyc29yKFwiZnJvbVwiKS5saW5lO1xuXHRcdGxldCBjdXJzb3JFbmQgPSBlZGl0b3IuZ2V0Q3Vyc29yKFwidG9cIikubGluZTtcblx0XHRpZiAoZnJvbUN1cnJlbnRMaXN0KSB7XG5cdFx0XHRjb25zdCBsaXN0ID0gY2FjaGUuc2VjdGlvbnMuZmluZCgoZSkgPT4ge1xuXHRcdFx0XHRyZXR1cm4gZS5wb3NpdGlvbi5zdGFydC5saW5lIDw9IGN1cnNvclN0YXJ0ICYmIGUucG9zaXRpb24uZW5kLmxpbmUgPj0gY3Vyc29yRW5kO1xuXHRcdFx0fSk7XG5cdFx0XHRpZiAobGlzdCkge1xuXHRcdFx0XHRjdXJzb3JTdGFydCA9IGxpc3QucG9zaXRpb24uc3RhcnQubGluZTtcblx0XHRcdFx0Y3Vyc29yRW5kID0gbGlzdC5wb3NpdGlvbi5lbmQubGluZTtcblx0XHRcdH1cblxuXHRcdH1cblx0XHRjb25zdCBjdXJzZXJFbmRMaW5lTGVuZ3RoID0gZWRpdG9yLmdldExpbmUoY3Vyc29yRW5kKS5sZW5ndGg7XG5cdFx0bGV0IGZyb250U3RhcnQgPSBjYWNoZS5mcm9udG1hdHRlcj8ucG9zaXRpb24/LmVuZD8ubGluZSArIDE7XG5cdFx0aWYgKGlzTmFOKGZyb250U3RhcnQpKSB7XG5cdFx0XHRmcm9udFN0YXJ0ID0gMDtcblx0XHR9XG5cblx0XHRjb25zdCBmcm9udEVuZCA9IGVkaXRvci5sYXN0TGluZSgpO1xuXHRcdGNvbnN0IGZyb250RW5kTGluZUxlbmd0aCA9IGVkaXRvci5nZXRMaW5lKGZyb250RW5kKS5sZW5ndGg7XG5cblx0XHRpZiAoY3Vyc29yU3RhcnQgIT0gY3Vyc29yRW5kKSB7XG5cdFx0XHRyZXR1cm4ge1xuXHRcdFx0XHRzdGFydDogY3Vyc29yU3RhcnQsXG5cdFx0XHRcdGVuZDogY3Vyc29yRW5kLFxuXHRcdFx0XHRlbmRMaW5lTGVuZ3RoOiBjdXJzZXJFbmRMaW5lTGVuZ3RoLFxuXHRcdFx0fTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0c3RhcnQ6IGZyb250U3RhcnQsXG5cdFx0XHRcdGVuZDogZnJvbnRFbmQsXG5cdFx0XHRcdGVuZExpbmVMZW5ndGg6IGZyb250RW5kTGluZUxlbmd0aCxcblx0XHRcdH07XG5cdFx0fVxuXHR9XG59Il0sIm5hbWVzIjpbIk1hcmtkb3duVmlldyIsIlBsdWdpbiJdLCJtYXBwaW5ncyI6Ijs7OztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSSxhQUFhLEdBQUcsU0FBUyxDQUFDLEVBQUUsQ0FBQyxFQUFFO0FBQ25DLElBQUksYUFBYSxHQUFHLE1BQU0sQ0FBQyxjQUFjO0FBQ3pDLFNBQVMsRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFLFlBQVksS0FBSyxJQUFJLFVBQVUsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxTQUFTLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQztBQUNwRixRQUFRLFVBQVUsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEtBQUssSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLElBQUksTUFBTSxDQUFDLFNBQVMsQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztBQUMxRyxJQUFJLE9BQU8sYUFBYSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUMvQixDQUFDLENBQUM7QUFDRjtBQUNPLFNBQVMsU0FBUyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUU7QUFDaEMsSUFBSSxJQUFJLE9BQU8sQ0FBQyxLQUFLLFVBQVUsSUFBSSxDQUFDLEtBQUssSUFBSTtBQUM3QyxRQUFRLE1BQU0sSUFBSSxTQUFTLENBQUMsc0JBQXNCLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLCtCQUErQixDQUFDLENBQUM7QUFDbEcsSUFBSSxhQUFhLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQ3hCLElBQUksU0FBUyxFQUFFLEdBQUcsRUFBRSxJQUFJLENBQUMsV0FBVyxHQUFHLENBQUMsQ0FBQyxFQUFFO0FBQzNDLElBQUksQ0FBQyxDQUFDLFNBQVMsR0FBRyxDQUFDLEtBQUssSUFBSSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDLFNBQVMsR0FBRyxDQUFDLENBQUMsU0FBUyxFQUFFLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQztBQUN6RixDQUFDO0FBb0ZEO0FBQ08sU0FBUyxTQUFTLENBQUMsT0FBTyxFQUFFLFVBQVUsRUFBRSxDQUFDLEVBQUUsU0FBUyxFQUFFO0FBQzdELElBQUksU0FBUyxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsT0FBTyxLQUFLLFlBQVksQ0FBQyxHQUFHLEtBQUssR0FBRyxJQUFJLENBQUMsQ0FBQyxVQUFVLE9BQU8sRUFBRSxFQUFFLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFO0FBQ2hILElBQUksT0FBTyxLQUFLLENBQUMsS0FBSyxDQUFDLEdBQUcsT0FBTyxDQUFDLEVBQUUsVUFBVSxPQUFPLEVBQUUsTUFBTSxFQUFFO0FBQy9ELFFBQVEsU0FBUyxTQUFTLENBQUMsS0FBSyxFQUFFLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxFQUFFLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRTtBQUNuRyxRQUFRLFNBQVMsUUFBUSxDQUFDLEtBQUssRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxFQUFFLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRTtBQUN0RyxRQUFRLFNBQVMsSUFBSSxDQUFDLE1BQU0sRUFBRSxFQUFFLE1BQU0sQ0FBQyxJQUFJLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsUUFBUSxDQUFDLENBQUMsRUFBRTtBQUN0SCxRQUFRLElBQUksQ0FBQyxDQUFDLFNBQVMsR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxVQUFVLElBQUksRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztBQUM5RSxLQUFLLENBQUMsQ0FBQztBQUNQLENBQUM7QUFDRDtBQUNPLFNBQVMsV0FBVyxDQUFDLE9BQU8sRUFBRSxJQUFJLEVBQUU7QUFDM0MsSUFBSSxJQUFJLENBQUMsR0FBRyxFQUFFLEtBQUssRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQ3JILElBQUksT0FBTyxDQUFDLEdBQUcsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsUUFBUSxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLE9BQU8sTUFBTSxLQUFLLFVBQVUsS0FBSyxDQUFDLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxHQUFHLFdBQVcsRUFBRSxPQUFPLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDN0osSUFBSSxTQUFTLElBQUksQ0FBQyxDQUFDLEVBQUUsRUFBRSxPQUFPLFVBQVUsQ0FBQyxFQUFFLEVBQUUsT0FBTyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRTtBQUN0RSxJQUFJLFNBQVMsSUFBSSxDQUFDLEVBQUUsRUFBRTtBQUN0QixRQUFRLElBQUksQ0FBQyxFQUFFLE1BQU0sSUFBSSxTQUFTLENBQUMsaUNBQWlDLENBQUMsQ0FBQztBQUN0RSxRQUFRLE9BQU8sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxJQUFJO0FBQ3RELFlBQVksSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsUUFBUSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQUM7QUFDekssWUFBWSxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3BELFlBQVksUUFBUSxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQ3pCLGdCQUFnQixLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxNQUFNO0FBQzlDLGdCQUFnQixLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQyxPQUFPLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLENBQUM7QUFDeEUsZ0JBQWdCLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVM7QUFDakUsZ0JBQWdCLEtBQUssQ0FBQyxFQUFFLEVBQUUsR0FBRyxDQUFDLENBQUMs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 diff --git a/.obsidian/plugins/obsidian-sort-and-permute-lines/manifest.json b/.obsidian/plugins/obsidian-sort-and-permute-lines/manifest.json deleted file mode 100644 index 9c954cd..0000000 --- a/.obsidian/plugins/obsidian-sort-and-permute-lines/manifest.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "id": "obsidian-sort-and-permute-lines", - "name": "Sort & Permute lines", - "version": "0.7.0", - "description": "", - "author": "Vinzent", - "authorUrl": "https://github.com/Vinzent03", - "fundingUrl": "https://ko-fi.com/vinzent", - "isDesktopOnly": false -} \ No newline at end of file diff --git a/.obsidian/plugins/table-editor-obsidian/data.json b/.obsidian/plugins/table-editor-obsidian/data.json deleted file mode 100644 index 9009465..0000000 --- a/.obsidian/plugins/table-editor-obsidian/data.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "formatType": "normal", - "showRibbonIcon": true, - "bindEnter": true, - "bindTab": true -} \ No newline at end of file diff --git a/.obsidian/plugins/table-editor-obsidian/main.js b/.obsidian/plugins/table-editor-obsidian/main.js deleted file mode 100644 index 8a03689..0000000 --- a/.obsidian/plugins/table-editor-obsidian/main.js +++ /dev/null @@ -1,14109 +0,0 @@ -/* -THIS IS A GENERATED/BUNDLED FILE BY ESBUILD -if you want to view the source, please visit the github repository of this plugin -*/ - -var __create = Object.create; -var __defProp = Object.defineProperty; -var __getOwnPropDesc = Object.getOwnPropertyDescriptor; -var __getOwnPropNames = Object.getOwnPropertyNames; -var __getProtoOf = Object.getPrototypeOf; -var __hasOwnProp = Object.prototype.hasOwnProperty; -var __commonJS = (cb, mod) => function __require() { - return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; -}; -var __export = (target, all) => { - for (var name in all) - __defProp(target, name, { get: all[name], enumerable: true }); -}; -var __copyProps = (to, from, except, desc) => { - if (from && typeof from === "object" || typeof from === "function") { - for (let key of __getOwnPropNames(from)) - if (!__hasOwnProp.call(to, key) && key !== except) - __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); - } - return to; -}; -var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( - // If the importer is in node compatibility mode or this is not an ESM - // file that has been converted to a CommonJS file using a Babel- - // compatible transform (i.e. "__esModule" has not been set), then set - // "default" to the CommonJS "module.exports" for node compatibility. - isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, - mod -)); -var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); - -// node_modules/@tgrosinger/md-advanced-tables/lib/point.js -var require_point = __commonJS({ - "node_modules/@tgrosinger/md-advanced-tables/lib/point.js"(exports) { - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.Point = void 0; - var Point2 = class { - /** - * Creates a new `Point` object. - * - * @param row - Row of the point, starts from 0. - * @param column - Column of the point, starts from 0. - */ - constructor(row, column) { - this.row = row; - this.column = column; - } - /** - * Checks if the point is equal to another point. - */ - equals(point) { - return this.row === point.row && this.column === point.column; - } - }; - exports.Point = Point2; - } -}); - -// node_modules/@tgrosinger/md-advanced-tables/lib/range.js -var require_range = __commonJS({ - "node_modules/@tgrosinger/md-advanced-tables/lib/range.js"(exports) { - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.Range = void 0; - var Range2 = class { - /** - * Creates a new `Range` object. - * - * @param start - The start point of the range. - * @param end - The end point of the range. - */ - constructor(start, end) { - this.start = start; - this.end = end; - } - }; - exports.Range = Range2; - } -}); - -// node_modules/@tgrosinger/md-advanced-tables/lib/focus.js -var require_focus = __commonJS({ - "node_modules/@tgrosinger/md-advanced-tables/lib/focus.js"(exports) { - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.Focus = void 0; - var Focus = class _Focus { - /** - * Creates a new `Focus` object. - * - * @param row - Row of the focused cell. - * @param column - Column of the focused cell. - * @param offset - Raw offset in the cell. - */ - constructor(row, column, offset) { - this.row = row; - this.column = column; - this.offset = offset; - } - /** - * Checks if two focuses point the same cell. - * Offsets are ignored. - */ - posEquals(focus) { - return this.row === focus.row && this.column === focus.column; - } - /** - * Creates a copy of the focus object by setting its row to the specified value. - * - * @param row - Row of the focused cell. - * @returns A new focus object with the specified row. - */ - setRow(row) { - return new _Focus(row, this.column, this.offset); - } - /** - * Creates a copy of the focus object by setting its column to the specified value. - * - * @param column - Column of the focused cell. - * @returns A new focus object with the specified column. - */ - setColumn(column) { - return new _Focus(this.row, column, this.offset); - } - /** - * Creates a copy of the focus object by setting its offset to the specified value. - * - * @param offset - Offset in the focused cell. - * @returns A new focus object with the specified offset. - */ - setOffset(offset) { - return new _Focus(this.row, this.column, offset); - } - }; - exports.Focus = Focus; - } -}); - -// node_modules/@tgrosinger/md-advanced-tables/lib/alignment.js -var require_alignment = __commonJS({ - "node_modules/@tgrosinger/md-advanced-tables/lib/alignment.js"(exports) { - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.HeaderAlignment = exports.DefaultAlignment = exports.Alignment = void 0; - var Alignment2; - (function(Alignment3) { - Alignment3["NONE"] = "none"; - Alignment3["LEFT"] = "left"; - Alignment3["RIGHT"] = "right"; - Alignment3["CENTER"] = "center"; - })(Alignment2 || (exports.Alignment = Alignment2 = {})); - var DefaultAlignment; - (function(DefaultAlignment2) { - DefaultAlignment2["LEFT"] = "left"; - DefaultAlignment2["RIGHT"] = "right"; - DefaultAlignment2["CENTER"] = "center"; - })(DefaultAlignment || (exports.DefaultAlignment = DefaultAlignment = {})); - var HeaderAlignment; - (function(HeaderAlignment2) { - HeaderAlignment2["FOLLOW"] = "follow"; - HeaderAlignment2["LEFT"] = "left"; - HeaderAlignment2["RIGHT"] = "right"; - HeaderAlignment2["CENTER"] = "center"; - })(HeaderAlignment || (exports.HeaderAlignment = HeaderAlignment = {})); - } -}); - -// node_modules/@tgrosinger/md-advanced-tables/lib/table-cell.js -var require_table_cell = __commonJS({ - "node_modules/@tgrosinger/md-advanced-tables/lib/table-cell.js"(exports) { - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.TableCell = void 0; - var alignment_1 = require_alignment(); - var TableCell = class { - /** - * Creates a new `TableCell` object. - * - * @param rawContent - Raw content of the cell. - */ - constructor(rawContent) { - this.rawContent = rawContent; - this.content = rawContent.trim(); - this.paddingLeft = this.content === "" ? this.rawContent === "" ? 0 : 1 : this.rawContent.length - this.rawContent.trimLeft().length; - this.paddingRight = this.rawContent.length - this.content.length - this.paddingLeft; - } - /** - * Convers the cell to a text representation. - * - * @returns The raw content of the cell. - */ - toText() { - return this.rawContent; - } - /** - * Checks if the cell is a delimiter i.e. it only contains hyphens `-` with optional one - * leading and trailing colons `:`. - * - * @returns `true` if the cell is a delimiter. - */ - isDelimiter() { - return /^\s*:?-+:?\s*$/.test(this.rawContent); - } - /** - * Returns the alignment the cell represents. - * - * @returns The alignment the cell represents; `undefined` if the cell is not a delimiter. - */ - getAlignment() { - if (!this.isDelimiter()) { - return void 0; - } - if (this.content[0] === ":") { - if (this.content[this.content.length - 1] === ":") { - return alignment_1.Alignment.CENTER; - } - return alignment_1.Alignment.LEFT; - } - if (this.content[this.content.length - 1] === ":") { - return alignment_1.Alignment.RIGHT; - } - return alignment_1.Alignment.NONE; - } - /** - * Computes a relative position in the trimmed content from that in the raw content. - * - * @param rawOffset - Relative position in the raw content. - * @returns - Relative position in the trimmed content. - */ - computeContentOffset(rawOffset) { - if (this.content === "") { - return 0; - } - if (rawOffset < this.paddingLeft) { - return 0; - } - if (rawOffset < this.paddingLeft + this.content.length) { - return rawOffset - this.paddingLeft; - } - return this.content.length; - } - /** - * Computes a relative position in the raw content from that in the trimmed content. - * - * @param contentOffset - Relative position in the trimmed content. - * @returns - Relative position in the raw content. - */ - computeRawOffset(contentOffset) { - return contentOffset + this.paddingLeft; - } - }; - exports.TableCell = TableCell; - } -}); - -// node_modules/@tgrosinger/md-advanced-tables/lib/table-row.js -var require_table_row = __commonJS({ - "node_modules/@tgrosinger/md-advanced-tables/lib/table-row.js"(exports) { - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.TableRow = void 0; - var table_cell_1 = require_table_cell(); - var TableRow = class _TableRow { - /** - * Creates a new `TableRow` objec. - * - * @param cells - Cells that the row contains. - * @param marginLeft - Margin string at the left of the row. - * @param marginRight - Margin string at the right of the row. - */ - constructor(cells, marginLeft, marginRight) { - this._cells = cells.slice(); - this.marginLeft = marginLeft; - this.marginRight = marginRight; - } - /** - * Gets the number of the cells in the row. - */ - getWidth() { - return this._cells.length; - } - /** - * Returns the cells that the row contains. - */ - getCells() { - return this._cells.slice(); - } - /** - * Gets a cell at the specified index. - * - * @param index - Index. - * @returns The cell at the specified index if exists; `undefined` if no cell is found. - */ - getCellAt(index) { - return this._cells[index]; - } - /** - * Sets a cell in the row to a new value, returning a copy of the row - * with the modified value. - * - * If an invalid index is provided, the row will be unchanged. - */ - setCellAt(index, value) { - const cells = this.getCells(); - cells[index] = new table_cell_1.TableCell(value); - return new _TableRow(cells, this.marginLeft, this.marginRight); - } - /** - * Convers the row to a text representation. - */ - toText() { - if (this._cells.length === 0) { - return this.marginLeft; - } - const cells = this._cells.map((cell) => cell.toText()).join("|"); - return `${this.marginLeft}|${cells}|${this.marginRight}`; - } - /** - * Checks if the row is a delimiter or not. - * - * @returns `true` if the row is a delimiter i.e. all the cells contained are delimiters. - */ - isDelimiter() { - return this._cells.every((cell) => cell.isDelimiter()); - } - }; - exports.TableRow = TableRow; - } -}); - -// node_modules/@tgrosinger/md-advanced-tables/lib/neverthrow/neverthrow.js -var require_neverthrow = __commonJS({ - "node_modules/@tgrosinger/md-advanced-tables/lib/neverthrow/neverthrow.js"(exports) { - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.Err = exports.Ok = exports.err = exports.ok = void 0; - var ok = (value) => new Ok(value); - exports.ok = ok; - var err = (err2) => new Err(err2); - exports.err = err; - var Ok = class { - constructor(value) { - this.value = value; - this.match = (ok2, _err) => ok2(this.value); - } - isOk() { - return true; - } - isErr() { - return !this.isOk(); - } - map(f) { - return (0, exports.ok)(f(this.value)); - } - mapErr(_f) { - return (0, exports.ok)(this.value); - } - // add info on how this is really useful for converting a - // Result, E1> - // into a Result - andThen(f) { - return f(this.value); - } - unwrapOr(_v) { - return this.value; - } - _unsafeUnwrap() { - return this.value; - } - _unsafeUnwrapErr() { - throw new Error("Called `_unsafeUnwrapErr` on an Ok"); - } - }; - exports.Ok = Ok; - var Err = class { - constructor(error) { - this.error = error; - this.match = (_ok, err2) => err2(this.error); - } - isOk() { - return false; - } - isErr() { - return !this.isOk(); - } - map(_f) { - return (0, exports.err)(this.error); - } - mapErr(f) { - return (0, exports.err)(f(this.error)); - } - andThen(_f) { - return (0, exports.err)(this.error); - } - unwrapOr(v) { - return v; - } - _unsafeUnwrap() { - throw new Error("Called `_unsafeUnwrap` on an Err"); - } - _unsafeUnwrapErr() { - return this.error; - } - }; - exports.Err = Err; - } -}); - -// node_modules/@tgrosinger/md-advanced-tables/lib/calc/ast_utils.js -var require_ast_utils = __commonJS({ - "node_modules/@tgrosinger/md-advanced-tables/lib/calc/ast_utils.js"(exports) { - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.prettyPrintAST = exports.checkChildLength = exports.checkType = exports.errRelativeReferenceIndex = exports.errIndex0 = void 0; - exports.errIndex0 = new Error("Index 0 used to create a reference"); - exports.errRelativeReferenceIndex = new Error("Can not use relative reference where absolute reference is required"); - var checkType = (ast, ...expectedTypes) => { - if (expectedTypes.indexOf(ast.type) >= 0) { - return; - } - return new Error(`Formula element '${ast.text}' is a ${ast.type} but expected one of ${expectedTypes} in this position.`); - }; - exports.checkType = checkType; - var checkChildLength = (ast, len) => { - if (ast.children.length === len) { - return; - } - return new Error(`Formula element '${ast.text}' was expected to have ${len} elements, but had ${ast.children.length}`); - }; - exports.checkChildLength = checkChildLength; - var prettyPrintAST = (token, level = 0) => { - console.log(" ".repeat(level) + `|-${token.type}${token.children.length === 0 ? "=" + token.text : ""}`); - if (token.children) { - token.children.forEach((c) => { - (0, exports.prettyPrintAST)(c, level + 1); - }); - } - }; - exports.prettyPrintAST = prettyPrintAST; - } -}); - -// node_modules/decimal.js/decimal.js -var require_decimal = __commonJS({ - "node_modules/decimal.js/decimal.js"(exports, module2) { - (function(globalScope) { - "use strict"; - var EXP_LIMIT = 9e15, MAX_DIGITS = 1e9, NUMERALS = "0123456789abcdef", LN10 = "2.3025850929940456840179914546843642076011014886287729760333279009675726096773524802359972050895982983419677840422862486334095254650828067566662873690987816894829072083255546808437998948262331985283935053089653777326288461633662222876982198867465436674744042432743651550489343149393914796194044002221051017141748003688084012647080685567743216228355220114804663715659121373450747856947683463616792101806445070648000277502684916746550586856935673420670581136429224554405758925724208241314695689016758940256776311356919292033376587141660230105703089634572075440370847469940168269282808481184289314848524948644871927809676271275775397027668605952496716674183485704422507197965004714951050492214776567636938662976979522110718264549734772662425709429322582798502585509785265383207606726317164309505995087807523710333101197857547331541421808427543863591778117054309827482385045648019095610299291824318237525357709750539565187697510374970888692180205189339507238539205144634197265287286965110862571492198849978748873771345686209167058", PI = "3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989380952572010654858632789", DEFAULTS = { - // These values must be integers within the stated ranges (inclusive). - // Most of these values can be changed at run-time using the `Decimal.config` method. - // The maximum number of significant digits of the result of a calculation or base conversion. - // E.g. `Decimal.config({ precision: 20 });` - precision: 20, - // 1 to MAX_DIGITS - // The rounding mode used when rounding to `precision`. - // - // ROUND_UP 0 Away from zero. - // ROUND_DOWN 1 Towards zero. - // ROUND_CEIL 2 Towards +Infinity. - // ROUND_FLOOR 3 Towards -Infinity. - // ROUND_HALF_UP 4 Towards nearest neighbour. If equidistant, up. - // ROUND_HALF_DOWN 5 Towards nearest neighbour. If equidistant, down. - // ROUND_HALF_EVEN 6 Towards nearest neighbour. If equidistant, towards even neighbour. - // ROUND_HALF_CEIL 7 Towards nearest neighbour. If equidistant, towards +Infinity. - // ROUND_HALF_FLOOR 8 Towards nearest neighbour. If equidistant, towards -Infinity. - // - // E.g. - // `Decimal.rounding = 4;` - // `Decimal.rounding = Decimal.ROUND_HALF_UP;` - rounding: 4, - // 0 to 8 - // The modulo mode used when calculating the modulus: a mod n. - // The quotient (q = a / n) is calculated according to the corresponding rounding mode. - // The remainder (r) is calculated as: r = a - n * q. - // - // UP 0 The remainder is positive if the dividend is negative, else is negative. - // DOWN 1 The remainder has the same sign as the dividend (JavaScript %). - // FLOOR 3 The remainder has the same sign as the divisor (Python %). - // HALF_EVEN 6 The IEEE 754 remainder function. - // EUCLID 9 Euclidian division. q = sign(n) * floor(a / abs(n)). Always positive. - // - // Truncated division (1), floored division (3), the IEEE 754 remainder (6), and Euclidian - // division (9) are commonly used for the modulus operation. The other rounding modes can also - // be used, but they may not give useful results. - modulo: 1, - // 0 to 9 - // The exponent value at and beneath which `toString` returns exponential notation. - // JavaScript numbers: -7 - toExpNeg: -7, - // 0 to -EXP_LIMIT - // The exponent value at and above which `toString` returns exponential notation. - // JavaScript numbers: 21 - toExpPos: 21, - // 0 to EXP_LIMIT - // The minimum exponent value, beneath which underflow to zero occurs. - // JavaScript numbers: -324 (5e-324) - minE: -EXP_LIMIT, - // -1 to -EXP_LIMIT - // The maximum exponent value, above which overflow to Infinity occurs. - // JavaScript numbers: 308 (1.7976931348623157e+308) - maxE: EXP_LIMIT, - // 1 to EXP_LIMIT - // Whether to use cryptographically-secure random number generation, if available. - crypto: false - // true/false - }, Decimal, inexact, noConflict, quadrant, external = true, decimalError = "[DecimalError] ", invalidArgument = decimalError + "Invalid argument: ", precisionLimitExceeded = decimalError + "Precision limit exceeded", cryptoUnavailable = decimalError + "crypto unavailable", tag = "[object Decimal]", mathfloor = Math.floor, mathpow = Math.pow, isBinary = /^0b([01]+(\.[01]*)?|\.[01]+)(p[+-]?\d+)?$/i, isHex = /^0x([0-9a-f]+(\.[0-9a-f]*)?|\.[0-9a-f]+)(p[+-]?\d+)?$/i, isOctal = /^0o([0-7]+(\.[0-7]*)?|\.[0-7]+)(p[+-]?\d+)?$/i, isDecimal = /^(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i, BASE = 1e7, LOG_BASE = 7, MAX_SAFE_INTEGER = 9007199254740991, LN10_PRECISION = LN10.length - 1, PI_PRECISION = PI.length - 1, P = { toStringTag: tag }; - P.absoluteValue = P.abs = function() { - var x = new this.constructor(this); - if (x.s < 0) x.s = 1; - return finalise(x); - }; - P.ceil = function() { - return finalise(new this.constructor(this), this.e + 1, 2); - }; - P.clampedTo = P.clamp = function(min2, max2) { - var k, x = this, Ctor = x.constructor; - min2 = new Ctor(min2); - max2 = new Ctor(max2); - if (!min2.s || !max2.s) return new Ctor(NaN); - if (min2.gt(max2)) throw Error(invalidArgument + max2); - k = x.cmp(min2); - return k < 0 ? min2 : x.cmp(max2) > 0 ? max2 : new Ctor(x); - }; - P.comparedTo = P.cmp = function(y) { - var i, j, xdL, ydL, x = this, xd = x.d, yd = (y = new x.constructor(y)).d, xs = x.s, ys = y.s; - if (!xd || !yd) { - return !xs || !ys ? NaN : xs !== ys ? xs : xd === yd ? 0 : !xd ^ xs < 0 ? 1 : -1; - } - if (!xd[0] || !yd[0]) return xd[0] ? xs : yd[0] ? -ys : 0; - if (xs !== ys) return xs; - if (x.e !== y.e) return x.e > y.e ^ xs < 0 ? 1 : -1; - xdL = xd.length; - ydL = yd.length; - for (i = 0, j = xdL < ydL ? xdL : ydL; i < j; ++i) { - if (xd[i] !== yd[i]) return xd[i] > yd[i] ^ xs < 0 ? 1 : -1; - } - return xdL === ydL ? 0 : xdL > ydL ^ xs < 0 ? 1 : -1; - }; - P.cosine = P.cos = function() { - var pr, rm, x = this, Ctor = x.constructor; - if (!x.d) return new Ctor(NaN); - if (!x.d[0]) return new Ctor(1); - pr = Ctor.precision; - rm = Ctor.rounding; - Ctor.precision = pr + Math.max(x.e, x.sd()) + LOG_BASE; - Ctor.rounding = 1; - x = cosine(Ctor, toLessThanHalfPi(Ctor, x)); - Ctor.precision = pr; - Ctor.rounding = rm; - return finalise(quadrant == 2 || quadrant == 3 ? x.neg() : x, pr, rm, true); - }; - P.cubeRoot = P.cbrt = function() { - var e, m, n, r, rep, s, sd, t, t3, t3plusx, x = this, Ctor = x.constructor; - if (!x.isFinite() || x.isZero()) return new Ctor(x); - external = false; - s = x.s * mathpow(x.s * x, 1 / 3); - if (!s || Math.abs(s) == 1 / 0) { - n = digitsToString(x.d); - e = x.e; - if (s = (e - n.length + 1) % 3) n += s == 1 || s == -2 ? "0" : "00"; - s = mathpow(n, 1 / 3); - e = mathfloor((e + 1) / 3) - (e % 3 == (e < 0 ? -1 : 2)); - if (s == 1 / 0) { - n = "5e" + e; - } else { - n = s.toExponential(); - n = n.slice(0, n.indexOf("e") + 1) + e; - } - r = new Ctor(n); - r.s = x.s; - } else { - r = new Ctor(s.toString()); - } - sd = (e = Ctor.precision) + 3; - for (; ; ) { - t = r; - t3 = t.times(t).times(t); - t3plusx = t3.plus(x); - r = divide(t3plusx.plus(x).times(t), t3plusx.plus(t3), sd + 2, 1); - if (digitsToString(t.d).slice(0, sd) === (n = digitsToString(r.d)).slice(0, sd)) { - n = n.slice(sd - 3, sd + 1); - if (n == "9999" || !rep && n == "4999") { - if (!rep) { - finalise(t, e + 1, 0); - if (t.times(t).times(t).eq(x)) { - r = t; - break; - } - } - sd += 4; - rep = 1; - } else { - if (!+n || !+n.slice(1) && n.charAt(0) == "5") { - finalise(r, e + 1, 1); - m = !r.times(r).times(r).eq(x); - } - break; - } - } - } - external = true; - return finalise(r, e, Ctor.rounding, m); - }; - P.decimalPlaces = P.dp = function() { - var w, d = this.d, n = NaN; - if (d) { - w = d.length - 1; - n = (w - mathfloor(this.e / LOG_BASE)) * LOG_BASE; - w = d[w]; - if (w) for (; w % 10 == 0; w /= 10) n--; - if (n < 0) n = 0; - } - return n; - }; - P.dividedBy = P.div = function(y) { - return divide(this, new this.constructor(y)); - }; - P.dividedToIntegerBy = P.divToInt = function(y) { - var x = this, Ctor = x.constructor; - return finalise(divide(x, new Ctor(y), 0, 1, 1), Ctor.precision, Ctor.rounding); - }; - P.equals = P.eq = function(y) { - return this.cmp(y) === 0; - }; - P.floor = function() { - return finalise(new this.constructor(this), this.e + 1, 3); - }; - P.greaterThan = P.gt = function(y) { - return this.cmp(y) > 0; - }; - P.greaterThanOrEqualTo = P.gte = function(y) { - var k = this.cmp(y); - return k == 1 || k === 0; - }; - P.hyperbolicCosine = P.cosh = function() { - var k, n, pr, rm, len, x = this, Ctor = x.constructor, one = new Ctor(1); - if (!x.isFinite()) return new Ctor(x.s ? 1 / 0 : NaN); - if (x.isZero()) return one; - pr = Ctor.precision; - rm = Ctor.rounding; - Ctor.precision = pr + Math.max(x.e, x.sd()) + 4; - Ctor.rounding = 1; - len = x.d.length; - if (len < 32) { - k = Math.ceil(len / 3); - n = (1 / tinyPow(4, k)).toString(); - } else { - k = 16; - n = "2.3283064365386962890625e-10"; - } - x = taylorSeries(Ctor, 1, x.times(n), new Ctor(1), true); - var cosh2_x, i = k, d8 = new Ctor(8); - for (; i--; ) { - cosh2_x = x.times(x); - x = one.minus(cosh2_x.times(d8.minus(cosh2_x.times(d8)))); - } - return finalise(x, Ctor.precision = pr, Ctor.rounding = rm, true); - }; - P.hyperbolicSine = P.sinh = function() { - var k, pr, rm, len, x = this, Ctor = x.constructor; - if (!x.isFinite() || x.isZero()) return new Ctor(x); - pr = Ctor.precision; - rm = Ctor.rounding; - Ctor.precision = pr + Math.max(x.e, x.sd()) + 4; - Ctor.rounding = 1; - len = x.d.length; - if (len < 3) { - x = taylorSeries(Ctor, 2, x, x, true); - } else { - k = 1.4 * Math.sqrt(len); - k = k > 16 ? 16 : k | 0; - x = x.times(1 / tinyPow(5, k)); - x = taylorSeries(Ctor, 2, x, x, true); - var sinh2_x, d5 = new Ctor(5), d16 = new Ctor(16), d20 = new Ctor(20); - for (; k--; ) { - sinh2_x = x.times(x); - x = x.times(d5.plus(sinh2_x.times(d16.times(sinh2_x).plus(d20)))); - } - } - Ctor.precision = pr; - Ctor.rounding = rm; - return finalise(x, pr, rm, true); - }; - P.hyperbolicTangent = P.tanh = function() { - var pr, rm, x = this, Ctor = x.constructor; - if (!x.isFinite()) return new Ctor(x.s); - if (x.isZero()) return new Ctor(x); - pr = Ctor.precision; - rm = Ctor.rounding; - Ctor.precision = pr + 7; - Ctor.rounding = 1; - return divide(x.sinh(), x.cosh(), Ctor.precision = pr, Ctor.rounding = rm); - }; - P.inverseCosine = P.acos = function() { - var halfPi, x = this, Ctor = x.constructor, k = x.abs().cmp(1), pr = Ctor.precision, rm = Ctor.rounding; - if (k !== -1) { - return k === 0 ? x.isNeg() ? getPi(Ctor, pr, rm) : new Ctor(0) : new Ctor(NaN); - } - if (x.isZero()) return getPi(Ctor, pr + 4, rm).times(0.5); - Ctor.precision = pr + 6; - Ctor.rounding = 1; - x = x.asin(); - halfPi = getPi(Ctor, pr + 4, rm).times(0.5); - Ctor.precision = pr; - Ctor.rounding = rm; - return halfPi.minus(x); - }; - P.inverseHyperbolicCosine = P.acosh = function() { - var pr, rm, x = this, Ctor = x.constructor; - if (x.lte(1)) return new Ctor(x.eq(1) ? 0 : NaN); - if (!x.isFinite()) return new Ctor(x); - pr = Ctor.precision; - rm = Ctor.rounding; - Ctor.precision = pr + Math.max(Math.abs(x.e), x.sd()) + 4; - Ctor.rounding = 1; - external = false; - x = x.times(x).minus(1).sqrt().plus(x); - external = true; - Ctor.precision = pr; - Ctor.rounding = rm; - return x.ln(); - }; - P.inverseHyperbolicSine = P.asinh = function() { - var pr, rm, x = this, Ctor = x.constructor; - if (!x.isFinite() || x.isZero()) return new Ctor(x); - pr = Ctor.precision; - rm = Ctor.rounding; - Ctor.precision = pr + 2 * Math.max(Math.abs(x.e), x.sd()) + 6; - Ctor.rounding = 1; - external = false; - x = x.times(x).plus(1).sqrt().plus(x); - external = true; - Ctor.precision = pr; - Ctor.rounding = rm; - return x.ln(); - }; - P.inverseHyperbolicTangent = P.atanh = function() { - var pr, rm, wpr, xsd, x = this, Ctor = x.constructor; - if (!x.isFinite()) return new Ctor(NaN); - if (x.e >= 0) return new Ctor(x.abs().eq(1) ? x.s / 0 : x.isZero() ? x : NaN); - pr = Ctor.precision; - rm = Ctor.rounding; - xsd = x.sd(); - if (Math.max(xsd, pr) < 2 * -x.e - 1) return finalise(new Ctor(x), pr, rm, true); - Ctor.precision = wpr = xsd - x.e; - x = divide(x.plus(1), new Ctor(1).minus(x), wpr + pr, 1); - Ctor.precision = pr + 4; - Ctor.rounding = 1; - x = x.ln(); - Ctor.precision = pr; - Ctor.rounding = rm; - return x.times(0.5); - }; - P.inverseSine = P.asin = function() { - var halfPi, k, pr, rm, x = this, Ctor = x.constructor; - if (x.isZero()) return new Ctor(x); - k = x.abs().cmp(1); - pr = Ctor.precision; - rm = Ctor.rounding; - if (k !== -1) { - if (k === 0) { - halfPi = getPi(Ctor, pr + 4, rm).times(0.5); - halfPi.s = x.s; - return halfPi; - } - return new Ctor(NaN); - } - Ctor.precision = pr + 6; - Ctor.rounding = 1; - x = x.div(new Ctor(1).minus(x.times(x)).sqrt().plus(1)).atan(); - Ctor.precision = pr; - Ctor.rounding = rm; - return x.times(2); - }; - P.inverseTangent = P.atan = function() { - var i, j, k, n, px, t, r, wpr, x2, x = this, Ctor = x.constructor, pr = Ctor.precision, rm = Ctor.rounding; - if (!x.isFinite()) { - if (!x.s) return new Ctor(NaN); - if (pr + 4 <= PI_PRECISION) { - r = getPi(Ctor, pr + 4, rm).times(0.5); - r.s = x.s; - return r; - } - } else if (x.isZero()) { - return new Ctor(x); - } else if (x.abs().eq(1) && pr + 4 <= PI_PRECISION) { - r = getPi(Ctor, pr + 4, rm).times(0.25); - r.s = x.s; - return r; - } - Ctor.precision = wpr = pr + 10; - Ctor.rounding = 1; - k = Math.min(28, wpr / LOG_BASE + 2 | 0); - for (i = k; i; --i) x = x.div(x.times(x).plus(1).sqrt().plus(1)); - external = false; - j = Math.ceil(wpr / LOG_BASE); - n = 1; - x2 = x.times(x); - r = new Ctor(x); - px = x; - for (; i !== -1; ) { - px = px.times(x2); - t = r.minus(px.div(n += 2)); - px = px.times(x2); - r = t.plus(px.div(n += 2)); - if (r.d[j] !== void 0) for (i = j; r.d[i] === t.d[i] && i--; ) ; - } - if (k) r = r.times(2 << k - 1); - external = true; - return finalise(r, Ctor.precision = pr, Ctor.rounding = rm, true); - }; - P.isFinite = function() { - return !!this.d; - }; - P.isInteger = P.isInt = function() { - return !!this.d && mathfloor(this.e / LOG_BASE) > this.d.length - 2; - }; - P.isNaN = function() { - return !this.s; - }; - P.isNegative = P.isNeg = function() { - return this.s < 0; - }; - P.isPositive = P.isPos = function() { - return this.s > 0; - }; - P.isZero = function() { - return !!this.d && this.d[0] === 0; - }; - P.lessThan = P.lt = function(y) { - return this.cmp(y) < 0; - }; - P.lessThanOrEqualTo = P.lte = function(y) { - return this.cmp(y) < 1; - }; - P.logarithm = P.log = function(base) { - var isBase10, d, denominator, k, inf, num, sd, r, arg = this, Ctor = arg.constructor, pr = Ctor.precision, rm = Ctor.rounding, guard = 5; - if (base == null) { - base = new Ctor(10); - isBase10 = true; - } else { - base = new Ctor(base); - d = base.d; - if (base.s < 0 || !d || !d[0] || base.eq(1)) return new Ctor(NaN); - isBase10 = base.eq(10); - } - d = arg.d; - if (arg.s < 0 || !d || !d[0] || arg.eq(1)) { - return new Ctor(d && !d[0] ? -1 / 0 : arg.s != 1 ? NaN : d ? 0 : 1 / 0); - } - if (isBase10) { - if (d.length > 1) { - inf = true; - } else { - for (k = d[0]; k % 10 === 0; ) k /= 10; - inf = k !== 1; - } - } - external = false; - sd = pr + guard; - num = naturalLogarithm(arg, sd); - denominator = isBase10 ? getLn10(Ctor, sd + 10) : naturalLogarithm(base, sd); - r = divide(num, denominator, sd, 1); - if (checkRoundingDigits(r.d, k = pr, rm)) { - do { - sd += 10; - num = naturalLogarithm(arg, sd); - denominator = isBase10 ? getLn10(Ctor, sd + 10) : naturalLogarithm(base, sd); - r = divide(num, denominator, sd, 1); - if (!inf) { - if (+digitsToString(r.d).slice(k + 1, k + 15) + 1 == 1e14) { - r = finalise(r, pr + 1, 0); - } - break; - } - } while (checkRoundingDigits(r.d, k += 10, rm)); - } - external = true; - return finalise(r, pr, rm); - }; - P.minus = P.sub = function(y) { - var d, e, i, j, k, len, pr, rm, xd, xe, xLTy, yd, x = this, Ctor = x.constructor; - y = new Ctor(y); - if (!x.d || !y.d) { - if (!x.s || !y.s) y = new Ctor(NaN); - else if (x.d) y.s = -y.s; - else y = new Ctor(y.d || x.s !== y.s ? x : NaN); - return y; - } - if (x.s != y.s) { - y.s = -y.s; - return x.plus(y); - } - xd = x.d; - yd = y.d; - pr = Ctor.precision; - rm = Ctor.rounding; - if (!xd[0] || !yd[0]) { - if (yd[0]) y.s = -y.s; - else if (xd[0]) y = new Ctor(x); - else return new Ctor(rm === 3 ? -0 : 0); - return external ? finalise(y, pr, rm) : y; - } - e = mathfloor(y.e / LOG_BASE); - xe = mathfloor(x.e / LOG_BASE); - xd = xd.slice(); - k = xe - e; - if (k) { - xLTy = k < 0; - if (xLTy) { - d = xd; - k = -k; - len = yd.length; - } else { - d = yd; - e = xe; - len = xd.length; - } - i = Math.max(Math.ceil(pr / LOG_BASE), len) + 2; - if (k > i) { - k = i; - d.length = 1; - } - d.reverse(); - for (i = k; i--; ) d.push(0); - d.reverse(); - } else { - i = xd.length; - len = yd.length; - xLTy = i < len; - if (xLTy) len = i; - for (i = 0; i < len; i++) { - if (xd[i] != yd[i]) { - xLTy = xd[i] < yd[i]; - break; - } - } - k = 0; - } - if (xLTy) { - d = xd; - xd = yd; - yd = d; - y.s = -y.s; - } - len = xd.length; - for (i = yd.length - len; i > 0; --i) xd[len++] = 0; - for (i = yd.length; i > k; ) { - if (xd[--i] < yd[i]) { - for (j = i; j && xd[--j] === 0; ) xd[j] = BASE - 1; - --xd[j]; - xd[i] += BASE; - } - xd[i] -= yd[i]; - } - for (; xd[--len] === 0; ) xd.pop(); - for (; xd[0] === 0; xd.shift()) --e; - if (!xd[0]) return new Ctor(rm === 3 ? -0 : 0); - y.d = xd; - y.e = getBase10Exponent(xd, e); - return external ? finalise(y, pr, rm) : y; - }; - P.modulo = P.mod = function(y) { - var q, x = this, Ctor = x.constructor; - y = new Ctor(y); - if (!x.d || !y.s || y.d && !y.d[0]) return new Ctor(NaN); - if (!y.d || x.d && !x.d[0]) { - return finalise(new Ctor(x), Ctor.precision, Ctor.rounding); - } - external = false; - if (Ctor.modulo == 9) { - q = divide(x, y.abs(), 0, 3, 1); - q.s *= y.s; - } else { - q = divide(x, y, 0, Ctor.modulo, 1); - } - q = q.times(y); - external = true; - return x.minus(q); - }; - P.naturalExponential = P.exp = function() { - return naturalExponential(this); - }; - P.naturalLogarithm = P.ln = function() { - return naturalLogarithm(this); - }; - P.negated = P.neg = function() { - var x = new this.constructor(this); - x.s = -x.s; - return finalise(x); - }; - P.plus = P.add = function(y) { - var carry, d, e, i, k, len, pr, rm, xd, yd, x = this, Ctor = x.constructor; - y = new Ctor(y); - if (!x.d || !y.d) { - if (!x.s || !y.s) y = new Ctor(NaN); - else if (!x.d) y = new Ctor(y.d || x.s === y.s ? x : NaN); - return y; - } - if (x.s != y.s) { - y.s = -y.s; - return x.minus(y); - } - xd = x.d; - yd = y.d; - pr = Ctor.precision; - rm = Ctor.rounding; - if (!xd[0] || !yd[0]) { - if (!yd[0]) y = new Ctor(x); - return external ? finalise(y, pr, rm) : y; - } - k = mathfloor(x.e / LOG_BASE); - e = mathfloor(y.e / LOG_BASE); - xd = xd.slice(); - i = k - e; - if (i) { - if (i < 0) { - d = xd; - i = -i; - len = yd.length; - } else { - d = yd; - e = k; - len = xd.length; - } - k = Math.ceil(pr / LOG_BASE); - len = k > len ? k + 1 : len + 1; - if (i > len) { - i = len; - d.length = 1; - } - d.reverse(); - for (; i--; ) d.push(0); - d.reverse(); - } - len = xd.length; - i = yd.length; - if (len - i < 0) { - i = len; - d = yd; - yd = xd; - xd = d; - } - for (carry = 0; i; ) { - carry = (xd[--i] = xd[i] + yd[i] + carry) / BASE | 0; - xd[i] %= BASE; - } - if (carry) { - xd.unshift(carry); - ++e; - } - for (len = xd.length; xd[--len] == 0; ) xd.pop(); - y.d = xd; - y.e = getBase10Exponent(xd, e); - return external ? finalise(y, pr, rm) : y; - }; - P.precision = P.sd = function(z) { - var k, x = this; - if (z !== void 0 && z !== !!z && z !== 1 && z !== 0) throw Error(invalidArgument + z); - if (x.d) { - k = getPrecision(x.d); - if (z && x.e + 1 > k) k = x.e + 1; - } else { - k = NaN; - } - return k; - }; - P.round = function() { - var x = this, Ctor = x.constructor; - return finalise(new Ctor(x), x.e + 1, Ctor.rounding); - }; - P.sine = P.sin = function() { - var pr, rm, x = this, Ctor = x.constructor; - if (!x.isFinite()) return new Ctor(NaN); - if (x.isZero()) return new Ctor(x); - pr = Ctor.precision; - rm = Ctor.rounding; - Ctor.precision = pr + Math.max(x.e, x.sd()) + LOG_BASE; - Ctor.rounding = 1; - x = sine(Ctor, toLessThanHalfPi(Ctor, x)); - Ctor.precision = pr; - Ctor.rounding = rm; - return finalise(quadrant > 2 ? x.neg() : x, pr, rm, true); - }; - P.squareRoot = P.sqrt = function() { - var m, n, sd, r, rep, t, x = this, d = x.d, e = x.e, s = x.s, Ctor = x.constructor; - if (s !== 1 || !d || !d[0]) { - return new Ctor(!s || s < 0 && (!d || d[0]) ? NaN : d ? x : 1 / 0); - } - external = false; - s = Math.sqrt(+x); - if (s == 0 || s == 1 / 0) { - n = digitsToString(d); - if ((n.length + e) % 2 == 0) n += "0"; - s = Math.sqrt(n); - e = mathfloor((e + 1) / 2) - (e < 0 || e % 2); - if (s == 1 / 0) { - n = "5e" + e; - } else { - n = s.toExponential(); - n = n.slice(0, n.indexOf("e") + 1) + e; - } - r = new Ctor(n); - } else { - r = new Ctor(s.toString()); - } - sd = (e = Ctor.precision) + 3; - for (; ; ) { - t = r; - r = t.plus(divide(x, t, sd + 2, 1)).times(0.5); - if (digitsToString(t.d).slice(0, sd) === (n = digitsToString(r.d)).slice(0, sd)) { - n = n.slice(sd - 3, sd + 1); - if (n == "9999" || !rep && n == "4999") { - if (!rep) { - finalise(t, e + 1, 0); - if (t.times(t).eq(x)) { - r = t; - break; - } - } - sd += 4; - rep = 1; - } else { - if (!+n || !+n.slice(1) && n.charAt(0) == "5") { - finalise(r, e + 1, 1); - m = !r.times(r).eq(x); - } - break; - } - } - } - external = true; - return finalise(r, e, Ctor.rounding, m); - }; - P.tangent = P.tan = function() { - var pr, rm, x = this, Ctor = x.constructor; - if (!x.isFinite()) return new Ctor(NaN); - if (x.isZero()) return new Ctor(x); - pr = Ctor.precision; - rm = Ctor.rounding; - Ctor.precision = pr + 10; - Ctor.rounding = 1; - x = x.sin(); - x.s = 1; - x = divide(x, new Ctor(1).minus(x.times(x)).sqrt(), pr + 10, 0); - Ctor.precision = pr; - Ctor.rounding = rm; - return finalise(quadrant == 2 || quadrant == 4 ? x.neg() : x, pr, rm, true); - }; - P.times = P.mul = function(y) { - var carry, e, i, k, r, rL, t, xdL, ydL, x = this, Ctor = x.constructor, xd = x.d, yd = (y = new Ctor(y)).d; - y.s *= x.s; - if (!xd || !xd[0] || !yd || !yd[0]) { - return new Ctor(!y.s || xd && !xd[0] && !yd || yd && !yd[0] && !xd ? NaN : !xd || !yd ? y.s / 0 : y.s * 0); - } - e = mathfloor(x.e / LOG_BASE) + mathfloor(y.e / LOG_BASE); - xdL = xd.length; - ydL = yd.length; - if (xdL < ydL) { - r = xd; - xd = yd; - yd = r; - rL = xdL; - xdL = ydL; - ydL = rL; - } - r = []; - rL = xdL + ydL; - for (i = rL; i--; ) r.push(0); - for (i = ydL; --i >= 0; ) { - carry = 0; - for (k = xdL + i; k > i; ) { - t = r[k] + yd[i] * xd[k - i - 1] + carry; - r[k--] = t % BASE | 0; - carry = t / BASE | 0; - } - r[k] = (r[k] + carry) % BASE | 0; - } - for (; !r[--rL]; ) r.pop(); - if (carry) ++e; - else r.shift(); - y.d = r; - y.e = getBase10Exponent(r, e); - return external ? finalise(y, Ctor.precision, Ctor.rounding) : y; - }; - P.toBinary = function(sd, rm) { - return toStringBinary(this, 2, sd, rm); - }; - P.toDecimalPlaces = P.toDP = function(dp, rm) { - var x = this, Ctor = x.constructor; - x = new Ctor(x); - if (dp === void 0) return x; - checkInt32(dp, 0, MAX_DIGITS); - if (rm === void 0) rm = Ctor.rounding; - else checkInt32(rm, 0, 8); - return finalise(x, dp + x.e + 1, rm); - }; - P.toExponential = function(dp, rm) { - var str, x = this, Ctor = x.constructor; - if (dp === void 0) { - str = finiteToString(x, true); - } else { - checkInt32(dp, 0, MAX_DIGITS); - if (rm === void 0) rm = Ctor.rounding; - else checkInt32(rm, 0, 8); - x = finalise(new Ctor(x), dp + 1, rm); - str = finiteToString(x, true, dp + 1); - } - return x.isNeg() && !x.isZero() ? "-" + str : str; - }; - P.toFixed = function(dp, rm) { - var str, y, x = this, Ctor = x.constructor; - if (dp === void 0) { - str = finiteToString(x); - } else { - checkInt32(dp, 0, MAX_DIGITS); - if (rm === void 0) rm = Ctor.rounding; - else checkInt32(rm, 0, 8); - y = finalise(new Ctor(x), dp + x.e + 1, rm); - str = finiteToString(y, false, dp + y.e + 1); - } - return x.isNeg() && !x.isZero() ? "-" + str : str; - }; - P.toFraction = function(maxD) { - var d, d0, d1, d2, e, k, n, n0, n1, pr, q, r, x = this, xd = x.d, Ctor = x.constructor; - if (!xd) return new Ctor(x); - n1 = d0 = new Ctor(1); - d1 = n0 = new Ctor(0); - d = new Ctor(d1); - e = d.e = getPrecision(xd) - x.e - 1; - k = e % LOG_BASE; - d.d[0] = mathpow(10, k < 0 ? LOG_BASE + k : k); - if (maxD == null) { - maxD = e > 0 ? d : n1; - } else { - n = new Ctor(maxD); - if (!n.isInt() || n.lt(n1)) throw Error(invalidArgument + n); - maxD = n.gt(d) ? e > 0 ? d : n1 : n; - } - external = false; - n = new Ctor(digitsToString(xd)); - pr = Ctor.precision; - Ctor.precision = e = xd.length * LOG_BASE * 2; - for (; ; ) { - q = divide(n, d, 0, 1, 1); - d2 = d0.plus(q.times(d1)); - if (d2.cmp(maxD) == 1) break; - d0 = d1; - d1 = d2; - d2 = n1; - n1 = n0.plus(q.times(d2)); - n0 = d2; - d2 = d; - d = n.minus(q.times(d2)); - n = d2; - } - d2 = divide(maxD.minus(d0), d1, 0, 1, 1); - n0 = n0.plus(d2.times(n1)); - d0 = d0.plus(d2.times(d1)); - n0.s = n1.s = x.s; - r = divide(n1, d1, e, 1).minus(x).abs().cmp(divide(n0, d0, e, 1).minus(x).abs()) < 1 ? [n1, d1] : [n0, d0]; - Ctor.precision = pr; - external = true; - return r; - }; - P.toHexadecimal = P.toHex = function(sd, rm) { - return toStringBinary(this, 16, sd, rm); - }; - P.toNearest = function(y, rm) { - var x = this, Ctor = x.constructor; - x = new Ctor(x); - if (y == null) { - if (!x.d) return x; - y = new Ctor(1); - rm = Ctor.rounding; - } else { - y = new Ctor(y); - if (rm === void 0) { - rm = Ctor.rounding; - } else { - checkInt32(rm, 0, 8); - } - if (!x.d) return y.s ? x : y; - if (!y.d) { - if (y.s) y.s = x.s; - return y; - } - } - if (y.d[0]) { - external = false; - x = divide(x, y, 0, rm, 1).times(y); - external = true; - finalise(x); - } else { - y.s = x.s; - x = y; - } - return x; - }; - P.toNumber = function() { - return +this; - }; - P.toOctal = function(sd, rm) { - return toStringBinary(this, 8, sd, rm); - }; - P.toPower = P.pow = function(y) { - var e, k, pr, r, rm, s, x = this, Ctor = x.constructor, yn = +(y = new Ctor(y)); - if (!x.d || !y.d || !x.d[0] || !y.d[0]) return new Ctor(mathpow(+x, yn)); - x = new Ctor(x); - if (x.eq(1)) return x; - pr = Ctor.precision; - rm = Ctor.rounding; - if (y.eq(1)) return finalise(x, pr, rm); - e = mathfloor(y.e / LOG_BASE); - if (e >= y.d.length - 1 && (k = yn < 0 ? -yn : yn) <= MAX_SAFE_INTEGER) { - r = intPow(Ctor, x, k, pr); - return y.s < 0 ? new Ctor(1).div(r) : finalise(r, pr, rm); - } - s = x.s; - if (s < 0) { - if (e < y.d.length - 1) return new Ctor(NaN); - if ((y.d[e] & 1) == 0) s = 1; - if (x.e == 0 && x.d[0] == 1 && x.d.length == 1) { - x.s = s; - return x; - } - } - k = mathpow(+x, yn); - e = k == 0 || !isFinite(k) ? mathfloor(yn * (Math.log("0." + digitsToString(x.d)) / Math.LN10 + x.e + 1)) : new Ctor(k + "").e; - if (e > Ctor.maxE + 1 || e < Ctor.minE - 1) return new Ctor(e > 0 ? s / 0 : 0); - external = false; - Ctor.rounding = x.s = 1; - k = Math.min(12, (e + "").length); - r = naturalExponential(y.times(naturalLogarithm(x, pr + k)), pr); - if (r.d) { - r = finalise(r, pr + 5, 1); - if (checkRoundingDigits(r.d, pr, rm)) { - e = pr + 10; - r = finalise(naturalExponential(y.times(naturalLogarithm(x, e + k)), e), e + 5, 1); - if (+digitsToString(r.d).slice(pr + 1, pr + 15) + 1 == 1e14) { - r = finalise(r, pr + 1, 0); - } - } - } - r.s = s; - external = true; - Ctor.rounding = rm; - return finalise(r, pr, rm); - }; - P.toPrecision = function(sd, rm) { - var str, x = this, Ctor = x.constructor; - if (sd === void 0) { - str = finiteToString(x, x.e <= Ctor.toExpNeg || x.e >= Ctor.toExpPos); - } else { - checkInt32(sd, 1, MAX_DIGITS); - if (rm === void 0) rm = Ctor.rounding; - else checkInt32(rm, 0, 8); - x = finalise(new Ctor(x), sd, rm); - str = finiteToString(x, sd <= x.e || x.e <= Ctor.toExpNeg, sd); - } - return x.isNeg() && !x.isZero() ? "-" + str : str; - }; - P.toSignificantDigits = P.toSD = function(sd, rm) { - var x = this, Ctor = x.constructor; - if (sd === void 0) { - sd = Ctor.precision; - rm = Ctor.rounding; - } else { - checkInt32(sd, 1, MAX_DIGITS); - if (rm === void 0) rm = Ctor.rounding; - else checkInt32(rm, 0, 8); - } - return finalise(new Ctor(x), sd, rm); - }; - P.toString = function() { - var x = this, Ctor = x.constructor, str = finiteToString(x, x.e <= Ctor.toExpNeg || x.e >= Ctor.toExpPos); - return x.isNeg() && !x.isZero() ? "-" + str : str; - }; - P.truncated = P.trunc = function() { - return finalise(new this.constructor(this), this.e + 1, 1); - }; - P.valueOf = P.toJSON = function() { - var x = this, Ctor = x.constructor, str = finiteToString(x, x.e <= Ctor.toExpNeg || x.e >= Ctor.toExpPos); - return x.isNeg() ? "-" + str : str; - }; - function digitsToString(d) { - var i, k, ws, indexOfLastWord = d.length - 1, str = "", w = d[0]; - if (indexOfLastWord > 0) { - str += w; - for (i = 1; i < indexOfLastWord; i++) { - ws = d[i] + ""; - k = LOG_BASE - ws.length; - if (k) str += getZeroString(k); - str += ws; - } - w = d[i]; - ws = w + ""; - k = LOG_BASE - ws.length; - if (k) str += getZeroString(k); - } else if (w === 0) { - return "0"; - } - for (; w % 10 === 0; ) w /= 10; - return str + w; - } - function checkInt32(i, min2, max2) { - if (i !== ~~i || i < min2 || i > max2) { - throw Error(invalidArgument + i); - } - } - function checkRoundingDigits(d, i, rm, repeating) { - var di, k, r, rd; - for (k = d[0]; k >= 10; k /= 10) --i; - if (--i < 0) { - i += LOG_BASE; - di = 0; - } else { - di = Math.ceil((i + 1) / LOG_BASE); - i %= LOG_BASE; - } - k = mathpow(10, LOG_BASE - i); - rd = d[di] % k | 0; - if (repeating == null) { - if (i < 3) { - if (i == 0) rd = rd / 100 | 0; - else if (i == 1) rd = rd / 10 | 0; - r = rm < 4 && rd == 99999 || rm > 3 && rd == 49999 || rd == 5e4 || rd == 0; - } else { - r = (rm < 4 && rd + 1 == k || rm > 3 && rd + 1 == k / 2) && (d[di + 1] / k / 100 | 0) == mathpow(10, i - 2) - 1 || (rd == k / 2 || rd == 0) && (d[di + 1] / k / 100 | 0) == 0; - } - } else { - if (i < 4) { - if (i == 0) rd = rd / 1e3 | 0; - else if (i == 1) rd = rd / 100 | 0; - else if (i == 2) rd = rd / 10 | 0; - r = (repeating || rm < 4) && rd == 9999 || !repeating && rm > 3 && rd == 4999; - } else { - r = ((repeating || rm < 4) && rd + 1 == k || !repeating && rm > 3 && rd + 1 == k / 2) && (d[di + 1] / k / 1e3 | 0) == mathpow(10, i - 3) - 1; - } - } - return r; - } - function convertBase(str, baseIn, baseOut) { - var j, arr = [0], arrL, i = 0, strL = str.length; - for (; i < strL; ) { - for (arrL = arr.length; arrL--; ) arr[arrL] *= baseIn; - arr[0] += NUMERALS.indexOf(str.charAt(i++)); - for (j = 0; j < arr.length; j++) { - if (arr[j] > baseOut - 1) { - if (arr[j + 1] === void 0) arr[j + 1] = 0; - arr[j + 1] += arr[j] / baseOut | 0; - arr[j] %= baseOut; - } - } - } - return arr.reverse(); - } - function cosine(Ctor, x) { - var k, len, y; - if (x.isZero()) return x; - len = x.d.length; - if (len < 32) { - k = Math.ceil(len / 3); - y = (1 / tinyPow(4, k)).toString(); - } else { - k = 16; - y = "2.3283064365386962890625e-10"; - } - Ctor.precision += k; - x = taylorSeries(Ctor, 1, x.times(y), new Ctor(1)); - for (var i = k; i--; ) { - var cos2x = x.times(x); - x = cos2x.times(cos2x).minus(cos2x).times(8).plus(1); - } - Ctor.precision -= k; - return x; - } - var divide = /* @__PURE__ */ function() { - function multiplyInteger(x, k, base) { - var temp, carry = 0, i = x.length; - for (x = x.slice(); i--; ) { - temp = x[i] * k + carry; - x[i] = temp % base | 0; - carry = temp / base | 0; - } - if (carry) x.unshift(carry); - return x; - } - function compare(a, b, aL, bL) { - var i, r; - if (aL != bL) { - r = aL > bL ? 1 : -1; - } else { - for (i = r = 0; i < aL; i++) { - if (a[i] != b[i]) { - r = a[i] > b[i] ? 1 : -1; - break; - } - } - } - return r; - } - function subtract(a, b, aL, base) { - var i = 0; - for (; aL--; ) { - a[aL] -= i; - i = a[aL] < b[aL] ? 1 : 0; - a[aL] = i * base + a[aL] - b[aL]; - } - for (; !a[0] && a.length > 1; ) a.shift(); - } - return function(x, y, pr, rm, dp, base) { - var cmp, e, i, k, logBase, more, prod, prodL, q, qd, rem, remL, rem0, sd, t, xi, xL, yd0, yL, yz, Ctor = x.constructor, sign2 = x.s == y.s ? 1 : -1, xd = x.d, yd = y.d; - if (!xd || !xd[0] || !yd || !yd[0]) { - return new Ctor( - // Return NaN if either NaN, or both Infinity or 0. - !x.s || !y.s || (xd ? yd && xd[0] == yd[0] : !yd) ? NaN : ( - // Return ±0 if x is 0 or y is ±Infinity, or return ±Infinity as y is 0. - xd && xd[0] == 0 || !yd ? sign2 * 0 : sign2 / 0 - ) - ); - } - if (base) { - logBase = 1; - e = x.e - y.e; - } else { - base = BASE; - logBase = LOG_BASE; - e = mathfloor(x.e / logBase) - mathfloor(y.e / logBase); - } - yL = yd.length; - xL = xd.length; - q = new Ctor(sign2); - qd = q.d = []; - for (i = 0; yd[i] == (xd[i] || 0); i++) ; - if (yd[i] > (xd[i] || 0)) e--; - if (pr == null) { - sd = pr = Ctor.precision; - rm = Ctor.rounding; - } else if (dp) { - sd = pr + (x.e - y.e) + 1; - } else { - sd = pr; - } - if (sd < 0) { - qd.push(1); - more = true; - } else { - sd = sd / logBase + 2 | 0; - i = 0; - if (yL == 1) { - k = 0; - yd = yd[0]; - sd++; - for (; (i < xL || k) && sd--; i++) { - t = k * base + (xd[i] || 0); - qd[i] = t / yd | 0; - k = t % yd | 0; - } - more = k || i < xL; - } else { - k = base / (yd[0] + 1) | 0; - if (k > 1) { - yd = multiplyInteger(yd, k, base); - xd = multiplyInteger(xd, k, base); - yL = yd.length; - xL = xd.length; - } - xi = yL; - rem = xd.slice(0, yL); - remL = rem.length; - for (; remL < yL; ) rem[remL++] = 0; - yz = yd.slice(); - yz.unshift(0); - yd0 = yd[0]; - if (yd[1] >= base / 2) ++yd0; - do { - k = 0; - cmp = compare(yd, rem, yL, remL); - if (cmp < 0) { - rem0 = rem[0]; - if (yL != remL) rem0 = rem0 * base + (rem[1] || 0); - k = rem0 / yd0 | 0; - if (k > 1) { - if (k >= base) k = base - 1; - prod = multiplyInteger(yd, k, base); - prodL = prod.length; - remL = rem.length; - cmp = compare(prod, rem, prodL, remL); - if (cmp == 1) { - k--; - subtract(prod, yL < prodL ? yz : yd, prodL, base); - } - } else { - if (k == 0) cmp = k = 1; - prod = yd.slice(); - } - prodL = prod.length; - if (prodL < remL) prod.unshift(0); - subtract(rem, prod, remL, base); - if (cmp == -1) { - remL = rem.length; - cmp = compare(yd, rem, yL, remL); - if (cmp < 1) { - k++; - subtract(rem, yL < remL ? yz : yd, remL, base); - } - } - remL = rem.length; - } else if (cmp === 0) { - k++; - rem = [0]; - } - qd[i++] = k; - if (cmp && rem[0]) { - rem[remL++] = xd[xi] || 0; - } else { - rem = [xd[xi]]; - remL = 1; - } - } while ((xi++ < xL || rem[0] !== void 0) && sd--); - more = rem[0] !== void 0; - } - if (!qd[0]) qd.shift(); - } - if (logBase == 1) { - q.e = e; - inexact = more; - } else { - for (i = 1, k = qd[0]; k >= 10; k /= 10) i++; - q.e = i + e * logBase - 1; - finalise(q, dp ? pr + q.e + 1 : pr, rm, more); - } - return q; - }; - }(); - function finalise(x, sd, rm, isTruncated) { - var digits, i, j, k, rd, roundUp, w, xd, xdi, Ctor = x.constructor; - out: if (sd != null) { - xd = x.d; - if (!xd) return x; - for (digits = 1, k = xd[0]; k >= 10; k /= 10) digits++; - i = sd - digits; - if (i < 0) { - i += LOG_BASE; - j = sd; - w = xd[xdi = 0]; - rd = w / mathpow(10, digits - j - 1) % 10 | 0; - } else { - xdi = Math.ceil((i + 1) / LOG_BASE); - k = xd.length; - if (xdi >= k) { - if (isTruncated) { - for (; k++ <= xdi; ) xd.push(0); - w = rd = 0; - digits = 1; - i %= LOG_BASE; - j = i - LOG_BASE + 1; - } else { - break out; - } - } else { - w = k = xd[xdi]; - for (digits = 1; k >= 10; k /= 10) digits++; - i %= LOG_BASE; - j = i - LOG_BASE + digits; - rd = j < 0 ? 0 : w / mathpow(10, digits - j - 1) % 10 | 0; - } - } - isTruncated = isTruncated || sd < 0 || xd[xdi + 1] !== void 0 || (j < 0 ? w : w % mathpow(10, digits - j - 1)); - roundUp = rm < 4 ? (rd || isTruncated) && (rm == 0 || rm == (x.s < 0 ? 3 : 2)) : rd > 5 || rd == 5 && (rm == 4 || isTruncated || rm == 6 && // Check whether the digit to the left of the rounding digit is odd. - (i > 0 ? j > 0 ? w / mathpow(10, digits - j) : 0 : xd[xdi - 1]) % 10 & 1 || rm == (x.s < 0 ? 8 : 7)); - if (sd < 1 || !xd[0]) { - xd.length = 0; - if (roundUp) { - sd -= x.e + 1; - xd[0] = mathpow(10, (LOG_BASE - sd % LOG_BASE) % LOG_BASE); - x.e = -sd || 0; - } else { - xd[0] = x.e = 0; - } - return x; - } - if (i == 0) { - xd.length = xdi; - k = 1; - xdi--; - } else { - xd.length = xdi + 1; - k = mathpow(10, LOG_BASE - i); - xd[xdi] = j > 0 ? (w / mathpow(10, digits - j) % mathpow(10, j) | 0) * k : 0; - } - if (roundUp) { - for (; ; ) { - if (xdi == 0) { - for (i = 1, j = xd[0]; j >= 10; j /= 10) i++; - j = xd[0] += k; - for (k = 1; j >= 10; j /= 10) k++; - if (i != k) { - x.e++; - if (xd[0] == BASE) xd[0] = 1; - } - break; - } else { - xd[xdi] += k; - if (xd[xdi] != BASE) break; - xd[xdi--] = 0; - k = 1; - } - } - } - for (i = xd.length; xd[--i] === 0; ) xd.pop(); - } - if (external) { - if (x.e > Ctor.maxE) { - x.d = null; - x.e = NaN; - } else if (x.e < Ctor.minE) { - x.e = 0; - x.d = [0]; - } - } - return x; - } - function finiteToString(x, isExp, sd) { - if (!x.isFinite()) return nonFiniteToString(x); - var k, e = x.e, str = digitsToString(x.d), len = str.length; - if (isExp) { - if (sd && (k = sd - len) > 0) { - str = str.charAt(0) + "." + str.slice(1) + getZeroString(k); - } else if (len > 1) { - str = str.charAt(0) + "." + str.slice(1); - } - str = str + (x.e < 0 ? "e" : "e+") + x.e; - } else if (e < 0) { - str = "0." + getZeroString(-e - 1) + str; - if (sd && (k = sd - len) > 0) str += getZeroString(k); - } else if (e >= len) { - str += getZeroString(e + 1 - len); - if (sd && (k = sd - e - 1) > 0) str = str + "." + getZeroString(k); - } else { - if ((k = e + 1) < len) str = str.slice(0, k) + "." + str.slice(k); - if (sd && (k = sd - len) > 0) { - if (e + 1 === len) str += "."; - str += getZeroString(k); - } - } - return str; - } - function getBase10Exponent(digits, e) { - var w = digits[0]; - for (e *= LOG_BASE; w >= 10; w /= 10) e++; - return e; - } - function getLn10(Ctor, sd, pr) { - if (sd > LN10_PRECISION) { - external = true; - if (pr) Ctor.precision = pr; - throw Error(precisionLimitExceeded); - } - return finalise(new Ctor(LN10), sd, 1, true); - } - function getPi(Ctor, sd, rm) { - if (sd > PI_PRECISION) throw Error(precisionLimitExceeded); - return finalise(new Ctor(PI), sd, rm, true); - } - function getPrecision(digits) { - var w = digits.length - 1, len = w * LOG_BASE + 1; - w = digits[w]; - if (w) { - for (; w % 10 == 0; w /= 10) len--; - for (w = digits[0]; w >= 10; w /= 10) len++; - } - return len; - } - function getZeroString(k) { - var zs = ""; - for (; k--; ) zs += "0"; - return zs; - } - function intPow(Ctor, x, n, pr) { - var isTruncated, r = new Ctor(1), k = Math.ceil(pr / LOG_BASE + 4); - external = false; - for (; ; ) { - if (n % 2) { - r = r.times(x); - if (truncate(r.d, k)) isTruncated = true; - } - n = mathfloor(n / 2); - if (n === 0) { - n = r.d.length - 1; - if (isTruncated && r.d[n] === 0) ++r.d[n]; - break; - } - x = x.times(x); - truncate(x.d, k); - } - external = true; - return r; - } - function isOdd(n) { - return n.d[n.d.length - 1] & 1; - } - function maxOrMin(Ctor, args, ltgt) { - var y, x = new Ctor(args[0]), i = 0; - for (; ++i < args.length; ) { - y = new Ctor(args[i]); - if (!y.s) { - x = y; - break; - } else if (x[ltgt](y)) { - x = y; - } - } - return x; - } - function naturalExponential(x, sd) { - var denominator, guard, j, pow2, sum2, t, wpr, rep = 0, i = 0, k = 0, Ctor = x.constructor, rm = Ctor.rounding, pr = Ctor.precision; - if (!x.d || !x.d[0] || x.e > 17) { - return new Ctor(x.d ? !x.d[0] ? 1 : x.s < 0 ? 0 : 1 / 0 : x.s ? x.s < 0 ? 0 : x : 0 / 0); - } - if (sd == null) { - external = false; - wpr = pr; - } else { - wpr = sd; - } - t = new Ctor(0.03125); - while (x.e > -2) { - x = x.times(t); - k += 5; - } - guard = Math.log(mathpow(2, k)) / Math.LN10 * 2 + 5 | 0; - wpr += guard; - denominator = pow2 = sum2 = new Ctor(1); - Ctor.precision = wpr; - for (; ; ) { - pow2 = finalise(pow2.times(x), wpr, 1); - denominator = denominator.times(++i); - t = sum2.plus(divide(pow2, denominator, wpr, 1)); - if (digitsToString(t.d).slice(0, wpr) === digitsToString(sum2.d).slice(0, wpr)) { - j = k; - while (j--) sum2 = finalise(sum2.times(sum2), wpr, 1); - if (sd == null) { - if (rep < 3 && checkRoundingDigits(sum2.d, wpr - guard, rm, rep)) { - Ctor.precision = wpr += 10; - denominator = pow2 = t = new Ctor(1); - i = 0; - rep++; - } else { - return finalise(sum2, Ctor.precision = pr, rm, external = true); - } - } else { - Ctor.precision = pr; - return sum2; - } - } - sum2 = t; - } - } - function naturalLogarithm(y, sd) { - var c, c0, denominator, e, numerator, rep, sum2, t, wpr, x1, x2, n = 1, guard = 10, x = y, xd = x.d, Ctor = x.constructor, rm = Ctor.rounding, pr = Ctor.precision; - if (x.s < 0 || !xd || !xd[0] || !x.e && xd[0] == 1 && xd.length == 1) { - return new Ctor(xd && !xd[0] ? -1 / 0 : x.s != 1 ? NaN : xd ? 0 : x); - } - if (sd == null) { - external = false; - wpr = pr; - } else { - wpr = sd; - } - Ctor.precision = wpr += guard; - c = digitsToString(xd); - c0 = c.charAt(0); - if (Math.abs(e = x.e) < 15e14) { - while (c0 < 7 && c0 != 1 || c0 == 1 && c.charAt(1) > 3) { - x = x.times(y); - c = digitsToString(x.d); - c0 = c.charAt(0); - n++; - } - e = x.e; - if (c0 > 1) { - x = new Ctor("0." + c); - e++; - } else { - x = new Ctor(c0 + "." + c.slice(1)); - } - } else { - t = getLn10(Ctor, wpr + 2, pr).times(e + ""); - x = naturalLogarithm(new Ctor(c0 + "." + c.slice(1)), wpr - guard).plus(t); - Ctor.precision = pr; - return sd == null ? finalise(x, pr, rm, external = true) : x; - } - x1 = x; - sum2 = numerator = x = divide(x.minus(1), x.plus(1), wpr, 1); - x2 = finalise(x.times(x), wpr, 1); - denominator = 3; - for (; ; ) { - numerator = finalise(numerator.times(x2), wpr, 1); - t = sum2.plus(divide(numerator, new Ctor(denominator), wpr, 1)); - if (digitsToString(t.d).slice(0, wpr) === digitsToString(sum2.d).slice(0, wpr)) { - sum2 = sum2.times(2); - if (e !== 0) sum2 = sum2.plus(getLn10(Ctor, wpr + 2, pr).times(e + "")); - sum2 = divide(sum2, new Ctor(n), wpr, 1); - if (sd == null) { - if (checkRoundingDigits(sum2.d, wpr - guard, rm, rep)) { - Ctor.precision = wpr += guard; - t = numerator = x = divide(x1.minus(1), x1.plus(1), wpr, 1); - x2 = finalise(x.times(x), wpr, 1); - denominator = rep = 1; - } else { - return finalise(sum2, Ctor.precision = pr, rm, external = true); - } - } else { - Ctor.precision = pr; - return sum2; - } - } - sum2 = t; - denominator += 2; - } - } - function nonFiniteToString(x) { - return String(x.s * x.s / 0); - } - function parseDecimal(x, str) { - var e, i, len; - if ((e = str.indexOf(".")) > -1) str = str.replace(".", ""); - if ((i = str.search(/e/i)) > 0) { - if (e < 0) e = i; - e += +str.slice(i + 1); - str = str.substring(0, i); - } else if (e < 0) { - e = str.length; - } - for (i = 0; str.charCodeAt(i) === 48; i++) ; - for (len = str.length; str.charCodeAt(len - 1) === 48; --len) ; - str = str.slice(i, len); - if (str) { - len -= i; - x.e = e = e - i - 1; - x.d = []; - i = (e + 1) % LOG_BASE; - if (e < 0) i += LOG_BASE; - if (i < len) { - if (i) x.d.push(+str.slice(0, i)); - for (len -= LOG_BASE; i < len; ) x.d.push(+str.slice(i, i += LOG_BASE)); - str = str.slice(i); - i = LOG_BASE - str.length; - } else { - i -= len; - } - for (; i--; ) str += "0"; - x.d.push(+str); - if (external) { - if (x.e > x.constructor.maxE) { - x.d = null; - x.e = NaN; - } else if (x.e < x.constructor.minE) { - x.e = 0; - x.d = [0]; - } - } - } else { - x.e = 0; - x.d = [0]; - } - return x; - } - function parseOther(x, str) { - var base, Ctor, divisor, i, isFloat, len, p, xd, xe; - if (str.indexOf("_") > -1) { - str = str.replace(/(\d)_(?=\d)/g, "$1"); - if (isDecimal.test(str)) return parseDecimal(x, str); - } else if (str === "Infinity" || str === "NaN") { - if (!+str) x.s = NaN; - x.e = NaN; - x.d = null; - return x; - } - if (isHex.test(str)) { - base = 16; - str = str.toLowerCase(); - } else if (isBinary.test(str)) { - base = 2; - } else if (isOctal.test(str)) { - base = 8; - } else { - throw Error(invalidArgument + str); - } - i = str.search(/p/i); - if (i > 0) { - p = +str.slice(i + 1); - str = str.substring(2, i); - } else { - str = str.slice(2); - } - i = str.indexOf("."); - isFloat = i >= 0; - Ctor = x.constructor; - if (isFloat) { - str = str.replace(".", ""); - len = str.length; - i = len - i; - divisor = intPow(Ctor, new Ctor(base), i, i * 2); - } - xd = convertBase(str, base, BASE); - xe = xd.length - 1; - for (i = xe; xd[i] === 0; --i) xd.pop(); - if (i < 0) return new Ctor(x.s * 0); - x.e = getBase10Exponent(xd, xe); - x.d = xd; - external = false; - if (isFloat) x = divide(x, divisor, len * 4); - if (p) x = x.times(Math.abs(p) < 54 ? mathpow(2, p) : Decimal.pow(2, p)); - external = true; - return x; - } - function sine(Ctor, x) { - var k, len = x.d.length; - if (len < 3) { - return x.isZero() ? x : taylorSeries(Ctor, 2, x, x); - } - k = 1.4 * Math.sqrt(len); - k = k > 16 ? 16 : k | 0; - x = x.times(1 / tinyPow(5, k)); - x = taylorSeries(Ctor, 2, x, x); - var sin2_x, d5 = new Ctor(5), d16 = new Ctor(16), d20 = new Ctor(20); - for (; k--; ) { - sin2_x = x.times(x); - x = x.times(d5.plus(sin2_x.times(d16.times(sin2_x).minus(d20)))); - } - return x; - } - function taylorSeries(Ctor, n, x, y, isHyperbolic) { - var j, t, u, x2, i = 1, pr = Ctor.precision, k = Math.ceil(pr / LOG_BASE); - external = false; - x2 = x.times(x); - u = new Ctor(y); - for (; ; ) { - t = divide(u.times(x2), new Ctor(n++ * n++), pr, 1); - u = isHyperbolic ? y.plus(t) : y.minus(t); - y = divide(t.times(x2), new Ctor(n++ * n++), pr, 1); - t = u.plus(y); - if (t.d[k] !== void 0) { - for (j = k; t.d[j] === u.d[j] && j--; ) ; - if (j == -1) break; - } - j = u; - u = y; - y = t; - t = j; - i++; - } - external = true; - t.d.length = k + 1; - return t; - } - function tinyPow(b, e) { - var n = b; - while (--e) n *= b; - return n; - } - function toLessThanHalfPi(Ctor, x) { - var t, isNeg = x.s < 0, pi = getPi(Ctor, Ctor.precision, 1), halfPi = pi.times(0.5); - x = x.abs(); - if (x.lte(halfPi)) { - quadrant = isNeg ? 4 : 1; - return x; - } - t = x.divToInt(pi); - if (t.isZero()) { - quadrant = isNeg ? 3 : 2; - } else { - x = x.minus(t.times(pi)); - if (x.lte(halfPi)) { - quadrant = isOdd(t) ? isNeg ? 2 : 3 : isNeg ? 4 : 1; - return x; - } - quadrant = isOdd(t) ? isNeg ? 1 : 4 : isNeg ? 3 : 2; - } - return x.minus(pi).abs(); - } - function toStringBinary(x, baseOut, sd, rm) { - var base, e, i, k, len, roundUp, str, xd, y, Ctor = x.constructor, isExp = sd !== void 0; - if (isExp) { - checkInt32(sd, 1, MAX_DIGITS); - if (rm === void 0) rm = Ctor.rounding; - else checkInt32(rm, 0, 8); - } else { - sd = Ctor.precision; - rm = Ctor.rounding; - } - if (!x.isFinite()) { - str = nonFiniteToString(x); - } else { - str = finiteToString(x); - i = str.indexOf("."); - if (isExp) { - base = 2; - if (baseOut == 16) { - sd = sd * 4 - 3; - } else if (baseOut == 8) { - sd = sd * 3 - 2; - } - } else { - base = baseOut; - } - if (i >= 0) { - str = str.replace(".", ""); - y = new Ctor(1); - y.e = str.length - i; - y.d = convertBase(finiteToString(y), 10, base); - y.e = y.d.length; - } - xd = convertBase(str, 10, base); - e = len = xd.length; - for (; xd[--len] == 0; ) xd.pop(); - if (!xd[0]) { - str = isExp ? "0p+0" : "0"; - } else { - if (i < 0) { - e--; - } else { - x = new Ctor(x); - x.d = xd; - x.e = e; - x = divide(x, y, sd, rm, 0, base); - xd = x.d; - e = x.e; - roundUp = inexact; - } - i = xd[sd]; - k = base / 2; - roundUp = roundUp || xd[sd + 1] !== void 0; - roundUp = rm < 4 ? (i !== void 0 || roundUp) && (rm === 0 || rm === (x.s < 0 ? 3 : 2)) : i > k || i === k && (rm === 4 || roundUp || rm === 6 && xd[sd - 1] & 1 || rm === (x.s < 0 ? 8 : 7)); - xd.length = sd; - if (roundUp) { - for (; ++xd[--sd] > base - 1; ) { - xd[sd] = 0; - if (!sd) { - ++e; - xd.unshift(1); - } - } - } - for (len = xd.length; !xd[len - 1]; --len) ; - for (i = 0, str = ""; i < len; i++) str += NUMERALS.charAt(xd[i]); - if (isExp) { - if (len > 1) { - if (baseOut == 16 || baseOut == 8) { - i = baseOut == 16 ? 4 : 3; - for (--len; len % i; len++) str += "0"; - xd = convertBase(str, base, baseOut); - for (len = xd.length; !xd[len - 1]; --len) ; - for (i = 1, str = "1."; i < len; i++) str += NUMERALS.charAt(xd[i]); - } else { - str = str.charAt(0) + "." + str.slice(1); - } - } - str = str + (e < 0 ? "p" : "p+") + e; - } else if (e < 0) { - for (; ++e; ) str = "0" + str; - str = "0." + str; - } else { - if (++e > len) for (e -= len; e--; ) str += "0"; - else if (e < len) str = str.slice(0, e) + "." + str.slice(e); - } - } - str = (baseOut == 16 ? "0x" : baseOut == 2 ? "0b" : baseOut == 8 ? "0o" : "") + str; - } - return x.s < 0 ? "-" + str : str; - } - function truncate(arr, len) { - if (arr.length > len) { - arr.length = len; - return true; - } - } - function abs(x) { - return new this(x).abs(); - } - function acos(x) { - return new this(x).acos(); - } - function acosh(x) { - return new this(x).acosh(); - } - function add(x, y) { - return new this(x).plus(y); - } - function asin(x) { - return new this(x).asin(); - } - function asinh(x) { - return new this(x).asinh(); - } - function atan(x) { - return new this(x).atan(); - } - function atanh(x) { - return new this(x).atanh(); - } - function atan2(y, x) { - y = new this(y); - x = new this(x); - var r, pr = this.precision, rm = this.rounding, wpr = pr + 4; - if (!y.s || !x.s) { - r = new this(NaN); - } else if (!y.d && !x.d) { - r = getPi(this, wpr, 1).times(x.s > 0 ? 0.25 : 0.75); - r.s = y.s; - } else if (!x.d || y.isZero()) { - r = x.s < 0 ? getPi(this, pr, rm) : new this(0); - r.s = y.s; - } else if (!y.d || x.isZero()) { - r = getPi(this, wpr, 1).times(0.5); - r.s = y.s; - } else if (x.s < 0) { - this.precision = wpr; - this.rounding = 1; - r = this.atan(divide(y, x, wpr, 1)); - x = getPi(this, wpr, 1); - this.precision = pr; - this.rounding = rm; - r = y.s < 0 ? r.minus(x) : r.plus(x); - } else { - r = this.atan(divide(y, x, wpr, 1)); - } - return r; - } - function cbrt(x) { - return new this(x).cbrt(); - } - function ceil(x) { - return finalise(x = new this(x), x.e + 1, 2); - } - function clamp(x, min2, max2) { - return new this(x).clamp(min2, max2); - } - function config(obj) { - if (!obj || typeof obj !== "object") throw Error(decimalError + "Object expected"); - var i, p, v, useDefaults = obj.defaults === true, ps = [ - "precision", - 1, - MAX_DIGITS, - "rounding", - 0, - 8, - "toExpNeg", - -EXP_LIMIT, - 0, - "toExpPos", - 0, - EXP_LIMIT, - "maxE", - 0, - EXP_LIMIT, - "minE", - -EXP_LIMIT, - 0, - "modulo", - 0, - 9 - ]; - for (i = 0; i < ps.length; i += 3) { - if (p = ps[i], useDefaults) this[p] = DEFAULTS[p]; - if ((v = obj[p]) !== void 0) { - if (mathfloor(v) === v && v >= ps[i + 1] && v <= ps[i + 2]) this[p] = v; - else throw Error(invalidArgument + p + ": " + v); - } - } - if (p = "crypto", useDefaults) this[p] = DEFAULTS[p]; - if ((v = obj[p]) !== void 0) { - if (v === true || v === false || v === 0 || v === 1) { - if (v) { - if (typeof crypto != "undefined" && crypto && (crypto.getRandomValues || crypto.randomBytes)) { - this[p] = true; - } else { - throw Error(cryptoUnavailable); - } - } else { - this[p] = false; - } - } else { - throw Error(invalidArgument + p + ": " + v); - } - } - return this; - } - function cos(x) { - return new this(x).cos(); - } - function cosh(x) { - return new this(x).cosh(); - } - function clone(obj) { - var i, p, ps; - function Decimal2(v) { - var e, i2, t, x = this; - if (!(x instanceof Decimal2)) return new Decimal2(v); - x.constructor = Decimal2; - if (isDecimalInstance(v)) { - x.s = v.s; - if (external) { - if (!v.d || v.e > Decimal2.maxE) { - x.e = NaN; - x.d = null; - } else if (v.e < Decimal2.minE) { - x.e = 0; - x.d = [0]; - } else { - x.e = v.e; - x.d = v.d.slice(); - } - } else { - x.e = v.e; - x.d = v.d ? v.d.slice() : v.d; - } - return; - } - t = typeof v; - if (t === "number") { - if (v === 0) { - x.s = 1 / v < 0 ? -1 : 1; - x.e = 0; - x.d = [0]; - return; - } - if (v < 0) { - v = -v; - x.s = -1; - } else { - x.s = 1; - } - if (v === ~~v && v < 1e7) { - for (e = 0, i2 = v; i2 >= 10; i2 /= 10) e++; - if (external) { - if (e > Decimal2.maxE) { - x.e = NaN; - x.d = null; - } else if (e < Decimal2.minE) { - x.e = 0; - x.d = [0]; - } else { - x.e = e; - x.d = [v]; - } - } else { - x.e = e; - x.d = [v]; - } - return; - } else if (v * 0 !== 0) { - if (!v) x.s = NaN; - x.e = NaN; - x.d = null; - return; - } - return parseDecimal(x, v.toString()); - } else if (t !== "string") { - throw Error(invalidArgument + v); - } - if ((i2 = v.charCodeAt(0)) === 45) { - v = v.slice(1); - x.s = -1; - } else { - if (i2 === 43) v = v.slice(1); - x.s = 1; - } - return isDecimal.test(v) ? parseDecimal(x, v) : parseOther(x, v); - } - Decimal2.prototype = P; - Decimal2.ROUND_UP = 0; - Decimal2.ROUND_DOWN = 1; - Decimal2.ROUND_CEIL = 2; - Decimal2.ROUND_FLOOR = 3; - Decimal2.ROUND_HALF_UP = 4; - Decimal2.ROUND_HALF_DOWN = 5; - Decimal2.ROUND_HALF_EVEN = 6; - Decimal2.ROUND_HALF_CEIL = 7; - Decimal2.ROUND_HALF_FLOOR = 8; - Decimal2.EUCLID = 9; - Decimal2.config = Decimal2.set = config; - Decimal2.clone = clone; - Decimal2.isDecimal = isDecimalInstance; - Decimal2.abs = abs; - Decimal2.acos = acos; - Decimal2.acosh = acosh; - Decimal2.add = add; - Decimal2.asin = asin; - Decimal2.asinh = asinh; - Decimal2.atan = atan; - Decimal2.atanh = atanh; - Decimal2.atan2 = atan2; - Decimal2.cbrt = cbrt; - Decimal2.ceil = ceil; - Decimal2.clamp = clamp; - Decimal2.cos = cos; - Decimal2.cosh = cosh; - Decimal2.div = div; - Decimal2.exp = exp; - Decimal2.floor = floor; - Decimal2.hypot = hypot; - Decimal2.ln = ln; - Decimal2.log = log; - Decimal2.log10 = log10; - Decimal2.log2 = log2; - Decimal2.max = max; - Decimal2.min = min; - Decimal2.mod = mod; - Decimal2.mul = mul; - Decimal2.pow = pow; - Decimal2.random = random; - Decimal2.round = round; - Decimal2.sign = sign; - Decimal2.sin = sin; - Decimal2.sinh = sinh; - Decimal2.sqrt = sqrt; - Decimal2.sub = sub; - Decimal2.sum = sum; - Decimal2.tan = tan; - Decimal2.tanh = tanh; - Decimal2.trunc = trunc; - if (obj === void 0) obj = {}; - if (obj) { - if (obj.defaults !== true) { - ps = ["precision", "rounding", "toExpNeg", "toExpPos", "maxE", "minE", "modulo", "crypto"]; - for (i = 0; i < ps.length; ) if (!obj.hasOwnProperty(p = ps[i++])) obj[p] = this[p]; - } - } - Decimal2.config(obj); - return Decimal2; - } - function div(x, y) { - return new this(x).div(y); - } - function exp(x) { - return new this(x).exp(); - } - function floor(x) { - return finalise(x = new this(x), x.e + 1, 3); - } - function hypot() { - var i, n, t = new this(0); - external = false; - for (i = 0; i < arguments.length; ) { - n = new this(arguments[i++]); - if (!n.d) { - if (n.s) { - external = true; - return new this(1 / 0); - } - t = n; - } else if (t.d) { - t = t.plus(n.times(n)); - } - } - external = true; - return t.sqrt(); - } - function isDecimalInstance(obj) { - return obj instanceof Decimal || obj && obj.toStringTag === tag || false; - } - function ln(x) { - return new this(x).ln(); - } - function log(x, y) { - return new this(x).log(y); - } - function log2(x) { - return new this(x).log(2); - } - function log10(x) { - return new this(x).log(10); - } - function max() { - return maxOrMin(this, arguments, "lt"); - } - function min() { - return maxOrMin(this, arguments, "gt"); - } - function mod(x, y) { - return new this(x).mod(y); - } - function mul(x, y) { - return new this(x).mul(y); - } - function pow(x, y) { - return new this(x).pow(y); - } - function random(sd) { - var d, e, k, n, i = 0, r = new this(1), rd = []; - if (sd === void 0) sd = this.precision; - else checkInt32(sd, 1, MAX_DIGITS); - k = Math.ceil(sd / LOG_BASE); - if (!this.crypto) { - for (; i < k; ) rd[i++] = Math.random() * 1e7 | 0; - } else if (crypto.getRandomValues) { - d = crypto.getRandomValues(new Uint32Array(k)); - for (; i < k; ) { - n = d[i]; - if (n >= 429e7) { - d[i] = crypto.getRandomValues(new Uint32Array(1))[0]; - } else { - rd[i++] = n % 1e7; - } - } - } else if (crypto.randomBytes) { - d = crypto.randomBytes(k *= 4); - for (; i < k; ) { - n = d[i] + (d[i + 1] << 8) + (d[i + 2] << 16) + ((d[i + 3] & 127) << 24); - if (n >= 214e7) { - crypto.randomBytes(4).copy(d, i); - } else { - rd.push(n % 1e7); - i += 4; - } - } - i = k / 4; - } else { - throw Error(cryptoUnavailable); - } - k = rd[--i]; - sd %= LOG_BASE; - if (k && sd) { - n = mathpow(10, LOG_BASE - sd); - rd[i] = (k / n | 0) * n; - } - for (; rd[i] === 0; i--) rd.pop(); - if (i < 0) { - e = 0; - rd = [0]; - } else { - e = -1; - for (; rd[0] === 0; e -= LOG_BASE) rd.shift(); - for (k = 1, n = rd[0]; n >= 10; n /= 10) k++; - if (k < LOG_BASE) e -= LOG_BASE - k; - } - r.e = e; - r.d = rd; - return r; - } - function round(x) { - return finalise(x = new this(x), x.e + 1, this.rounding); - } - function sign(x) { - x = new this(x); - return x.d ? x.d[0] ? x.s : 0 * x.s : x.s || NaN; - } - function sin(x) { - return new this(x).sin(); - } - function sinh(x) { - return new this(x).sinh(); - } - function sqrt(x) { - return new this(x).sqrt(); - } - function sub(x, y) { - return new this(x).sub(y); - } - function sum() { - var i = 0, args = arguments, x = new this(args[i]); - external = false; - for (; x.s && ++i < args.length; ) x = x.plus(args[i]); - external = true; - return finalise(x, this.precision, this.rounding); - } - function tan(x) { - return new this(x).tan(); - } - function tanh(x) { - return new this(x).tanh(); - } - function trunc(x) { - return finalise(x = new this(x), x.e + 1, 1); - } - Decimal = clone(DEFAULTS); - Decimal.prototype.constructor = Decimal; - Decimal["default"] = Decimal.Decimal = Decimal; - LN10 = new Decimal(LN10); - PI = new Decimal(PI); - if (typeof define == "function" && define.amd) { - define(function() { - return Decimal; - }); - } else if (typeof module2 != "undefined" && module2.exports) { - if (typeof Symbol == "function" && typeof Symbol.iterator == "symbol") { - P[Symbol["for"]("nodejs.util.inspect.custom")] = P.toString; - P[Symbol.toStringTag] = "Decimal"; - } - module2.exports = Decimal; - } else { - if (!globalScope) { - globalScope = typeof self != "undefined" && self && self.self == self ? self : window; - } - noConflict = globalScope.Decimal; - Decimal.noConflict = function() { - globalScope.Decimal = noConflict; - return Decimal; - }; - globalScope.Decimal = Decimal; - } - })(exports); - } -}); - -// node_modules/lodash/lodash.js -var require_lodash = __commonJS({ - "node_modules/lodash/lodash.js"(exports, module2) { - (function() { - var undefined2; - var VERSION = "4.17.21"; - var LARGE_ARRAY_SIZE = 200; - var CORE_ERROR_TEXT = "Unsupported core-js use. Try https://npms.io/search?q=ponyfill.", FUNC_ERROR_TEXT = "Expected a function", INVALID_TEMPL_VAR_ERROR_TEXT = "Invalid `variable` option passed into `_.template`"; - var HASH_UNDEFINED = "__lodash_hash_undefined__"; - var MAX_MEMOIZE_SIZE = 500; - var PLACEHOLDER = "__lodash_placeholder__"; - var CLONE_DEEP_FLAG = 1, CLONE_FLAT_FLAG = 2, CLONE_SYMBOLS_FLAG = 4; - var COMPARE_PARTIAL_FLAG = 1, COMPARE_UNORDERED_FLAG = 2; - var WRAP_BIND_FLAG = 1, WRAP_BIND_KEY_FLAG = 2, WRAP_CURRY_BOUND_FLAG = 4, WRAP_CURRY_FLAG = 8, WRAP_CURRY_RIGHT_FLAG = 16, WRAP_PARTIAL_FLAG = 32, WRAP_PARTIAL_RIGHT_FLAG = 64, WRAP_ARY_FLAG = 128, WRAP_REARG_FLAG = 256, WRAP_FLIP_FLAG = 512; - var DEFAULT_TRUNC_LENGTH = 30, DEFAULT_TRUNC_OMISSION = "..."; - var HOT_COUNT = 800, HOT_SPAN = 16; - var LAZY_FILTER_FLAG = 1, LAZY_MAP_FLAG = 2, LAZY_WHILE_FLAG = 3; - var INFINITY = 1 / 0, MAX_SAFE_INTEGER = 9007199254740991, MAX_INTEGER = 17976931348623157e292, NAN = 0 / 0; - var MAX_ARRAY_LENGTH = 4294967295, MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1, HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1; - var wrapFlags = [ - ["ary", WRAP_ARY_FLAG], - ["bind", WRAP_BIND_FLAG], - ["bindKey", WRAP_BIND_KEY_FLAG], - ["curry", WRAP_CURRY_FLAG], - ["curryRight", WRAP_CURRY_RIGHT_FLAG], - ["flip", WRAP_FLIP_FLAG], - ["partial", WRAP_PARTIAL_FLAG], - ["partialRight", WRAP_PARTIAL_RIGHT_FLAG], - ["rearg", WRAP_REARG_FLAG] - ]; - var argsTag = "[object Arguments]", arrayTag = "[object Array]", asyncTag = "[object AsyncFunction]", boolTag = "[object Boolean]", dateTag = "[object Date]", domExcTag = "[object DOMException]", errorTag = "[object Error]", funcTag = "[object Function]", genTag = "[object GeneratorFunction]", mapTag = "[object Map]", numberTag = "[object Number]", nullTag = "[object Null]", objectTag = "[object Object]", promiseTag = "[object Promise]", proxyTag = "[object Proxy]", regexpTag = "[object RegExp]", setTag = "[object Set]", stringTag = "[object String]", symbolTag = "[object Symbol]", undefinedTag = "[object Undefined]", weakMapTag = "[object WeakMap]", weakSetTag = "[object WeakSet]"; - var arrayBufferTag = "[object ArrayBuffer]", dataViewTag = "[object DataView]", float32Tag = "[object Float32Array]", float64Tag = "[object Float64Array]", int8Tag = "[object Int8Array]", int16Tag = "[object Int16Array]", int32Tag = "[object Int32Array]", uint8Tag = "[object Uint8Array]", uint8ClampedTag = "[object Uint8ClampedArray]", uint16Tag = "[object Uint16Array]", uint32Tag = "[object Uint32Array]"; - var reEmptyStringLeading = /\b__p \+= '';/g, reEmptyStringMiddle = /\b(__p \+=) '' \+/g, reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; - var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g, reUnescapedHtml = /[&<>"']/g, reHasEscapedHtml = RegExp(reEscapedHtml.source), reHasUnescapedHtml = RegExp(reUnescapedHtml.source); - var reEscape = /<%-([\s\S]+?)%>/g, reEvaluate = /<%([\s\S]+?)%>/g, reInterpolate = /<%=([\s\S]+?)%>/g; - var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, reIsPlainProp = /^\w*$/, rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g; - var reRegExpChar = /[\\^$.*+?()[\]{}|]/g, reHasRegExpChar = RegExp(reRegExpChar.source); - var reTrimStart = /^\s+/; - var reWhitespace = /\s/; - var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/, reWrapDetails = /\{\n\/\* \[wrapped with (.+)\] \*/, reSplitDetails = /,? & /; - var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g; - var reForbiddenIdentifierChars = /[()=,{}\[\]\/\s]/; - var reEscapeChar = /\\(\\)?/g; - var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; - var reFlags = /\w*$/; - var reIsBadHex = /^[-+]0x[0-9a-f]+$/i; - var reIsBinary = /^0b[01]+$/i; - var reIsHostCtor = /^\[object .+?Constructor\]$/; - var reIsOctal = /^0o[0-7]+$/i; - var reIsUint = /^(?:0|[1-9]\d*)$/; - var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g; - var reNoMatch = /($^)/; - var reUnescapedString = /['\n\r\u2028\u2029\\]/g; - var rsAstralRange = "\\ud800-\\udfff", rsComboMarksRange = "\\u0300-\\u036f", reComboHalfMarksRange = "\\ufe20-\\ufe2f", rsComboSymbolsRange = "\\u20d0-\\u20ff", rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange, rsDingbatRange = "\\u2700-\\u27bf", rsLowerRange = "a-z\\xdf-\\xf6\\xf8-\\xff", rsMathOpRange = "\\xac\\xb1\\xd7\\xf7", rsNonCharRange = "\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf", rsPunctuationRange = "\\u2000-\\u206f", rsSpaceRange = " \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000", rsUpperRange = "A-Z\\xc0-\\xd6\\xd8-\\xde", rsVarRange = "\\ufe0e\\ufe0f", rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange; - var rsApos = "['\u2019]", rsAstral = "[" + rsAstralRange + "]", rsBreak = "[" + rsBreakRange + "]", rsCombo = "[" + rsComboRange + "]", rsDigits = "\\d+", rsDingbat = "[" + rsDingbatRange + "]", rsLower = "[" + rsLowerRange + "]", rsMisc = "[^" + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + "]", rsFitz = "\\ud83c[\\udffb-\\udfff]", rsModifier = "(?:" + rsCombo + "|" + rsFitz + ")", rsNonAstral = "[^" + rsAstralRange + "]", rsRegional = "(?:\\ud83c[\\udde6-\\uddff]){2}", rsSurrPair = "[\\ud800-\\udbff][\\udc00-\\udfff]", rsUpper = "[" + rsUpperRange + "]", rsZWJ = "\\u200d"; - var rsMiscLower = "(?:" + rsLower + "|" + rsMisc + ")", rsMiscUpper = "(?:" + rsUpper + "|" + rsMisc + ")", rsOptContrLower = "(?:" + rsApos + "(?:d|ll|m|re|s|t|ve))?", rsOptContrUpper = "(?:" + rsApos + "(?:D|LL|M|RE|S|T|VE))?", reOptMod = rsModifier + "?", rsOptVar = "[" + rsVarRange + "]?", rsOptJoin = "(?:" + rsZWJ + "(?:" + [rsNonAstral, rsRegional, rsSurrPair].join("|") + ")" + rsOptVar + reOptMod + ")*", rsOrdLower = "\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])", rsOrdUpper = "\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])", rsSeq = rsOptVar + reOptMod + rsOptJoin, rsEmoji = "(?:" + [rsDingbat, rsRegional, rsSurrPair].join("|") + ")" + rsSeq, rsSymbol = "(?:" + [rsNonAstral + rsCombo + "?", rsCombo, rsRegional, rsSurrPair, rsAstral].join("|") + ")"; - var reApos = RegExp(rsApos, "g"); - var reComboMark = RegExp(rsCombo, "g"); - var reUnicode = RegExp(rsFitz + "(?=" + rsFitz + ")|" + rsSymbol + rsSeq, "g"); - var reUnicodeWord = RegExp([ - rsUpper + "?" + rsLower + "+" + rsOptContrLower + "(?=" + [rsBreak, rsUpper, "$"].join("|") + ")", - rsMiscUpper + "+" + rsOptContrUpper + "(?=" + [rsBreak, rsUpper + rsMiscLower, "$"].join("|") + ")", - rsUpper + "?" + rsMiscLower + "+" + rsOptContrLower, - rsUpper + "+" + rsOptContrUpper, - rsOrdUpper, - rsOrdLower, - rsDigits, - rsEmoji - ].join("|"), "g"); - var reHasUnicode = RegExp("[" + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + "]"); - var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/; - var contextProps = [ - "Array", - "Buffer", - "DataView", - "Date", - "Error", - "Float32Array", - "Float64Array", - "Function", - "Int8Array", - "Int16Array", - "Int32Array", - "Map", - "Math", - "Object", - "Promise", - "RegExp", - "Set", - "String", - "Symbol", - "TypeError", - "Uint8Array", - "Uint8ClampedArray", - "Uint16Array", - "Uint32Array", - "WeakMap", - "_", - "clearTimeout", - "isFinite", - "parseInt", - "setTimeout" - ]; - var templateCounter = -1; - var typedArrayTags = {}; - typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = typedArrayTags[uint32Tag] = true; - typedArrayTags[argsTag] = typedArrayTags[arrayTag] = typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = typedArrayTags[dataViewTag] = typedArrayTags[dateTag] = typedArrayTags[errorTag] = typedArrayTags[funcTag] = typedArrayTags[mapTag] = typedArrayTags[numberTag] = typedArrayTags[objectTag] = typedArrayTags[regexpTag] = typedArrayTags[setTag] = typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false; - var cloneableTags = {}; - cloneableTags[argsTag] = cloneableTags[arrayTag] = cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] = cloneableTags[boolTag] = cloneableTags[dateTag] = cloneableTags[float32Tag] = cloneableTags[float64Tag] = cloneableTags[int8Tag] = cloneableTags[int16Tag] = cloneableTags[int32Tag] = cloneableTags[mapTag] = cloneableTags[numberTag] = cloneableTags[objectTag] = cloneableTags[regexpTag] = cloneableTags[setTag] = cloneableTags[stringTag] = cloneableTags[symbolTag] = cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true; - cloneableTags[errorTag] = cloneableTags[funcTag] = cloneableTags[weakMapTag] = false; - var deburredLetters = { - // Latin-1 Supplement block. - "\xC0": "A", - "\xC1": "A", - "\xC2": "A", - "\xC3": "A", - "\xC4": "A", - "\xC5": "A", - "\xE0": "a", - "\xE1": "a", - "\xE2": "a", - "\xE3": "a", - "\xE4": "a", - "\xE5": "a", - "\xC7": "C", - "\xE7": "c", - "\xD0": "D", - "\xF0": "d", - "\xC8": "E", - "\xC9": "E", - "\xCA": "E", - "\xCB": "E", - "\xE8": "e", - "\xE9": "e", - "\xEA": "e", - "\xEB": "e", - "\xCC": "I", - "\xCD": "I", - "\xCE": "I", - "\xCF": "I", - "\xEC": "i", - "\xED": "i", - "\xEE": "i", - "\xEF": "i", - "\xD1": "N", - "\xF1": "n", - "\xD2": "O", - "\xD3": "O", - "\xD4": "O", - "\xD5": "O", - "\xD6": "O", - "\xD8": "O", - "\xF2": "o", - "\xF3": "o", - "\xF4": "o", - "\xF5": "o", - "\xF6": "o", - "\xF8": "o", - "\xD9": "U", - "\xDA": "U", - "\xDB": "U", - "\xDC": "U", - "\xF9": "u", - "\xFA": "u", - "\xFB": "u", - "\xFC": "u", - "\xDD": "Y", - "\xFD": "y", - "\xFF": "y", - "\xC6": "Ae", - "\xE6": "ae", - "\xDE": "Th", - "\xFE": "th", - "\xDF": "ss", - // Latin Extended-A block. - "\u0100": "A", - "\u0102": "A", - "\u0104": "A", - "\u0101": "a", - "\u0103": "a", - "\u0105": "a", - "\u0106": "C", - "\u0108": "C", - "\u010A": "C", - "\u010C": "C", - "\u0107": "c", - "\u0109": "c", - "\u010B": "c", - "\u010D": "c", - "\u010E": "D", - "\u0110": "D", - "\u010F": "d", - "\u0111": "d", - "\u0112": "E", - "\u0114": "E", - "\u0116": "E", - "\u0118": "E", - "\u011A": "E", - "\u0113": "e", - "\u0115": "e", - "\u0117": "e", - "\u0119": "e", - "\u011B": "e", - "\u011C": "G", - "\u011E": "G", - "\u0120": "G", - "\u0122": "G", - "\u011D": "g", - "\u011F": "g", - "\u0121": "g", - "\u0123": "g", - "\u0124": "H", - "\u0126": "H", - "\u0125": "h", - "\u0127": "h", - "\u0128": "I", - "\u012A": "I", - "\u012C": "I", - "\u012E": "I", - "\u0130": "I", - "\u0129": "i", - "\u012B": "i", - "\u012D": "i", - "\u012F": "i", - "\u0131": "i", - "\u0134": "J", - "\u0135": "j", - "\u0136": "K", - "\u0137": "k", - "\u0138": "k", - "\u0139": "L", - "\u013B": "L", - "\u013D": "L", - "\u013F": "L", - "\u0141": "L", - "\u013A": "l", - "\u013C": "l", - "\u013E": "l", - "\u0140": "l", - "\u0142": "l", - "\u0143": "N", - "\u0145": "N", - "\u0147": "N", - "\u014A": "N", - "\u0144": "n", - "\u0146": "n", - "\u0148": "n", - "\u014B": "n", - "\u014C": "O", - "\u014E": "O", - "\u0150": "O", - "\u014D": "o", - "\u014F": "o", - "\u0151": "o", - "\u0154": "R", - "\u0156": "R", - "\u0158": "R", - "\u0155": "r", - "\u0157": "r", - "\u0159": "r", - "\u015A": "S", - "\u015C": "S", - "\u015E": "S", - "\u0160": "S", - "\u015B": "s", - "\u015D": "s", - "\u015F": "s", - "\u0161": "s", - "\u0162": "T", - "\u0164": "T", - "\u0166": "T", - "\u0163": "t", - "\u0165": "t", - "\u0167": "t", - "\u0168": "U", - "\u016A": "U", - "\u016C": "U", - "\u016E": "U", - "\u0170": "U", - "\u0172": "U", - "\u0169": "u", - "\u016B": "u", - "\u016D": "u", - "\u016F": "u", - "\u0171": "u", - "\u0173": "u", - "\u0174": "W", - "\u0175": "w", - "\u0176": "Y", - "\u0177": "y", - "\u0178": "Y", - "\u0179": "Z", - "\u017B": "Z", - "\u017D": "Z", - "\u017A": "z", - "\u017C": "z", - "\u017E": "z", - "\u0132": "IJ", - "\u0133": "ij", - "\u0152": "Oe", - "\u0153": "oe", - "\u0149": "'n", - "\u017F": "s" - }; - var htmlEscapes = { - "&": "&", - "<": "<", - ">": ">", - '"': """, - "'": "'" - }; - var htmlUnescapes = { - "&": "&", - "<": "<", - ">": ">", - """: '"', - "'": "'" - }; - var stringEscapes = { - "\\": "\\", - "'": "'", - "\n": "n", - "\r": "r", - "\u2028": "u2028", - "\u2029": "u2029" - }; - var freeParseFloat = parseFloat, freeParseInt = parseInt; - var freeGlobal = typeof global == "object" && global && global.Object === Object && global; - var freeSelf = typeof self == "object" && self && self.Object === Object && self; - var root = freeGlobal || freeSelf || Function("return this")(); - var freeExports = typeof exports == "object" && exports && !exports.nodeType && exports; - var freeModule = freeExports && typeof module2 == "object" && module2 && !module2.nodeType && module2; - var moduleExports = freeModule && freeModule.exports === freeExports; - var freeProcess = moduleExports && freeGlobal.process; - var nodeUtil = function() { - try { - var types = freeModule && freeModule.require && freeModule.require("util").types; - if (types) { - return types; - } - return freeProcess && freeProcess.binding && freeProcess.binding("util"); - } catch (e) { - } - }(); - var nodeIsArrayBuffer = nodeUtil && nodeUtil.isArrayBuffer, nodeIsDate = nodeUtil && nodeUtil.isDate, nodeIsMap = nodeUtil && nodeUtil.isMap, nodeIsRegExp = nodeUtil && nodeUtil.isRegExp, nodeIsSet = nodeUtil && nodeUtil.isSet, nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray; - function apply(func, thisArg, args) { - switch (args.length) { - case 0: - return func.call(thisArg); - case 1: - return func.call(thisArg, args[0]); - case 2: - return func.call(thisArg, args[0], args[1]); - case 3: - return func.call(thisArg, args[0], args[1], args[2]); - } - return func.apply(thisArg, args); - } - function arrayAggregator(array, setter, iteratee, accumulator) { - var index = -1, length = array == null ? 0 : array.length; - while (++index < length) { - var value = array[index]; - setter(accumulator, value, iteratee(value), array); - } - return accumulator; - } - function arrayEach(array, iteratee) { - var index = -1, length = array == null ? 0 : array.length; - while (++index < length) { - if (iteratee(array[index], index, array) === false) { - break; - } - } - return array; - } - function arrayEachRight(array, iteratee) { - var length = array == null ? 0 : array.length; - while (length--) { - if (iteratee(array[length], length, array) === false) { - break; - } - } - return array; - } - function arrayEvery(array, predicate) { - var index = -1, length = array == null ? 0 : array.length; - while (++index < length) { - if (!predicate(array[index], index, array)) { - return false; - } - } - return true; - } - function arrayFilter(array, predicate) { - var index = -1, length = array == null ? 0 : array.length, resIndex = 0, result = []; - while (++index < length) { - var value = array[index]; - if (predicate(value, index, array)) { - result[resIndex++] = value; - } - } - return result; - } - function arrayIncludes(array, value) { - var length = array == null ? 0 : array.length; - return !!length && baseIndexOf(array, value, 0) > -1; - } - function arrayIncludesWith(array, value, comparator) { - var index = -1, length = array == null ? 0 : array.length; - while (++index < length) { - if (comparator(value, array[index])) { - return true; - } - } - return false; - } - function arrayMap(array, iteratee) { - var index = -1, length = array == null ? 0 : array.length, result = Array(length); - while (++index < length) { - result[index] = iteratee(array[index], index, array); - } - return result; - } - function arrayPush(array, values) { - var index = -1, length = values.length, offset = array.length; - while (++index < length) { - array[offset + index] = values[index]; - } - return array; - } - function arrayReduce(array, iteratee, accumulator, initAccum) { - var index = -1, length = array == null ? 0 : array.length; - if (initAccum && length) { - accumulator = array[++index]; - } - while (++index < length) { - accumulator = iteratee(accumulator, array[index], index, array); - } - return accumulator; - } - function arrayReduceRight(array, iteratee, accumulator, initAccum) { - var length = array == null ? 0 : array.length; - if (initAccum && length) { - accumulator = array[--length]; - } - while (length--) { - accumulator = iteratee(accumulator, array[length], length, array); - } - return accumulator; - } - function arraySome(array, predicate) { - var index = -1, length = array == null ? 0 : array.length; - while (++index < length) { - if (predicate(array[index], index, array)) { - return true; - } - } - return false; - } - var asciiSize = baseProperty("length"); - function asciiToArray(string) { - return string.split(""); - } - function asciiWords(string) { - return string.match(reAsciiWord) || []; - } - function baseFindKey(collection, predicate, eachFunc) { - var result; - eachFunc(collection, function(value, key, collection2) { - if (predicate(value, key, collection2)) { - result = key; - return false; - } - }); - return result; - } - function baseFindIndex(array, predicate, fromIndex, fromRight) { - var length = array.length, index = fromIndex + (fromRight ? 1 : -1); - while (fromRight ? index-- : ++index < length) { - if (predicate(array[index], index, array)) { - return index; - } - } - return -1; - } - function baseIndexOf(array, value, fromIndex) { - return value === value ? strictIndexOf(array, value, fromIndex) : baseFindIndex(array, baseIsNaN, fromIndex); - } - function baseIndexOfWith(array, value, fromIndex, comparator) { - var index = fromIndex - 1, length = array.length; - while (++index < length) { - if (comparator(array[index], value)) { - return index; - } - } - return -1; - } - function baseIsNaN(value) { - return value !== value; - } - function baseMean(array, iteratee) { - var length = array == null ? 0 : array.length; - return length ? baseSum(array, iteratee) / length : NAN; - } - function baseProperty(key) { - return function(object) { - return object == null ? undefined2 : object[key]; - }; - } - function basePropertyOf(object) { - return function(key) { - return object == null ? undefined2 : object[key]; - }; - } - function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) { - eachFunc(collection, function(value, index, collection2) { - accumulator = initAccum ? (initAccum = false, value) : iteratee(accumulator, value, index, collection2); - }); - return accumulator; - } - function baseSortBy(array, comparer) { - var length = array.length; - array.sort(comparer); - while (length--) { - array[length] = array[length].value; - } - return array; - } - function baseSum(array, iteratee) { - var result, index = -1, length = array.length; - while (++index < length) { - var current = iteratee(array[index]); - if (current !== undefined2) { - result = result === undefined2 ? current : result + current; - } - } - return result; - } - function baseTimes(n, iteratee) { - var index = -1, result = Array(n); - while (++index < n) { - result[index] = iteratee(index); - } - return result; - } - function baseToPairs(object, props) { - return arrayMap(props, function(key) { - return [key, object[key]]; - }); - } - function baseTrim(string) { - return string ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, "") : string; - } - function baseUnary(func) { - return function(value) { - return func(value); - }; - } - function baseValues(object, props) { - return arrayMap(props, function(key) { - return object[key]; - }); - } - function cacheHas(cache, key) { - return cache.has(key); - } - function charsStartIndex(strSymbols, chrSymbols) { - var index = -1, length = strSymbols.length; - while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) { - } - return index; - } - function charsEndIndex(strSymbols, chrSymbols) { - var index = strSymbols.length; - while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) { - } - return index; - } - function countHolders(array, placeholder) { - var length = array.length, result = 0; - while (length--) { - if (array[length] === placeholder) { - ++result; - } - } - return result; - } - var deburrLetter = basePropertyOf(deburredLetters); - var escapeHtmlChar = basePropertyOf(htmlEscapes); - function escapeStringChar(chr) { - return "\\" + stringEscapes[chr]; - } - function getValue(object, key) { - return object == null ? undefined2 : object[key]; - } - function hasUnicode(string) { - return reHasUnicode.test(string); - } - function hasUnicodeWord(string) { - return reHasUnicodeWord.test(string); - } - function iteratorToArray(iterator) { - var data, result = []; - while (!(data = iterator.next()).done) { - result.push(data.value); - } - return result; - } - function mapToArray(map) { - var index = -1, result = Array(map.size); - map.forEach(function(value, key) { - result[++index] = [key, value]; - }); - return result; - } - function overArg(func, transform) { - return function(arg) { - return func(transform(arg)); - }; - } - function replaceHolders(array, placeholder) { - var index = -1, length = array.length, resIndex = 0, result = []; - while (++index < length) { - var value = array[index]; - if (value === placeholder || value === PLACEHOLDER) { - array[index] = PLACEHOLDER; - result[resIndex++] = index; - } - } - return result; - } - function setToArray(set) { - var index = -1, result = Array(set.size); - set.forEach(function(value) { - result[++index] = value; - }); - return result; - } - function setToPairs(set) { - var index = -1, result = Array(set.size); - set.forEach(function(value) { - result[++index] = [value, value]; - }); - return result; - } - function strictIndexOf(array, value, fromIndex) { - var index = fromIndex - 1, length = array.length; - while (++index < length) { - if (array[index] === value) { - return index; - } - } - return -1; - } - function strictLastIndexOf(array, value, fromIndex) { - var index = fromIndex + 1; - while (index--) { - if (array[index] === value) { - return index; - } - } - return index; - } - function stringSize(string) { - return hasUnicode(string) ? unicodeSize(string) : asciiSize(string); - } - function stringToArray(string) { - return hasUnicode(string) ? unicodeToArray(string) : asciiToArray(string); - } - function trimmedEndIndex(string) { - var index = string.length; - while (index-- && reWhitespace.test(string.charAt(index))) { - } - return index; - } - var unescapeHtmlChar = basePropertyOf(htmlUnescapes); - function unicodeSize(string) { - var result = reUnicode.lastIndex = 0; - while (reUnicode.test(string)) { - ++result; - } - return result; - } - function unicodeToArray(string) { - return string.match(reUnicode) || []; - } - function unicodeWords(string) { - return string.match(reUnicodeWord) || []; - } - var runInContext = function runInContext2(context) { - context = context == null ? root : _.defaults(root.Object(), context, _.pick(root, contextProps)); - var Array2 = context.Array, Date2 = context.Date, Error2 = context.Error, Function2 = context.Function, Math2 = context.Math, Object2 = context.Object, RegExp2 = context.RegExp, String2 = context.String, TypeError2 = context.TypeError; - var arrayProto = Array2.prototype, funcProto = Function2.prototype, objectProto = Object2.prototype; - var coreJsData = context["__core-js_shared__"]; - var funcToString = funcProto.toString; - var hasOwnProperty = objectProto.hasOwnProperty; - var idCounter = 0; - var maskSrcKey = function() { - var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || ""); - return uid ? "Symbol(src)_1." + uid : ""; - }(); - var nativeObjectToString = objectProto.toString; - var objectCtorString = funcToString.call(Object2); - var oldDash = root._; - var reIsNative = RegExp2( - "^" + funcToString.call(hasOwnProperty).replace(reRegExpChar, "\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, "$1.*?") + "$" - ); - var Buffer2 = moduleExports ? context.Buffer : undefined2, Symbol2 = context.Symbol, Uint8Array2 = context.Uint8Array, allocUnsafe = Buffer2 ? Buffer2.allocUnsafe : undefined2, getPrototype = overArg(Object2.getPrototypeOf, Object2), objectCreate = Object2.create, propertyIsEnumerable = objectProto.propertyIsEnumerable, splice = arrayProto.splice, spreadableSymbol = Symbol2 ? Symbol2.isConcatSpreadable : undefined2, symIterator = Symbol2 ? Symbol2.iterator : undefined2, symToStringTag = Symbol2 ? Symbol2.toStringTag : undefined2; - var defineProperty = function() { - try { - var func = getNative(Object2, "defineProperty"); - func({}, "", {}); - return func; - } catch (e) { - } - }(); - var ctxClearTimeout = context.clearTimeout !== root.clearTimeout && context.clearTimeout, ctxNow = Date2 && Date2.now !== root.Date.now && Date2.now, ctxSetTimeout = context.setTimeout !== root.setTimeout && context.setTimeout; - var nativeCeil = Math2.ceil, nativeFloor = Math2.floor, nativeGetSymbols = Object2.getOwnPropertySymbols, nativeIsBuffer = Buffer2 ? Buffer2.isBuffer : undefined2, nativeIsFinite = context.isFinite, nativeJoin = arrayProto.join, nativeKeys = overArg(Object2.keys, Object2), nativeMax = Math2.max, nativeMin = Math2.min, nativeNow = Date2.now, nativeParseInt = context.parseInt, nativeRandom = Math2.random, nativeReverse = arrayProto.reverse; - var DataView = getNative(context, "DataView"), Map = getNative(context, "Map"), Promise2 = getNative(context, "Promise"), Set2 = getNative(context, "Set"), WeakMap = getNative(context, "WeakMap"), nativeCreate = getNative(Object2, "create"); - var metaMap = WeakMap && new WeakMap(); - var realNames = {}; - var dataViewCtorString = toSource(DataView), mapCtorString = toSource(Map), promiseCtorString = toSource(Promise2), setCtorString = toSource(Set2), weakMapCtorString = toSource(WeakMap); - var symbolProto = Symbol2 ? Symbol2.prototype : undefined2, symbolValueOf = symbolProto ? symbolProto.valueOf : undefined2, symbolToString = symbolProto ? symbolProto.toString : undefined2; - function lodash(value) { - if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) { - if (value instanceof LodashWrapper) { - return value; - } - if (hasOwnProperty.call(value, "__wrapped__")) { - return wrapperClone(value); - } - } - return new LodashWrapper(value); - } - var baseCreate = /* @__PURE__ */ function() { - function object() { - } - return function(proto) { - if (!isObject(proto)) { - return {}; - } - if (objectCreate) { - return objectCreate(proto); - } - object.prototype = proto; - var result2 = new object(); - object.prototype = undefined2; - return result2; - }; - }(); - function baseLodash() { - } - function LodashWrapper(value, chainAll) { - this.__wrapped__ = value; - this.__actions__ = []; - this.__chain__ = !!chainAll; - this.__index__ = 0; - this.__values__ = undefined2; - } - lodash.templateSettings = { - /** - * Used to detect `data` property values to be HTML-escaped. - * - * @memberOf _.templateSettings - * @type {RegExp} - */ - "escape": reEscape, - /** - * Used to detect code to be evaluated. - * - * @memberOf _.templateSettings - * @type {RegExp} - */ - "evaluate": reEvaluate, - /** - * Used to detect `data` property values to inject. - * - * @memberOf _.templateSettings - * @type {RegExp} - */ - "interpolate": reInterpolate, - /** - * Used to reference the data object in the template text. - * - * @memberOf _.templateSettings - * @type {string} - */ - "variable": "", - /** - * Used to import variables into the compiled template. - * - * @memberOf _.templateSettings - * @type {Object} - */ - "imports": { - /** - * A reference to the `lodash` function. - * - * @memberOf _.templateSettings.imports - * @type {Function} - */ - "_": lodash - } - }; - lodash.prototype = baseLodash.prototype; - lodash.prototype.constructor = lodash; - LodashWrapper.prototype = baseCreate(baseLodash.prototype); - LodashWrapper.prototype.constructor = LodashWrapper; - function LazyWrapper(value) { - this.__wrapped__ = value; - this.__actions__ = []; - this.__dir__ = 1; - this.__filtered__ = false; - this.__iteratees__ = []; - this.__takeCount__ = MAX_ARRAY_LENGTH; - this.__views__ = []; - } - function lazyClone() { - var result2 = new LazyWrapper(this.__wrapped__); - result2.__actions__ = copyArray(this.__actions__); - result2.__dir__ = this.__dir__; - result2.__filtered__ = this.__filtered__; - result2.__iteratees__ = copyArray(this.__iteratees__); - result2.__takeCount__ = this.__takeCount__; - result2.__views__ = copyArray(this.__views__); - return result2; - } - function lazyReverse() { - if (this.__filtered__) { - var result2 = new LazyWrapper(this); - result2.__dir__ = -1; - result2.__filtered__ = true; - } else { - result2 = this.clone(); - result2.__dir__ *= -1; - } - return result2; - } - function lazyValue() { - var array = this.__wrapped__.value(), dir = this.__dir__, isArr = isArray(array), isRight = dir < 0, arrLength = isArr ? array.length : 0, view = getView(0, arrLength, this.__views__), start = view.start, end = view.end, length = end - start, index = isRight ? end : start - 1, iteratees = this.__iteratees__, iterLength = iteratees.length, resIndex = 0, takeCount = nativeMin(length, this.__takeCount__); - if (!isArr || !isRight && arrLength == length && takeCount == length) { - return baseWrapperValue(array, this.__actions__); - } - var result2 = []; - outer: - while (length-- && resIndex < takeCount) { - index += dir; - var iterIndex = -1, value = array[index]; - while (++iterIndex < iterLength) { - var data = iteratees[iterIndex], iteratee2 = data.iteratee, type = data.type, computed = iteratee2(value); - if (type == LAZY_MAP_FLAG) { - value = computed; - } else if (!computed) { - if (type == LAZY_FILTER_FLAG) { - continue outer; - } else { - break outer; - } - } - } - result2[resIndex++] = value; - } - return result2; - } - LazyWrapper.prototype = baseCreate(baseLodash.prototype); - LazyWrapper.prototype.constructor = LazyWrapper; - function Hash(entries) { - var index = -1, length = entries == null ? 0 : entries.length; - this.clear(); - while (++index < length) { - var entry = entries[index]; - this.set(entry[0], entry[1]); - } - } - function hashClear() { - this.__data__ = nativeCreate ? nativeCreate(null) : {}; - this.size = 0; - } - function hashDelete(key) { - var result2 = this.has(key) && delete this.__data__[key]; - this.size -= result2 ? 1 : 0; - return result2; - } - function hashGet(key) { - var data = this.__data__; - if (nativeCreate) { - var result2 = data[key]; - return result2 === HASH_UNDEFINED ? undefined2 : result2; - } - return hasOwnProperty.call(data, key) ? data[key] : undefined2; - } - function hashHas(key) { - var data = this.__data__; - return nativeCreate ? data[key] !== undefined2 : hasOwnProperty.call(data, key); - } - function hashSet(key, value) { - var data = this.__data__; - this.size += this.has(key) ? 0 : 1; - data[key] = nativeCreate && value === undefined2 ? HASH_UNDEFINED : value; - return this; - } - Hash.prototype.clear = hashClear; - Hash.prototype["delete"] = hashDelete; - Hash.prototype.get = hashGet; - Hash.prototype.has = hashHas; - Hash.prototype.set = hashSet; - function ListCache(entries) { - var index = -1, length = entries == null ? 0 : entries.length; - this.clear(); - while (++index < length) { - var entry = entries[index]; - this.set(entry[0], entry[1]); - } - } - function listCacheClear() { - this.__data__ = []; - this.size = 0; - } - function listCacheDelete(key) { - var data = this.__data__, index = assocIndexOf(data, key); - if (index < 0) { - return false; - } - var lastIndex = data.length - 1; - if (index == lastIndex) { - data.pop(); - } else { - splice.call(data, index, 1); - } - --this.size; - return true; - } - function listCacheGet(key) { - var data = this.__data__, index = assocIndexOf(data, key); - return index < 0 ? undefined2 : data[index][1]; - } - function listCacheHas(key) { - return assocIndexOf(this.__data__, key) > -1; - } - function listCacheSet(key, value) { - var data = this.__data__, index = assocIndexOf(data, key); - if (index < 0) { - ++this.size; - data.push([key, value]); - } else { - data[index][1] = value; - } - return this; - } - ListCache.prototype.clear = listCacheClear; - ListCache.prototype["delete"] = listCacheDelete; - ListCache.prototype.get = listCacheGet; - ListCache.prototype.has = listCacheHas; - ListCache.prototype.set = listCacheSet; - function MapCache(entries) { - var index = -1, length = entries == null ? 0 : entries.length; - this.clear(); - while (++index < length) { - var entry = entries[index]; - this.set(entry[0], entry[1]); - } - } - function mapCacheClear() { - this.size = 0; - this.__data__ = { - "hash": new Hash(), - "map": new (Map || ListCache)(), - "string": new Hash() - }; - } - function mapCacheDelete(key) { - var result2 = getMapData(this, key)["delete"](key); - this.size -= result2 ? 1 : 0; - return result2; - } - function mapCacheGet(key) { - return getMapData(this, key).get(key); - } - function mapCacheHas(key) { - return getMapData(this, key).has(key); - } - function mapCacheSet(key, value) { - var data = getMapData(this, key), size2 = data.size; - data.set(key, value); - this.size += data.size == size2 ? 0 : 1; - return this; - } - MapCache.prototype.clear = mapCacheClear; - MapCache.prototype["delete"] = mapCacheDelete; - MapCache.prototype.get = mapCacheGet; - MapCache.prototype.has = mapCacheHas; - MapCache.prototype.set = mapCacheSet; - function SetCache(values2) { - var index = -1, length = values2 == null ? 0 : values2.length; - this.__data__ = new MapCache(); - while (++index < length) { - this.add(values2[index]); - } - } - function setCacheAdd(value) { - this.__data__.set(value, HASH_UNDEFINED); - return this; - } - function setCacheHas(value) { - return this.__data__.has(value); - } - SetCache.prototype.add = SetCache.prototype.push = setCacheAdd; - SetCache.prototype.has = setCacheHas; - function Stack(entries) { - var data = this.__data__ = new ListCache(entries); - this.size = data.size; - } - function stackClear() { - this.__data__ = new ListCache(); - this.size = 0; - } - function stackDelete(key) { - var data = this.__data__, result2 = data["delete"](key); - this.size = data.size; - return result2; - } - function stackGet(key) { - return this.__data__.get(key); - } - function stackHas(key) { - return this.__data__.has(key); - } - function stackSet(key, value) { - var data = this.__data__; - if (data instanceof ListCache) { - var pairs = data.__data__; - if (!Map || pairs.length < LARGE_ARRAY_SIZE - 1) { - pairs.push([key, value]); - this.size = ++data.size; - return this; - } - data = this.__data__ = new MapCache(pairs); - } - data.set(key, value); - this.size = data.size; - return this; - } - Stack.prototype.clear = stackClear; - Stack.prototype["delete"] = stackDelete; - Stack.prototype.get = stackGet; - Stack.prototype.has = stackHas; - Stack.prototype.set = stackSet; - function arrayLikeKeys(value, inherited) { - var isArr = isArray(value), isArg = !isArr && isArguments(value), isBuff = !isArr && !isArg && isBuffer(value), isType = !isArr && !isArg && !isBuff && isTypedArray(value), skipIndexes = isArr || isArg || isBuff || isType, result2 = skipIndexes ? baseTimes(value.length, String2) : [], length = result2.length; - for (var key in value) { - if ((inherited || hasOwnProperty.call(value, key)) && !(skipIndexes && // Safari 9 has enumerable `arguments.length` in strict mode. - (key == "length" || // Node.js 0.10 has enumerable non-index properties on buffers. - isBuff && (key == "offset" || key == "parent") || // PhantomJS 2 has enumerable non-index properties on typed arrays. - isType && (key == "buffer" || key == "byteLength" || key == "byteOffset") || // Skip index properties. - isIndex(key, length)))) { - result2.push(key); - } - } - return result2; - } - function arraySample(array) { - var length = array.length; - return length ? array[baseRandom(0, length - 1)] : undefined2; - } - function arraySampleSize(array, n) { - return shuffleSelf(copyArray(array), baseClamp(n, 0, array.length)); - } - function arrayShuffle(array) { - return shuffleSelf(copyArray(array)); - } - function assignMergeValue(object, key, value) { - if (value !== undefined2 && !eq(object[key], value) || value === undefined2 && !(key in object)) { - baseAssignValue(object, key, value); - } - } - function assignValue(object, key, value) { - var objValue = object[key]; - if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) || value === undefined2 && !(key in object)) { - baseAssignValue(object, key, value); - } - } - function assocIndexOf(array, key) { - var length = array.length; - while (length--) { - if (eq(array[length][0], key)) { - return length; - } - } - return -1; - } - function baseAggregator(collection, setter, iteratee2, accumulator) { - baseEach(collection, function(value, key, collection2) { - setter(accumulator, value, iteratee2(value), collection2); - }); - return accumulator; - } - function baseAssign(object, source) { - return object && copyObject(source, keys(source), object); - } - function baseAssignIn(object, source) { - return object && copyObject(source, keysIn(source), object); - } - function baseAssignValue(object, key, value) { - if (key == "__proto__" && defineProperty) { - defineProperty(object, key, { - "configurable": true, - "enumerable": true, - "value": value, - "writable": true - }); - } else { - object[key] = value; - } - } - function baseAt(object, paths) { - var index = -1, length = paths.length, result2 = Array2(length), skip = object == null; - while (++index < length) { - result2[index] = skip ? undefined2 : get(object, paths[index]); - } - return result2; - } - function baseClamp(number, lower, upper) { - if (number === number) { - if (upper !== undefined2) { - number = number <= upper ? number : upper; - } - if (lower !== undefined2) { - number = number >= lower ? number : lower; - } - } - return number; - } - function baseClone(value, bitmask, customizer, key, object, stack) { - var result2, isDeep = bitmask & CLONE_DEEP_FLAG, isFlat = bitmask & CLONE_FLAT_FLAG, isFull = bitmask & CLONE_SYMBOLS_FLAG; - if (customizer) { - result2 = object ? customizer(value, key, object, stack) : customizer(value); - } - if (result2 !== undefined2) { - return result2; - } - if (!isObject(value)) { - return value; - } - var isArr = isArray(value); - if (isArr) { - result2 = initCloneArray(value); - if (!isDeep) { - return copyArray(value, result2); - } - } else { - var tag = getTag(value), isFunc = tag == funcTag || tag == genTag; - if (isBuffer(value)) { - return cloneBuffer(value, isDeep); - } - if (tag == objectTag || tag == argsTag || isFunc && !object) { - result2 = isFlat || isFunc ? {} : initCloneObject(value); - if (!isDeep) { - return isFlat ? copySymbolsIn(value, baseAssignIn(result2, value)) : copySymbols(value, baseAssign(result2, value)); - } - } else { - if (!cloneableTags[tag]) { - return object ? value : {}; - } - result2 = initCloneByTag(value, tag, isDeep); - } - } - stack || (stack = new Stack()); - var stacked = stack.get(value); - if (stacked) { - return stacked; - } - stack.set(value, result2); - if (isSet(value)) { - value.forEach(function(subValue) { - result2.add(baseClone(subValue, bitmask, customizer, subValue, value, stack)); - }); - } else if (isMap(value)) { - value.forEach(function(subValue, key2) { - result2.set(key2, baseClone(subValue, bitmask, customizer, key2, value, stack)); - }); - } - var keysFunc = isFull ? isFlat ? getAllKeysIn : getAllKeys : isFlat ? keysIn : keys; - var props = isArr ? undefined2 : keysFunc(value); - arrayEach(props || value, function(subValue, key2) { - if (props) { - key2 = subValue; - subValue = value[key2]; - } - assignValue(result2, key2, baseClone(subValue, bitmask, customizer, key2, value, stack)); - }); - return result2; - } - function baseConforms(source) { - var props = keys(source); - return function(object) { - return baseConformsTo(object, source, props); - }; - } - function baseConformsTo(object, source, props) { - var length = props.length; - if (object == null) { - return !length; - } - object = Object2(object); - while (length--) { - var key = props[length], predicate = source[key], value = object[key]; - if (value === undefined2 && !(key in object) || !predicate(value)) { - return false; - } - } - return true; - } - function baseDelay(func, wait, args) { - if (typeof func != "function") { - throw new TypeError2(FUNC_ERROR_TEXT); - } - return setTimeout(function() { - func.apply(undefined2, args); - }, wait); - } - function baseDifference(array, values2, iteratee2, comparator) { - var index = -1, includes2 = arrayIncludes, isCommon = true, length = array.length, result2 = [], valuesLength = values2.length; - if (!length) { - return result2; - } - if (iteratee2) { - values2 = arrayMap(values2, baseUnary(iteratee2)); - } - if (comparator) { - includes2 = arrayIncludesWith; - isCommon = false; - } else if (values2.length >= LARGE_ARRAY_SIZE) { - includes2 = cacheHas; - isCommon = false; - values2 = new SetCache(values2); - } - outer: - while (++index < length) { - var value = array[index], computed = iteratee2 == null ? value : iteratee2(value); - value = comparator || value !== 0 ? value : 0; - if (isCommon && computed === computed) { - var valuesIndex = valuesLength; - while (valuesIndex--) { - if (values2[valuesIndex] === computed) { - continue outer; - } - } - result2.push(value); - } else if (!includes2(values2, computed, comparator)) { - result2.push(value); - } - } - return result2; - } - var baseEach = createBaseEach(baseForOwn); - var baseEachRight = createBaseEach(baseForOwnRight, true); - function baseEvery(collection, predicate) { - var result2 = true; - baseEach(collection, function(value, index, collection2) { - result2 = !!predicate(value, index, collection2); - return result2; - }); - return result2; - } - function baseExtremum(array, iteratee2, comparator) { - var index = -1, length = array.length; - while (++index < length) { - var value = array[index], current = iteratee2(value); - if (current != null && (computed === undefined2 ? current === current && !isSymbol(current) : comparator(current, computed))) { - var computed = current, result2 = value; - } - } - return result2; - } - function baseFill(array, value, start, end) { - var length = array.length; - start = toInteger(start); - if (start < 0) { - start = -start > length ? 0 : length + start; - } - end = end === undefined2 || end > length ? length : toInteger(end); - if (end < 0) { - end += length; - } - end = start > end ? 0 : toLength(end); - while (start < end) { - array[start++] = value; - } - return array; - } - function baseFilter(collection, predicate) { - var result2 = []; - baseEach(collection, function(value, index, collection2) { - if (predicate(value, index, collection2)) { - result2.push(value); - } - }); - return result2; - } - function baseFlatten(array, depth, predicate, isStrict, result2) { - var index = -1, length = array.length; - predicate || (predicate = isFlattenable); - result2 || (result2 = []); - while (++index < length) { - var value = array[index]; - if (depth > 0 && predicate(value)) { - if (depth > 1) { - baseFlatten(value, depth - 1, predicate, isStrict, result2); - } else { - arrayPush(result2, value); - } - } else if (!isStrict) { - result2[result2.length] = value; - } - } - return result2; - } - var baseFor = createBaseFor(); - var baseForRight = createBaseFor(true); - function baseForOwn(object, iteratee2) { - return object && baseFor(object, iteratee2, keys); - } - function baseForOwnRight(object, iteratee2) { - return object && baseForRight(object, iteratee2, keys); - } - function baseFunctions(object, props) { - return arrayFilter(props, function(key) { - return isFunction(object[key]); - }); - } - function baseGet(object, path) { - path = castPath(path, object); - var index = 0, length = path.length; - while (object != null && index < length) { - object = object[toKey(path[index++])]; - } - return index && index == length ? object : undefined2; - } - function baseGetAllKeys(object, keysFunc, symbolsFunc) { - var result2 = keysFunc(object); - return isArray(object) ? result2 : arrayPush(result2, symbolsFunc(object)); - } - function baseGetTag(value) { - if (value == null) { - return value === undefined2 ? undefinedTag : nullTag; - } - return symToStringTag && symToStringTag in Object2(value) ? getRawTag(value) : objectToString(value); - } - function baseGt(value, other) { - return value > other; - } - function baseHas(object, key) { - return object != null && hasOwnProperty.call(object, key); - } - function baseHasIn(object, key) { - return object != null && key in Object2(object); - } - function baseInRange(number, start, end) { - return number >= nativeMin(start, end) && number < nativeMax(start, end); - } - function baseIntersection(arrays, iteratee2, comparator) { - var includes2 = comparator ? arrayIncludesWith : arrayIncludes, length = arrays[0].length, othLength = arrays.length, othIndex = othLength, caches = Array2(othLength), maxLength = Infinity, result2 = []; - while (othIndex--) { - var array = arrays[othIndex]; - if (othIndex && iteratee2) { - array = arrayMap(array, baseUnary(iteratee2)); - } - maxLength = nativeMin(array.length, maxLength); - caches[othIndex] = !comparator && (iteratee2 || length >= 120 && array.length >= 120) ? new SetCache(othIndex && array) : undefined2; - } - array = arrays[0]; - var index = -1, seen = caches[0]; - outer: - while (++index < length && result2.length < maxLength) { - var value = array[index], computed = iteratee2 ? iteratee2(value) : value; - value = comparator || value !== 0 ? value : 0; - if (!(seen ? cacheHas(seen, computed) : includes2(result2, computed, comparator))) { - othIndex = othLength; - while (--othIndex) { - var cache = caches[othIndex]; - if (!(cache ? cacheHas(cache, computed) : includes2(arrays[othIndex], computed, comparator))) { - continue outer; - } - } - if (seen) { - seen.push(computed); - } - result2.push(value); - } - } - return result2; - } - function baseInverter(object, setter, iteratee2, accumulator) { - baseForOwn(object, function(value, key, object2) { - setter(accumulator, iteratee2(value), key, object2); - }); - return accumulator; - } - function baseInvoke(object, path, args) { - path = castPath(path, object); - object = parent(object, path); - var func = object == null ? object : object[toKey(last(path))]; - return func == null ? undefined2 : apply(func, object, args); - } - function baseIsArguments(value) { - return isObjectLike(value) && baseGetTag(value) == argsTag; - } - function baseIsArrayBuffer(value) { - return isObjectLike(value) && baseGetTag(value) == arrayBufferTag; - } - function baseIsDate(value) { - return isObjectLike(value) && baseGetTag(value) == dateTag; - } - function baseIsEqual(value, other, bitmask, customizer, stack) { - if (value === other) { - return true; - } - if (value == null || other == null || !isObjectLike(value) && !isObjectLike(other)) { - return value !== value && other !== other; - } - return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack); - } - function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) { - var objIsArr = isArray(object), othIsArr = isArray(other), objTag = objIsArr ? arrayTag : getTag(object), othTag = othIsArr ? arrayTag : getTag(other); - objTag = objTag == argsTag ? objectTag : objTag; - othTag = othTag == argsTag ? objectTag : othTag; - var objIsObj = objTag == objectTag, othIsObj = othTag == objectTag, isSameTag = objTag == othTag; - if (isSameTag && isBuffer(object)) { - if (!isBuffer(other)) { - return false; - } - objIsArr = true; - objIsObj = false; - } - if (isSameTag && !objIsObj) { - stack || (stack = new Stack()); - return objIsArr || isTypedArray(object) ? equalArrays(object, other, bitmask, customizer, equalFunc, stack) : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack); - } - if (!(bitmask & COMPARE_PARTIAL_FLAG)) { - var objIsWrapped = objIsObj && hasOwnProperty.call(object, "__wrapped__"), othIsWrapped = othIsObj && hasOwnProperty.call(other, "__wrapped__"); - if (objIsWrapped || othIsWrapped) { - var objUnwrapped = objIsWrapped ? object.value() : object, othUnwrapped = othIsWrapped ? other.value() : other; - stack || (stack = new Stack()); - return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack); - } - } - if (!isSameTag) { - return false; - } - stack || (stack = new Stack()); - return equalObjects(object, other, bitmask, customizer, equalFunc, stack); - } - function baseIsMap(value) { - return isObjectLike(value) && getTag(value) == mapTag; - } - function baseIsMatch(object, source, matchData, customizer) { - var index = matchData.length, length = index, noCustomizer = !customizer; - if (object == null) { - return !length; - } - object = Object2(object); - while (index--) { - var data = matchData[index]; - if (noCustomizer && data[2] ? data[1] !== object[data[0]] : !(data[0] in object)) { - return false; - } - } - while (++index < length) { - data = matchData[index]; - var key = data[0], objValue = object[key], srcValue = data[1]; - if (noCustomizer && data[2]) { - if (objValue === undefined2 && !(key in object)) { - return false; - } - } else { - var stack = new Stack(); - if (customizer) { - var result2 = customizer(objValue, srcValue, key, object, source, stack); - } - if (!(result2 === undefined2 ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack) : result2)) { - return false; - } - } - } - return true; - } - function baseIsNative(value) { - if (!isObject(value) || isMasked(value)) { - return false; - } - var pattern = isFunction(value) ? reIsNative : reIsHostCtor; - return pattern.test(toSource(value)); - } - function baseIsRegExp(value) { - return isObjectLike(value) && baseGetTag(value) == regexpTag; - } - function baseIsSet(value) { - return isObjectLike(value) && getTag(value) == setTag; - } - function baseIsTypedArray(value) { - return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[baseGetTag(value)]; - } - function baseIteratee(value) { - if (typeof value == "function") { - return value; - } - if (value == null) { - return identity; - } - if (typeof value == "object") { - return isArray(value) ? baseMatchesProperty(value[0], value[1]) : baseMatches(value); - } - return property(value); - } - function baseKeys(object) { - if (!isPrototype(object)) { - return nativeKeys(object); - } - var result2 = []; - for (var key in Object2(object)) { - if (hasOwnProperty.call(object, key) && key != "constructor") { - result2.push(key); - } - } - return result2; - } - function baseKeysIn(object) { - if (!isObject(object)) { - return nativeKeysIn(object); - } - var isProto = isPrototype(object), result2 = []; - for (var key in object) { - if (!(key == "constructor" && (isProto || !hasOwnProperty.call(object, key)))) { - result2.push(key); - } - } - return result2; - } - function baseLt(value, other) { - return value < other; - } - function baseMap(collection, iteratee2) { - var index = -1, result2 = isArrayLike(collection) ? Array2(collection.length) : []; - baseEach(collection, function(value, key, collection2) { - result2[++index] = iteratee2(value, key, collection2); - }); - return result2; - } - function baseMatches(source) { - var matchData = getMatchData(source); - if (matchData.length == 1 && matchData[0][2]) { - return matchesStrictComparable(matchData[0][0], matchData[0][1]); - } - return function(object) { - return object === source || baseIsMatch(object, source, matchData); - }; - } - function baseMatchesProperty(path, srcValue) { - if (isKey(path) && isStrictComparable(srcValue)) { - return matchesStrictComparable(toKey(path), srcValue); - } - return function(object) { - var objValue = get(object, path); - return objValue === undefined2 && objValue === srcValue ? hasIn(object, path) : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG); - }; - } - function baseMerge(object, source, srcIndex, customizer, stack) { - if (object === source) { - return; - } - baseFor(source, function(srcValue, key) { - stack || (stack = new Stack()); - if (isObject(srcValue)) { - baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack); - } else { - var newValue = customizer ? customizer(safeGet(object, key), srcValue, key + "", object, source, stack) : undefined2; - if (newValue === undefined2) { - newValue = srcValue; - } - assignMergeValue(object, key, newValue); - } - }, keysIn); - } - function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) { - var objValue = safeGet(object, key), srcValue = safeGet(source, key), stacked = stack.get(srcValue); - if (stacked) { - assignMergeValue(object, key, stacked); - return; - } - var newValue = customizer ? customizer(objValue, srcValue, key + "", object, source, stack) : undefined2; - var isCommon = newValue === undefined2; - if (isCommon) { - var isArr = isArray(srcValue), isBuff = !isArr && isBuffer(srcValue), isTyped = !isArr && !isBuff && isTypedArray(srcValue); - newValue = srcValue; - if (isArr || isBuff || isTyped) { - if (isArray(objValue)) { - newValue = objValue; - } else if (isArrayLikeObject(objValue)) { - newValue = copyArray(objValue); - } else if (isBuff) { - isCommon = false; - newValue = cloneBuffer(srcValue, true); - } else if (isTyped) { - isCommon = false; - newValue = cloneTypedArray(srcValue, true); - } else { - newValue = []; - } - } else if (isPlainObject(srcValue) || isArguments(srcValue)) { - newValue = objValue; - if (isArguments(objValue)) { - newValue = toPlainObject(objValue); - } else if (!isObject(objValue) || isFunction(objValue)) { - newValue = initCloneObject(srcValue); - } - } else { - isCommon = false; - } - } - if (isCommon) { - stack.set(srcValue, newValue); - mergeFunc(newValue, srcValue, srcIndex, customizer, stack); - stack["delete"](srcValue); - } - assignMergeValue(object, key, newValue); - } - function baseNth(array, n) { - var length = array.length; - if (!length) { - return; - } - n += n < 0 ? length : 0; - return isIndex(n, length) ? array[n] : undefined2; - } - function baseOrderBy(collection, iteratees, orders) { - if (iteratees.length) { - iteratees = arrayMap(iteratees, function(iteratee2) { - if (isArray(iteratee2)) { - return function(value) { - return baseGet(value, iteratee2.length === 1 ? iteratee2[0] : iteratee2); - }; - } - return iteratee2; - }); - } else { - iteratees = [identity]; - } - var index = -1; - iteratees = arrayMap(iteratees, baseUnary(getIteratee())); - var result2 = baseMap(collection, function(value, key, collection2) { - var criteria = arrayMap(iteratees, function(iteratee2) { - return iteratee2(value); - }); - return { "criteria": criteria, "index": ++index, "value": value }; - }); - return baseSortBy(result2, function(object, other) { - return compareMultiple(object, other, orders); - }); - } - function basePick(object, paths) { - return basePickBy(object, paths, function(value, path) { - return hasIn(object, path); - }); - } - function basePickBy(object, paths, predicate) { - var index = -1, length = paths.length, result2 = {}; - while (++index < length) { - var path = paths[index], value = baseGet(object, path); - if (predicate(value, path)) { - baseSet(result2, castPath(path, object), value); - } - } - return result2; - } - function basePropertyDeep(path) { - return function(object) { - return baseGet(object, path); - }; - } - function basePullAll(array, values2, iteratee2, comparator) { - var indexOf2 = comparator ? baseIndexOfWith : baseIndexOf, index = -1, length = values2.length, seen = array; - if (array === values2) { - values2 = copyArray(values2); - } - if (iteratee2) { - seen = arrayMap(array, baseUnary(iteratee2)); - } - while (++index < length) { - var fromIndex = 0, value = values2[index], computed = iteratee2 ? iteratee2(value) : value; - while ((fromIndex = indexOf2(seen, computed, fromIndex, comparator)) > -1) { - if (seen !== array) { - splice.call(seen, fromIndex, 1); - } - splice.call(array, fromIndex, 1); - } - } - return array; - } - function basePullAt(array, indexes) { - var length = array ? indexes.length : 0, lastIndex = length - 1; - while (length--) { - var index = indexes[length]; - if (length == lastIndex || index !== previous) { - var previous = index; - if (isIndex(index)) { - splice.call(array, index, 1); - } else { - baseUnset(array, index); - } - } - } - return array; - } - function baseRandom(lower, upper) { - return lower + nativeFloor(nativeRandom() * (upper - lower + 1)); - } - function baseRange(start, end, step, fromRight) { - var index = -1, length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), result2 = Array2(length); - while (length--) { - result2[fromRight ? length : ++index] = start; - start += step; - } - return result2; - } - function baseRepeat(string, n) { - var result2 = ""; - if (!string || n < 1 || n > MAX_SAFE_INTEGER) { - return result2; - } - do { - if (n % 2) { - result2 += string; - } - n = nativeFloor(n / 2); - if (n) { - string += string; - } - } while (n); - return result2; - } - function baseRest(func, start) { - return setToString(overRest(func, start, identity), func + ""); - } - function baseSample(collection) { - return arraySample(values(collection)); - } - function baseSampleSize(collection, n) { - var array = values(collection); - return shuffleSelf(array, baseClamp(n, 0, array.length)); - } - function baseSet(object, path, value, customizer) { - if (!isObject(object)) { - return object; - } - path = castPath(path, object); - var index = -1, length = path.length, lastIndex = length - 1, nested = object; - while (nested != null && ++index < length) { - var key = toKey(path[index]), newValue = value; - if (key === "__proto__" || key === "constructor" || key === "prototype") { - return object; - } - if (index != lastIndex) { - var objValue = nested[key]; - newValue = customizer ? customizer(objValue, key, nested) : undefined2; - if (newValue === undefined2) { - newValue = isObject(objValue) ? objValue : isIndex(path[index + 1]) ? [] : {}; - } - } - assignValue(nested, key, newValue); - nested = nested[key]; - } - return object; - } - var baseSetData = !metaMap ? identity : function(func, data) { - metaMap.set(func, data); - return func; - }; - var baseSetToString = !defineProperty ? identity : function(func, string) { - return defineProperty(func, "toString", { - "configurable": true, - "enumerable": false, - "value": constant(string), - "writable": true - }); - }; - function baseShuffle(collection) { - return shuffleSelf(values(collection)); - } - function baseSlice(array, start, end) { - var index = -1, length = array.length; - if (start < 0) { - start = -start > length ? 0 : length + start; - } - end = end > length ? length : end; - if (end < 0) { - end += length; - } - length = start > end ? 0 : end - start >>> 0; - start >>>= 0; - var result2 = Array2(length); - while (++index < length) { - result2[index] = array[index + start]; - } - return result2; - } - function baseSome(collection, predicate) { - var result2; - baseEach(collection, function(value, index, collection2) { - result2 = predicate(value, index, collection2); - return !result2; - }); - return !!result2; - } - function baseSortedIndex(array, value, retHighest) { - var low = 0, high = array == null ? low : array.length; - if (typeof value == "number" && value === value && high <= HALF_MAX_ARRAY_LENGTH) { - while (low < high) { - var mid = low + high >>> 1, computed = array[mid]; - if (computed !== null && !isSymbol(computed) && (retHighest ? computed <= value : computed < value)) { - low = mid + 1; - } else { - high = mid; - } - } - return high; - } - return baseSortedIndexBy(array, value, identity, retHighest); - } - function baseSortedIndexBy(array, value, iteratee2, retHighest) { - var low = 0, high = array == null ? 0 : array.length; - if (high === 0) { - return 0; - } - value = iteratee2(value); - var valIsNaN = value !== value, valIsNull = value === null, valIsSymbol = isSymbol(value), valIsUndefined = value === undefined2; - while (low < high) { - var mid = nativeFloor((low + high) / 2), computed = iteratee2(array[mid]), othIsDefined = computed !== undefined2, othIsNull = computed === null, othIsReflexive = computed === computed, othIsSymbol = isSymbol(computed); - if (valIsNaN) { - var setLow = retHighest || othIsReflexive; - } else if (valIsUndefined) { - setLow = othIsReflexive && (retHighest || othIsDefined); - } else if (valIsNull) { - setLow = othIsReflexive && othIsDefined && (retHighest || !othIsNull); - } else if (valIsSymbol) { - setLow = othIsReflexive && othIsDefined && !othIsNull && (retHighest || !othIsSymbol); - } else if (othIsNull || othIsSymbol) { - setLow = false; - } else { - setLow = retHighest ? computed <= value : computed < value; - } - if (setLow) { - low = mid + 1; - } else { - high = mid; - } - } - return nativeMin(high, MAX_ARRAY_INDEX); - } - function baseSortedUniq(array, iteratee2) { - var index = -1, length = array.length, resIndex = 0, result2 = []; - while (++index < length) { - var value = array[index], computed = iteratee2 ? iteratee2(value) : value; - if (!index || !eq(computed, seen)) { - var seen = computed; - result2[resIndex++] = value === 0 ? 0 : value; - } - } - return result2; - } - function baseToNumber(value) { - if (typeof value == "number") { - return value; - } - if (isSymbol(value)) { - return NAN; - } - return +value; - } - function baseToString(value) { - if (typeof value == "string") { - return value; - } - if (isArray(value)) { - return arrayMap(value, baseToString) + ""; - } - if (isSymbol(value)) { - return symbolToString ? symbolToString.call(value) : ""; - } - var result2 = value + ""; - return result2 == "0" && 1 / value == -INFINITY ? "-0" : result2; - } - function baseUniq(array, iteratee2, comparator) { - var index = -1, includes2 = arrayIncludes, length = array.length, isCommon = true, result2 = [], seen = result2; - if (comparator) { - isCommon = false; - includes2 = arrayIncludesWith; - } else if (length >= LARGE_ARRAY_SIZE) { - var set2 = iteratee2 ? null : createSet(array); - if (set2) { - return setToArray(set2); - } - isCommon = false; - includes2 = cacheHas; - seen = new SetCache(); - } else { - seen = iteratee2 ? [] : result2; - } - outer: - while (++index < length) { - var value = array[index], computed = iteratee2 ? iteratee2(value) : value; - value = comparator || value !== 0 ? value : 0; - if (isCommon && computed === computed) { - var seenIndex = seen.length; - while (seenIndex--) { - if (seen[seenIndex] === computed) { - continue outer; - } - } - if (iteratee2) { - seen.push(computed); - } - result2.push(value); - } else if (!includes2(seen, computed, comparator)) { - if (seen !== result2) { - seen.push(computed); - } - result2.push(value); - } - } - return result2; - } - function baseUnset(object, path) { - path = castPath(path, object); - object = parent(object, path); - return object == null || delete object[toKey(last(path))]; - } - function baseUpdate(object, path, updater, customizer) { - return baseSet(object, path, updater(baseGet(object, path)), customizer); - } - function baseWhile(array, predicate, isDrop, fromRight) { - var length = array.length, index = fromRight ? length : -1; - while ((fromRight ? index-- : ++index < length) && predicate(array[index], index, array)) { - } - return isDrop ? baseSlice(array, fromRight ? 0 : index, fromRight ? index + 1 : length) : baseSlice(array, fromRight ? index + 1 : 0, fromRight ? length : index); - } - function baseWrapperValue(value, actions) { - var result2 = value; - if (result2 instanceof LazyWrapper) { - result2 = result2.value(); - } - return arrayReduce(actions, function(result3, action) { - return action.func.apply(action.thisArg, arrayPush([result3], action.args)); - }, result2); - } - function baseXor(arrays, iteratee2, comparator) { - var length = arrays.length; - if (length < 2) { - return length ? baseUniq(arrays[0]) : []; - } - var index = -1, result2 = Array2(length); - while (++index < length) { - var array = arrays[index], othIndex = -1; - while (++othIndex < length) { - if (othIndex != index) { - result2[index] = baseDifference(result2[index] || array, arrays[othIndex], iteratee2, comparator); - } - } - } - return baseUniq(baseFlatten(result2, 1), iteratee2, comparator); - } - function baseZipObject(props, values2, assignFunc) { - var index = -1, length = props.length, valsLength = values2.length, result2 = {}; - while (++index < length) { - var value = index < valsLength ? values2[index] : undefined2; - assignFunc(result2, props[index], value); - } - return result2; - } - function castArrayLikeObject(value) { - return isArrayLikeObject(value) ? value : []; - } - function castFunction(value) { - return typeof value == "function" ? value : identity; - } - function castPath(value, object) { - if (isArray(value)) { - return value; - } - return isKey(value, object) ? [value] : stringToPath(toString(value)); - } - var castRest = baseRest; - function castSlice(array, start, end) { - var length = array.length; - end = end === undefined2 ? length : end; - return !start && end >= length ? array : baseSlice(array, start, end); - } - var clearTimeout = ctxClearTimeout || function(id) { - return root.clearTimeout(id); - }; - function cloneBuffer(buffer, isDeep) { - if (isDeep) { - return buffer.slice(); - } - var length = buffer.length, result2 = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length); - buffer.copy(result2); - return result2; - } - function cloneArrayBuffer(arrayBuffer) { - var result2 = new arrayBuffer.constructor(arrayBuffer.byteLength); - new Uint8Array2(result2).set(new Uint8Array2(arrayBuffer)); - return result2; - } - function cloneDataView(dataView, isDeep) { - var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer; - return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength); - } - function cloneRegExp(regexp) { - var result2 = new regexp.constructor(regexp.source, reFlags.exec(regexp)); - result2.lastIndex = regexp.lastIndex; - return result2; - } - function cloneSymbol(symbol) { - return symbolValueOf ? Object2(symbolValueOf.call(symbol)) : {}; - } - function cloneTypedArray(typedArray, isDeep) { - var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer; - return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length); - } - function compareAscending(value, other) { - if (value !== other) { - var valIsDefined = value !== undefined2, valIsNull = value === null, valIsReflexive = value === value, valIsSymbol = isSymbol(value); - var othIsDefined = other !== undefined2, othIsNull = other === null, othIsReflexive = other === other, othIsSymbol = isSymbol(other); - if (!othIsNull && !othIsSymbol && !valIsSymbol && value > other || valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol || valIsNull && othIsDefined && othIsReflexive || !valIsDefined && othIsReflexive || !valIsReflexive) { - return 1; - } - if (!valIsNull && !valIsSymbol && !othIsSymbol && value < other || othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol || othIsNull && valIsDefined && valIsReflexive || !othIsDefined && valIsReflexive || !othIsReflexive) { - return -1; - } - } - return 0; - } - function compareMultiple(object, other, orders) { - var index = -1, objCriteria = object.criteria, othCriteria = other.criteria, length = objCriteria.length, ordersLength = orders.length; - while (++index < length) { - var result2 = compareAscending(objCriteria[index], othCriteria[index]); - if (result2) { - if (index >= ordersLength) { - return result2; - } - var order = orders[index]; - return result2 * (order == "desc" ? -1 : 1); - } - } - return object.index - other.index; - } - function composeArgs(args, partials, holders, isCurried) { - var argsIndex = -1, argsLength = args.length, holdersLength = holders.length, leftIndex = -1, leftLength = partials.length, rangeLength = nativeMax(argsLength - holdersLength, 0), result2 = Array2(leftLength + rangeLength), isUncurried = !isCurried; - while (++leftIndex < leftLength) { - result2[leftIndex] = partials[leftIndex]; - } - while (++argsIndex < holdersLength) { - if (isUncurried || argsIndex < argsLength) { - result2[holders[argsIndex]] = args[argsIndex]; - } - } - while (rangeLength--) { - result2[leftIndex++] = args[argsIndex++]; - } - return result2; - } - function composeArgsRight(args, partials, holders, isCurried) { - var argsIndex = -1, argsLength = args.length, holdersIndex = -1, holdersLength = holders.length, rightIndex = -1, rightLength = partials.length, rangeLength = nativeMax(argsLength - holdersLength, 0), result2 = Array2(rangeLength + rightLength), isUncurried = !isCurried; - while (++argsIndex < rangeLength) { - result2[argsIndex] = args[argsIndex]; - } - var offset = argsIndex; - while (++rightIndex < rightLength) { - result2[offset + rightIndex] = partials[rightIndex]; - } - while (++holdersIndex < holdersLength) { - if (isUncurried || argsIndex < argsLength) { - result2[offset + holders[holdersIndex]] = args[argsIndex++]; - } - } - return result2; - } - function copyArray(source, array) { - var index = -1, length = source.length; - array || (array = Array2(length)); - while (++index < length) { - array[index] = source[index]; - } - return array; - } - function copyObject(source, props, object, customizer) { - var isNew = !object; - object || (object = {}); - var index = -1, length = props.length; - while (++index < length) { - var key = props[index]; - var newValue = customizer ? customizer(object[key], source[key], key, object, source) : undefined2; - if (newValue === undefined2) { - newValue = source[key]; - } - if (isNew) { - baseAssignValue(object, key, newValue); - } else { - assignValue(object, key, newValue); - } - } - return object; - } - function copySymbols(source, object) { - return copyObject(source, getSymbols(source), object); - } - function copySymbolsIn(source, object) { - return copyObject(source, getSymbolsIn(source), object); - } - function createAggregator(setter, initializer) { - return function(collection, iteratee2) { - var func = isArray(collection) ? arrayAggregator : baseAggregator, accumulator = initializer ? initializer() : {}; - return func(collection, setter, getIteratee(iteratee2, 2), accumulator); - }; - } - function createAssigner(assigner) { - return baseRest(function(object, sources) { - var index = -1, length = sources.length, customizer = length > 1 ? sources[length - 1] : undefined2, guard = length > 2 ? sources[2] : undefined2; - customizer = assigner.length > 3 && typeof customizer == "function" ? (length--, customizer) : undefined2; - if (guard && isIterateeCall(sources[0], sources[1], guard)) { - customizer = length < 3 ? undefined2 : customizer; - length = 1; - } - object = Object2(object); - while (++index < length) { - var source = sources[index]; - if (source) { - assigner(object, source, index, customizer); - } - } - return object; - }); - } - function createBaseEach(eachFunc, fromRight) { - return function(collection, iteratee2) { - if (collection == null) { - return collection; - } - if (!isArrayLike(collection)) { - return eachFunc(collection, iteratee2); - } - var length = collection.length, index = fromRight ? length : -1, iterable = Object2(collection); - while (fromRight ? index-- : ++index < length) { - if (iteratee2(iterable[index], index, iterable) === false) { - break; - } - } - return collection; - }; - } - function createBaseFor(fromRight) { - return function(object, iteratee2, keysFunc) { - var index = -1, iterable = Object2(object), props = keysFunc(object), length = props.length; - while (length--) { - var key = props[fromRight ? length : ++index]; - if (iteratee2(iterable[key], key, iterable) === false) { - break; - } - } - return object; - }; - } - function createBind(func, bitmask, thisArg) { - var isBind = bitmask & WRAP_BIND_FLAG, Ctor = createCtor(func); - function wrapper() { - var fn = this && this !== root && this instanceof wrapper ? Ctor : func; - return fn.apply(isBind ? thisArg : this, arguments); - } - return wrapper; - } - function createCaseFirst(methodName) { - return function(string) { - string = toString(string); - var strSymbols = hasUnicode(string) ? stringToArray(string) : undefined2; - var chr = strSymbols ? strSymbols[0] : string.charAt(0); - var trailing = strSymbols ? castSlice(strSymbols, 1).join("") : string.slice(1); - return chr[methodName]() + trailing; - }; - } - function createCompounder(callback) { - return function(string) { - return arrayReduce(words(deburr(string).replace(reApos, "")), callback, ""); - }; - } - function createCtor(Ctor) { - return function() { - var args = arguments; - switch (args.length) { - case 0: - return new Ctor(); - case 1: - return new Ctor(args[0]); - case 2: - return new Ctor(args[0], args[1]); - case 3: - return new Ctor(args[0], args[1], args[2]); - case 4: - return new Ctor(args[0], args[1], args[2], args[3]); - case 5: - return new Ctor(args[0], args[1], args[2], args[3], args[4]); - case 6: - return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]); - case 7: - return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); - } - var thisBinding = baseCreate(Ctor.prototype), result2 = Ctor.apply(thisBinding, args); - return isObject(result2) ? result2 : thisBinding; - }; - } - function createCurry(func, bitmask, arity) { - var Ctor = createCtor(func); - function wrapper() { - var length = arguments.length, args = Array2(length), index = length, placeholder = getHolder(wrapper); - while (index--) { - args[index] = arguments[index]; - } - var holders = length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder ? [] : replaceHolders(args, placeholder); - length -= holders.length; - if (length < arity) { - return createRecurry( - func, - bitmask, - createHybrid, - wrapper.placeholder, - undefined2, - args, - holders, - undefined2, - undefined2, - arity - length - ); - } - var fn = this && this !== root && this instanceof wrapper ? Ctor : func; - return apply(fn, this, args); - } - return wrapper; - } - function createFind(findIndexFunc) { - return function(collection, predicate, fromIndex) { - var iterable = Object2(collection); - if (!isArrayLike(collection)) { - var iteratee2 = getIteratee(predicate, 3); - collection = keys(collection); - predicate = function(key) { - return iteratee2(iterable[key], key, iterable); - }; - } - var index = findIndexFunc(collection, predicate, fromIndex); - return index > -1 ? iterable[iteratee2 ? collection[index] : index] : undefined2; - }; - } - function createFlow(fromRight) { - return flatRest(function(funcs) { - var length = funcs.length, index = length, prereq = LodashWrapper.prototype.thru; - if (fromRight) { - funcs.reverse(); - } - while (index--) { - var func = funcs[index]; - if (typeof func != "function") { - throw new TypeError2(FUNC_ERROR_TEXT); - } - if (prereq && !wrapper && getFuncName(func) == "wrapper") { - var wrapper = new LodashWrapper([], true); - } - } - index = wrapper ? index : length; - while (++index < length) { - func = funcs[index]; - var funcName = getFuncName(func), data = funcName == "wrapper" ? getData(func) : undefined2; - if (data && isLaziable(data[0]) && data[1] == (WRAP_ARY_FLAG | WRAP_CURRY_FLAG | WRAP_PARTIAL_FLAG | WRAP_REARG_FLAG) && !data[4].length && data[9] == 1) { - wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]); - } else { - wrapper = func.length == 1 && isLaziable(func) ? wrapper[funcName]() : wrapper.thru(func); - } - } - return function() { - var args = arguments, value = args[0]; - if (wrapper && args.length == 1 && isArray(value)) { - return wrapper.plant(value).value(); - } - var index2 = 0, result2 = length ? funcs[index2].apply(this, args) : value; - while (++index2 < length) { - result2 = funcs[index2].call(this, result2); - } - return result2; - }; - }); - } - function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary2, arity) { - var isAry = bitmask & WRAP_ARY_FLAG, isBind = bitmask & WRAP_BIND_FLAG, isBindKey = bitmask & WRAP_BIND_KEY_FLAG, isCurried = bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG), isFlip = bitmask & WRAP_FLIP_FLAG, Ctor = isBindKey ? undefined2 : createCtor(func); - function wrapper() { - var length = arguments.length, args = Array2(length), index = length; - while (index--) { - args[index] = arguments[index]; - } - if (isCurried) { - var placeholder = getHolder(wrapper), holdersCount = countHolders(args, placeholder); - } - if (partials) { - args = composeArgs(args, partials, holders, isCurried); - } - if (partialsRight) { - args = composeArgsRight(args, partialsRight, holdersRight, isCurried); - } - length -= holdersCount; - if (isCurried && length < arity) { - var newHolders = replaceHolders(args, placeholder); - return createRecurry( - func, - bitmask, - createHybrid, - wrapper.placeholder, - thisArg, - args, - newHolders, - argPos, - ary2, - arity - length - ); - } - var thisBinding = isBind ? thisArg : this, fn = isBindKey ? thisBinding[func] : func; - length = args.length; - if (argPos) { - args = reorder(args, argPos); - } else if (isFlip && length > 1) { - args.reverse(); - } - if (isAry && ary2 < length) { - args.length = ary2; - } - if (this && this !== root && this instanceof wrapper) { - fn = Ctor || createCtor(fn); - } - return fn.apply(thisBinding, args); - } - return wrapper; - } - function createInverter(setter, toIteratee) { - return function(object, iteratee2) { - return baseInverter(object, setter, toIteratee(iteratee2), {}); - }; - } - function createMathOperation(operator, defaultValue) { - return function(value, other) { - var result2; - if (value === undefined2 && other === undefined2) { - return defaultValue; - } - if (value !== undefined2) { - result2 = value; - } - if (other !== undefined2) { - if (result2 === undefined2) { - return other; - } - if (typeof value == "string" || typeof other == "string") { - value = baseToString(value); - other = baseToString(other); - } else { - value = baseToNumber(value); - other = baseToNumber(other); - } - result2 = operator(value, other); - } - return result2; - }; - } - function createOver(arrayFunc) { - return flatRest(function(iteratees) { - iteratees = arrayMap(iteratees, baseUnary(getIteratee())); - return baseRest(function(args) { - var thisArg = this; - return arrayFunc(iteratees, function(iteratee2) { - return apply(iteratee2, thisArg, args); - }); - }); - }); - } - function createPadding(length, chars) { - chars = chars === undefined2 ? " " : baseToString(chars); - var charsLength = chars.length; - if (charsLength < 2) { - return charsLength ? baseRepeat(chars, length) : chars; - } - var result2 = baseRepeat(chars, nativeCeil(length / stringSize(chars))); - return hasUnicode(chars) ? castSlice(stringToArray(result2), 0, length).join("") : result2.slice(0, length); - } - function createPartial(func, bitmask, thisArg, partials) { - var isBind = bitmask & WRAP_BIND_FLAG, Ctor = createCtor(func); - function wrapper() { - var argsIndex = -1, argsLength = arguments.length, leftIndex = -1, leftLength = partials.length, args = Array2(leftLength + argsLength), fn = this && this !== root && this instanceof wrapper ? Ctor : func; - while (++leftIndex < leftLength) { - args[leftIndex] = partials[leftIndex]; - } - while (argsLength--) { - args[leftIndex++] = arguments[++argsIndex]; - } - return apply(fn, isBind ? thisArg : this, args); - } - return wrapper; - } - function createRange(fromRight) { - return function(start, end, step) { - if (step && typeof step != "number" && isIterateeCall(start, end, step)) { - end = step = undefined2; - } - start = toFinite(start); - if (end === undefined2) { - end = start; - start = 0; - } else { - end = toFinite(end); - } - step = step === undefined2 ? start < end ? 1 : -1 : toFinite(step); - return baseRange(start, end, step, fromRight); - }; - } - function createRelationalOperation(operator) { - return function(value, other) { - if (!(typeof value == "string" && typeof other == "string")) { - value = toNumber(value); - other = toNumber(other); - } - return operator(value, other); - }; - } - function createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary2, arity) { - var isCurry = bitmask & WRAP_CURRY_FLAG, newHolders = isCurry ? holders : undefined2, newHoldersRight = isCurry ? undefined2 : holders, newPartials = isCurry ? partials : undefined2, newPartialsRight = isCurry ? undefined2 : partials; - bitmask |= isCurry ? WRAP_PARTIAL_FLAG : WRAP_PARTIAL_RIGHT_FLAG; - bitmask &= ~(isCurry ? WRAP_PARTIAL_RIGHT_FLAG : WRAP_PARTIAL_FLAG); - if (!(bitmask & WRAP_CURRY_BOUND_FLAG)) { - bitmask &= ~(WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG); - } - var newData = [ - func, - bitmask, - thisArg, - newPartials, - newHolders, - newPartialsRight, - newHoldersRight, - argPos, - ary2, - arity - ]; - var result2 = wrapFunc.apply(undefined2, newData); - if (isLaziable(func)) { - setData(result2, newData); - } - result2.placeholder = placeholder; - return setWrapToString(result2, func, bitmask); - } - function createRound(methodName) { - var func = Math2[methodName]; - return function(number, precision) { - number = toNumber(number); - precision = precision == null ? 0 : nativeMin(toInteger(precision), 292); - if (precision && nativeIsFinite(number)) { - var pair = (toString(number) + "e").split("e"), value = func(pair[0] + "e" + (+pair[1] + precision)); - pair = (toString(value) + "e").split("e"); - return +(pair[0] + "e" + (+pair[1] - precision)); - } - return func(number); - }; - } - var createSet = !(Set2 && 1 / setToArray(new Set2([, -0]))[1] == INFINITY) ? noop : function(values2) { - return new Set2(values2); - }; - function createToPairs(keysFunc) { - return function(object) { - var tag = getTag(object); - if (tag == mapTag) { - return mapToArray(object); - } - if (tag == setTag) { - return setToPairs(object); - } - return baseToPairs(object, keysFunc(object)); - }; - } - function createWrap(func, bitmask, thisArg, partials, holders, argPos, ary2, arity) { - var isBindKey = bitmask & WRAP_BIND_KEY_FLAG; - if (!isBindKey && typeof func != "function") { - throw new TypeError2(FUNC_ERROR_TEXT); - } - var length = partials ? partials.length : 0; - if (!length) { - bitmask &= ~(WRAP_PARTIAL_FLAG | WRAP_PARTIAL_RIGHT_FLAG); - partials = holders = undefined2; - } - ary2 = ary2 === undefined2 ? ary2 : nativeMax(toInteger(ary2), 0); - arity = arity === undefined2 ? arity : toInteger(arity); - length -= holders ? holders.length : 0; - if (bitmask & WRAP_PARTIAL_RIGHT_FLAG) { - var partialsRight = partials, holdersRight = holders; - partials = holders = undefined2; - } - var data = isBindKey ? undefined2 : getData(func); - var newData = [ - func, - bitmask, - thisArg, - partials, - holders, - partialsRight, - holdersRight, - argPos, - ary2, - arity - ]; - if (data) { - mergeData(newData, data); - } - func = newData[0]; - bitmask = newData[1]; - thisArg = newData[2]; - partials = newData[3]; - holders = newData[4]; - arity = newData[9] = newData[9] === undefined2 ? isBindKey ? 0 : func.length : nativeMax(newData[9] - length, 0); - if (!arity && bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG)) { - bitmask &= ~(WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG); - } - if (!bitmask || bitmask == WRAP_BIND_FLAG) { - var result2 = createBind(func, bitmask, thisArg); - } else if (bitmask == WRAP_CURRY_FLAG || bitmask == WRAP_CURRY_RIGHT_FLAG) { - result2 = createCurry(func, bitmask, arity); - } else if ((bitmask == WRAP_PARTIAL_FLAG || bitmask == (WRAP_BIND_FLAG | WRAP_PARTIAL_FLAG)) && !holders.length) { - result2 = createPartial(func, bitmask, thisArg, partials); - } else { - result2 = createHybrid.apply(undefined2, newData); - } - var setter = data ? baseSetData : setData; - return setWrapToString(setter(result2, newData), func, bitmask); - } - function customDefaultsAssignIn(objValue, srcValue, key, object) { - if (objValue === undefined2 || eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key)) { - return srcValue; - } - return objValue; - } - function customDefaultsMerge(objValue, srcValue, key, object, source, stack) { - if (isObject(objValue) && isObject(srcValue)) { - stack.set(srcValue, objValue); - baseMerge(objValue, srcValue, undefined2, customDefaultsMerge, stack); - stack["delete"](srcValue); - } - return objValue; - } - function customOmitClone(value) { - return isPlainObject(value) ? undefined2 : value; - } - function equalArrays(array, other, bitmask, customizer, equalFunc, stack) { - var isPartial = bitmask & COMPARE_PARTIAL_FLAG, arrLength = array.length, othLength = other.length; - if (arrLength != othLength && !(isPartial && othLength > arrLength)) { - return false; - } - var arrStacked = stack.get(array); - var othStacked = stack.get(other); - if (arrStacked && othStacked) { - return arrStacked == other && othStacked == array; - } - var index = -1, result2 = true, seen = bitmask & COMPARE_UNORDERED_FLAG ? new SetCache() : undefined2; - stack.set(array, other); - stack.set(other, array); - while (++index < arrLength) { - var arrValue = array[index], othValue = other[index]; - if (customizer) { - var compared = isPartial ? customizer(othValue, arrValue, index, other, array, stack) : customizer(arrValue, othValue, index, array, other, stack); - } - if (compared !== undefined2) { - if (compared) { - continue; - } - result2 = false; - break; - } - if (seen) { - if (!arraySome(other, function(othValue2, othIndex) { - if (!cacheHas(seen, othIndex) && (arrValue === othValue2 || equalFunc(arrValue, othValue2, bitmask, customizer, stack))) { - return seen.push(othIndex); - } - })) { - result2 = false; - break; - } - } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) { - result2 = false; - break; - } - } - stack["delete"](array); - stack["delete"](other); - return result2; - } - function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) { - switch (tag) { - case dataViewTag: - if (object.byteLength != other.byteLength || object.byteOffset != other.byteOffset) { - return false; - } - object = object.buffer; - other = other.buffer; - case arrayBufferTag: - if (object.byteLength != other.byteLength || !equalFunc(new Uint8Array2(object), new Uint8Array2(other))) { - return false; - } - return true; - case boolTag: - case dateTag: - case numberTag: - return eq(+object, +other); - case errorTag: - return object.name == other.name && object.message == other.message; - case regexpTag: - case stringTag: - return object == other + ""; - case mapTag: - var convert = mapToArray; - case setTag: - var isPartial = bitmask & COMPARE_PARTIAL_FLAG; - convert || (convert = setToArray); - if (object.size != other.size && !isPartial) { - return false; - } - var stacked = stack.get(object); - if (stacked) { - return stacked == other; - } - bitmask |= COMPARE_UNORDERED_FLAG; - stack.set(object, other); - var result2 = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack); - stack["delete"](object); - return result2; - case symbolTag: - if (symbolValueOf) { - return symbolValueOf.call(object) == symbolValueOf.call(other); - } - } - return false; - } - function equalObjects(object, other, bitmask, customizer, equalFunc, stack) { - var isPartial = bitmask & COMPARE_PARTIAL_FLAG, objProps = getAllKeys(object), objLength = objProps.length, othProps = getAllKeys(other), othLength = othProps.length; - if (objLength != othLength && !isPartial) { - return false; - } - var index = objLength; - while (index--) { - var key = objProps[index]; - if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) { - return false; - } - } - var objStacked = stack.get(object); - var othStacked = stack.get(other); - if (objStacked && othStacked) { - return objStacked == other && othStacked == object; - } - var result2 = true; - stack.set(object, other); - stack.set(other, object); - var skipCtor = isPartial; - while (++index < objLength) { - key = objProps[index]; - var objValue = object[key], othValue = other[key]; - if (customizer) { - var compared = isPartial ? customizer(othValue, objValue, key, other, object, stack) : customizer(objValue, othValue, key, object, other, stack); - } - if (!(compared === undefined2 ? objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack) : compared)) { - result2 = false; - break; - } - skipCtor || (skipCtor = key == "constructor"); - } - if (result2 && !skipCtor) { - var objCtor = object.constructor, othCtor = other.constructor; - if (objCtor != othCtor && ("constructor" in object && "constructor" in other) && !(typeof objCtor == "function" && objCtor instanceof objCtor && typeof othCtor == "function" && othCtor instanceof othCtor)) { - result2 = false; - } - } - stack["delete"](object); - stack["delete"](other); - return result2; - } - function flatRest(func) { - return setToString(overRest(func, undefined2, flatten), func + ""); - } - function getAllKeys(object) { - return baseGetAllKeys(object, keys, getSymbols); - } - function getAllKeysIn(object) { - return baseGetAllKeys(object, keysIn, getSymbolsIn); - } - var getData = !metaMap ? noop : function(func) { - return metaMap.get(func); - }; - function getFuncName(func) { - var result2 = func.name + "", array = realNames[result2], length = hasOwnProperty.call(realNames, result2) ? array.length : 0; - while (length--) { - var data = array[length], otherFunc = data.func; - if (otherFunc == null || otherFunc == func) { - return data.name; - } - } - return result2; - } - function getHolder(func) { - var object = hasOwnProperty.call(lodash, "placeholder") ? lodash : func; - return object.placeholder; - } - function getIteratee() { - var result2 = lodash.iteratee || iteratee; - result2 = result2 === iteratee ? baseIteratee : result2; - return arguments.length ? result2(arguments[0], arguments[1]) : result2; - } - function getMapData(map2, key) { - var data = map2.__data__; - return isKeyable(key) ? data[typeof key == "string" ? "string" : "hash"] : data.map; - } - function getMatchData(object) { - var result2 = keys(object), length = result2.length; - while (length--) { - var key = result2[length], value = object[key]; - result2[length] = [key, value, isStrictComparable(value)]; - } - return result2; - } - function getNative(object, key) { - var value = getValue(object, key); - return baseIsNative(value) ? value : undefined2; - } - function getRawTag(value) { - var isOwn = hasOwnProperty.call(value, symToStringTag), tag = value[symToStringTag]; - try { - value[symToStringTag] = undefined2; - var unmasked = true; - } catch (e) { - } - var result2 = nativeObjectToString.call(value); - if (unmasked) { - if (isOwn) { - value[symToStringTag] = tag; - } else { - delete value[symToStringTag]; - } - } - return result2; - } - var getSymbols = !nativeGetSymbols ? stubArray : function(object) { - if (object == null) { - return []; - } - object = Object2(object); - return arrayFilter(nativeGetSymbols(object), function(symbol) { - return propertyIsEnumerable.call(object, symbol); - }); - }; - var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) { - var result2 = []; - while (object) { - arrayPush(result2, getSymbols(object)); - object = getPrototype(object); - } - return result2; - }; - var getTag = baseGetTag; - if (DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag || Map && getTag(new Map()) != mapTag || Promise2 && getTag(Promise2.resolve()) != promiseTag || Set2 && getTag(new Set2()) != setTag || WeakMap && getTag(new WeakMap()) != weakMapTag) { - getTag = function(value) { - var result2 = baseGetTag(value), Ctor = result2 == objectTag ? value.constructor : undefined2, ctorString = Ctor ? toSource(Ctor) : ""; - if (ctorString) { - switch (ctorString) { - case dataViewCtorString: - return dataViewTag; - case mapCtorString: - return mapTag; - case promiseCtorString: - return promiseTag; - case setCtorString: - return setTag; - case weakMapCtorString: - return weakMapTag; - } - } - return result2; - }; - } - function getView(start, end, transforms) { - var index = -1, length = transforms.length; - while (++index < length) { - var data = transforms[index], size2 = data.size; - switch (data.type) { - case "drop": - start += size2; - break; - case "dropRight": - end -= size2; - break; - case "take": - end = nativeMin(end, start + size2); - break; - case "takeRight": - start = nativeMax(start, end - size2); - break; - } - } - return { "start": start, "end": end }; - } - function getWrapDetails(source) { - var match = source.match(reWrapDetails); - return match ? match[1].split(reSplitDetails) : []; - } - function hasPath(object, path, hasFunc) { - path = castPath(path, object); - var index = -1, length = path.length, result2 = false; - while (++index < length) { - var key = toKey(path[index]); - if (!(result2 = object != null && hasFunc(object, key))) { - break; - } - object = object[key]; - } - if (result2 || ++index != length) { - return result2; - } - length = object == null ? 0 : object.length; - return !!length && isLength(length) && isIndex(key, length) && (isArray(object) || isArguments(object)); - } - function initCloneArray(array) { - var length = array.length, result2 = new array.constructor(length); - if (length && typeof array[0] == "string" && hasOwnProperty.call(array, "index")) { - result2.index = array.index; - result2.input = array.input; - } - return result2; - } - function initCloneObject(object) { - return typeof object.constructor == "function" && !isPrototype(object) ? baseCreate(getPrototype(object)) : {}; - } - function initCloneByTag(object, tag, isDeep) { - var Ctor = object.constructor; - switch (tag) { - case arrayBufferTag: - return cloneArrayBuffer(object); - case boolTag: - case dateTag: - return new Ctor(+object); - case dataViewTag: - return cloneDataView(object, isDeep); - case float32Tag: - case float64Tag: - case int8Tag: - case int16Tag: - case int32Tag: - case uint8Tag: - case uint8ClampedTag: - case uint16Tag: - case uint32Tag: - return cloneTypedArray(object, isDeep); - case mapTag: - return new Ctor(); - case numberTag: - case stringTag: - return new Ctor(object); - case regexpTag: - return cloneRegExp(object); - case setTag: - return new Ctor(); - case symbolTag: - return cloneSymbol(object); - } - } - function insertWrapDetails(source, details) { - var length = details.length; - if (!length) { - return source; - } - var lastIndex = length - 1; - details[lastIndex] = (length > 1 ? "& " : "") + details[lastIndex]; - details = details.join(length > 2 ? ", " : " "); - return source.replace(reWrapComment, "{\n/* [wrapped with " + details + "] */\n"); - } - function isFlattenable(value) { - return isArray(value) || isArguments(value) || !!(spreadableSymbol && value && value[spreadableSymbol]); - } - function isIndex(value, length) { - var type = typeof value; - length = length == null ? MAX_SAFE_INTEGER : length; - return !!length && (type == "number" || type != "symbol" && reIsUint.test(value)) && (value > -1 && value % 1 == 0 && value < length); - } - function isIterateeCall(value, index, object) { - if (!isObject(object)) { - return false; - } - var type = typeof index; - if (type == "number" ? isArrayLike(object) && isIndex(index, object.length) : type == "string" && index in object) { - return eq(object[index], value); - } - return false; - } - function isKey(value, object) { - if (isArray(value)) { - return false; - } - var type = typeof value; - if (type == "number" || type == "symbol" || type == "boolean" || value == null || isSymbol(value)) { - return true; - } - return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || object != null && value in Object2(object); - } - function isKeyable(value) { - var type = typeof value; - return type == "string" || type == "number" || type == "symbol" || type == "boolean" ? value !== "__proto__" : value === null; - } - function isLaziable(func) { - var funcName = getFuncName(func), other = lodash[funcName]; - if (typeof other != "function" || !(funcName in LazyWrapper.prototype)) { - return false; - } - if (func === other) { - return true; - } - var data = getData(other); - return !!data && func === data[0]; - } - function isMasked(func) { - return !!maskSrcKey && maskSrcKey in func; - } - var isMaskable = coreJsData ? isFunction : stubFalse; - function isPrototype(value) { - var Ctor = value && value.constructor, proto = typeof Ctor == "function" && Ctor.prototype || objectProto; - return value === proto; - } - function isStrictComparable(value) { - return value === value && !isObject(value); - } - function matchesStrictComparable(key, srcValue) { - return function(object) { - if (object == null) { - return false; - } - return object[key] === srcValue && (srcValue !== undefined2 || key in Object2(object)); - }; - } - function memoizeCapped(func) { - var result2 = memoize(func, function(key) { - if (cache.size === MAX_MEMOIZE_SIZE) { - cache.clear(); - } - return key; - }); - var cache = result2.cache; - return result2; - } - function mergeData(data, source) { - var bitmask = data[1], srcBitmask = source[1], newBitmask = bitmask | srcBitmask, isCommon = newBitmask < (WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG | WRAP_ARY_FLAG); - var isCombo = srcBitmask == WRAP_ARY_FLAG && bitmask == WRAP_CURRY_FLAG || srcBitmask == WRAP_ARY_FLAG && bitmask == WRAP_REARG_FLAG && data[7].length <= source[8] || srcBitmask == (WRAP_ARY_FLAG | WRAP_REARG_FLAG) && source[7].length <= source[8] && bitmask == WRAP_CURRY_FLAG; - if (!(isCommon || isCombo)) { - return data; - } - if (srcBitmask & WRAP_BIND_FLAG) { - data[2] = source[2]; - newBitmask |= bitmask & WRAP_BIND_FLAG ? 0 : WRAP_CURRY_BOUND_FLAG; - } - var value = source[3]; - if (value) { - var partials = data[3]; - data[3] = partials ? composeArgs(partials, value, source[4]) : value; - data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : source[4]; - } - value = source[5]; - if (value) { - partials = data[5]; - data[5] = partials ? composeArgsRight(partials, value, source[6]) : value; - data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : source[6]; - } - value = source[7]; - if (value) { - data[7] = value; - } - if (srcBitmask & WRAP_ARY_FLAG) { - data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]); - } - if (data[9] == null) { - data[9] = source[9]; - } - data[0] = source[0]; - data[1] = newBitmask; - return data; - } - function nativeKeysIn(object) { - var result2 = []; - if (object != null) { - for (var key in Object2(object)) { - result2.push(key); - } - } - return result2; - } - function objectToString(value) { - return nativeObjectToString.call(value); - } - function overRest(func, start, transform2) { - start = nativeMax(start === undefined2 ? func.length - 1 : start, 0); - return function() { - var args = arguments, index = -1, length = nativeMax(args.length - start, 0), array = Array2(length); - while (++index < length) { - array[index] = args[start + index]; - } - index = -1; - var otherArgs = Array2(start + 1); - while (++index < start) { - otherArgs[index] = args[index]; - } - otherArgs[start] = transform2(array); - return apply(func, this, otherArgs); - }; - } - function parent(object, path) { - return path.length < 2 ? object : baseGet(object, baseSlice(path, 0, -1)); - } - function reorder(array, indexes) { - var arrLength = array.length, length = nativeMin(indexes.length, arrLength), oldArray = copyArray(array); - while (length--) { - var index = indexes[length]; - array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined2; - } - return array; - } - function safeGet(object, key) { - if (key === "constructor" && typeof object[key] === "function") { - return; - } - if (key == "__proto__") { - return; - } - return object[key]; - } - var setData = shortOut(baseSetData); - var setTimeout = ctxSetTimeout || function(func, wait) { - return root.setTimeout(func, wait); - }; - var setToString = shortOut(baseSetToString); - function setWrapToString(wrapper, reference, bitmask) { - var source = reference + ""; - return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask))); - } - function shortOut(func) { - var count = 0, lastCalled = 0; - return function() { - var stamp = nativeNow(), remaining = HOT_SPAN - (stamp - lastCalled); - lastCalled = stamp; - if (remaining > 0) { - if (++count >= HOT_COUNT) { - return arguments[0]; - } - } else { - count = 0; - } - return func.apply(undefined2, arguments); - }; - } - function shuffleSelf(array, size2) { - var index = -1, length = array.length, lastIndex = length - 1; - size2 = size2 === undefined2 ? length : size2; - while (++index < size2) { - var rand = baseRandom(index, lastIndex), value = array[rand]; - array[rand] = array[index]; - array[index] = value; - } - array.length = size2; - return array; - } - var stringToPath = memoizeCapped(function(string) { - var result2 = []; - if (string.charCodeAt(0) === 46) { - result2.push(""); - } - string.replace(rePropName, function(match, number, quote, subString) { - result2.push(quote ? subString.replace(reEscapeChar, "$1") : number || match); - }); - return result2; - }); - function toKey(value) { - if (typeof value == "string" || isSymbol(value)) { - return value; - } - var result2 = value + ""; - return result2 == "0" && 1 / value == -INFINITY ? "-0" : result2; - } - function toSource(func) { - if (func != null) { - try { - return funcToString.call(func); - } catch (e) { - } - try { - return func + ""; - } catch (e) { - } - } - return ""; - } - function updateWrapDetails(details, bitmask) { - arrayEach(wrapFlags, function(pair) { - var value = "_." + pair[0]; - if (bitmask & pair[1] && !arrayIncludes(details, value)) { - details.push(value); - } - }); - return details.sort(); - } - function wrapperClone(wrapper) { - if (wrapper instanceof LazyWrapper) { - return wrapper.clone(); - } - var result2 = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__); - result2.__actions__ = copyArray(wrapper.__actions__); - result2.__index__ = wrapper.__index__; - result2.__values__ = wrapper.__values__; - return result2; - } - function chunk(array, size2, guard) { - if (guard ? isIterateeCall(array, size2, guard) : size2 === undefined2) { - size2 = 1; - } else { - size2 = nativeMax(toInteger(size2), 0); - } - var length = array == null ? 0 : array.length; - if (!length || size2 < 1) { - return []; - } - var index = 0, resIndex = 0, result2 = Array2(nativeCeil(length / size2)); - while (index < length) { - result2[resIndex++] = baseSlice(array, index, index += size2); - } - return result2; - } - function compact(array) { - var index = -1, length = array == null ? 0 : array.length, resIndex = 0, result2 = []; - while (++index < length) { - var value = array[index]; - if (value) { - result2[resIndex++] = value; - } - } - return result2; - } - function concat() { - var length = arguments.length; - if (!length) { - return []; - } - var args = Array2(length - 1), array = arguments[0], index = length; - while (index--) { - args[index - 1] = arguments[index]; - } - return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1)); - } - var difference = baseRest(function(array, values2) { - return isArrayLikeObject(array) ? baseDifference(array, baseFlatten(values2, 1, isArrayLikeObject, true)) : []; - }); - var differenceBy = baseRest(function(array, values2) { - var iteratee2 = last(values2); - if (isArrayLikeObject(iteratee2)) { - iteratee2 = undefined2; - } - return isArrayLikeObject(array) ? baseDifference(array, baseFlatten(values2, 1, isArrayLikeObject, true), getIteratee(iteratee2, 2)) : []; - }); - var differenceWith = baseRest(function(array, values2) { - var comparator = last(values2); - if (isArrayLikeObject(comparator)) { - comparator = undefined2; - } - return isArrayLikeObject(array) ? baseDifference(array, baseFlatten(values2, 1, isArrayLikeObject, true), undefined2, comparator) : []; - }); - function drop(array, n, guard) { - var length = array == null ? 0 : array.length; - if (!length) { - return []; - } - n = guard || n === undefined2 ? 1 : toInteger(n); - return baseSlice(array, n < 0 ? 0 : n, length); - } - function dropRight(array, n, guard) { - var length = array == null ? 0 : array.length; - if (!length) { - return []; - } - n = guard || n === undefined2 ? 1 : toInteger(n); - n = length - n; - return baseSlice(array, 0, n < 0 ? 0 : n); - } - function dropRightWhile(array, predicate) { - return array && array.length ? baseWhile(array, getIteratee(predicate, 3), true, true) : []; - } - function dropWhile(array, predicate) { - return array && array.length ? baseWhile(array, getIteratee(predicate, 3), true) : []; - } - function fill(array, value, start, end) { - var length = array == null ? 0 : array.length; - if (!length) { - return []; - } - if (start && typeof start != "number" && isIterateeCall(array, value, start)) { - start = 0; - end = length; - } - return baseFill(array, value, start, end); - } - function findIndex(array, predicate, fromIndex) { - var length = array == null ? 0 : array.length; - if (!length) { - return -1; - } - var index = fromIndex == null ? 0 : toInteger(fromIndex); - if (index < 0) { - index = nativeMax(length + index, 0); - } - return baseFindIndex(array, getIteratee(predicate, 3), index); - } - function findLastIndex(array, predicate, fromIndex) { - var length = array == null ? 0 : array.length; - if (!length) { - return -1; - } - var index = length - 1; - if (fromIndex !== undefined2) { - index = toInteger(fromIndex); - index = fromIndex < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1); - } - return baseFindIndex(array, getIteratee(predicate, 3), index, true); - } - function flatten(array) { - var length = array == null ? 0 : array.length; - return length ? baseFlatten(array, 1) : []; - } - function flattenDeep(array) { - var length = array == null ? 0 : array.length; - return length ? baseFlatten(array, INFINITY) : []; - } - function flattenDepth(array, depth) { - var length = array == null ? 0 : array.length; - if (!length) { - return []; - } - depth = depth === undefined2 ? 1 : toInteger(depth); - return baseFlatten(array, depth); - } - function fromPairs(pairs) { - var index = -1, length = pairs == null ? 0 : pairs.length, result2 = {}; - while (++index < length) { - var pair = pairs[index]; - result2[pair[0]] = pair[1]; - } - return result2; - } - function head(array) { - return array && array.length ? array[0] : undefined2; - } - function indexOf(array, value, fromIndex) { - var length = array == null ? 0 : array.length; - if (!length) { - return -1; - } - var index = fromIndex == null ? 0 : toInteger(fromIndex); - if (index < 0) { - index = nativeMax(length + index, 0); - } - return baseIndexOf(array, value, index); - } - function initial(array) { - var length = array == null ? 0 : array.length; - return length ? baseSlice(array, 0, -1) : []; - } - var intersection = baseRest(function(arrays) { - var mapped = arrayMap(arrays, castArrayLikeObject); - return mapped.length && mapped[0] === arrays[0] ? baseIntersection(mapped) : []; - }); - var intersectionBy = baseRest(function(arrays) { - var iteratee2 = last(arrays), mapped = arrayMap(arrays, castArrayLikeObject); - if (iteratee2 === last(mapped)) { - iteratee2 = undefined2; - } else { - mapped.pop(); - } - return mapped.length && mapped[0] === arrays[0] ? baseIntersection(mapped, getIteratee(iteratee2, 2)) : []; - }); - var intersectionWith = baseRest(function(arrays) { - var comparator = last(arrays), mapped = arrayMap(arrays, castArrayLikeObject); - comparator = typeof comparator == "function" ? comparator : undefined2; - if (comparator) { - mapped.pop(); - } - return mapped.length && mapped[0] === arrays[0] ? baseIntersection(mapped, undefined2, comparator) : []; - }); - function join(array, separator) { - return array == null ? "" : nativeJoin.call(array, separator); - } - function last(array) { - var length = array == null ? 0 : array.length; - return length ? array[length - 1] : undefined2; - } - function lastIndexOf(array, value, fromIndex) { - var length = array == null ? 0 : array.length; - if (!length) { - return -1; - } - var index = length; - if (fromIndex !== undefined2) { - index = toInteger(fromIndex); - index = index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1); - } - return value === value ? strictLastIndexOf(array, value, index) : baseFindIndex(array, baseIsNaN, index, true); - } - function nth(array, n) { - return array && array.length ? baseNth(array, toInteger(n)) : undefined2; - } - var pull = baseRest(pullAll); - function pullAll(array, values2) { - return array && array.length && values2 && values2.length ? basePullAll(array, values2) : array; - } - function pullAllBy(array, values2, iteratee2) { - return array && array.length && values2 && values2.length ? basePullAll(array, values2, getIteratee(iteratee2, 2)) : array; - } - function pullAllWith(array, values2, comparator) { - return array && array.length && values2 && values2.length ? basePullAll(array, values2, undefined2, comparator) : array; - } - var pullAt = flatRest(function(array, indexes) { - var length = array == null ? 0 : array.length, result2 = baseAt(array, indexes); - basePullAt(array, arrayMap(indexes, function(index) { - return isIndex(index, length) ? +index : index; - }).sort(compareAscending)); - return result2; - }); - function remove(array, predicate) { - var result2 = []; - if (!(array && array.length)) { - return result2; - } - var index = -1, indexes = [], length = array.length; - predicate = getIteratee(predicate, 3); - while (++index < length) { - var value = array[index]; - if (predicate(value, index, array)) { - result2.push(value); - indexes.push(index); - } - } - basePullAt(array, indexes); - return result2; - } - function reverse(array) { - return array == null ? array : nativeReverse.call(array); - } - function slice(array, start, end) { - var length = array == null ? 0 : array.length; - if (!length) { - return []; - } - if (end && typeof end != "number" && isIterateeCall(array, start, end)) { - start = 0; - end = length; - } else { - start = start == null ? 0 : toInteger(start); - end = end === undefined2 ? length : toInteger(end); - } - return baseSlice(array, start, end); - } - function sortedIndex(array, value) { - return baseSortedIndex(array, value); - } - function sortedIndexBy(array, value, iteratee2) { - return baseSortedIndexBy(array, value, getIteratee(iteratee2, 2)); - } - function sortedIndexOf(array, value) { - var length = array == null ? 0 : array.length; - if (length) { - var index = baseSortedIndex(array, value); - if (index < length && eq(array[index], value)) { - return index; - } - } - return -1; - } - function sortedLastIndex(array, value) { - return baseSortedIndex(array, value, true); - } - function sortedLastIndexBy(array, value, iteratee2) { - return baseSortedIndexBy(array, value, getIteratee(iteratee2, 2), true); - } - function sortedLastIndexOf(array, value) { - var length = array == null ? 0 : array.length; - if (length) { - var index = baseSortedIndex(array, value, true) - 1; - if (eq(array[index], value)) { - return index; - } - } - return -1; - } - function sortedUniq(array) { - return array && array.length ? baseSortedUniq(array) : []; - } - function sortedUniqBy(array, iteratee2) { - return array && array.length ? baseSortedUniq(array, getIteratee(iteratee2, 2)) : []; - } - function tail(array) { - var length = array == null ? 0 : array.length; - return length ? baseSlice(array, 1, length) : []; - } - function take(array, n, guard) { - if (!(array && array.length)) { - return []; - } - n = guard || n === undefined2 ? 1 : toInteger(n); - return baseSlice(array, 0, n < 0 ? 0 : n); - } - function takeRight(array, n, guard) { - var length = array == null ? 0 : array.length; - if (!length) { - return []; - } - n = guard || n === undefined2 ? 1 : toInteger(n); - n = length - n; - return baseSlice(array, n < 0 ? 0 : n, length); - } - function takeRightWhile(array, predicate) { - return array && array.length ? baseWhile(array, getIteratee(predicate, 3), false, true) : []; - } - function takeWhile(array, predicate) { - return array && array.length ? baseWhile(array, getIteratee(predicate, 3)) : []; - } - var union = baseRest(function(arrays) { - return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true)); - }); - var unionBy = baseRest(function(arrays) { - var iteratee2 = last(arrays); - if (isArrayLikeObject(iteratee2)) { - iteratee2 = undefined2; - } - return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), getIteratee(iteratee2, 2)); - }); - var unionWith = baseRest(function(arrays) { - var comparator = last(arrays); - comparator = typeof comparator == "function" ? comparator : undefined2; - return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), undefined2, comparator); - }); - function uniq(array) { - return array && array.length ? baseUniq(array) : []; - } - function uniqBy(array, iteratee2) { - return array && array.length ? baseUniq(array, getIteratee(iteratee2, 2)) : []; - } - function uniqWith(array, comparator) { - comparator = typeof comparator == "function" ? comparator : undefined2; - return array && array.length ? baseUniq(array, undefined2, comparator) : []; - } - function unzip(array) { - if (!(array && array.length)) { - return []; - } - var length = 0; - array = arrayFilter(array, function(group) { - if (isArrayLikeObject(group)) { - length = nativeMax(group.length, length); - return true; - } - }); - return baseTimes(length, function(index) { - return arrayMap(array, baseProperty(index)); - }); - } - function unzipWith(array, iteratee2) { - if (!(array && array.length)) { - return []; - } - var result2 = unzip(array); - if (iteratee2 == null) { - return result2; - } - return arrayMap(result2, function(group) { - return apply(iteratee2, undefined2, group); - }); - } - var without = baseRest(function(array, values2) { - return isArrayLikeObject(array) ? baseDifference(array, values2) : []; - }); - var xor = baseRest(function(arrays) { - return baseXor(arrayFilter(arrays, isArrayLikeObject)); - }); - var xorBy = baseRest(function(arrays) { - var iteratee2 = last(arrays); - if (isArrayLikeObject(iteratee2)) { - iteratee2 = undefined2; - } - return baseXor(arrayFilter(arrays, isArrayLikeObject), getIteratee(iteratee2, 2)); - }); - var xorWith = baseRest(function(arrays) { - var comparator = last(arrays); - comparator = typeof comparator == "function" ? comparator : undefined2; - return baseXor(arrayFilter(arrays, isArrayLikeObject), undefined2, comparator); - }); - var zip = baseRest(unzip); - function zipObject(props, values2) { - return baseZipObject(props || [], values2 || [], assignValue); - } - function zipObjectDeep(props, values2) { - return baseZipObject(props || [], values2 || [], baseSet); - } - var zipWith = baseRest(function(arrays) { - var length = arrays.length, iteratee2 = length > 1 ? arrays[length - 1] : undefined2; - iteratee2 = typeof iteratee2 == "function" ? (arrays.pop(), iteratee2) : undefined2; - return unzipWith(arrays, iteratee2); - }); - function chain(value) { - var result2 = lodash(value); - result2.__chain__ = true; - return result2; - } - function tap(value, interceptor) { - interceptor(value); - return value; - } - function thru(value, interceptor) { - return interceptor(value); - } - var wrapperAt = flatRest(function(paths) { - var length = paths.length, start = length ? paths[0] : 0, value = this.__wrapped__, interceptor = function(object) { - return baseAt(object, paths); - }; - if (length > 1 || this.__actions__.length || !(value instanceof LazyWrapper) || !isIndex(start)) { - return this.thru(interceptor); - } - value = value.slice(start, +start + (length ? 1 : 0)); - value.__actions__.push({ - "func": thru, - "args": [interceptor], - "thisArg": undefined2 - }); - return new LodashWrapper(value, this.__chain__).thru(function(array) { - if (length && !array.length) { - array.push(undefined2); - } - return array; - }); - }); - function wrapperChain() { - return chain(this); - } - function wrapperCommit() { - return new LodashWrapper(this.value(), this.__chain__); - } - function wrapperNext() { - if (this.__values__ === undefined2) { - this.__values__ = toArray(this.value()); - } - var done = this.__index__ >= this.__values__.length, value = done ? undefined2 : this.__values__[this.__index__++]; - return { "done": done, "value": value }; - } - function wrapperToIterator() { - return this; - } - function wrapperPlant(value) { - var result2, parent2 = this; - while (parent2 instanceof baseLodash) { - var clone2 = wrapperClone(parent2); - clone2.__index__ = 0; - clone2.__values__ = undefined2; - if (result2) { - previous.__wrapped__ = clone2; - } else { - result2 = clone2; - } - var previous = clone2; - parent2 = parent2.__wrapped__; - } - previous.__wrapped__ = value; - return result2; - } - function wrapperReverse() { - var value = this.__wrapped__; - if (value instanceof LazyWrapper) { - var wrapped = value; - if (this.__actions__.length) { - wrapped = new LazyWrapper(this); - } - wrapped = wrapped.reverse(); - wrapped.__actions__.push({ - "func": thru, - "args": [reverse], - "thisArg": undefined2 - }); - return new LodashWrapper(wrapped, this.__chain__); - } - return this.thru(reverse); - } - function wrapperValue() { - return baseWrapperValue(this.__wrapped__, this.__actions__); - } - var countBy = createAggregator(function(result2, value, key) { - if (hasOwnProperty.call(result2, key)) { - ++result2[key]; - } else { - baseAssignValue(result2, key, 1); - } - }); - function every(collection, predicate, guard) { - var func = isArray(collection) ? arrayEvery : baseEvery; - if (guard && isIterateeCall(collection, predicate, guard)) { - predicate = undefined2; - } - return func(collection, getIteratee(predicate, 3)); - } - function filter(collection, predicate) { - var func = isArray(collection) ? arrayFilter : baseFilter; - return func(collection, getIteratee(predicate, 3)); - } - var find = createFind(findIndex); - var findLast = createFind(findLastIndex); - function flatMap(collection, iteratee2) { - return baseFlatten(map(collection, iteratee2), 1); - } - function flatMapDeep(collection, iteratee2) { - return baseFlatten(map(collection, iteratee2), INFINITY); - } - function flatMapDepth(collection, iteratee2, depth) { - depth = depth === undefined2 ? 1 : toInteger(depth); - return baseFlatten(map(collection, iteratee2), depth); - } - function forEach(collection, iteratee2) { - var func = isArray(collection) ? arrayEach : baseEach; - return func(collection, getIteratee(iteratee2, 3)); - } - function forEachRight(collection, iteratee2) { - var func = isArray(collection) ? arrayEachRight : baseEachRight; - return func(collection, getIteratee(iteratee2, 3)); - } - var groupBy = createAggregator(function(result2, value, key) { - if (hasOwnProperty.call(result2, key)) { - result2[key].push(value); - } else { - baseAssignValue(result2, key, [value]); - } - }); - function includes(collection, value, fromIndex, guard) { - collection = isArrayLike(collection) ? collection : values(collection); - fromIndex = fromIndex && !guard ? toInteger(fromIndex) : 0; - var length = collection.length; - if (fromIndex < 0) { - fromIndex = nativeMax(length + fromIndex, 0); - } - return isString(collection) ? fromIndex <= length && collection.indexOf(value, fromIndex) > -1 : !!length && baseIndexOf(collection, value, fromIndex) > -1; - } - var invokeMap = baseRest(function(collection, path, args) { - var index = -1, isFunc = typeof path == "function", result2 = isArrayLike(collection) ? Array2(collection.length) : []; - baseEach(collection, function(value) { - result2[++index] = isFunc ? apply(path, value, args) : baseInvoke(value, path, args); - }); - return result2; - }); - var keyBy = createAggregator(function(result2, value, key) { - baseAssignValue(result2, key, value); - }); - function map(collection, iteratee2) { - var func = isArray(collection) ? arrayMap : baseMap; - return func(collection, getIteratee(iteratee2, 3)); - } - function orderBy(collection, iteratees, orders, guard) { - if (collection == null) { - return []; - } - if (!isArray(iteratees)) { - iteratees = iteratees == null ? [] : [iteratees]; - } - orders = guard ? undefined2 : orders; - if (!isArray(orders)) { - orders = orders == null ? [] : [orders]; - } - return baseOrderBy(collection, iteratees, orders); - } - var partition = createAggregator(function(result2, value, key) { - result2[key ? 0 : 1].push(value); - }, function() { - return [[], []]; - }); - function reduce(collection, iteratee2, accumulator) { - var func = isArray(collection) ? arrayReduce : baseReduce, initAccum = arguments.length < 3; - return func(collection, getIteratee(iteratee2, 4), accumulator, initAccum, baseEach); - } - function reduceRight(collection, iteratee2, accumulator) { - var func = isArray(collection) ? arrayReduceRight : baseReduce, initAccum = arguments.length < 3; - return func(collection, getIteratee(iteratee2, 4), accumulator, initAccum, baseEachRight); - } - function reject(collection, predicate) { - var func = isArray(collection) ? arrayFilter : baseFilter; - return func(collection, negate(getIteratee(predicate, 3))); - } - function sample(collection) { - var func = isArray(collection) ? arraySample : baseSample; - return func(collection); - } - function sampleSize(collection, n, guard) { - if (guard ? isIterateeCall(collection, n, guard) : n === undefined2) { - n = 1; - } else { - n = toInteger(n); - } - var func = isArray(collection) ? arraySampleSize : baseSampleSize; - return func(collection, n); - } - function shuffle(collection) { - var func = isArray(collection) ? arrayShuffle : baseShuffle; - return func(collection); - } - function size(collection) { - if (collection == null) { - return 0; - } - if (isArrayLike(collection)) { - return isString(collection) ? stringSize(collection) : collection.length; - } - var tag = getTag(collection); - if (tag == mapTag || tag == setTag) { - return collection.size; - } - return baseKeys(collection).length; - } - function some(collection, predicate, guard) { - var func = isArray(collection) ? arraySome : baseSome; - if (guard && isIterateeCall(collection, predicate, guard)) { - predicate = undefined2; - } - return func(collection, getIteratee(predicate, 3)); - } - var sortBy = baseRest(function(collection, iteratees) { - if (collection == null) { - return []; - } - var length = iteratees.length; - if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) { - iteratees = []; - } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) { - iteratees = [iteratees[0]]; - } - return baseOrderBy(collection, baseFlatten(iteratees, 1), []); - }); - var now = ctxNow || function() { - return root.Date.now(); - }; - function after(n, func) { - if (typeof func != "function") { - throw new TypeError2(FUNC_ERROR_TEXT); - } - n = toInteger(n); - return function() { - if (--n < 1) { - return func.apply(this, arguments); - } - }; - } - function ary(func, n, guard) { - n = guard ? undefined2 : n; - n = func && n == null ? func.length : n; - return createWrap(func, WRAP_ARY_FLAG, undefined2, undefined2, undefined2, undefined2, n); - } - function before(n, func) { - var result2; - if (typeof func != "function") { - throw new TypeError2(FUNC_ERROR_TEXT); - } - n = toInteger(n); - return function() { - if (--n > 0) { - result2 = func.apply(this, arguments); - } - if (n <= 1) { - func = undefined2; - } - return result2; - }; - } - var bind = baseRest(function(func, thisArg, partials) { - var bitmask = WRAP_BIND_FLAG; - if (partials.length) { - var holders = replaceHolders(partials, getHolder(bind)); - bitmask |= WRAP_PARTIAL_FLAG; - } - return createWrap(func, bitmask, thisArg, partials, holders); - }); - var bindKey = baseRest(function(object, key, partials) { - var bitmask = WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG; - if (partials.length) { - var holders = replaceHolders(partials, getHolder(bindKey)); - bitmask |= WRAP_PARTIAL_FLAG; - } - return createWrap(key, bitmask, object, partials, holders); - }); - function curry(func, arity, guard) { - arity = guard ? undefined2 : arity; - var result2 = createWrap(func, WRAP_CURRY_FLAG, undefined2, undefined2, undefined2, undefined2, undefined2, arity); - result2.placeholder = curry.placeholder; - return result2; - } - function curryRight(func, arity, guard) { - arity = guard ? undefined2 : arity; - var result2 = createWrap(func, WRAP_CURRY_RIGHT_FLAG, undefined2, undefined2, undefined2, undefined2, undefined2, arity); - result2.placeholder = curryRight.placeholder; - return result2; - } - function debounce(func, wait, options) { - var lastArgs, lastThis, maxWait, result2, timerId, lastCallTime, lastInvokeTime = 0, leading = false, maxing = false, trailing = true; - if (typeof func != "function") { - throw new TypeError2(FUNC_ERROR_TEXT); - } - wait = toNumber(wait) || 0; - if (isObject(options)) { - leading = !!options.leading; - maxing = "maxWait" in options; - maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait; - trailing = "trailing" in options ? !!options.trailing : trailing; - } - function invokeFunc(time) { - var args = lastArgs, thisArg = lastThis; - lastArgs = lastThis = undefined2; - lastInvokeTime = time; - result2 = func.apply(thisArg, args); - return result2; - } - function leadingEdge(time) { - lastInvokeTime = time; - timerId = setTimeout(timerExpired, wait); - return leading ? invokeFunc(time) : result2; - } - function remainingWait(time) { - var timeSinceLastCall = time - lastCallTime, timeSinceLastInvoke = time - lastInvokeTime, timeWaiting = wait - timeSinceLastCall; - return maxing ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke) : timeWaiting; - } - function shouldInvoke(time) { - var timeSinceLastCall = time - lastCallTime, timeSinceLastInvoke = time - lastInvokeTime; - return lastCallTime === undefined2 || timeSinceLastCall >= wait || timeSinceLastCall < 0 || maxing && timeSinceLastInvoke >= maxWait; - } - function timerExpired() { - var time = now(); - if (shouldInvoke(time)) { - return trailingEdge(time); - } - timerId = setTimeout(timerExpired, remainingWait(time)); - } - function trailingEdge(time) { - timerId = undefined2; - if (trailing && lastArgs) { - return invokeFunc(time); - } - lastArgs = lastThis = undefined2; - return result2; - } - function cancel() { - if (timerId !== undefined2) { - clearTimeout(timerId); - } - lastInvokeTime = 0; - lastArgs = lastCallTime = lastThis = timerId = undefined2; - } - function flush() { - return timerId === undefined2 ? result2 : trailingEdge(now()); - } - function debounced() { - var time = now(), isInvoking = shouldInvoke(time); - lastArgs = arguments; - lastThis = this; - lastCallTime = time; - if (isInvoking) { - if (timerId === undefined2) { - return leadingEdge(lastCallTime); - } - if (maxing) { - clearTimeout(timerId); - timerId = setTimeout(timerExpired, wait); - return invokeFunc(lastCallTime); - } - } - if (timerId === undefined2) { - timerId = setTimeout(timerExpired, wait); - } - return result2; - } - debounced.cancel = cancel; - debounced.flush = flush; - return debounced; - } - var defer = baseRest(function(func, args) { - return baseDelay(func, 1, args); - }); - var delay = baseRest(function(func, wait, args) { - return baseDelay(func, toNumber(wait) || 0, args); - }); - function flip(func) { - return createWrap(func, WRAP_FLIP_FLAG); - } - function memoize(func, resolver) { - if (typeof func != "function" || resolver != null && typeof resolver != "function") { - throw new TypeError2(FUNC_ERROR_TEXT); - } - var memoized = function() { - var args = arguments, key = resolver ? resolver.apply(this, args) : args[0], cache = memoized.cache; - if (cache.has(key)) { - return cache.get(key); - } - var result2 = func.apply(this, args); - memoized.cache = cache.set(key, result2) || cache; - return result2; - }; - memoized.cache = new (memoize.Cache || MapCache)(); - return memoized; - } - memoize.Cache = MapCache; - function negate(predicate) { - if (typeof predicate != "function") { - throw new TypeError2(FUNC_ERROR_TEXT); - } - return function() { - var args = arguments; - switch (args.length) { - case 0: - return !predicate.call(this); - case 1: - return !predicate.call(this, args[0]); - case 2: - return !predicate.call(this, args[0], args[1]); - case 3: - return !predicate.call(this, args[0], args[1], args[2]); - } - return !predicate.apply(this, args); - }; - } - function once(func) { - return before(2, func); - } - var overArgs = castRest(function(func, transforms) { - transforms = transforms.length == 1 && isArray(transforms[0]) ? arrayMap(transforms[0], baseUnary(getIteratee())) : arrayMap(baseFlatten(transforms, 1), baseUnary(getIteratee())); - var funcsLength = transforms.length; - return baseRest(function(args) { - var index = -1, length = nativeMin(args.length, funcsLength); - while (++index < length) { - args[index] = transforms[index].call(this, args[index]); - } - return apply(func, this, args); - }); - }); - var partial = baseRest(function(func, partials) { - var holders = replaceHolders(partials, getHolder(partial)); - return createWrap(func, WRAP_PARTIAL_FLAG, undefined2, partials, holders); - }); - var partialRight = baseRest(function(func, partials) { - var holders = replaceHolders(partials, getHolder(partialRight)); - return createWrap(func, WRAP_PARTIAL_RIGHT_FLAG, undefined2, partials, holders); - }); - var rearg = flatRest(function(func, indexes) { - return createWrap(func, WRAP_REARG_FLAG, undefined2, undefined2, undefined2, indexes); - }); - function rest(func, start) { - if (typeof func != "function") { - throw new TypeError2(FUNC_ERROR_TEXT); - } - start = start === undefined2 ? start : toInteger(start); - return baseRest(func, start); - } - function spread(func, start) { - if (typeof func != "function") { - throw new TypeError2(FUNC_ERROR_TEXT); - } - start = start == null ? 0 : nativeMax(toInteger(start), 0); - return baseRest(function(args) { - var array = args[start], otherArgs = castSlice(args, 0, start); - if (array) { - arrayPush(otherArgs, array); - } - return apply(func, this, otherArgs); - }); - } - function throttle(func, wait, options) { - var leading = true, trailing = true; - if (typeof func != "function") { - throw new TypeError2(FUNC_ERROR_TEXT); - } - if (isObject(options)) { - leading = "leading" in options ? !!options.leading : leading; - trailing = "trailing" in options ? !!options.trailing : trailing; - } - return debounce(func, wait, { - "leading": leading, - "maxWait": wait, - "trailing": trailing - }); - } - function unary(func) { - return ary(func, 1); - } - function wrap(value, wrapper) { - return partial(castFunction(wrapper), value); - } - function castArray() { - if (!arguments.length) { - return []; - } - var value = arguments[0]; - return isArray(value) ? value : [value]; - } - function clone(value) { - return baseClone(value, CLONE_SYMBOLS_FLAG); - } - function cloneWith(value, customizer) { - customizer = typeof customizer == "function" ? customizer : undefined2; - return baseClone(value, CLONE_SYMBOLS_FLAG, customizer); - } - function cloneDeep(value) { - return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG); - } - function cloneDeepWith(value, customizer) { - customizer = typeof customizer == "function" ? customizer : undefined2; - return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG, customizer); - } - function conformsTo(object, source) { - return source == null || baseConformsTo(object, source, keys(source)); - } - function eq(value, other) { - return value === other || value !== value && other !== other; - } - var gt = createRelationalOperation(baseGt); - var gte = createRelationalOperation(function(value, other) { - return value >= other; - }); - var isArguments = baseIsArguments(/* @__PURE__ */ function() { - return arguments; - }()) ? baseIsArguments : function(value) { - return isObjectLike(value) && hasOwnProperty.call(value, "callee") && !propertyIsEnumerable.call(value, "callee"); - }; - var isArray = Array2.isArray; - var isArrayBuffer = nodeIsArrayBuffer ? baseUnary(nodeIsArrayBuffer) : baseIsArrayBuffer; - function isArrayLike(value) { - return value != null && isLength(value.length) && !isFunction(value); - } - function isArrayLikeObject(value) { - return isObjectLike(value) && isArrayLike(value); - } - function isBoolean(value) { - return value === true || value === false || isObjectLike(value) && baseGetTag(value) == boolTag; - } - var isBuffer = nativeIsBuffer || stubFalse; - var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate; - function isElement(value) { - return isObjectLike(value) && value.nodeType === 1 && !isPlainObject(value); - } - function isEmpty(value) { - if (value == null) { - return true; - } - if (isArrayLike(value) && (isArray(value) || typeof value == "string" || typeof value.splice == "function" || isBuffer(value) || isTypedArray(value) || isArguments(value))) { - return !value.length; - } - var tag = getTag(value); - if (tag == mapTag || tag == setTag) { - return !value.size; - } - if (isPrototype(value)) { - return !baseKeys(value).length; - } - for (var key in value) { - if (hasOwnProperty.call(value, key)) { - return false; - } - } - return true; - } - function isEqual(value, other) { - return baseIsEqual(value, other); - } - function isEqualWith(value, other, customizer) { - customizer = typeof customizer == "function" ? customizer : undefined2; - var result2 = customizer ? customizer(value, other) : undefined2; - return result2 === undefined2 ? baseIsEqual(value, other, undefined2, customizer) : !!result2; - } - function isError(value) { - if (!isObjectLike(value)) { - return false; - } - var tag = baseGetTag(value); - return tag == errorTag || tag == domExcTag || typeof value.message == "string" && typeof value.name == "string" && !isPlainObject(value); - } - function isFinite2(value) { - return typeof value == "number" && nativeIsFinite(value); - } - function isFunction(value) { - if (!isObject(value)) { - return false; - } - var tag = baseGetTag(value); - return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag; - } - function isInteger(value) { - return typeof value == "number" && value == toInteger(value); - } - function isLength(value) { - return typeof value == "number" && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; - } - function isObject(value) { - var type = typeof value; - return value != null && (type == "object" || type == "function"); - } - function isObjectLike(value) { - return value != null && typeof value == "object"; - } - var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap; - function isMatch(object, source) { - return object === source || baseIsMatch(object, source, getMatchData(source)); - } - function isMatchWith(object, source, customizer) { - customizer = typeof customizer == "function" ? customizer : undefined2; - return baseIsMatch(object, source, getMatchData(source), customizer); - } - function isNaN2(value) { - return isNumber(value) && value != +value; - } - function isNative(value) { - if (isMaskable(value)) { - throw new Error2(CORE_ERROR_TEXT); - } - return baseIsNative(value); - } - function isNull(value) { - return value === null; - } - function isNil(value) { - return value == null; - } - function isNumber(value) { - return typeof value == "number" || isObjectLike(value) && baseGetTag(value) == numberTag; - } - function isPlainObject(value) { - if (!isObjectLike(value) || baseGetTag(value) != objectTag) { - return false; - } - var proto = getPrototype(value); - if (proto === null) { - return true; - } - var Ctor = hasOwnProperty.call(proto, "constructor") && proto.constructor; - return typeof Ctor == "function" && Ctor instanceof Ctor && funcToString.call(Ctor) == objectCtorString; - } - var isRegExp = nodeIsRegExp ? baseUnary(nodeIsRegExp) : baseIsRegExp; - function isSafeInteger(value) { - return isInteger(value) && value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER; - } - var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet; - function isString(value) { - return typeof value == "string" || !isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag; - } - function isSymbol(value) { - return typeof value == "symbol" || isObjectLike(value) && baseGetTag(value) == symbolTag; - } - var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray; - function isUndefined(value) { - return value === undefined2; - } - function isWeakMap(value) { - return isObjectLike(value) && getTag(value) == weakMapTag; - } - function isWeakSet(value) { - return isObjectLike(value) && baseGetTag(value) == weakSetTag; - } - var lt = createRelationalOperation(baseLt); - var lte = createRelationalOperation(function(value, other) { - return value <= other; - }); - function toArray(value) { - if (!value) { - return []; - } - if (isArrayLike(value)) { - return isString(value) ? stringToArray(value) : copyArray(value); - } - if (symIterator && value[symIterator]) { - return iteratorToArray(value[symIterator]()); - } - var tag = getTag(value), func = tag == mapTag ? mapToArray : tag == setTag ? setToArray : values; - return func(value); - } - function toFinite(value) { - if (!value) { - return value === 0 ? value : 0; - } - value = toNumber(value); - if (value === INFINITY || value === -INFINITY) { - var sign = value < 0 ? -1 : 1; - return sign * MAX_INTEGER; - } - return value === value ? value : 0; - } - function toInteger(value) { - var result2 = toFinite(value), remainder = result2 % 1; - return result2 === result2 ? remainder ? result2 - remainder : result2 : 0; - } - function toLength(value) { - return value ? baseClamp(toInteger(value), 0, MAX_ARRAY_LENGTH) : 0; - } - function toNumber(value) { - if (typeof value == "number") { - return value; - } - if (isSymbol(value)) { - return NAN; - } - if (isObject(value)) { - var other = typeof value.valueOf == "function" ? value.valueOf() : value; - value = isObject(other) ? other + "" : other; - } - if (typeof value != "string") { - return value === 0 ? value : +value; - } - value = baseTrim(value); - var isBinary = reIsBinary.test(value); - return isBinary || reIsOctal.test(value) ? freeParseInt(value.slice(2), isBinary ? 2 : 8) : reIsBadHex.test(value) ? NAN : +value; - } - function toPlainObject(value) { - return copyObject(value, keysIn(value)); - } - function toSafeInteger(value) { - return value ? baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER) : value === 0 ? value : 0; - } - function toString(value) { - return value == null ? "" : baseToString(value); - } - var assign = createAssigner(function(object, source) { - if (isPrototype(source) || isArrayLike(source)) { - copyObject(source, keys(source), object); - return; - } - for (var key in source) { - if (hasOwnProperty.call(source, key)) { - assignValue(object, key, source[key]); - } - } - }); - var assignIn = createAssigner(function(object, source) { - copyObject(source, keysIn(source), object); - }); - var assignInWith = createAssigner(function(object, source, srcIndex, customizer) { - copyObject(source, keysIn(source), object, customizer); - }); - var assignWith = createAssigner(function(object, source, srcIndex, customizer) { - copyObject(source, keys(source), object, customizer); - }); - var at = flatRest(baseAt); - function create(prototype, properties) { - var result2 = baseCreate(prototype); - return properties == null ? result2 : baseAssign(result2, properties); - } - var defaults = baseRest(function(object, sources) { - object = Object2(object); - var index = -1; - var length = sources.length; - var guard = length > 2 ? sources[2] : undefined2; - if (guard && isIterateeCall(sources[0], sources[1], guard)) { - length = 1; - } - while (++index < length) { - var source = sources[index]; - var props = keysIn(source); - var propsIndex = -1; - var propsLength = props.length; - while (++propsIndex < propsLength) { - var key = props[propsIndex]; - var value = object[key]; - if (value === undefined2 || eq(value, objectProto[key]) && !hasOwnProperty.call(object, key)) { - object[key] = source[key]; - } - } - } - return object; - }); - var defaultsDeep = baseRest(function(args) { - args.push(undefined2, customDefaultsMerge); - return apply(mergeWith, undefined2, args); - }); - function findKey(object, predicate) { - return baseFindKey(object, getIteratee(predicate, 3), baseForOwn); - } - function findLastKey(object, predicate) { - return baseFindKey(object, getIteratee(predicate, 3), baseForOwnRight); - } - function forIn(object, iteratee2) { - return object == null ? object : baseFor(object, getIteratee(iteratee2, 3), keysIn); - } - function forInRight(object, iteratee2) { - return object == null ? object : baseForRight(object, getIteratee(iteratee2, 3), keysIn); - } - function forOwn(object, iteratee2) { - return object && baseForOwn(object, getIteratee(iteratee2, 3)); - } - function forOwnRight(object, iteratee2) { - return object && baseForOwnRight(object, getIteratee(iteratee2, 3)); - } - function functions(object) { - return object == null ? [] : baseFunctions(object, keys(object)); - } - function functionsIn(object) { - return object == null ? [] : baseFunctions(object, keysIn(object)); - } - function get(object, path, defaultValue) { - var result2 = object == null ? undefined2 : baseGet(object, path); - return result2 === undefined2 ? defaultValue : result2; - } - function has(object, path) { - return object != null && hasPath(object, path, baseHas); - } - function hasIn(object, path) { - return object != null && hasPath(object, path, baseHasIn); - } - var invert = createInverter(function(result2, value, key) { - if (value != null && typeof value.toString != "function") { - value = nativeObjectToString.call(value); - } - result2[value] = key; - }, constant(identity)); - var invertBy = createInverter(function(result2, value, key) { - if (value != null && typeof value.toString != "function") { - value = nativeObjectToString.call(value); - } - if (hasOwnProperty.call(result2, value)) { - result2[value].push(key); - } else { - result2[value] = [key]; - } - }, getIteratee); - var invoke = baseRest(baseInvoke); - function keys(object) { - return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object); - } - function keysIn(object) { - return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object); - } - function mapKeys(object, iteratee2) { - var result2 = {}; - iteratee2 = getIteratee(iteratee2, 3); - baseForOwn(object, function(value, key, object2) { - baseAssignValue(result2, iteratee2(value, key, object2), value); - }); - return result2; - } - function mapValues(object, iteratee2) { - var result2 = {}; - iteratee2 = getIteratee(iteratee2, 3); - baseForOwn(object, function(value, key, object2) { - baseAssignValue(result2, key, iteratee2(value, key, object2)); - }); - return result2; - } - var merge = createAssigner(function(object, source, srcIndex) { - baseMerge(object, source, srcIndex); - }); - var mergeWith = createAssigner(function(object, source, srcIndex, customizer) { - baseMerge(object, source, srcIndex, customizer); - }); - var omit = flatRest(function(object, paths) { - var result2 = {}; - if (object == null) { - return result2; - } - var isDeep = false; - paths = arrayMap(paths, function(path) { - path = castPath(path, object); - isDeep || (isDeep = path.length > 1); - return path; - }); - copyObject(object, getAllKeysIn(object), result2); - if (isDeep) { - result2 = baseClone(result2, CLONE_DEEP_FLAG | CLONE_FLAT_FLAG | CLONE_SYMBOLS_FLAG, customOmitClone); - } - var length = paths.length; - while (length--) { - baseUnset(result2, paths[length]); - } - return result2; - }); - function omitBy(object, predicate) { - return pickBy(object, negate(getIteratee(predicate))); - } - var pick = flatRest(function(object, paths) { - return object == null ? {} : basePick(object, paths); - }); - function pickBy(object, predicate) { - if (object == null) { - return {}; - } - var props = arrayMap(getAllKeysIn(object), function(prop) { - return [prop]; - }); - predicate = getIteratee(predicate); - return basePickBy(object, props, function(value, path) { - return predicate(value, path[0]); - }); - } - function result(object, path, defaultValue) { - path = castPath(path, object); - var index = -1, length = path.length; - if (!length) { - length = 1; - object = undefined2; - } - while (++index < length) { - var value = object == null ? undefined2 : object[toKey(path[index])]; - if (value === undefined2) { - index = length; - value = defaultValue; - } - object = isFunction(value) ? value.call(object) : value; - } - return object; - } - function set(object, path, value) { - return object == null ? object : baseSet(object, path, value); - } - function setWith(object, path, value, customizer) { - customizer = typeof customizer == "function" ? customizer : undefined2; - return object == null ? object : baseSet(object, path, value, customizer); - } - var toPairs = createToPairs(keys); - var toPairsIn = createToPairs(keysIn); - function transform(object, iteratee2, accumulator) { - var isArr = isArray(object), isArrLike = isArr || isBuffer(object) || isTypedArray(object); - iteratee2 = getIteratee(iteratee2, 4); - if (accumulator == null) { - var Ctor = object && object.constructor; - if (isArrLike) { - accumulator = isArr ? new Ctor() : []; - } else if (isObject(object)) { - accumulator = isFunction(Ctor) ? baseCreate(getPrototype(object)) : {}; - } else { - accumulator = {}; - } - } - (isArrLike ? arrayEach : baseForOwn)(object, function(value, index, object2) { - return iteratee2(accumulator, value, index, object2); - }); - return accumulator; - } - function unset(object, path) { - return object == null ? true : baseUnset(object, path); - } - function update(object, path, updater) { - return object == null ? object : baseUpdate(object, path, castFunction(updater)); - } - function updateWith(object, path, updater, customizer) { - customizer = typeof customizer == "function" ? customizer : undefined2; - return object == null ? object : baseUpdate(object, path, castFunction(updater), customizer); - } - function values(object) { - return object == null ? [] : baseValues(object, keys(object)); - } - function valuesIn(object) { - return object == null ? [] : baseValues(object, keysIn(object)); - } - function clamp(number, lower, upper) { - if (upper === undefined2) { - upper = lower; - lower = undefined2; - } - if (upper !== undefined2) { - upper = toNumber(upper); - upper = upper === upper ? upper : 0; - } - if (lower !== undefined2) { - lower = toNumber(lower); - lower = lower === lower ? lower : 0; - } - return baseClamp(toNumber(number), lower, upper); - } - function inRange(number, start, end) { - start = toFinite(start); - if (end === undefined2) { - end = start; - start = 0; - } else { - end = toFinite(end); - } - number = toNumber(number); - return baseInRange(number, start, end); - } - function random(lower, upper, floating) { - if (floating && typeof floating != "boolean" && isIterateeCall(lower, upper, floating)) { - upper = floating = undefined2; - } - if (floating === undefined2) { - if (typeof upper == "boolean") { - floating = upper; - upper = undefined2; - } else if (typeof lower == "boolean") { - floating = lower; - lower = undefined2; - } - } - if (lower === undefined2 && upper === undefined2) { - lower = 0; - upper = 1; - } else { - lower = toFinite(lower); - if (upper === undefined2) { - upper = lower; - lower = 0; - } else { - upper = toFinite(upper); - } - } - if (lower > upper) { - var temp = lower; - lower = upper; - upper = temp; - } - if (floating || lower % 1 || upper % 1) { - var rand = nativeRandom(); - return nativeMin(lower + rand * (upper - lower + freeParseFloat("1e-" + ((rand + "").length - 1))), upper); - } - return baseRandom(lower, upper); - } - var camelCase = createCompounder(function(result2, word, index) { - word = word.toLowerCase(); - return result2 + (index ? capitalize(word) : word); - }); - function capitalize(string) { - return upperFirst(toString(string).toLowerCase()); - } - function deburr(string) { - string = toString(string); - return string && string.replace(reLatin, deburrLetter).replace(reComboMark, ""); - } - function endsWith(string, target, position) { - string = toString(string); - target = baseToString(target); - var length = string.length; - position = position === undefined2 ? length : baseClamp(toInteger(position), 0, length); - var end = position; - position -= target.length; - return position >= 0 && string.slice(position, end) == target; - } - function escape(string) { - string = toString(string); - return string && reHasUnescapedHtml.test(string) ? string.replace(reUnescapedHtml, escapeHtmlChar) : string; - } - function escapeRegExp(string) { - string = toString(string); - return string && reHasRegExpChar.test(string) ? string.replace(reRegExpChar, "\\$&") : string; - } - var kebabCase = createCompounder(function(result2, word, index) { - return result2 + (index ? "-" : "") + word.toLowerCase(); - }); - var lowerCase = createCompounder(function(result2, word, index) { - return result2 + (index ? " " : "") + word.toLowerCase(); - }); - var lowerFirst = createCaseFirst("toLowerCase"); - function pad(string, length, chars) { - string = toString(string); - length = toInteger(length); - var strLength = length ? stringSize(string) : 0; - if (!length || strLength >= length) { - return string; - } - var mid = (length - strLength) / 2; - return createPadding(nativeFloor(mid), chars) + string + createPadding(nativeCeil(mid), chars); - } - function padEnd(string, length, chars) { - string = toString(string); - length = toInteger(length); - var strLength = length ? stringSize(string) : 0; - return length && strLength < length ? string + createPadding(length - strLength, chars) : string; - } - function padStart(string, length, chars) { - string = toString(string); - length = toInteger(length); - var strLength = length ? stringSize(string) : 0; - return length && strLength < length ? createPadding(length - strLength, chars) + string : string; - } - function parseInt2(string, radix, guard) { - if (guard || radix == null) { - radix = 0; - } else if (radix) { - radix = +radix; - } - return nativeParseInt(toString(string).replace(reTrimStart, ""), radix || 0); - } - function repeat(string, n, guard) { - if (guard ? isIterateeCall(string, n, guard) : n === undefined2) { - n = 1; - } else { - n = toInteger(n); - } - return baseRepeat(toString(string), n); - } - function replace() { - var args = arguments, string = toString(args[0]); - return args.length < 3 ? string : string.replace(args[1], args[2]); - } - var snakeCase = createCompounder(function(result2, word, index) { - return result2 + (index ? "_" : "") + word.toLowerCase(); - }); - function split(string, separator, limit) { - if (limit && typeof limit != "number" && isIterateeCall(string, separator, limit)) { - separator = limit = undefined2; - } - limit = limit === undefined2 ? MAX_ARRAY_LENGTH : limit >>> 0; - if (!limit) { - return []; - } - string = toString(string); - if (string && (typeof separator == "string" || separator != null && !isRegExp(separator))) { - separator = baseToString(separator); - if (!separator && hasUnicode(string)) { - return castSlice(stringToArray(string), 0, limit); - } - } - return string.split(separator, limit); - } - var startCase = createCompounder(function(result2, word, index) { - return result2 + (index ? " " : "") + upperFirst(word); - }); - function startsWith(string, target, position) { - string = toString(string); - position = position == null ? 0 : baseClamp(toInteger(position), 0, string.length); - target = baseToString(target); - return string.slice(position, position + target.length) == target; - } - function template(string, options, guard) { - var settings = lodash.templateSettings; - if (guard && isIterateeCall(string, options, guard)) { - options = undefined2; - } - string = toString(string); - options = assignInWith({}, options, settings, customDefaultsAssignIn); - var imports = assignInWith({}, options.imports, settings.imports, customDefaultsAssignIn), importsKeys = keys(imports), importsValues = baseValues(imports, importsKeys); - var isEscaping, isEvaluating, index = 0, interpolate = options.interpolate || reNoMatch, source = "__p += '"; - var reDelimiters = RegExp2( - (options.escape || reNoMatch).source + "|" + interpolate.source + "|" + (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + "|" + (options.evaluate || reNoMatch).source + "|$", - "g" - ); - var sourceURL = "//# sourceURL=" + (hasOwnProperty.call(options, "sourceURL") ? (options.sourceURL + "").replace(/\s/g, " ") : "lodash.templateSources[" + ++templateCounter + "]") + "\n"; - string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) { - interpolateValue || (interpolateValue = esTemplateValue); - source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar); - if (escapeValue) { - isEscaping = true; - source += "' +\n__e(" + escapeValue + ") +\n'"; - } - if (evaluateValue) { - isEvaluating = true; - source += "';\n" + evaluateValue + ";\n__p += '"; - } - if (interpolateValue) { - source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'"; - } - index = offset + match.length; - return match; - }); - source += "';\n"; - var variable = hasOwnProperty.call(options, "variable") && options.variable; - if (!variable) { - source = "with (obj) {\n" + source + "\n}\n"; - } else if (reForbiddenIdentifierChars.test(variable)) { - throw new Error2(INVALID_TEMPL_VAR_ERROR_TEXT); - } - source = (isEvaluating ? source.replace(reEmptyStringLeading, "") : source).replace(reEmptyStringMiddle, "$1").replace(reEmptyStringTrailing, "$1;"); - source = "function(" + (variable || "obj") + ") {\n" + (variable ? "" : "obj || (obj = {});\n") + "var __t, __p = ''" + (isEscaping ? ", __e = _.escape" : "") + (isEvaluating ? ", __j = Array.prototype.join;\nfunction print() { __p += __j.call(arguments, '') }\n" : ";\n") + source + "return __p\n}"; - var result2 = attempt(function() { - return Function2(importsKeys, sourceURL + "return " + source).apply(undefined2, importsValues); - }); - result2.source = source; - if (isError(result2)) { - throw result2; - } - return result2; - } - function toLower(value) { - return toString(value).toLowerCase(); - } - function toUpper(value) { - return toString(value).toUpperCase(); - } - function trim(string, chars, guard) { - string = toString(string); - if (string && (guard || chars === undefined2)) { - return baseTrim(string); - } - if (!string || !(chars = baseToString(chars))) { - return string; - } - var strSymbols = stringToArray(string), chrSymbols = stringToArray(chars), start = charsStartIndex(strSymbols, chrSymbols), end = charsEndIndex(strSymbols, chrSymbols) + 1; - return castSlice(strSymbols, start, end).join(""); - } - function trimEnd(string, chars, guard) { - string = toString(string); - if (string && (guard || chars === undefined2)) { - return string.slice(0, trimmedEndIndex(string) + 1); - } - if (!string || !(chars = baseToString(chars))) { - return string; - } - var strSymbols = stringToArray(string), end = charsEndIndex(strSymbols, stringToArray(chars)) + 1; - return castSlice(strSymbols, 0, end).join(""); - } - function trimStart(string, chars, guard) { - string = toString(string); - if (string && (guard || chars === undefined2)) { - return string.replace(reTrimStart, ""); - } - if (!string || !(chars = baseToString(chars))) { - return string; - } - var strSymbols = stringToArray(string), start = charsStartIndex(strSymbols, stringToArray(chars)); - return castSlice(strSymbols, start).join(""); - } - function truncate(string, options) { - var length = DEFAULT_TRUNC_LENGTH, omission = DEFAULT_TRUNC_OMISSION; - if (isObject(options)) { - var separator = "separator" in options ? options.separator : separator; - length = "length" in options ? toInteger(options.length) : length; - omission = "omission" in options ? baseToString(options.omission) : omission; - } - string = toString(string); - var strLength = string.length; - if (hasUnicode(string)) { - var strSymbols = stringToArray(string); - strLength = strSymbols.length; - } - if (length >= strLength) { - return string; - } - var end = length - stringSize(omission); - if (end < 1) { - return omission; - } - var result2 = strSymbols ? castSlice(strSymbols, 0, end).join("") : string.slice(0, end); - if (separator === undefined2) { - return result2 + omission; - } - if (strSymbols) { - end += result2.length - end; - } - if (isRegExp(separator)) { - if (string.slice(end).search(separator)) { - var match, substring = result2; - if (!separator.global) { - separator = RegExp2(separator.source, toString(reFlags.exec(separator)) + "g"); - } - separator.lastIndex = 0; - while (match = separator.exec(substring)) { - var newEnd = match.index; - } - result2 = result2.slice(0, newEnd === undefined2 ? end : newEnd); - } - } else if (string.indexOf(baseToString(separator), end) != end) { - var index = result2.lastIndexOf(separator); - if (index > -1) { - result2 = result2.slice(0, index); - } - } - return result2 + omission; - } - function unescape(string) { - string = toString(string); - return string && reHasEscapedHtml.test(string) ? string.replace(reEscapedHtml, unescapeHtmlChar) : string; - } - var upperCase = createCompounder(function(result2, word, index) { - return result2 + (index ? " " : "") + word.toUpperCase(); - }); - var upperFirst = createCaseFirst("toUpperCase"); - function words(string, pattern, guard) { - string = toString(string); - pattern = guard ? undefined2 : pattern; - if (pattern === undefined2) { - return hasUnicodeWord(string) ? unicodeWords(string) : asciiWords(string); - } - return string.match(pattern) || []; - } - var attempt = baseRest(function(func, args) { - try { - return apply(func, undefined2, args); - } catch (e) { - return isError(e) ? e : new Error2(e); - } - }); - var bindAll = flatRest(function(object, methodNames) { - arrayEach(methodNames, function(key) { - key = toKey(key); - baseAssignValue(object, key, bind(object[key], object)); - }); - return object; - }); - function cond(pairs) { - var length = pairs == null ? 0 : pairs.length, toIteratee = getIteratee(); - pairs = !length ? [] : arrayMap(pairs, function(pair) { - if (typeof pair[1] != "function") { - throw new TypeError2(FUNC_ERROR_TEXT); - } - return [toIteratee(pair[0]), pair[1]]; - }); - return baseRest(function(args) { - var index = -1; - while (++index < length) { - var pair = pairs[index]; - if (apply(pair[0], this, args)) { - return apply(pair[1], this, args); - } - } - }); - } - function conforms(source) { - return baseConforms(baseClone(source, CLONE_DEEP_FLAG)); - } - function constant(value) { - return function() { - return value; - }; - } - function defaultTo(value, defaultValue) { - return value == null || value !== value ? defaultValue : value; - } - var flow = createFlow(); - var flowRight = createFlow(true); - function identity(value) { - return value; - } - function iteratee(func) { - return baseIteratee(typeof func == "function" ? func : baseClone(func, CLONE_DEEP_FLAG)); - } - function matches(source) { - return baseMatches(baseClone(source, CLONE_DEEP_FLAG)); - } - function matchesProperty(path, srcValue) { - return baseMatchesProperty(path, baseClone(srcValue, CLONE_DEEP_FLAG)); - } - var method = baseRest(function(path, args) { - return function(object) { - return baseInvoke(object, path, args); - }; - }); - var methodOf = baseRest(function(object, args) { - return function(path) { - return baseInvoke(object, path, args); - }; - }); - function mixin(object, source, options) { - var props = keys(source), methodNames = baseFunctions(source, props); - if (options == null && !(isObject(source) && (methodNames.length || !props.length))) { - options = source; - source = object; - object = this; - methodNames = baseFunctions(source, keys(source)); - } - var chain2 = !(isObject(options) && "chain" in options) || !!options.chain, isFunc = isFunction(object); - arrayEach(methodNames, function(methodName) { - var func = source[methodName]; - object[methodName] = func; - if (isFunc) { - object.prototype[methodName] = function() { - var chainAll = this.__chain__; - if (chain2 || chainAll) { - var result2 = object(this.__wrapped__), actions = result2.__actions__ = copyArray(this.__actions__); - actions.push({ "func": func, "args": arguments, "thisArg": object }); - result2.__chain__ = chainAll; - return result2; - } - return func.apply(object, arrayPush([this.value()], arguments)); - }; - } - }); - return object; - } - function noConflict() { - if (root._ === this) { - root._ = oldDash; - } - return this; - } - function noop() { - } - function nthArg(n) { - n = toInteger(n); - return baseRest(function(args) { - return baseNth(args, n); - }); - } - var over = createOver(arrayMap); - var overEvery = createOver(arrayEvery); - var overSome = createOver(arraySome); - function property(path) { - return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path); - } - function propertyOf(object) { - return function(path) { - return object == null ? undefined2 : baseGet(object, path); - }; - } - var range = createRange(); - var rangeRight = createRange(true); - function stubArray() { - return []; - } - function stubFalse() { - return false; - } - function stubObject() { - return {}; - } - function stubString() { - return ""; - } - function stubTrue() { - return true; - } - function times(n, iteratee2) { - n = toInteger(n); - if (n < 1 || n > MAX_SAFE_INTEGER) { - return []; - } - var index = MAX_ARRAY_LENGTH, length = nativeMin(n, MAX_ARRAY_LENGTH); - iteratee2 = getIteratee(iteratee2); - n -= MAX_ARRAY_LENGTH; - var result2 = baseTimes(length, iteratee2); - while (++index < n) { - iteratee2(index); - } - return result2; - } - function toPath(value) { - if (isArray(value)) { - return arrayMap(value, toKey); - } - return isSymbol(value) ? [value] : copyArray(stringToPath(toString(value))); - } - function uniqueId(prefix) { - var id = ++idCounter; - return toString(prefix) + id; - } - var add = createMathOperation(function(augend, addend) { - return augend + addend; - }, 0); - var ceil = createRound("ceil"); - var divide = createMathOperation(function(dividend, divisor) { - return dividend / divisor; - }, 1); - var floor = createRound("floor"); - function max(array) { - return array && array.length ? baseExtremum(array, identity, baseGt) : undefined2; - } - function maxBy(array, iteratee2) { - return array && array.length ? baseExtremum(array, getIteratee(iteratee2, 2), baseGt) : undefined2; - } - function mean(array) { - return baseMean(array, identity); - } - function meanBy(array, iteratee2) { - return baseMean(array, getIteratee(iteratee2, 2)); - } - function min(array) { - return array && array.length ? baseExtremum(array, identity, baseLt) : undefined2; - } - function minBy(array, iteratee2) { - return array && array.length ? baseExtremum(array, getIteratee(iteratee2, 2), baseLt) : undefined2; - } - var multiply = createMathOperation(function(multiplier, multiplicand) { - return multiplier * multiplicand; - }, 1); - var round = createRound("round"); - var subtract = createMathOperation(function(minuend, subtrahend) { - return minuend - subtrahend; - }, 0); - function sum(array) { - return array && array.length ? baseSum(array, identity) : 0; - } - function sumBy(array, iteratee2) { - return array && array.length ? baseSum(array, getIteratee(iteratee2, 2)) : 0; - } - lodash.after = after; - lodash.ary = ary; - lodash.assign = assign; - lodash.assignIn = assignIn; - lodash.assignInWith = assignInWith; - lodash.assignWith = assignWith; - lodash.at = at; - lodash.before = before; - lodash.bind = bind; - lodash.bindAll = bindAll; - lodash.bindKey = bindKey; - lodash.castArray = castArray; - lodash.chain = chain; - lodash.chunk = chunk; - lodash.compact = compact; - lodash.concat = concat; - lodash.cond = cond; - lodash.conforms = conforms; - lodash.constant = constant; - lodash.countBy = countBy; - lodash.create = create; - lodash.curry = curry; - lodash.curryRight = curryRight; - lodash.debounce = debounce; - lodash.defaults = defaults; - lodash.defaultsDeep = defaultsDeep; - lodash.defer = defer; - lodash.delay = delay; - lodash.difference = difference; - lodash.differenceBy = differenceBy; - lodash.differenceWith = differenceWith; - lodash.drop = drop; - lodash.dropRight = dropRight; - lodash.dropRightWhile = dropRightWhile; - lodash.dropWhile = dropWhile; - lodash.fill = fill; - lodash.filter = filter; - lodash.flatMap = flatMap; - lodash.flatMapDeep = flatMapDeep; - lodash.flatMapDepth = flatMapDepth; - lodash.flatten = flatten; - lodash.flattenDeep = flattenDeep; - lodash.flattenDepth = flattenDepth; - lodash.flip = flip; - lodash.flow = flow; - lodash.flowRight = flowRight; - lodash.fromPairs = fromPairs; - lodash.functions = functions; - lodash.functionsIn = functionsIn; - lodash.groupBy = groupBy; - lodash.initial = initial; - lodash.intersection = intersection; - lodash.intersectionBy = intersectionBy; - lodash.intersectionWith = intersectionWith; - lodash.invert = invert; - lodash.invertBy = invertBy; - lodash.invokeMap = invokeMap; - lodash.iteratee = iteratee; - lodash.keyBy = keyBy; - lodash.keys = keys; - lodash.keysIn = keysIn; - lodash.map = map; - lodash.mapKeys = mapKeys; - lodash.mapValues = mapValues; - lodash.matches = matches; - lodash.matchesProperty = matchesProperty; - lodash.memoize = memoize; - lodash.merge = merge; - lodash.mergeWith = mergeWith; - lodash.method = method; - lodash.methodOf = methodOf; - lodash.mixin = mixin; - lodash.negate = negate; - lodash.nthArg = nthArg; - lodash.omit = omit; - lodash.omitBy = omitBy; - lodash.once = once; - lodash.orderBy = orderBy; - lodash.over = over; - lodash.overArgs = overArgs; - lodash.overEvery = overEvery; - lodash.overSome = overSome; - lodash.partial = partial; - lodash.partialRight = partialRight; - lodash.partition = partition; - lodash.pick = pick; - lodash.pickBy = pickBy; - lodash.property = property; - lodash.propertyOf = propertyOf; - lodash.pull = pull; - lodash.pullAll = pullAll; - lodash.pullAllBy = pullAllBy; - lodash.pullAllWith = pullAllWith; - lodash.pullAt = pullAt; - lodash.range = range; - lodash.rangeRight = rangeRight; - lodash.rearg = rearg; - lodash.reject = reject; - lodash.remove = remove; - lodash.rest = rest; - lodash.reverse = reverse; - lodash.sampleSize = sampleSize; - lodash.set = set; - lodash.setWith = setWith; - lodash.shuffle = shuffle; - lodash.slice = slice; - lodash.sortBy = sortBy; - lodash.sortedUniq = sortedUniq; - lodash.sortedUniqBy = sortedUniqBy; - lodash.split = split; - lodash.spread = spread; - lodash.tail = tail; - lodash.take = take; - lodash.takeRight = takeRight; - lodash.takeRightWhile = takeRightWhile; - lodash.takeWhile = takeWhile; - lodash.tap = tap; - lodash.throttle = throttle; - lodash.thru = thru; - lodash.toArray = toArray; - lodash.toPairs = toPairs; - lodash.toPairsIn = toPairsIn; - lodash.toPath = toPath; - lodash.toPlainObject = toPlainObject; - lodash.transform = transform; - lodash.unary = unary; - lodash.union = union; - lodash.unionBy = unionBy; - lodash.unionWith = unionWith; - lodash.uniq = uniq; - lodash.uniqBy = uniqBy; - lodash.uniqWith = uniqWith; - lodash.unset = unset; - lodash.unzip = unzip; - lodash.unzipWith = unzipWith; - lodash.update = update; - lodash.updateWith = updateWith; - lodash.values = values; - lodash.valuesIn = valuesIn; - lodash.without = without; - lodash.words = words; - lodash.wrap = wrap; - lodash.xor = xor; - lodash.xorBy = xorBy; - lodash.xorWith = xorWith; - lodash.zip = zip; - lodash.zipObject = zipObject; - lodash.zipObjectDeep = zipObjectDeep; - lodash.zipWith = zipWith; - lodash.entries = toPairs; - lodash.entriesIn = toPairsIn; - lodash.extend = assignIn; - lodash.extendWith = assignInWith; - mixin(lodash, lodash); - lodash.add = add; - lodash.attempt = attempt; - lodash.camelCase = camelCase; - lodash.capitalize = capitalize; - lodash.ceil = ceil; - lodash.clamp = clamp; - lodash.clone = clone; - lodash.cloneDeep = cloneDeep; - lodash.cloneDeepWith = cloneDeepWith; - lodash.cloneWith = cloneWith; - lodash.conformsTo = conformsTo; - lodash.deburr = deburr; - lodash.defaultTo = defaultTo; - lodash.divide = divide; - lodash.endsWith = endsWith; - lodash.eq = eq; - lodash.escape = escape; - lodash.escapeRegExp = escapeRegExp; - lodash.every = every; - lodash.find = find; - lodash.findIndex = findIndex; - lodash.findKey = findKey; - lodash.findLast = findLast; - lodash.findLastIndex = findLastIndex; - lodash.findLastKey = findLastKey; - lodash.floor = floor; - lodash.forEach = forEach; - lodash.forEachRight = forEachRight; - lodash.forIn = forIn; - lodash.forInRight = forInRight; - lodash.forOwn = forOwn; - lodash.forOwnRight = forOwnRight; - lodash.get = get; - lodash.gt = gt; - lodash.gte = gte; - lodash.has = has; - lodash.hasIn = hasIn; - lodash.head = head; - lodash.identity = identity; - lodash.includes = includes; - lodash.indexOf = indexOf; - lodash.inRange = inRange; - lodash.invoke = invoke; - lodash.isArguments = isArguments; - lodash.isArray = isArray; - lodash.isArrayBuffer = isArrayBuffer; - lodash.isArrayLike = isArrayLike; - lodash.isArrayLikeObject = isArrayLikeObject; - lodash.isBoolean = isBoolean; - lodash.isBuffer = isBuffer; - lodash.isDate = isDate; - lodash.isElement = isElement; - lodash.isEmpty = isEmpty; - lodash.isEqual = isEqual; - lodash.isEqualWith = isEqualWith; - lodash.isError = isError; - lodash.isFinite = isFinite2; - lodash.isFunction = isFunction; - lodash.isInteger = isInteger; - lodash.isLength = isLength; - lodash.isMap = isMap; - lodash.isMatch = isMatch; - lodash.isMatchWith = isMatchWith; - lodash.isNaN = isNaN2; - lodash.isNative = isNative; - lodash.isNil = isNil; - lodash.isNull = isNull; - lodash.isNumber = isNumber; - lodash.isObject = isObject; - lodash.isObjectLike = isObjectLike; - lodash.isPlainObject = isPlainObject; - lodash.isRegExp = isRegExp; - lodash.isSafeInteger = isSafeInteger; - lodash.isSet = isSet; - lodash.isString = isString; - lodash.isSymbol = isSymbol; - lodash.isTypedArray = isTypedArray; - lodash.isUndefined = isUndefined; - lodash.isWeakMap = isWeakMap; - lodash.isWeakSet = isWeakSet; - lodash.join = join; - lodash.kebabCase = kebabCase; - lodash.last = last; - lodash.lastIndexOf = lastIndexOf; - lodash.lowerCase = lowerCase; - lodash.lowerFirst = lowerFirst; - lodash.lt = lt; - lodash.lte = lte; - lodash.max = max; - lodash.maxBy = maxBy; - lodash.mean = mean; - lodash.meanBy = meanBy; - lodash.min = min; - lodash.minBy = minBy; - lodash.stubArray = stubArray; - lodash.stubFalse = stubFalse; - lodash.stubObject = stubObject; - lodash.stubString = stubString; - lodash.stubTrue = stubTrue; - lodash.multiply = multiply; - lodash.nth = nth; - lodash.noConflict = noConflict; - lodash.noop = noop; - lodash.now = now; - lodash.pad = pad; - lodash.padEnd = padEnd; - lodash.padStart = padStart; - lodash.parseInt = parseInt2; - lodash.random = random; - lodash.reduce = reduce; - lodash.reduceRight = reduceRight; - lodash.repeat = repeat; - lodash.replace = replace; - lodash.result = result; - lodash.round = round; - lodash.runInContext = runInContext2; - lodash.sample = sample; - lodash.size = size; - lodash.snakeCase = snakeCase; - lodash.some = some; - lodash.sortedIndex = sortedIndex; - lodash.sortedIndexBy = sortedIndexBy; - lodash.sortedIndexOf = sortedIndexOf; - lodash.sortedLastIndex = sortedLastIndex; - lodash.sortedLastIndexBy = sortedLastIndexBy; - lodash.sortedLastIndexOf = sortedLastIndexOf; - lodash.startCase = startCase; - lodash.startsWith = startsWith; - lodash.subtract = subtract; - lodash.sum = sum; - lodash.sumBy = sumBy; - lodash.template = template; - lodash.times = times; - lodash.toFinite = toFinite; - lodash.toInteger = toInteger; - lodash.toLength = toLength; - lodash.toLower = toLower; - lodash.toNumber = toNumber; - lodash.toSafeInteger = toSafeInteger; - lodash.toString = toString; - lodash.toUpper = toUpper; - lodash.trim = trim; - lodash.trimEnd = trimEnd; - lodash.trimStart = trimStart; - lodash.truncate = truncate; - lodash.unescape = unescape; - lodash.uniqueId = uniqueId; - lodash.upperCase = upperCase; - lodash.upperFirst = upperFirst; - lodash.each = forEach; - lodash.eachRight = forEachRight; - lodash.first = head; - mixin(lodash, function() { - var source = {}; - baseForOwn(lodash, function(func, methodName) { - if (!hasOwnProperty.call(lodash.prototype, methodName)) { - source[methodName] = func; - } - }); - return source; - }(), { "chain": false }); - lodash.VERSION = VERSION; - arrayEach(["bind", "bindKey", "curry", "curryRight", "partial", "partialRight"], function(methodName) { - lodash[methodName].placeholder = lodash; - }); - arrayEach(["drop", "take"], function(methodName, index) { - LazyWrapper.prototype[methodName] = function(n) { - n = n === undefined2 ? 1 : nativeMax(toInteger(n), 0); - var result2 = this.__filtered__ && !index ? new LazyWrapper(this) : this.clone(); - if (result2.__filtered__) { - result2.__takeCount__ = nativeMin(n, result2.__takeCount__); - } else { - result2.__views__.push({ - "size": nativeMin(n, MAX_ARRAY_LENGTH), - "type": methodName + (result2.__dir__ < 0 ? "Right" : "") - }); - } - return result2; - }; - LazyWrapper.prototype[methodName + "Right"] = function(n) { - return this.reverse()[methodName](n).reverse(); - }; - }); - arrayEach(["filter", "map", "takeWhile"], function(methodName, index) { - var type = index + 1, isFilter = type == LAZY_FILTER_FLAG || type == LAZY_WHILE_FLAG; - LazyWrapper.prototype[methodName] = function(iteratee2) { - var result2 = this.clone(); - result2.__iteratees__.push({ - "iteratee": getIteratee(iteratee2, 3), - "type": type - }); - result2.__filtered__ = result2.__filtered__ || isFilter; - return result2; - }; - }); - arrayEach(["head", "last"], function(methodName, index) { - var takeName = "take" + (index ? "Right" : ""); - LazyWrapper.prototype[methodName] = function() { - return this[takeName](1).value()[0]; - }; - }); - arrayEach(["initial", "tail"], function(methodName, index) { - var dropName = "drop" + (index ? "" : "Right"); - LazyWrapper.prototype[methodName] = function() { - return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1); - }; - }); - LazyWrapper.prototype.compact = function() { - return this.filter(identity); - }; - LazyWrapper.prototype.find = function(predicate) { - return this.filter(predicate).head(); - }; - LazyWrapper.prototype.findLast = function(predicate) { - return this.reverse().find(predicate); - }; - LazyWrapper.prototype.invokeMap = baseRest(function(path, args) { - if (typeof path == "function") { - return new LazyWrapper(this); - } - return this.map(function(value) { - return baseInvoke(value, path, args); - }); - }); - LazyWrapper.prototype.reject = function(predicate) { - return this.filter(negate(getIteratee(predicate))); - }; - LazyWrapper.prototype.slice = function(start, end) { - start = toInteger(start); - var result2 = this; - if (result2.__filtered__ && (start > 0 || end < 0)) { - return new LazyWrapper(result2); - } - if (start < 0) { - result2 = result2.takeRight(-start); - } else if (start) { - result2 = result2.drop(start); - } - if (end !== undefined2) { - end = toInteger(end); - result2 = end < 0 ? result2.dropRight(-end) : result2.take(end - start); - } - return result2; - }; - LazyWrapper.prototype.takeRightWhile = function(predicate) { - return this.reverse().takeWhile(predicate).reverse(); - }; - LazyWrapper.prototype.toArray = function() { - return this.take(MAX_ARRAY_LENGTH); - }; - baseForOwn(LazyWrapper.prototype, function(func, methodName) { - var checkIteratee = /^(?:filter|find|map|reject)|While$/.test(methodName), isTaker = /^(?:head|last)$/.test(methodName), lodashFunc = lodash[isTaker ? "take" + (methodName == "last" ? "Right" : "") : methodName], retUnwrapped = isTaker || /^find/.test(methodName); - if (!lodashFunc) { - return; - } - lodash.prototype[methodName] = function() { - var value = this.__wrapped__, args = isTaker ? [1] : arguments, isLazy = value instanceof LazyWrapper, iteratee2 = args[0], useLazy = isLazy || isArray(value); - var interceptor = function(value2) { - var result3 = lodashFunc.apply(lodash, arrayPush([value2], args)); - return isTaker && chainAll ? result3[0] : result3; - }; - if (useLazy && checkIteratee && typeof iteratee2 == "function" && iteratee2.length != 1) { - isLazy = useLazy = false; - } - var chainAll = this.__chain__, isHybrid = !!this.__actions__.length, isUnwrapped = retUnwrapped && !chainAll, onlyLazy = isLazy && !isHybrid; - if (!retUnwrapped && useLazy) { - value = onlyLazy ? value : new LazyWrapper(this); - var result2 = func.apply(value, args); - result2.__actions__.push({ "func": thru, "args": [interceptor], "thisArg": undefined2 }); - return new LodashWrapper(result2, chainAll); - } - if (isUnwrapped && onlyLazy) { - return func.apply(this, args); - } - result2 = this.thru(interceptor); - return isUnwrapped ? isTaker ? result2.value()[0] : result2.value() : result2; - }; - }); - arrayEach(["pop", "push", "shift", "sort", "splice", "unshift"], function(methodName) { - var func = arrayProto[methodName], chainName = /^(?:push|sort|unshift)$/.test(methodName) ? "tap" : "thru", retUnwrapped = /^(?:pop|shift)$/.test(methodName); - lodash.prototype[methodName] = function() { - var args = arguments; - if (retUnwrapped && !this.__chain__) { - var value = this.value(); - return func.apply(isArray(value) ? value : [], args); - } - return this[chainName](function(value2) { - return func.apply(isArray(value2) ? value2 : [], args); - }); - }; - }); - baseForOwn(LazyWrapper.prototype, function(func, methodName) { - var lodashFunc = lodash[methodName]; - if (lodashFunc) { - var key = lodashFunc.name + ""; - if (!hasOwnProperty.call(realNames, key)) { - realNames[key] = []; - } - realNames[key].push({ "name": methodName, "func": lodashFunc }); - } - }); - realNames[createHybrid(undefined2, WRAP_BIND_KEY_FLAG).name] = [{ - "name": "wrapper", - "func": undefined2 - }]; - LazyWrapper.prototype.clone = lazyClone; - LazyWrapper.prototype.reverse = lazyReverse; - LazyWrapper.prototype.value = lazyValue; - lodash.prototype.at = wrapperAt; - lodash.prototype.chain = wrapperChain; - lodash.prototype.commit = wrapperCommit; - lodash.prototype.next = wrapperNext; - lodash.prototype.plant = wrapperPlant; - lodash.prototype.reverse = wrapperReverse; - lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue; - lodash.prototype.first = lodash.prototype.head; - if (symIterator) { - lodash.prototype[symIterator] = wrapperToIterator; - } - return lodash; - }; - var _ = runInContext(); - if (typeof define == "function" && typeof define.amd == "object" && define.amd) { - root._ = _; - define(function() { - return _; - }); - } else if (freeModule) { - (freeModule.exports = _)._ = _; - freeExports._ = _; - } else { - root._ = _; - } - }).call(exports); - } -}); - -// node_modules/@tgrosinger/md-advanced-tables/lib/calc/results.js -var require_results = __commonJS({ - "node_modules/@tgrosinger/md-advanced-tables/lib/calc/results.js"(exports) { - "use strict"; - var __importDefault = exports && exports.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.Value = exports.Arity = exports.FloatOrMilliseconds = void 0; - var decimal_js_1 = __importDefault(require_decimal()); - var lodash_1 = require_lodash(); - var datetimeRe = new RegExp("[1-9][0-9]{3}-[01][0-9]-[0-3][0-9][T ][0-2][0-9]:[0-5][0-9]"); - var durationRe = new RegExp("^-?[0-9]+:[0-5][0-9]"); - var FloatOrMilliseconds = (value) => { - const v = value.trim(); - if (v === "") { - return new decimal_js_1.default(0); - } - if (datetimeRe.test(v)) { - return new decimal_js_1.default(new Date(v).valueOf()); - } - if (durationRe.test(v)) { - const neg = v.charAt(0) == "-"; - const w = v.slice(neg ? 1 : 0); - const minutes = parseInt(w.slice(0, -3)) * 60 + parseInt(w.slice(-2)); - return new decimal_js_1.default((neg ? -1 : 1) * minutes * 6e4); - } - const decimalValue = new decimal_js_1.default(v); - return decimalValue.isNaN() ? new decimal_js_1.default(0) : decimalValue; - }; - exports.FloatOrMilliseconds = FloatOrMilliseconds; - var Arity = class { - constructor(rows, columns) { - this.isRow = () => this.rows > 1 && this.cols === 1; - this.isColumn = () => this.rows === 1 && this.cols > 1; - this.isCell = () => this.rows === 1 && this.cols === 1; - this.rows = rows; - this.cols = columns; - } - }; - exports.Arity = Arity; - var Value = class { - constructor(val) { - this.get = (row, column) => this.val[row][column]; - this.getAsNumber = (row, column) => { - const value = this.get(row, column); - return (0, exports.FloatOrMilliseconds)(value); - }; - this.getArity = () => { - const maxCols = this.val.reduce((max, currentRow) => Math.max(max, currentRow.length), 0); - return new Arity(this.val.length, maxCols); - }; - this.toString = () => { - if (this.getArity().isCell()) { - return this.get(0, 0); - } - return `[${(0, lodash_1.flatten)(this.val).map((val2) => val2.trim()).filter((val2) => val2 !== "").join(", ")}]`; - }; - this.val = val; - } - }; - exports.Value = Value; - } -}); - -// node_modules/@tgrosinger/md-advanced-tables/lib/calc/algebraic_operation.js -var require_algebraic_operation = __commonJS({ - "node_modules/@tgrosinger/md-advanced-tables/lib/calc/algebraic_operation.js"(exports) { - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.AlgebraicOperation = void 0; - var neverthrow_1 = require_neverthrow(); - var ast_utils_1 = require_ast_utils(); - var calc_1 = require_calc(); - var results_1 = require_results(); - var lodash_1 = require_lodash(); - var AlgebraicOperation = class { - constructor(ast, table) { - this.getValue = (table2, cell) => { - switch (this.operator) { - case "+": - return this.add(table2, cell); - case "-": - return this.subtract(table2, cell); - case "*": - return this.multiply(table2, cell); - case "/": - return this.divide(table2, cell); - default: - return (0, neverthrow_1.err)(Error("Invalid algbraic operator: " + this.operator)); - } - }; - this.withCellAndRange = (table2, cell, name, canHaveRightRange, fn) => { - const leftValue = this.leftSource.getValue(table2, cell); - if (leftValue.isErr()) { - return (0, neverthrow_1.err)(leftValue.error); - } - const rightValue = this.rightSource.getValue(table2, cell); - if (rightValue.isErr()) { - return (0, neverthrow_1.err)(rightValue.error); - } - const leftArity = leftValue.value.getArity(); - const rightArity = rightValue.value.getArity(); - if (!rightArity.isCell() && !leftArity.isCell()) { - return (0, neverthrow_1.err)(Error(`At least one operand in algebraic "${name}" must be a single cell.`)); - } - if (!rightArity.isCell() && !canHaveRightRange) { - return (0, neverthrow_1.err)(Error(`Right operand in algebraic "${name}" must be a single cell.`)); - } - if (rightArity.isCell()) { - const rightCellValue = rightValue.value.getAsNumber(0, 0); - const result2 = (0, lodash_1.map)(leftValue.value.val, (currentRow) => (0, lodash_1.map)(currentRow, (currentCell) => { - const leftCellValue2 = (0, results_1.FloatOrMilliseconds)(currentCell); - return fn(leftCellValue2, rightCellValue).toString(); - })); - return (0, neverthrow_1.ok)(new results_1.Value(result2)); - } - const leftCellValue = leftValue.value.getAsNumber(0, 0); - const result = (0, lodash_1.map)(rightValue.value.val, (currentRow) => (0, lodash_1.map)(currentRow, (currentCell) => { - const rightCellValue = (0, results_1.FloatOrMilliseconds)(currentCell); - return fn(leftCellValue, rightCellValue).toString(); - })); - return (0, neverthrow_1.ok)(new results_1.Value(result)); - }; - this.add = (table2, cell) => this.withCellAndRange(table2, cell, "add", true, (left, right) => left.plus(right)); - this.subtract = (table2, cell) => this.withCellAndRange(table2, cell, "subtract", true, (left, right) => left.minus(right)); - this.multiply = (table2, cell) => this.withCellAndRange(table2, cell, "multiply", true, (left, right) => left.times(right)); - this.divide = (table2, cell) => this.withCellAndRange(table2, cell, "divide", false, (left, right) => left.dividedBy(right)); - const typeErr = (0, ast_utils_1.checkType)(ast, "algebraic_operation"); - if (typeErr) { - throw typeErr; - } - const lengthError = (0, ast_utils_1.checkChildLength)(ast, 3); - if (lengthError) { - throw lengthError; - } - const childTypeErr = (0, ast_utils_1.checkType)(ast.children[1], "algebraic_operator"); - if (childTypeErr) { - throw childTypeErr; - } - this.operator = ast.children[1].text; - try { - this.leftSource = new calc_1.Source(ast.children[0], table); - this.rightSource = new calc_1.Source(ast.children[2], table); - } catch (error) { - throw error; - } - } - }; - exports.AlgebraicOperation = AlgebraicOperation; - } -}); - -// node_modules/@tgrosinger/md-advanced-tables/lib/calc/conditional_function.js -var require_conditional_function = __commonJS({ - "node_modules/@tgrosinger/md-advanced-tables/lib/calc/conditional_function.js"(exports) { - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.ConditionalFunctionCall = void 0; - var neverthrow_1 = require_neverthrow(); - var ast_utils_1 = require_ast_utils(); - var calc_1 = require_calc(); - var ConditionalFunctionCall = class { - constructor(ast, table) { - this.getValue = (table2, cell) => this.predicate.eval(table2, cell).andThen((predicateResult) => predicateResult ? this.leftSource.getValue(table2, cell) : this.rightSource.getValue(table2, cell)); - const typeError = (0, ast_utils_1.checkType)(ast, "conditional_function_call"); - if (typeError) { - throw typeError; - } - const lengthError = (0, ast_utils_1.checkChildLength)(ast, 3); - if (lengthError) { - throw lengthError; - } - try { - this.predicate = new Predicate(ast.children[0], table); - this.leftSource = new calc_1.Source(ast.children[1], table); - this.rightSource = new calc_1.Source(ast.children[2], table); - } catch (error) { - throw error; - } - } - }; - exports.ConditionalFunctionCall = ConditionalFunctionCall; - var Predicate = class { - constructor(ast, table) { - this.eval = (table2, cell) => { - const leftData = this.leftSource.getValue(table2, cell); - if (leftData.isErr()) { - return (0, neverthrow_1.err)(leftData.error); - } - const rightData = this.rightSource.getValue(table2, cell); - if (rightData.isErr()) { - return (0, neverthrow_1.err)(rightData.error); - } - const leftArity = leftData.value.getArity(); - const rightArity = rightData.value.getArity(); - if (!leftArity.isCell()) { - return (0, neverthrow_1.err)(Error("Can only use comparison operator on a single cell. Left side is not a cell.")); - } - if (!rightArity.isCell()) { - return (0, neverthrow_1.err)(Error("Can only use comparison operator on a single cell. Right side is not a cell.")); - } - const leftVal = leftData.value.getAsNumber(0, 0); - const rightVal = rightData.value.getAsNumber(0, 0); - switch (this.operator) { - case ">": - return (0, neverthrow_1.ok)(leftVal.greaterThan(rightVal)); - case ">=": - return (0, neverthrow_1.ok)(leftVal.greaterThanOrEqualTo(rightVal)); - case "<": - return (0, neverthrow_1.ok)(leftVal.lessThan(rightVal)); - case "<=": - return (0, neverthrow_1.ok)(leftVal.lessThanOrEqualTo(rightVal)); - case "==": - return (0, neverthrow_1.ok)(leftVal.equals(rightVal)); - case "!=": - return (0, neverthrow_1.ok)(!leftVal.equals(rightVal)); - default: - return (0, neverthrow_1.err)(Error("Invalid conditional operator: " + this.operator)); - } - }; - const typeError = (0, ast_utils_1.checkType)(ast, "predicate"); - if (typeError) { - throw typeError; - } - const lengthError = (0, ast_utils_1.checkChildLength)(ast, 3); - if (lengthError) { - throw lengthError; - } - const childTypeError = (0, ast_utils_1.checkType)(ast.children[1], "conditional_operator"); - if (childTypeError) { - throw childTypeError; - } - this.operator = ast.children[1].text; - try { - this.leftSource = new calc_1.Source(ast.children[0], table); - this.rightSource = new calc_1.Source(ast.children[2], table); - } catch (error) { - throw error; - } - } - }; - } -}); - -// node_modules/@tgrosinger/md-advanced-tables/lib/calc/constant.js -var require_constant = __commonJS({ - "node_modules/@tgrosinger/md-advanced-tables/lib/calc/constant.js"(exports) { - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.Constant = void 0; - var neverthrow_1 = require_neverthrow(); - var ast_utils_1 = require_ast_utils(); - var results_1 = require_results(); - var Constant = class { - constructor(ast, table) { - const typeErr = (0, ast_utils_1.checkType)(ast, "real", "float"); - if (typeErr) { - throw typeErr; - } - const multiplier = ast.text[0] === "-" ? -1 : 1; - if (ast.type === "real") { - this.value = multiplier * parseInt(ast.children[0].text); - } else { - this.value = multiplier * parseFloat(ast.children[0].text + "." + ast.children[1].text); - } - } - getValue(table, currentCell) { - return (0, neverthrow_1.ok)(new results_1.Value([[this.value.toString()]])); - } - }; - exports.Constant = Constant; - } -}); - -// node_modules/@tgrosinger/md-advanced-tables/lib/calc/column.js -var require_column = __commonJS({ - "node_modules/@tgrosinger/md-advanced-tables/lib/calc/column.js"(exports) { - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.AbsoluteColumn = exports.Column = exports.newColumn = void 0; - var neverthrow_1 = require_neverthrow(); - var ast_utils_1 = require_ast_utils(); - var results_1 = require_results(); - var newColumn = (ast, table) => { - try { - switch (ast.type) { - case "relative_column": - return (0, neverthrow_1.ok)(new RelativeColumn(ast, table)); - case "absolute_column": - return (0, neverthrow_1.ok)(new AbsoluteColumn(ast, table)); - default: - return (0, neverthrow_1.err)(new Error(`Formula element '${ast.text}' is a ${ast.type} but expected an relatve_column or absolute_column in this position.`)); - } - } catch (error) { - return (0, neverthrow_1.err)(error); - } - }; - exports.newColumn = newColumn; - var Column = class { - constructor() { - this.getValue = (table, currentCell) => { - var _a; - const val = ((_a = table.getCellAt(currentCell.row, this.getIndex(currentCell))) === null || _a === void 0 ? void 0 : _a.toText()) || ""; - return (0, neverthrow_1.ok)(new results_1.Value([[val]])); - }; - } - }; - exports.Column = Column; - var RelativeColumn = class extends Column { - constructor(ast, table) { - super(); - this.getIndex = (currentCell) => currentCell.column + this.offset; - this.getAbsoluteIndex = () => (0, neverthrow_1.err)(ast_utils_1.errRelativeReferenceIndex); - const typeError = (0, ast_utils_1.checkType)(ast, "relative_column"); - if (typeError) { - throw typeError; - } - const lengthError = (0, ast_utils_1.checkChildLength)(ast, 1); - if (lengthError) { - throw lengthError; - } - const multiplier = ast.text[1] === "-" ? -1 : 1; - this.offset = multiplier * parseInt(ast.children[0].text); - } - }; - var AbsoluteColumn = class extends Column { - constructor(ast, table) { - super(); - this.getIndex = (currentCell) => this.index; - this.getAbsoluteIndex = () => (0, neverthrow_1.ok)(this.index); - let index = -1; - let symbol = ""; - switch (ast.children.length) { - case 0: - symbol = ast.text[1]; - break; - case 1: - const typeError = (0, ast_utils_1.checkType)(ast.children[0], "int"); - if (typeError) { - throw (0, neverthrow_1.err)(typeError); - } - index = parseInt(ast.children[0].text); - break; - default: - throw new Error(`Formula element '${ast.text}' is a ${ast.type} but expected a 'absolute_column' in this position.`); - } - switch (symbol) { - case "": - break; - case "<": - index = 1; - break; - case ">": - index = table.getWidth(); - break; - default: - throw new Error(`Invalid column symbol '${symbol}'`); - } - if (index === 0) { - throw ast_utils_1.errIndex0; - } - this.index = index - 1; - } - }; - exports.AbsoluteColumn = AbsoluteColumn; - } -}); - -// node_modules/@tgrosinger/md-advanced-tables/lib/calc/row.js -var require_row = __commonJS({ - "node_modules/@tgrosinger/md-advanced-tables/lib/calc/row.js"(exports) { - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.AbsoluteRow = exports.Row = exports.newRow = void 0; - var neverthrow_1 = require_neverthrow(); - var ast_utils_1 = require_ast_utils(); - var results_1 = require_results(); - var newRow = (ast, table) => { - try { - switch (ast.type) { - case "relative_row": - return (0, neverthrow_1.ok)(new RelativeRow(ast, table)); - case "absolute_row": - return (0, neverthrow_1.ok)(new AbsoluteRow(ast, table)); - default: - return (0, neverthrow_1.err)(new Error(`Formula element '${ast.text}' is a ${ast.type} but expected an relatve_row or absolute_row in this position.`)); - } - } catch (error) { - return (0, neverthrow_1.err)(error); - } - }; - exports.newRow = newRow; - var Row = class { - constructor() { - this.getValue = (table, currentCell) => { - var _a; - const val = ((_a = table.getCellAt(this.getIndex(currentCell), currentCell.column)) === null || _a === void 0 ? void 0 : _a.toText()) || ""; - return (0, neverthrow_1.ok)(new results_1.Value([[val]])); - }; - } - }; - exports.Row = Row; - var RelativeRow = class extends Row { - constructor(ast, table) { - super(); - this.getIndex = (currentCell) => currentCell.row + this.offset; - this.getAbsoluteIndex = () => (0, neverthrow_1.err)(ast_utils_1.errRelativeReferenceIndex); - const typeError = (0, ast_utils_1.checkType)(ast, "relative_row"); - if (typeError) { - throw typeError; - } - const lengthError = (0, ast_utils_1.checkChildLength)(ast, 1); - if (lengthError) { - throw lengthError; - } - const multiplier = ast.text[1] === "-" ? -1 : 1; - this.offset = multiplier * parseInt(ast.children[0].text); - } - }; - var AbsoluteRow = class extends Row { - constructor(ast, table) { - super(); - this.getIndex = (currentCell) => this.index; - this.getAbsoluteIndex = () => (0, neverthrow_1.ok)(this.index); - let index = -1; - let symbol = ""; - switch (ast.children.length) { - case 0: - symbol = ast.text[1]; - break; - case 1: - const typeError = (0, ast_utils_1.checkType)(ast.children[0], "int"); - if (typeError) { - throw (0, neverthrow_1.err)(typeError); - } - index = parseInt(ast.children[0].text); - break; - default: - throw new Error(`Formula element '${ast.text}' is a ${ast.type} but expected a 'absolute_row' in this position.`); - } - switch (symbol) { - case "": - break; - case "<": - index = 1; - break; - case ">": - index = table.getHeight() - 1; - break; - case "I": - index = 2; - break; - default: - throw new Error(`Invalid row symbol '${symbol}'`); - } - if (index === 0) { - throw ast_utils_1.errIndex0; - } - if (index === 1) { - this.index = 0; - } else { - this.index = index; - } - } - }; - exports.AbsoluteRow = AbsoluteRow; - } -}); - -// node_modules/@tgrosinger/md-advanced-tables/lib/calc/reference.js -var require_reference = __commonJS({ - "node_modules/@tgrosinger/md-advanced-tables/lib/calc/reference.js"(exports) { - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.Reference = void 0; - var neverthrow_1 = require_neverthrow(); - var ast_utils_1 = require_ast_utils(); - var column_1 = require_column(); - var results_1 = require_results(); - var row_1 = require_row(); - var Reference = class { - constructor(ast, table) { - this.getValue = (table2, currentCell) => { - var _a; - const cell = { - row: this.row ? this.row.getIndex(currentCell) : currentCell.row, - column: this.column ? this.column.getIndex(currentCell) : currentCell.column - }; - const val = ((_a = table2.getCellAt(cell.row, cell.column)) === null || _a === void 0 ? void 0 : _a.toText()) || ""; - return (0, neverthrow_1.ok)(new results_1.Value([[val]])); - }; - const typeErr = (0, ast_utils_1.checkType)(ast, "source_reference", "absolute_reference", "relative_reference"); - if (typeErr) { - throw typeErr; - } - for (let i = 0; i < ast.children.length; i++) { - const child = ast.children[i]; - switch (child.type) { - case "relative_row": - case "absolute_row": - if (this.row !== void 0) { - throw Error("Reference may only have at most 1 row, more than 1 provided"); - } - const createdRow = (0, row_1.newRow)(child, table); - if (createdRow.isErr()) { - if (createdRow.error === ast_utils_1.errIndex0) { - break; - } - throw createdRow.error; - } - this.row = createdRow.value; - break; - case "relative_column": - case "absolute_column": - if (this.column !== void 0) { - throw Error("Reference may only have at most 1 column, more than 1 provided"); - } - const createdCol = (0, column_1.newColumn)(child, table); - if (createdCol.isErr()) { - if (createdCol.error === ast_utils_1.errIndex0) { - break; - } - throw createdCol.error; - } - this.column = createdCol.value; - break; - } - } - } - }; - exports.Reference = Reference; - } -}); - -// node_modules/@tgrosinger/md-advanced-tables/lib/calc/range.js -var require_range2 = __commonJS({ - "node_modules/@tgrosinger/md-advanced-tables/lib/calc/range.js"(exports) { - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.Range = void 0; - var neverthrow_1 = require_neverthrow(); - var ast_utils_1 = require_ast_utils(); - var reference_1 = require_reference(); - var results_1 = require_results(); - var lodash_1 = require_lodash(); - var Range2 = class { - constructor(ast, table) { - this.getValue = (table2, currentCell) => { - const startColumn = this.startColumn ? this.startColumn.getIndex(currentCell) : currentCell.column; - const endColumn = this.endColumn ? this.endColumn.getIndex(currentCell) : startColumn; - const startRow = this.startRow ? this.startRow.getIndex(currentCell) : currentCell.row; - const endRow = this.endRow ? this.endRow.getIndex(currentCell) : currentCell.row; - return (0, neverthrow_1.ok)(new results_1.Value((0, lodash_1.map)((0, lodash_1.range)(startRow, endRow + 1), (row) => (0, lodash_1.map)((0, lodash_1.range)(startColumn, endColumn + 1), (col) => { - var _a; - return ((_a = table2.getCellAt(row, col)) === null || _a === void 0 ? void 0 : _a.toText()) || ""; - })))); - }; - this.asCells = () => { - if (!this.startColumn || !this.startRow || !this.endRow) { - return (0, neverthrow_1.err)(new Error("A range used as a desintation must define rows and cells")); - } - let endColumn = this.endColumn; - if (!endColumn) { - endColumn = this.startColumn; - } - const startRowIndex = this.startRow.getAbsoluteIndex(); - const endRowIndex = this.endRow.getAbsoluteIndex(); - const startColumnIndex = this.startColumn.getAbsoluteIndex(); - const endColumnIndex = endColumn.getAbsoluteIndex(); - if (startRowIndex.isErr() || endRowIndex.isErr() || startColumnIndex.isErr() || endColumnIndex.isErr()) { - return (0, neverthrow_1.err)(new Error("A relative range can not be used in a formula destination")); - } - const minRow = Math.min(startRowIndex.value, endRowIndex.value); - const maxRow = Math.max(startRowIndex.value, endRowIndex.value); - const minColumn = Math.min(startColumnIndex.value, endColumnIndex.value); - const maxColumn = Math.max(startColumnIndex.value, endColumnIndex.value); - return (0, neverthrow_1.ok)((0, lodash_1.flatMap)((0, lodash_1.range)(minRow, maxRow + 1), (rowNum) => (0, lodash_1.range)(minColumn, maxColumn + 1).map((colNum) => ({ row: rowNum, column: colNum })))); - }; - let typeErr = (0, ast_utils_1.checkType)(ast, "range"); - if (typeErr) { - throw typeErr; - } - let lengthError = (0, ast_utils_1.checkChildLength)(ast, 2); - if (lengthError) { - throw lengthError; - } - const startChild = ast.children[0]; - const endChild = ast.children[1]; - typeErr = (0, ast_utils_1.checkType)(startChild, "source_reference"); - if (typeErr) { - throw typeErr; - } - typeErr = (0, ast_utils_1.checkType)(endChild, "source_reference"); - if (typeErr) { - throw typeErr; - } - lengthError = (0, ast_utils_1.checkChildLength)(startChild, 1); - if (lengthError) { - throw lengthError; - } - lengthError = (0, ast_utils_1.checkChildLength)(endChild, 1); - if (lengthError) { - throw lengthError; - } - const start = new reference_1.Reference(startChild.children[0], table); - const end = new reference_1.Reference(endChild.children[0], table); - if (start.row && !end.row || end.row && !start.row) { - throw new Error("Range must use references of the same kind"); - } - if (!start.row && !start.column) { - console.log(start); - throw new Error("Range must have a row or a column defined"); - } - if (start.row) { - this.startRow = start.row; - } - if (start.column) { - this.startColumn = start.column; - } - if (end.row) { - this.endRow = end.row; - } - if (end.column) { - this.endColumn = end.column; - } else { - this.endColumn = start.column; - } - } - }; - exports.Range = Range2; - } -}); - -// node_modules/@tgrosinger/md-advanced-tables/lib/calc/destination.js -var require_destination = __commonJS({ - "node_modules/@tgrosinger/md-advanced-tables/lib/calc/destination.js"(exports) { - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.RangeDestination = exports.CellDestination = exports.ColumnDestination = exports.RowDestination = exports.newDestination = void 0; - var neverthrow_1 = require_neverthrow(); - var ast_utils_1 = require_ast_utils(); - var column_1 = require_column(); - var range_1 = require_range2(); - var row_1 = require_row(); - var lodash_1 = require_lodash(); - var newDestination = (ast, table, formatter) => { - const typeErr = (0, ast_utils_1.checkType)(ast, "destination"); - if (typeErr) { - return (0, neverthrow_1.err)(typeErr); - } - const lengthError = (0, ast_utils_1.checkChildLength)(ast, 1); - if (lengthError) { - return (0, neverthrow_1.err)(lengthError); - } - const child = ast.children[0]; - if (child.type === "range") { - return (0, neverthrow_1.ok)(new RangeDestination(child, table, formatter)); - } - try { - switch (child.children.length) { - case 2: - return (0, neverthrow_1.ok)(new CellDestination(child, table, formatter)); - case 1: - const innerChild = child.children[0]; - if (innerChild.type === "absolute_row") { - return (0, neverthrow_1.ok)(new RowDestination(child, table, formatter)); - } else if (innerChild.type === "absolute_column") { - return (0, neverthrow_1.ok)(new ColumnDestination(child, table, formatter)); - } - default: - return (0, neverthrow_1.err)(new Error("Unexpected destination type " + child.type)); - } - } catch (error) { - if (error === ast_utils_1.errIndex0) { - return (0, neverthrow_1.err)(new Error("Index 0 may not be used in a destination")); - } - return (0, neverthrow_1.err)(error); - } - }; - exports.newDestination = newDestination; - var RowDestination = class { - constructor(ast, table, formatter) { - this.merge = (source, table2) => { - const cells = (0, lodash_1.range)(0, table2.getWidth()).map((columnNum) => ({ row: this.row.index, column: columnNum })); - return mergeForCells(source, table2, cells, this.formatter); - }; - this.formatter = formatter; - const typeErr = (0, ast_utils_1.checkType)(ast, "absolute_reference"); - if (typeErr) { - throw typeErr; - } - const lengthError = (0, ast_utils_1.checkChildLength)(ast, 1); - if (lengthError) { - throw lengthError; - } - const child = ast.children[0]; - try { - this.row = new row_1.AbsoluteRow(child, table); - } catch (error) { - throw error; - } - } - }; - exports.RowDestination = RowDestination; - var ColumnDestination = class { - constructor(ast, table, formatter) { - this.merge = (source, table2) => { - const cells = (0, lodash_1.range)(2, table2.getHeight()).map((rowNum) => ({ row: rowNum, column: this.column.index })); - return mergeForCells(source, table2, cells, this.formatter); - }; - this.formatter = formatter; - const typeErr = (0, ast_utils_1.checkType)(ast, "absolute_reference"); - if (typeErr) { - throw typeErr; - } - const lengthError = (0, ast_utils_1.checkChildLength)(ast, 1); - if (lengthError) { - throw lengthError; - } - const child = ast.children[0]; - try { - this.column = new column_1.AbsoluteColumn(child, table); - } catch (error) { - throw error; - } - } - }; - exports.ColumnDestination = ColumnDestination; - var CellDestination = class { - constructor(ast, table, formatter) { - this.merge = (source, table2) => { - const cell = { row: this.row.index, column: this.column.index }; - return mergeForCells(source, table2, [cell], this.formatter); - }; - this.formatter = formatter; - const typeErr = (0, ast_utils_1.checkType)(ast, "absolute_reference"); - if (typeErr) { - throw typeErr; - } - const lengthError = (0, ast_utils_1.checkChildLength)(ast, 2); - if (lengthError) { - throw lengthError; - } - const rowChild = ast.children[0]; - const colChild = ast.children[1]; - try { - this.row = new row_1.AbsoluteRow(rowChild, table); - this.column = new column_1.AbsoluteColumn(colChild, table); - } catch (error) { - throw error; - } - } - }; - exports.CellDestination = CellDestination; - var RangeDestination = class { - constructor(ast, table, formatter) { - this.merge = (source, table2) => this.range.asCells().andThen((cells) => mergeForCells(source, table2, cells, this.formatter)); - this.formatter = formatter; - const typeErr = (0, ast_utils_1.checkType)(ast, "range"); - if (typeErr) { - throw typeErr; - } - const lengthError = (0, ast_utils_1.checkChildLength)(ast, 2); - if (lengthError) { - throw lengthError; - } - ast.children.forEach((child) => { - let childTypeErr = (0, ast_utils_1.checkType)(child, "source_reference"); - if (childTypeErr) { - throw childTypeErr; - } - const childLengthError = (0, ast_utils_1.checkChildLength)(child, 1); - if (childLengthError) { - throw childLengthError; - } - childTypeErr = (0, ast_utils_1.checkType)(child.children[0], "absolute_reference"); - if (childTypeErr) { - throw childTypeErr; - } - }); - this.range = new range_1.Range(ast, table); - } - }; - exports.RangeDestination = RangeDestination; - var mergeForCells = (source, table, cells, formatter) => cells.reduce((currentTable, currentCell) => currentTable.andThen((t) => source.getValue(t, currentCell).andThen((val) => (0, neverthrow_1.ok)(val.toString())).andThen((val) => (0, neverthrow_1.ok)(val.trim() === "" ? "0" : val)).andThen((val) => (0, neverthrow_1.ok)(t.setCellAt(currentCell.row, currentCell.column, formatter.format(val))))), (0, neverthrow_1.ok)(table)); - } -}); - -// node_modules/@tgrosinger/md-advanced-tables/lib/calc/display_directive.js -var require_display_directive = __commonJS({ - "node_modules/@tgrosinger/md-advanced-tables/lib/calc/display_directive.js"(exports) { - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.DisplayDirective = exports.DefaultFormatter = void 0; - var ast_utils_1 = require_ast_utils(); - var DefaultFormatter = class { - constructor() { - this.format = (num) => { - if (typeof num === "string") { - return num; - } - return num.toString(); - }; - } - }; - exports.DefaultFormatter = DefaultFormatter; - var DisplayDirective = class { - constructor(ast) { - this.format = (num) => { - const parsed = typeof num === "string" ? parseFloat(num) : num; - if (this.displayAsDatetime) { - const date = new Date(parsed); - const pad = (v) => `0${v}`.slice(-2); - const y = date.getFullYear(); - const mo = pad(date.getMonth() + 1); - const d = pad(date.getDate()); - const h = pad(date.getHours()); - const min = pad(date.getMinutes()); - return `${y}-${mo}-${d} ${h}:${min}`; - } - if (this.displayAsHourMinute) { - let sign = parsed < 0 ? "-" : ""; - const minutes = Math.floor(Math.abs(parsed) / 6e4); - const pad = (v) => `0${v}`.slice(-2); - const h = pad(Math.floor(minutes / 60)); - const m = pad(minutes % 60); - return `${sign}${h}:${m}`; - } - return parsed.toFixed(this.decimalLength); - }; - let typeError = (0, ast_utils_1.checkType)(ast, "display_directive"); - if (typeError) { - throw typeError; - } - let lengthError = (0, ast_utils_1.checkChildLength)(ast, 1); - if (lengthError) { - throw lengthError; - } - const displayDirectiveOption = ast.children[0]; - typeError = (0, ast_utils_1.checkType)(displayDirectiveOption, "display_directive_option"); - if (typeError) { - throw typeError; - } - lengthError = (0, ast_utils_1.checkChildLength)(displayDirectiveOption, 1); - if (lengthError) { - throw lengthError; - } - const formattingDirective = displayDirectiveOption.children[0]; - typeError = (0, ast_utils_1.checkType)(formattingDirective, "formatting_directive", "datetime_directive", "hourminute_directive"); - if (typeError) { - throw typeError; - } - this.displayAsDatetime = formattingDirective.type === "datetime_directive"; - this.displayAsHourMinute = formattingDirective.type === "hourminute_directive"; - if (this.displayAsDatetime || this.displayAsHourMinute) { - this.decimalLength = -1; - return; - } - lengthError = (0, ast_utils_1.checkChildLength)(formattingDirective, 1); - if (lengthError) { - throw lengthError; - } - const formattingDirectiveLength = formattingDirective.children[0]; - typeError = (0, ast_utils_1.checkType)(formattingDirectiveLength, "int"); - if (typeError) { - throw typeError; - } - this.decimalLength = parseInt(formattingDirectiveLength.text); - } - }; - exports.DisplayDirective = DisplayDirective; - } -}); - -// node_modules/@tgrosinger/md-advanced-tables/lib/calc/single_param_function.js -var require_single_param_function = __commonJS({ - "node_modules/@tgrosinger/md-advanced-tables/lib/calc/single_param_function.js"(exports) { - "use strict"; - var __importDefault = exports && exports.__importDefault || function(mod) { - return mod && mod.__esModule ? mod : { "default": mod }; - }; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.SingleParamFunctionCall = void 0; - var neverthrow_1 = require_neverthrow(); - var ast_utils_1 = require_ast_utils(); - var calc_1 = require_calc(); - var results_1 = require_results(); - var decimal_js_1 = __importDefault(require_decimal()); - var SingleParamFunctionCall = class { - constructor(ast, table) { - this.getValue = (table2, cell) => this.param.getValue(table2, cell).andThen((sourceData) => ( - // The operation functions do not throw errors because data arity has - // already been validated. - (0, neverthrow_1.ok)(this.op(sourceData)) - )); - const typeError = (0, ast_utils_1.checkType)(ast, "single_param_function_call"); - if (typeError) { - throw typeError; - } - const lengthError = (0, ast_utils_1.checkChildLength)(ast, 2); - if (lengthError) { - throw lengthError; - } - const childTypeError = (0, ast_utils_1.checkType)(ast.children[0], "single_param_function"); - if (childTypeError) { - throw childTypeError; - } - const functionName = ast.children[0].text; - switch (functionName) { - case "sum": - this.op = sum; - break; - case "mean": - this.op = mean; - break; - default: - throw Error("Unknown single param function call: " + functionName); - } - this.param = new calc_1.Source(ast.children[1], table); - } - }; - exports.SingleParamFunctionCall = SingleParamFunctionCall; - var sum = (value) => { - const total = value.val.reduce((runningTotal, currentRow) => currentRow.reduce((rowTotal, currentCell) => { - const currentCellValue = (0, results_1.FloatOrMilliseconds)(currentCell); - return currentCellValue.add(rowTotal); - }, runningTotal), new decimal_js_1.default(0)); - return new results_1.Value([[total.toString()]]); - }; - var mean = (value) => { - const { total, count } = value.val.reduce(({ total: runningTotal1, count: currentCount1 }, currentRow) => currentRow.reduce(({ total: runningTotal2, count: currentCount2 }, currentCell) => ({ - total: runningTotal2 + +currentCell, - count: currentCount2 + 1 - }), { total: runningTotal1, count: currentCount1 }), { total: 0, count: 0 }); - return new results_1.Value([[(total / count).toString()]]); - }; - } -}); - -// node_modules/ebnf/dist/TokenError.js -var require_TokenError = __commonJS({ - "node_modules/ebnf/dist/TokenError.js"(exports) { - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.TokenError = void 0; - var TokenError = class extends Error { - constructor(message, token) { - super(message); - this.message = message; - this.token = token; - if (token && token.errors) - token.errors.push(this); - else - throw this; - } - inspect() { - return "SyntaxError: " + this.message; - } - }; - exports.TokenError = TokenError; - } -}); - -// node_modules/ebnf/dist/Parser.js -var require_Parser = __commonJS({ - "node_modules/ebnf/dist/Parser.js"(exports) { - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.Parser = exports.findRuleByName = exports.parseRuleName = exports.escapeRegExp = exports.readToken = void 0; - var UPPER_SNAKE_RE = /^[A-Z0-9_]+$/; - var decorationRE = /(\?|\+|\*)$/; - var preDecorationRE = /^(@|&|!)/; - var WS_RULE = "WS"; - var TokenError_1 = require_TokenError(); - function readToken(txt, expr) { - let result = expr.exec(txt); - if (result && result.index == 0) { - if (result[0].length == 0 && expr.source.length > 0) - return null; - return { - type: null, - text: result[0], - rest: txt.substr(result[0].length), - start: 0, - end: result[0].length - 1, - fullText: result[0], - errors: [], - children: [], - parent: null - }; - } - return null; - } - exports.readToken = readToken; - function escapeRegExp(str) { - return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); - } - exports.escapeRegExp = escapeRegExp; - function fixRest(token) { - token.rest = ""; - token.children && token.children.forEach((c) => fixRest(c)); - } - function fixPositions(token, start) { - token.start += start; - token.end += start; - token.children && token.children.forEach((c) => fixPositions(c, token.start)); - } - function agregateErrors(errors, token) { - if (token.errors && token.errors.length) - token.errors.forEach((err) => errors.push(err)); - token.children && token.children.forEach((tok) => agregateErrors(errors, tok)); - } - function parseRuleName(name) { - let postDecoration = decorationRE.exec(name); - let preDecoration = preDecorationRE.exec(name); - let postDecorationText = postDecoration && postDecoration[0] || ""; - let preDecorationText = preDecoration && preDecoration[0] || ""; - let out = { - raw: name, - name: name.replace(decorationRE, "").replace(preDecorationRE, ""), - isOptional: postDecorationText == "?" || postDecorationText == "*", - allowRepetition: postDecorationText == "+" || postDecorationText == "*", - atLeastOne: postDecorationText == "+", - lookupPositive: preDecorationText == "&", - lookupNegative: preDecorationText == "!", - pinned: preDecorationText == "@", - lookup: false, - isLiteral: false - }; - out.isLiteral = out.name[0] == "'" || out.name[0] == '"'; - out.lookup = out.lookupNegative || out.lookupPositive; - return out; - } - exports.parseRuleName = parseRuleName; - function findRuleByName(name, parser) { - let parsed = parseRuleName(name); - return parser.cachedRules[parsed.name] || null; - } - exports.findRuleByName = findRuleByName; - function stripRules(token, re) { - if (token.children) { - let localRules = token.children.filter((x) => x.type && re.test(x.type)); - for (let i = 0; i < localRules.length; i++) { - let indexOnChildren = token.children.indexOf(localRules[i]); - if (indexOnChildren != -1) { - token.children.splice(indexOnChildren, 1); - } - } - token.children.forEach((c) => stripRules(c, re)); - } - } - var ignoreMissingRules = ["EOF"]; - var Parser = class { - constructor(grammarRules, options) { - this.grammarRules = grammarRules; - this.options = options; - this.cachedRules = {}; - this.debug = options ? options.debug === true : false; - let errors = []; - let neededRules = []; - grammarRules.forEach((rule) => { - let parsedName = parseRuleName(rule.name); - if (parsedName.name in this.cachedRules) { - errors.push("Duplicated rule " + parsedName.name); - return; - } else { - this.cachedRules[parsedName.name] = rule; - } - if (!rule.bnf || !rule.bnf.length) { - let error = "Missing rule content, rule: " + rule.name; - if (errors.indexOf(error) == -1) - errors.push(error); - } else { - rule.bnf.forEach((options2) => { - if (typeof options2[0] === "string") { - let parsed = parseRuleName(options2[0]); - if (parsed.name == rule.name) { - let error = "Left recursion is not allowed, rule: " + rule.name; - if (errors.indexOf(error) == -1) - errors.push(error); - } - } - options2.forEach((option) => { - if (typeof option == "string") { - let name = parseRuleName(option); - if (!name.isLiteral && neededRules.indexOf(name.name) == -1 && ignoreMissingRules.indexOf(name.name) == -1) - neededRules.push(name.name); - } - }); - }); - } - if (WS_RULE == rule.name) - rule.implicitWs = false; - if (rule.implicitWs) { - if (neededRules.indexOf(WS_RULE) == -1) - neededRules.push(WS_RULE); - } - if (rule.recover) { - if (neededRules.indexOf(rule.recover) == -1) - neededRules.push(rule.recover); - } - }); - neededRules.forEach((ruleName) => { - if (!(ruleName in this.cachedRules)) { - errors.push("Missing rule " + ruleName); - } - }); - if (errors.length) - throw new Error(errors.join("\n")); - } - getAST(txt, target) { - if (!target) { - target = this.grammarRules.filter((x) => !x.fragment && x.name.indexOf("%") != 0)[0].name; - } - let result = this.parse(txt, target); - if (result) { - agregateErrors(result.errors, result); - fixPositions(result, 0); - stripRules(result, /^%/); - if (!this.options || !this.options.keepUpperRules) - stripRules(result, UPPER_SNAKE_RE); - let rest = result.rest; - if (rest) { - new TokenError_1.TokenError("Unexpected end of input: \n" + rest, result); - } - fixRest(result); - result.rest = rest; - } - return result; - } - emitSource() { - return "CANNOT EMIT SOURCE FROM BASE Parser"; - } - parse(txt, target, recursion = 0) { - let out = null; - let type = parseRuleName(target); - let expr; - let printable = this.debug && /*!isLiteral &*/ - !UPPER_SNAKE_RE.test(type.name); - printable && console.log(new Array(recursion).join("\u2502 ") + "Trying to get " + target + " from " + JSON.stringify(txt.split("\n")[0])); - let realType = type.name; - let targetLex = findRuleByName(type.name, this); - if (type.name == "EOF") { - if (txt.length) { - return null; - } else if (txt.length == 0) { - return { - type: "EOF", - text: "", - rest: "", - start: 0, - end: 0, - fullText: "", - errors: [], - children: [], - parent: null - }; - } - } - try { - if (!targetLex && type.isLiteral) { - let src = type.name.trim(); - if (src.startsWith('"')) { - src = JSON.parse(src); - } else if (src.startsWith("'")) { - src = src.replace(/^'(.+)'$/, "$1").replace(/\\'/g, "'"); - } - if (src === "") { - return { - type: "%%EMPTY%%", - text: "", - rest: txt, - start: 0, - end: 0, - fullText: "", - errors: [], - children: [], - parent: null - }; - } - expr = new RegExp(escapeRegExp(src)); - realType = null; - } - } catch (e) { - if (e instanceof ReferenceError) { - console.error(e); - } - return null; - } - if (expr) { - let result = readToken(txt, expr); - if (result) { - result.type = realType; - return result; - } - } else { - let options = targetLex.bnf; - if (options instanceof Array) { - options.forEach((phases) => { - if (out) - return; - let pinned = null; - let tmp = { - type: type.name, - text: "", - children: [], - end: 0, - errors: [], - fullText: "", - parent: null, - start: 0, - rest: txt - }; - if (targetLex.fragment) - tmp.fragment = true; - let tmpTxt = txt; - let position = 0; - let allOptional = phases.length > 0; - let foundSomething = false; - for (let i = 0; i < phases.length; i++) { - if (typeof phases[i] == "string") { - let localTarget = parseRuleName(phases[i]); - allOptional = allOptional && localTarget.isOptional; - let got; - let foundAtLeastOne = false; - do { - got = null; - if (targetLex.implicitWs) { - got = this.parse(tmpTxt, localTarget.name, recursion + 1); - if (!got) { - let WS; - do { - WS = this.parse(tmpTxt, WS_RULE, recursion + 1); - if (WS) { - tmp.text = tmp.text + WS.text; - tmp.end = tmp.text.length; - WS.parent = tmp; - tmp.children.push(WS); - tmpTxt = tmpTxt.substr(WS.text.length); - position += WS.text.length; - } else { - break; - } - } while (WS && WS.text.length); - } - } - got = got || this.parse(tmpTxt, localTarget.name, recursion + 1); - if (localTarget.lookupNegative) { - if (got) - return; - break; - } - if (localTarget.lookupPositive) { - if (!got) - return; - } - if (!got) { - if (localTarget.isOptional) - break; - if (localTarget.atLeastOne && foundAtLeastOne) - break; - } - if (got && targetLex.pinned == i + 1) { - pinned = got; - printable && console.log(new Array(recursion + 1).join("\u2502 ") + "\u2514\u2500 " + got.type + " PINNED"); - } - if (!got) - got = this.parseRecovery(targetLex, tmpTxt, recursion + 1); - if (!got) { - if (pinned) { - out = tmp; - got = { - type: "SyntaxError", - text: tmpTxt, - children: [], - end: tmpTxt.length, - errors: [], - fullText: "", - parent: null, - start: 0, - rest: "" - }; - if (tmpTxt.length) { - new TokenError_1.TokenError(`Unexpected end of input. Expecting ${localTarget.name} Got: ${tmpTxt}`, got); - } else { - new TokenError_1.TokenError(`Unexpected end of input. Missing ${localTarget.name}`, got); - } - printable && console.log(new Array(recursion + 1).join("\u2502 ") + "\u2514\u2500 " + got.type + " " + JSON.stringify(got.text)); - } else { - return; - } - } - foundAtLeastOne = true; - foundSomething = true; - if (got.type == "%%EMPTY%%") { - break; - } - got.start += position; - got.end += position; - if (!localTarget.lookupPositive && got.type) { - if (got.fragment) { - got.children && got.children.forEach((x) => { - x.start += position; - x.end += position; - x.parent = tmp; - tmp.children.push(x); - }); - } else { - got.parent = tmp; - tmp.children.push(got); - } - } - if (localTarget.lookup) - got.lookup = true; - printable && console.log(new Array(recursion + 1).join("\u2502 ") + "\u2514\u2500 " + got.type + " " + JSON.stringify(got.text)); - if (!localTarget.lookup && !got.lookup) { - tmp.text = tmp.text + got.text; - tmp.end = tmp.text.length; - tmpTxt = tmpTxt.substr(got.text.length); - position += got.text.length; - } - tmp.rest = tmpTxt; - } while (got && localTarget.allowRepetition && tmpTxt.length && !got.lookup); - } else { - let got = readToken(tmpTxt, phases[i]); - if (!got) { - return; - } - printable && console.log(new Array(recursion + 1).join("\u2502 ") + "\u2514> " + JSON.stringify(got.text) + phases[i].source); - foundSomething = true; - got.start += position; - got.end += position; - tmp.text = tmp.text + got.text; - tmp.end = tmp.text.length; - tmpTxt = tmpTxt.substr(got.text.length); - position += got.text.length; - tmp.rest = tmpTxt; - } - } - if (foundSomething) { - out = tmp; - printable && console.log(new Array(recursion).join("\u2502 ") + "\u251C<\u2500\u2534< PUSHING " + out.type + " " + JSON.stringify(out.text)); - } - }); - } - if (out && targetLex.simplifyWhenOneChildren && out.children.length == 1) { - out = out.children[0]; - } - } - if (!out) { - printable && console.log(target + " NOT RESOLVED FROM " + txt); - } - return out; - } - parseRecovery(recoverableToken, tmpTxt, recursion) { - if (recoverableToken.recover && tmpTxt.length) { - let printable = this.debug; - printable && console.log(new Array(recursion + 1).join("\u2502 ") + "Trying to recover until token " + recoverableToken.recover + " from " + JSON.stringify(tmpTxt.split("\n")[0] + tmpTxt.split("\n")[1])); - let tmp = { - type: "SyntaxError", - text: "", - children: [], - end: 0, - errors: [], - fullText: "", - parent: null, - start: 0, - rest: "" - }; - let got; - do { - got = this.parse(tmpTxt, recoverableToken.recover, recursion + 1); - if (got) { - new TokenError_1.TokenError('Unexpected input: "' + tmp.text + `" Expecting: ${recoverableToken.name}`, tmp); - break; - } else { - tmp.text = tmp.text + tmpTxt[0]; - tmp.end = tmp.text.length; - tmpTxt = tmpTxt.substr(1); - } - } while (!got && tmpTxt.length > 0); - if (tmp.text.length > 0 && got) { - printable && console.log(new Array(recursion + 1).join("\u2502 ") + "Recovered text: " + JSON.stringify(tmp.text)); - return tmp; - } - } - return null; - } - }; - exports.Parser = Parser; - exports.default = Parser; - } -}); - -// node_modules/ebnf/dist/SemanticHelpers.js -var require_SemanticHelpers = __commonJS({ - "node_modules/ebnf/dist/SemanticHelpers.js"(exports) { - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.findChildrenByType = void 0; - function findChildrenByType(token, type) { - return token.children ? token.children.filter((x) => x.type == type) : []; - } - exports.findChildrenByType = findChildrenByType; - } -}); - -// node_modules/ebnf/dist/Grammars/BNF.js -var require_BNF = __commonJS({ - "node_modules/ebnf/dist/Grammars/BNF.js"(exports) { - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - var SemanticHelpers_1 = require_SemanticHelpers(); - var Parser_1 = require_Parser(); - var BNF; - (function(BNF2) { - BNF2.RULES = [ - { - name: "syntax", - bnf: [["RULE_EOL*", "rule+"]] - }, - { - name: "rule", - bnf: [ - [ - '" "*', - '"<"', - "rule-name", - '">"', - '" "*', - '"::="', - "firstExpression", - "otherExpression*", - '" "*', - "RULE_EOL+", - '" "*' - ] - ] - }, - { - name: "firstExpression", - bnf: [['" "*', "list"]] - }, - { - name: "otherExpression", - bnf: [['" "*', '"|"', '" "*', "list"]] - }, - { - name: "RULE_EOL", - bnf: [['"\\r"'], ['"\\n"']] - }, - { - name: "list", - bnf: [["term", '" "*', "list"], ["term"]] - }, - { - name: "term", - bnf: [["literal"], ['"<"', "rule-name", '">"']] - }, - { - name: "literal", - bnf: [[`'"'`, "RULE_CHARACTER1*", `'"'`], [`"'"`, "RULE_CHARACTER2*", `"'"`]] - }, - { - name: "RULE_CHARACTER", - bnf: [['" "'], ["RULE_LETTER"], ["RULE_DIGIT"], ["RULE_SYMBOL"]] - }, - { - name: "RULE_LETTER", - bnf: [ - ['"A"'], - ['"B"'], - ['"C"'], - ['"D"'], - ['"E"'], - ['"F"'], - ['"G"'], - ['"H"'], - ['"I"'], - ['"J"'], - ['"K"'], - ['"L"'], - ['"M"'], - ['"N"'], - ['"O"'], - ['"P"'], - ['"Q"'], - ['"R"'], - ['"S"'], - ['"T"'], - ['"U"'], - ['"V"'], - ['"W"'], - ['"X"'], - ['"Y"'], - ['"Z"'], - ['"a"'], - ['"b"'], - ['"c"'], - ['"d"'], - ['"e"'], - ['"f"'], - ['"g"'], - ['"h"'], - ['"i"'], - ['"j"'], - ['"k"'], - ['"l"'], - ['"m"'], - ['"n"'], - ['"o"'], - ['"p"'], - ['"q"'], - ['"r"'], - ['"s"'], - ['"t"'], - ['"u"'], - ['"v"'], - ['"w"'], - ['"x"'], - ['"y"'], - ['"z"'] - ] - }, - { - name: "RULE_DIGIT", - bnf: [['"0"'], ['"1"'], ['"2"'], ['"3"'], ['"4"'], ['"5"'], ['"6"'], ['"7"'], ['"8"'], ['"9"']] - }, - { - name: "RULE_SYMBOL", - bnf: [ - ['"-"'], - ['"_"'], - ['"!"'], - ['"#"'], - ['"$"'], - ['"%"'], - ['"&"'], - ['"("'], - ['")"'], - ['"*"'], - ['"+"'], - ['","'], - ['"-"'], - ['"."'], - ['"/"'], - ['":"'], - ['";"'], - ['"<"'], - ['"="'], - ['">"'], - ['"?"'], - ['"@"'], - ['"["'], - ['"\\"'], - ['"]"'], - ['"^"'], - ['"_"'], - ['"`"'], - ['"{"'], - ['"|"'], - ['"}"'], - ['"~"'] - ] - }, - { - name: "RULE_CHARACTER1", - bnf: [["RULE_CHARACTER"], [`"'"`]] - }, - { - name: "RULE_CHARACTER2", - bnf: [["RULE_CHARACTER"], [`'"'`]] - }, - { - name: "rule-name", - bnf: [["RULE_LETTER", "RULE_CHAR*"]] - }, - { - name: "RULE_CHAR", - bnf: [["RULE_LETTER"], ["RULE_DIGIT"], ['"_"'], ['"-"']] - } - ]; - BNF2.defaultParser = new Parser_1.Parser(BNF2.RULES, { debug: false }); - function getAllTerms(expr) { - let terms = SemanticHelpers_1.findChildrenByType(expr, "term").map((term) => { - return SemanticHelpers_1.findChildrenByType(term, "literal").concat(SemanticHelpers_1.findChildrenByType(term, "rule-name"))[0].text; - }); - SemanticHelpers_1.findChildrenByType(expr, "list").forEach((expr2) => { - terms = terms.concat(getAllTerms(expr2)); - }); - return terms; - } - function getRules(source, parser = BNF2.defaultParser) { - let ast = parser.getAST(source); - if (!ast) - throw new Error("Could not parse " + source); - if (ast.errors && ast.errors.length) { - throw ast.errors[0]; - } - let rules = SemanticHelpers_1.findChildrenByType(ast, "rule"); - let ret = rules.map((rule) => { - let name = SemanticHelpers_1.findChildrenByType(rule, "rule-name")[0].text; - let expressions = SemanticHelpers_1.findChildrenByType(rule, "firstExpression").concat(SemanticHelpers_1.findChildrenByType(rule, "otherExpression")); - let bnf = []; - expressions.forEach((expr) => { - bnf.push(getAllTerms(expr)); - }); - return { - name, - bnf - }; - }); - if (!ret.some((x) => x.name == "EOL")) { - ret.push({ - name: "EOL", - bnf: [['"\\r\\n"', '"\\r"', '"\\n"']] - }); - } - return ret; - } - BNF2.getRules = getRules; - function Transform(source, subParser = BNF2.defaultParser) { - return getRules(source.join(""), subParser); - } - BNF2.Transform = Transform; - class Parser extends Parser_1.Parser { - constructor(source, options) { - const subParser = options && options.debugRulesParser === true ? new Parser_1.Parser(BNF2.RULES, { debug: true }) : BNF2.defaultParser; - super(getRules(source, subParser), options); - this.source = source; - } - emitSource() { - return this.source; - } - } - BNF2.Parser = Parser; - })(BNF || (BNF = {})); - exports.default = BNF; - } -}); - -// node_modules/ebnf/dist/Grammars/W3CEBNF.js -var require_W3CEBNF = __commonJS({ - "node_modules/ebnf/dist/Grammars/W3CEBNF.js"(exports) { - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - var Parser_1 = require_Parser(); - var BNF; - (function(BNF2) { - BNF2.RULES = [ - { - name: "Grammar", - bnf: [["RULE_S*", "%Atomic*", "EOF"]] - }, - { - name: "%Atomic", - bnf: [["Production", "RULE_S*"]], - fragment: true - }, - { - name: "Production", - bnf: [["NCName", "RULE_S*", '"::="', "RULE_WHITESPACE*", "Choice", "RULE_WHITESPACE*", "RULE_EOL+", "RULE_S*"]] - }, - { - name: "NCName", - bnf: [[/[a-zA-Z][a-zA-Z_0-9]*/]] - }, - { - name: "Choice", - bnf: [["SequenceOrDifference", "%_Choice_1*"]], - fragment: true - }, - { - name: "%_Choice_1", - bnf: [["RULE_WHITESPACE*", '"|"', "RULE_WHITESPACE*", "SequenceOrDifference"]], - fragment: true - }, - { - name: "SequenceOrDifference", - bnf: [["Item", "RULE_WHITESPACE*", "%_Item_1?"]] - }, - { - name: "%_Item_1", - bnf: [["Minus", "Item"], ["Item*"]], - fragment: true - }, - { - name: "Minus", - bnf: [['"-"']] - }, - { - name: "Item", - bnf: [["RULE_WHITESPACE*", "%Primary", "PrimaryDecoration?"]], - fragment: true - }, - { - name: "PrimaryDecoration", - bnf: [['"?"'], ['"*"'], ['"+"']] - }, - { - name: "DecorationName", - bnf: [['"ebnf://"', /[^\x5D#]+/]] - }, - { - name: "%Primary", - bnf: [["NCName"], ["StringLiteral"], ["CharCode"], ["CharClass"], ["SubItem"]], - fragment: true - }, - { - name: "SubItem", - bnf: [['"("', "RULE_WHITESPACE*", "Choice", "RULE_WHITESPACE*", '")"']] - }, - { - name: "StringLiteral", - bnf: [[`'"'`, /[^"]*/, `'"'`], [`"'"`, /[^']*/, `"'"`]], - pinned: 1 - }, - { - name: "CharCode", - bnf: [['"#x"', /[0-9a-zA-Z]+/]] - }, - { - name: "CharClass", - bnf: [["'['", "'^'?", "%RULE_CharClass_1+", '"]"']] - }, - { - name: "%RULE_CharClass_1", - bnf: [["CharCodeRange"], ["CharRange"], ["CharCode"], ["RULE_Char"]], - fragment: true - }, - { - name: "RULE_Char", - bnf: [[/\x09/], [/\x0A/], [/\x0D/], [/[\x20-\x5c]/], [/[\x5e-\uD7FF]/], [/[\uE000-\uFFFD]/]] - }, - { - name: "CharRange", - bnf: [["RULE_Char", '"-"', "RULE_Char"]] - }, - { - name: "CharCodeRange", - bnf: [["CharCode", '"-"', "CharCode"]] - }, - { - name: "RULE_WHITESPACE", - bnf: [["%RULE_WHITESPACE_CHAR*"], ["Comment", "RULE_WHITESPACE*"]] - }, - { - name: "RULE_S", - bnf: [["RULE_WHITESPACE", "RULE_S*"], ["RULE_EOL", "RULE_S*"]] - }, - { - name: "%RULE_WHITESPACE_CHAR", - bnf: [[/\x09/], [/\x20/]], - fragment: true - }, - { - name: "Comment", - bnf: [['"/*"', "%RULE_Comment_Body*", '"*/"']] - }, - { - name: "%RULE_Comment_Body", - bnf: [['!"*/"', /[^*]/]], - fragment: true - }, - { - name: "RULE_EOL", - bnf: [[/\x0D/, /\x0A/], [/\x0A/], [/\x0D/]] - }, - { - name: "Link", - bnf: [["'['", "Url", "']'"]] - }, - { - name: "Url", - bnf: [[/[^\x5D:/?#]/, '"://"', /[^\x5D#]+/, "%Url1?"]] - }, - { - name: "%Url1", - bnf: [['"#"', "NCName"]], - fragment: true - } - ]; - BNF2.defaultParser = new Parser_1.Parser(BNF2.RULES, { debug: false }); - const preDecorationRE = /^(!|&)/; - const decorationRE = /(\?|\+|\*)$/; - const subExpressionRE = /^%/; - function getBNFRule(name, parser) { - if (typeof name == "string") { - if (preDecorationRE.test(name)) - return ""; - let subexpression = subExpressionRE.test(name); - if (subexpression) { - let decoration = decorationRE.exec(name); - let decorationText = decoration ? decoration[0] + " " : ""; - let lonely = isLonelyRule(name, parser); - if (lonely) - return getBNFBody(name, parser) + decorationText; - return "(" + getBNFBody(name, parser) + ")" + decorationText; - } - return name; - } else { - return name.source.replace(/\\(?:x|u)([a-zA-Z0-9]+)/g, "#x$1").replace(/\[\\(?:x|u)([a-zA-Z0-9]+)-\\(?:x|u)([a-zA-Z0-9]+)\]/g, "[#x$1-#x$2]"); - } - } - function isLonelyRule(name, parser) { - let rule = Parser_1.findRuleByName(name, parser); - return rule && rule.bnf.length == 1 && rule.bnf[0].length == 1 && (rule.bnf[0][0] instanceof RegExp || rule.bnf[0][0][0] == '"' || rule.bnf[0][0][0] == "'"); - } - function getBNFChoice(rules, parser) { - return rules.map((x) => getBNFRule(x, parser)).join(" "); - } - function getBNFBody(name, parser) { - let rule = Parser_1.findRuleByName(name, parser); - if (rule) - return rule.bnf.map((x) => getBNFChoice(x, parser)).join(" | "); - return "RULE_NOT_FOUND {" + name + "}"; - } - function emit(parser) { - let acumulator = []; - parser.grammarRules.forEach((l) => { - if (!/^%/.test(l.name)) { - let recover = l.recover ? " /* { recoverUntil=" + l.recover + " } */" : ""; - acumulator.push(l.name + " ::= " + getBNFBody(l.name, parser) + recover); - } - }); - return acumulator.join("\n"); - } - BNF2.emit = emit; - let subitems = 0; - function restar(total, resta) { - console.log("reberia restar " + resta + " a " + total); - throw new Error("Difference not supported yet"); - } - function convertRegex(txt) { - return new RegExp(txt.replace(/#x([a-zA-Z0-9]{4})/g, "\\u$1").replace(/#x([a-zA-Z0-9]{3})/g, "\\u0$1").replace(/#x([a-zA-Z0-9]{2})/g, "\\x$1").replace(/#x([a-zA-Z0-9]{1})/g, "\\x0$1")); - } - function getSubItems(tmpRules, seq, parentName) { - let anterior = null; - let bnfSeq = []; - seq.children.forEach((x, i) => { - if (x.type == "Minus") { - restar(anterior, x); - } else { - } - let decoration = seq.children[i + 1]; - decoration = decoration && decoration.type == "PrimaryDecoration" && decoration.text || ""; - let preDecoration = ""; - switch (x.type) { - case "SubItem": - let name = "%" + (parentName + subitems++); - createRule(tmpRules, x, name); - bnfSeq.push(preDecoration + name + decoration); - break; - case "NCName": - case "StringLiteral": - bnfSeq.push(preDecoration + x.text + decoration); - break; - case "CharCode": - case "CharClass": - if (decoration || preDecoration) { - let newRule = { - name: "%" + (parentName + subitems++), - bnf: [[convertRegex(x.text)]] - }; - tmpRules.push(newRule); - bnfSeq.push(preDecoration + newRule.name + decoration); - } else { - bnfSeq.push(convertRegex(x.text)); - } - break; - case "PrimaryDecoration": - break; - default: - throw new Error(" HOW SHOULD I PARSE THIS? " + x.type + " -> " + JSON.stringify(x.text)); - } - anterior = x; - }); - return bnfSeq; - } - function createRule(tmpRules, token, name) { - let bnf = token.children.filter((x) => x.type == "SequenceOrDifference").map((s) => getSubItems(tmpRules, s, name)); - let rule = { - name, - bnf - }; - let recover = null; - bnf.forEach((x) => { - recover = recover || x["recover"]; - delete x["recover"]; - }); - if (name.indexOf("%") == 0) - rule.fragment = true; - if (recover) - rule.recover = recover; - tmpRules.push(rule); - } - function getRules(source, parser = BNF2.defaultParser) { - let ast = parser.getAST(source); - if (!ast) - throw new Error("Could not parse " + source); - if (ast.errors && ast.errors.length) { - throw ast.errors[0]; - } - let tmpRules = []; - ast.children.filter((x) => x.type == "Production").map((x) => { - let name = x.children.filter((x2) => x2.type == "NCName")[0].text; - createRule(tmpRules, x, name); - }); - return tmpRules; - } - BNF2.getRules = getRules; - function Transform(source, subParser = BNF2.defaultParser) { - return getRules(source.join(""), subParser); - } - BNF2.Transform = Transform; - class Parser extends Parser_1.Parser { - constructor(source, options) { - const subParser = options && options.debugRulesParser === true ? new Parser_1.Parser(BNF2.RULES, { debug: true }) : BNF2.defaultParser; - super(getRules(source, subParser), options); - } - emitSource() { - return emit(this); - } - } - BNF2.Parser = Parser; - })(BNF || (BNF = {})); - exports.default = BNF; - } -}); - -// node_modules/ebnf/dist/Grammars/Custom.js -var require_Custom = __commonJS({ - "node_modules/ebnf/dist/Grammars/Custom.js"(exports) { - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - var TokenError_1 = require_TokenError(); - var Parser_1 = require_Parser(); - var BNF; - (function(BNF2) { - BNF2.RULES = [ - { - name: "Grammar", - bnf: [["RULE_S*", "Attributes?", "RULE_S*", "%Atomic*", "EOF"]] - }, - { - name: "%Atomic", - bnf: [["Production", "RULE_S*"]], - fragment: true - }, - { - name: "Production", - bnf: [ - [ - "NCName", - "RULE_S*", - '"::="', - "RULE_WHITESPACE*", - "%Choice", - "RULE_WHITESPACE*", - "Attributes?", - "RULE_EOL+", - "RULE_S*" - ] - ] - }, - { - name: "NCName", - bnf: [[/[a-zA-Z][a-zA-Z_0-9]*/]] - }, - { - name: "Attributes", - bnf: [['"{"', "Attribute", "%Attributes*", "RULE_S*", '"}"']] - }, - { - name: "%Attributes", - bnf: [["RULE_S*", '","', "Attribute"]], - fragment: true - }, - { - name: "Attribute", - bnf: [["RULE_S*", "NCName", "RULE_WHITESPACE*", '"="', "RULE_WHITESPACE*", "AttributeValue"]] - }, - { - name: "AttributeValue", - bnf: [["NCName"], [/[1-9][0-9]*/]] - }, - { - name: "%Choice", - bnf: [["SequenceOrDifference", "%_Choice_1*"]], - fragment: true - }, - { - name: "%_Choice_1", - bnf: [["RULE_S*", '"|"', "RULE_S*", "SequenceOrDifference"]], - fragment: true - }, - { - name: "SequenceOrDifference", - bnf: [["%Item", "RULE_WHITESPACE*", "%_Item_1?"]] - }, - { - name: "%_Item_1", - bnf: [["Minus", "%Item"], ["%Item*"]], - fragment: true - }, - { - name: "Minus", - bnf: [['"-"']] - }, - { - name: "%Item", - bnf: [["RULE_WHITESPACE*", "PrimaryPreDecoration?", "%Primary", "PrimaryDecoration?"]], - fragment: true - }, - { - name: "PrimaryDecoration", - bnf: [['"?"'], ['"*"'], ['"+"']] - }, - { - name: "PrimaryPreDecoration", - bnf: [['"&"'], ['"!"'], ['"~"']] - }, - { - name: "%Primary", - bnf: [["NCName"], ["StringLiteral"], ["CharCode"], ["CharClass"], ["SubItem"]], - fragment: true - }, - { - name: "SubItem", - bnf: [['"("', "RULE_S*", "%Choice", "RULE_S*", '")"']] - }, - { - name: "StringLiteral", - bnf: [[`'"'`, /[^"]*/, `'"'`], [`"'"`, /[^']*/, `"'"`]] - }, - { - name: "CharCode", - bnf: [['"#x"', /[0-9a-zA-Z]+/]] - }, - { - name: "CharClass", - bnf: [["'['", "'^'?", "%RULE_CharClass_1+", '"]"']] - }, - { - name: "%RULE_CharClass_1", - bnf: [["CharCodeRange"], ["CharRange"], ["CharCode"], ["RULE_Char"]], - fragment: true - }, - { - name: "RULE_Char", - bnf: [[/\x09/], [/\x0A/], [/\x0D/], [/[\x20-\x5c]/], [/[\x5e-\uD7FF]/], [/[\uE000-\uFFFD]/]] - }, - { - name: "CharRange", - bnf: [["RULE_Char", '"-"', "RULE_Char"]] - }, - { - name: "CharCodeRange", - bnf: [["CharCode", '"-"', "CharCode"]] - }, - { - name: "RULE_WHITESPACE", - bnf: [["%RULE_WHITESPACE_CHAR*"], ["Comment", "RULE_WHITESPACE*"]] - }, - { - name: "RULE_S", - bnf: [["RULE_WHITESPACE", "RULE_S*"], ["RULE_EOL", "RULE_S*"]] - }, - { - name: "%RULE_WHITESPACE_CHAR", - bnf: [[/\x09/], [/\x20/]], - fragment: true - }, - { - name: "Comment", - bnf: [['"/*"', "%RULE_Comment_Body*", '"*/"']] - }, - { - name: "%RULE_Comment_Body", - bnf: [[/[^*]/], ['"*"+', /[^/]*/]], - fragment: true - }, - { - name: "RULE_EOL", - bnf: [[/\x0D/, /\x0A/], [/\x0A/], [/\x0D/]] - }, - { - name: "Link", - bnf: [["'['", "Url", "']'"]] - }, - { - name: "Url", - bnf: [[/[^\x5D:/?#]/, '"://"', /[^\x5D#]+/, "%Url1?"]] - }, - { - name: "%Url1", - bnf: [['"#"', "NCName"]], - fragment: true - } - ]; - BNF2.defaultParser = new Parser_1.Parser(BNF2.RULES, { debug: false }); - const preDecorationRE = /^(!|&)/; - const decorationRE = /(\?|\+|\*)$/; - const subExpressionRE = /^%/; - function getBNFRule(name, parser) { - if (typeof name == "string") { - let decoration = decorationRE.exec(name); - let preDecoration = preDecorationRE.exec(name); - let preDecorationText = preDecoration ? preDecoration[0] : ""; - let decorationText = decoration ? decoration[0] + " " : ""; - let subexpression = subExpressionRE.test(name); - if (subexpression) { - let lonely = isLonelyRule(name, parser); - if (lonely) - return preDecorationText + getBNFBody(name, parser) + decorationText; - return preDecorationText + "(" + getBNFBody(name, parser) + ")" + decorationText; - } - return name.replace(preDecorationRE, preDecorationText); - } else { - return name.source.replace(/\\(?:x|u)([a-zA-Z0-9]+)/g, "#x$1").replace(/\[\\(?:x|u)([a-zA-Z0-9]+)-\\(?:x|u)([a-zA-Z0-9]+)\]/g, "[#x$1-#x$2]"); - } - } - function isLonelyRule(name, parser) { - let rule = Parser_1.findRuleByName(name, parser); - return rule && rule.bnf.length == 1 && rule.bnf[0].length == 1 && (rule.bnf[0][0] instanceof RegExp || rule.bnf[0][0][0] == '"' || rule.bnf[0][0][0] == "'"); - } - function getBNFChoice(rules, parser) { - return rules.map((x) => getBNFRule(x, parser)).join(" "); - } - function getBNFBody(name, parser) { - let rule = Parser_1.findRuleByName(name, parser); - if (rule) - return rule.bnf.map((x) => getBNFChoice(x, parser)).join(" | "); - return "RULE_NOT_FOUND {" + name + "}"; - } - function emit(parser) { - let acumulator = []; - parser.grammarRules.forEach((l) => { - if (!/^%/.test(l.name)) { - let recover = l.recover ? " { recoverUntil=" + l.recover + " }" : ""; - acumulator.push(l.name + " ::= " + getBNFBody(l.name, parser) + recover); - } - }); - return acumulator.join("\n"); - } - BNF2.emit = emit; - let subitems = 0; - function restar(total, resta) { - console.log("reberia restar " + resta + " a " + total); - throw new Error("Difference not supported yet"); - } - function convertRegex(txt) { - return new RegExp(txt.replace(/#x([a-zA-Z0-9]{4})/g, "\\u$1").replace(/#x([a-zA-Z0-9]{3})/g, "\\u0$1").replace(/#x([a-zA-Z0-9]{2})/g, "\\x$1").replace(/#x([a-zA-Z0-9]{1})/g, "\\x0$1")); - } - function getSubItems(tmpRules, seq, parentName, parentAttributes) { - let anterior = null; - let bnfSeq = []; - seq.children.forEach((x, i) => { - if (x.type == "Minus") { - restar(anterior, x); - } else { - } - let decoration = seq.children[i + 1]; - decoration = decoration && decoration.type == "PrimaryDecoration" && decoration.text || ""; - let preDecoration = ""; - if (anterior && anterior.type == "PrimaryPreDecoration") { - preDecoration = anterior.text; - } - let pinned = preDecoration == "~" ? 1 : void 0; - if (pinned) { - preDecoration = ""; - } - switch (x.type) { - case "SubItem": - let name = "%" + (parentName + subitems++); - createRule(tmpRules, x, name, parentAttributes); - bnfSeq.push(preDecoration + name + decoration); - break; - case "NCName": - bnfSeq.push(preDecoration + x.text + decoration); - break; - case "StringLiteral": - if (decoration || preDecoration || !/^['"/()a-zA-Z0-9&_.:=,+*\-\^\\]+$/.test(x.text)) { - bnfSeq.push(preDecoration + x.text + decoration); - } else { - for (const c of x.text.slice(1, -1)) { - if (parentAttributes && parentAttributes["ignoreCase"] == "true" && /[a-zA-Z]/.test(c)) { - bnfSeq.push(new RegExp("[" + c.toUpperCase() + c.toLowerCase() + "]")); - } else { - bnfSeq.push(new RegExp(Parser_1.escapeRegExp(c))); - } - } - } - break; - case "CharCode": - case "CharClass": - if (decoration || preDecoration) { - let newRule = { - name: "%" + (parentName + subitems++), - bnf: [[convertRegex(x.text)]], - pinned - }; - tmpRules.push(newRule); - bnfSeq.push(preDecoration + newRule.name + decoration); - } else { - bnfSeq.push(convertRegex(x.text)); - } - break; - case "PrimaryPreDecoration": - case "PrimaryDecoration": - break; - default: - throw new Error(" HOW SHOULD I PARSE THIS? " + x.type + " -> " + JSON.stringify(x.text)); - } - anterior = x; - }); - return bnfSeq; - } - function createRule(tmpRules, token, name, parentAttributes = void 0) { - let attrNode = token.children.filter((x) => x.type == "Attributes")[0]; - let attributes = {}; - if (attrNode) { - attrNode.children.forEach((x) => { - let name2 = x.children.filter((x2) => x2.type == "NCName")[0].text; - if (name2 in attributes) { - throw new TokenError_1.TokenError("Duplicated attribute " + name2, x); - } else { - attributes[name2] = x.children.filter((x2) => x2.type == "AttributeValue")[0].text; - } - }); - } - let bnf = token.children.filter((x) => x.type == "SequenceOrDifference").map((s) => getSubItems(tmpRules, s, name, parentAttributes ? parentAttributes : attributes)); - let rule = { - name, - bnf - }; - if (name.indexOf("%") == 0) - rule.fragment = true; - if (attributes["recoverUntil"]) { - rule.recover = attributes["recoverUntil"]; - if (rule.bnf.length > 1) - throw new TokenError_1.TokenError("only one-option productions are suitable for error recovering", token); - } - if ("pin" in attributes) { - let num = parseInt(attributes["pin"]); - if (!isNaN(num)) { - rule.pinned = num; - } - if (rule.bnf.length > 1) - throw new TokenError_1.TokenError("only one-option productions are suitable for pinning", token); - } - if ("ws" in attributes) { - rule.implicitWs = attributes["ws"] != "explicit"; - } else { - rule.implicitWs = null; - } - rule.fragment = rule.fragment || attributes["fragment"] == "true"; - rule.simplifyWhenOneChildren = attributes["simplifyWhenOneChildren"] == "true"; - tmpRules.push(rule); - } - function getRules(source, parser = BNF2.defaultParser) { - let ast = parser.getAST(source); - if (!ast) - throw new Error("Could not parse " + source); - if (ast.errors && ast.errors.length) { - throw ast.errors[0]; - } - let implicitWs = null; - let attrNode = ast.children.filter((x) => x.type == "Attributes")[0]; - let attributes = {}; - if (attrNode) { - attrNode.children.forEach((x) => { - let name = x.children.filter((x2) => x2.type == "NCName")[0].text; - if (name in attributes) { - throw new TokenError_1.TokenError("Duplicated attribute " + name, x); - } else { - attributes[name] = x.children.filter((x2) => x2.type == "AttributeValue")[0].text; - } - }); - } - implicitWs = attributes["ws"] == "implicit"; - let tmpRules = []; - ast.children.filter((x) => x.type == "Production").map((x) => { - let name = x.children.filter((x2) => x2.type == "NCName")[0].text; - createRule(tmpRules, x, name); - }); - tmpRules.forEach((rule) => { - if (rule.implicitWs === null) - rule.implicitWs = implicitWs; - }); - return tmpRules; - } - BNF2.getRules = getRules; - function Transform(source, subParser = BNF2.defaultParser) { - return getRules(source.join(""), subParser); - } - BNF2.Transform = Transform; - class Parser extends Parser_1.Parser { - constructor(source, options) { - const subParser = options && options.debugRulesParser === true ? new Parser_1.Parser(BNF2.RULES, { debug: true }) : BNF2.defaultParser; - super(getRules(source, subParser), options); - } - emitSource() { - return emit(this); - } - } - BNF2.Parser = Parser; - })(BNF || (BNF = {})); - exports.default = BNF; - } -}); - -// node_modules/ebnf/dist/Grammars/index.js -var require_Grammars = __commonJS({ - "node_modules/ebnf/dist/Grammars/index.js"(exports) { - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - var BNF_1 = require_BNF(); - Object.defineProperty(exports, "BNF", { enumerable: true, get: function() { - return BNF_1.default; - } }); - var W3CEBNF_1 = require_W3CEBNF(); - Object.defineProperty(exports, "W3C", { enumerable: true, get: function() { - return W3CEBNF_1.default; - } }); - var Custom_1 = require_Custom(); - Object.defineProperty(exports, "Custom", { enumerable: true, get: function() { - return Custom_1.default; - } }); - } -}); - -// node_modules/ebnf/dist/index.js -var require_dist = __commonJS({ - "node_modules/ebnf/dist/index.js"(exports) { - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - var Parser_1 = require_Parser(); - Object.defineProperty(exports, "Parser", { enumerable: true, get: function() { - return Parser_1.Parser; - } }); - var TokenError_1 = require_TokenError(); - Object.defineProperty(exports, "TokenError", { enumerable: true, get: function() { - return TokenError_1.TokenError; - } }); - exports.Grammars = require_Grammars(); - } -}); - -// node_modules/@tgrosinger/md-advanced-tables/lib/calc/calc.js -var require_calc = __commonJS({ - "node_modules/@tgrosinger/md-advanced-tables/lib/calc/calc.js"(exports) { - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.parseFormula = exports.parseAndApply = exports.Source = exports.Formula = void 0; - var neverthrow_1 = require_neverthrow(); - var algebraic_operation_1 = require_algebraic_operation(); - var ast_utils_1 = require_ast_utils(); - var conditional_function_1 = require_conditional_function(); - var constant_1 = require_constant(); - var destination_1 = require_destination(); - var display_directive_1 = require_display_directive(); - var range_1 = require_range2(); - var reference_1 = require_reference(); - var single_param_function_1 = require_single_param_function(); - var ebnf_1 = require_dist(); - var lodash_1 = require_lodash(); - var parserGrammar = ` -tblfm_line ::= "" -formula_list ::= formula ( "::" formula_list )? -formula ::= destination "=" source display_directive? - -source ::= range | source_reference | single_param_function_call | conditional_function_call | algebraic_operation | float | real -range ::= source_reference ".." source_reference -source_reference ::= absolute_reference | relative_reference -destination ::= range | absolute_reference - -relative_reference ::= (relative_row | absolute_row) (relative_column | absolute_column) | relative_row | relative_column -relative_row ::= "@" ( "-" | "+" ) int -relative_column ::= "$" ( "-" | "+" ) int - -absolute_reference ::= absolute_row absolute_column | absolute_row | absolute_column -absolute_row ::= "@" ( "I" | "<" | ">" | int ) -absolute_column ::= "$" ( "<" | ">" | int ) - -single_param_function_call ::= single_param_function "(" source ")" -single_param_function ::= "mean" | "sum" - -conditional_function_call ::= "if(" predicate "," " "? source "," " "? source ")" -predicate ::= source_without_range conditional_operator source_without_range -source_without_range ::= source_reference | single_param_function_call | conditional_function_call | algebraic_operation | float | real -conditional_operator ::= ">" | "<" | ">=" | "<=" | "==" | "!=" - -algebraic_operation ::= "(" source " "? algebraic_operator " "? source ")" -algebraic_operator ::= "+" | "-" | "*" | "/" - -display_directive ::= ";" display_directive_option -display_directive_option ::= formatting_directive | datetime_directive | hourminute_directive -formatting_directive ::= "%." int "f" -datetime_directive ::= "dt" -hourminute_directive ::= "hm" - -float ::= "-"? int "." int -real ::= "-"? int -int ::= [0-9]+ -`; - var Formula = class { - constructor(ast, table) { - this.merge = (table2) => this.destination.merge(this.source, table2); - let formatter = new display_directive_1.DefaultFormatter(); - if (ast.children.length === 3) { - formatter = new display_directive_1.DisplayDirective(ast.children[2]); - } - const destination = (0, destination_1.newDestination)(ast.children[0], table, formatter); - if (destination.isErr()) { - throw destination.error; - } - this.destination = destination.value; - this.source = new Source(ast.children[1], table); - } - }; - exports.Formula = Formula; - var Source = class { - constructor(ast, table) { - this.getValue = (table2, currentCell) => this.locationDescriptor.getValue(table2, currentCell); - if (ast.type !== "source" && ast.type !== "source_without_range") { - throw Error("Invalid AST token type of " + ast.type); - } - if (ast.children.length !== 1) { - throw Error("Unexpected children length in Source"); - } - const paramChild = ast.children[0]; - const vp = newValueProvider(paramChild, table); - if (vp.isErr()) { - throw vp.error; - } - this.locationDescriptor = vp.value; - } - }; - exports.Source = Source; - var newValueProvider = (ast, table) => { - try { - switch (ast.type) { - case "range": - return (0, neverthrow_1.ok)(new range_1.Range(ast, table)); - case "source_reference": - const lengthError = (0, ast_utils_1.checkChildLength)(ast, 1); - if (lengthError) { - return (0, neverthrow_1.err)(lengthError); - } - return (0, neverthrow_1.ok)(new reference_1.Reference(ast.children[0], table)); - case "single_param_function_call": - return (0, neverthrow_1.ok)(new single_param_function_1.SingleParamFunctionCall(ast, table)); - case "conditional_function_call": - return (0, neverthrow_1.ok)(new conditional_function_1.ConditionalFunctionCall(ast, table)); - case "algebraic_operation": - return (0, neverthrow_1.ok)(new algebraic_operation_1.AlgebraicOperation(ast, table)); - case "real": - return (0, neverthrow_1.ok)(new constant_1.Constant(ast, table)); - case "float": - return (0, neverthrow_1.ok)(new constant_1.Constant(ast, table)); - default: - throw Error("Unrecognized valueProvider type " + ast.type); - } - } catch (error) { - return (0, neverthrow_1.err)(error); - } - }; - var parseAndApply = (formulaLines, table) => { - const formulas = formulaLines.reduce((prev, formulaLine) => prev.andThen((currentFormulas) => { - const newFormulas = (0, exports.parseFormula)(formulaLine, table); - if (newFormulas.isErr()) { - return newFormulas; - } - return (0, neverthrow_1.ok)((0, lodash_1.concat)(newFormulas.value, currentFormulas)); - }), (0, neverthrow_1.ok)([])); - return formulas.andThen((innerFormulas) => ( - // for each formula - innerFormulas.reduceRight( - (prevValue, formula) => ( - // If the previous formula didn't give an error - prevValue.andThen((prevTable) => ( - // attempt to apply this formula to the table and return the result - formula.merge(prevTable) - )) - ), - // Start with the current table state - (0, neverthrow_1.ok)(table) - ) - )); - }; - exports.parseAndApply = parseAndApply; - var parseFormula = (line, table) => { - const parser = new ebnf_1.Grammars.W3C.Parser(parserGrammar); - const ast = parser.getAST(line); - if (!ast) { - return (0, neverthrow_1.err)(new Error(`Formula '${line}' could not be parsed`)); - } - const typeError = (0, ast_utils_1.checkType)(ast, "tblfm_line"); - if (typeError) { - return (0, neverthrow_1.err)(typeError); - } - const lengthError = (0, ast_utils_1.checkChildLength)(ast, 1); - if (lengthError) { - return (0, neverthrow_1.err)(lengthError); - } - let unparsedFormulas = ast.children[0].children; - const formulas = []; - try { - do { - formulas.push(new Formula(unparsedFormulas[0], table)); - if (unparsedFormulas.length > 1 && unparsedFormulas[1].type === "formula_list") { - unparsedFormulas = unparsedFormulas[1].children; - } else { - unparsedFormulas = []; - } - } while (unparsedFormulas.length > 0); - return (0, neverthrow_1.ok)(formulas); - } catch (error) { - return (0, neverthrow_1.err)(error); - } - }; - exports.parseFormula = parseFormula; - } -}); - -// node_modules/@tgrosinger/md-advanced-tables/lib/table.js -var require_table = __commonJS({ - "node_modules/@tgrosinger/md-advanced-tables/lib/table.js"(exports) { - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.Table = void 0; - var calc_1 = require_calc(); - var focus_1 = require_focus(); - var point_1 = require_point(); - var range_1 = require_range(); - var Table = class _Table { - /** - * Creates a new `Table` object. - * - * @param rows - An array of rows that the table contains. - * @param formulas - An array of formulas attached to the table. - */ - constructor(rows) { - this._rows = rows.slice(); - } - /** - * Gets the number of rows in the table. - * - * @returns The number of rows. - */ - getHeight() { - return this._rows.length; - } - /** - * Gets the maximum width of the rows in the table. - * - * @returns The maximum width of the rows. - */ - getWidth() { - return this._rows.map((row) => row.getWidth()).reduce((x, y) => Math.max(x, y), 0); - } - /** - * Gets the width of the header row. - * Assumes that it is called on a valid table with a header row. - * - * @returns The width of the header row - */ - getHeaderWidth() { - return this._rows[0].getWidth(); - } - /** - * Gets the rows that the table contains. - * - * @returns An array of the rows. - */ - getRows() { - return this._rows.slice(); - } - /** - * Gets the delimiter row of the table. - * - * @returns The delimiter row; `undefined` if there is not delimiter row. - */ - getDelimiterRow() { - const row = this._rows[1]; - if (row === void 0) { - return void 0; - } - if (row.isDelimiter()) { - return row; - } - return void 0; - } - /** - * Gets a cell at the specified index. - * - * @param rowIndex - Row index of the cell. - * @param columnIndex - Column index of the cell. - * @returns The cell at the specified index; `undefined` if not found. - */ - getCellAt(rowIndex, columnIndex) { - const row = this._rows[rowIndex]; - if (row === void 0) { - return void 0; - } - return row.getCellAt(columnIndex); - } - /** - * Gets the cell at the focus. - * - * @param focus - Focus object. - * @returns The cell at the focus; `undefined` if not found. - */ - getFocusedCell(focus) { - return this.getCellAt(focus.row, focus.column); - } - /** - * Converts the table to an array of text representations of the rows. - * - * @returns An array of text representations of the rows. - */ - toLines() { - return this._rows.map((row) => row.toText()); - } - /** - * Sets a cell in the table to a new value, returning a copy of the table - * with the modified value. - * - * If an invalid index is provided, the table will be unchanged. - */ - setCellAt(rowIndex, columnIndex, value) { - const rows = this.getRows(); - rows[rowIndex] = rows[rowIndex].setCellAt(columnIndex, value); - return new _Table(rows); - } - /** - * Computes a focus from a point in the text editor. - * - * @param pos - A point in the text editor. - * @param rowOffset - The row index where the table starts in the text editor. - * @returns A focus object that corresponds to the specified point; - * `undefined` if the row index is out of bounds. - */ - focusOfPosition(pos, rowOffset) { - const rowIndex = pos.row - rowOffset; - const row = this._rows[rowIndex]; - if (row === void 0) { - return void 0; - } - if (pos.column < row.marginLeft.length + 1) { - return new focus_1.Focus(rowIndex, -1, pos.column); - } - const cellWidths = row.getCells().map((cell) => cell.rawContent.length); - let columnPos = row.marginLeft.length + 1; - let columnIndex = 0; - for (; columnIndex < cellWidths.length; columnIndex++) { - if (columnPos + cellWidths[columnIndex] + 1 > pos.column) { - break; - } - columnPos += cellWidths[columnIndex] + 1; - } - const offset = pos.column - columnPos; - return new focus_1.Focus(rowIndex, columnIndex, offset); - } - /** - * Computes a position in the text editor from a focus. - * - * @param focus - A focus object. - * @param rowOffset - The row index where the table starts in the text editor. - * @returns A position in the text editor that corresponds to the focus; - * `undefined` if the focused row is out of the table. - */ - positionOfFocus(focus, rowOffset) { - const row = this._rows[focus.row]; - if (row === void 0) { - return void 0; - } - const rowPos = focus.row + rowOffset; - if (focus.column < 0) { - return new point_1.Point(rowPos, focus.offset); - } - const cellWidths = row.getCells().map((cell) => cell.rawContent.length); - const maxIndex = Math.min(focus.column, cellWidths.length); - let columnPos = row.marginLeft.length + 1; - for (let columnIndex = 0; columnIndex < maxIndex; columnIndex++) { - columnPos += cellWidths[columnIndex] + 1; - } - return new point_1.Point(rowPos, columnPos + focus.offset); - } - /** - * Computes a selection range from a focus. - * - * @param focus - A focus object. - * @param rowOffset - The row index where the table starts in the text editor. - * @returns A range to be selected that corresponds to the focus; - * `undefined` if the focus does not specify any cell or the specified cell is empty. - */ - selectionRangeOfFocus(focus, rowOffset) { - const row = this._rows[focus.row]; - if (row === void 0) { - return void 0; - } - const cell = row.getCellAt(focus.column); - if (cell === void 0) { - return void 0; - } - if (cell.content === "") { - return void 0; - } - const rowPos = focus.row + rowOffset; - const cellWidths = row.getCells().map((cell2) => cell2.rawContent.length); - let columnPos = row.marginLeft.length + 1; - for (let columnIndex = 0; columnIndex < focus.column; columnIndex++) { - columnPos += cellWidths[columnIndex] + 1; - } - columnPos += cell.paddingLeft; - return new range_1.Range(new point_1.Point(rowPos, columnPos), new point_1.Point(rowPos, columnPos + cell.content.length)); - } - /** - * Evaluate the formula, applying the results to this table and returning the - * changes as a new table. - */ - applyFormulas(formulaLines) { - return (0, calc_1.parseAndApply)(formulaLines, this); - } - }; - exports.Table = Table; - } -}); - -// node_modules/@tgrosinger/md-advanced-tables/lib/parser.js -var require_parser = __commonJS({ - "node_modules/@tgrosinger/md-advanced-tables/lib/parser.js"(exports) { - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.readTable = exports._marginRegex = exports.marginRegexSrc = exports._readRow = exports._splitCells = void 0; - var table_1 = require_table(); - var table_cell_1 = require_table_cell(); - var table_row_1 = require_table_row(); - var _splitCells = (text) => { - const cells = []; - let buf = ""; - let rest = text; - while (rest !== "") { - switch (rest[0]) { - case "`": - { - const startMatch = rest.match(/^`*/); - if (startMatch === null) { - break; - } - const start = startMatch[0]; - let buf1 = start; - let rest1 = rest.substr(start.length); - let closed = false; - while (rest1 !== "") { - if (rest1[0] === "`") { - const endMatch = rest1.match(/^`*/); - if (endMatch === null) { - break; - } - const end = endMatch[0]; - buf1 += end; - rest1 = rest1.substr(end.length); - if (end.length === start.length) { - closed = true; - break; - } - } else { - buf1 += rest1[0]; - rest1 = rest1.substr(1); - } - } - if (closed) { - buf += buf1; - rest = rest1; - } else { - buf += "`"; - rest = rest.substr(1); - } - } - break; - case "\\": - if (rest.length >= 2) { - buf += rest.substr(0, 2); - rest = rest.substr(2); - } else { - buf += "\\"; - rest = rest.substr(1); - } - break; - case "[": - buf += "["; - rest = rest.substr(1); - if (/\[[^\\|\]]+\|[^|\]]+]]/.test(rest)) { - const idx = rest.indexOf("|"); - buf += rest.slice(0, idx); - buf += "\\|"; - rest = rest.substr(idx + 1); - } - break; - case "|": - cells.push(buf); - buf = ""; - rest = rest.substr(1); - break; - default: - buf += rest[0]; - rest = rest.substr(1); - } - } - cells.push(buf); - return cells; - }; - exports._splitCells = _splitCells; - var _readRow = (text, leftMarginRegex = /^\s*$/) => { - let cells = (0, exports._splitCells)(text); - let marginLeft; - if (cells.length > 0 && leftMarginRegex.test(cells[0])) { - marginLeft = cells[0]; - cells = cells.slice(1); - } else { - marginLeft = ""; - } - let marginRight; - if (cells.length > 1 && /^\s*$/.test(cells[cells.length - 1])) { - marginRight = cells[cells.length - 1]; - cells = cells.slice(0, cells.length - 1); - } else { - marginRight = ""; - } - return new table_row_1.TableRow(cells.map((cell) => new table_cell_1.TableCell(cell)), marginLeft, marginRight); - }; - exports._readRow = _readRow; - var marginRegexSrc = (chars) => { - let cs = ""; - chars.forEach((c) => { - if (c !== "|" && c !== "\\" && c !== "`") { - cs += `\\u{${c.codePointAt(0).toString(16)}}`; - } - }); - return `[\\s${cs}]*`; - }; - exports.marginRegexSrc = marginRegexSrc; - var _marginRegex = (chars) => new RegExp(`^${(0, exports.marginRegexSrc)(chars)}$`, "u"); - exports._marginRegex = _marginRegex; - var readTable = (lines, options) => { - const leftMarginRegex = (0, exports._marginRegex)(options.leftMarginChars); - return new table_1.Table(lines.map((line) => (0, exports._readRow)(line, leftMarginRegex))); - }; - exports.readTable = readTable; - } -}); - -// node_modules/meaw/lib/index.js -var require_lib = __commonJS({ - "node_modules/meaw/lib/index.js"(exports) { - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - var defs = [ - [0, 31, "N"], - [32, 126, "Na"], - [127, 160, "N"], - [161, 161, "A"], - [162, 163, "Na"], - [164, 164, "A"], - [165, 166, "Na"], - [167, 168, "A"], - [169, 169, "N"], - [170, 170, "A"], - [171, 171, "N"], - [172, 172, "Na"], - [173, 174, "A"], - [175, 175, "Na"], - [176, 180, "A"], - [181, 181, "N"], - [182, 186, "A"], - [187, 187, "N"], - [188, 191, "A"], - [192, 197, "N"], - [198, 198, "A"], - [199, 207, "N"], - [208, 208, "A"], - [209, 214, "N"], - [215, 216, "A"], - [217, 221, "N"], - [222, 225, "A"], - [226, 229, "N"], - [230, 230, "A"], - [231, 231, "N"], - [232, 234, "A"], - [235, 235, "N"], - [236, 237, "A"], - [238, 239, "N"], - [240, 240, "A"], - [241, 241, "N"], - [242, 243, "A"], - [244, 246, "N"], - [247, 250, "A"], - [251, 251, "N"], - [252, 252, "A"], - [253, 253, "N"], - [254, 254, "A"], - [255, 256, "N"], - [257, 257, "A"], - [258, 272, "N"], - [273, 273, "A"], - [274, 274, "N"], - [275, 275, "A"], - [276, 282, "N"], - [283, 283, "A"], - [284, 293, "N"], - [294, 295, "A"], - [296, 298, "N"], - [299, 299, "A"], - [300, 304, "N"], - [305, 307, "A"], - [308, 311, "N"], - [312, 312, "A"], - [313, 318, "N"], - [319, 322, "A"], - [323, 323, "N"], - [324, 324, "A"], - [325, 327, "N"], - [328, 331, "A"], - [332, 332, "N"], - [333, 333, "A"], - [334, 337, "N"], - [338, 339, "A"], - [340, 357, "N"], - [358, 359, "A"], - [360, 362, "N"], - [363, 363, "A"], - [364, 461, "N"], - [462, 462, "A"], - [463, 463, "N"], - [464, 464, "A"], - [465, 465, "N"], - [466, 466, "A"], - [467, 467, "N"], - [468, 468, "A"], - [469, 469, "N"], - [470, 470, "A"], - [471, 471, "N"], - [472, 472, "A"], - [473, 473, "N"], - [474, 474, "A"], - [475, 475, "N"], - [476, 476, "A"], - [477, 592, "N"], - [593, 593, "A"], - [594, 608, "N"], - [609, 609, "A"], - [610, 707, "N"], - [708, 708, "A"], - [709, 710, "N"], - [711, 711, "A"], - [712, 712, "N"], - [713, 715, "A"], - [716, 716, "N"], - [717, 717, "A"], - [718, 719, "N"], - [720, 720, "A"], - [721, 727, "N"], - [728, 731, "A"], - [732, 732, "N"], - [733, 733, "A"], - [734, 734, "N"], - [735, 735, "A"], - [736, 767, "N"], - [768, 879, "A"], - [880, 912, "N"], - [913, 929, "A"], - [930, 930, "N"], - [931, 937, "A"], - [938, 944, "N"], - [945, 961, "A"], - [962, 962, "N"], - [963, 969, "A"], - [970, 1024, "N"], - [1025, 1025, "A"], - [1026, 1039, "N"], - [1040, 1103, "A"], - [1104, 1104, "N"], - [1105, 1105, "A"], - [1106, 4351, "N"], - [4352, 4447, "W"], - [4448, 8207, "N"], - [8208, 8208, "A"], - [8209, 8210, "N"], - [8211, 8214, "A"], - [8215, 8215, "N"], - [8216, 8217, "A"], - [8218, 8219, "N"], - [8220, 8221, "A"], - [8222, 8223, "N"], - [8224, 8226, "A"], - [8227, 8227, "N"], - [8228, 8231, "A"], - [8232, 8239, "N"], - [8240, 8240, "A"], - [8241, 8241, "N"], - [8242, 8243, "A"], - [8244, 8244, "N"], - [8245, 8245, "A"], - [8246, 8250, "N"], - [8251, 8251, "A"], - [8252, 8253, "N"], - [8254, 8254, "A"], - [8255, 8307, "N"], - [8308, 8308, "A"], - [8309, 8318, "N"], - [8319, 8319, "A"], - [8320, 8320, "N"], - [8321, 8324, "A"], - [8325, 8360, "N"], - [8361, 8361, "H"], - [8362, 8363, "N"], - [8364, 8364, "A"], - [8365, 8450, "N"], - [8451, 8451, "A"], - [8452, 8452, "N"], - [8453, 8453, "A"], - [8454, 8456, "N"], - [8457, 8457, "A"], - [8458, 8466, "N"], - [8467, 8467, "A"], - [8468, 8469, "N"], - [8470, 8470, "A"], - [8471, 8480, "N"], - [8481, 8482, "A"], - [8483, 8485, "N"], - [8486, 8486, "A"], - [8487, 8490, "N"], - [8491, 8491, "A"], - [8492, 8530, "N"], - [8531, 8532, "A"], - [8533, 8538, "N"], - [8539, 8542, "A"], - [8543, 8543, "N"], - [8544, 8555, "A"], - [8556, 8559, "N"], - [8560, 8569, "A"], - [8570, 8584, "N"], - [8585, 8585, "A"], - [8586, 8591, "N"], - [8592, 8601, "A"], - [8602, 8631, "N"], - [8632, 8633, "A"], - [8634, 8657, "N"], - [8658, 8658, "A"], - [8659, 8659, "N"], - [8660, 8660, "A"], - [8661, 8678, "N"], - [8679, 8679, "A"], - [8680, 8703, "N"], - [8704, 8704, "A"], - [8705, 8705, "N"], - [8706, 8707, "A"], - [8708, 8710, "N"], - [8711, 8712, "A"], - [8713, 8714, "N"], - [8715, 8715, "A"], - [8716, 8718, "N"], - [8719, 8719, "A"], - [8720, 8720, "N"], - [8721, 8721, "A"], - [8722, 8724, "N"], - [8725, 8725, "A"], - [8726, 8729, "N"], - [8730, 8730, "A"], - [8731, 8732, "N"], - [8733, 8736, "A"], - [8737, 8738, "N"], - [8739, 8739, "A"], - [8740, 8740, "N"], - [8741, 8741, "A"], - [8742, 8742, "N"], - [8743, 8748, "A"], - [8749, 8749, "N"], - [8750, 8750, "A"], - [8751, 8755, "N"], - [8756, 8759, "A"], - [8760, 8763, "N"], - [8764, 8765, "A"], - [8766, 8775, "N"], - [8776, 8776, "A"], - [8777, 8779, "N"], - [8780, 8780, "A"], - [8781, 8785, "N"], - [8786, 8786, "A"], - [8787, 8799, "N"], - [8800, 8801, "A"], - [8802, 8803, "N"], - [8804, 8807, "A"], - [8808, 8809, "N"], - [8810, 8811, "A"], - [8812, 8813, "N"], - [8814, 8815, "A"], - [8816, 8833, "N"], - [8834, 8835, "A"], - [8836, 8837, "N"], - [8838, 8839, "A"], - [8840, 8852, "N"], - [8853, 8853, "A"], - [8854, 8856, "N"], - [8857, 8857, "A"], - [8858, 8868, "N"], - [8869, 8869, "A"], - [8870, 8894, "N"], - [8895, 8895, "A"], - [8896, 8977, "N"], - [8978, 8978, "A"], - [8979, 8985, "N"], - [8986, 8987, "W"], - [8988, 9e3, "N"], - [9001, 9002, "W"], - [9003, 9192, "N"], - [9193, 9196, "W"], - [9197, 9199, "N"], - [9200, 9200, "W"], - [9201, 9202, "N"], - [9203, 9203, "W"], - [9204, 9311, "N"], - [9312, 9449, "A"], - [9450, 9450, "N"], - [9451, 9547, "A"], - [9548, 9551, "N"], - [9552, 9587, "A"], - [9588, 9599, "N"], - [9600, 9615, "A"], - [9616, 9617, "N"], - [9618, 9621, "A"], - [9622, 9631, "N"], - [9632, 9633, "A"], - [9634, 9634, "N"], - [9635, 9641, "A"], - [9642, 9649, "N"], - [9650, 9651, "A"], - [9652, 9653, "N"], - [9654, 9655, "A"], - [9656, 9659, "N"], - [9660, 9661, "A"], - [9662, 9663, "N"], - [9664, 9665, "A"], - [9666, 9669, "N"], - [9670, 9672, "A"], - [9673, 9674, "N"], - [9675, 9675, "A"], - [9676, 9677, "N"], - [9678, 9681, "A"], - [9682, 9697, "N"], - [9698, 9701, "A"], - [9702, 9710, "N"], - [9711, 9711, "A"], - [9712, 9724, "N"], - [9725, 9726, "W"], - [9727, 9732, "N"], - [9733, 9734, "A"], - [9735, 9736, "N"], - [9737, 9737, "A"], - [9738, 9741, "N"], - [9742, 9743, "A"], - [9744, 9747, "N"], - [9748, 9749, "W"], - [9750, 9755, "N"], - [9756, 9756, "A"], - [9757, 9757, "N"], - [9758, 9758, "A"], - [9759, 9791, "N"], - [9792, 9792, "A"], - [9793, 9793, "N"], - [9794, 9794, "A"], - [9795, 9799, "N"], - [9800, 9811, "W"], - [9812, 9823, "N"], - [9824, 9825, "A"], - [9826, 9826, "N"], - [9827, 9829, "A"], - [9830, 9830, "N"], - [9831, 9834, "A"], - [9835, 9835, "N"], - [9836, 9837, "A"], - [9838, 9838, "N"], - [9839, 9839, "A"], - [9840, 9854, "N"], - [9855, 9855, "W"], - [9856, 9874, "N"], - [9875, 9875, "W"], - [9876, 9885, "N"], - [9886, 9887, "A"], - [9888, 9888, "N"], - [9889, 9889, "W"], - [9890, 9897, "N"], - [9898, 9899, "W"], - [9900, 9916, "N"], - [9917, 9918, "W"], - [9919, 9919, "A"], - [9920, 9923, "N"], - [9924, 9925, "W"], - [9926, 9933, "A"], - [9934, 9934, "W"], - [9935, 9939, "A"], - [9940, 9940, "W"], - [9941, 9953, "A"], - [9954, 9954, "N"], - [9955, 9955, "A"], - [9956, 9959, "N"], - [9960, 9961, "A"], - [9962, 9962, "W"], - [9963, 9969, "A"], - [9970, 9971, "W"], - [9972, 9972, "A"], - [9973, 9973, "W"], - [9974, 9977, "A"], - [9978, 9978, "W"], - [9979, 9980, "A"], - [9981, 9981, "W"], - [9982, 9983, "A"], - [9984, 9988, "N"], - [9989, 9989, "W"], - [9990, 9993, "N"], - [9994, 9995, "W"], - [9996, 10023, "N"], - [10024, 10024, "W"], - [10025, 10044, "N"], - [10045, 10045, "A"], - [10046, 10059, "N"], - [10060, 10060, "W"], - [10061, 10061, "N"], - [10062, 10062, "W"], - [10063, 10066, "N"], - [10067, 10069, "W"], - [10070, 10070, "N"], - [10071, 10071, "W"], - [10072, 10101, "N"], - [10102, 10111, "A"], - [10112, 10132, "N"], - [10133, 10135, "W"], - [10136, 10159, "N"], - [10160, 10160, "W"], - [10161, 10174, "N"], - [10175, 10175, "W"], - [10176, 10213, "N"], - [10214, 10221, "Na"], - [10222, 10628, "N"], - [10629, 10630, "Na"], - [10631, 11034, "N"], - [11035, 11036, "W"], - [11037, 11087, "N"], - [11088, 11088, "W"], - [11089, 11092, "N"], - [11093, 11093, "W"], - [11094, 11097, "A"], - [11098, 11903, "N"], - [11904, 11929, "W"], - [11930, 11930, "N"], - [11931, 12019, "W"], - [12020, 12031, "N"], - [12032, 12245, "W"], - [12246, 12271, "N"], - [12272, 12283, "W"], - [12284, 12287, "N"], - [12288, 12288, "F"], - [12289, 12350, "W"], - [12351, 12352, "N"], - [12353, 12438, "W"], - [12439, 12440, "N"], - [12441, 12543, "W"], - [12544, 12548, "N"], - [12549, 12591, "W"], - [12592, 12592, "N"], - [12593, 12686, "W"], - [12687, 12687, "N"], - [12688, 12771, "W"], - [12772, 12783, "N"], - [12784, 12830, "W"], - [12831, 12831, "N"], - [12832, 12871, "W"], - [12872, 12879, "A"], - [12880, 19903, "W"], - [19904, 19967, "N"], - [19968, 42124, "W"], - [42125, 42127, "N"], - [42128, 42182, "W"], - [42183, 43359, "N"], - [43360, 43388, "W"], - [43389, 44031, "N"], - [44032, 55203, "W"], - [55204, 57343, "N"], - [57344, 63743, "A"], - [63744, 64255, "W"], - [64256, 65023, "N"], - [65024, 65039, "A"], - [65040, 65049, "W"], - [65050, 65071, "N"], - [65072, 65106, "W"], - [65107, 65107, "N"], - [65108, 65126, "W"], - [65127, 65127, "N"], - [65128, 65131, "W"], - [65132, 65280, "N"], - [65281, 65376, "F"], - [65377, 65470, "H"], - [65471, 65473, "N"], - [65474, 65479, "H"], - [65480, 65481, "N"], - [65482, 65487, "H"], - [65488, 65489, "N"], - [65490, 65495, "H"], - [65496, 65497, "N"], - [65498, 65500, "H"], - [65501, 65503, "N"], - [65504, 65510, "F"], - [65511, 65511, "N"], - [65512, 65518, "H"], - [65519, 65532, "N"], - [65533, 65533, "A"], - [65534, 94175, "N"], - [94176, 94180, "W"], - [94181, 94191, "N"], - [94192, 94193, "W"], - [94194, 94207, "N"], - [94208, 100343, "W"], - [100344, 100351, "N"], - [100352, 101589, "W"], - [101590, 101631, "N"], - [101632, 101640, "W"], - [101641, 110591, "N"], - [110592, 110878, "W"], - [110879, 110927, "N"], - [110928, 110930, "W"], - [110931, 110947, "N"], - [110948, 110951, "W"], - [110952, 110959, "N"], - [110960, 111355, "W"], - [111356, 126979, "N"], - [126980, 126980, "W"], - [126981, 127182, "N"], - [127183, 127183, "W"], - [127184, 127231, "N"], - [127232, 127242, "A"], - [127243, 127247, "N"], - [127248, 127277, "A"], - [127278, 127279, "N"], - [127280, 127337, "A"], - [127338, 127343, "N"], - [127344, 127373, "A"], - [127374, 127374, "W"], - [127375, 127376, "A"], - [127377, 127386, "W"], - [127387, 127404, "A"], - [127405, 127487, "N"], - [127488, 127490, "W"], - [127491, 127503, "N"], - [127504, 127547, "W"], - [127548, 127551, "N"], - [127552, 127560, "W"], - [127561, 127567, "N"], - [127568, 127569, "W"], - [127570, 127583, "N"], - [127584, 127589, "W"], - [127590, 127743, "N"], - [127744, 127776, "W"], - [127777, 127788, "N"], - [127789, 127797, "W"], - [127798, 127798, "N"], - [127799, 127868, "W"], - [127869, 127869, "N"], - [127870, 127891, "W"], - [127892, 127903, "N"], - [127904, 127946, "W"], - [127947, 127950, "N"], - [127951, 127955, "W"], - [127956, 127967, "N"], - [127968, 127984, "W"], - [127985, 127987, "N"], - [127988, 127988, "W"], - [127989, 127991, "N"], - [127992, 128062, "W"], - [128063, 128063, "N"], - [128064, 128064, "W"], - [128065, 128065, "N"], - [128066, 128252, "W"], - [128253, 128254, "N"], - [128255, 128317, "W"], - [128318, 128330, "N"], - [128331, 128334, "W"], - [128335, 128335, "N"], - [128336, 128359, "W"], - [128360, 128377, "N"], - [128378, 128378, "W"], - [128379, 128404, "N"], - [128405, 128406, "W"], - [128407, 128419, "N"], - [128420, 128420, "W"], - [128421, 128506, "N"], - [128507, 128591, "W"], - [128592, 128639, "N"], - [128640, 128709, "W"], - [128710, 128715, "N"], - [128716, 128716, "W"], - [128717, 128719, "N"], - [128720, 128722, "W"], - [128723, 128724, "N"], - [128725, 128727, "W"], - [128728, 128746, "N"], - [128747, 128748, "W"], - [128749, 128755, "N"], - [128756, 128764, "W"], - [128765, 128991, "N"], - [128992, 129003, "W"], - [129004, 129291, "N"], - [129292, 129338, "W"], - [129339, 129339, "N"], - [129340, 129349, "W"], - [129350, 129350, "N"], - [129351, 129400, "W"], - [129401, 129401, "N"], - [129402, 129483, "W"], - [129484, 129484, "N"], - [129485, 129535, "W"], - [129536, 129647, "N"], - [129648, 129652, "W"], - [129653, 129655, "N"], - [129656, 129658, "W"], - [129659, 129663, "N"], - [129664, 129670, "W"], - [129671, 129679, "N"], - [129680, 129704, "W"], - [129705, 129711, "N"], - [129712, 129718, "W"], - [129719, 129727, "N"], - [129728, 129730, "W"], - [129731, 129743, "N"], - [129744, 129750, "W"], - [129751, 131071, "N"], - [131072, 196605, "W"], - [196606, 196607, "N"], - [196608, 262141, "W"], - [262142, 917759, "N"], - [917760, 917999, "A"], - [918e3, 983039, "N"], - [983040, 1048573, "A"], - [1048574, 1048575, "N"], - [1048576, 1114109, "A"], - [1114110, 1114111, "N"] - ]; - var version = "13.0.0"; - function getEAWOfCodePoint(codePoint) { - var min = 0; - var max = defs.length - 1; - while (min !== max) { - var i = min + (max - min >> 1); - var _a = defs[i], start = _a[0], end = _a[1], prop = _a[2]; - if (codePoint < start) { - max = i - 1; - } else if (codePoint > end) { - min = i + 1; - } else { - return prop; - } - } - return defs[min][2]; - } - function getEAW(str, pos) { - if (pos === void 0) { - pos = 0; - } - var codePoint = str.codePointAt(pos); - if (codePoint === void 0) { - return void 0; - } - return getEAWOfCodePoint(codePoint); - } - var defaultWidths = { - N: 1, - Na: 1, - W: 2, - F: 2, - H: 1, - A: 1 - }; - function computeWidth(str, widths) { - var width = 0; - for (var _i = 0, str_1 = str; _i < str_1.length; _i++) { - var char = str_1[_i]; - var eaw = getEAW(char); - width += widths && widths[eaw] || defaultWidths[eaw]; - } - return width; - } - exports.computeWidth = computeWidth; - exports.eawVersion = version; - exports.getEAW = getEAW; - } -}); - -// node_modules/@tgrosinger/md-advanced-tables/lib/formatter.js -var require_formatter = __commonJS({ - "node_modules/@tgrosinger/md-advanced-tables/lib/formatter.js"(exports) { - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.moveColumn = exports.deleteColumn = exports.insertColumn = exports.moveRow = exports.deleteRow = exports.insertRow = exports.alterAlignment = exports.formatTable = exports.FormatType = exports._weakFormatTable = exports._formatTable = exports._padText = exports._alignText = exports._computeTextWidth = exports.completeTable = exports._extendArray = exports._delimiterText = void 0; - var alignment_1 = require_alignment(); - var table_1 = require_table(); - var table_cell_1 = require_table_cell(); - var table_row_1 = require_table_row(); - var meaw_1 = require_lib(); - var _delimiterText = (alignment, width) => { - const bar = "-".repeat(width); - switch (alignment) { - case alignment_1.Alignment.NONE: - return ` ${bar} `; - case alignment_1.Alignment.LEFT: - return `:${bar} `; - case alignment_1.Alignment.RIGHT: - return ` ${bar}:`; - case alignment_1.Alignment.CENTER: - return `:${bar}:`; - default: - throw new Error("Unknown alignment: " + alignment); - } - }; - exports._delimiterText = _delimiterText; - var _extendArray = (arr, size, callback) => { - const extended = arr.slice(); - for (let i = arr.length; i < size; i++) { - extended.push(callback(i, arr)); - } - return extended; - }; - exports._extendArray = _extendArray; - var completeTable = (table, options) => { - const tableHeight = table.getHeight(); - const tableWidth = table.getWidth(); - if (tableHeight === 0) { - throw new Error("Empty table"); - } - const rows = table.getRows(); - const newRows = []; - const headerRow = rows[0]; - const headerCells = headerRow.getCells(); - newRows.push(new table_row_1.TableRow((0, exports._extendArray)(headerCells, tableWidth, (j) => new table_cell_1.TableCell(j === headerCells.length ? headerRow.marginRight : "")), headerRow.marginLeft, headerCells.length < tableWidth ? "" : headerRow.marginRight)); - const delimiterRow = table.getDelimiterRow(); - if (delimiterRow !== void 0) { - const delimiterCells = delimiterRow.getCells(); - newRows.push(new table_row_1.TableRow((0, exports._extendArray)(delimiterCells, tableWidth, (j) => new table_cell_1.TableCell((0, exports._delimiterText)(alignment_1.Alignment.NONE, j === delimiterCells.length ? Math.max(options.minDelimiterWidth, delimiterRow.marginRight.length - 2) : options.minDelimiterWidth))), delimiterRow.marginLeft, delimiterCells.length < tableWidth ? "" : delimiterRow.marginRight)); - } else { - newRows.push(new table_row_1.TableRow((0, exports._extendArray)([], tableWidth, () => new table_cell_1.TableCell((0, exports._delimiterText)(alignment_1.Alignment.NONE, options.minDelimiterWidth))), "", "")); - } - for (let i = delimiterRow !== void 0 ? 2 : 1; i < tableHeight; i++) { - const row = rows[i]; - const cells = row.getCells(); - newRows.push(new table_row_1.TableRow((0, exports._extendArray)(cells, tableWidth, (j) => new table_cell_1.TableCell(j === cells.length ? row.marginRight : "")), row.marginLeft, cells.length < tableWidth ? "" : row.marginRight)); - } - return { - table: new table_1.Table(newRows), - delimiterInserted: delimiterRow === void 0 - }; - }; - exports.completeTable = completeTable; - var _computeTextWidth = (text, options) => { - const normalized = options.normalize ? text.normalize("NFC") : text; - let w = 0; - for (const char of normalized) { - if (options.wideChars.has(char)) { - w += 2; - continue; - } - if (options.narrowChars.has(char)) { - w += 1; - continue; - } - switch ((0, meaw_1.getEAW)(char)) { - case "F": - case "W": - w += 2; - break; - case "A": - w += options.ambiguousAsWide ? 2 : 1; - break; - default: - w += 1; - } - } - return w; - }; - exports._computeTextWidth = _computeTextWidth; - var _alignText = (text, width, alignment, options) => { - const space = width - (0, exports._computeTextWidth)(text, options); - if (space < 0) { - return text; - } - switch (alignment) { - case alignment_1.Alignment.NONE: - throw new Error("Unexpected default alignment"); - case alignment_1.Alignment.LEFT: - return text + " ".repeat(space); - case alignment_1.Alignment.RIGHT: - return " ".repeat(space) + text; - case alignment_1.Alignment.CENTER: - return " ".repeat(Math.floor(space / 2)) + text + " ".repeat(Math.ceil(space / 2)); - default: - throw new Error("Unknown alignment: " + alignment); - } - }; - exports._alignText = _alignText; - var _padText = (text) => ` ${text} `; - exports._padText = _padText; - var _formatTable = (table, options) => { - const tableHeight = table.getHeight(); - const tableWidth = table.getWidth(); - if (tableHeight === 0) { - return { - table, - marginLeft: "" - }; - } - const marginLeft = table.getRows()[0].marginLeft; - if (tableWidth === 0) { - const rows2 = new Array(tableHeight).fill(new table_row_1.TableRow([], marginLeft, "")); - return { - table: new table_1.Table(rows2), - marginLeft - }; - } - const delimiterRow = table.getDelimiterRow(); - const columnWidths = new Array(tableWidth).fill(0); - if (delimiterRow !== void 0) { - const delimiterRowWidth = delimiterRow.getWidth(); - for (let j = 0; j < delimiterRowWidth; j++) { - columnWidths[j] = options.minDelimiterWidth; - } - } - for (let i = 0; i < tableHeight; i++) { - if (delimiterRow !== void 0 && i === 1) { - continue; - } - const row = table.getRows()[i]; - const rowWidth = row.getWidth(); - for (let j = 0; j < rowWidth; j++) { - columnWidths[j] = Math.max(columnWidths[j], (0, exports._computeTextWidth)(row.getCellAt(j).content, options.textWidthOptions)); - } - } - const alignments = delimiterRow !== void 0 ? (0, exports._extendArray)( - delimiterRow.getCells().map((cell) => cell.getAlignment()), - tableWidth, - // Safe conversion because DefaultAlignment is a subset of Alignment - () => options.defaultAlignment - ) : new Array(tableWidth).fill(options.defaultAlignment); - const rows = []; - const headerRow = table.getRows()[0]; - rows.push(new table_row_1.TableRow(headerRow.getCells().map((cell, j) => new table_cell_1.TableCell((0, exports._padText)((0, exports._alignText)(cell.content, columnWidths[j], options.headerAlignment === alignment_1.HeaderAlignment.FOLLOW ? alignments[j] === alignment_1.Alignment.NONE ? options.defaultAlignment : alignments[j] : options.headerAlignment, options.textWidthOptions)))), marginLeft, "")); - if (delimiterRow !== void 0) { - rows.push(new table_row_1.TableRow(delimiterRow.getCells().map((cell, j) => new table_cell_1.TableCell((0, exports._delimiterText)(alignments[j], columnWidths[j]))), marginLeft, "")); - } - for (let i = delimiterRow !== void 0 ? 2 : 1; i < tableHeight; i++) { - const row = table.getRows()[i]; - rows.push(new table_row_1.TableRow(row.getCells().map((cell, j) => new table_cell_1.TableCell((0, exports._padText)((0, exports._alignText)(cell.content, columnWidths[j], alignments[j] === alignment_1.Alignment.NONE ? options.defaultAlignment : alignments[j], options.textWidthOptions)))), marginLeft, "")); - } - return { - table: new table_1.Table(rows), - marginLeft - }; - }; - exports._formatTable = _formatTable; - var _weakFormatTable = (table, options) => { - const tableHeight = table.getHeight(); - const tableWidth = table.getWidth(); - if (tableHeight === 0) { - return { - table, - marginLeft: "" - }; - } - const marginLeft = table.getRows()[0].marginLeft; - if (tableWidth === 0) { - const rows2 = new Array(tableHeight).fill(new table_row_1.TableRow([], marginLeft, "")); - return { - table: new table_1.Table(rows2), - marginLeft - }; - } - const delimiterRow = table.getDelimiterRow(); - const rows = []; - const headerRow = table.getRows()[0]; - rows.push(new table_row_1.TableRow(headerRow.getCells().map((cell) => new table_cell_1.TableCell((0, exports._padText)(cell.content))), marginLeft, "")); - if (delimiterRow !== void 0) { - rows.push(new table_row_1.TableRow(delimiterRow.getCells().map((cell) => new table_cell_1.TableCell((0, exports._delimiterText)(cell.getAlignment(), options.minDelimiterWidth))), marginLeft, "")); - } - for (let i = delimiterRow !== void 0 ? 2 : 1; i < tableHeight; i++) { - const row = table.getRows()[i]; - rows.push(new table_row_1.TableRow(row.getCells().map((cell) => new table_cell_1.TableCell((0, exports._padText)(cell.content))), marginLeft, "")); - } - return { - table: new table_1.Table(rows), - marginLeft - }; - }; - exports._weakFormatTable = _weakFormatTable; - var FormatType3; - (function(FormatType4) { - FormatType4["NORMAL"] = "normal"; - FormatType4["WEAK"] = "weak"; - })(FormatType3 || (exports.FormatType = FormatType3 = {})); - var formatTable = (table, options) => { - switch (options.formatType) { - case FormatType3.NORMAL: - return (0, exports._formatTable)(table, options); - case FormatType3.WEAK: - return (0, exports._weakFormatTable)(table, options); - default: - throw new Error("Unknown format type: " + options.formatType); - } - }; - exports.formatTable = formatTable; - var alterAlignment = (table, columnIndex, alignment, options) => { - if (table.getHeight() < 1) { - return table; - } - const delimiterRow = table.getRows()[1]; - if (columnIndex < 0 || delimiterRow.getWidth() - 1 < columnIndex) { - return table; - } - const delimiterCells = delimiterRow.getCells(); - delimiterCells[columnIndex] = new table_cell_1.TableCell((0, exports._delimiterText)(alignment, options.minDelimiterWidth)); - const rows = table.getRows(); - rows[1] = new table_row_1.TableRow(delimiterCells, delimiterRow.marginLeft, delimiterRow.marginRight); - return new table_1.Table(rows); - }; - exports.alterAlignment = alterAlignment; - var insertRow = (table, rowIndex, row) => { - const rows = table.getRows(); - rows.splice(Math.max(rowIndex, 2), 0, row); - return new table_1.Table(rows); - }; - exports.insertRow = insertRow; - var deleteRow = (table, rowIndex) => { - if (rowIndex === 1) { - return table; - } - const rows = table.getRows(); - if (rowIndex === 0) { - const headerRow = rows[0]; - rows[0] = new table_row_1.TableRow(new Array(headerRow.getWidth()).fill(new table_cell_1.TableCell("")), headerRow.marginLeft, headerRow.marginRight); - } else { - rows.splice(rowIndex, 1); - } - return new table_1.Table(rows); - }; - exports.deleteRow = deleteRow; - var moveRow = (table, rowIndex, destIndex) => { - if (rowIndex <= 1 || destIndex <= 1 || rowIndex === destIndex) { - return table; - } - const rows = table.getRows(); - const row = rows[rowIndex]; - rows.splice(rowIndex, 1); - rows.splice(destIndex, 0, row); - return new table_1.Table(rows); - }; - exports.moveRow = moveRow; - var insertColumn = (table, columnIndex, column, options) => { - const rows = table.getRows(); - for (let i = 0; i < rows.length; i++) { - const row = rows[i]; - const cells = rows[i].getCells(); - const cell = i === 1 ? new table_cell_1.TableCell((0, exports._delimiterText)(alignment_1.Alignment.NONE, options.minDelimiterWidth)) : column[i > 1 ? i - 1 : i]; - cells.splice(columnIndex, 0, cell); - rows[i] = new table_row_1.TableRow(cells, row.marginLeft, row.marginRight); - } - return new table_1.Table(rows); - }; - exports.insertColumn = insertColumn; - var deleteColumn = (table, columnIndex, options) => { - const rows = table.getRows(); - for (let i = 0; i < rows.length; i++) { - const row = rows[i]; - let cells = row.getCells(); - if (cells.length <= 1) { - cells = [ - new table_cell_1.TableCell(i === 1 ? (0, exports._delimiterText)(alignment_1.Alignment.NONE, options.minDelimiterWidth) : "") - ]; - } else { - cells.splice(columnIndex, 1); - } - rows[i] = new table_row_1.TableRow(cells, row.marginLeft, row.marginRight); - } - return new table_1.Table(rows); - }; - exports.deleteColumn = deleteColumn; - var moveColumn = (table, columnIndex, destIndex) => { - if (columnIndex === destIndex) { - return table; - } - const rows = table.getRows(); - for (let i = 0; i < rows.length; i++) { - const row = rows[i]; - const cells = row.getCells(); - const cell = cells[columnIndex]; - cells.splice(columnIndex, 1); - cells.splice(destIndex, 0, cell); - rows[i] = new table_row_1.TableRow(cells, row.marginLeft, row.marginRight); - } - return new table_1.Table(rows); - }; - exports.moveColumn = moveColumn; - } -}); - -// node_modules/@tgrosinger/md-advanced-tables/lib/edit-script.js -var require_edit_script = __commonJS({ - "node_modules/@tgrosinger/md-advanced-tables/lib/edit-script.js"(exports) { - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.shortestEditScript = exports.applyEditScript = exports._applyCommand = exports.Delete = exports.Insert = void 0; - var Insert = class { - /** - * Creats a new `Insert` object. - * - * @param row - Row index, starts from `0`. - * @param line - A string to be inserted at the row. - */ - constructor(row, line) { - this.row = row; - this.line = line; - } - }; - exports.Insert = Insert; - var Delete = class { - /** - * Creates a new `Delete` object. - * - * @param row - Row index, starts from `0`. - */ - constructor(row) { - this.row = row; - } - }; - exports.Delete = Delete; - var _applyCommand = (textEditor, command, rowOffset) => { - if (command instanceof Insert) { - textEditor.insertLine(rowOffset + command.row, command.line); - } else if (command instanceof Delete) { - textEditor.deleteLine(rowOffset + command.row); - } else { - throw new Error("Unknown command"); - } - }; - exports._applyCommand = _applyCommand; - var applyEditScript = (textEditor, script, rowOffset) => { - for (const command of script) { - (0, exports._applyCommand)(textEditor, command, rowOffset); - } - }; - exports.applyEditScript = applyEditScript; - var IList = class { - get car() { - throw new Error("Not implemented"); - } - get cdr() { - throw new Error("Not implemented"); - } - isEmpty() { - throw new Error("Not implemented"); - } - unshift(value) { - return new Cons(value, this); - } - toArray() { - const arr = []; - let rest = this; - while (!rest.isEmpty()) { - arr.push(rest.car); - rest = rest.cdr; - } - return arr; - } - }; - var Nil = class extends IList { - constructor() { - super(); - } - get car() { - throw new Error("Empty list"); - } - get cdr() { - throw new Error("Empty list"); - } - isEmpty() { - return true; - } - }; - var Cons = class extends IList { - constructor(car, cdr) { - super(); - this._car = car; - this._cdr = cdr; - } - get car() { - return this._car; - } - get cdr() { - return this._cdr; - } - isEmpty() { - return false; - } - }; - var shortestEditScript = (from, to, limit = -1) => { - const fromLen = from.length; - const toLen = to.length; - const maxd = limit >= 0 ? Math.min(limit, fromLen + toLen) : fromLen + toLen; - const mem = new Array(Math.min(maxd, fromLen) + Math.min(maxd, toLen) + 1); - const offset = Math.min(maxd, fromLen); - for (let d = 0; d <= maxd; d++) { - const mink = d <= fromLen ? -d : d - 2 * fromLen; - const maxk = d <= toLen ? d : -d + 2 * toLen; - for (let k = mink; k <= maxk; k += 2) { - let i; - let script; - if (d === 0) { - i = 0; - script = new Nil(); - } else if (k === -d) { - i = mem[offset + k + 1].i + 1; - script = mem[offset + k + 1].script.unshift(new Delete(i + k)); - } else if (k === d) { - i = mem[offset + k - 1].i; - script = mem[offset + k - 1].script.unshift(new Insert(i + k - 1, to[i + k - 1])); - } else { - const vi = mem[offset + k + 1].i + 1; - const hi = mem[offset + k - 1].i; - if (vi > hi) { - i = vi; - script = mem[offset + k + 1].script.unshift(new Delete(i + k)); - } else { - i = hi; - script = mem[offset + k - 1].script.unshift(new Insert(i + k - 1, to[i + k - 1])); - } - } - while (i < fromLen && i + k < toLen && from[i] === to[i + k]) { - i += 1; - } - if (k === toLen - fromLen && i === fromLen) { - return script.toArray().reverse(); - } - mem[offset + k] = { i, script }; - } - } - return void 0; - }; - exports.shortestEditScript = shortestEditScript; - } -}); - -// node_modules/@tgrosinger/md-advanced-tables/lib/text-editor.js -var require_text_editor = __commonJS({ - "node_modules/@tgrosinger/md-advanced-tables/lib/text-editor.js"(exports) { - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.ITextEditor = void 0; - var ITextEditor = class { - /** - * Gets the current cursor position. - * - * @returns A point object that represents the cursor position. - */ - getCursorPosition() { - throw new Error("Not implemented: getCursorPosition"); - } - /** - * Sets the cursor position to a specified one. - */ - setCursorPosition(pos) { - throw new Error("Not implemented: setCursorPosition"); - } - /** - * Sets the selection range. - * This method also expects the cursor position to be moved as the end of the selection range. - */ - setSelectionRange(range) { - throw new Error("Not implemented: setSelectionRange"); - } - /** - * Gets the last row index of the text editor. - */ - getLastRow() { - throw new Error("Not implemented: getLastRow"); - } - /** - * Checks if the editor accepts a table at a row to be editted. - * It should return `false` if, for example, the row is in a code block (not Markdown). - * - * @param row - A row index in the text editor. - * @returns `true` if the table at the row can be editted. - */ - acceptsTableEdit(row) { - throw new Error("Not implemented: acceptsTableEdit"); - } - /** - * Gets a line string at a row. - * - * @param row - Row index, starts from `0`. - * @returns The line at the specified row. - * The line must not contain an EOL like `"\n"` or `"\r"`. - */ - getLine(row) { - throw new Error("Not implemented: getLine"); - } - /** - * Inserts a line at a specified row. - * - * @param row - Row index, starts from `0`. - * @param line - A string to be inserted. - * This must not contain an EOL like `"\n"` or `"\r"`. - */ - insertLine(row, line) { - throw new Error("Not implemented: insertLine"); - } - /** - * Deletes a line at a specified row. - * - * @param row - Row index, starts from `0`. - */ - deleteLine(row) { - throw new Error("Not implemented: deleteLine"); - } - /** - * Replace lines in a specified range. - * - * @param startRow - Start row index, starts from `0`. - * @param endRow - End row index. - * Lines from `startRow` to `endRow - 1` is replaced. - * @param lines - An array of string. - * Each strings must not contain an EOL like `"\n"` or `"\r"`. - */ - replaceLines(startRow, endRow, lines) { - throw new Error("Not implemented: replaceLines"); - } - /** - * Batches multiple operations as a single undo/redo step. - * - * @param func - A callback function that executes some operations on the text editor. - */ - transact(func) { - throw new Error("Not implemented: transact"); - } - }; - exports.ITextEditor = ITextEditor; - } -}); - -// node_modules/@tgrosinger/md-advanced-tables/lib/options.js -var require_options = __commonJS({ - "node_modules/@tgrosinger/md-advanced-tables/lib/options.js"(exports) { - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.defaultOptions = exports.optionsWithDefaults = void 0; - var alignment_1 = require_alignment(); - var formatter_1 = require_formatter(); - var DEFAULT_TEXT_WIDTH_OPTIONS = { - normalize: true, - wideChars: /* @__PURE__ */ new Set(), - narrowChars: /* @__PURE__ */ new Set(), - ambiguousAsWide: false - }; - var DEFAULT_OPTIONS = { - leftMarginChars: /* @__PURE__ */ new Set(), - formatType: formatter_1.FormatType.NORMAL, - minDelimiterWidth: 3, - defaultAlignment: alignment_1.DefaultAlignment.LEFT, - headerAlignment: alignment_1.HeaderAlignment.FOLLOW, - smartCursor: false - }; - var optionsWithDefaults2 = (options) => Object.assign(Object.assign(Object.assign({}, DEFAULT_OPTIONS), options), { textWidthOptions: options.textWidthOptions ? Object.assign(Object.assign({}, DEFAULT_TEXT_WIDTH_OPTIONS), options.textWidthOptions) : DEFAULT_TEXT_WIDTH_OPTIONS }); - exports.optionsWithDefaults = optionsWithDefaults2; - exports.defaultOptions = (0, exports.optionsWithDefaults)({}); - } -}); - -// node_modules/@tgrosinger/md-advanced-tables/lib/table-editor.js -var require_table_editor = __commonJS({ - "node_modules/@tgrosinger/md-advanced-tables/lib/table-editor.js"(exports) { - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.TableEditor = exports._computeNewOffset = exports._createIsTableFormulaRegex = exports._createIsTableRowRegex = exports.SortOrder = void 0; - var edit_script_1 = require_edit_script(); - var focus_1 = require_focus(); - var formatter_1 = require_formatter(); - var parser_1 = require_parser(); - var point_1 = require_point(); - var range_1 = require_range(); - var table_1 = require_table(); - var table_cell_1 = require_table_cell(); - var table_row_1 = require_table_row(); - var SortOrder2; - (function(SortOrder3) { - SortOrder3["Ascending"] = "ascending"; - SortOrder3["Descending"] = "descending"; - })(SortOrder2 || (exports.SortOrder = SortOrder2 = {})); - var _createIsTableRowRegex = (leftMarginChars) => new RegExp(`^${(0, parser_1.marginRegexSrc)(leftMarginChars)}\\|`, "u"); - exports._createIsTableRowRegex = _createIsTableRowRegex; - var _createIsTableFormulaRegex = (leftMarginChars) => new RegExp(`^${(0, parser_1.marginRegexSrc)(leftMarginChars)}$`, "u"); - exports._createIsTableFormulaRegex = _createIsTableFormulaRegex; - var _computeNewOffset = (focus, table, formatted, moved) => { - if (moved) { - const formattedFocusedCell2 = formatted.table.getFocusedCell(focus); - if (formattedFocusedCell2 !== void 0) { - return formattedFocusedCell2.computeRawOffset(0); - } - return focus.column < 0 ? formatted.marginLeft.length : 0; - } - const focusedCell = table.getFocusedCell(focus); - const formattedFocusedCell = formatted.table.getFocusedCell(focus); - if (focusedCell !== void 0 && formattedFocusedCell !== void 0) { - const contentOffset = Math.min(focusedCell.computeContentOffset(focus.offset), formattedFocusedCell.content.length); - return formattedFocusedCell.computeRawOffset(contentOffset); - } - return focus.column < 0 ? formatted.marginLeft.length : 0; - }; - exports._computeNewOffset = _computeNewOffset; - var TableEditor2 = class { - /** - * Creates a new table editor instance. - * - * @param textEditor - A text editor interface. - */ - constructor(textEditor) { - this._textEditor = textEditor; - this._scActive = false; - } - /** - * Resets the smart cursor. - * Call this method when the table editor is inactivated. - */ - resetSmartCursor() { - this._scActive = false; - } - /** - * Checks if the cursor is in a table row. Returns false if the cursor is in a - * table formula row (see cursorIsInTableFormula). - * This is useful to check whether the table editor should be activated or not. - * - * @returns `true` if the cursor is in a table row. - */ - cursorIsInTable(options) { - const re = (0, exports._createIsTableRowRegex)(options.leftMarginChars); - const pos = this._textEditor.getCursorPosition(); - return this._textEditor.acceptsTableEdit(pos.row) && re.test(this._textEditor.getLine(pos.row)); - } - /** - * Checks if the cursor is in a formula row below a table. - * This is useful to check whether the table editor should be activated or not. - * - * @returns `true` if the cursor is in a formula row. - */ - cursorIsInTableFormula(options) { - const formulaRe = (0, exports._createIsTableFormulaRegex)(options.leftMarginChars); - const pos = this._textEditor.getCursorPosition(); - return this._textEditor.acceptsTableEdit(pos.row) && formulaRe.test(this._textEditor.getLine(pos.row)); - } - /** - * Finds a table under the current cursor position. - * - * @returns undefined if there is no table or the determined focus is invalid. - */ - _findTable(options) { - const re = (0, exports._createIsTableRowRegex)(options.leftMarginChars); - const formulaRe = (0, exports._createIsTableFormulaRegex)(options.leftMarginChars); - let pos = this._textEditor.getCursorPosition(); - const lastRow = this._textEditor.getLastRow(); - const lines = []; - const formulaLines = []; - let startRow = pos.row; - let endRow = pos.row; - { - let line = this._textEditor.getLine(pos.row); - while (formulaRe.test(line) && pos.row >= 0) { - pos = new point_1.Point(pos.row - 1, pos.column); - endRow--; - line = this._textEditor.getLine(pos.row); - } - } - { - const line = this._textEditor.getLine(pos.row); - if (!this._textEditor.acceptsTableEdit(pos.row) || !re.test(line)) { - return void 0; - } - lines.push(line); - } - for (let row = pos.row - 1; row >= 0; row--) { - const line = this._textEditor.getLine(row); - if (!this._textEditor.acceptsTableEdit(row) || !re.test(line)) { - break; - } - lines.unshift(line); - startRow = row; - } - for (let row = pos.row + 1; row <= lastRow; row++) { - const line = this._textEditor.getLine(row); - if (!this._textEditor.acceptsTableEdit(row) || !re.test(line)) { - break; - } - lines.push(line); - endRow = row; - } - for (let row = endRow + 1; row <= lastRow; row++) { - const line = this._textEditor.getLine(row); - if (!this._textEditor.acceptsTableEdit(row) || !formulaRe.test(line)) { - break; - } - formulaLines.push(line); - } - const range = new range_1.Range(new point_1.Point(startRow, 0), new point_1.Point(endRow, lines[lines.length - 1].length)); - const table = (0, parser_1.readTable)(lines, options); - const focus = table.focusOfPosition(pos, startRow); - if (focus === void 0) { - return void 0; - } - return { range, lines, formulaLines, table, focus }; - } - /** - * Finds a table and does an operation with it. - * - * @private - * @param func - A function that does some operation on table information obtained by - * {@link TableEditor#_findTable}. - */ - _withTable(options, func) { - const info = this._findTable(options); - if (info === void 0) { - return; - } - return func(info); - } - /** - * Updates lines in a given range in the text editor. - * - * @private - * @param startRow - Start row index, starts from `0`. - * @param endRow - End row index. - * Lines from `startRow` to `endRow - 1` are replaced. - * @param newLines - New lines. - * @param [oldLines=undefined] - Old lines to be replaced. - */ - _updateLines(startRow, endRow, newLines, oldLines = void 0) { - if (oldLines !== void 0) { - const ses = (0, edit_script_1.shortestEditScript)(oldLines, newLines, 3); - if (ses !== void 0) { - (0, edit_script_1.applyEditScript)(this._textEditor, ses, startRow); - return; - } - } - this._textEditor.replaceLines(startRow, endRow, newLines); - } - /** - * Moves the cursor position to the focused cell, - * - * @private - * @param startRow - Row index where the table starts in the text editor. - * @param table - A table. - * @param focus - A focus to which the cursor will be moved. - */ - _moveToFocus(startRow, table, focus) { - const pos = table.positionOfFocus(focus, startRow); - if (pos !== void 0) { - this._textEditor.setCursorPosition(pos); - } - } - /** - * Selects the focused cell. - * If the cell has no content to be selected, then just moves the cursor position. - * - * @private - * @param startRow - Row index where the table starts in the text editor. - * @param table - A table. - * @param focus - A focus to be selected. - */ - _selectFocus(startRow, table, focus) { - const range = table.selectionRangeOfFocus(focus, startRow); - if (range !== void 0) { - this._textEditor.setSelectionRange(range); - } else { - this._moveToFocus(startRow, table, focus); - } - } - /** - * Formats the table under the cursor. - */ - format(options) { - this.withCompletedTable(options, ({ range, lines, table, focus }) => { - const newFocus = focus; - this._textEditor.transact(() => { - this._updateLines(range.start.row, range.end.row + 1, table.toLines(), lines); - this._moveToFocus(range.start.row, table, newFocus); - }); - }); - } - /** - * Formats and escapes from the table. - */ - escape(options) { - this._withTable(options, ({ range, lines, table, focus }) => { - const completed = (0, formatter_1.completeTable)(table, options); - const formatted = (0, formatter_1.formatTable)(completed.table, options); - const newRow = range.end.row + (completed.delimiterInserted ? 2 : 1); - this._textEditor.transact(() => { - this._updateLines(range.start.row, range.end.row + 1, formatted.table.toLines(), lines); - let newPos; - if (newRow > this._textEditor.getLastRow()) { - this._textEditor.insertLine(newRow, ""); - newPos = new point_1.Point(newRow, 0); - } else { - const re = new RegExp(`^${(0, parser_1.marginRegexSrc)(options.leftMarginChars)}`, "u"); - const nextLine = this._textEditor.getLine(newRow); - const margin = re.exec(nextLine)[0]; - newPos = new point_1.Point(newRow, margin.length); - } - this._textEditor.setCursorPosition(newPos); - }); - this.resetSmartCursor(); - }); - } - /** - * Alters the alignment of the focused column. - */ - alignColumn(alignment, options) { - this.withCompletedTable(options, ({ range, lines, table, focus }) => { - let newFocus = focus; - let altered = table; - if (0 <= newFocus.column && newFocus.column <= altered.getHeaderWidth() - 1) { - altered = (0, formatter_1.alterAlignment)(table, newFocus.column, alignment, options); - } - const formatted = (0, formatter_1.formatTable)(altered, options); - newFocus = newFocus.setOffset((0, exports._computeNewOffset)(newFocus, table, formatted, false)); - this._textEditor.transact(() => { - this._updateLines(range.start.row, range.end.row + 1, formatted.table.toLines(), lines); - this._moveToFocus(range.start.row, formatted.table, newFocus); - }); - }); - } - /** - * Selects the focused cell content. - */ - selectCell(options) { - this.withCompletedTable(options, ({ range, lines, table, focus }) => { - const newFocus = focus; - this._textEditor.transact(() => { - this._updateLines(range.start.row, range.end.row + 1, table.toLines(), lines); - this._selectFocus(range.start.row, table, newFocus); - }); - }); - } - /** - * Moves the focus to another cell. - * - * @param rowOffset - Offset in row. - * @param columnOffset - Offset in column. - */ - moveFocus(rowOffset, columnOffset, options) { - this.withCompletedTable(options, ({ range, lines, table, focus }) => { - let newFocus = focus; - const startFocus = newFocus; - if (rowOffset !== 0) { - const height = table.getHeight(); - const skip = newFocus.row < 1 && newFocus.row + rowOffset >= 1 ? 1 : newFocus.row > 1 && newFocus.row + rowOffset <= 1 ? -1 : 0; - newFocus = newFocus.setRow(Math.min(Math.max(newFocus.row + rowOffset + skip, 0), height <= 2 ? 0 : height - 1)); - } - if (columnOffset !== 0) { - const width = table.getHeaderWidth(); - if (!(newFocus.column < 0 && columnOffset < 0) && !(newFocus.column > width - 1 && columnOffset > 0)) { - newFocus = newFocus.setColumn(Math.min(Math.max(newFocus.column + columnOffset, 0), width - 1)); - } - } - const moved = !newFocus.posEquals(startFocus); - const formatted = (0, formatter_1.formatTable)(table, options); - newFocus = newFocus.setOffset((0, exports._computeNewOffset)(newFocus, table, formatted, moved)); - this._textEditor.transact(() => { - this._updateLines(range.start.row, range.end.row + 1, formatted.table.toLines(), lines); - if (moved) { - this._selectFocus(range.start.row, formatted.table, newFocus); - } else { - this._moveToFocus(range.start.row, formatted.table, newFocus); - } - }); - if (moved) { - this.resetSmartCursor(); - } - }); - } - /** - * Moves the focus to the next cell. - */ - nextCell(options) { - this._withTable(options, ({ range, lines, table, focus }) => { - const focusMoved = this._scTablePos !== void 0 && !range.start.equals(this._scTablePos) || this._scLastFocus !== void 0 && !focus.posEquals(this._scLastFocus); - if (this._scActive && focusMoved) { - this.resetSmartCursor(); - } - let newFocus = focus; - const completed = (0, formatter_1.completeTable)(table, options); - if (completed.delimiterInserted && newFocus.row > 0) { - newFocus = newFocus.setRow(newFocus.row + 1); - } - const startFocus = newFocus; - let altered = completed.table; - if (newFocus.row === 1) { - newFocus = newFocus.setRow(2); - if (options.smartCursor) { - if (newFocus.column < 0 || altered.getHeaderWidth() - 1 < newFocus.column) { - newFocus = newFocus.setColumn(0); - } - } else { - newFocus = newFocus.setColumn(0); - } - if (newFocus.row > altered.getHeight() - 1) { - const row = new Array(altered.getHeaderWidth()).fill(new table_cell_1.TableCell("")); - altered = (0, formatter_1.insertRow)(altered, altered.getHeight(), new table_row_1.TableRow(row, "", "")); - } - } else { - if (newFocus.column > altered.getHeaderWidth() - 1) { - const column = new Array(altered.getHeight() - 1).fill(new table_cell_1.TableCell("")); - altered = (0, formatter_1.insertColumn)(altered, altered.getHeaderWidth(), column, options); - } - newFocus = newFocus.setColumn(newFocus.column + 1); - } - const formatted = (0, formatter_1.formatTable)(altered, options); - newFocus = newFocus.setOffset((0, exports._computeNewOffset)(newFocus, altered, formatted, true)); - const newLines = formatted.table.toLines(); - if (newFocus.column > formatted.table.getHeaderWidth() - 1) { - newLines[newFocus.row] += " "; - newFocus = newFocus.setOffset(1); - } - this._textEditor.transact(() => { - this._updateLines(range.start.row, range.end.row + 1, newLines, lines); - this._selectFocus(range.start.row, formatted.table, newFocus); - }); - if (options.smartCursor) { - if (!this._scActive) { - this._scActive = true; - this._scTablePos = range.start; - if (startFocus.column < 0 || formatted.table.getHeaderWidth() - 1 < startFocus.column) { - this._scStartFocus = new focus_1.Focus(startFocus.row, 0, 0); - } else { - this._scStartFocus = startFocus; - } - } - this._scLastFocus = newFocus; - } - }); - } - /** - * Moves the focus to the previous cell. - */ - previousCell(options) { - this.withCompletedTable(options, ({ range, lines, table, focus }) => { - let newFocus = focus; - const startFocus = newFocus; - if (newFocus.row === 0) { - if (newFocus.column > 0) { - newFocus = newFocus.setColumn(newFocus.column - 1); - } - } else if (newFocus.row === 1) { - newFocus = new focus_1.Focus(0, table.getHeaderWidth() - 1, newFocus.offset); - } else { - if (newFocus.column > 0) { - newFocus = newFocus.setColumn(newFocus.column - 1); - } else { - newFocus = new focus_1.Focus(newFocus.row === 2 ? 0 : newFocus.row - 1, table.getHeaderWidth() - 1, newFocus.offset); - } - } - const moved = !newFocus.posEquals(startFocus); - const formatted = (0, formatter_1.formatTable)(table, options); - newFocus = newFocus.setOffset((0, exports._computeNewOffset)(newFocus, table, formatted, moved)); - this._textEditor.transact(() => { - this._updateLines(range.start.row, range.end.row + 1, formatted.table.toLines(), lines); - if (moved) { - this._selectFocus(range.start.row, formatted.table, newFocus); - } else { - this._moveToFocus(range.start.row, formatted.table, newFocus); - } - }); - if (moved) { - this.resetSmartCursor(); - } - }); - } - /** - * Moves the focus to the next row. - */ - nextRow(options) { - this._withTable(options, ({ range, lines, table, focus }) => { - const focusMoved = this._scTablePos !== void 0 && !range.start.equals(this._scTablePos) || this._scLastFocus !== void 0 && !focus.posEquals(this._scLastFocus); - if (this._scActive && focusMoved) { - this.resetSmartCursor(); - } - let newFocus = focus; - const completed = (0, formatter_1.completeTable)(table, options); - if (completed.delimiterInserted && newFocus.row > 0) { - newFocus = newFocus.setRow(newFocus.row + 1); - } - const startFocus = newFocus; - let altered = completed.table; - if (newFocus.row === 0) { - newFocus = newFocus.setRow(2); - } else { - newFocus = newFocus.setRow(newFocus.row + 1); - } - if (options.smartCursor) { - if (this._scActive && this._scStartFocus !== void 0) { - newFocus = newFocus.setColumn(this._scStartFocus.column); - } else if (newFocus.column < 0 || altered.getHeaderWidth() - 1 < newFocus.column) { - newFocus = newFocus.setColumn(0); - } - } else { - newFocus = newFocus.setColumn(0); - } - if (newFocus.row > altered.getHeight() - 1) { - const row = new Array(altered.getHeaderWidth()).fill(new table_cell_1.TableCell("")); - altered = (0, formatter_1.insertRow)(altered, altered.getHeight(), new table_row_1.TableRow(row, "", "")); - } - const formatted = (0, formatter_1.formatTable)(altered, options); - newFocus = newFocus.setOffset((0, exports._computeNewOffset)(newFocus, altered, formatted, true)); - this._textEditor.transact(() => { - this._updateLines(range.start.row, range.end.row + 1, formatted.table.toLines(), lines); - this._selectFocus(range.start.row, formatted.table, newFocus); - }); - if (options.smartCursor) { - if (!this._scActive) { - this._scActive = true; - this._scTablePos = range.start; - if (startFocus.column < 0 || formatted.table.getHeaderWidth() - 1 < startFocus.column) { - this._scStartFocus = new focus_1.Focus(startFocus.row, 0, 0); - } else { - this._scStartFocus = startFocus; - } - } - this._scLastFocus = newFocus; - } - }); - } - /** - * Inserts an empty row at the current focus. - */ - insertRow(options) { - this.withCompletedTable(options, ({ range, lines, formulaLines, table, focus }) => { - let newFocus = focus; - if (newFocus.row <= 1) { - newFocus = newFocus.setRow(2); - } - newFocus = newFocus.setColumn(0); - const row = new Array(table.getHeaderWidth()).fill(new table_cell_1.TableCell("")); - const altered = (0, formatter_1.insertRow)(table, newFocus.row, new table_row_1.TableRow(row, "", "")); - this.formatAndApply(options, range, lines, formulaLines, altered, newFocus); - }); - } - /** - * Deletes a row at the current focus. - */ - deleteRow(options) { - this.withCompletedTable(options, ({ range, lines, formulaLines, table, focus }) => { - let newFocus = focus; - let altered = table; - let moved = false; - if (newFocus.row !== 1) { - altered = (0, formatter_1.deleteRow)(altered, newFocus.row); - moved = true; - if (newFocus.row > altered.getHeight() - 1) { - newFocus = newFocus.setRow(newFocus.row === 2 ? 0 : newFocus.row - 1); - } - } - this.formatAndApply(options, range, lines, formulaLines, altered, newFocus, moved); - }); - } - /** - * Moves the focused row by the specified offset. - * - * @param offset - An offset the row is moved by. - */ - moveRow(offset, options) { - this.withCompletedTable(options, ({ range, lines, formulaLines, table, focus }) => { - let newFocus = focus; - let altered = table; - if (newFocus.row > 1) { - const dest = Math.min(Math.max(newFocus.row + offset, 2), altered.getHeight() - 1); - altered = (0, formatter_1.moveRow)(altered, newFocus.row, dest); - newFocus = newFocus.setRow(dest); - } - this.formatAndApply(options, range, lines, formulaLines, altered, newFocus); - }); - } - evaluateFormulas(options) { - return this.withCompletedTable(options, ({ range, lines, formulaLines, table, focus }) => { - const result = table.applyFormulas(formulaLines); - if (result.isErr()) { - return result.error; - } - const { table: formattedTable, focus: newFocus } = this.formatAndApply(options, range, lines, formulaLines, result.value, focus, false); - }); - } - /** - * Transpose rows and columns of a table by inverting the X and Y axis values. - * @param options - */ - transpose(options) { - this.withCompletedTable(options, ({ range, lines, formulaLines, table, focus }) => { - var _a, _b, _c, _d, _e, _f, _g, _h; - const width = table.getWidth(); - const height = table.getHeight(); - const newRows = new Array(width + 1); - for (let x = 0; x < width + 1; ++x) { - if (x === 0) { - const newRow = new Array(height - 1); - for (let y = 0; y < height; ++y) { - if (y === 0) { - const s = (_b = (_a = table.getCellAt(y, x)) === null || _a === void 0 ? void 0 : _a.content) !== null && _b !== void 0 ? _b : ""; - newRow[y] = new table_cell_1.TableCell(s); - } else if (y === 1) { - continue; - } else if (y > 1) { - const s = (_d = (_c = table.getCellAt(y, x)) === null || _c === void 0 ? void 0 : _c.content) !== null && _d !== void 0 ? _d : ""; - newRow[y - 1] = new table_cell_1.TableCell(s); - } - } - newRows[x] = new table_row_1.TableRow(newRow, "", ""); - } else if (x === 1) { - const newRow = new Array(height - 1); - for (let i = 0; i < height - 1; ++i) { - newRow[i] = new table_cell_1.TableCell(" --- "); - } - newRows[x] = new table_row_1.TableRow(newRow, "", ""); - continue; - } else if (x > 1) { - const newRow = new Array(height - 1); - for (let y = 0; y < height; ++y) { - if (y === 0) { - const s = (_f = (_e = table.getCellAt(y, x - 1)) === null || _e === void 0 ? void 0 : _e.content) !== null && _f !== void 0 ? _f : ""; - newRow[y] = new table_cell_1.TableCell(s); - } else if (y === 1) { - continue; - } else if (y > 1) { - const s = (_h = (_g = table.getCellAt(y, x - 1)) === null || _g === void 0 ? void 0 : _g.content) !== null && _h !== void 0 ? _h : ""; - newRow[y - 1] = new table_cell_1.TableCell(s); - } - } - newRows[x] = new table_row_1.TableRow(newRow, "", ""); - } - } - const newTable = new table_1.Table(newRows); - const { table: formattedTable, focus: newFocus } = this.formatAndApply(options, range, lines, formulaLines, newTable, focus, true); - this._moveToFocus(range.start.row, formattedTable, newFocus); - }); - } - /** - * Sorts rows alphanumerically using the column at the current focus. - * If all cells in the sorting column are numbers, the column is sorted - * numerically. - */ - sortRows(sortOrder, options) { - this.withCompletedTable(options, ({ range, lines, formulaLines, table, focus }) => { - const bodyRows = table.getRows().slice(2); - const isNumber = (s) => /^\s*[-+]?((\d+(\.\d+)?)|(\d+\.)|(\.\d+))([eE][-+]?\d+)?\s*$/.test(s); - const notAllNums = bodyRows.map((row) => { - var _a; - return (_a = row.getCellAt(focus.column)) === null || _a === void 0 ? void 0 : _a.content; - }).some((cell) => cell !== void 0 && cell !== "" && !isNumber(cell)); - bodyRows.sort((rowA, rowB) => { - const cellA = rowA.getCellAt(focus.column); - const cellB = rowB.getCellAt(focus.column); - if (cellA === void 0 || cellA.content === "") { - if (cellB === void 0 || cellB.content === "") { - return 0; - } - return -1; - } else if (cellB === void 0 || cellB.content === "") { - return 1; - } - const contentA = notAllNums ? cellA.content.replace(/[*~_$]/g, "") : parseFloat(cellA.content); - const contentB = notAllNums ? cellB.content.replace(/[*~_$]/g, "") : parseFloat(cellB.content); - if (contentA === contentB) { - return 0; - } else if (contentA === void 0) { - return -1; - } else if (contentB === void 0) { - return 1; - } - return contentA < contentB ? -1 : 1; - }); - if (sortOrder === SortOrder2.Descending) { - bodyRows.reverse(); - } - const allRows = table.getRows().slice(0, 2).concat(bodyRows); - const newTable = new table_1.Table(allRows); - const { table: formattedTable, focus: newFocus } = this.formatAndApply(options, range, lines, formulaLines, newTable, focus, true); - this._moveToFocus(range.start.row, formattedTable, newFocus); - }); - } - /** - * Inserts an empty column at the current focus. - */ - insertColumn(options) { - this.withCompletedTable(options, ({ range, lines, formulaLines, table, focus }) => { - let newFocus = focus; - if (newFocus.row === 1) { - newFocus = newFocus.setRow(0); - } - if (newFocus.column < 0) { - newFocus = newFocus.setColumn(0); - } - const column = new Array(table.getHeight() - 1).fill(new table_cell_1.TableCell("")); - const altered = (0, formatter_1.insertColumn)(table, newFocus.column, column, options); - this.formatAndApply(options, range, lines, formulaLines, altered, newFocus); - }); - } - /** - * Deletes a column at the current focus. - */ - deleteColumn(options) { - this.withCompletedTable(options, ({ range, lines, formulaLines, table, focus }) => { - let newFocus = focus; - if (newFocus.row === 1) { - newFocus = newFocus.setRow(0); - } - let altered = table; - let moved = false; - if (0 <= newFocus.column && newFocus.column <= altered.getHeaderWidth() - 1) { - altered = (0, formatter_1.deleteColumn)(table, newFocus.column, options); - moved = true; - if (newFocus.column > altered.getHeaderWidth() - 1) { - newFocus = newFocus.setColumn(altered.getHeaderWidth() - 1); - } - } - this.formatAndApply(options, range, lines, formulaLines, altered, newFocus, moved); - }); - } - /** - * Moves the focused column by the specified offset. - * - * @param offset - An offset the column is moved by. - */ - moveColumn(offset, options) { - this.withCompletedTable(options, ({ range, lines, formulaLines, table, focus }) => { - let newFocus = focus; - let altered = table; - if (0 <= newFocus.column && newFocus.column <= altered.getHeaderWidth() - 1) { - const dest = Math.min(Math.max(newFocus.column + offset, 0), altered.getHeaderWidth() - 1); - altered = (0, formatter_1.moveColumn)(altered, newFocus.column, dest); - newFocus = newFocus.setColumn(dest); - } - this.formatAndApply(options, range, lines, formulaLines, altered, newFocus); - }); - } - /** - * Formats all the tables in the text editor. - */ - formatAll(options) { - this._textEditor.transact(() => { - const re = (0, exports._createIsTableRowRegex)(options.leftMarginChars); - let pos = this._textEditor.getCursorPosition(); - let lines = []; - let startRow = void 0; - let lastRow = this._textEditor.getLastRow(); - for (let row = 0; row <= lastRow; row++) { - const line = this._textEditor.getLine(row); - if (this._textEditor.acceptsTableEdit(row) && re.test(line)) { - lines.push(line); - if (startRow === void 0) { - startRow = row; - } - } else if (startRow !== void 0) { - const endRow = row - 1; - const range = new range_1.Range(new point_1.Point(startRow, 0), new point_1.Point(endRow, lines[lines.length - 1].length)); - const table = (0, parser_1.readTable)(lines, options); - const focus = table.focusOfPosition(pos, startRow); - let diff; - if (focus !== void 0) { - let newFocus = focus; - const completed = (0, formatter_1.completeTable)(table, options); - if (completed.delimiterInserted && newFocus.row > 0) { - newFocus = newFocus.setRow(newFocus.row + 1); - } - const formatted = (0, formatter_1.formatTable)(completed.table, options); - newFocus = newFocus.setOffset((0, exports._computeNewOffset)(newFocus, completed.table, formatted, false)); - const newLines = formatted.table.toLines(); - this._updateLines(range.start.row, range.end.row + 1, newLines, lines); - diff = newLines.length - lines.length; - pos = formatted.table.positionOfFocus(newFocus, startRow); - } else { - const completed = (0, formatter_1.completeTable)(table, options); - const formatted = (0, formatter_1.formatTable)(completed.table, options); - const newLines = formatted.table.toLines(); - this._updateLines(range.start.row, range.end.row + 1, newLines, lines); - diff = newLines.length - lines.length; - if (pos.row > endRow) { - pos = new point_1.Point(pos.row + diff, pos.column); - } - } - lines = []; - startRow = void 0; - lastRow += diff; - row += diff; - } - } - if (startRow !== void 0) { - const endRow = lastRow; - const range = new range_1.Range(new point_1.Point(startRow, 0), new point_1.Point(endRow, lines[lines.length - 1].length)); - const table = (0, parser_1.readTable)(lines, options); - const focus = table.focusOfPosition(pos, startRow); - let newFocus = focus; - const completed = (0, formatter_1.completeTable)(table, options); - if (completed.delimiterInserted && newFocus.row > 0) { - newFocus = newFocus.setRow(newFocus.row + 1); - } - const formatted = (0, formatter_1.formatTable)(completed.table, options); - newFocus = newFocus.setOffset( - // @ts-expect-error TODO - (0, exports._computeNewOffset)(newFocus, completed.table, formatted, false) - ); - const newLines = formatted.table.toLines(); - this._updateLines(range.start.row, range.end.row + 1, newLines, lines); - pos = formatted.table.positionOfFocus(newFocus, startRow); - } - this._textEditor.setCursorPosition(pos); - }); - } - /** - * Exports the table as a two dimensional string array - */ - exportTable(withtHeaders, options) { - return this.withCompletedTable(options, ({ range, lines, formulaLines, table, focus }) => { - const bodyRows = table.getRows(); - if (bodyRows.length > 0 && !withtHeaders) { - bodyRows.splice(0, 2); - } - return bodyRows.map((row) => row.getCells().map((cell) => cell.content)); - }); - } - /** - * Exports the table as a two dimensional string array - */ - exportCSV(withtHeaders, options) { - const r = this.exportTable(withtHeaders, options); - return !r ? void 0 : r.map((row) => row.join(" ")).join("\n"); - } - /** - * Finds a table, completes it, then does an operation with it. - * - * @param func - A function that does some operation on table information obtained by - * {@link TableEditor#_findTable}. - */ - withCompletedTable(options, func) { - return this._withTable(options, (tableInfo) => { - let newFocus = tableInfo.focus; - const completed = (0, formatter_1.completeTable)(tableInfo.table, options); - if (completed.delimiterInserted && newFocus.row > 0) { - newFocus = newFocus.setRow(newFocus.row + 1); - } - const formatted = (0, formatter_1.formatTable)(completed.table, options); - newFocus = newFocus.setOffset((0, exports._computeNewOffset)(newFocus, completed.table, formatted, false)); - tableInfo.table = formatted.table; - tableInfo.focus = newFocus; - return func(tableInfo); - }); - } - /** - * Formats the table and applies any changes based on the difference between - * originalLines and the newTable. Should generally be the last function call - * in a TableEditor function. - */ - formatAndApply(options, range, originalLines, formulaLines, newTable, newFocus, moved = false) { - const formatted = (0, formatter_1.formatTable)(newTable, options); - newFocus = newFocus.setOffset((0, exports._computeNewOffset)(newFocus, newTable, formatted, moved)); - this._textEditor.transact(() => { - this._updateLines(range.start.row, range.end.row + 1, formatted.table.toLines(), originalLines); - if (moved) { - this._selectFocus(range.start.row, formatted.table, newFocus); - } else { - this._moveToFocus(range.start.row, formatted.table, newFocus); - } - }); - this.resetSmartCursor(); - return { - range, - lines: originalLines, - formulaLines, - table: formatted.table, - focus: newFocus - }; - } - }; - exports.TableEditor = TableEditor2; - } -}); - -// node_modules/@tgrosinger/md-advanced-tables/lib/index.js -var require_lib2 = __commonJS({ - "node_modules/@tgrosinger/md-advanced-tables/lib/index.js"(exports) { - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.SortOrder = exports.TableEditor = exports.optionsWithDefaults = exports.defaultOptions = exports.ITextEditor = exports.shortestEditScript = exports.applyEditScript = exports.Delete = exports.Insert = exports.moveColumn = exports.deleteColumn = exports.insertColumn = exports.moveRow = exports.deleteRow = exports.insertRow = exports.alterAlignment = exports.formatTable = exports.completeTable = exports.FormatType = exports.readTable = exports.Table = exports.TableRow = exports.TableCell = exports.HeaderAlignment = exports.DefaultAlignment = exports.Alignment = exports.Focus = exports.Range = exports.Point = void 0; - var point_1 = require_point(); - Object.defineProperty(exports, "Point", { enumerable: true, get: function() { - return point_1.Point; - } }); - var range_1 = require_range(); - Object.defineProperty(exports, "Range", { enumerable: true, get: function() { - return range_1.Range; - } }); - var focus_1 = require_focus(); - Object.defineProperty(exports, "Focus", { enumerable: true, get: function() { - return focus_1.Focus; - } }); - var alignment_1 = require_alignment(); - Object.defineProperty(exports, "Alignment", { enumerable: true, get: function() { - return alignment_1.Alignment; - } }); - Object.defineProperty(exports, "DefaultAlignment", { enumerable: true, get: function() { - return alignment_1.DefaultAlignment; - } }); - Object.defineProperty(exports, "HeaderAlignment", { enumerable: true, get: function() { - return alignment_1.HeaderAlignment; - } }); - var table_cell_1 = require_table_cell(); - Object.defineProperty(exports, "TableCell", { enumerable: true, get: function() { - return table_cell_1.TableCell; - } }); - var table_row_1 = require_table_row(); - Object.defineProperty(exports, "TableRow", { enumerable: true, get: function() { - return table_row_1.TableRow; - } }); - var table_1 = require_table(); - Object.defineProperty(exports, "Table", { enumerable: true, get: function() { - return table_1.Table; - } }); - var parser_1 = require_parser(); - Object.defineProperty(exports, "readTable", { enumerable: true, get: function() { - return parser_1.readTable; - } }); - var formatter_js_1 = require_formatter(); - Object.defineProperty(exports, "FormatType", { enumerable: true, get: function() { - return formatter_js_1.FormatType; - } }); - Object.defineProperty(exports, "completeTable", { enumerable: true, get: function() { - return formatter_js_1.completeTable; - } }); - Object.defineProperty(exports, "formatTable", { enumerable: true, get: function() { - return formatter_js_1.formatTable; - } }); - Object.defineProperty(exports, "alterAlignment", { enumerable: true, get: function() { - return formatter_js_1.alterAlignment; - } }); - Object.defineProperty(exports, "insertRow", { enumerable: true, get: function() { - return formatter_js_1.insertRow; - } }); - Object.defineProperty(exports, "deleteRow", { enumerable: true, get: function() { - return formatter_js_1.deleteRow; - } }); - Object.defineProperty(exports, "moveRow", { enumerable: true, get: function() { - return formatter_js_1.moveRow; - } }); - Object.defineProperty(exports, "insertColumn", { enumerable: true, get: function() { - return formatter_js_1.insertColumn; - } }); - Object.defineProperty(exports, "deleteColumn", { enumerable: true, get: function() { - return formatter_js_1.deleteColumn; - } }); - Object.defineProperty(exports, "moveColumn", { enumerable: true, get: function() { - return formatter_js_1.moveColumn; - } }); - var edit_script_1 = require_edit_script(); - Object.defineProperty(exports, "Insert", { enumerable: true, get: function() { - return edit_script_1.Insert; - } }); - Object.defineProperty(exports, "Delete", { enumerable: true, get: function() { - return edit_script_1.Delete; - } }); - Object.defineProperty(exports, "applyEditScript", { enumerable: true, get: function() { - return edit_script_1.applyEditScript; - } }); - Object.defineProperty(exports, "shortestEditScript", { enumerable: true, get: function() { - return edit_script_1.shortestEditScript; - } }); - var text_editor_1 = require_text_editor(); - Object.defineProperty(exports, "ITextEditor", { enumerable: true, get: function() { - return text_editor_1.ITextEditor; - } }); - var options_1 = require_options(); - Object.defineProperty(exports, "defaultOptions", { enumerable: true, get: function() { - return options_1.defaultOptions; - } }); - Object.defineProperty(exports, "optionsWithDefaults", { enumerable: true, get: function() { - return options_1.optionsWithDefaults; - } }); - var table_editor_1 = require_table_editor(); - Object.defineProperty(exports, "TableEditor", { enumerable: true, get: function() { - return table_editor_1.TableEditor; - } }); - Object.defineProperty(exports, "SortOrder", { enumerable: true, get: function() { - return table_editor_1.SortOrder; - } }); - } -}); - -// src/main.ts -var main_exports = {}; -__export(main_exports, { - default: () => TableEditorPlugin -}); -module.exports = __toCommonJS(main_exports); - -// src/icons.ts -var import_obsidian = require("obsidian"); -var icons = { - spreadsheet: ` - - -`, - alignLeft: ` - - - - - - - -`, - alignCenter: ` - - - - - - - -`, - alignRight: ` - - - - - -`, - deleteColumn: ` - - - -`, - deleteRow: ` - - - - -`, - insertColumn: ` - - - - - - - -`, - insertRow: ` - - - - - - - -`, - moveColumnLeft: ` - - - - -`, - moveColumnRight: ` - - - - -`, - moveRowDown: ` - - - - -`, - moveRowUp: ` - - - - -`, - transpose: ` - - - - -`, - sortAsc: ` - - - - - - - -`, - sortDesc: ` - - - - - - - -`, - formula: ` - - - -`, - help: ` - - - - -`, - csv: ` - - -`, - arrowenter: ` - - -`, - arrowtab: ` - - -` -}; -var addIcons = () => { - Object.keys(icons).forEach((key) => { - if (key !== "help") { - (0, import_obsidian.addIcon)(key, icons[key]); - } - }); -}; - -// src/settings.ts -var import_md_advanced_tables = __toESM(require_lib2()); -var defaultSettings = { - formatType: import_md_advanced_tables.FormatType.NORMAL, - showRibbonIcon: true, - bindEnter: true, - bindTab: true -}; -var TableEditorPluginSettings = class { - constructor(loadedData) { - const allFields = { ...defaultSettings, ...loadedData }; - this.formatType = allFields.formatType; - this.showRibbonIcon = allFields.showRibbonIcon; - this.bindEnter = allFields.bindEnter; - this.bindTab = allFields.bindTab; - } - asOptions() { - return (0, import_md_advanced_tables.optionsWithDefaults)({ formatType: this.formatType }); - } -}; - -// src/obsidian-text-editor.ts -var import_md_advanced_tables2 = __toESM(require_lib2()); -var ObsidianTextEditor = class { - constructor(app, file, editor) { - this.getCursorPosition = () => { - const position = this.editor.getCursor(); - return new import_md_advanced_tables2.Point(position.line, position.ch); - }; - this.setCursorPosition = (pos) => { - this.editor.setCursor({ line: pos.row, ch: pos.column }); - }; - this.setSelectionRange = (range) => { - this.editor.setSelection( - { line: range.start.row, ch: range.start.column }, - { line: range.end.row, ch: range.end.column } - ); - }; - this.getLastRow = () => this.editor.lastLine(); - this.acceptsTableEdit = (row) => { - const cache = this.app.metadataCache.getFileCache(this.file); - if (!cache.sections) { - return true; - } - const table = cache.sections.find( - (section) => section.position.start.line <= row && section.position.end.line >= row && section.type !== "code" && section.type !== "math" - ); - if (table === void 0) { - return false; - } - const preceedingLineIndex = table.position.start.line; - if (preceedingLineIndex >= 0) { - const preceedingLine = this.getLine(preceedingLineIndex); - if (preceedingLine === "-tx-") { - return false; - } - } - return true; - }; - this.getLine = (row) => this.editor.getLine(row); - this.insertLine = (row, line) => { - if (row > this.getLastRow()) { - this.editor.replaceRange("\n" + line, { line: row, ch: 0 }); - } else { - this.editor.replaceRange(line + "\n", { line: row, ch: 0 }); - } - }; - this.deleteLine = (row) => { - if (row === this.getLastRow()) { - const rowContents = this.getLine(row); - this.editor.replaceRange( - "", - { line: row, ch: 0 }, - { line: row, ch: rowContents.length } - ); - } else { - this.editor.replaceRange( - "", - { line: row, ch: 0 }, - { line: row + 1, ch: 0 } - ); - } - }; - this.replaceLines = (startRow, endRow, lines) => { - const realEndRow = endRow - 1; - const endRowContents = this.editor.getLine(realEndRow); - const endRowFinalIndex = endRowContents.length; - this.editor.replaceRange( - lines.join("\n"), - { line: startRow, ch: 0 }, - { line: realEndRow, ch: endRowFinalIndex } - ); - }; - this.transact = (func) => { - func(); - }; - this.app = app; - this.file = file; - this.editor = editor; - } -}; - -// src/table-editor.ts -var import_md_advanced_tables3 = __toESM(require_lib2()); -var import_obsidian2 = require("obsidian"); -var TableEditor = class { - constructor(app, file, editor, settings) { - this.cursorIsInTableFormula = () => this.mte.cursorIsInTableFormula(this.settings.asOptions()); - this.cursorIsInTable = () => this.mte.cursorIsInTable(this.settings.asOptions()); - this.nextCell = () => { - this.mte.nextCell(this.settings.asOptions()); - }; - this.previousCell = () => { - this.mte.previousCell(this.settings.asOptions()); - }; - this.nextRow = () => { - this.mte.nextRow(this.settings.asOptions()); - }; - this.formatTable = () => { - this.mte.format(this.settings.asOptions()); - }; - this.formatAllTables = () => { - this.mte.formatAll(this.settings.asOptions()); - }; - this.insertColumn = () => { - this.mte.insertColumn(this.settings.asOptions()); - }; - this.insertRow = () => { - this.mte.insertRow(this.settings.asOptions()); - }; - this.leftAlignColumn = () => { - this.mte.alignColumn(import_md_advanced_tables3.Alignment.LEFT, this.settings.asOptions()); - }; - this.centerAlignColumn = () => { - this.mte.alignColumn(import_md_advanced_tables3.Alignment.CENTER, this.settings.asOptions()); - }; - this.rightAlignColumn = () => { - this.mte.alignColumn(import_md_advanced_tables3.Alignment.RIGHT, this.settings.asOptions()); - }; - this.moveColumnLeft = () => { - this.mte.moveColumn(-1, this.settings.asOptions()); - }; - this.moveColumnRight = () => { - this.mte.moveColumn(1, this.settings.asOptions()); - }; - this.moveRowUp = () => { - this.mte.moveRow(-1, this.settings.asOptions()); - }; - this.moveRowDown = () => { - this.mte.moveRow(1, this.settings.asOptions()); - }; - this.deleteColumn = () => { - this.mte.deleteColumn(this.settings.asOptions()); - }; - this.deleteRow = () => { - this.mte.deleteRow(this.settings.asOptions()); - }; - this.sortRowsAsc = () => { - this.mte.sortRows(import_md_advanced_tables3.SortOrder.Ascending, this.settings.asOptions()); - }; - this.sortRowsDesc = () => { - this.mte.sortRows(import_md_advanced_tables3.SortOrder.Descending, this.settings.asOptions()); - }; - this.transpose = () => { - this.mte.transpose(this.settings.asOptions()); - }; - this.escape = () => { - this.mte.escape(this.settings.asOptions()); - }; - this.evaluateFormulas = () => { - const err = this.mte.evaluateFormulas(this.settings.asOptions()); - if (err) { - new import_obsidian2.Notice(err.message); - } - }; - this.exportCSVModal = () => { - new CSVModal(this.app, this.mte, this.settings).open(); - }; - this.app = app; - this.settings = settings; - const ote = new ObsidianTextEditor(app, file, editor); - this.mte = new import_md_advanced_tables3.TableEditor(ote); - } -}; -var CSVModal = class extends import_obsidian2.Modal { - constructor(app, mte, settings) { - super(app); - this.mte = mte; - this.settings = settings; - } - onOpen() { - const { contentEl } = this; - const div = contentEl.createDiv({ - cls: "advanced-tables-csv-export" - }); - const ta = div.createEl("textarea", { - attr: { - readonly: true - } - }); - ta.value = this.mte.exportCSV(true, this.settings.asOptions()); - ta.onClickEvent(() => ta.select()); - const lb = div.createEl("label"); - const cb = lb.createEl("input", { - type: "checkbox", - attr: { - checked: true - } - }); - lb.createSpan().setText("Include table headers"); - cb.onClickEvent(() => { - ta.value = this.mte.exportCSV(cb.checked, this.settings.asOptions()); - }); - } - onClose() { - const { contentEl } = this; - contentEl.empty(); - } -}; - -// src/table-controls-view.ts -var import_obsidian3 = require("obsidian"); -var TableControlsViewType = "advanced-tables-toolbar"; -var TableControlsView = class extends import_obsidian3.ItemView { - constructor(leaf, settings) { - super(leaf); - this.draw = () => { - const container = this.containerEl.children[1]; - const rootEl = document.createElement("div"); - rootEl.addClass("advanced-tables-buttons"); - rootEl.createDiv().createSpan({ cls: "title" }).setText("Advanced Tables"); - const navHeader = rootEl.createDiv({ cls: "nav-header" }); - const rowOneBtns = navHeader.createDiv({ cls: "nav-buttons-container" }); - rowOneBtns.createSpan({ cls: "advanced-tables-row-label" }).setText("Align:"); - this.drawBtn( - rowOneBtns, - "alignLeft", - "left align column", - (te) => te.leftAlignColumn() - ); - this.drawBtn( - rowOneBtns, - "alignCenter", - "center align column", - (te) => te.centerAlignColumn() - ); - this.drawBtn( - rowOneBtns, - "alignRight", - "right align column", - (te) => te.rightAlignColumn() - ); - const rowTwoBtns = navHeader.createDiv({ cls: "nav-buttons-container" }); - rowTwoBtns.createSpan({ cls: "advanced-tables-row-label" }).setText("Move:"); - this.drawBtn( - rowTwoBtns, - "moveRowDown", - "move row down", - (te) => te.moveRowDown() - ); - this.drawBtn( - rowTwoBtns, - "moveRowUp", - "move row up", - (te) => te.moveRowUp() - ); - this.drawBtn( - rowTwoBtns, - "moveColumnRight", - "move column right", - (te) => te.moveColumnRight() - ); - this.drawBtn( - rowTwoBtns, - "moveColumnLeft", - "move column left", - (te) => te.moveColumnLeft() - ); - this.drawBtn( - rowTwoBtns, - "transpose", - "transpose", - (te) => te.transpose() - ); - const rowThreeBtns = navHeader.createDiv({ cls: "nav-buttons-container" }); - rowThreeBtns.createSpan({ cls: "advanced-tables-row-label" }).setText("Edit:"); - this.drawBtn( - rowThreeBtns, - "insertRow", - "insert row above", - (te) => te.insertRow() - ); - this.drawBtn( - rowThreeBtns, - "insertColumn", - "insert column left", - (te) => te.insertColumn() - ); - this.drawBtn( - rowThreeBtns, - "deleteRow", - "delete row", - (te) => te.deleteRow() - ); - this.drawBtn( - rowThreeBtns, - "deleteColumn", - "delete column", - (te) => te.deleteColumn() - ); - const rowFourBtns = navHeader.createDiv({ cls: "nav-buttons-container" }); - rowFourBtns.createSpan({ cls: "advanced-tables-row-label" }).setText("Sort/F:"); - this.drawBtn( - rowFourBtns, - "sortAsc", - "sort by column ascending", - (te) => te.sortRowsAsc() - ); - this.drawBtn( - rowFourBtns, - "sortDesc", - "sort by column descending", - (te) => te.sortRowsDesc() - ); - this.drawBtn( - rowFourBtns, - "formula", - "evaluate formulas", - (te) => te.evaluateFormulas() - ); - const rowFiveBtns = navHeader.createDiv({ cls: "nav-buttons-container" }); - rowFiveBtns.createSpan({ cls: "advanced-tables-row-label" }).setText("Misc:"); - this.drawBtn( - rowFiveBtns, - "csv", - "export as csv", - (te) => te.exportCSVModal() - ); - this.drawBtn( - rowFiveBtns, - "help", - "help", - () => window.open( - "https://github.com/tgrosinger/advanced-tables-obsidian/blob/main/docs/help.md" - ) - ); - container.empty(); - container.appendChild(rootEl); - }; - this.drawBtn = (parent, iconName, title, fn) => { - const cursorCheck = (te) => { - if (title === "evaluate formulas") { - return te.cursorIsInTable() || te.cursorIsInTableFormula(); - } - return te.cursorIsInTable(); - }; - const button = parent.createDiv({ cls: "advanced-tables-button nav-action-button", title }); - button.onClickEvent(() => this.withTE(fn, cursorCheck)); - button.appendChild(Element(icons[iconName])); - }; - this.withTE = (fn, cursorCheck, alertOnNoTable = true) => { - let editor; - const leaf = this.app.workspace.getMostRecentLeaf(); - if (leaf.view instanceof import_obsidian3.MarkdownView) { - editor = leaf.view.editor; - } else { - console.warn("Advanced Tables: Unable to determine current editor."); - return; - } - const te = new TableEditor(this.app, leaf.view.file, editor, this.settings); - if (!cursorCheck(te)) { - if (alertOnNoTable) { - new import_obsidian3.Notice("Advanced Tables: Cursor must be in a table."); - } - return; - } - fn(te); - }; - this.settings = settings; - } - getViewType() { - return TableControlsViewType; - } - getDisplayText() { - return "Advanced Tables"; - } - getIcon() { - return "spreadsheet"; - } - load() { - super.load(); - this.draw(); - } -}; -var Element = (svgText) => { - const parser = new DOMParser(); - return parser.parseFromString(svgText, "text/xml").documentElement; -}; - -// src/main.ts -var import_state = require("@codemirror/state"); -var import_view = require("@codemirror/view"); -var import_md_advanced_tables4 = __toESM(require_lib2()); -var import_obsidian4 = require("obsidian"); -var TableEditorPlugin = class extends import_obsidian4.Plugin { - constructor() { - super(...arguments); - // makeEditorExtension is used to bind Tab and Enter in the new CM6 Live Preview editor. - this.makeEditorExtension = () => { - const keymaps = []; - if (this.settings.bindEnter) { - keymaps.push({ - key: "Enter", - run: () => this.newPerformTableActionCM6((te) => te.nextRow())(), - preventDefault: true - }); - } - if (this.settings.bindTab) { - keymaps.push({ - key: "Tab", - run: () => this.newPerformTableActionCM6((te) => te.nextCell())(), - shift: () => this.newPerformTableActionCM6( - (te) => te.previousCell() - )(), - preventDefault: true - }); - } - return import_state.Prec.highest(import_view.keymap.of(keymaps)); - }; - this.newPerformTableActionCM6 = (fn) => () => { - const view = this.app.workspace.getActiveViewOfType(import_obsidian4.MarkdownView); - if (view) { - const currentMode = view.currentMode; - if ("sourceMode" in currentMode && !currentMode.sourceMode) { - return false; - } - const te = new TableEditor( - this.app, - view.file, - view.editor, - this.settings - ); - if (te.cursorIsInTable()) { - fn(te); - return true; - } - } - return false; - }; - this.newPerformTableAction = (fn, alertOnNoTable = true) => (checking, editor, view) => { - const te = new TableEditor(this.app, view.file, editor, this.settings); - if (checking) { - return te.cursorIsInTable(); - } - fn(te); - }; - // handleKeyDown is used to bind the tab and enter keys in the legacy CM5 editor. - this.handleKeyDown = (cm, event) => { - if (["Tab", "Enter"].contains(event.key)) { - const view = this.app.workspace.getActiveViewOfType(import_obsidian4.MarkdownView); - const editor = view ? view.editor : null; - const action = this.newPerformTableAction((te) => { - switch (event.key) { - case "Tab": - if (!this.settings.bindTab) { - return; - } - if (event.shiftKey) { - te.previousCell(); - } else { - te.nextCell(); - } - break; - case "Enter": - if (!this.settings.bindEnter) { - return; - } - if (event.shiftKey) { - te.escape(); - } else if (event.ctrlKey || event.metaKey || event.altKey) { - return; - } else { - te.nextRow(); - } - break; - } - event.preventDefault(); - }, false); - if (action(true, editor, view)) { - action(false, editor, view); - } - } - }; - this.toggleTableControlsView = async () => { - const existing = this.app.workspace.getLeavesOfType(TableControlsViewType); - if (existing.length) { - this.app.workspace.revealLeaf(existing[0]); - return; - } - await this.app.workspace.getRightLeaf(false).setViewState({ - type: TableControlsViewType, - active: true - }); - this.app.workspace.revealLeaf( - this.app.workspace.getLeavesOfType(TableControlsViewType)[0] - ); - }; - this.isMobile = () => this.app.isMobile; - } - async onload() { - console.log("loading markdown-table-editor plugin"); - await this.loadSettings(); - this.registerView( - TableControlsViewType, - (leaf) => new TableControlsView(leaf, this.settings) - ); - addIcons(); - if (this.settings.showRibbonIcon) { - this.addRibbonIcon("spreadsheet", "Advanced Tables Toolbar", () => { - this.toggleTableControlsView(); - }); - } - this.registerEditorExtension(this.makeEditorExtension()); - this.addCommand({ - id: "next-row", - name: "Go to next row", - icon: "arrowenter", - editorCheckCallback: this.newPerformTableAction((te) => { - if (this.settings.bindEnter && !this.isMobile) { - new import_obsidian4.Notice( - "Advanced Tables: Next row also bound to enter. Possibly producing double actions. See Advanced Tables settings." - ); - } - te.nextRow(); - }) - }); - this.addCommand({ - id: "next-cell", - name: "Go to next cell", - icon: "arrowtab", - editorCheckCallback: this.newPerformTableAction((te) => { - if (this.settings.bindTab && !this.isMobile) { - new import_obsidian4.Notice( - "Advanced Tables: Next cell also bound to tab. Possibly producing double actions. See Advanced Tables settings." - ); - } - te.nextCell(); - }) - }); - this.addCommand({ - id: "previous-cell", - name: "Go to previous cell", - editorCheckCallback: this.newPerformTableAction((te) => { - if (this.settings.bindTab && !this.isMobile) { - new import_obsidian4.Notice( - "Advanced Tables: Previous cell also bound to shift+tab. Possibly producing double actions. See Advanced Tables settings." - ); - } - te.previousCell(); - }) - }); - this.addCommand({ - id: "format-table", - name: "Format table at the cursor", - editorCheckCallback: this.newPerformTableAction((te) => { - te.formatTable(); - }) - }); - this.addCommand({ - id: "format-all-tables", - name: "Format all tables in this file", - editorCallback: (editor, view) => { - const te = new TableEditor(this.app, view.file, editor, this.settings); - te.formatAllTables(); - } - }); - this.addCommand({ - id: "insert-column", - name: "Insert column before current", - icon: "insertColumn", - editorCheckCallback: this.newPerformTableAction((te) => { - te.insertColumn(); - }) - }); - this.addCommand({ - id: "insert-row", - name: "Insert row before current", - icon: "insertRow", - editorCheckCallback: this.newPerformTableAction((te) => { - te.insertRow(); - }) - }); - this.addCommand({ - id: "escape-table", - name: "Move cursor out of table", - editorCheckCallback: this.newPerformTableAction((te) => { - te.escape(); - }) - }); - this.addCommand({ - id: "left-align-column", - name: "Left align column", - icon: "alignLeft", - editorCheckCallback: this.newPerformTableAction((te) => { - te.leftAlignColumn(); - }) - }); - this.addCommand({ - id: "center-align-column", - name: "Center align column", - icon: "alignCenter", - editorCheckCallback: this.newPerformTableAction((te) => { - te.centerAlignColumn(); - }) - }); - this.addCommand({ - id: "right-align-column", - name: "Right align column", - icon: "alignRight", - editorCheckCallback: this.newPerformTableAction((te) => { - te.rightAlignColumn(); - }) - }); - this.addCommand({ - id: "move-column-left", - name: "Move column left", - icon: "moveColumnLeft", - editorCheckCallback: this.newPerformTableAction((te) => { - te.moveColumnLeft(); - }) - }); - this.addCommand({ - id: "move-column-right", - name: "Move column right", - icon: "moveColumnRight", - editorCheckCallback: this.newPerformTableAction((te) => { - te.moveColumnRight(); - }) - }); - this.addCommand({ - id: "move-row-up", - name: "Move row up", - icon: "moveRowUp", - editorCheckCallback: this.newPerformTableAction((te) => { - te.moveRowUp(); - }) - }); - this.addCommand({ - id: "move-row-down", - name: "Move row down", - icon: "moveRowDown", - editorCheckCallback: this.newPerformTableAction((te) => { - te.moveRowDown(); - }) - }); - this.addCommand({ - id: "delete-column", - name: "Delete column", - icon: "deleteColumn", - editorCheckCallback: this.newPerformTableAction((te) => { - te.deleteColumn(); - }) - }); - this.addCommand({ - id: "delete-row", - name: "Delete row", - icon: "deleteRow", - editorCheckCallback: this.newPerformTableAction((te) => { - te.deleteRow(); - }) - }); - this.addCommand({ - id: "sort-rows-ascending", - name: "Sort rows ascending", - icon: "sortAsc", - editorCheckCallback: this.newPerformTableAction((te) => { - te.sortRowsAsc(); - }) - }); - this.addCommand({ - id: "sort-rows-descending", - name: "Sort rows descending", - icon: "sortDesc", - editorCheckCallback: this.newPerformTableAction((te) => { - te.sortRowsDesc(); - }) - }); - this.addCommand({ - id: "transpose", - name: "Transpose", - icon: "transpose", - editorCheckCallback: this.newPerformTableAction((te) => { - te.transpose(); - }) - }); - this.addCommand({ - id: "evaluate-formulas", - name: "Evaluate table formulas", - icon: "formula", - editorCheckCallback: (checking, editor, view) => { - const te = new TableEditor(this.app, view.file, editor, this.settings); - if (checking) { - return te.cursorIsInTable() || te.cursorIsInTableFormula(); - } - te.evaluateFormulas(); - } - }); - this.addCommand({ - id: "table-control-bar", - name: "Open table controls toolbar", - hotkeys: [ - { - modifiers: ["Mod", "Shift"], - key: "d" - } - ], - callback: () => { - this.toggleTableControlsView(); - } - }); - this.addSettingTab(new TableEditorSettingsTab(this.app, this)); - } - async loadSettings() { - const settingsOptions = Object.assign( - defaultSettings, - await this.loadData() - ); - this.settings = new TableEditorPluginSettings(settingsOptions); - this.saveData(this.settings); - } -}; -var TableEditorSettingsTab = class extends import_obsidian4.PluginSettingTab { - constructor(app, plugin) { - super(app, plugin); - this.plugin = plugin; - } - display() { - const { containerEl } = this; - containerEl.empty(); - containerEl.createEl("h2", { text: "Advanced Tables Plugin - Settings" }); - new import_obsidian4.Setting(containerEl).setName("Bind enter to table navigation").setDesc( - 'Requires restart of Obsidian. If enabled, when the cursor is in a table, enter advances to the next row. Disabling this can help avoid conflicting with tag or CJK autocompletion. If disabling, bind "Go to ..." in the Obsidian Hotkeys settings.' - ).addToggle( - (toggle) => toggle.setValue(this.plugin.settings.bindEnter).onChange((value) => { - this.plugin.settings.bindEnter = value; - this.plugin.saveData(this.plugin.settings); - this.display(); - }) - ); - new import_obsidian4.Setting(containerEl).setName("Bind tab to table navigation").setDesc( - 'Requires restart of Obsidian. If enabled, when the cursor is in a table, tab/shift+tab navigate between cells. Disabling this can help avoid conflicting with tag or CJK autocompletion. If disabling, bind "Go to ..." in the Obsidian Hotkeys settings.' - ).addToggle( - (toggle) => toggle.setValue(this.plugin.settings.bindTab).onChange((value) => { - this.plugin.settings.bindTab = value; - this.plugin.saveData(this.plugin.settings); - this.display(); - }) - ); - new import_obsidian4.Setting(containerEl).setName("Pad cell width using spaces").setDesc( - "If enabled, table cells will have spaces added to match the width of the longest cell in the column." - ).addToggle( - (toggle) => toggle.setValue(this.plugin.settings.formatType === import_md_advanced_tables4.FormatType.NORMAL).onChange((value) => { - this.plugin.settings.formatType = value ? import_md_advanced_tables4.FormatType.NORMAL : import_md_advanced_tables4.FormatType.WEAK; - this.plugin.saveData(this.plugin.settings); - this.display(); - }) - ); - new import_obsidian4.Setting(containerEl).setName("Show icon in sidebar").setDesc( - "If enabled, a button which opens the table controls toolbar will be added to the Obsidian sidebar. The toolbar can also be opened with a Hotkey. Changes only take effect on reload." - ).addToggle( - (toggle) => toggle.setValue(this.plugin.settings.showRibbonIcon).onChange((value) => { - this.plugin.settings.showRibbonIcon = value; - this.plugin.saveData(this.plugin.settings); - this.display(); - }) - ); - const div = containerEl.createEl("div", { - cls: "advanced-tables-donation" - }); - const donateText = document.createElement("p"); - donateText.appendText( - "If this plugin adds value for you and you would like to help support continued development, please use the buttons below:" - ); - div.appendChild(donateText); - const parser = new DOMParser(); - div.appendChild( - createDonateButton( - "https://paypal.me/tgrosinger", - parser.parseFromString(paypal, "text/xml").documentElement - ) - ); - div.appendChild( - createDonateButton( - "https://www.buymeacoffee.com/tgrosinger", - parser.parseFromString(buyMeACoffee, "text/xml").documentElement - ) - ); - } -}; -var createDonateButton = (link, img) => { - const a = document.createElement("a"); - a.setAttribute("href", link); - a.addClass("advanced-tables-donate-button"); - a.appendChild(img); - return a; -}; -var buyMeACoffee = ` - - - - - - - - - - - - - - - - - - - - - -`; -var paypal = ` - - - - - - - -`; -/*! Bundled license information: - -decimal.js/decimal.js: - (*! - * decimal.js v10.4.3 - * An arbitrary-precision Decimal type for JavaScript. - * https://github.com/MikeMcl/decimal.js - * Copyright (c) 2022 Michael Mclaughlin - * MIT Licence - *) - -lodash/lodash.js: - (** - * @license - * Lodash - * Copyright OpenJS Foundation and other contributors - * Released under MIT license - * Based on Underscore.js 1.8.3 - * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - *) -*/ diff --git a/.obsidian/plugins/table-editor-obsidian/manifest.json b/.obsidian/plugins/table-editor-obsidian/manifest.json deleted file mode 100644 index 5d03cdf..0000000 --- a/.obsidian/plugins/table-editor-obsidian/manifest.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "id": "table-editor-obsidian", - "name": "Advanced Tables", - "author": "Tony Grosinger", - "authorUrl": "https://grosinger.net", - "description": "Improved table navigation, formatting, manipulation, and formulas", - "isDesktopOnly": false, - "minAppVersion": "1.0.0", - "version": "0.22.0", - "js": "main.js", - "fundingUrl": { - "Github Sponsor": "https://github.com/sponsors/tgrosinger", - "Buy me a Coffee": "https://buymeacoffee.com/tgrosinger", - "Paypal": "https://paypal.me/tgrosinger" - }, - "donation": "https://buymeacoffee.com/tgrosinger" -} \ No newline at end of file diff --git a/.obsidian/plugins/table-editor-obsidian/styles.css b/.obsidian/plugins/table-editor-obsidian/styles.css deleted file mode 100644 index 089b8cd..0000000 --- a/.obsidian/plugins/table-editor-obsidian/styles.css +++ /dev/null @@ -1,78 +0,0 @@ -:root { - --advanced-tables-helper-size: 28px; -} - -.HyperMD-table-row span.cm-inline-code { - font-size: 100%; - padding: 0px; -} - -.advanced-tables-buttons>div>.title { - font-weight: var(--font-medium); - font-size: var(--nav-item-size); - color: var(--nav-item-color); - text-decoration: underline; -} - -[data-type="advanced-tables-toolbar"] .nav-buttons-container { - column-gap: 0.2rem; - margin: 0.2rem 0 0.2rem 0; - justify-content: start; -} - -[data-type="advanced-tables-toolbar"] .nav-buttons-container::before { - min-width: 2.6rem; - line-height: var(--advanced-tables-helper-size); - font-size: var(--nav-item-size); - font-weight: var(--nav-item-weight); - color: var(--nav-item-color); -} - -[data-type="advanced-tables-toolbar"] .nav-buttons-container>* { - height: var(--advanced-tables-helper-size); - line-height: var(--advanced-tables-helper-size); -} - -[data-type="advanced-tables-toolbar"] .nav-buttons-container .nav-action-button { - width: var(--advanced-tables-helper-size); - height: var(--advanced-tables-helper-size); - display: flex; - justify-content: center; - align-items: center; - border-radius: var(--radius-s); -} - -[data-type="advanced-tables-toolbar"] .nav-buttons-container .nav-action-button:hover { - background-color: var(--nav-item-background-hover); - color: var(--nav-item-color-hover); - font-weight: var(--nav-item-weight-hover); -} - -.advanced-tables-row-label { - width: 50px; -} - -.widget-icon { - width: 20px; - height: 20px; - fill: var(--text-muted); -} - -.widget-icon:hover { - fill: var(--text-normal); -} - -.advanced-tables-csv-export textarea { - height: 200px; - width: 100%; -} - -.advanced-tables-donation { - width: 70%; - margin: 0 auto; - text-align: center; -} - -.advanced-tables-donate-button { - margin: 10px; -} \ No newline at end of file diff --git a/.obsidian/plugins/tag-page-md/data.json b/.obsidian/plugins/tag-page-md/data.json deleted file mode 100644 index 65a2c61..0000000 --- a/.obsidian/plugins/tag-page-md/data.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "tagPageDir": "_Tags/", - "frontmatterQueryProperty": "tag-page-query", - "nestedSeparator": "_", - "bulletedSubItems": true, - "includeLines": true, - "autoRefresh": true, - "fullLinkName": false -} \ No newline at end of file diff --git a/.obsidian/plugins/tag-page-md/main.js b/.obsidian/plugins/tag-page-md/main.js deleted file mode 100644 index bbfc042..0000000 --- a/.obsidian/plugins/tag-page-md/main.js +++ /dev/null @@ -1,525 +0,0 @@ -/* -THIS IS A GENERATED/BUNDLED FILE BY ESBUILD -if you want to view the source, please visit the github repository of this plugin -*/ - -var __defProp = Object.defineProperty; -var __getOwnPropDesc = Object.getOwnPropertyDescriptor; -var __getOwnPropNames = Object.getOwnPropertyNames; -var __hasOwnProp = Object.prototype.hasOwnProperty; -var __export = (target, all) => { - for (var name in all) - __defProp(target, name, { get: all[name], enumerable: true }); -}; -var __copyProps = (to, from, except, desc) => { - if (from && typeof from === "object" || typeof from === "function") { - for (let key of __getOwnPropNames(from)) - if (!__hasOwnProp.call(to, key) && key !== except) - __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); - } - return to; -}; -var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); - -// main.ts -var main_exports = {}; -__export(main_exports, { - default: () => TagPagePlugin -}); -module.exports = __toCommonJS(main_exports); -var import_obsidian2 = require("obsidian"); - -// src/utils/obsidianApi.ts -var import_obsidian = require("obsidian"); -var isTagPage = (app, tagPageFrontmatterKey, providedFile, tagOfInterest) => { - var _a, _b, _c; - const file = providedFile || ((_a = app.workspace.getActiveViewOfType(import_obsidian.MarkdownView)) == null ? void 0 : _a.file) || null; - if (!file) - return false; - const frontmatterValue = (_c = (_b = app.metadataCache.getFileCache(file)) == null ? void 0 : _b.frontmatter) == null ? void 0 : _c[tagPageFrontmatterKey]; - if (tagOfInterest !== void 0) { - return frontmatterValue === tagOfInterest; - } - return !!frontmatterValue; -}; - -// src/utils/tagSearch.ts -var getIsWildCard = (tag) => { - const isWildCard = tag.endsWith("/*"); - const cleanedTag = isWildCard ? tag.slice(0, -2) : tag; - return { isWildCard, cleanedTag }; -}; -var containsTag = (stringToSearch, tag) => { - const { isWildCard, cleanedTag } = getIsWildCard(tag); - const lowerStringToSearch = stringToSearch.toLowerCase(); - const lowerCleanedTag = cleanedTag.toLowerCase(); - if (isWildCard) { - return lowerStringToSearch.includes(lowerCleanedTag); - } else { - const regex = new RegExp(`${lowerCleanedTag}\\s`, "gi"); - return regex.test(lowerStringToSearch); - } -}; -var findSmallestUnitsContainingTag = (content, tag, excludeBullets = false) => { - const { isWildCard, cleanedTag } = getIsWildCard(tag); - const escapedSubstring = cleanedTag.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); - const wildcardPattern = isWildCard ? "(?:\\/[^\\s]*)?" : ""; - const contentLines = content.split("\n").filter((line) => !(excludeBullets && line.trim().startsWith("-"))); - const matchesMap = /* @__PURE__ */ new Map(); - contentLines.forEach((line) => { - const regex = new RegExp(`${escapedSubstring}${wildcardPattern}`, "gi"); - const matches = [...line.matchAll(regex)]; - matches.forEach((match) => { - let key = match[0].toLowerCase(); - if (isWildCard && key.endsWith("/*")) { - key = key.slice(0, -2); - } - if (!matchesMap.has(key)) { - matchesMap.set(key, [line.trim()]); - } else { - const existingLines = matchesMap.get(key); - if (!existingLines.includes(line.trim())) { - existingLines.push(line.trim()); - } - } - }); - }); - return matchesMap; -}; -var findBulletListsContainingTag = (content, tag) => { - const capturedBulletLists = /* @__PURE__ */ new Map(); - const fileLines = content.split("\n").filter((line) => line.trim() !== ""); - let currentBulletIndentation = 0; - const lastTagsAtCurrentIndentation = /* @__PURE__ */ new Set(); - let capturingSubBullet = false; - fileLines.forEach((line) => { - const lineTrim = line.trim(); - const startsWithBullet = lineTrim.startsWith("- "); - const lineIndentation = line.search(/\S/); - if (startsWithBullet) { - const { isWildCard, cleanedTag } = getIsWildCard(tag); - const tagRegex = isWildCard ? `${cleanedTag}(/[^\\s]+)?` : `${cleanedTag}(?![^\\s])`; - const regex = new RegExp(tagRegex, "gi"); - const matches = line.match(regex); - if (startsWithBullet && (matches || lineIndentation <= currentBulletIndentation)) { - capturingSubBullet = false; - currentBulletIndentation = lineIndentation; - lastTagsAtCurrentIndentation.clear(); - } - if (matches) { - capturingSubBullet = false; - matches.forEach((match) => { - var _a; - const trimmedMatch = isWildCard && match.endsWith("/") ? match.slice(0, -1) : match; - const trimmedMatchLowerCase = trimmedMatch.toLowerCase(); - if (!capturedBulletLists.has(trimmedMatchLowerCase)) { - capturedBulletLists.set(trimmedMatchLowerCase, []); - } - (_a = capturedBulletLists.get(trimmedMatchLowerCase)) == null ? void 0 : _a.push( - lineIndentation > currentBulletIndentation && capturingSubBullet ? line : lineTrim - ); - lastTagsAtCurrentIndentation.add(trimmedMatchLowerCase); - }); - } else if (lineIndentation > currentBulletIndentation && lastTagsAtCurrentIndentation.size > 0) { - capturingSubBullet = true; - lastTagsAtCurrentIndentation.forEach((tag2) => { - var _a; - (_a = capturedBulletLists.get(tag2)) == null ? void 0 : _a.push(line); - }); - } - } - }); - return capturedBulletLists; -}; -function consolidateTagInfo(fileLink, unitsContainingTag, bulletListsContainingTag) { - const consolidatedInfo = /* @__PURE__ */ new Map(); - const addMatchesToConsolidatedInfo = (tag, matches) => { - const existingMatches = consolidatedInfo.get(tag) || []; - const newMatches = matches.map((matchString) => ({ - stringContainingTag: matchString, - fileLink - })); - consolidatedInfo.set(tag, existingMatches.concat(newMatches)); - }; - unitsContainingTag == null ? void 0 : unitsContainingTag.forEach((matches, tag) => { - addMatchesToConsolidatedInfo(tag, matches); - }); - bulletListsContainingTag == null ? void 0 : bulletListsContainingTag.forEach((matches, tag) => { - addMatchesToConsolidatedInfo(tag, matches); - }); - return consolidatedInfo; -} -var processFile = async (vault, settings, file, tagOfInterest) => { - const fileContents = await vault.cachedRead(file); - if (!containsTag(fileContents, tagOfInterest)) - return /* @__PURE__ */ new Map(); - const fileLink = settings.fullLinkName ? `[[${file.basename}]]` : `[[${file.basename}|*]]`; - switch (true) { - case (settings.bulletedSubItems && settings.includeLines): - return consolidateTagInfo( - fileLink, - findSmallestUnitsContainingTag( - fileContents, - tagOfInterest, - true - ), - findBulletListsContainingTag(fileContents, tagOfInterest) - ); - case (settings.bulletedSubItems && !settings.includeLines): - return consolidateTagInfo( - fileLink, - void 0, - findBulletListsContainingTag(fileContents, tagOfInterest) - ); - case (!settings.bulletedSubItems && settings.includeLines): - default: - return consolidateTagInfo( - fileLink, - findSmallestUnitsContainingTag( - fileContents, - tagOfInterest, - false - ), - void 0 - ); - } -}; -var fetchTagData = async (app, settings, tagOfInterest) => { - const vault = app.vault; - const allFiles = vault.getMarkdownFiles(); - return await Promise.all( - allFiles.filter( - (file) => !isTagPage(app, settings.frontmatterQueryProperty, file) - ).map((file) => processFile(vault, settings, file, tagOfInterest)) - ).then((tagInfos) => { - const consolidatedTagInfo = /* @__PURE__ */ new Map(); - tagInfos.forEach((tagInfo) => { - tagInfo.forEach((details, tag) => { - const existingDetails = consolidatedTagInfo.get(tag) || []; - consolidatedTagInfo.set(tag, existingDetails.concat(details)); - }); - }); - return consolidatedTagInfo; - }); -}; - -// src/utils/pageContent.ts -var generateTagPageContent = async (app, settings, tagsInfo, tagOfInterest) => { - const tagPageContent = []; - tagPageContent.push( - `--- -${settings.frontmatterQueryProperty}: "${tagOfInterest}" ----` - ); - tagPageContent.push(`## Tag Content for ${tagOfInterest.replace("*", "")}`); - if (tagsInfo.size > 1) { - const sortedTagsInfo = Array.from(tagsInfo).sort((a, b) => { - return a[0].length - b[0].length; - }); - sortedTagsInfo.forEach(([baseTag, details]) => { - tagPageContent.push(`### ${baseTag}`); - details.forEach(({ stringContainingTag, fileLink }) => { - processTagMatch(stringContainingTag, fileLink, tagPageContent); - }); - }); - } else { - tagsInfo.forEach((details) => { - details.forEach(({ stringContainingTag, fileLink }) => { - processTagMatch(stringContainingTag, fileLink, tagPageContent); - }); - }); - } - const filesWithFrontmatterTag = app.vault.getMarkdownFiles().filter((file) => { - var _a; - const metaMatter = (_a = app.metadataCache.getFileCache(file)) == null ? void 0 : _a.frontmatter; - return (metaMatter == null ? void 0 : metaMatter.tags) ? matchesTagOfInterest(metaMatter.tags, tagOfInterest) : false; - }).map((file) => `- [[${file.basename}]]`); - if (filesWithFrontmatterTag.length > 0) { - const { cleanedTag } = getIsWildCard(tagOfInterest); - tagPageContent.push(`## Files with ${cleanedTag} in frontmatter`); - tagPageContent.push(...filesWithFrontmatterTag); - } - return tagPageContent.join("\n"); -}; -var extractFrontMatterTagValue = (app, view, frontMatterTag) => { - var _a; - if (view.file) { - try { - const metaMatter = (_a = app.metadataCache.getFileCache(view.file)) == null ? void 0 : _a.frontmatter; - return metaMatter == null ? void 0 : metaMatter[frontMatterTag]; - } catch (err) { - console.log(err); - return; - } - } -}; -function processTagMatch(fullTag, fileLink, tagPageContent) { - if (fullTag.trim().startsWith("-")) { - const [firstBullet, ...bullets] = fullTag.split("\n"); - const firstBulletWithLink = `${firstBullet} ${fileLink}`; - tagPageContent.push([firstBulletWithLink, ...bullets].join("\n")); - } else { - tagPageContent.push(`- ${fullTag} ${fileLink}`); - } -} -function matchesTagOfInterest(tags, tagOfInterest) { - const normalizedTags = Array.isArray(tags) ? tags : [tags]; - const { isWildCard, cleanedTag: tagBase } = getIsWildCard(tagOfInterest); - if (isWildCard) { - return normalizedTags.some((tag) => { - const fullTag = `#${tag}`; - return fullTag === tagBase || fullTag.startsWith(`${tagBase}/`); - }); - } else { - return normalizedTags.some((tag) => `#${tag}` === tagBase); - } -} -var swapPageContent = (activeLeaf, newPageContent) => { - var _a; - (_a = activeLeaf == null ? void 0 : activeLeaf.currentMode) == null ? void 0 : _a.set(newPageContent, true); -}; -var generateFilename = (cleanedTag, isWildCard, nestedSeparator) => { - return `${cleanedTag.replace("#", "").replaceAll("/", nestedSeparator)}${isWildCard ? nestedSeparator + "nested" : ""}${nestedSeparator}Tags.md`; -}; - -// main.ts -var DEFAULT_SETTINGS = { - tagPageDir: "Tags/", - frontmatterQueryProperty: "tag-page-query", - nestedSeparator: "_", - bulletedSubItems: true, - includeLines: true, - autoRefresh: true, - fullLinkName: false -}; -var TagPagePlugin = class extends import_obsidian2.Plugin { - async onload() { - await this.loadSettings(); - this.addSettingTab(new TagPageSettingTab(this.app, this)); - this.ribbonIcon = this.addRibbonIcon( - "tag-glyph", - "Refresh tag page", - () => { - this.refreshTagPageContent(); - } - ); - this.ribbonIcon.style.display = "none"; - this.addCommand({ - id: "create-tag-page", - name: "Create tag page", - callback: () => { - new CreateTagPageModal(this.app, this).open(); - } - }); - this.registerEvent( - this.app.workspace.on("layout-change", () => { - this.updateRibbonIconVisibility(); - this.autoRefreshTagPage(); - }) - ); - this.registerEvent( - this.app.workspace.on("file-open", () => { - this.updateRibbonIconVisibility(); - this.autoRefreshTagPage(); - }) - ); - this.updateRibbonIconVisibility(); - await this.autoRefreshTagPage(); - } - updateRibbonIconVisibility() { - this.ribbonIcon.style.display = isTagPage( - this.app, - this.settings.frontmatterQueryProperty - ) ? "block" : "none"; - } - async autoRefreshTagPage() { - if (this.settings.autoRefresh && isTagPage(this.app, this.settings.frontmatterQueryProperty)) { - await this.refreshTagPageContent(); - } - } - onunload() { - } - async loadSettings() { - this.settings = Object.assign( - {}, - DEFAULT_SETTINGS, - await this.loadData() - ); - } - async saveSettings() { - await this.saveData(this.settings); - } - /** - * Refreshes the content of the active tag page based on the current settings. - * - * @returns {Promise} - A promise that resolves when the operation is complete. - */ - async refreshTagPageContent() { - const activeLeaf = this.app.workspace.getActiveViewOfType(import_obsidian2.MarkdownView); - if (!activeLeaf) - return; - const tagOfInterest = extractFrontMatterTagValue( - this.app, - activeLeaf, - this.settings.frontmatterQueryProperty - ); - if (!tagOfInterest) - return; - const tagsInfo = await fetchTagData( - this.app, - this.settings, - tagOfInterest - ); - const tagPageContentString = await generateTagPageContent( - this.app, - this.settings, - tagsInfo, - tagOfInterest - ); - swapPageContent(activeLeaf, tagPageContentString); - } - /** - * Creates a new tag page or navigates to an existing one. - * - * @param {string} tag - The tag for which to create or navigate to a page. - * @returns {Promise} - A promise that resolves when the operation is complete. - */ - async createTagPage(tag) { - const tagOfInterest = tag.startsWith("#") ? tag : `#${tag}`; - const { isWildCard, cleanedTag } = getIsWildCard(tagOfInterest); - const filename = generateFilename( - cleanedTag, - isWildCard, - this.settings.nestedSeparator - ); - const tagPage = this.app.vault.getAbstractFileByPath( - `${this.settings.tagPageDir}${filename}` - ); - if (!tagPage) { - const tagsInfo = await fetchTagData( - this.app, - this.settings, - tagOfInterest - ); - const tagPageContentString = await generateTagPageContent( - this.app, - this.settings, - tagsInfo, - tagOfInterest - ); - const exists = await this.app.vault.adapter.exists( - (0, import_obsidian2.normalizePath)(this.settings.tagPageDir) - ); - if (!exists) { - await this.app.vault.createFolder(this.settings.tagPageDir); - } - const createdPage = await this.app.vault.create( - `${this.settings.tagPageDir}${filename}`, - tagPageContentString - ); - await this.app.workspace.getLeaf().openFile(createdPage); - } else { - await this.app.workspace.getLeaf().openFile(tagPage); - } - } -}; -var CreateTagPageModal = class extends import_obsidian2.Modal { - constructor(app, plugin) { - super(app); - this.plugin = plugin; - } - onOpen() { - const { contentEl } = this; - contentEl.setText("Tag to create page for:"); - const tagForm = contentEl.createEl("form"); - contentEl.addClass("create-page-modal"); - const input = tagForm.createEl("input", { type: "text" }); - input.placeholder = "#tag"; - input.value = "#"; - input.addEventListener("keydown", (e) => { - const cursorPosition = input.selectionStart; - if (cursorPosition === 1 && (e.key === "Backspace" || e.key === "Delete")) { - e.preventDefault(); - } - }); - const submitButton = tagForm.createEl("button", { type: "submit" }); - submitButton.innerText = "Create Tag Page"; - tagForm.addEventListener("submit", async (e) => { - e.preventDefault(); - const tag = input.value; - this.contentEl.empty(); - this.contentEl.setText(`Creating tag page for ${tag}...`); - await this.plugin.createTagPage(tag); - this.close(); - }); - } - onClose() { - const { contentEl } = this; - contentEl.empty(); - } -}; -var TagPageSettingTab = class extends import_obsidian2.PluginSettingTab { - constructor(app, plugin) { - super(app, plugin); - this.plugin = plugin; - } - display() { - const { containerEl } = this; - containerEl.empty(); - new import_obsidian2.Setting(containerEl).setName("Tag page directory").setDesc("The directory in which to create tag pages.").addText( - (text) => text.setValue(this.plugin.settings.tagPageDir).onChange(async (value) => { - if (!value.endsWith("/")) { - value = `${value}/`; - } - this.plugin.settings.tagPageDir = value; - await this.plugin.saveSettings(); - }) - ); - new import_obsidian2.Setting(containerEl).setName("Frontmatter query property").setDesc( - "The frontmatter property to use storing the query tag within the tag page. Required for page refresh." - ).addText( - (text) => text.setValue(this.plugin.settings.frontmatterQueryProperty).onChange(async (value) => { - this.plugin.settings.frontmatterQueryProperty = value; - await this.plugin.saveSettings(); - }) - ); - new import_obsidian2.Setting(containerEl).setName("Nested page separator").setDesc( - `Text used to separate levels for nested tags. Avoid \\/<>:"|?* and other characters that aren't file-safe, or you won't be able to make pages for nested tags.` - ).addText( - (text) => text.setValue(this.plugin.settings.nestedSeparator).onChange(async (value) => { - this.plugin.settings.nestedSeparator = value; - await this.plugin.saveSettings(); - }) - ); - new import_obsidian2.Setting(containerEl).setName("Include lines").setDesc("Include lines containing the tag in the tag page.").addToggle( - (toggle) => toggle.setValue(this.plugin.settings.includeLines).onChange(async (value) => { - this.plugin.settings.includeLines = value; - await this.plugin.saveSettings(); - }) - ); - new import_obsidian2.Setting(containerEl).setName("Bulleted sub-items").setDesc( - "Include bulleted sub-items containing the tag in the tag page." - ).addToggle( - (toggle) => toggle.setValue(this.plugin.settings.bulletedSubItems).onChange(async (value) => { - this.plugin.settings.bulletedSubItems = value; - await this.plugin.saveSettings(); - }) - ); - new import_obsidian2.Setting(containerEl).setName("Auto refresh").setDesc( - "Automatically refresh tag pages when they are opened or become active." - ).addToggle( - (toggle) => toggle.setValue(this.plugin.settings.autoRefresh).onChange(async (value) => { - this.plugin.settings.autoRefresh = value; - await this.plugin.saveSettings(); - }) - ); - new import_obsidian2.Setting(containerEl).setName("Display full link name as reference").setDesc( - "Each bit of pulled content will display the full link title as a reference as an end of line. Displays * when false." - ).addToggle( - (toggle) => toggle.setValue(this.plugin.settings.fullLinkName).onChange(async (value) => { - this.plugin.settings.fullLinkName = value; - await this.plugin.saveSettings(); - }) - ); - } -}; diff --git a/.obsidian/plugins/tag-page-md/manifest.json b/.obsidian/plugins/tag-page-md/manifest.json deleted file mode 100644 index 78eea34..0000000 --- a/.obsidian/plugins/tag-page-md/manifest.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "id": "tag-page-md", - "name": "Tag Page", - "version": "1.1.0", - "minAppVersion": "0.15.0", - "description": "Dynamically generate and update tag-specific pages, offering a consolidated view of each tag's references across your vault.", - "author": "Matthew Sumpter", - "authorUrl": "https://matthewsumpter.org", - "fundingUrl": "https://www.buymeacoffee.com/buymeacofftu", - "isDesktopOnly": false -} \ No newline at end of file diff --git a/.obsidian/plugins/tag-page-md/styles.css b/.obsidian/plugins/tag-page-md/styles.css deleted file mode 100644 index 7b345cc..0000000 --- a/.obsidian/plugins/tag-page-md/styles.css +++ /dev/null @@ -1,29 +0,0 @@ -/* - -This CSS file will be included with your plugin, and -available in the app when your plugin is enabled. - -If your plugin does not need CSS, delete this file. - -*/ - -.create-page-modal { - /* add margin to all children */ - & > * { - margin: 10px; - } - - display: flex; - flex-direction: column; - text-align: center; - - & form { - display: flex; - flex-direction: column; - - & > input { - text-align: center; - } - } -} - diff --git a/.obsidian/workspace.json b/.obsidian/workspace.json index 6c4540e..a8cf3dd 100644 --- a/.obsidian/workspace.json +++ b/.obsidian/workspace.json @@ -10,16 +10,53 @@ { "id": "7d5274162457b1c7", "type": "leaf", + "pinned": true, "state": { "type": "markdown", "state": { "file": "Readme.md", "mode": "preview", "source": true - } + }, + "pinned": true, + "icon": "lucide-file", + "title": "Readme" + } + }, + { + "id": "073b99b42ebd2844", + "type": "leaf", + "pinned": true, + "state": { + "type": "markdown", + "state": { + "file": "Notes/__Using The Vault.md", + "mode": "preview", + "source": true + }, + "pinned": true, + "icon": "lucide-file", + "title": "__Using The Vault" + } + }, + { + "id": "ac5db91574f2a15e", + "type": "leaf", + "pinned": true, + "state": { + "type": "markdown", + "state": { + "file": "__Dashboard.md", + "mode": "preview", + "source": true + }, + "pinned": true, + "icon": "lucide-file", + "title": "__Dashboard" } } - ] + ], + "currentTab": 1 } ], "direction": "vertical" @@ -39,7 +76,9 @@ "type": "file-explorer", "state": { "sortOrder": "alphabetical" - } + }, + "icon": "lucide-folder-closed", + "title": "Files" } }, { @@ -54,7 +93,9 @@ "collapseAll": false, "extraContext": false, "sortOrder": "alphabetical" - } + }, + "icon": "lucide-search", + "title": "Search" } }, { @@ -62,7 +103,9 @@ "type": "leaf", "state": { "type": "bookmarks", - "state": {} + "state": {}, + "icon": "lucide-bookmark", + "title": "Bookmarks" } } ] @@ -93,7 +136,9 @@ "searchQuery": "", "backlinkCollapsed": false, "unlinkedCollapsed": true - } + }, + "icon": "links-coming-in", + "title": "Backlinks for Readme" } }, { @@ -105,7 +150,9 @@ "file": "Readme.md", "linksCollapsed": false, "unlinkedCollapsed": true - } + }, + "icon": "links-going-out", + "title": "Outgoing links from Readme" } }, { @@ -116,7 +163,9 @@ "state": { "sortOrder": "frequency", "useHierarchy": true - } + }, + "icon": "lucide-tags", + "title": "Tags" } }, { @@ -126,7 +175,9 @@ "type": "outline", "state": { "file": "Readme.md" - } + }, + "icon": "lucide-list", + "title": "Outline of Readme" } }, { @@ -138,7 +189,9 @@ "sortOrder": "frequency", "showSearch": false, "searchQuery": "" - } + }, + "icon": "lucide-archive", + "title": "All properties" } } ], @@ -160,11 +213,12 @@ "table-editor-obsidian:Advanced Tables Toolbar": true } }, - "active": "7d5274162457b1c7", + "active": "073b99b42ebd2844", "lastOpenFiles": [ - "Notes/__Using The Vault.md", "Readme.md", + "Notes/__Using The Vault.md", "__Dashboard.md", + "Notes/_Troubleshooting The Vault.md", "Notes/Obtaining Source Material.md", "Notes/Obsidian ToC.md", "Notes/Krita Quick Reference.md", @@ -177,7 +231,6 @@ "Notes/Convert PDF Coloring Pages.md", "Notes/Color Palette Generator.md", "Notes/Android Drawing Apps.md", - "Notes/_Troubleshooting The Vault.md", "_Gallery - Favorites.md", "Notes/attachments/Imagepipe_360.jpg", "Notes/attachments/Imagepipe_359.jpg",