UNPKG

obsidian-dev-utils

Version:

This is the collection of useful functions that you can use for your Obsidian plugin development

361 lines (358 loc) 47.1 kB
/* THIS IS A GENERATED/BUNDLED FILE BY ESBUILD if you want to view the source, please visit the github repository of this plugin */ (function initEsm(){if(globalThis.process){return}const browserProcess={browser:true,cwd(){return"/"},env:{},platform:"android"};globalThis.process=browserProcess})(); import { isFrontmatterLinkCache, isReferenceCache } from "obsidian-typings/implementations"; import { getLibDebugger } from "../Debug.mjs"; import { printError } from "../Error.mjs"; import { deepEqual, getNestedPropertyValue, setNestedPropertyValue } from "../ObjectUtils.mjs"; import { resolveValue } from "../ValueProvider.mjs"; import { getPath, isCanvasFile } from "./FileSystem.mjs"; import { parseFrontmatter, setFrontmatter } from "./Frontmatter.mjs"; import { isFrontmatterLinkCacheWithOffsets, toFrontmatterLinkCacheWithOffsets } from "./FrontmatterLinkCacheWithOffsets.mjs"; import { isCanvasReference, referenceToFileChange } from "./Reference.mjs"; import { process } from "./Vault.mjs"; async function applyContentChanges(abortSignal, content, path, changesProvider, shouldRetryOnInvalidChanges = true) { abortSignal.throwIfAborted(); let changes = await resolveValue(changesProvider, abortSignal, content); abortSignal.throwIfAborted(); if (changes === null) { return null; } const { frontmatter, hasFrontmatterError } = parseFrontmatterSafely(content, path); if (!validateChanges(changes, content, frontmatter, path)) { return shouldRetryOnInvalidChanges ? null : content; } changes = sortAndFilterChanges(changes); if (!validateChangeOverlaps(changes)) { return null; } const { frontmatterChanged, newContent } = applyContentChangesToText(changes, content, hasFrontmatterError, path); await applyFrontmatterChangesWithOffsets(abortSignal, frontmatter, frontmatterChanged, path); abortSignal.throwIfAborted(); return buildFinalContent(newContent, frontmatter, frontmatterChanged); } async function applyFileChanges(app, pathOrFile, changesProvider, processOptions = {}, shouldRetryOnInvalidChanges = true) { await process(app, pathOrFile, async (abortSignal, content) => { if (isCanvasFile(app, pathOrFile)) { return await applyCanvasChanges(abortSignal, content, getPath(app, pathOrFile), changesProvider, shouldRetryOnInvalidChanges); } return await applyContentChanges(abortSignal, content, getPath(app, pathOrFile), changesProvider, shouldRetryOnInvalidChanges); }, processOptions); } function isCanvasChange(change) { return isCanvasReference(change.reference); } function isCanvasFileNodeChange(change) { return isCanvasChange(change) && change.reference.type === "file"; } function isCanvasTextNodeChange(change) { return isCanvasChange(change) && change.reference.type === "text"; } function isContentChange(fileChange) { return isReferenceCache(fileChange.reference); } function isFrontmatterChange(fileChange) { return isFrontmatterLinkCache(fileChange.reference); } function isFrontmatterChangeWithOffsets(fileChange) { return isFrontmatterLinkCacheWithOffsets(fileChange.reference); } function toFrontmatterChangeWithOffsets(fileChange) { if (isFrontmatterChangeWithOffsets(fileChange)) { return fileChange; } return { ...fileChange, reference: toFrontmatterLinkCacheWithOffsets(fileChange.reference) }; } async function applyCanvasChanges(abortSignal, content, path, changesProvider, shouldRetryOnInvalidChanges = true) { const changes = await resolveValue(changesProvider, abortSignal, content); abortSignal.throwIfAborted(); if (changes === null) { return null; } const canvasData = parseJsonSafe(content); const canvasTextChanges = /* @__PURE__ */ new Map(); for (const change of changes) { if (!isCanvasChange(change)) { const message = "Only canvas changes are supported for canvas files"; console.error(message, { change, path }); throw new Error(message); } const node = canvasData.nodes[change.reference.nodeIndex]; if (!node) { const message = "Node not found"; console.error(message, { nodeIndex: change.reference.nodeIndex, path }); throw new Error(message); } if (isCanvasFileNodeChange(change)) { if (node.file !== change.oldContent) { getLibDebugger("FileChange:applyCanvasChanges")("Content mismatch", { actualContent: node.file, expectedContent: change.oldContent, nodeIndex: change.reference.nodeIndex, path, type: "file" }); return null; } node.file = change.newContent; } else if (isCanvasTextNodeChange(change)) { let canvasTextChangesForNode = canvasTextChanges.get(change.reference.nodeIndex); if (!canvasTextChangesForNode) { canvasTextChangesForNode = []; canvasTextChanges.set(change.reference.nodeIndex, canvasTextChangesForNode); } canvasTextChangesForNode.push(change); } } for (const [nodeIndex, canvasTextChangesForNode] of canvasTextChanges.entries()) { const node = canvasData.nodes[nodeIndex]; if (!node) { const message = "Node not found"; console.error(message, { nodeIndex, path }); throw new Error(message); } if (typeof node.text !== "string") { const message = "Node text is not a string"; console.error(message, { nodeIndex, path }); throw new Error(message); } const contentChanges = canvasTextChangesForNode.map((change) => referenceToFileChange(change.reference.originalReference, change.newContent)); node.text = await applyContentChanges( abortSignal, node.text, `${path}.node${String(nodeIndex)}.VIRTUAL_FILE.md`, contentChanges, shouldRetryOnInvalidChanges ); } return JSON.stringify(canvasData, null, " "); } function applyContentChangesToText(changes, content, hasFrontmatterError, path) { let newContent = ""; let lastIndex = 0; const frontmatterChangesWithOffsetMap = /* @__PURE__ */ new Map(); for (const change of changes) { if (isContentChange(change)) { newContent += content.slice(lastIndex, change.reference.position.start.offset); newContent += change.newContent; lastIndex = change.reference.position.end.offset; } else if (isFrontmatterChange(change)) { if (hasFrontmatterError) { console.error(`Cannot apply frontmatter change in ${path}, because frontmatter parsing failed`, { change }); } else { let frontmatterChangesWithOffsets = frontmatterChangesWithOffsetMap.get(change.reference.key); if (!frontmatterChangesWithOffsets) { frontmatterChangesWithOffsets = []; frontmatterChangesWithOffsetMap.set(change.reference.key, frontmatterChangesWithOffsets); } frontmatterChangesWithOffsets.push(toFrontmatterChangeWithOffsets(change)); } } } newContent += content.slice(lastIndex); return { frontmatterChanged: frontmatterChangesWithOffsetMap, newContent }; } async function applyFrontmatterChangesWithOffsets(abortSignal, frontmatter, frontmatterChangesWithOffsetMap, path) { for (const [key, frontmatterChangesWithOffsets] of frontmatterChangesWithOffsetMap.entries()) { const propertyValue = getNestedPropertyValue(frontmatter, key); if (typeof propertyValue !== "string") { return; } const contentChanges = frontmatterChangesWithOffsets.map((change) => ({ newContent: change.newContent, oldContent: change.oldContent, reference: { link: "", original: "", position: { end: { col: change.reference.endOffset, line: 0, offset: change.reference.endOffset }, start: { col: change.reference.startOffset, line: 0, offset: change.reference.startOffset } } } })); const newPropertyValue = await applyContentChanges(abortSignal, propertyValue, `${path}.frontmatter.${key}.VIRTUAL_FILE.md`, contentChanges); if (newPropertyValue === null) { return; } setNestedPropertyValue(frontmatter, key, newPropertyValue); } } function buildFinalContent(newContent, frontmatter, frontmatterChanged) { if (frontmatterChanged.size > 0) { return setFrontmatter(newContent, frontmatter); } return newContent; } function parseFrontmatterSafely(content, path) { let frontmatter = {}; let hasFrontmatterError = false; try { frontmatter = parseFrontmatter(content); } catch (error) { printError(new Error(`Frontmatter parsing failed in ${path}`, { cause: error })); hasFrontmatterError = true; } return { frontmatter, hasFrontmatterError }; } function parseJsonSafe(content) { let parsed; try { parsed = JSON.parse(content); } catch { parsed = null; } if (parsed === null || typeof parsed !== "object") { parsed = {}; } return parsed; } function sortAndFilterChanges(changes) { changes.sort((a, b) => { if (isContentChange(a) && isContentChange(b)) { return a.reference.position.start.offset - b.reference.position.start.offset; } if (isFrontmatterChangeWithOffsets(a) && isFrontmatterChangeWithOffsets(b)) { return a.reference.key.localeCompare(b.reference.key) || a.reference.startOffset - b.reference.startOffset; } if (isFrontmatterChange(a) && isFrontmatterChange(b)) { return a.reference.key.localeCompare(b.reference.key); } return isContentChange(a) ? -1 : 1; }); return changes.filter((change, index) => { if (change.oldContent === change.newContent) { return false; } if (index === 0) { return true; } return !deepEqual(change, changes[index - 1]); }); } function validateChangeOverlaps(changes) { for (let i = 1; i < changes.length; i++) { const change = changes[i]; if (!change) { continue; } const previousChange = changes[i - 1]; if (!previousChange) { continue; } if (isContentChange(previousChange) && isContentChange(change) && previousChange.reference.position.end.offset && previousChange.reference.position.end.offset > change.reference.position.start.offset) { const message = "Overlapping changes"; console.error(message, { change, previousChange }); throw new Error(message); } } return true; } function validateChanges(changes, content, frontmatter, path) { const validateChangesDebugger = getLibDebugger("FileChange:validateChanges"); for (const change of changes) { if (isContentChange(change)) { const startOffset = change.reference.position.start.offset; const endOffset = change.reference.position.end.offset; const actualContent = content.slice(startOffset, endOffset); if (actualContent !== change.oldContent) { validateChangesDebugger("Content mismatch", { actualContent, endOffset, expectedContent: change.oldContent, path, startOffset }); return false; } } else if (isFrontmatterChangeWithOffsets(change)) { const propertyValue = getNestedPropertyValue(frontmatter, change.reference.key); if (typeof propertyValue !== "string") { validateChangesDebugger("Property value is not a string", { frontmatterKey: change.reference.key, path, propertyValue }); return false; } const actualContent = propertyValue.slice(change.reference.startOffset, change.reference.endOffset); if (actualContent !== change.oldContent) { validateChangesDebugger("Content mismatch", { actualContent, expectedContent: change.oldContent, frontmatterKey: change.reference.key, path, startOffset: change.reference.startOffset }); return false; } } else if (isFrontmatterChange(change)) { const actualContent = getNestedPropertyValue(frontmatter, change.reference.key); if (actualContent !== change.oldContent) { validateChangesDebugger("Content mismatch", { actualContent, expectedContent: change.oldContent, frontmatterKey: change.reference.key, path }); return false; } } } return true; } export { applyContentChanges, applyFileChanges, isCanvasChange, isCanvasFileNodeChange, isCanvasTextNodeChange, isContentChange, isFrontmatterChange, isFrontmatterChangeWithOffsets, toFrontmatterChangeWithOffsets }; //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vLi4vc3JjL29ic2lkaWFuL0ZpbGVDaGFuZ2UudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8qKlxuICogQHBhY2thZ2VEb2N1bWVudGF0aW9uXG4gKlxuICogQ29udGFpbnMgdXRpbGl0eSB0eXBlcyBhbmQgZnVuY3Rpb25zIGZvciBoYW5kbGluZyBmaWxlIGNoYW5nZXMgaW4gT2JzaWRpYW4uXG4gKi9cblxuaW1wb3J0IHR5cGUge1xuICBBcHAsXG4gIEZyb250bWF0dGVyTGlua0NhY2hlLFxuICBSZWZlcmVuY2UsXG4gIFJlZmVyZW5jZUNhY2hlXG59IGZyb20gJ29ic2lkaWFuJztcbmltcG9ydCB0eXBlIHsgQ2FudmFzRGF0YSB9IGZyb20gJ29ic2lkaWFuL0NhbnZhcy5kLnRzJztcblxuaW1wb3J0IHtcbiAgaXNGcm9udG1hdHRlckxpbmtDYWNoZSxcbiAgaXNSZWZlcmVuY2VDYWNoZVxufSBmcm9tICdvYnNpZGlhbi10eXBpbmdzL2ltcGxlbWVudGF0aW9ucyc7XG5cbmltcG9ydCB0eXBlIHsgR2VuZXJpY09iamVjdCB9IGZyb20gJy4uL09iamVjdFV0aWxzLnRzJztcbmltcG9ydCB0eXBlIHsgVmFsdWVQcm92aWRlciB9IGZyb20gJy4uL1ZhbHVlUHJvdmlkZXIudHMnO1xuaW1wb3J0IHR5cGUgeyBQYXRoT3JGaWxlIH0gZnJvbSAnLi9GaWxlU3lzdGVtLnRzJztcbmltcG9ydCB0eXBlIHsgQ29tYmluZWRGcm9udG1hdHRlciB9IGZyb20gJy4vRnJvbnRtYXR0ZXIudHMnO1xuaW1wb3J0IHR5cGUgeyBGcm9udG1hdHRlckxpbmtDYWNoZVdpdGhPZmZzZXRzIH0gZnJvbSAnLi9Gcm9udG1hdHRlckxpbmtDYWNoZVdpdGhPZmZzZXRzLnRzJztcbmltcG9ydCB0eXBlIHtcbiAgQ2FudmFzRmlsZU5vZGVSZWZlcmVuY2UsXG4gIENhbnZhc1JlZmVyZW5jZSxcbiAgQ2FudmFzVGV4dE5vZGVSZWZlcmVuY2Vcbn0gZnJvbSAnLi9SZWZlcmVuY2UudHMnO1xuaW1wb3J0IHR5cGUgeyBQcm9jZXNzT3B0aW9ucyB9IGZyb20gJy4vVmF1bHQudHMnO1xuXG5pbXBvcnQgeyBnZXRMaWJEZWJ1Z2dlciB9IGZyb20gJy4uL0RlYnVnLnRzJztcbmltcG9ydCB7IHByaW50RXJyb3IgfSBmcm9tICcuLi9FcnJvci50cyc7XG5pbXBvcnQge1xuICBkZWVwRXF1YWwsXG4gIGdldE5lc3RlZFByb3BlcnR5VmFsdWUsXG4gIHNldE5lc3RlZFByb3BlcnR5VmFsdWVcbn0gZnJvbSAnLi4vT2JqZWN0VXRpbHMudHMnO1xuaW1wb3J0IHsgcmVzb2x2ZVZhbHVlIH0gZnJvbSAnLi4vVmFsdWVQcm92aWRlci50cyc7XG5pbXBvcnQge1xuICBnZXRQYXRoLFxuICBpc0NhbnZhc0ZpbGVcbn0gZnJvbSAnLi9GaWxlU3lzdGVtLnRzJztcbmltcG9ydCB7XG4gIHBhcnNlRnJvbnRtYXR0ZXIsXG4gIHNldEZyb250bWF0dGVyXG59IGZyb20gJy4vRnJvbnRtYXR0ZXIudHMnO1xuaW1wb3J0IHtcbiAgaXNGcm9udG1hdHRlckxpbmtDYWNoZVdpdGhPZmZzZXRzLFxuICB0b0Zyb250bWF0dGVyTGlua0NhY2hlV2l0aE9mZnNldHNcbn0gZnJvbSAnLi9Gcm9udG1hdHRlckxpbmtDYWNoZVdpdGhPZmZzZXRzLnRzJztcbmltcG9ydCB7XG4gIGlzQ2FudmFzUmVmZXJlbmNlLFxuICByZWZlcmVuY2VUb0ZpbGVDaGFuZ2Vcbn0gZnJvbSAnLi9SZWZlcmVuY2UudHMnO1xuaW1wb3J0IHsgcHJvY2VzcyB9IGZyb20gJy4vVmF1bHQudHMnO1xuXG4vKipcbiAqIEEgZmlsZSBjaGFuZ2UgaW4gdGhlIHZhdWx0LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEZpbGVDaGFuZ2Uge1xuICAvKipcbiAgICogQSBuZXcgY29udGVudCB0byByZXBsYWNlIHRoZSBvbGQgY29udGVudC5cbiAgICovXG4gIG5ld0NvbnRlbnQ6IHN0cmluZztcblxuICAvKipcbiAgICogQW4gb2xkIGNvbnRlbnQgdGhhdCB3aWxsIGJlIHJlcGxhY2VkLlxuICAgKi9cbiAgb2xkQ29udGVudDogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBBIHJlZmVyZW5jZSB0aGF0IGNhdXNlZCB0aGUgY2hhbmdlLlxuICAgKi9cbiAgcmVmZXJlbmNlOiBSZWZlcmVuY2U7XG59XG50eXBlIENhbnZhc0NoYW5nZSA9IHsgcmVmZXJlbmNlOiBDYW52YXNSZWZlcmVuY2UgfSAmIEZpbGVDaGFuZ2U7XG50eXBlIENhbnZhc0ZpbGVOb2RlQ2hhbmdlID0geyByZWZlcmVuY2U6IENhbnZhc0ZpbGVOb2RlUmVmZXJlbmNlIH0gJiBGaWxlQ2hhbmdlO1xudHlwZSBDYW52YXNUZXh0Tm9kZUNoYW5nZSA9IHsgcmVmZXJlbmNlOiBDYW52YXNUZXh0Tm9kZVJlZmVyZW5jZSB9ICYgRmlsZUNoYW5nZTtcbnR5cGUgQ29udGVudENoYW5nZSA9IHsgcmVmZXJlbmNlOiBSZWZlcmVuY2VDYWNoZSB9ICYgRmlsZUNoYW5nZTtcbnR5cGUgRnJvbnRtYXR0ZXJDaGFuZ2UgPSB7IHJlZmVyZW5jZTogRnJvbnRtYXR0ZXJMaW5rQ2FjaGUgfSAmIEZpbGVDaGFuZ2U7XG50eXBlIEZyb250bWF0dGVyQ2hhbmdlV2l0aE9mZnNldHMgPSB7IHJlZmVyZW5jZTogRnJvbnRtYXR0ZXJMaW5rQ2FjaGVXaXRoT2Zmc2V0cyB9ICYgRmlsZUNoYW5nZTtcblxuLyoqXG4gKiBBcHBsaWVzIGEgc2VyaWVzIG9mIGNvbnRlbnQgY2hhbmdlcyB0byB0aGUgc3BlY2lmaWVkIGNvbnRlbnQuXG4gKlxuICogQHBhcmFtIGFib3J0U2lnbmFsIC0gVGhlIGFib3J0IHNpZ25hbCB0byBjb250cm9sIHRoZSBleGVjdXRpb24gb2YgdGhlIGZ1bmN0aW9uLlxuICogQHBhcmFtIGNvbnRlbnQgLSBUaGUgY29udGVudCB0byB3aGljaCB0aGUgY2hhbmdlcyBzaG91bGQgYmUgYXBwbGllZC5cbiAqIEBwYXJhbSBwYXRoIC0gVGhlIHBhdGggdG8gd2hpY2ggdGhlIGNoYW5nZXMgc2hvdWxkIGJlIGFwcGxpZWQuXG4gKiBAcGFyYW0gY2hhbmdlc1Byb3ZpZGVyIC0gQSBwcm92aWRlciB0aGF0IHJldHVybnMgYW4gYXJyYXkgb2YgY29udGVudCBjaGFuZ2VzIHRvIGFwcGx5LlxuICogQHBhcmFtIHNob3VsZFJldHJ5T25JbnZhbGlkQ2hhbmdlcyAtIFdoZXRoZXIgdG8gcmV0cnkgdGhlIG9wZXJhdGlvbiBpZiB0aGUgY2hhbmdlcyBhcmUgaW52YWxpZC5cbiAqIEByZXR1cm5zIEEge0BsaW5rIFByb21pc2V9IHRoYXQgcmVzb2x2ZXMgdG8gdGhlIHVwZGF0ZWQgY29udGVudCBvciB0byBgbnVsbGAgaWYgdXBkYXRlIGRpZG4ndCBzdWNjZWVkLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gYXBwbHlDb250ZW50Q2hhbmdlcyhcbiAgYWJvcnRTaWduYWw6IEFib3J0U2lnbmFsLFxuICBjb250ZW50OiBzdHJpbmcsXG4gIHBhdGg6IHN0cmluZyxcbiAgY2hhbmdlc1Byb3ZpZGVyOiBWYWx1ZVByb3ZpZGVyPEZpbGVDaGFuZ2VbXSB8IG51bGwsIFtjb250ZW50OiBzdHJpbmddPixcbiAgc2hvdWxkUmV0cnlPbkludmFsaWRDaGFuZ2VzID0gdHJ1ZVxuKTogUHJvbWlzZTxudWxsIHwgc3RyaW5nPiB7XG4gIGFib3J0U2lnbmFsLnRocm93SWZBYm9ydGVkKCk7XG4gIGxldCBjaGFuZ2VzID0gYXdhaXQgcmVzb2x2ZVZhbHVlKGNoYW5nZXNQcm92aWRlciwgYWJvcnRTaWduYWwsIGNvbnRlbnQpO1xuICBhYm9ydFNpZ25hbC50aHJvd0lmQWJvcnRlZCgpO1xuICBpZiAoY2hhbmdlcyA9PT0gbnVsbCkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgY29uc3QgeyBmcm9udG1hdHRlciwgaGFzRnJvbnRtYXR0ZXJFcnJvciB9ID0gcGFyc2VGcm9udG1hdHRlclNhZmVseShjb250ZW50LCBwYXRoKTtcblxuICBpZiAoIXZhbGlkYXRlQ2hhbmdlcyhjaGFuZ2VzLCBjb250ZW50LCBmcm9udG1hdHRlciwgcGF0aCkpIHtcbiAgICByZXR1cm4gc2hvdWxkUmV0cnlPbkludmFsaWRDaGFuZ2VzID8gbnVsbCA6IGNvbnRlbnQ7XG4gIH1cblxuICBjaGFuZ2VzID0gc29ydEFuZEZpbHRlckNoYW5nZXMoY2hhbmdlcyk7XG5cbiAgaWYgKCF2YWxpZGF0ZUNoYW5nZU92ZXJsYXBzKGNoYW5nZXMpKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBjb25zdCB7IGZyb250bWF0dGVyQ2hhbmdlZCwgbmV3Q29udGVudCB9ID0gYXBwbHlDb250ZW50Q2hhbmdlc1RvVGV4dChjaGFuZ2VzLCBjb250ZW50LCBoYXNGcm9udG1hdHRlckVycm9yLCBwYXRoKTtcblxuICBhd2FpdCBhcHBseUZyb250bWF0dGVyQ2hhbmdlc1dpdGhPZmZzZXRzKGFib3J0U2lnbmFsLCBmcm9udG1hdHRlciwgZnJvbnRtYXR0ZXJDaGFuZ2VkLCBwYXRoKTtcbiAgYWJvcnRTaWduYWwudGhyb3dJZkFib3J0ZWQoKTtcblxuICByZXR1cm4gYnVpbGRGaW5hbENvbnRlbnQobmV3Q29udGVudCwgZnJvbnRtYXR0ZXIsIGZyb250bWF0dGVyQ2hhbmdlZCk7XG59XG5cbi8qKlxuICogQXBwbGllcyBhIHNlcmllcyBvZiBmaWxlIGNoYW5nZXMgdG8gdGhlIHNwZWNpZmllZCBmaWxlIG9yIHBhdGggd2l0aGluIHRoZSBhcHBsaWNhdGlvbi5cbiAqXG4gKiBAcGFyYW0gYXBwIC0gVGhlIGFwcGxpY2F0aW9uIGluc3RhbmNlIHdoZXJlIHRoZSBmaWxlIGNoYW5nZXMgd2lsbCBiZSBhcHBsaWVkLlxuICogQHBhcmFtIHBhdGhPckZpbGUgLSBUaGUgcGF0aCBvciBmaWxlIHRvIHdoaWNoIHRoZSBjaGFuZ2VzIHNob3VsZCBiZSBhcHBsaWVkLlxuICogQHBhcmFtIGNoYW5nZXNQcm92aWRlciAtIEEgcHJvdmlkZXIgdGhhdCByZXR1cm5zIGFuIGFycmF5IG9mIGZpbGUgY2hhbmdlcyB0byBhcHBseS5cbiAqIEBwYXJhbSBwcm9jZXNzT3B0aW9ucyAtIE9wdGlvbmFsIG9wdGlvbnMgZm9yIHByb2Nlc3NpbmcvcmV0cnlpbmcgdGhlIG9wZXJhdGlvbi5cbiAqIEBwYXJhbSBzaG91bGRSZXRyeU9uSW52YWxpZENoYW5nZXMgLSBXaGV0aGVyIHRvIHJldHJ5IHRoZSBvcGVyYXRpb24gaWYgdGhlIGNoYW5nZXMgYXJlIGludmFsaWQuXG4gKlxuICogQHJldHVybnMgQSB7QGxpbmsgUHJvbWlzZX0gdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBmaWxlIGNoYW5nZXMgaGF2ZSBiZWVuIHN1Y2Nlc3NmdWxseSBhcHBsaWVkLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gYXBwbHlGaWxlQ2hhbmdlcyhcbiAgYXBwOiBBcHAsXG4gIHBhdGhPckZpbGU6IFBhdGhPckZpbGUsXG4gIGNoYW5nZXNQcm92aWRlcjogVmFsdWVQcm92aWRlcjxGaWxlQ2hhbmdlW10gfCBudWxsLCBbY29udGVudDogc3RyaW5nXT4sXG4gIHByb2Nlc3NPcHRpb25zOiBQcm9jZXNzT3B0aW9ucyA9IHt9LFxuICBzaG91bGRSZXRyeU9uSW52YWxpZENoYW5nZXMgPSB0cnVlXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgYXdhaXQgcHJvY2VzcyhhcHAsIHBhdGhPckZpbGUsIGFzeW5jIChhYm9ydFNpZ25hbCwgY29udGVudCkgPT4ge1xuICAgIGlmIChpc0NhbnZhc0ZpbGUoYXBwLCBwYXRoT3JGaWxlKSkge1xuICAgICAgcmV0dXJuIGF3YWl0IGFwcGx5Q2FudmFzQ2hhbmdlcyhhYm9ydFNpZ25hbCwgY29udGVudCwgZ2V0UGF0aChhcHAsIHBhdGhPckZpbGUpLCBjaGFuZ2VzUHJvdmlkZXIsIHNob3VsZFJldHJ5T25JbnZhbGlkQ2hhbmdlcyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGF3YWl0IGFwcGx5Q29udGVudENoYW5nZXMoYWJvcnRTaWduYWwsIGNvbnRlbnQsIGdldFBhdGgoYXBwLCBwYXRoT3JGaWxlKSwgY2hhbmdlc1Byb3ZpZGVyLCBzaG91bGRSZXRyeU9uSW52YWxpZENoYW5nZXMpO1xuICB9LCBwcm9jZXNzT3B0aW9ucyk7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIGEgZmlsZSBjaGFuZ2UgaXMgYSBjYW52YXMgY2hhbmdlLlxuICpcbiAqIEBwYXJhbSBjaGFuZ2UgLSBUaGUgZmlsZSBjaGFuZ2UgdG8gY2hlY2suXG4gKiBAcmV0dXJucyBXaGV0aGVyIHRoZSBmaWxlIGNoYW5nZSBpcyBhIGNhbnZhcyBjaGFuZ2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0NhbnZhc0NoYW5nZShjaGFuZ2U6IEZpbGVDaGFuZ2UpOiBjaGFuZ2UgaXMgQ2FudmFzQ2hhbmdlIHtcbiAgcmV0dXJuIGlzQ2FudmFzUmVmZXJlbmNlKGNoYW5nZS5yZWZlcmVuY2UpO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiBhIGZpbGUgY2hhbmdlIGlzIGEgY2FudmFzIGZpbGUgbm9kZSBjaGFuZ2UuXG4gKlxuICogQHBhcmFtIGNoYW5nZSAtIFRoZSBmaWxlIGNoYW5nZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIFdoZXRoZXIgdGhlIGZpbGUgY2hhbmdlIGlzIGEgY2FudmFzIGZpbGUgbm9kZSBjaGFuZ2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0NhbnZhc0ZpbGVOb2RlQ2hhbmdlKGNoYW5nZTogRmlsZUNoYW5nZSk6IGNoYW5nZSBpcyBDYW52YXNGaWxlTm9kZUNoYW5nZSB7XG4gIHJldHVybiBpc0NhbnZhc0NoYW5nZShjaGFuZ2UpICYmIGNoYW5nZS5yZWZlcmVuY2UudHlwZSA9PT0gJ2ZpbGUnO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiBhIGZpbGUgY2hhbmdlIGlzIGEgY2FudmFzIHRleHQgbm9kZSBjaGFuZ2UuXG4gKlxuICogQHBhcmFtIGNoYW5nZSAtIFRoZSBmaWxlIGNoYW5nZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIFdoZXRoZXIgdGhlIGZpbGUgY2hhbmdlIGlzIGEgY2FudmFzIHRleHQgbm9kZSBjaGFuZ2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0NhbnZhc1RleHROb2RlQ2hhbmdlKGNoYW5nZTogRmlsZUNoYW5nZSk6IGNoYW5nZSBpcyBDYW52YXNUZXh0Tm9kZUNoYW5nZSB7XG4gIHJldHVybiBpc0NhbnZhc0NoYW5nZShjaGFuZ2UpICYmIGNoYW5nZS5yZWZlcmVuY2UudHlwZSA9PT0gJ3RleHQnO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiBhIGZpbGUgY2hhbmdlIGlzIGEgY29udGVudCBjaGFuZ2UuXG4gKlxuICogQHBhcmFtIGZpbGVDaGFuZ2UgLSBUaGUgZmlsZSBjaGFuZ2UgdG8gY2hlY2suXG4gKiBAcmV0dXJucyBBIGJvb2xlYW4gaW5kaWNhdGluZyB3aGV0aGVyIHRoZSBmaWxlIGNoYW5nZSBpcyBhIGNvbnRlbnQgY2hhbmdlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNDb250ZW50Q2hhbmdlKGZpbGVDaGFuZ2U6IEZpbGVDaGFuZ2UpOiBmaWxlQ2hhbmdlIGlzIENvbnRlbnRDaGFuZ2Uge1xuICByZXR1cm4gaXNSZWZlcmVuY2VDYWNoZShmaWxlQ2hhbmdlLnJlZmVyZW5jZSk7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIGEgZmlsZSBjaGFuZ2UgaXMgYSBmcm9udG1hdHRlciBjaGFuZ2UuXG4gKlxuICogQHBhcmFtIGZpbGVDaGFuZ2UgLSBUaGUgZmlsZSBjaGFuZ2UgdG8gY2hlY2suXG4gKiBAcmV0dXJucyBBIGJvb2xlYW4gaW5kaWNhdGluZyB3aGV0aGVyIHRoZSBmaWxlIGNoYW5nZSBpcyBhIGZyb250bWF0dGVyIGNoYW5nZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzRnJvbnRtYXR0ZXJDaGFuZ2UoZmlsZUNoYW5nZTogRmlsZUNoYW5nZSk6IGZpbGVDaGFuZ2UgaXMgRnJvbnRtYXR0ZXJDaGFuZ2Uge1xuICByZXR1cm4gaXNGcm9udG1hdHRlckxpbmtDYWNoZShmaWxlQ2hhbmdlLnJlZmVyZW5jZSk7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIGEgZmlsZSBjaGFuZ2UgaXMgYSBmcm9udG1hdHRlciBjaGFuZ2Ugd2l0aCBvZmZzZXRzLlxuICpcbiAqIEBwYXJhbSBmaWxlQ2hhbmdlIC0gVGhlIGZpbGUgY2hhbmdlIHRvIGNoZWNrLlxuICogQHJldHVybnMgQSBib29sZWFuIGluZGljYXRpbmcgd2hldGhlciB0aGUgZmlsZSBjaGFuZ2UgaXMgYSBmcm9udG1hdHRlciBjaGFuZ2Ugd2l0aCBvZmZzZXRzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNGcm9udG1hdHRlckNoYW5nZVdpdGhPZmZzZXRzKGZpbGVDaGFuZ2U6IEZpbGVDaGFuZ2UpOiBmaWxlQ2hhbmdlIGlzIEZyb250bWF0dGVyQ2hhbmdlV2l0aE9mZnNldHMge1xuICByZXR1cm4gaXNGcm9udG1hdHRlckxpbmtDYWNoZVdpdGhPZmZzZXRzKGZpbGVDaGFuZ2UucmVmZXJlbmNlKTtcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBhIGZyb250bWF0dGVyIGNoYW5nZSB0byBhIGZyb250bWF0dGVyIGNoYW5nZSB3aXRoIG9mZnNldHMuXG4gKlxuICogQHBhcmFtIGZpbGVDaGFuZ2UgLSBUaGUgZmlsZSBjaGFuZ2UgdG8gY29udmVydC5cbiAqIEByZXR1cm5zIFRoZSBjb252ZXJ0ZWQgZmlsZSBjaGFuZ2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0b0Zyb250bWF0dGVyQ2hhbmdlV2l0aE9mZnNldHMoZmlsZUNoYW5nZTogRnJvbnRtYXR0ZXJDaGFuZ2UpOiBGcm9udG1hdHRlckNoYW5nZVdpdGhPZmZzZXRzIHtcbiAgaWYgKGlzRnJvbnRtYXR0ZXJDaGFuZ2VXaXRoT2Zmc2V0cyhmaWxlQ2hhbmdlKSkge1xuICAgIHJldHVybiBmaWxlQ2hhbmdlO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICAuLi5maWxlQ2hhbmdlLFxuICAgIHJlZmVyZW5jZTogdG9Gcm9udG1hdHRlckxpbmtDYWNoZVdpdGhPZmZzZXRzKGZpbGVDaGFuZ2UucmVmZXJlbmNlKVxuICB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBhcHBseUNhbnZhc0NoYW5nZXMoXG4gIGFib3J0U2lnbmFsOiBBYm9ydFNpZ25hbCxcbiAgY29udGVudDogc3RyaW5nLFxuICBwYXRoOiBzdHJpbmcsXG4gIGNoYW5nZXNQcm92aWRlcjogVmFsdWVQcm92aWRlcjxGaWxlQ2hhbmdlW10gfCBudWxsLCBbY29udGVudDogc3RyaW5nXT4sXG4gIHNob3VsZFJldHJ5T25JbnZhbGlkQ2hhbmdlcyA9IHRydWVcbik6IFByb21pc2U8bnVsbCB8IHN0cmluZz4ge1xuICBjb25zdCBjaGFuZ2VzID0gYXdhaXQgcmVzb2x2ZVZhbHVlKGNoYW5nZXNQcm92aWRlciwgYWJvcnRTaWduYWwsIGNvbnRlbnQpO1xuICBhYm9ydFNpZ25hbC50aHJvd0lmQWJvcnRlZCgpO1xuICBpZiAoY2hhbmdlcyA9PT0gbnVsbCkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgY29uc3QgY2FudmFzRGF0YSA9IHBhcnNlSnNvblNhZmUoY29udGVudCkgYXMgQ2FudmFzRGF0YTtcblxuICBjb25zdCBjYW52YXNUZXh0Q2hhbmdlcyA9IG5ldyBNYXA8bnVtYmVyLCBDYW52YXNUZXh0Tm9kZUNoYW5nZVtdPigpO1xuXG4gIGZvciAoY29uc3QgY2hhbmdlIG9mIGNoYW5nZXMpIHtcbiAgICBpZiAoIWlzQ2FudmFzQ2hhbmdlKGNoYW5nZSkpIHtcbiAgICAgIGNvbnN0IG1lc3NhZ2UgPSAnT25seSBjYW52YXMgY2hhbmdlcyBhcmUgc3VwcG9ydGVkIGZvciBjYW52YXMgZmlsZXMnO1xuICAgICAgY29uc29sZS5lcnJvcihtZXNzYWdlLCB7XG4gICAgICAgIGNoYW5nZSxcbiAgICAgICAgcGF0aFxuICAgICAgfSk7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IobWVzc2FnZSk7XG4gICAgfVxuXG4gICAgY29uc3Qgbm9kZSA9IGNhbnZhc0RhdGEubm9kZXNbY2hhbmdlLnJlZmVyZW5jZS5ub2RlSW5kZXhdO1xuICAgIGlmICghbm9kZSkge1xuICAgICAgY29uc3QgbWVzc2FnZSA9ICdOb2RlIG5vdCBmb3VuZCc7XG4gICAgICBjb25zb2xlLmVycm9yKG1lc3NhZ2UsIHtcbiAgICAgICAgbm9kZUluZGV4OiBjaGFuZ2UucmVmZXJlbmNlLm5vZGVJbmRleCxcbiAgICAgICAgcGF0aFxuICAgICAgfSk7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IobWVzc2FnZSk7XG4gICAgfVxuXG4gICAgaWYgKGlzQ2FudmFzRmlsZU5vZGVDaGFuZ2UoY2hhbmdlKSkge1xuICAgICAgaWYgKG5vZGUuZmlsZSAhPT0gY2hhbmdlLm9sZENvbnRlbnQpIHtcbiAgICAgICAgZ2V0TGliRGVidWdnZXIoJ0ZpbGVDaGFuZ2U6YXBwbHlDYW52YXNDaGFuZ2VzJykoJ0NvbnRlbnQgbWlzbWF0Y2gnLCB7XG4gICAgICAgICAgYWN0dWFsQ29udGVudDogbm9kZS5maWxlIGFzIHN0cmluZyB8IHVuZGVmaW5lZCxcbiAgICAgICAgICBleHBlY3RlZENvbnRlbnQ6IGNoYW5nZS5vbGRDb250ZW50LFxuICAgICAgICAgIG5vZGVJbmRleDogY2hhbmdlLnJlZmVyZW5jZS5ub2RlSW5kZXgsXG4gICAgICAgICAgcGF0aCxcbiAgICAgICAgICB0eXBlOiAnZmlsZSdcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgICBub2RlLmZpbGUgPSBjaGFuZ2UubmV3Q29udGVudDtcbiAgICB9IGVsc2UgaWYgKGlzQ2FudmFzVGV4dE5vZGVDaGFuZ2UoY2hhbmdlKSkge1xuICAgICAgbGV0IGNhbnZhc1RleHRDaGFuZ2VzRm9yTm9kZSA9IGNhbnZhc1RleHRDaGFuZ2VzLmdldChjaGFuZ2UucmVmZXJlbmNlLm5vZGVJbmRleCk7XG4gICAgICBpZiAoIWNhbnZhc1RleHRDaGFuZ2VzRm9yTm9kZSkge1xuICAgICAgICBjYW52YXNUZXh0Q2hhbmdlc0Zvck5vZGUgPSBbXTtcbiAgICAgICAgY2FudmFzVGV4dENoYW5nZXMuc2V0KGNoYW5nZS5yZWZlcmVuY2Uubm9kZUluZGV4LCBjYW52YXNUZXh0Q2hhbmdlc0Zvck5vZGUpO1xuICAgICAgfVxuXG4gICAgICBjYW52YXNUZXh0Q2hhbmdlc0Zvck5vZGUucHVzaChjaGFuZ2UpO1xuICAgIH1cbiAgfVxuXG4gIGZvciAoY29uc3QgW25vZGVJbmRleCwgY2FudmFzVGV4dENoYW5nZXNGb3JOb2RlXSBvZiBjYW52YXNUZXh0Q2hhbmdlcy5lbnRyaWVzKCkpIHtcbiAgICBjb25zdCBub2RlID0gY2FudmFzRGF0YS5ub2Rlc1tub2RlSW5kZXhdO1xuICAgIGlmICghbm9kZSkge1xuICAgICAgY29uc3QgbWVzc2FnZSA9ICdOb2RlIG5vdCBmb3VuZCc7XG4gICAgICBjb25zb2xlLmVycm9yKG1lc3NhZ2UsIHtcbiAgICAgICAgbm9kZUluZGV4LFxuICAgICAgICBwYXRoXG4gICAgICB9KTtcblxuICAgICAgdGhyb3cgbmV3IEVycm9yKG1lc3NhZ2UpO1xuICAgIH1cblxuICAgIGlmICh0eXBlb2Ygbm9kZS50ZXh0ICE9PSAnc3RyaW5nJykge1xuICAgICAgY29uc3QgbWVzc2FnZSA9ICdOb2RlIHRleHQgaXMgbm90IGEgc3RyaW5nJztcbiAgICAgIGNvbnNvbGUuZXJyb3IobWVzc2FnZSwge1xuICAgICAgICBub2RlSW5kZXgsXG4gICAgICAgIHBhdGhcbiAgICAgIH0pO1xuXG4gICAgICB0aHJvdyBuZXcgRXJyb3IobWVzc2FnZSk7XG4gICAgfVxuXG4gICAgY29uc3QgY29udGVudENoYW5nZXMgPSBjYW52YXNUZXh0Q2hhbmdlc0Zvck5vZGUubWFwKChjaGFuZ2UpID0+IHJlZmVyZW5jZVRvRmlsZUNoYW5nZShjaGFuZ2UucmVmZXJlbmNlLm9yaWdpbmFsUmVmZXJlbmNlLCBjaGFuZ2UubmV3Q29udGVudCkpO1xuICAgIG5vZGUudGV4dCA9IGF3YWl0IGFwcGx5Q29udGVudENoYW5nZXMoXG4gICAgICBhYm9ydFNpZ25hbCxcbiAgICAgIG5vZGUudGV4dCxcbiAgICAgIGAke3BhdGh9Lm5vZGUke1N0cmluZyhub2RlSW5kZXgpfS5WSVJUVUFMX0ZJTEUubWRgLFxuICAgICAgY29udGVudENoYW5nZXMsXG4gICAgICBzaG91bGRSZXRyeU9uSW52YWxpZENoYW5nZXNcbiAgICApO1xuICB9XG5cbiAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KGNhbnZhc0RhdGEsIG51bGwsICdcXHQnKTtcbn1cblxuZnVuY3Rpb24gYXBwbHlDb250ZW50Q2hhbmdlc1RvVGV4dChcbiAgY2hhbmdlczogRmlsZUNoYW5nZVtdLFxuICBjb250ZW50OiBzdHJpbmcsXG4gIGhhc0Zyb250bWF0dGVyRXJyb3I6IGJvb2xlYW4sXG4gIHBhdGg6IHN0cmluZ1xuKTogeyBmcm9udG1hdHRlckNoYW5nZWQ6IE1hcDxzdHJpbmcsIEZyb250bWF0dGVyQ2hhbmdlV2l0aE9mZnNldHNbXT47IG5ld0NvbnRlbnQ6IHN0cmluZyB9IHtcbiAgbGV0IG5ld0NvbnRlbnQgPSAnJztcbiAgbGV0IGxhc3RJbmRleCA9IDA7XG4gIGNvbnN0IGZyb250bWF0dGVyQ2hhbmdlc1dpdGhPZmZzZXRNYXAgPSBuZXcgTWFwPHN0cmluZywgRnJvbnRtYXR0ZXJDaGFuZ2VXaXRoT2Zmc2V0c1tdPigpO1xuXG4gIGZvciAoY29uc3QgY2hhbmdlIG9mIGNoYW5nZXMpIHtcbiAgICBpZiAoaXNDb250ZW50Q2hhbmdlKGNoYW5nZSkpIHtcbiAgICAgIG5ld0NvbnRlbnQgKz0gY29udGVudC5zbGljZShsYXN0SW5kZXgsIGNoYW5nZS5yZWZlcmVuY2UucG9zaXRpb24uc3RhcnQub2Zmc2V0KTtcbiAgICAgIG5ld0NvbnRlbnQgKz0gY2hhbmdlLm5ld0NvbnRlbnQ7XG4gICAgICBsYXN0SW5kZXggPSBjaGFuZ2UucmVmZXJlbmNlLnBvc2l0aW9uLmVuZC5vZmZzZXQ7XG4gICAgfSBlbHNlIGlmIChpc0Zyb250bWF0dGVyQ2hhbmdlKGNoYW5nZSkpIHtcbiAgICAgIGlmIChoYXNGcm9udG1hdHRlckVycm9yKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoYENhbm5vdCBhcHBseSBmcm9udG1hdHRlciBjaGFuZ2UgaW4gJHtwYXRofSwgYmVjYXVzZSBmcm9udG1hdHRlciBwYXJzaW5nIGZhaWxlZGAsIHsgY2hhbmdlIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbGV0IGZyb250bWF0dGVyQ2hhbmdlc1dpdGhPZmZzZXRzID0gZnJvbnRtYXR0ZXJDaGFuZ2VzV2l0aE9mZnNldE1hcC5nZXQoY2hhbmdlLnJlZmVyZW5jZS5rZXkpO1xuICAgICAgICBpZiAoIWZyb250bWF0dGVyQ2hhbmdlc1dpdGhPZmZzZXRzKSB7XG4gICAgICAgICAgZnJvbnRtYXR0ZXJDaGFuZ2VzV2l0aE9mZnNldHMgPSBbXTtcbiAgICAgICAgICBmcm9udG1hdHRlckNoYW5nZXNXaXRoT2Zmc2V0TWFwLnNldChjaGFuZ2UucmVmZXJlbmNlLmtleSwgZnJvbnRtYXR0ZXJDaGFuZ2VzV2l0aE9mZnNldHMpO1xuICAgICAgICB9XG4gICAgICAgIGZyb250bWF0dGVyQ2hhbmdlc1dpdGhPZmZzZXRzLnB1c2godG9Gcm9udG1hdHRlckNoYW5nZVdpdGhPZmZzZXRzKGNoYW5nZSkpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIG5ld0NvbnRlbnQgKz0gY29udGVudC5zbGljZShsYXN0SW5kZXgpO1xuXG4gIHJldHVybiB7IGZyb250bWF0dGVyQ2hhbmdlZDogZnJvbnRtYXR0ZXJDaGFuZ2VzV2l0aE9mZnNldE1hcCwgbmV3Q29udGVudCB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBhcHBseUZyb250bWF0dGVyQ2hhbmdlc1dpdGhPZmZzZXRzKFxuICBhYm9ydFNpZ25hbDogQWJvcnRTaWduYWwsXG4gIGZyb250bWF0dGVyOiBDb21iaW5lZEZyb250bWF0dGVyPHVua25vd24+LFxuICBmcm9udG1hdHRlckNoYW5nZXNXaXRoT2Zmc2V0TWFwOiBNYXA8c3RyaW5nLCBGcm9udG1hdHRlckNoYW5nZVdpdGhPZmZzZXRzW10+LFxuICBwYXRoOiBzdHJpbmdcbik6IFByb21pc2U8dm9pZD4ge1xuICBmb3IgKGNvbnN0IFtrZXksIGZyb250bWF0dGVyQ2hhbmdlc1dpdGhPZmZzZXRzXSBvZiBmcm9udG1hdHRlckNoYW5nZXNXaXRoT2Zmc2V0TWFwLmVudHJpZXMoKSkge1xuICAgIGNvbnN0IHByb3BlcnR5VmFsdWUgPSBnZXROZXN0ZWRQcm9wZXJ0eVZhbHVlKGZyb250bWF0dGVyLCBrZXkpO1xuICAgIGlmICh0eXBlb2YgcHJvcGVydHlWYWx1ZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBjb250ZW50Q2hhbmdlczogQ29udGVudENoYW5nZVtdID0gZnJvbnRtYXR0ZXJDaGFuZ2VzV2l0aE9mZnNldHMubWFwKChjaGFuZ2UpID0+ICh7XG4gICAgICBuZXdDb250ZW50OiBjaGFuZ2UubmV3Q29udGVudCxcbiAgICAgIG9sZENvbnRlbnQ6IGNoYW5nZS5vbGRDb250ZW50LFxuICAgICAgcmVmZXJlbmNlOiB7XG4gICAgICAgIGxpbms6ICcnLFxuICAgICAgICBvcmlnaW5hbDogJycsXG4gICAgICAgIHBvc2l0aW9uOiB7XG4gICAgICAgICAgZW5kOiB7XG4gICAgICAgICAgICBjb2w6IGNoYW5nZS5yZWZlcmVuY2UuZW5kT2Zmc2V0LFxuICAgICAgICAgICAgbGluZTogMCxcbiAgICAgICAgICAgIG9mZnNldDogY2hhbmdlLnJlZmVyZW5jZS5lbmRPZmZzZXRcbiAgICAgICAgICB9LFxuICAgICAgICAgIHN0YXJ0OiB7XG4gICAgICAgICAgICBjb2w6IGNoYW5nZS5yZWZlcmVuY2Uuc3RhcnRPZmZzZXQsXG4gICAgICAgICAgICBsaW5lOiAwLFxuICAgICAgICAgICAgb2Zmc2V0OiBjaGFuZ2UucmVmZXJlbmNlLnN0YXJ0T2Zmc2V0XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBhcyBDb250ZW50Q2hhbmdlKSk7XG5cbiAgICBjb25zdCBuZXdQcm9wZXJ0eVZhbHVlID0gYXdhaXQgYXBwbHlDb250ZW50Q2hhbmdlcyhhYm9ydFNpZ25hbCwgcHJvcGVydHlWYWx1ZSwgYCR7cGF0aH0uZnJvbnRtYXR0ZXIuJHtrZXl9LlZJUlRVQUxfRklMRS5tZGAsIGNvbnRlbnRDaGFuZ2VzKTtcbiAgICBpZiAobmV3UHJvcGVydHlWYWx1ZSA9PT0gbnVsbCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHNldE5lc3RlZFByb3BlcnR5VmFsdWUoZnJvbnRtYXR0ZXIsIGtleSwgbmV3UHJvcGVydHlWYWx1ZSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gYnVpbGRGaW5hbENvbnRlbnQoXG4gIG5ld0NvbnRlbnQ6IHN0cmluZyxcbiAgZnJvbnRtYXR0ZXI6IENvbWJpbmVkRnJvbnRtYXR0ZXI8dW5rbm93bj4sXG4gIGZyb250bWF0dGVyQ2hhbmdlZDogTWFwPHN0cmluZywgRnJvbnRtYXR0ZXJDaGFuZ2VXaXRoT2Zmc2V0c1tdPlxuKTogc3RyaW5nIHtcbiAgaWYgKGZyb250bWF0dGVyQ2hhbmdlZC5zaXplID4gMCkge1xuICAgIHJldHVybiBzZXRGcm9udG1hdHRlcihuZXdDb250ZW50LCBmcm9udG1hdHRlcik7XG4gIH1cbiAgcmV0dXJuIG5ld0NvbnRlbnQ7XG59XG5cbmZ1bmN0aW9uIHBhcnNlRnJvbnRtYXR0ZXJTYWZlbHkoY29udGVudDogc3RyaW5nLCBwYXRoOiBzdHJpbmcpOiB7IGZyb250bWF0dGVyOiBDb21iaW5lZEZyb250bWF0dGVyPHVua25vd24+OyBoYXNGcm9udG1hdHRlckVycm9yOiBib29sZWFuIH0ge1xuICBsZXQgZnJvbnRtYXR0ZXI6IENvbWJpbmVkRnJvbnRtYXR0ZXI8dW5rbm93bj4gPSB7fTtcbiAgbGV0IGhhc0Zyb250bWF0dGVyRXJyb3IgPSBmYWxzZTtcblxuICB0cnkge1xuICAgIGZyb250bWF0dGVyID0gcGFyc2VGcm9udG1hdHRlcihjb250ZW50KTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBwcmludEVycm9yKG5ldyBFcnJvcihgRnJvbnRtYXR0ZXIgcGFyc2luZyBmYWlsZWQgaW4gJHtwYXRofWAsIHsgY2F1c2U6IGVycm9yIH0pKTtcbiAgICBoYXNGcm9udG1hdHRlckVycm9yID0gdHJ1ZTtcbiAgfVxuXG4gIHJldHVybiB7IGZyb250bWF0dGVyLCBoYXNGcm9udG1hdHRlckVycm9yIH07XG59XG5cbmZ1bmN0aW9uIHBhcnNlSnNvblNhZmUoY29udGVudDogc3RyaW5nKTogR2VuZXJpY09iamVjdCB7XG4gIGxldCBwYXJzZWQ6IHVua25vd247XG4gIHRyeSB7XG4gICAgcGFyc2VkID0gSlNPTi5wYXJzZShjb250ZW50KTtcbiAgfSBjYXRjaCB7XG4gICAgcGFyc2VkID0gbnVsbDtcbiAgfVxuXG4gIGlmIChwYXJzZWQgPT09IG51bGwgfHwgdHlwZW9mIHBhcnNlZCAhPT0gJ29iamVjdCcpIHtcbiAgICBwYXJzZWQgPSB7fTtcbiAgfVxuXG4gIHJldHVybiBwYXJzZWQgYXMgR2VuZXJpY09iamVjdDtcbn1cblxuZnVuY3Rpb24gc29ydEFuZEZpbHRlckNoYW5nZXMoY2hhbmdlczogRmlsZUNoYW5nZVtdKTogRmlsZUNoYW5nZVtdIHtcbiAgLy8gU29ydCBjaGFuZ2VzIGJ5IHR5cGUgYW5kIHBvc2l0aW9uXG4gIGNoYW5nZXMuc29ydCgoYSwgYikgPT4ge1xuICAgIGlmIChpc0NvbnRlbnRDaGFuZ2UoYSkgJiYgaXNDb250ZW50Q2hhbmdlKGIpKSB7XG4gICAgICByZXR1cm4gYS5yZWZlcmVuY2UucG9zaXRpb24uc3RhcnQub2Zmc2V0IC0gYi5yZWZlcmVuY2UucG9zaXRpb24uc3RhcnQub2Zmc2V0O1xuICAgIH1cblxuICAgIGlmIChpc0Zyb250bWF0dGVyQ2hhbmdlV2l0aE9mZnNldHMoYSkgJiYgaXNGcm9udG1hdHRlckNoYW5nZVdpdGhPZmZzZXRzKGIpKSB7XG4gICAgICByZXR1cm4gYS5yZWZlcmVuY2Uua2V5LmxvY2FsZUNvbXBhcmUoYi5yZWZlcmVuY2Uua2V5KSB8fCBhLnJlZmVyZW5jZS5zdGFydE9mZnNldCAtIGIucmVmZXJlbmNlLnN0YXJ0T2Zmc2V0O1xuICAgIH1cblxuICAgIGlmIChpc0Zyb250bWF0dGVyQ2hhbmdlKGEpICYmIGlzRnJvbnRtYXR0ZXJDaGFuZ2UoYikpIHtcbiAgICAgIHJldHVybiBhLnJlZmVyZW5jZS5rZXkubG9jYWxlQ29tcGFyZShiLnJlZmVyZW5jZS5rZXkpO1xuICAgIH1cblxuICAgIHJldHVybiBpc0NvbnRlbnRDaGFuZ2UoYSkgPyAtMSA6IDE7XG4gIH0pO1xuXG4gIC8vIEZpbHRlciBvdXQgZHVwbGljYXRlIGFuZCBuby1vcCBjaGFuZ2VzXG4gIHJldHVybiBjaGFuZ2VzLmZpbHRlcigoY2hhbmdlLCBpbmRleCkgPT4ge1xuICAgIGlmIChjaGFuZ2Uub2xkQ29udGVudCA9PT0gY2hhbmdlLm5ld0NvbnRlbnQpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgaWYgKGluZGV4ID09PSAwKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuICFkZWVwRXF1YWwoY2hhbmdlLCBjaGFuZ2VzW2luZGV4IC0gMV0pO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gdmFsaWRhdGVDaGFuZ2VPdmVybGFwcyhjaGFuZ2VzOiBGaWxlQ2hhbmdlW10pOiBib29sZWFuIHtcbiAgZm9yIChsZXQgaSA9IDE7IGkgPCBjaGFuZ2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgY29uc3QgY2hhbmdlID0gY2hhbmdlc1tpXTtcbiAgICBpZiAoIWNoYW5nZSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgY29uc3QgcHJldmlvdXNDaGFuZ2UgPSBjaGFuZ2VzW2kgLSAxXTtcbiAgICBpZiAoIXByZXZpb3VzQ2hhbmdlKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBpZiAoXG4gICAgICBpc0NvbnRlbnRDaGFuZ2UocHJldmlvdXNDaGFuZ2UpXG4gICAgICAmJiBpc0NvbnRlbnRDaGFuZ2UoY2hhbmdlKVxuICAgICAgJiYgcHJldmlvdXNDaGFuZ2UucmVmZXJlbmNlLnBvc2l0aW9uLmVuZC5vZmZzZXRcbiAgICAgICYmIHByZXZpb3VzQ2hhbmdlLnJlZmVyZW5jZS5wb3NpdGlvbi5lbmQub2Zmc2V0ID4gY2hhbmdlLnJlZmVyZW5jZS5wb3NpdGlvbi5zdGFydC5vZmZzZXRcbiAgICApIHtcbiAgICAgIGNvbnN0IG1lc3NhZ2UgPSAnT3ZlcmxhcHBpbmcgY2hhbmdlcyc7XG4gICAgICBjb25zb2xlLmVycm9yKG1lc3NhZ2UsIHsgY2hhbmdlLCBwcmV2aW91c0NoYW5nZSB9KTtcbiAgICAgIHRocm93IG5ldyBFcnJvcihtZXNzYWdlKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIHZhbGlkYXRlQ2hhbmdlcyhjaGFuZ2VzOiBGaWxlQ2hhbmdlW10sIGNvbnRlbnQ6IHN0cmluZywgZnJvbnRtYXR0ZXI6IENvbWJpbmVkRnJvbnRtYXR0ZXI8dW5rbm93bj4sIHBhdGg6IHN0cmluZyk6IGJvb2xlYW4ge1xuICBjb25zdCB2YWxpZGF0ZUNoYW5nZXNEZWJ1Z2dlciA9IGdldExpYkRlYnVnZ2VyKCdGaWxlQ2hhbmdlOnZhbGlkYXRlQ2hhbmdlcycpO1xuICBmb3IgKGNvbnN0IGNoYW5nZSBvZiBjaGFuZ2VzKSB7XG4gICAgaWYgKGlzQ29udGVudENoYW5nZShjaGFuZ2UpKSB7XG4gICAgICBjb25zdCBzdGFydE9mZnNldCA9IGNoYW5nZS5yZWZlcmVuY2UucG9zaXRpb24uc3RhcnQub2Zmc2V0O1xuICAgICAgY29uc3QgZW5kT2Zmc2V0ID0gY2hhbmdlLnJlZmVyZW5jZS5wb3NpdGlvbi5lbmQub2Zmc2V0O1xuICAgICAgY29uc3QgYWN0dWFsQ29udGVudCA9IGNvbnRlbnQuc2xpY2Uoc3RhcnRPZmZzZXQsIGVuZE9mZnNldCk7XG4gICAgICBpZiAoYWN0dWFsQ29udGVudCAhPT0gY2hhbmdlLm9sZENvbnRlbnQpIHtcbiAgICAgICAgdmFsaWRhdGVDaGFuZ2VzRGVidWdnZXIoJ0NvbnRlbnQgbWlzbWF0Y2gnLCB7XG4gICAgICAgICAgYWN0dWFsQ29udGVudCxcbiAgICAgICAgICBlbmRPZmZzZXQsXG4gICAgICAgICAgZXhwZWN0ZWRDb250ZW50OiBjaGFuZ2Uub2xkQ29udGVudCxcbiAgICAgICAgICBwYXRoLFxuICAgICAgICAgIHN0YXJ0T2Zmc2V0XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGlzRnJvbnRtYXR0ZXJDaGFuZ2VXaXRoT2Zmc2V0cyhjaGFuZ2UpKSB7XG4gICAgICBjb25zdCBwcm9wZXJ0eVZhbHVlID0gZ2V0TmVzdGVkUHJvcGVydHlWYWx1ZShmcm9udG1hdHRlciwgY2hhbmdlLnJlZmVyZW5jZS5rZXkpO1xuICAgICAgaWYgKHR5cGVvZiBwcm9wZXJ0eVZhbHVlICE9PSAnc3RyaW5nJykge1xuICAgICAgICB2YWxpZGF0ZUNoYW5nZXNEZWJ1Z2dlcignUHJvcGVydHkgdmFsdWUgaXMgbm90IGEgc3RyaW5nJywge1xuICAgICAgICAgIGZyb250bWF0dGVyS2V5OiBjaGFuZ2UucmVmZXJlbmNlLmtleSxcbiAgICAgICAgICBwYXRoLFxuICAgICAgICAgIHByb3BlcnR5VmFsdWVcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgYWN0dWFsQ29udGVudCA9IHByb3BlcnR5VmFsdWUuc2xpY2UoY2hhbmdlLnJlZmVyZW5jZS5zdGFydE9mZnNldCwgY2hhbmdlLnJlZmVyZW5jZS5lbmRPZmZzZXQpO1xuICAgICAgaWYgKGFjdHVhbENvbnRlbnQgIT09IGNoYW5nZS5vbGRDb250ZW50KSB7XG4gICAgICAgIHZhbGlkYXRlQ2hhbmdlc0RlYnVnZ2VyKCdDb250ZW50IG1pc21hdGNoJywge1xuICAgICAgICAgIGFjdHVhbENvbnRlbnQsXG4gICAgICAgICAgZXhwZWN0ZWRDb250ZW50OiBjaGFuZ2Uub2xkQ29udGVudCxcbiAgICAgICAgICBmcm9udG1hdHRlcktleTogY2hhbmdlLnJlZmVyZW5jZS5rZXksXG4gICAgICAgICAgcGF0aCxcbiAgICAgICAgICBzdGFydE9mZnNldDogY2hhbmdlLnJlZmVyZW5jZS5zdGFydE9mZnNldFxuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChpc0Zyb250bWF0dGVyQ2hhbmdlKGNoYW5nZSkpIHtcbiAgICAgIGNvbnN0IGFjdHVhbENvbnRlbnQgPSBnZXROZXN0ZWRQcm9wZXJ0eVZhbHVlKGZyb250bWF0dGVyLCBjaGFuZ2UucmVmZXJlbmNlLmtleSk7XG4gICAgICBpZiAoYWN0dWFsQ29udGVudCAhPT0gY2hhbmdlLm9sZENvbnRlbnQpIHtcbiAgICAgICAgdmFsaWRhdGVDaGFuZ2VzRGVidWdnZXIoJ0NvbnRlbnQgbWlzbWF0Y2gnLCB7XG4gICAgICAgICAgYWN0dWFsQ29udGVudCxcbiAgICAgICAgICBleHBlY3RlZENvbnRlbnQ6IGNoYW5nZS5vbGRDb250ZW50LFxuICAgICAgICAgIGZyb250bWF0dGVyS2V5OiBjaGFuZ2UucmVmZXJlbmNlLmtleSxcbiAgICAgICAgICBwYXRoXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn1cbiJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7QUFjQTtBQUFBLEVBQ0U7QUFBQSxFQUNBO0FBQUEsT0FDSztBQWNQLFNBQVMsc0JBQXNCO0FBQy9CLFNBQVMsa0JBQWtCO0FBQzNCO0FBQUEsRUFDRTtBQUFBLEVBQ0E7QUFBQSxFQUNBO0FBQUEsT0FDSztBQUNQLFNBQVMsb0JBQW9CO0FBQzdCO0FBQUEsRUFDRTtBQUFBLEVBQ0E7QUFBQSxPQUNLO0FBQ1A7QUFBQSxFQUNFO0FBQUEsRUFDQTtBQUFBLE9BQ0s7QUFDUDtBQUFBLEVBQ0U7QUFBQSxFQUNBO0FBQUEsT0FDSztBQUNQO0FBQUEsRUFDRTtBQUFBLEVBQ0E7QUFBQSxPQUNLO0FBQ1AsU0FBUyxlQUFlO0FBc0N4QixlQUFzQixvQkFDcEIsYUFDQSxTQUNBLE1BQ0EsaUJBQ0EsOEJBQThCLE1BQ047QUFDeEIsY0FBWSxlQUFlO0FBQzNCLE1BQUksVUFBVSxNQUFNLGFBQWEsaUJBQWlCLGFBQWEsT0FBTztBQUN0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