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.
371 lines • 57.1 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;
}
getPageAsText(pageNumber) {
const PDFViewerApplication = window.PDFViewerApplication;
const pdfDocument = PDFViewerApplication.pdfDocument;
const pagePromise = pdfDocument.getPage(pageNumber);
const extractTextSnippets = (pdfPage) => Promise.resolve(pdfPage.getTextContent());
const combineTextSnippets = (textSnippets) => Promise.resolve(this.convertTextInfoToText(textSnippets));
return pagePromise.then(extractTextSnippets).then(combineTextSnippets);
}
convertTextInfoToText(textInfo) {
if (!textInfo) {
return '';
}
return textInfo.items.map((info) => 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 /*: PDFDocumentProxy */ = 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.isVisible(layerId);
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LWV4dGVuZGVkLXBkZi12aWV3ZXIuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1leHRlbmRlZC1wZGYtdmlld2VyL3NyYy9saWIvbmd4LWV4dGVuZGVkLXBkZi12aWV3ZXIuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQy9CLE9BQU8sRUFBRSw2QkFBNkIsRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBMkJwRixNQUFNLE9BQU8sMkJBQTJCO0lBQXhDO1FBQ1MscUJBQWdCLEdBQUcsSUFBSSxPQUFPLEVBQVEsQ0FBQztJQThZaEQsQ0FBQztJQTVZUSxZQUFZLENBQUMsSUFBbUIsRUFBRSxVQUF1QixFQUFFO1FBQ2hFLE9BQU8sR0FBRztZQUNSLEdBQUcsT0FBTztZQUNWLHVCQUF1QixFQUFFLElBQUk7U0FDOUIsQ0FBQztRQUNGLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDO1FBQzVDLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDMUMsQ0FBQztJQUVNLElBQUksQ0FBQyxJQUFZLEVBQUUsVUFBdUIsRUFBRTtRQUNqRCxJQUFJLENBQUMsNkJBQTZCLENBQUMsK0JBQStCLEVBQUU7WUFDbEUscUNBQXFDO1lBQ3JDLE9BQU8sQ0FBQyxLQUFLLENBQUMsd0VBQXdFLENBQUMsQ0FBQztZQUN4RixPQUFPLEtBQUssQ0FBQztTQUNkO2FBQU07WUFDTCxNQUFNLG9CQUFvQixHQUFHLFFBQVEsQ0FBQyxjQUFjLENBQUMsa0JBQWtCLENBQXFCLENBQUM7WUFDN0YsSUFBSSxvQkFBb0IsRUFBRTtnQkFDeEIsb0JBQW9CLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQyxZQUFZLElBQUksS0FBSyxDQUFD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QUFJLFFBQVEsRUFBRTtnQkFDWixTQUFTLEdBQUksUUFBNkIsQ0FBQyxPQUFPLENBQUM7Z0JBQ2xELFFBQTZCLENBQUMsT0FBTyxHQUFHLENBQUMsU0FBUyxDQUFDO2FBQ3JEO1lBQ0QscUJBQXFCLENBQUMsYUFBYSxDQUFDLE9BQU8sRUFBRSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBQ3pELG9CQUFvQixDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsdUJBQXVCLEVBQUU7Z0JBQzlELE1BQU0sRUFBRSxJQUFJO2dCQUNaLE9BQU8sRUFBRSxPQUFPLENBQUMsT0FBTyxDQUFDLHFCQUFxQixDQUFDO2FBQ2hELENBQUMsQ0FBQztTQUNKO0lBQ0gsQ0FBQztJQUVNLGtCQUFrQixDQUFDLFVBQWtCLEVBQUUsUUFBNEQ7UUFDeEcsTUFBTSxvQkFBb0IsR0FBMkIsTUFBYyxDQUFDLG9CQUFvQixDQUFDO1FBQ3pGLE1BQU0sTUFBTSxHQUFHLG9CQUFvQixDQUFDLFNBQWdCLENBQUM7UUFDckQsTUFBTSxDQUFDLHFCQUFxQixDQUFDLFVBQVUsRUFBRSxRQUFRLENBQUMsQ0FBQztJQUNyRCxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBTdWJqZWN0IH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBOZ3hFeHRlbmRlZFBkZlZpZXdlckNvbXBvbmVudCB9IGZyb20gJy4vbmd4LWV4dGVuZGVkLXBkZi12aWV3ZXIuY29tcG9uZW50JztcbmltcG9ydCB7IFBkZkxheWVyIH0gZnJvbSAnLi9vcHRpb25zL29wdGlvbmFsX2NvbnRlbnRfY29uZmlnJztcbmltcG9ydCB7IFBERlByaW50UmFuZ2UgfSBmcm9tICcuL29wdGlvbnMvcGRmLXByaW50LXJhbmdlJztcbmltcG9ydCB7IElQREZWaWV3ZXJBcHBsaWNhdGlvbiB9IGZyb20gJy4vb3B0aW9ucy9wZGYtdmlld2VyLWFwcGxpY2F0aW9uJztcblxuZXhwb3J0IGludGVyZmFjZSBGaW5kT3B0aW9ucyB7XG4gIGhpZ2hsaWdodEFsbD86IGJvb2xlYW47XG4gIG1hdGNoQ2FzZT86IGJvb2xlYW47XG4gIHdob2xlV29yZHM/OiBib29sZWFuO1xuICBpZ25vcmVBY2NlbnRzPzogYm9vbGVhbjtcbiAgZmluZE11bHRpcGxlU2VhcmNoVGV4dHM/OiBib29sZWFuO1xuICBmdXp6eVNlYXJjaD86IGJvb2xlYW47XG4gIGN1cnJlbnRQYWdlPzogYm9vbGVhbjsgLy8gc2VhcmNoIG9ubHkgaW4gdGhlIGN1cnJlbnQgcGFnZVxuICBwYWdlUmFuZ2U/OiBzdHJpbmc7IC8vIHBhZ2UgcmFuZ2UgZGVmaW5pdGlvbiwgZS5nLiBcIjJcIiwgXCIyLDMsNFwiLCBcIjUtNlwiIG9yIFwiMiw1LTYsN1wiXG59XG5cbmludGVyZmFjZSBEcmF3Q29udGV4dCB7XG4gIGN0eDogQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEO1xuICBjYW52YXM6IEhUTUxDYW52YXNFbGVtZW50O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFBERkV4cG9ydFNjYWxlRmFjdG9yIHtcbiAgd2lkdGg/OiBudW1iZXI7XG4gIGhlaWdodD86IG51bWJlcjtcbiAgc2NhbGU/OiBudW1iZXI7XG59XG5cbmV4cG9ydCBjbGFzcyBOZ3hFeHRlbmRlZFBkZlZpZXdlclNlcnZpY2Uge1xuICBwdWJsaWMgcmVjYWxjdWxhdGVTaXplJCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG5cbiAgcHVibGljIGZpbmRNdWx0aXBsZSh0ZXh0OiBBcnJheTxzdHJpbmc+LCBvcHRpb25zOiBGaW5kT3B0aW9ucyA9IHt9KTogYm9vbGVhbiB7XG4gICAgb3B0aW9ucyA9IHtcbiAgICAgIC4uLm9wdGlvbnMsXG4gICAgICBmaW5kTXVsdGlwbGVTZWFyY2hUZXh0czogdHJ1ZSxcbiAgICB9O1xuICAgIGNvbnN0IHNlYXJjaFN0cmluZyA9IHRleHQuam9pbignXFxuJykgKyAnXFxuJztcbiAgICByZXR1cm4gdGhpcy5maW5kKHNlYXJjaFN0cmluZywgb3B0aW9ucyk7XG4gIH1cblxuICBwdWJsaWMgZmluZCh0ZXh0OiBzdHJpbmcsIG9wdGlvbnM6IEZpbmRPcHRpb25zID0ge30pOiBib29sZWFuIHtcbiAgICBpZiAoIU5neEV4dGVuZGVkUGRmVmlld2VyQ29tcG9uZW50Lm5neEV4dGVuZGVkUGRmVmlld2VySW5pdGlhbGl6ZWQpIHtcbiAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpxdW90ZW1hcmtcbiAgICAgIGNvbnNvbGUuZXJyb3IoXCJUaGUgUERGIHZpZXdlciBoYXNuJ3QgZmluaXNoZWQgaW5pdGlhbGl6aW5nLiBQbGVhc2UgY2FsbCBmaW5kKCkgbGF0ZXIuXCIpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBoaWdobGlnaHRBbGxDaGVja2JveCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdmaW5kSGlnaGxpZ2h0QWxsJykgYXMgSFRNTElucHV0RWxlbWVudDtcbiAgICAgIGlmIChoaWdobGlnaHRBbGxDaGVja2JveCkge1xuICAgICAgICBoaWdobGlnaHRBbGxDaGVja2JveC5jaGVja2VkID0gb3B0aW9ucy5oaWdobGlnaHRBbGwgfHwgZmFsc2U7XG4gICAgICB9XG4gICAgICBjb25zdCBmaW5kUGFnZVJhbmdlID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2ZpbmRSYW5nZScpIGFzIEhUTUxJbnB1dEVsZW1lbnQ7XG4gICAgICBpZiAoZmluZFBhZ2VSYW5nZSkge1xuICAgICAgICBmaW5kUGFnZVJhbmdlLnZhbHVlID0gb3B0aW9ucy5wYWdlUmFuZ2UgfHwgJyc7XG4gICAgICB9XG4gICAgICBjb25zdCBmaW5kQ3VycmVudFBhZ2VDaGVja2JveCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdmaW5kQ3VycmVudFBhZ2UnKSBhcyBIVE1MSW5wdXRFbGVtZW50O1xuICAgICAgaWYgKGZpbmRDdXJyZW50UGFnZUNoZWNrYm94KSB7XG4gICAgICAgIGZpbmRDdXJyZW50UGFnZUNoZWNrYm94LmNoZWNrZWQgPSBvcHRpb25zLmN1cnJlbnRQYWdlIHx8IGZhbHNlO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBtYXRjaENhc2VDaGVja2JveCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdmaW5kTWF0Y2hDYXNlJykgYXMgSFRNTElucHV0RWxlbWVudDtcbiAgICAgIGlmIChtYXRjaENhc2VDaGVja2JveCkge1xuICAgICAgICBtYXRjaENhc2VDaGVja2JveC5jaGVja2VkID0gb3B0aW9ucy5tYXRjaENhc2UgfHwgZmFsc2U7XG4gICAgICB9XG4gICAgICBjb25zdCBlbnRpcmVXb3JkQ2hlY2tib3ggPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZmluZEVudGlyZVdvcmQnKSBhcyBIVE1MSW5wdXRFbGVtZW50O1xuICAgICAgaWYgKGVudGlyZVdvcmRDaGVja2JveCkge1xuICAgICAgICBlbnRpcmVXb3JkQ2hlY2tib3guY2hlY2tlZCA9IG9wdGlvbnMud2hvbGVXb3JkcyB8fCBmYWxzZTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGZpbmRJZ25vcmVBY2NlbnRzQ2hlY2tib3ggPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZmluZElnbm9yZUFjY2VudHMnKSBhcyBIVE1MSW5wdXRFbGVtZW50O1xuICAgICAgaWYgKGZpbmRJZ25vcmVBY2NlbnRzQ2hlY2tib3gpIHtcbiAgICAgICAgZmluZElnbm9yZUFjY2VudHNDaGVja2JveC5jaGVja2VkID0gb3B0aW9ucy5pZ25vcmVBY2NlbnRzIHx8IGZhbHNlO1xuICAgICAgfVxuICAgICAgY29uc3QgbXVsdGlwbGVTZWFyY2hUZXJtcyA9IG9wdGlvbnMuZmluZE11bHRpcGxlU2VhcmNoVGV4dHMgfHwgdGV4dC5pbmNsdWRlcygnXFxuJykgfHwgZmFsc2U7XG4gICAgICBjb25zdCBmaW5kTXVsdGlwbGVTZWFyY2hUZXh0c0NoZWNrYm94ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2ZpbmRNdWx0aXBsZVNlYXJjaFRleHRzJykgYXMgSFRNTElucHV0RWxlbWVudDtcbiAgICAgIGlmIChmaW5kTXVsdGlwbGVTZWFyY2hUZXh0c0NoZWNrYm94KSB7XG4gICAgICAgIGZpbmRNdWx0aXBsZVNlYXJjaFRleHRzQ2hlY2tib3guY2hlY2tlZCA9IG11bHRpcGxlU2VhcmNoVGVybXM7XG4gICAgICB9XG4gICAgICBjb25zdCBpbmRpdmlkdWFsV29yZHNNb2RlQ2hlY2tib3ggPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnaW5kaXZpZHVhbFdvcmRzTW9kZScpIGFzIEhUTUxJbnB1dEVsZW1lbnQ7XG4gICAgICBpZiAoaW5kaXZpZHVhbFdvcmRzTW9kZUNoZWNrYm94KSB7XG4gICAgICAgIGluZGl2aWR1YWxXb3Jkc01vZGVDaGVja2JveC5jaGVja2VkID0gZmFsc2U7XG4gICAgICB9XG4gICAgICBjb25zdCBmdXp6eVNlYXJjaENoZWNrYm94ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2ZpbmRGdXp6eScpIGFzIEhUTUxJbnB1dEVsZW1lbnQ7XG4gICAgICBpZiAoZnV6enlTZWFyY2hDaGVja2JveCkge1xuICAgICAgICBmdXp6eVNlYXJjaENoZWNrYm94LmNoZWNrZWQgPSBvcHRpb25zLmZ1enp5U2VhcmNoIHx8IGZhbHNlO1xuICAgICAgfVxuICAgICAgY29uc3QgaW5wdXRGaWVsZCA9IG11bHRpcGxlU2VhcmNoVGVybXMgPyBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZmluZElucHV0TXVsdGlsaW5lJykgOiBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZmluZElucHV0Jyk7XG4gICAgICBpZiAoaW5wdXRGaWVsZCkge1xuICAgICAgICBpZiAoaW5wdXRGaWVsZCBpbnN0YW5jZW9mIEhUTUxUZXh0QXJlYUVsZW1lbnQpIHtcbiAgICAgICAgICBpbnB1dEZpZWxkLnZhbHVlID0gdGV4dDtcblxuICAgICAgICAgIC8vIHRvZG8gZGlydHkgaGFjayFcbiAgICAgICAgICBpbnB1dEZpZWxkLmNsYXNzTGlzdC5yZW1vdmUoJ2hpZGRlbicpO1xuICAgICAgICAgIChkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZmluZElucHV0JykgYXMgSFRNTElucHV0RWxlbWVudCkuY2xhc3NMaXN0LmFkZCgnaGlkZGVuJyk7XG4gICAgICAgICAgKGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdpbmRpdmlkdWFsV29yZHNNb2RlTGFiZWwnKSBhcyBIVE1MSW5wdXRFbGVtZW50KS5jbGFzc0xpc3QucmVtb3ZlKCdoaWRkZW4nKTtcbiAgICAgICAgICAoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2luZGl2aWR1YWxXb3Jkc01vZGUnKSBhcyBIVE1MSW5wdXRFbGVtZW50KS5jbGFzc0xpc3QucmVtb3ZlKCdoaWRkZW4nKTtcbiAgICAgICAgICAvLyBlbmQgb2YgdGhlIGRpcnR5IGhhY2tcbiAgICAgICAgfSBlbHNlIGlmIChpbnB1dEZpZWxkIGluc3RhbmNlb2YgSFRNTElucHV0RWxlbWVudCkge1xuICAgICAgICAgIGlucHV0RmllbGQudmFsdWUgPSB0ZXh0O1xuICAgICAgICAgIC8vIHRvZG8gZGlydHkgaGFjayFcbiAgICAgICAgICBpbnB1dEZpZWxkLmNsYXNzTGlzdC5yZW1vdmUoJ2hpZGRlbicpO1xuICAgICAgICAgIChkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZmluZElucHV0TXVsdGlsaW5lJykgYXMgSFRNTElucHV0RWxlbWVudCkuY2xhc3NMaXN0LmFkZCgnaGlkZGVuJyk7XG4gICAgICAgICAgKGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdpbmRpdmlkdWFsV29yZHNNb2RlTGFiZWwnKSBhcyBIVE1MSW5wdXRFbGVtZW50KS5jbGFzc0xpc3QuYWRkKCdoaWRkZW4nKTtcbiAgICAgICAgICAoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2luZGl2aWR1YWxXb3Jkc01vZGUnKSBhcyBIVE1MSW5wdXRFbGVtZW50KS5jbGFzc0xpc3QuYWRkKCdoaWRkZW4nKTtcbiAgICAgICAgICAvLyBlbmQgb2YgdGhlIGRpcnR5IGhhY2tcbiAgICAgICAgfVxuICAgICAgICBpbnB1dEZpZWxkLmRpc3BhdGNoRXZlbnQobmV3IEV2ZW50KCdpbnB1dCcpKTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6cXVvdGVtYXJrXG4gICAgICAgIGNvbnNvbGUuZXJyb3IoXCJVbmV4cGVjdGVkIGVycm9yOiB0aGUgaW5wdXQgZmllbGQgdXNlZCB0byBzZWFyY2ggaXNuJ3QgcGFydCBvZiB0aGUgRE9NLlwiKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBmaW5kTmV4dCgpOiBib29sZWFuIHtcbiAgICBpZiAoIU5neEV4dGVuZGVkUGRmVmlld2VyQ29tcG9uZW50Lm5neEV4dGVuZGVkUGRmVmlld2VySW5pdGlhbGl6ZWQpIHtcbiAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpxdW90ZW1hcmtcbiAgICAgIGNvbnNvbGUuZXJyb3IoXCJUaGUgUERGIHZpZXdlciBoYXNuJ3QgZmluaXNoZWQgaW5pdGlhbGl6aW5nLiBQbGVhc2UgY2FsbCBmaW5kTmV4dCgpIGxhdGVyLlwiKTtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgYnV0dG9uID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2ZpbmROZXh0Jyk7XG4gICAgICBpZiAoYnV0dG9uKSB7XG4gICAgICAgIGJ1dHRvbi5jbGljaygpO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgZmluZFByZXZpb3VzKCk6IGJvb2xlYW4ge1xuICAgIGlmICghTmd4RXh0ZW5kZWRQZGZWaWV3ZXJDb21wb25lbnQubmd4RXh0ZW5kZWRQZGZWaWV3ZXJJbml0aWFsaXplZCkge1xuICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOnF1b3RlbWFya1xuICAgICAgY29uc29sZS5lcnJvcihcIlRoZSBQREYgdmlld2VyIGhhc24ndCBmaW5pc2hlZCBpbml0aWFsaXppbmcuIFBsZWFzZSBjYWxsIGZpbmRQcmV2aW91cygpIGxhdGVyLlwiKTtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgYnV0dG9uID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2ZpbmRQcmV2aW91cycpO1xuICAgICAgaWYgKGJ1dHRvbikge1xuICAgICAgICBidXR0b24uY2xpY2soKTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIHByaW50KHByaW50UmFuZ2U/OiBQREZQcmludFJhbmdlKSB7XG4gICAgY29uc3QgUERGVmlld2VyQXBwbGljYXRpb246IElQREZWaWV3ZXJBcHBsaWNhdGlvbiA9ICh3aW5kb3cgYXMgYW55KS5QREZWaWV3ZXJBcHBsaWNhdGlvbjtcbiAgICBjb25zdCBhbHJlYWR5VGhlcmUgPSAhIXdpbmRvd1snaXNJblBERlByaW50UmFuZ2UnXSAmJiAhcHJpbnRSYW5nZTtcbiAgICBpZiAoIWFscmVhZHlUaGVyZSkge1xuICAgICAgaWYgKCFwcmludFJhbmdlKSB7XG4gICAgICAgIHByaW50UmFuZ2UgPSB7fSBhcyBQREZQcmludFJhbmdlO1xuICAgICAgfVxuICAgICAgdGhpcy5zZXRQcmludFJhbmdlKHByaW50UmFuZ2UpO1xuICAgIH1cbiAgICAod2luZG93IGFzIGFueSkucHJpbnRQREYoKTtcbiAgICBpZiAoIWFscmVhZHlUaGVyZSkge1xuICAgICAgUERGVmlld2VyQXBwbGljYXRpb24uZXZlbnRCdXMub24oJ2FmdGVycHJpbnQnLCAoKSA9PiB7XG4gICAgICAgIHRoaXMucmVtb3ZlUHJpbnRSYW5nZSgpO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIHJlbW92ZVByaW50UmFuZ2UoKSB7XG4gICAgd2luZG93Wydpc0luUERGUHJpbnRSYW5nZSddID0gdW5kZWZpbmVkO1xuICAgIHdpbmRvd1snZmlsdGVyZWRQYWdlQ291bnQnXSA9IHVuZGVmaW5lZDtcbiAgfVxuXG4gIHB1YmxpYyBzZXRQcmludFJhbmdlKHByaW50UmFuZ2U6IFBERlByaW50UmFuZ2UpIHtcbiAgICBjb25zdCBQREZWaWV3ZXJBcHBsaWNhdGlvbjogSVBERlZpZXdlckFwcGxpY2F0aW9uID0gKHdpbmRvdyBhcyBhbnkpLlBERlZpZXdlckFwcGxpY2F0aW9uO1xuICAgIHdpbmRvd1snaXNJblBERlByaW50UmFuZ2UnXSA9IChwYWdlOiBudW1iZXIpID0+IHRoaXMuaXNJblBERlByaW50UmFuZ2UocGFnZSwgcHJpbnRSYW5nZSBhcyBQREZQcmludFJhbmdlKTtcbiAgICB3aW5kb3dbJ2ZpbHRlcmVkUGFnZUNvdW50J10gPSB0aGlzLmZpbHRlcmVkUGFnZUNvdW50KFBERlZpZXdlckFwcGxpY2F0aW9uLnBhZ2VzQ291bnQsIHByaW50UmFuZ2UpO1xuICB9XG5cbiAgcHVibGljIGZpbHRlcmVkUGFnZUNvdW50KHBhZ2VDb3VudDogbnVtYmVyLCByYW5nZTogUERGUHJpbnRSYW5nZSk6IG51bWJlciB7XG4gICAgbGV0IHJlc3VsdCA9IDA7XG4gICAgZm9yIChsZXQgcGFnZSA9IDE7IHBhZ2UgPD0gcGFnZUNvdW50OyBwYWdlKyspIHtcbiAgICAgIGlmICh0aGlzLmlzSW5QREZQcmludFJhbmdlKHBhZ2UsIHJhbmdlKSkge1xuICAgICAgICByZXN1bHQrKztcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIHB1YmxpYyBpc0luUERGUHJpbnRSYW5nZShwYWdlSW5kZXg6IG51bWJlciwgcHJpbnRSYW5nZTogUERGUHJpbnRSYW5nZSkge1xuICAgIGNvbnN0IHBhZ2UgPSBwYWdlSW5kZXggKyAxO1xuICAgIGlmIChwcmludFJhbmdlLmZyb20pIHtcbiAgICAgIGlmIChwYWdlIDwgcHJpbnRSYW5nZS5mcm9tKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKHByaW50UmFuZ2UudG8pIHtcbiAgICAgIGlmIChwYWdlID4gcHJpbnRSYW5nZS50bykge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChwcmludFJhbmdlLmV4Y2x1ZGVkKSB7XG4gICAgICBjb25zdCBlID0gcHJpbnRSYW5nZS5leGNsdWRlZCBhcyBBcnJheTxudW1iZXI+O1xuICAgICAgaWYgKGUuc29tZSgocCkgPT4gcCA9PT0gcGFnZSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAocHJpbnRSYW5nZS5pbmNsdWRlZCkge1xuICAgICAgaWYgKCFwcmludFJhbmdlLmluY2x1ZGVkLnNvbWUoKHApID0+IHAgPT09IHBhZ2UpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBwdWJsaWMgZ2V0UGFnZUFzVGV4dChwYWdlTnVtYmVyOiBudW1iZXIpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IFBERlZpZXdlckFwcGxpY2F0aW9uOiBJUERGVmlld2VyQXBwbGljYXRpb24gPSAod2luZG93IGFzIGFueSkuUERGVmlld2VyQXBwbGljYXRpb247XG4gICAgY29uc3QgcGRmRG9jdW1lbnQgPSBQREZWaWV3ZXJBcHBsaWNhdGlvbi5wZGZEb2N1bWVudDtcblxuICAgIGNvbnN0IHBhZ2VQcm9taXNlOiBQcm9taXNlPGFueT4gPSBwZGZEb2N1bWVudC5nZXRQYWdlKHBhZ2VOdW1iZXIpO1xuXG4gICAgY29uc3QgZXh0cmFjdFRleHRTbmlwcGV0cyA9IChwZGZQYWdlKSA9PiBQcm9taXNlLnJlc29sdmUocGRmUGFnZS5nZXRUZXh0Q29udGVudCgpKTtcbiAgICBjb25zdCBjb21iaW5lVGV4dFNuaXBwZXRzID0gKHRleHRTbmlwcGV0cykgPT4gUHJvbWlzZS5yZXNvbHZlKHRoaXMuY29udmVydFRleHRJbmZvVG9UZXh0KHRleHRTbmlwcGV0cykpO1xuICAgIHJldHVybiBwYWdlUHJvbWlzZS50aGVuKGV4dHJhY3RUZXh0U25pcHBldHMpLnRoZW4oY29tYmluZVRleHRTbmlwcGV0cyk7XG4gIH1cblxuICBwcml2YXRlIGNvbnZlcnRUZXh0SW5mb1RvVGV4dCh0ZXh0SW5mbzogYW55KTogc3RyaW5nIHtcbiAgICBpZiAoIXRleHRJbmZvKSB7XG4gICAgICByZXR1cm4gJyc7XG4gICAgfVxuICAgIHJldHVybiB0ZXh0SW5mby5pdGVtcy5tYXAoKGluZm86IHsgc3RyOiBhbnkgfSkgPT4gaW5mby5zdHIpLmpvaW4oJycpO1xuICB9XG5cbiAgcHVibGljIGdldFBhZ2VBc0ltYWdlKHBhZ2VOdW1iZXI6IG51bWJlciwgc2NhbGU6IFBERkV4cG9ydFNjYWxlRmFjdG9yLCBiYWNrZ3JvdW5kPzogc3RyaW5nLCBiYWNrZ3JvdW5kQ29sb3JUb1JlcGxhY2U6IHN0cmluZyA9ICcjRkZGRkZGJyk6IFByb21pc2U8YW55PiB7XG4gICAgY29uc3QgUERGVmlld2VyQXBwbGljYXRpb246IElQREZWaWV3ZXJBcHBsaWNhdGlvbiA9ICh3aW5kb3cgYXMgYW55KS5QREZWaWV3ZXJBcHBsaWNhdGlvbjtcbiAgICBjb25zdCBwZGZEb2N1bWVudCA9IFBERlZpZXdlckFwcGxpY2F0aW9uLnBkZkRvY3VtZW50O1xuICAgIGNvbnN0IHBhZ2VQcm9taXNlOiBQcm9taXNlPGFueT4gPSBwZGZEb2N1bWVudC5nZXRQYWdlKHBhZ2VOdW1iZXIpO1xuICAgIGNvbnN0IGltYWdlUHJvbWlzZSA9IChwZGZQYWdlKSA9PiBQcm9taXNlLnJlc29sdmUodGhpcy5kcmF3KHBkZlBhZ2UsIHNjYWxlLCBiYWNrZ3JvdW5kLCBiYWNrZ3JvdW5kQ29sb3JUb1JlcGxhY2UpKTtcblxuICAgIHJldHVybiBwYWdlUHJvbWlzZS50aGVuKGltYWdlUHJvbWlzZSk7XG4gIH1cblxuICBwcml2YXRlIGRyYXcocGRmUGFnZTogYW55LCBzY2FsZTogUERGRXhwb3J0U2NhbGVGYWN0b3IsIGJhY2tncm91bmQ/OiBzdHJpbmcsIGJhY2tncm91bmRDb2xvclRvUmVwbGFjZTogc3RyaW5nID0gJyNGRkZGRkYnKTogUHJvbWlzZTxIVE1MQ2FudmFzRWxlbWVudD4ge1xuICAgIGxldCB6b29tRmFjdG9yID0gMTtcbiAgICBpZiAoc2NhbGUuc2NhbGUpIHtcbiAgICAgIHpvb21GYWN0b3IgPSBzY2FsZS5zY2FsZTtcbiAgICB9IGVsc2UgaWYgKHNjYWxlLndpZHRoKSB7XG4gICAgICB6b29tRmFjdG9yID0gc2NhbGUud2lkdGggLyBwZGZQYWdlLmdldFZpZXdwb3J0KHsgc2NhbGU6IDEgfSkud2lkdGg7XG4gICAgfSBlbHNlIGlmIChzY2FsZS5oZWlnaHQpIHtcbiAgICAgIHpvb21GYWN0b3IgPSBzY2FsZS5oZWlnaHQgLyBwZGZQYWdlLmdldFZpZXdwb3J0KHsgc2NhbGU6IDEgfSkuaGVpZ2h0O1xuICAgIH1cbiAgICBjb25zdCB2aWV3cG9ydCA9IHBkZlBhZ2UuZ2V0Vmlld3BvcnQoe1xuICAgICAgc2NhbGU6IHpvb21GYWN0b3IsXG4gICAgfSk7XG4gICAgY29uc3QgeyBjdHgsIGNhbnZhcyB9ID0gdGhpcy5nZXRQYWdlRHJhd0NvbnRleHQodmlld3BvcnQud2lkdGgsIHZpZXdwb3J0LmhlaWdodCk7XG4gICAgY29uc3QgZHJhd1ZpZXdwb3J0ID0gdmlld3BvcnQuY2xvbmUoKTtcblxuICAgIGNvbnN0IHJlbmRlckNvbnRleHQgPSB7XG4gICAgICBjYW52YXNDb250ZXh0OiBjdHgsXG4gICAgICB2aWV3cG9ydDogZHJhd1ZpZXdwb3J0LFxuICAgICAgYmFja2dyb3VuZCxcbiAgICAgIGJhY2tncm91bmRDb2xvclRvUmVwbGFjZSxcbiAgICB9O1xuICAgIGNvbnN0IHJlbmRlclRhc2sgPSBwZGZQYWdlLnJlbmRlcihyZW5kZXJDb250ZXh0KTtcblxuICAgIGNvbnN0IGRhdGFVcmxQcm9taXNlID0gKCkgPT4gUHJvbWlzZS5yZXNvbHZlKGNhbnZhcy50b0RhdGFVUkwoKSk7XG5cbiAgICByZXR1cm4gcmVuZGVyVGFzay5wcm9taXNlLnRoZW4oZGF0YVVybFByb21pc2UpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRQYWdlRHJhd0NvbnRleHQod2lkdGg6IG51bWJlciwgaGVpZ2h0OiBudW1iZXIpOiBEcmF3Q29udGV4dCB7XG4gICAgY29uc3QgY2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7XG4gICAgY29uc3QgY3R4ID0gY2FudmFzLmdldENvbnRleHQoJzJkJywgeyBhbHBoYTogdHJ1ZSB9KTtcbiAgICBpZiAoIWN0eCkge1xuICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOiBxdW90ZW1hcmtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkNvdWxkbid0IGNyZWF0ZSB0aGUgMmQgY29udGV4dFwiKTtcbiAgICB9XG5cbiAgICBjYW52YXMud2lkdGggPSB3aWR0aDtcbiAgICBjYW52YXMuaGVpZ2h0ID0gaGVpZ2h0O1xuICAgIGNhbnZhcy5zdHlsZS53aWR0aCA9IGAke3dpZHRofXB4YDtcbiAgICBjYW52YXMuc3R5bGUuaGVpZ2h0ID0gYCR7aGVpZ2h0fXB4YDtcblxuICAgIHJldHVybiB7IGN0eCwgY2FudmFzIH07XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgZ2V0Q3VycmVudERvY3VtZW50QXNCbG9iKCk6IFByb21pc2U8QmxvYj4ge1xuICAgIGNvbnN0IFBERlZpZXdlckFwcGxpY2F0aW9uOiBJUERGVmlld2VyQXBwbGljYXRpb24gPSAod2luZG93IGFzIGFueSkuUERGVmlld2VyQXBwbGljYXRpb247XG4gICAgY29uc3QgZGF0YSA9IGF3YWl0IFBERlZpZXdlckFwcGxpY2F0aW9uLnBkZkRvY3VtZW50LnNhdmVEb2N1bWVudChQREZWaWV3ZXJBcHBsaWNhdGlvbi5wZGZEb2N1bWVudC5hbm5vdGF0aW9uU3RvcmFnZSk7XG4gICAgcmV0dXJuIG5ldyBCbG9iKFtkYXRhXSwgeyB0eXBlOiAnYXBwbGljYXRpb24vcGRmJyB9KTtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBnZXRGb3JtRGF0YShjdXJyZW50Rm9ybVZhbHVlcyA9IHRydWUpOiBQcm9taXNlPEFycmF5PE9iamVjdD4+IHtcbiAgICBjb25zdCBQREZWaWV3ZXJBcHBsaWNhdGlvbjogSVBERlZpZXdlckFwcGxpY2F0aW9uID0gKHdpbmRvdyBhcyBhbnkpLlBERlZpZXdlckFwcGxpY2F0aW9uO1xuICAgIGNvbnN0IHBkZiAvKjogUERGRG9jdW1lbnRQcm94eSAqLyA9IFBERlZpZXdlckFwcGxpY2F0aW9uLnBkZkRvY3VtZW50O1xuICAgIC8vIHNjcmVlbiBEUEkgLyBQREYgRFBJXG4gICAgY29uc3QgZHBpUmF0aW8gPSA5NiAvIDcyO1xuICAgIGNvbnN0IHJlc3VsdDogQXJyYXk8T2JqZWN0PiA9IFtdO1xuICAgIGZvciAobGV0IGkgPSAxOyBpIDw9IHBkZi5udW1QYWdlczsgaSsrKSB7XG4gICAgICAvLyB0cmFjayB0aGUgY3VycmVudCBwYWdlXG4gICAgICBjb25zdCBjdXJyZW50UGFnZSAvKiA6IFBERlBhZ2VQcm94eSAqLyA9IGF3YWl0IHBkZi5nZXRQYWdlKGkpO1xuICAgICAgY29uc3QgYW5ub3RhdGlvbnMgPSBhd2FpdCBjdXJyZW50UGFnZS5nZXRBbm5vdGF0aW9ucygpO1xuXG4gICAgICBhbm5vdGF0aW9uc1xuICAgICAgICAuZmlsdGVyKChhKSA9PiBhLnN1YnR5cGUgPT09ICdXaWRnZXQnKSAvLyBnZXQgdGhlIGZvcm0gZmllbGQgYW5ub3RhdGlvbnMgb25seVxuICAgICAgICAubWFwKChhKSA9PiAoeyAuLi5hIH0pKSAvLyBvbmx5IGV4cG9zZSBjb3BpZXMgb2YgdGhlIGFubm90YXRpb25zIHRvIGF2b2lkIHNpZGUtZWZmZWN0c1xuICAgICAgICAuZm9yRWFjaCgoYSkgPT4ge1xuICAgICAgICAgIC8vIGdldCB0aGUgcmVjdGFuZ2xlIHRoYXQgcmVwcmVzZW50IHRoZSBzaW5nbGUgZmllbGRcbiAgICAgICAgICAvLyBhbmQgcmVzaXplIGl0IGFjY29yZGluZyB0byB0aGUgY3VycmVudCBEUElcbiAgICAgICAgICBjb25zdCBmaWVsZFJlY3Q6IEFyc