ngx-extended-pdf-viewer
Version:
Embedding PDF files in your Angular application. Highly configurable viewer including the toolbar, sidebar, and all the features you're used to.
430 lines • 65.7 kB
JavaScript
import { Subject } from 'rxjs';
import { NgxExtendedPdfViewerComponent } from './ngx-extended-pdf-viewer.component';
export class NgxExtendedPdfViewerService {
constructor() {
this.recalculateSize$ = new Subject();
}
findMultiple(text, options = {}) {
options = {
...options,
findMultipleSearchTexts: true,
};
const searchString = text.join('\n') + '\n';
return this.find(searchString, options);
}
find(text, options = {}) {
if (!NgxExtendedPdfViewerComponent.ngxExtendedPdfViewerInitialized) {
// tslint:disable-next-line:quotemark
console.error("The PDF viewer hasn't finished initializing. Please call find() later.");
return false;
}
else {
const highlightAllCheckbox = document.getElementById('findHighlightAll');
if (highlightAllCheckbox) {
highlightAllCheckbox.checked = options.highlightAll || false;
}
const findPageRange = document.getElementById('findRange');
if (findPageRange) {
findPageRange.value = options.pageRange || '';
}
const findCurrentPageCheckbox = document.getElementById('findCurrentPage');
if (findCurrentPageCheckbox) {
findCurrentPageCheckbox.checked = options.currentPage || false;
}
const matchCaseCheckbox = document.getElementById('findMatchCase');
if (matchCaseCheckbox) {
matchCaseCheckbox.checked = options.matchCase || false;
}
const entireWordCheckbox = document.getElementById('findEntireWord');
if (entireWordCheckbox) {
entireWordCheckbox.checked = options.wholeWords || false;
}
const findIgnoreAccentsCheckbox = document.getElementById('findIgnoreAccents');
if (findIgnoreAccentsCheckbox) {
findIgnoreAccentsCheckbox.checked = options.ignoreAccents || false;
}
const multipleSearchTerms = options.findMultipleSearchTexts || text.includes('\n') || false;
const findMultipleSearchTextsCheckbox = document.getElementById('findMultipleSearchTexts');
if (findMultipleSearchTextsCheckbox) {
findMultipleSearchTextsCheckbox.checked = multipleSearchTerms;
}
const individualWordsModeCheckbox = document.getElementById('individualWordsMode');
if (individualWordsModeCheckbox) {
individualWordsModeCheckbox.checked = false;
}
const fuzzySearchCheckbox = document.getElementById('findFuzzy');
if (fuzzySearchCheckbox) {
fuzzySearchCheckbox.checked = options.fuzzySearch || false;
}
const inputField = multipleSearchTerms ? document.getElementById('findInputMultiline') : document.getElementById('findInput');
if (inputField) {
if (inputField instanceof HTMLTextAreaElement) {
inputField.value = text;
// todo dirty hack!
inputField.classList.remove('hidden');
document.getElementById('findInput').classList.add('hidden');
document.getElementById('individualWordsModeLabel').classList.remove('hidden');
document.getElementById('individualWordsMode').classList.remove('hidden');
// end of the dirty hack
}
else if (inputField instanceof HTMLInputElement) {
inputField.value = text;
// todo dirty hack!
inputField.classList.remove('hidden');
document.getElementById('findInputMultiline').classList.add('hidden');
document.getElementById('individualWordsModeLabel').classList.add('hidden');
document.getElementById('individualWordsMode').classList.add('hidden');
// end of the dirty hack
}
inputField.dispatchEvent(new Event('input'));
return true;
}
else {
// tslint:disable-next-line:quotemark
console.error("Unexpected error: the input field used to search isn't part of the DOM.");
return false;
}
}
}
findNext() {
if (!NgxExtendedPdfViewerComponent.ngxExtendedPdfViewerInitialized) {
// tslint:disable-next-line:quotemark
console.error("The PDF viewer hasn't finished initializing. Please call findNext() later.");
return false;
}
else {
const button = document.getElementById('findNext');
if (button) {
button.click();
return true;
}
return false;
}
}
findPrevious() {
if (!NgxExtendedPdfViewerComponent.ngxExtendedPdfViewerInitialized) {
// tslint:disable-next-line:quotemark
console.error("The PDF viewer hasn't finished initializing. Please call findPrevious() later.");
return false;
}
else {
const button = document.getElementById('findPrevious');
if (button) {
button.click();
return true;
}
return false;
}
}
print(printRange) {
const PDFViewerApplication = window.PDFViewerApplication;
const alreadyThere = !!window['isInPDFPrintRange'] && !printRange;
if (!alreadyThere) {
if (!printRange) {
printRange = {};
}
this.setPrintRange(printRange);
}
window.printPDF();
if (!alreadyThere) {
PDFViewerApplication.eventBus.on('afterprint', () => {
this.removePrintRange();
});
}
}
removePrintRange() {
window['isInPDFPrintRange'] = undefined;
window['filteredPageCount'] = undefined;
}
setPrintRange(printRange) {
const PDFViewerApplication = window.PDFViewerApplication;
window['isInPDFPrintRange'] = (page) => this.isInPDFPrintRange(page, printRange);
window['filteredPageCount'] = this.filteredPageCount(PDFViewerApplication.pagesCount, printRange);
}
filteredPageCount(pageCount, range) {
let result = 0;
for (let page = 1; page <= pageCount; page++) {
if (this.isInPDFPrintRange(page, range)) {
result++;
}
}
return result;
}
isInPDFPrintRange(pageIndex, printRange) {
const page = pageIndex + 1;
if (printRange.from) {
if (page < printRange.from) {
return false;
}
}
if (printRange.to) {
if (page > printRange.to) {
return false;
}
}
if (printRange.excluded) {
const e = printRange.excluded;
if (e.some((p) => p === page)) {
return false;
}
}
if (printRange.included) {
if (!printRange.included.some((p) => p === page)) {
return false;
}
}
return true;
}
async getPageAsLines(pageNumber) {
const PDFViewerApplication = window.PDFViewerApplication;
const pdfDocument = PDFViewerApplication.pdfDocument;
const page = await pdfDocument.getPage(pageNumber);
const textSnippets = (await page.getTextContent()).items //
.filter((info) => !info['type']); // ignore the TextMarkedContent items
const snippets = textSnippets;
let minX = Number.MAX_SAFE_INTEGER;
let minY = Number.MAX_SAFE_INTEGER;
let maxX = Number.MIN_SAFE_INTEGER;
let maxY = Number.MIN_SAFE_INTEGER;
let countLTR = 0;
let countRTL = 0;
let text = '';
let lines = new Array();
for (let i = 0; i < snippets.length; i++) {
const currentSnippet = snippets[i];
if (!currentSnippet.hasEOL) {
const x = currentSnippet.transform[4];
const y = -currentSnippet.transform[5];
const width = currentSnippet.width;
const height = currentSnippet.height;
minX = Math.min(minX, x);
minY = Math.min(minY, y);
maxX = Math.max(maxX, x + width);
maxY = Math.max(maxY, y + height);
text += currentSnippet.str;
if (currentSnippet.dir === 'rtl') {
countRTL++;
}
if (currentSnippet.dir === 'ltr') {
countLTR++;
}
}
let addIt = i === snippets.length - 1 || currentSnippet.hasEOL;
if (addIt) {
const direction = countLTR > 0 ? (countRTL > 0 ? 'both' : 'ltr') : countRTL > 0 ? 'rtl' : undefined;
const line = {
direction,
x: minX,
y: minY,
width: maxX - minX,
height: maxY - minY,
text: text.trim(),
};
lines.push(line);
minX = Number.MAX_SAFE_INTEGER;
minY = Number.MAX_SAFE_INTEGER;
maxX = Number.MIN_SAFE_INTEGER;
maxY = Number.MIN_SAFE_INTEGER;
countLTR = 0;
countRTL = 0;
text = '';
}
}
return lines;
}
async getPageAsText(pageNumber) {
const PDFViewerApplication = window.PDFViewerApplication;
const pdfDocument = PDFViewerApplication.pdfDocument;
const page = await pdfDocument.getPage(pageNumber);
const textSnippets = (await page.getTextContent()).items;
return this.convertTextInfoToText(textSnippets);
}
convertTextInfoToText(textInfoItems) {
if (!textInfoItems) {
return '';
}
return textInfoItems
.filter((info) => !info['type'])
.map((info) => (info.hasEOL ? info.str + '\n' : info.str))
.join('');
}
getPageAsImage(pageNumber, scale, background, backgroundColorToReplace = '#FFFFFF') {
const PDFViewerApplication = window.PDFViewerApplication;
const pdfDocument = PDFViewerApplication.pdfDocument;
const pagePromise = pdfDocument.getPage(pageNumber);
const imagePromise = (pdfPage) => Promise.resolve(this.draw(pdfPage, scale, background, backgroundColorToReplace));
return pagePromise.then(imagePromise);
}
draw(pdfPage, scale, background, backgroundColorToReplace = '#FFFFFF') {
let zoomFactor = 1;
if (scale.scale) {
zoomFactor = scale.scale;
}
else if (scale.width) {
zoomFactor = scale.width / pdfPage.getViewport({ scale: 1 }).width;
}
else if (scale.height) {
zoomFactor = scale.height / pdfPage.getViewport({ scale: 1 }).height;
}
const viewport = pdfPage.getViewport({
scale: zoomFactor,
});
const { ctx, canvas } = this.getPageDrawContext(viewport.width, viewport.height);
const drawViewport = viewport.clone();
const renderContext = {
canvasContext: ctx,
viewport: drawViewport,
background,
backgroundColorToReplace,
};
const renderTask = pdfPage.render(renderContext);
const dataUrlPromise = () => Promise.resolve(canvas.toDataURL());
return renderTask.promise.then(dataUrlPromise);
}
getPageDrawContext(width, height) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d', { alpha: true });
if (!ctx) {
// tslint:disable-next-line: quotemark
throw new Error("Couldn't create the 2d context");
}
canvas.width = width;
canvas.height = height;
canvas.style.width = `${width}px`;
canvas.style.height = `${height}px`;
return { ctx, canvas };
}
async getCurrentDocumentAsBlob() {
const PDFViewerApplication = window.PDFViewerApplication;
const data = await PDFViewerApplication.pdfDocument.saveDocument(); // (PDFViewerApplication.pdfDocument.annotationStorage);
return new Blob([data], { type: 'application/pdf' });
}
async getFormData(currentFormValues = true) {
const PDFViewerApplication = window.PDFViewerApplication;
const pdf = PDFViewerApplication.pdfDocument;
// screen DPI / PDF DPI
const dpiRatio = 96 / 72;
const result = [];
for (let i = 1; i <= pdf?.numPages; i++) {
// track the current page
const currentPage /* : PDFPageProxy */ = await pdf.getPage(i);
const annotations = await currentPage.getAnnotations();
annotations
.filter((a) => a.subtype === 'Widget') // get the form field annotations only
.map((a) => ({ ...a })) // only expose copies of the annotations to avoid side-effects
.forEach((a) => {
// get the rectangle that represent the single field
// and resize it according to the current DPI
const fieldRect = currentPage.getViewport({ scale: dpiRatio }).convertToViewportRectangle(a.rect);
// add the corresponding input
if (currentFormValues && a.fieldName) {
try {
if (a.exportValue) {
const currentValue = PDFViewerApplication.pdfDocument.annotationStorage.getValue(a.id, a.fieldName + '/' + a.exportValue, '');
a.value = currentValue?.value;
}
else if (a.radioButton) {
const currentValue = PDFViewerApplication.pdfDocument.annotationStorage.getValue(a.id, a.fieldName + '/' + a.fieldValue, '');
a.value = currentValue?.value;
}
else {
const currentValue = PDFViewerApplication.pdfDocument.annotationStorage.getValue(a.id, a.fieldName, '');
a.value = currentValue?.value;
}
}
catch (exception) {
// just ignore it
}
}
result.push({ fieldAnnotation: a, fieldRect, pageNumber: i });
});
}
return result;
}
/**
* Adds a page to the rendering queue
* @param {number} pageIndex Index of the page to render
* @returns {boolean} false, if the page has already been rendered
* or if it's out of range
*/
addPageToRenderQueue(pageIndex) {
const PDFViewerApplication = window.PDFViewerApplication;
return PDFViewerApplication.pdfViewer.addPageToRenderQueue(pageIndex);
}
isRenderQueueEmpty() {
const scrolledDown = true;
const renderExtra = false;
const PDFViewerApplication = window.PDFViewerApplication;
const nextPage = PDFViewerApplication.pdfViewer.renderingQueue.getHighestPriority(PDFViewerApplication.pdfViewer._getVisiblePages(), PDFViewerApplication.pdfViewer._pages, scrolledDown, renderExtra);
return !nextPage;
}
hasPageBeenRendered(pageIndex) {
const PDFViewerApplication = window.PDFViewerApplication;
const pages = PDFViewerApplication.pdfViewer._pages;
if (pages.length > pageIndex && pageIndex >= 0) {
const pageView = pages[pageIndex];
const isLoading = pageView.div.querySelector('.loadingIcon');
return !isLoading;
}
return false;
}
currentlyRenderedPages() {
const PDFViewerApplication = window.PDFViewerApplication;
const pages = PDFViewerApplication.pdfViewer._pages;
return pages.filter((page) => !page.div.querySelector('.loadingIcon')).map((page) => page.id);
}
numberOfPages() {
const PDFViewerApplication = window.PDFViewerApplication;
const pages = PDFViewerApplication.pdfViewer._pages;
return pages.length;
}
getCurrentlyVisiblePageNumbers() {
const app = window.PDFViewerApplication;
const pages = app.pdfViewer._getVisiblePages().views;
return pages?.map((page) => page.id);
}
recalculateSize() {
this.recalculateSize$.next();
}
async listLayers() {
const PDFViewerApplication = window.PDFViewerApplication;
const optionalContentConfig = await PDFViewerApplication.pdfViewer.optionalContentConfigPromise;
if (optionalContentConfig) {
const levelData = optionalContentConfig.getOrder();
console.log(levelData);
const layerIds = levelData.filter((groupId) => typeof groupId !== 'object');
return layerIds.map((layerId) => {
const config = optionalContentConfig.getGroup(layerId);
return {
layerId: layerId,
name: config.name,
visible: config.visible,
};
});
}
return undefined;
}
async toggleLayer(layerId) {
const PDFViewerApplication = window.PDFViewerApplication;
const optionalContentConfig = await PDFViewerApplication.pdfViewer.optionalContentConfigPromise;
if (optionalContentConfig) {
let isVisible = optionalContentConfig.getGroup(layerId).visible;
const checkbox = document.querySelector(`input[id='${layerId}']`);
if (checkbox) {
isVisible = checkbox.checked;
checkbox.checked = !isVisible;
}
optionalContentConfig.setVisibility(layerId, !isVisible);
PDFViewerApplication.eventBus.dispatch('optionalcontentconfig', {
source: this,
promise: Promise.resolve(optionalContentConfig),
});
}
}
scrollPageIntoView(pageNumber, pageSpot) {
const PDFViewerApplication = window.PDFViewerApplication;
const viewer = PDFViewerApplication.pdfViewer;
viewer.scrollPagePosIntoView(pageNumber, pageSpot);
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LWV4dGVuZGVkLXBkZi12aWV3ZXIuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1leHRlbmRlZC1wZGYtdmlld2VyL3NyYy9saWIvbmd4LWV4dGVuZGVkLXBkZi12aWV3ZXIuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQy9CLE9BQU8sRUFBRSw2QkFBNkIsRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBNENwRixNQUFNLE9BQU8sMkJBQTJCO0lBQXhDO1FBQ1MscUJBQWdCLEdBQUcsSUFBSSxPQUFPLEVBQVEsQ0FBQztJQTZjaEQsQ0FBQztJQTNjUSxZQUFZLENBQUMsSUFBbUIsRUFBRSxVQUF1QixFQUFFO1FBQ2hFLE9BQU8sR0FBRztZQUNSLEdBQUcsT0FBTztZQUNWLHVCQUF1QixFQUFFLElBQUk7U0FDOUIsQ0FBQztRQUNGLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDO1FBQzVDLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDMUMsQ0FBQztJQUVNLElBQUksQ0FBQyxJQUFZLEVBQUUsVUFBdUIsRUFBRTtRQUNqRCxJQUFJLENBQUMsNkJBQTZCLENBQUMsK0JBQStCLEVBQUU7WUFDbEUscUNBQXFDO1lBQ3JDLE9BQU8sQ0FBQyxLQUFLLENBQUMsd0VBQXdFLENBQUMsQ0FBQztZQUN4RixPQUFPLEtBQUssQ0FBQztTQUNkO2FBQU07WUFDTCxNQUFNLG9CQUFvQixHQUFHLFFBQVEsQ0FBQyxjQUFjLENBQUMsa0JBQWtCLENBQXFCLENBQUM7WUFDN0YsSUFBSSxvQkFBb0IsRUFBRTtnQkFDeEIsb0JBQW9CLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQyxZQUFZLElBQUksS0FBSyxDQUFD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QUFNLENBQUMscUJBQXFCLENBQUMsVUFBVSxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBQ3JELENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFN1YmplY3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IE5neEV4dGVuZGVkUGRmVmlld2VyQ29tcG9uZW50IH0gZnJvbSAnLi9uZ3gtZXh0ZW5kZWQtcGRmLXZpZXdlci5jb21wb25lbnQnO1xuaW1wb3J0IHsgUGRmTGF5ZXIgfSBmcm9tICcuL29wdGlvbnMvb3B0aW9uYWxfY29udGVudF9jb25maWcnO1xuaW1wb3J0IHsgUERGUHJpbnRSYW5nZSB9IGZyb20gJy4vb3B0aW9ucy9wZGYtcHJpbnQtcmFuZ2UnO1xuaW1wb3J0IHsgSVBERlZpZXdlckFwcGxpY2F0aW9uLCBQREZEb2N1bWVudFByb3h5LCBUZXh0SXRlbSwgVGV4dE1hcmtlZENvbnRlbnQgfSBmcm9tICcuL29wdGlvbnMvcGRmLXZpZXdlci1hcHBsaWNhdGlvbic7XG5cbmV4cG9ydCBpbnRlcmZhY2UgRmluZE9wdGlvbnMge1xuICBoaWdobGlnaHRBbGw/OiBib29sZWFuO1xuICBtYXRjaENhc2U/OiBib29sZWFuO1xuICB3aG9sZVdvcmRzPzogYm9vbGVhbjtcbiAgaWdub3JlQWNjZW50cz86IGJvb2xlYW47XG4gIGZpbmRNdWx0aXBsZVNlYXJjaFRleHRzPzogYm9vbGVhbjtcbiAgZnV6enlTZWFyY2g/OiBib29sZWFuO1xuICBjdXJyZW50UGFnZT86IGJvb2xlYW47IC8vIHNlYXJjaCBvbmx5IGluIHRoZSBjdXJyZW50IHBhZ2VcbiAgcGFnZVJhbmdlPzogc3RyaW5nOyAvLyBwYWdlIHJhbmdlIGRlZmluaXRpb24sIGUuZy4gXCIyXCIsIFwiMiwzLDRcIiwgXCI1LTZcIiBvciBcIjIsNS02LDdcIlxufVxuXG5pbnRlcmZhY2UgRHJhd0NvbnRleHQge1xuICBjdHg6IENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRDtcbiAgY2FudmFzOiBIVE1MQ2FudmFzRWxlbWVudDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBQREZFeHBvcnRTY2FsZUZhY3RvciB7XG4gIHdpZHRoPzogbnVtYmVyO1xuICBoZWlnaHQ/OiBudW1iZXI7XG4gIHNjYWxlPzogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIExpbmUge1xuICB4OiBudW1iZXI7XG4gIHk6IG51bWJlcjtcbiAgd2lkdGg6IG51bWJlcjtcbiAgaGVpZ2h0OiBudW1iZXI7XG4gIGRpcmVjdGlvbjogJ2x0cicgfCAncnRsJyB8ICdib3RoJyB8IHVuZGVmaW5lZDtcbiAgdGV4dDogc3RyaW5nO1xufVxuZXhwb3J0IGludGVyZmFjZSBTZWN0aW9uIHtcbiAgeDogbnVtYmVyO1xuICB5OiBudW1iZXI7XG4gIHdpZHRoOiBudW1iZXI7XG4gIGhlaWdodDogbnVtYmVyO1xuICBkaXJlY3Rpb246ICdsdHInIHwgJ3J0bCcgfCAnYm90aCcgfCB1bmRlZmluZWQ7XG4gIGxpbmVzOiBBcnJheTxMaW5lPjtcbn1cblxuZXhwb3J0IGNsYXNzIE5neEV4dGVuZGVkUGRmVmlld2VyU2VydmljZSB7XG4gIHB1YmxpYyByZWNhbGN1bGF0ZVNpemUkID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcblxuICBwdWJsaWMgZmluZE11bHRpcGxlKHRleHQ6IEFycmF5PHN0cmluZz4sIG9wdGlvbnM6IEZpbmRPcHRpb25zID0ge30pOiBib29sZWFuIHtcbiAgICBvcHRpb25zID0ge1xuICAgICAgLi4ub3B0aW9ucyxcbiAgICAgIGZpbmRNdWx0aXBsZVNlYXJjaFRleHRzOiB0cnVlLFxuICAgIH07XG4gICAgY29uc3Qgc2VhcmNoU3RyaW5nID0gdGV4dC5qb2luKCdcXG4nKSArICdcXG4nO1xuICAgIHJldHVybiB0aGlzLmZpbmQoc2VhcmNoU3RyaW5nLCBvcHRpb25zKTtcbiAgfVxuXG4gIHB1YmxpYyBmaW5kKHRleHQ6IHN0cmluZywgb3B0aW9uczogRmluZE9wdGlvbnMgPSB7fSk6IGJvb2xlYW4ge1xuICAgIGlmICghTmd4RXh0ZW5kZWRQZGZWaWV3ZXJDb21wb25lbnQubmd4RXh0ZW5kZWRQZGZWaWV3ZXJJbml0aWFsaXplZCkge1xuICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOnF1b3RlbWFya1xuICAgICAgY29uc29sZS5lcnJvcihcIlRoZSBQREYgdmlld2VyIGhhc24ndCBmaW5pc2hlZCBpbml0aWFsaXppbmcuIFBsZWFzZSBjYWxsIGZpbmQoKSBsYXRlci5cIik7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGhpZ2hsaWdodEFsbENoZWNrYm94ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2ZpbmRIaWdobGlnaHRBbGwnKSBhcyBIVE1MSW5wdXRFbGVtZW50O1xuICAgICAgaWYgKGhpZ2hsaWdodEFsbENoZWNrYm94KSB7XG4gICAgICAgIGhpZ2hsaWdodEFsbENoZWNrYm94LmNoZWNrZWQgPSBvcHRpb25zLmhpZ2hsaWdodEFsbCB8fCBmYWxzZTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGZpbmRQYWdlUmFuZ2UgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZmluZFJhbmdlJykgYXMgSFRNTElucHV0RWxlbWVudDtcbiAgICAgIGlmIChmaW5kUGFnZVJhbmdlKSB7XG4gICAgICAgIGZpbmRQYWdlUmFuZ2UudmFsdWUgPSBvcHRpb25zLnBhZ2VSYW5nZSB8fCAnJztcbiAgICAgIH1cbiAgICAgIGNvbnN0IGZpbmRDdXJyZW50UGFnZUNoZWNrYm94ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2ZpbmRDdXJyZW50UGFnZScpIGFzIEhUTUxJbnB1dEVsZW1lbnQ7XG4gICAgICBpZiAoZmluZEN1cnJlbnRQYWdlQ2hlY2tib3gpIHtcbiAgICAgICAgZmluZEN1cnJlbnRQYWdlQ2hlY2tib3guY2hlY2tlZCA9IG9wdGlvbnMuY3VycmVudFBhZ2UgfHwgZmFsc2U7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IG1hdGNoQ2FzZUNoZWNrYm94ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2ZpbmRNYXRjaENhc2UnKSBhcyBIVE1MSW5wdXRFbGVtZW50O1xuICAgICAgaWYgKG1hdGNoQ2FzZUNoZWNrYm94KSB7XG4gICAgICAgIG1hdGNoQ2FzZUNoZWNrYm94LmNoZWNrZWQgPSBvcHRpb25zLm1hdGNoQ2FzZSB8fCBmYWxzZTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGVudGlyZVdvcmRDaGVja2JveCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdmaW5kRW50aXJlV29yZCcpIGFzIEhUTUxJbnB1dEVsZW1lbnQ7XG4gICAgICBpZiAoZW50aXJlV29yZENoZWNrYm94KSB7XG4gICAgICAgIGVudGlyZVdvcmRDaGVja2JveC5jaGVja2VkID0gb3B0aW9ucy53aG9sZVdvcmRzIHx8IGZhbHNlO1xuICAgICAgfVxuICAgICAgY29uc3QgZmluZElnbm9yZUFjY2VudHNDaGVja2JveCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdmaW5kSWdub3JlQWNjZW50cycpIGFzIEhUTUxJbnB1dEVsZW1lbnQ7XG4gICAgICBpZiAoZmluZElnbm9yZUFjY2VudHNDaGVja2JveCkge1xuICAgICAgICBmaW5kSWdub3JlQWNjZW50c0NoZWNrYm94LmNoZWNrZWQgPSBvcHRpb25zLmlnbm9yZUFjY2VudHMgfHwgZmFsc2U7XG4gICAgICB9XG4gICAgICBjb25zdCBtdWx0aXBsZVNlYXJjaFRlcm1zID0gb3B0aW9ucy5maW5kTXVsdGlwbGVTZWFyY2hUZXh0cyB8fCB0ZXh0LmluY2x1ZGVzKCdcXG4nKSB8fCBmYWxzZTtcbiAgICAgIGNvbnN0IGZpbmRNdWx0aXBsZVNlYXJjaFRleHRzQ2hlY2tib3ggPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZmluZE11bHRpcGxlU2VhcmNoVGV4dHMnKSBhcyBIVE1MSW5wdXRFbGVtZW50O1xuICAgICAgaWYgKGZpbmRNdWx0aXBsZVNlYXJjaFRleHRzQ2hlY2tib3gpIHtcbiAgICAgICAgZmluZE11bHRpcGxlU2VhcmNoVGV4dHNDaGVja2JveC5jaGVja2VkID0gbXVsdGlwbGVTZWFyY2hUZXJtcztcbiAgICAgIH1cbiAgICAgIGNvbnN0IGluZGl2aWR1YWxXb3Jkc01vZGVDaGVja2JveCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdpbmRpdmlkdWFsV29yZHNNb2RlJykgYXMgSFRNTElucHV0RWxlbWVudDtcbiAgICAgIGlmIChpbmRpdmlkdWFsV29yZHNNb2RlQ2hlY2tib3gpIHtcbiAgICAgICAgaW5kaXZpZHVhbFdvcmRzTW9kZUNoZWNrYm94LmNoZWNrZWQgPSBmYWxzZTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGZ1enp5U2VhcmNoQ2hlY2tib3ggPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZmluZEZ1enp5JykgYXMgSFRNTElucHV0RWxlbWVudDtcbiAgICAgIGlmIChmdXp6eVNlYXJjaENoZWNrYm94KSB7XG4gICAgICAgIGZ1enp5U2VhcmNoQ2hlY2tib3guY2hlY2tlZCA9IG9wdGlvbnMuZnV6enlTZWFyY2ggfHwgZmFsc2U7XG4gICAgICB9XG4gICAgICBjb25zdCBpbnB1dEZpZWxkID0gbXVsdGlwbGVTZWFyY2hUZXJtcyA/IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdmaW5kSW5wdXRNdWx0aWxpbmUnKSA6IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdmaW5kSW5wdXQnKTtcbiAgICAgIGlmIChpbnB1dEZpZWxkKSB7XG4gICAgICAgIGlmIChpbnB1dEZpZWxkIGluc3RhbmNlb2YgSFRNTFRleHRBcmVhRWxlbWVudCkge1xuICAgICAgICAgIGlucHV0RmllbGQudmFsdWUgPSB0ZXh0O1xuXG4gICAgICAgICAgLy8gdG9kbyBkaXJ0eSBoYWNrIVxuICAgICAgICAgIGlucHV0RmllbGQuY2xhc3NMaXN0LnJlbW92ZSgnaGlkZGVuJyk7XG4gICAgICAgICAgKGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdmaW5kSW5wdXQnKSBhcyBIVE1MSW5wdXRFbGVtZW50KS5jbGFzc0xpc3QuYWRkKCdoaWRkZW4nKTtcbiAgICAgICAgICAoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2luZGl2aWR1YWxXb3Jkc01vZGVMYWJlbCcpIGFzIEhUTUxJbnB1dEVsZW1lbnQpLmNsYXNzTGlzdC5yZW1vdmUoJ2hpZGRlbicpO1xuICAgICAgICAgIChkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnaW5kaXZpZHVhbFdvcmRzTW9kZScpIGFzIEhUTUxJbnB1dEVsZW1lbnQpLmNsYXNzTGlzdC5yZW1vdmUoJ2hpZGRlbicpO1xuICAgICAgICAgIC8vIGVuZCBvZiB0aGUgZGlydHkgaGFja1xuICAgICAgICB9IGVsc2UgaWYgKGlucHV0RmllbGQgaW5zdGFuY2VvZiBIVE1MSW5wdXRFbGVtZW50KSB7XG4gICAgICAgICAgaW5wdXRGaWVsZC52YWx1ZSA9IHRleHQ7XG4gICAgICAgICAgLy8gdG9kbyBkaXJ0eSBoYWNrIVxuICAgICAgICAgIGlucHV0RmllbGQuY2xhc3NMaXN0LnJlbW92ZSgnaGlkZGVuJyk7XG4gICAgICAgICAgKGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdmaW5kSW5wdXRNdWx0aWxpbmUnKSBhcyBIVE1MSW5wdXRFbGVtZW50KS5jbGFzc0xpc3QuYWRkKCdoaWRkZW4nKTtcbiAgICAgICAgICAoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2luZGl2aWR1YWxXb3Jkc01vZGVMYWJlbCcpIGFzIEhUTUxJbnB1dEVsZW1lbnQpLmNsYXNzTGlzdC5hZGQoJ2hpZGRlbicpO1xuICAgICAgICAgIChkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnaW5kaXZpZHVhbFdvcmRzTW9kZScpIGFzIEhUTUxJbnB1dEVsZW1lbnQpLmNsYXNzTGlzdC5hZGQoJ2hpZGRlbicpO1xuICAgICAgICAgIC8vIGVuZCBvZiB0aGUgZGlydHkgaGFja1xuICAgICAgICB9XG4gICAgICAgIGlucHV0RmllbGQuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnQoJ2lucHV0JykpO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpxdW90ZW1hcmtcbiAgICAgICAgY29uc29sZS5lcnJvcihcIlVuZXhwZWN0ZWQgZXJyb3I6IHRoZSBpbnB1dCBmaWVsZCB1c2VkIHRvIHNlYXJjaCBpc24ndCBwYXJ0IG9mIHRoZSBET00uXCIpO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGZpbmROZXh0KCk6IGJvb2xlYW4ge1xuICAgIGlmICghTmd4RXh0ZW5kZWRQZGZWaWV3ZXJDb21wb25lbnQubmd4RXh0ZW5kZWRQZGZWaWV3ZXJJbml0aWFsaXplZCkge1xuICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOnF1b3RlbWFya1xuICAgICAgY29uc29sZS5lcnJvcihcIlRoZSBQREYgdmlld2VyIGhhc24ndCBmaW5pc2hlZCBpbml0aWFsaXppbmcuIFBsZWFzZSBjYWxsIGZpbmROZXh0KCkgbGF0ZXIuXCIpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBidXR0b24gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZmluZE5leHQnKTtcbiAgICAgIGlmIChidXR0b24pIHtcbiAgICAgICAgYnV0dG9uLmNsaWNrKCk7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBmaW5kUHJldmlvdXMoKTogYm9vbGVhbiB7XG4gICAgaWYgKCFOZ3hFeHRlbmRlZFBkZlZpZXdlckNvbXBvbmVudC5uZ3hFeHRlbmRlZFBkZlZpZXdlckluaXRpYWxpemVkKSB7XG4gICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6cXVvdGVtYXJrXG4gICAgICBjb25zb2xlLmVycm9yKFwiVGhlIFBERiB2aWV3ZXIgaGFzbid0IGZpbmlzaGVkIGluaXRpYWxpemluZy4gUGxlYXNlIGNhbGwgZmluZFByZXZpb3VzKCkgbGF0ZXIuXCIpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBidXR0b24gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZmluZFByZXZpb3VzJyk7XG4gICAgICBpZiAoYnV0dG9uKSB7XG4gICAgICAgIGJ1dHRvbi5jbGljaygpO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgcHJpbnQocHJpbnRSYW5nZT86IFBERlByaW50UmFuZ2UpIHtcbiAgICBjb25zdCBQREZWaWV3ZXJBcHBsaWNhdGlvbjogSVBERlZpZXdlckFwcGxpY2F0aW9uID0gKHdpbmRvdyBhcyBhbnkpLlBERlZpZXdlckFwcGxpY2F0aW9uO1xuICAgIGNvbnN0IGFscmVhZHlUaGVyZSA9ICEhd2luZG93Wydpc0luUERGUHJpbnRSYW5nZSddICYmICFwcmludFJhbmdlO1xuICAgIGlmICghYWxyZWFkeVRoZXJlKSB7XG4gICAgICBpZiAoIXByaW50UmFuZ2UpIHtcbiAgICAgICAgcHJpbnRSYW5nZSA9IHt9IGFzIFBERlByaW50UmFuZ2U7XG4gICAgICB9XG4gICAgICB0aGlzLnNldFByaW50UmFuZ2UocHJpbnRSYW5nZSk7XG4gICAgfVxuICAgICh3aW5kb3cgYXMgYW55KS5wcmludFBERigpO1xuICAgIGlmICghYWxyZWFkeVRoZXJlKSB7XG4gICAgICBQREZWaWV3ZXJBcHBsaWNhdGlvbi5ldmVudEJ1cy5vbignYWZ0ZXJwcmludCcsICgpID0+IHtcbiAgICAgICAgdGhpcy5yZW1vdmVQcmludFJhbmdlKCk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgcmVtb3ZlUHJpbnRSYW5nZSgpIHtcbiAgICB3aW5kb3dbJ2lzSW5QREZQcmludFJhbmdlJ10gPSB1bmRlZmluZWQ7XG4gICAgd2luZG93WydmaWx0ZXJlZFBhZ2VDb3VudCddID0gdW5kZWZpbmVkO1xuICB9XG5cbiAgcHVibGljIHNldFByaW50UmFuZ2UocHJpbnRSYW5nZTogUERGUHJpbnRSYW5nZSkge1xuICAgIGNvbnN0IFBERlZpZXdlckFwcGxpY2F0aW9uOiBJUERGVmlld2VyQXBwbGljYXRpb24gPSAod2luZG93IGFzIGFueSkuUERGVmlld2VyQXBwbGljYXRpb247XG4gICAgd2luZG93Wydpc0luUERGUHJpbnRSYW5nZSddID0gKHBhZ2U6IG51bWJlcikgPT4gdGhpcy5pc0luUERGUHJpbnRSYW5nZShwYWdlLCBwcmludFJhbmdlIGFzIFBERlByaW50UmFuZ2UpO1xuICAgIHdpbmRvd1snZmlsdGVyZWRQYWdlQ291bnQnXSA9IHRoaXMuZmlsdGVyZWRQYWdlQ291bnQoUERGVmlld2VyQXBwbGljYXRpb24ucGFnZXNDb3VudCwgcHJpbnRSYW5nZSk7XG4gIH1cblxuICBwdWJsaWMgZmlsdGVyZWRQYWdlQ291bnQocGFnZUNvdW50OiBudW1iZXIsIHJhbmdlOiBQREZQcmludFJhbmdlKTogbnVtYmVyIHtcbiAgICBsZXQgcmVzdWx0ID0gMDtcbiAgICBmb3IgKGxldCBwYWdlID0gMTsgcGFnZSA8PSBwYWdlQ291bnQ7IHBhZ2UrKykge1xuICAgICAgaWYgKHRoaXMuaXNJblBERlByaW50UmFuZ2UocGFnZSwgcmFuZ2UpKSB7XG4gICAgICAgIHJlc3VsdCsrO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgcHVibGljIGlzSW5QREZQcmludFJhbmdlKHBhZ2VJbmRleDogbnVtYmVyLCBwcmludFJhbmdlOiBQREZQcmludFJhbmdlKSB7XG4gICAgY29uc3QgcGFnZSA9IHBhZ2VJbmRleCArIDE7XG4gICAgaWYgKHByaW50UmFuZ2UuZnJvbSkge1xuICAgICAgaWYgKHBhZ2UgPCBwcmludFJhbmdlLmZyb20pIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAocHJpbnRSYW5nZS50bykge1xuICAgICAgaWYgKHBhZ2UgPiBwcmludFJhbmdlLnRvKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKHByaW50UmFuZ2UuZXhjbHVkZWQpIHtcbiAgICAgIGNvbnN0IGUgPSBwcmludFJhbmdlLmV4Y2x1ZGVkIGFzIEFycmF5PG51bWJlcj47XG4gICAgICBpZiAoZS5zb21lKChwKSA9PiBwID09PSBwYWdlKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChwcmludFJhbmdlLmluY2x1ZGVkKSB7XG4gICAgICBpZiAoIXByaW50UmFuZ2UuaW5jbHVkZWQuc29tZSgocCkgPT4gcCA9PT0gcGFnZSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBnZXRQYWdlQXNMaW5lcyhwYWdlTnVtYmVyOiBudW1iZXIpOiBQcm9taXNlPEFycmF5PExpbmU+PiB7XG4gICAgY29uc3QgUERGVmlld2VyQXBwbGljYXRpb246IElQREZWaWV3ZXJBcHBsaWNhdGlvbiA9ICh3aW5kb3cgYXMgYW55KS5QREZWaWV3ZXJBcHBsaWNhdGlvbjtcbiAgICBjb25zdCBwZGZEb2N1bWVudCA9IFBERlZpZXdlckFwcGxpY2F0aW9uLnBkZkRvY3VtZW50O1xuXG4gICAgY29uc3QgcGFnZSA9IGF3YWl0IHBkZkRvY3VtZW50LmdldFBhZ2UocGFnZU51bWJlcik7XG4gICAgY29uc3QgdGV4dFNuaXBwZXRzID0gKGF3YWl0IHBhZ2UuZ2V0VGV4dENvbnRlbnQoKSkuaXRlbXMgLy9cbiAgICAgIC5maWx0ZXIoKGluZm8pID0+ICFpbmZvWyd0eXBlJ10pOyAvLyBpZ25vcmUgdGhlIFRleHRNYXJrZWRDb250ZW50IGl0ZW1zXG5cbiAgICBjb25zdCBzbmlwcGV0cyA9IHRleHRTbmlwcGV0cyBhcyBBcnJheTxUZXh0SXRlbT47XG5cbiAgICBsZXQgbWluWCA9IE51bWJlci5NQVhfU0FGRV9JTlRFR0VSO1xuICAgIGxldCBtaW5ZID0gTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVI7XG4gICAgbGV0IG1heFggPSBOdW1iZXIuTUlOX1NBRkVfSU5URUdFUjtcbiAgICBsZXQgbWF4WSA9IE51bWJlci5NSU5fU0FGRV9JTlRFR0VSO1xuICAgIGxldCBjb3VudExUUiA9IDA7XG4gICAgbGV0IGNvdW50UlRMID0gMDtcbiAgICBsZXQgdGV4dCA9ICcnO1xuICAgIGxldCBsaW5lcyA9IG5ldyBBcnJheTxMaW5lPigpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc25pcHBldHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IGN1cnJlbnRTbmlwcGV0ID0gc25pcHBldHNbaV07XG4gICAgICBpZiAoIWN1cnJlbnRTbmlwcGV0Lmhhc0VPTCkge1xuICAgICAgICBjb25zdCB4ID0gY3VycmVudFNuaXBwZXQudHJhbnNmb3JtWzRdO1xuICAgICAgICBjb25zdCB5ID0gLWN1cnJlbnRTbmlwcGV0LnRyYW5zZm9ybVs1XTtcbiAgICAgICAgY29uc3Qgd2lkdGggPSBjdXJyZW50U25pcHBldC53aWR0aDtcbiAgICAgICAgY29uc3QgaGVpZ2h0ID0gY3VycmVudFNuaXBwZXQuaGVpZ2h0O1xuICAgICAgICBtaW5YID0gTWF0aC5taW4obWluWCwgeCk7XG4gICAgICAgIG1pblkgPSBNYXRoLm1pbihtaW5ZLCB5KTtcbiAgICAgICAgbWF4WCA9IE1hdGgubWF4KG1heFgsIHggKyB3aWR0aCk7XG4gICAgICAgIG1heFkgPSBNYXRoLm1heChtYXhZLCB5ICsgaGVpZ2h0KTtcbiAgICAgICAgdGV4dCArPSBjdXJyZW50U25pcHBldC5zdHI7XG4gICAgICAgIGlmIChjdXJyZW50U25pcHBldC5kaXIgPT09ICdydGwnKSB7XG4gICAgICAgICAgY291bnRSVEwrKztcbiAgICAgICAgfVxuICAgICAgICBpZiAoY3VycmVudFNuaXBwZXQuZGlyID09PSAnbHRyJykge1xuICAgICAgICAgIGNvdW50TFRSKys7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgbGV0IGFkZEl0ID0gaSA9PT0gc25pcHBldHMubGVuZ3RoIC0gMSB8fCBjdXJyZW50U25pcHBldC5oYXNFT0w7XG4gICAgICBpZiAoYWRkSXQpIHtcbiAgICAgICAgY29uc3QgZGlyZWN0aW9uID0gY291bnRMVFIgPiAwID8gKGNvdW50UlRMID4gMCA/ICdib3RoJyA6ICdsdHInKSA6IGNvdW50UlRMID4gMCA/ICdydGwnIDogdW5kZWZpbmVkO1xuICAgICAgICBjb25zdCBsaW5lID0ge1xuICAgICAgICAgIGRpcmVjdGlvbixcbiAgICAgICAgICB4OiBtaW5YLFxuICAgICAgICAgIHk6IG1pblksXG4gICAgICAgICAgd2lkdGg6IG1heFggLSBtaW5YLFxuICAgICAgICAgIGhlaWdodDogbWF4WSAtIG1pblksXG4gICAgICAgICAgdGV4dDogdGV4dC50cmltKCksXG4gICAgICAgIH0gYXMgTGluZTtcbiAgICAgICAgbGluZXMucHVzaChsaW5lKTtcbiAgICAgICAgbWluWCA9IE51bWJlci5NQVhfU0FGRV9JTlRFR0VSO1xuICAgICAgICBtaW5ZID0gTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVI7XG4gICAgICAgIG1heFggPSBOdW1iZXIuTUlOX1NBRkVfSU5URUdFUjtcbiAgICAgICAgbWF4WSA9IE51bWJlci5NSU5fU0FGRV9JTlRFR0VSO1xuICAgICAgICBjb3VudExUUiA9IDA7XG4gICAgICAgIGNvdW50UlRMID0gMDtcbiAgICAgICAgdGV4dCA9ICcnO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbGluZXM7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgZ2V0UGFnZUFzVGV4dChwYWdlTnVtYmVyOiBudW1iZXIpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IFBERlZpZXdlckFwcGxpY2F0aW9uOiBJUERGVmlld2VyQXBwbGljYXRpb24gPSAod2luZG93IGFzIGFueSkuUERGVmlld2VyQXBwbGljYXRpb247XG4gICAgY29uc3QgcGRmRG9jdW1lbnQgPSBQREZWaWV3ZXJBcHBsaWNhdGlvbi5wZGZEb2N1bWVudDtcblxuICAgIGNvbnN0IHBhZ2UgPSBhd2FpdCBwZGZEb2N1bWVudC5nZXRQYWdlKHBhZ2VOdW1iZXIpO1xuICAgIGNvbnN0IHRleHRTbmlwcGV0cyA9IChhd2FpdCBwYWdlLmdldFRleHRDb250ZW50KCkpLml0ZW1zO1xuICAgIHJldHVybiB0aGlzLmNvbnZlcnRUZXh0SW5mb1RvVGV4dCh0ZXh0U25pcHBldHMpO1xuICB9XG5cbiAgcHJpdmF0ZSBjb252ZXJ0VGV4dEluZm9Ub1RleHQodGV4dEluZm9JdGVtczogQXJyYXk8VGV4dEl0ZW0gfCBUZXh0TWFya2VkQ29udGVudD4pOiBzdHJpbmcge1xuICAgIGlmICghdGV4dEluZm9JdGVtcykge1xuICAgICAgcmV0dXJuICcnO1xuICAgIH1cbiAgICByZXR1cm4gdGV4dEluZm9JdGVtc1xuICAgICAgLmZpbHRlcigoaW5mbykgPT4gIWluZm9bJ3R5cGUnXSlcbiAgICAgIC5tYXAoKGluZm86IFRleHRJdGVtKSA9PiAoaW5mby5oYXNFT0wgPyBpbmZvLnN0ciArICdcXG4nIDogaW5mby5zdHIpKVxuICAgICAgLmpvaW4oJycpO1xuICB9XG5cbiAgcHVibGljIGdldFBhZ2VBc0ltYWdlKHBhZ2VOdW1iZXI6IG51bWJlciwgc2NhbGU6IFBERkV4cG9ydFNjYWxlRmFjdG9yLCBiYWNrZ3JvdW5kPzogc3RyaW5nLCBiYWNrZ3JvdW5kQ29sb3JUb1JlcGxhY2U6IHN0cmluZyA9ICcjRkZGRkZGJyk6IFByb21pc2U8YW55PiB7XG4gICAgY29uc3QgUERGVmlld2VyQXBwbGljYXRpb246IElQREZWaWV3ZXJBcHBsaWNhdGlvbiA9ICh3aW5kb3cgYXMgYW55KS5QREZWaWV3ZXJBcHBsaWNhdGlvbjtcbiAgICBjb25zdCBwZGZEb2N1bWVudCA9IFBERlZpZXdlckFwcGxpY2F0aW9uLnBkZkRvY3VtZW50O1xuICAgIGNvbnN0IHBhZ2VQcm9taXNlOiBQcm9taXNlPGFueT4gPSBwZGZEb2N1bWVudC5nZXRQYWdlKHBhZ2VOdW1iZXIpO1xuICAgIGNvbnN0IGltYWdlUHJvbWlzZSA9IChwZGZQYWdlKSA9PiBQcm9taXNlLnJlc29sdmUodGhpcy5kcmF3KHBkZlBhZ2UsIHNjYWxlLCBiYWNrZ3JvdW5kLCBiYWNrZ3JvdW5kQ29sb3JUb1JlcGxhY2UpKTtcblxuICAgIHJldHVybiBwYWdlUHJvbWlzZS50aGVuKGltYWdlUHJvbWlzZSk7XG4gIH1cblxuICBwcml2YXRlIGRyYXcocGRmUGFnZTogYW55LCBzY2FsZTogUERGRXhwb3J0U2NhbGVGYWN0b3IsIGJhY2tncm91bmQ/OiBzdHJpbmcsIGJhY2tncm91bmRDb2xvclRvUmVwbGFjZTogc3RyaW5nID0gJyNGRkZGRkYnKTogUHJvbWlzZTxIVE1MQ2FudmFzRWxlbWVudD4ge1xuICAgIGxldCB6b29tRmFjdG9yID0gMTtcbiAgICBpZiAoc2NhbGUuc2NhbGUpIHtcbiAgICAgIHpvb21GYWN0b3IgPSBzY2FsZS5zY2FsZTtcbiAgICB9IGVsc2UgaWYgKHNjYWxlLndpZHRoKSB7XG4gICAgICB6b29tRmFjdG9yID0gc2NhbGUud2lkdGggLyBwZGZQYWdlLmdldFZpZXdwb3J0KHsgc2NhbGU6IDEgfSkud2lkdGg7XG4gICAgfSBlbHNlIGlmIChzY2FsZS5oZWlnaHQpIHtcbiAgICAgIHpvb21GYWN0b3IgPSBzY2FsZS5oZWlnaHQgLyBwZGZQYWdlLmdldFZpZXdwb3J0KHsgc2NhbGU6IDEgfSkuaGVpZ2h0O1xuICAgIH1cbiAgICBjb25zdCB2aWV3cG9ydCA9IHBkZlBhZ2UuZ2V0Vmlld3BvcnQoe1xuICAgICAgc2NhbGU6IHpvb21GYWN0b3IsXG4gICAgfSk7XG4gICAgY29uc3QgeyBjdHgsIGNhbnZhcyB9ID0gdGhpcy5nZXRQYWdlRHJhd0NvbnRleHQodmlld3BvcnQud2lkdGgsIHZpZXdwb3J0LmhlaWdodCk7XG4gICAgY29uc3QgZHJhd1ZpZXdwb3J0ID0gdmlld3BvcnQuY2xvbmUoKTtcblxuICAgIGNvbnN0IHJlbmRlckNvbnRleHQgPSB7XG4gICAgICBjYW52YXNDb250ZXh0OiBjdHgsXG4gICAgICB2aWV3cG9ydDogZHJhd1ZpZXdwb3J0LFxuICAgICAgYmFja2dyb3VuZCxcbiAgICAgIGJhY2tncm91bmRDb2xvclRvUmVwbGFjZSxcbiAgICB9O1xuICAgIGNvbnN0IHJlbmRlclRhc2sgPSBwZGZQYWdlLnJlbmRlcihyZW5kZXJDb250ZXh0KTtcblxuICAgIGNvbnN0IGRhdGFVcmxQcm9taXNlID0gKCkgPT4gUHJvbWlzZS5yZXNvbHZlKGNhbnZhcy50b0RhdGFVUkwoKSk7XG5cbiAgICByZXR1cm4gcmVuZGVyVGFzay5wcm9taXNlLnRoZW4oZGF0YVVybFByb21pc2UpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRQYWdlRHJhd0NvbnRleHQod2lkdGg6IG51bWJlciwgaGVpZ2h0OiBudW1iZXIpOiBEcmF3Q29udGV4dCB7XG4gICAgY29uc3QgY2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7XG4gICAgY29uc3QgY3R4ID0gY2FudmFzLmdldENvbnRleHQoJzJkJywgeyBhbHBoYTogdHJ1ZSB9KTtcbiAgICBpZiAoIWN0eCkge1xuICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOiBxdW90ZW1hcmtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkNvdWxkbid0IGNyZWF0ZSB0aGUgMmQgY29udGV4dFwiKTtcbiAgICB9XG5cbiAgICBjYW52YXMud2lkdGggPSB3aWR0aDtcbiAgICBjYW52YXMuaGVpZ2h0ID0gaGVpZ2h0O1xuICAgIGNhbnZhcy5zdHlsZS53aWR0aCA9IGAke3dpZHRofXB4YDtcbiAgICBjYW52YXMuc3R5bGUuaGVpZ2h0ID0gYCR7aGVpZ2h0fXB4YDtcblxuICAgIHJldHVybiB7IGN0eCwgY2FudmFzIH07XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgZ2V0Q3VycmVudERvY3VtZW50QXNCbG9iKCk6IFByb21pc2U8QmxvYj4ge1xuICAgIGNvbnN0IFBERlZpZXdlckFwcGxpY2F0aW9uOiBJUERGVmlld2VyQXBwbGljYXRpb24gPSAod2luZG93IGFzIGFueSkuUERGVmlld2VyQXBwbGljYXRpb247XG4gICAgY29uc3QgZGF0YSA9IGF3YWl0IFBERlZpZXdlckFwcGxpY2F0aW9uLnBkZkRvY3VtZW50LnNhdmVEb2N1bWVudCgpOyAvLyAoUERGVmlld2VyQXBwbGljYXRpb24ucGRmRG9jdW1lbnQuYW5ub3RhdGlvblN0b3JhZ2UpO1xuICAgIHJldHVybiBuZXcgQmxvYihbZGF0YV0sIHsgdHlwZTogJ2FwcGxpY2F0aW9uL3BkZicgfSk7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgZ2V0Rm9ybURhdGEoY3VycmVudEZvcm1WYWx1ZXMgPSB0cnVlKTogUHJvbWlzZTxBcnJheTxPYmplY3Q+PiB7XG4gICAgY29uc3QgUERGVmlld2VyQXBwbGljYXRpb246IElQREZWaWV3ZXJBcHBsaWNhdGlvbiA9ICh3aW5kb3cgYXMgYW55KS5QREZWaWV3ZXJBcHBsaWNhdGlvbjtcbiAgICBjb25zdCBwZGY6IFBERkRvY3VtZW50UHJveHkgfCB1bmRlZmluZWQgPSBQREZWaWV3ZXJBcHBsaWNhdGlvbi5wZGZEb2N1bWVudDtcbiAgICAvLyBzY3JlZW4gRFBJIC8gUERGIERQSVxuICAgIGNvbnN0IGRwaVJhdGlvID0gOTYgLyA3MjtcbiAgICBjb25zdCByZXN1bHQ6IEFycmF5PE9iamVjdD4gPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMTsgaSA8PSBwZGY/Lm51bVBhZ2VzOyBpKyspIHtcbiAgICAgIC8vIHRyYWNrIHRoZSBjdXJyZW50IHBhZ2VcbiAgICAgIGNvbnN0IGN1cnJlbnRQYWdlIC8qIDogUERGUGFnZVByb3h5ICovID0gYXdhaXQgcGRmLmdldFBhZ2UoaSk7XG4gICAgICBjb25zdCBhbm5vdGF0aW9ucyA9IGF3YWl0IGN1cnJlbnRQYWdlLmdldEFubm90YXRpb25zKCk7XG5cbiAgICAgIGFubm90YXRpb25zXG4gICAgICAgIC5maWx0ZXIoKGEpID0+IGEuc3VidHlwZSA9PT0gJ1dpZGdldCcpIC8vIGdldCB0aGUgZm9ybSBmaWVsZCBhbm5vdGF0aW9ucyBvbmx5XG4gICAgICAgIC5tYXAoKGEpID0+ICh7IC4uLmEgfSkpIC8vIG9ubHkgZXhwb3NlIGNvcGllcyBvZiB0aGUgYW5ub3RhdGlvbnMgdG8gYXZvaWQgc2lkZS1lZmZlY3RzXG4gICAgICAgIC5mb3JFYWNoKChhKSA9PiB7XG4gICAgICAgICAgLy8gZ2V0IHRoZSByZWN0YW5nbGUgdGhhdCByZXByZXNlbnQgdGhlIHNpbmdsZSBmaWVsZFxuICAgICAgICAgIC8vIGFuZCByZXNpemUgaXQgYWNjb3JkaW5nIHRvIHRoZSBjdXJyZW50IERQSVxuICAgICAgICAgIGNvbnN0IGZpZWxkUmVjdDogQXJyYXk8bnVtYmVyPiA9IGN1cnJlbnRQYWdlLmdldFZpZXdwb3J0KHsgc2NhbGU6IGRwaVJhdGlvIH0pLmNvbnZlcnRUb1ZpZXdwb3J0UmVjdGFuZ2xlKGEucmVjdCk7XG5cbiAgICAgICAgICAvLyBhZGQgdGhlIGNvcnJlc3BvbmRpbmcgaW5wdXRcbiAgICAgICAgICBpZiAoY3VycmVudEZvcm1WYWx1ZXMgJiYgYS5maWVsZE5hbWUpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgIGlmIChhLmV4cG9ydFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgY3VycmVudFZhbHVlOiBhbnkgPSBQREZWaWV3ZXJBcHBsaWNhdGlvbi5wZGZEb2N1bWVudC5hbm5vdGF0aW9uU3RvcmFnZS5nZXRWYWx1ZShhLmlkLCBhLmZpZWxkTmFtZSArICcvJyArIGEuZXhwb3J0VmFsdWUsICcnKTtcbiAgICAgICAgICAgICAgICBhLnZhbHVlID0gY3VycmVudFZhbHVlPy52YWx1ZTtcbiAgICAgICAgICAgICAgfSBlbHNlIGlmIChhLnJhZGlvQnV0dG9uKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgY3VycmVudFZhbHVlOiBhbnkgPSBQREZWaWV3ZXJBcHBsaWNhdGlvbi5wZGZEb2N1bWVudC5hbm5vdGF0aW9uU3RvcmFnZS5nZXRWYWx1ZShhLmlkLCBhLmZpZWxkTmFtZSArICcvJyArIGEuZmllbGRWYWx1ZSwgJycpO1xuICAgICAgICAgICAgICAgIGEudmFsdWUgPSBjdXJyZW50VmFsdWU/LnZhbHVlO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnN0IGN1cnJlbnRWYWx1ZTogYW55ID0gUERGVmlld2VyQXBwbGljYXRpb24ucGRmRG9jdW1lbnQuYW5ub3RhdGlvblN0b3JhZ2UuZ2V0VmFsdWUoYS5pZCwgYS5maWVsZE5hbWUsICcnKTtcbiAgICAgICAgICAgICAgICBhLnZhbHVlID0gY3VycmVudFZhbHVlPy52YWx1ZTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBjYXRjaCAoZXhjZXB0aW9uKSB7XG4gICAgICAgICAgICAgIC8vIGp1c3QgaWdub3JlIGl0XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIHJlc3VsdC5wdXNoKHsgZmllbGRBbm5vdGF0aW9uOiBhLCBmaWVsZFJlY3QsIHBhZ2VOdW1iZXI6IGkgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYSBwYWdlIHRvIHRoZSByZW5kZXJpbmcgcXVldWVcbiAgICogQHBhcmFtIHtudW1iZXJ9IHBhZ2VJbmRleCBJbmRleCBvZiB0aGUgcGFnZSB0byByZW5kZXJcbiAgICogQHJldHVybnMge2Jvb2xlYW59IGZhbHNlLCBpZiB0aGUgcGFnZSBoYXMgYWxyZWFkeSBiZWVuIHJlbmRlcmVkXG4gICAqIG9yIGlmIGl0J3Mgb3V0IG9mIHJhbmdlXG4gICAqL1xuICBwdWJsaWMgYWRkUGFnZVRvUmVuZGVyUXVldWUocGFnZUluZGV4OiBudW1iZXIpOiBib29sZWFuIHtcbiAgICBjb25zdCBQREZWaWV3ZXJBcHBsaWNhdGlvbjogSVBERlZpZXdlckFwcGxpY2F0aW9uID0gKHdpbmRvdyBhcyBhbnkpLlBERlZpZXdlckFwcGxpY2F0aW9uO1xuICAgIHJldHVybiBQREZWaWV3ZXJBcHBsaWNhdGlvbi5wZGZWaWV3ZXIuYWRkUGFnZVRvUmVuZGVyUXVldWUocGFnZUluZGV4KTtcbiAgfVxuXG4gIHB1YmxpYyBpc1JlbmRlclF1ZXVlRW1wdHkoKTogYm9vbGVhbiB7XG4gICAgY29uc3Qgc2Nyb2xsZWREb3duID0gdHJ1ZTtcbiAgICBjb25zdCByZW5kZXJFeHRyYSA9IGZhbHNlO1xuICAgIGNvbnN0IFBERlZpZXdlckFwcGxpY2F0aW9uOiBJUERGVmlld2VyQXBwbGljYXRpb24gPSAod2luZG93IGFzIGFueSkuUERGVmlld2VyQXBwbGljYXRpb247XG4gICAgY29uc3QgbmV4dFBhZ2UgPSBQREZWaWV3ZXJBcHBsaWNhdGlvbi5wZGZWaWV3ZXIucmVuZGVyaW5nUXVldWUuZ2V0SGlnaGVzdFByaW9yaXR5KFxuICAgICAgUERGVmlld2VyQXBwbGljYXRpb24ucGRmVmlld2VyLl9nZXRWaXNpYmxlUGFnZXMoKSxcbiAgICAgIFBERlZpZXdlckFwcGxpY2F0aW9uLnBkZlZpZXdlci5fcGFnZXMsXG4gICAgICBzY3JvbGxlZERvd24sXG4gICAgICByZW5kZXJFeHRyYVxuICAgICk7XG4gICAgcmV0dXJuICFuZXh0UGFnZTtcbiAgfVxuXG4gIHB1YmxpYyBoYXNQYWdlQmVlblJlbmRlcmVkKHBhZ2VJbmRleDogbnVtYmVyKTogYm9vbGVhbiB7XG4gICAgY29uc3QgUERGVmlld2VyQXBwbGljYXRpb246IElQREZWaWV3ZXJBcHBsaWNhdGlvbiA9ICh3aW5kb3cgYXMgYW55KS5QREZWaWV3ZXJBcHBsaWNhdGlvbjtcbiAgICBjb25zdCBwYWdlcyA9IFBERlZpZXdlckFwcGxpY2F0aW9uLnBkZlZpZXdlci5fcGFnZXM7XG4gICAgaWYgKHBhZ2VzLmxlbmd0aCA+IHBhZ2VJbmRleCAmJiBwYWdlSW5kZXggPj0gMCkge1xuICAgICAgY29uc3QgcGFnZVZpZXcgPSBwYWdlc1twYWdlSW5kZXhdO1xuICAgICAgY29uc3QgaXNMb2FkaW5nID0gcGFnZVZpZXcuZGl2LnF1ZXJ5U2VsZWN0b3IoJy5sb2FkaW5nSWNvbicpO1xuICAgICAgcmV0dXJuICFpc0xvYWRpbmc7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHB1YmxpYyBjdXJyZW50bHlSZW5kZXJlZFBhZ2VzKCk6IEFycmF5PG51bWJlcj4ge1xuICAgIGNvbnN0IFBERlZpZXdlckFwcGxpY2F0aW9uOiBJUERGVmlld2VyQXBwbGljYXRpb24gPSAod2luZG93IGFzIGFueSkuUERGVmlld2VyQXBwbGljYXRpb247XG4gICAgY29uc3QgcGFnZXMgPSBQREZWaWV3ZXJBcHBsaWNhdGlvbi5wZGZWaWV3ZXIuX3BhZ2VzO1xuICAgIHJldHVybiBwYWdlcy5maWx0ZXIoKHBhZ2UpID0+ICFwYWdlLmRpdi5xdWVyeVNlbGVjdG9yKCcubG9hZGluZ0ljb24nKSkubWFwKChwYWdlKSA9PiBwYWdlLmlkKTtcbiAgfVxuXG4gIHB1YmxpYyBudW1iZXJPZlBhZ2VzKCk6IG51bWJlciB7XG4gICAgY29uc3QgUERGVmlld2VyQXBwbGljYXRpb246IElQREZWaWV3ZXJBcHBsaWNhdGlvbiA9ICh3aW5kb3cgYXMgYW55KS5QREZWaWV3ZXJBcHBsaWNhdGlvbjtcbiAgICBjb25zdCBwYWdlcyA9IFBERlZpZXdlckFwcGxpY2F0aW9uLnBkZlZpZXdlci5fcGFnZXM7XG4gICAgcmV0dXJuIHBhZ2VzLmxlbmd0aDtcbiAgfVxuXG4gIHB1YmxpYyBnZXRDdXJyZW50bHlWaXNpYmxlUGFnZU51bWJlcnMoKTogQXJyYXk8bnVtYmVyPiB7XG4gICAgY29uc3QgYXBwID0gKHdpbmRvdyBhcyBhbnkpLlBERlZpZXdlckFwcGxpY2F0aW9uIGFzIElQREZWaWV3ZXJBcHBsaWNhdGlvbjtcbiAgICBjb25zdCBwYWdlcyA9IChhcHAucGRmVmlld2VyLl9nZXRWaXNpYmxlUGFnZXMoKSBhcyBhbnkpLnZpZXdzIGFzIEFycmF5PGFueT47XG4gICAgcmV0dXJuIHBhZ2VzPy5tYXAoKHBhZ2UpID0+IHBhZ2UuaWQpO1xuICB9XG5cbiAgcHVibGljIHJlY2FsY3VsYXRlU2l6ZSgpOiB2b2lkIHtcbiAgICB0aGlzLnJlY2FsY3VsYXRlU2l6ZSQubmV4dCgpO1xuICB9XG5cbiAgcHVibGljIGFzeW5jIGxpc3RMYXllcnMoKTogUHJvbWlzZTxBcnJheTxQZGZMYXllcj4gfCB1bmRlZmluZWQ+IHtcbiAgICBjb25zdCBQREZWaWV3ZXJBcHBsaWNhdGlvbjogSVBERlZpZXdlckFwcGxpY2F0aW9uID0gKHdpbmRvdyBhcyBhbnkpLlBERlZpZXdlckFwcGxpY2F0aW9uO1xuXG4gICAgY29uc3Qgb3B0aW9uYWxDb250ZW50Q29uZmlnID0gYXdhaXQgUERGVmlld2VyQXBwbGljYXRpb24ucGRmVmlld2VyLm9wdGlvbmFsQ29udGVudENvbmZpZ1Byb21pc2U7XG4gICAgaWYgKG9wdGlvbmFsQ29udGVudENvbmZpZykge1xuICAgICAgY29uc3QgbGV2ZWxEYXRhID0gb3B0aW9uYWxDb250ZW50Q29uZmlnLmdldE9yZGVyKCk7XG4gICAgICBjb25zb2xlLmxvZyhsZXZlbERhdGEpO1xuICAgICAgY29uc3QgbGF5ZXJJZHMgPSBsZXZlbERhdGEuZmlsdGVyKChncm91cElkKSA9PiB0eXBlb2YgZ3JvdXBJZCAhPT0gJ29iamVjdCcpO1xuICAgICAgcmV0dXJuIGxheWVySWRzLm1hcCgobGF5ZXJJZCkgPT4ge1xuICAgICAgICBjb25zdCBjb25maWcgPSBvcHRpb25hbENvbnRlbnRDb25maWcuZ2V0R3JvdXAobGF5ZXJJZCk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgbGF5ZXJJZDogbGF5ZXJJZCxcbiAgICAgICAgICBuYW1lOiBjb25maWcubmFtZSxcbiAgICAgICAgICB2aXNpYmxlOiBjb25maWcudmlzaWJsZSxcbiAgICAgICAgfSBhcyBQZGZMYXllcjtcbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgcHVibGljIGFzeW5jIHRvZ2dsZUxheWVyKGxheWVySWQ6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IFBERlZpZXdlckFwcGxpY2F0aW9uOiBJUERGVmlld2VyQXBwbGljYXRpb24gPSAod2luZG93IGFzIGFueSkuUERGVmlld2VyQXBwbGljYXRpb247XG4gICAgY29uc3Qgb3B0aW9uYWxDb250ZW50Q29uZmlnID0gYXdhaXQgUERGVmlld2VyQXBwbGljYXRpb24ucGRmVmlld2VyLm9wdGlvbmFsQ29udGVudENvbmZpZ1Byb21pc2U7XG4gICAgaWYgKG9wdGlvbmFsQ29udGVudENvbmZpZykge1xuICAgICAgbGV0IGlzVmlzaWJsZSA9IG9wdGlvbmFsQ29udGVudENvbmZpZy5nZXRHcm91cChsYXllcklkKS52aXNpYmxlO1xuICAgICAgY29uc3QgY2hlY2tib3ggPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKGBpbnB1dFtpZD0nJHtsYXllcklkfSddYCk7XG4gICAgICBpZiAoY2hlY2tib3gpIHtcbiAgICAgICAgaXNWaXNpYmxlID0gKGNoZWNrYm94IGFzIEhUTUxJbnB1dEVsZW1lbnQpLmNoZWNrZWQ7XG4gICAgICAgIChjaGVja2JveCBhcyBIVE1MSW5wdXRFbGVtZW50KS5jaGVja2VkID0gIWlzVmlzaWJsZTtcbiAgICAgIH1cbiAgICAgIG9wdGlvbmFsQ29udGVudENvbmZpZy5zZXRWaXNpYmlsaXR5KGxheWVySWQsICFpc1Zpc2libGUpO1xuICAgICAgUERGVmlld2VyQXBwbGljYXRpb24uZXZlbnRCdXMuZGlzcGF0Y2goJ29wdGlvbmFsY29udGVudGNvbmZpZycsIHtcbiAgICAgICAgc291cmNlOiB0aGlzLFxuICAgICAgICBwcm9taXNlOiBQcm9taXNlLnJlc29sdmUob3B0aW9uYWxDb250ZW50Q29uZmlnKSxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBzY3JvbGxQYWdlSW50b1ZpZXcocGFnZU51bWJlcjogbnVtYmVyLCBwYWdlU3BvdD86IHsgdG9wPzogbnVtYmVyIHwgc3RyaW5nOyBsZWZ0PzogbnVtYmVyIHwgc3RyaW5nIH0pOiB2b2lkIHtcbiAgICBjb25zdCBQREZWaWV3ZXJBcHBsaWNhdGlvbjogSVBERlZpZXdlckFwcGxpY2F0aW9uID0gKHdpbmRvdyBhcyBhbnkpLlBERlZpZXdlckFwcGxpY2F0aW9uO1xuICAgIGNvbnN0IHZpZXdlciA9IFBERlZpZXdlckFwcGxpY2F0aW9uLnBkZlZpZXdlciBhcyBhbnk7XG4gICAgdmlld2VyLnNjcm9sbFBhZ2VQb3NJbnRvVmlldyhwYWdlTnVtYmVyLCBwYWdlU3BvdCk7XG4gIH1cbn1cbiJdfQ==