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.
356 lines • 53.3 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) {
let 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) => new Promise((resolve, reject) => {
const textSnippets = pdfPage.getTextContent();
resolve(textSnippets);
});
const combineTextSnippets = (textSnippets) => new Promise((resolve, reject) => {
const text = this.convertTextInfoToText(textSnippets);
resolve(text);
});
return pagePromise.then(extractTextSnippets).then(combineTextSnippets);
}
convertTextInfoToText(textInfo) {
if (!textInfo) {
return '';
}
return textInfo.items.map((info) => info.str).join('');
}
getPageAsImage(pageNumber, scale) {
const PDFViewerApplication = window.PDFViewerApplication;
const pdfDocument = PDFViewerApplication.pdfDocument;
const pagePromise = pdfDocument.getPage(pageNumber);
const imagePromise = (pdfPage) => new Promise((resolve, reject) => {
resolve(this.draw(pdfPage, scale));
});
return pagePromise.then(imagePromise);
}
draw(pdfPage, scale) {
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: 'rgba(255, 0, 255, 0.3)',
};
const renderTask = pdfPage.render(renderContext);
const dataUrlPromise = () => new Promise((resolve, reject) => {
resolve(canvas.toDataURL());
});
return renderTask.promise.then(dataUrlPromise);
}
getPageDrawContext(width, height) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d', { alpha: false });
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() {
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
.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
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;
const pageNumbers = pages?.map((page) => page.id);
return pageNumbers;
}
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),
});
}
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LWV4dGVuZGVkLXBkZi12aWV3ZXIuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1leHRlbmRlZC1wZGYtdmlld2VyL3NyYy9saWIvbmd4LWV4dGVuZGVkLXBkZi12aWV3ZXIuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQy9CLE9BQU8sRUFBRSw2QkFBNkIsRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBMkJwRixNQUFNLE9BQU8sMkJBQTJCO0lBR3RDO1FBRk8scUJBQWdCLEdBQUcsSUFBSSxPQUFPLEVBQVEsQ0FBQztJQUUvQixDQUFDO0lBRVQsWUFBWSxDQUFDLElBQW1CLEVBQUUsVUFBdUIsRUFBRTtRQUNoRSxPQUFPLEdBQUc7WUFDUixHQUFHLE9BQU87WUFDVix1QkFBdUIsRUFBRSxJQUFJO1NBQzlCLENBQUM7UUFDRixNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQztRQUM1QyxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQzFDLENBQUM7SUFFTSxJQUFJLENBQUMsSUFBWSxFQUFFLFVBQXVCLEVBQUU7UUFDakQsSUFBSSxDQUFDLDZCQUE2QixDQUFDLCtCQUErQixFQUFFO1lBQ2xFLHFDQUFxQztZQUNyQyxPQUFPLENBQUMsS0FBSyxDQUFDLHdFQUF3RSxDQUFDLENBQUM7WUFDeEYsT0FBTyxLQUFLLENBQUM7U0FDZDthQUFNO1lBQ0wsTUFBTSxvQkFBb0IsR0FBRyxRQUFRLENBQUMsY0FBYyxDQUFDLGtCQUFrQixDQUFxQixDQUFDO1lBQzdGLElBQUksb0JBQW9CLEVBQUU7Z0JBQ3hCLG9CQUFvQixDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUMsWUFBWSxJQUFJLEtBQUssQ0FBQzth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QyxXQUFXLENBQUMsT0FBZTtRQUN0QyxNQUFNLG9CQUFvQixHQUEyQixNQUFjLENBQUMsb0JBQW9CLENBQUM7UUFDekYsTUFBTSxxQkFBcUIsR0FBRyxNQUFNLG9CQUFvQixDQUFDLFNBQVMsQ0FBQyw0QkFBNEIsQ0FBQztRQUNoRyxJQUFJLHFCQUFxQixFQUFFO1lBQ3pCLElBQUksU0FBUyxHQUFHLHFCQUFxQixDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUN6RCxNQUFNLFFBQVEsR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLGFBQWEsT0FBTyxJQUFJLENBQUMsQ0FBQztZQUNsRSxJQUFJLFFBQVEsRUFBRTtnQkFDWixTQUFTLEdBQUksUUFBNkIsQ0FBQyxPQUFPLENBQUM7Z0JBQ2xELFFBQTZCLENBQUMsT0FBTyxHQUFHLENBQUMsU0FBUyxDQUFDO2FBQ3JEO1lBQ0QscUJBQXFCLENBQUMsYUFBYSxDQUFDLE9BQU8sRUFBRSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBQ3pELG9CQUFvQixDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsdUJBQXVCLEVBQUU7Z0JBQzlELE1BQU0sRUFBRSxJQUFJO2dCQUNaLE9BQU8sRUFBRSxPQUFPLENBQUMsT0FBTyxDQUFDLHFCQUFxQixDQUFDO2FBQ2hELENBQUMsQ0FBQztTQUNKO0lBQ0gsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgTmd4RXh0ZW5kZWRQZGZWaWV3ZXJDb21wb25lbnQgfSBmcm9tICcuL25neC1leHRlbmRlZC1wZGYtdmlld2VyLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBQZGZMYXllciB9IGZyb20gJy4vb3B0aW9ucy9vcHRpb25hbF9jb250ZW50X2NvbmZpZyc7XG5pbXBvcnQgeyBQREZQcmludFJhbmdlIH0gZnJvbSAnLi9vcHRpb25zL3BkZi1wcmludC1yYW5nZSc7XG5pbXBvcnQgeyBJUERGVmlld2VyQXBwbGljYXRpb24gfSBmcm9tICcuL29wdGlvbnMvcGRmLXZpZXdlci1hcHBsaWNhdGlvbic7XG5cbmV4cG9ydCBpbnRlcmZhY2UgRmluZE9wdGlvbnMge1xuICBoaWdobGlnaHRBbGw/OiBib29sZWFuO1xuICBtYXRjaENhc2U/OiBib29sZWFuO1xuICB3aG9sZVdvcmRzPzogYm9vbGVhbjtcbiAgaWdub3JlQWNjZW50cz86IGJvb2xlYW47XG4gIGZpbmRNdWx0aXBsZVNlYXJjaFRleHRzPzogYm9vbGVhbjtcbiAgZnV6enlTZWFyY2g/OiBib29sZWFuO1xuICBjdXJyZW50UGFnZT86IGJvb2xlYW47IC8vIHNlYXJjaCBvbmx5IGluIHRoZSBjdXJyZW50IHBhZ2VcbiAgcGFnZVJhbmdlPzogc3RyaW5nOyAvLyBwYWdlIHJhbmdlIGRlZmluaXRpb24sIGUuZy4gXCIyXCIsIFwiMiwzLDRcIiwgXCI1LTZcIiBvciBcIjIsNS02LDdcIlxufVxuXG5pbnRlcmZhY2UgRHJhd0NvbnRleHQge1xuICBjdHg6IENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRDtcbiAgY2FudmFzOiBIVE1MQ2FudmFzRWxlbWVudDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBQREZFeHBvcnRTY2FsZUZhY3RvciB7XG4gIHdpZHRoPzogbnVtYmVyO1xuICBoZWlnaHQ/OiBudW1iZXI7XG4gIHNjYWxlPzogbnVtYmVyO1xufVxuXG5leHBvcnQgY2xhc3MgTmd4RXh0ZW5kZWRQZGZWaWV3ZXJTZXJ2aWNlIHtcbiAgcHVibGljIHJlY2FsY3VsYXRlU2l6ZSQgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuXG4gIGNvbnN0cnVjdG9yKCkge31cblxuICBwdWJsaWMgZmluZE11bHRpcGxlKHRleHQ6IEFycmF5PHN0cmluZz4sIG9wdGlvbnM6IEZpbmRPcHRpb25zID0ge30pOiBib29sZWFuIHtcbiAgICBvcHRpb25zID0ge1xuICAgICAgLi4ub3B0aW9ucyxcbiAgICAgIGZpbmRNdWx0aXBsZVNlYXJjaFRleHRzOiB0cnVlLFxuICAgIH07XG4gICAgY29uc3Qgc2VhcmNoU3RyaW5nID0gdGV4dC5qb2luKCdcXG4nKSArICdcXG4nO1xuICAgIHJldHVybiB0aGlzLmZpbmQoc2VhcmNoU3RyaW5nLCBvcHRpb25zKTtcbiAgfVxuXG4gIHB1YmxpYyBmaW5kKHRleHQ6IHN0cmluZywgb3B0aW9uczogRmluZE9wdGlvbnMgPSB7fSk6IGJvb2xlYW4ge1xuICAgIGlmICghTmd4RXh0ZW5kZWRQZGZWaWV3ZXJDb21wb25lbnQubmd4RXh0ZW5kZWRQZGZWaWV3ZXJJbml0aWFsaXplZCkge1xuICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOnF1b3RlbWFya1xuICAgICAgY29uc29sZS5lcnJvcihcIlRoZSBQREYgdmlld2VyIGhhc24ndCBmaW5pc2hlZCBpbml0aWFsaXppbmcuIFBsZWFzZSBjYWxsIGZpbmQoKSBsYXRlci5cIik7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGhpZ2hsaWdodEFsbENoZWNrYm94ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2ZpbmRIaWdobGlnaHRBbGwnKSBhcyBIVE1MSW5wdXRFbGVtZW50O1xuICAgICAgaWYgKGhpZ2hsaWdodEFsbENoZWNrYm94KSB7XG4gICAgICAgIGhpZ2hsaWdodEFsbENoZWNrYm94LmNoZWNrZWQgPSBvcHRpb25zLmhpZ2hsaWdodEFsbCB8fCBmYWxzZTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGZpbmRQYWdlUmFuZ2UgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZmluZFJhbmdlJykgYXMgSFRNTElucHV0RWxlbWVudDtcbiAgICAgIGlmIChmaW5kUGFnZVJhbmdlKSB7XG4gICAgICAgIGZpbmRQYWdlUmFuZ2UudmFsdWUgPSBvcHRpb25zLnBhZ2VSYW5nZSB8fCAnJztcbiAgICAgIH1cbiAgICAgIGNvbnN0IGZpbmRDdXJyZW50UGFnZUNoZWNrYm94ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2ZpbmRDdXJyZW50UGFnZScpIGFzIEhUTUxJbnB1dEVsZW1lbnQ7XG4gICAgICBpZiAoZmluZEN1cnJlbnRQYWdlQ2hlY2tib3gpIHtcbiAgICAgICAgZmluZEN1cnJlbnRQYWdlQ2hlY2tib3guY2hlY2tlZCA9IG9wdGlvbnMuY3VycmVudFBhZ2UgfHwgZmFsc2U7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IG1hdGNoQ2FzZUNoZWNrYm94ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2ZpbmRNYXRjaENhc2UnKSBhcyBIVE1MSW5wdXRFbGVtZW50O1xuICAgICAgaWYgKG1hdGNoQ2FzZUNoZWNrYm94KSB7XG4gICAgICAgIG1hdGNoQ2FzZUNoZWNrYm94LmNoZWNrZWQgPSBvcHRpb25zLm1hdGNoQ2FzZSB8fCBmYWxzZTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGVudGlyZVdvcmRDaGVja2JveCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdmaW5kRW50aXJlV29yZCcpIGFzIEhUTUxJbnB1dEVsZW1lbnQ7XG4gICAgICBpZiAoZW50aXJlV29yZENoZWNrYm94KSB7XG4gICAgICAgIGVudGlyZVdvcmRDaGVja2JveC5jaGVja2VkID0gb3B0aW9ucy53aG9sZVdvcmRzIHx8IGZhbHNlO1xuICAgICAgfVxuICAgICAgY29uc3QgZmluZElnbm9yZUFjY2VudHNDaGVja2JveCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdmaW5kSWdub3JlQWNjZW50cycpIGFzIEhUTUxJbnB1dEVsZW1lbnQ7XG4gICAgICBpZiAoZmluZElnbm9yZUFjY2VudHNDaGVja2JveCkge1xuICAgICAgICBmaW5kSWdub3JlQWNjZW50c0NoZWNrYm94LmNoZWNrZWQgPSBvcHRpb25zLmlnbm9yZUFjY2VudHMgfHwgZmFsc2U7XG4gICAgICB9XG4gICAgICBjb25zdCBtdWx0aXBsZVNlYXJjaFRlcm1zID0gb3B0aW9ucy5maW5kTXVsdGlwbGVTZWFyY2hUZXh0cyB8fCB0ZXh0LmluY2x1ZGVzKCdcXG4nKSB8fCBmYWxzZTtcbiAgICAgIGNvbnN0IGZpbmRNdWx0aXBsZVNlYXJjaFRleHRzQ2hlY2tib3ggPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZmluZE11bHRpcGxlU2VhcmNoVGV4dHMnKSBhcyBIVE1MSW5wdXRFbGVtZW50O1xuICAgICAgaWYgKGZpbmRNdWx0aXBsZVNlYXJjaFRleHRzQ2hlY2tib3gpIHtcbiAgICAgICAgZmluZE11bHRpcGxlU2VhcmNoVGV4dHNDaGVja2JveC5jaGVja2VkID0gbXVsdGlwbGVTZWFyY2hUZXJtcztcbiAgICAgIH1cbiAgICAgIGNvbnN0IGluZGl2aWR1YWxXb3Jkc01vZGVDaGVja2JveCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdpbmRpdmlkdWFsV29yZHNNb2RlJykgYXMgSFRNTElucHV0RWxlbWVudDtcbiAgICAgIGlmIChpbmRpdmlkdWFsV29yZHNNb2RlQ2hlY2tib3gpIHtcbiAgICAgICAgaW5kaXZpZHVhbFdvcmRzTW9kZUNoZWNrYm94LmNoZWNrZWQgPSBmYWxzZTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGZ1enp5U2VhcmNoQ2hlY2tib3ggPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZmluZEZ1enp5JykgYXMgSFRNTElucHV0RWxlbWVudDtcbiAgICAgIGlmIChmdXp6eVNlYXJjaENoZWNrYm94KSB7XG4gICAgICAgIGZ1enp5U2VhcmNoQ2hlY2tib3guY2hlY2tlZCA9IG9wdGlvbnMuZnV6enlTZWFyY2ggfHwgZmFsc2U7XG4gICAgICB9XG4gICAgICBjb25zdCBpbnB1dEZpZWxkID0gbXVsdGlwbGVTZWFyY2hUZXJtcyA/IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdmaW5kSW5wdXRNdWx0aWxpbmUnKSA6IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdmaW5kSW5wdXQnKTtcbiAgICAgIGlmIChpbnB1dEZpZWxkKSB7XG4gICAgICAgIGlmIChpbnB1dEZpZWxkIGluc3RhbmNlb2YgSFRNTFRleHRBcmVhRWxlbWVudCkge1xuICAgICAgICAgIGlucHV0RmllbGQudmFsdWUgPSB0ZXh0O1xuXG4gICAgICAgICAgLy8gdG9kbyBkaXJ0eSBoYWNrIVxuICAgICAgICAgIGlucHV0RmllbGQuY2xhc3NMaXN0LnJlbW92ZSgnaGlkZGVuJyk7XG4gICAgICAgICAgKGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdmaW5kSW5wdXQnKSBhcyBIVE1MSW5wdXRFbGVtZW50KS5jbGFzc0xpc3QuYWRkKCdoaWRkZW4nKTtcbiAgICAgICAgICAoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2luZGl2aWR1YWxXb3Jkc01vZGVMYWJlbCcpIGFzIEhUTUxJbnB1dEVsZW1lbnQpLmNsYXNzTGlzdC5yZW1vdmUoJ2hpZGRlbicpO1xuICAgICAgICAgIChkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnaW5kaXZpZHVhbFdvcmRzTW9kZScpIGFzIEhUTUxJbnB1dEVsZW1lbnQpLmNsYXNzTGlzdC5yZW1vdmUoJ2hpZGRlbicpO1xuICAgICAgICAgIC8vIGVuZCBvZiB0aGUgZGlydHkgaGFja1xuICAgICAgICB9IGVsc2UgaWYgKGlucHV0RmllbGQgaW5zdGFuY2VvZiBIVE1MSW5wdXRFbGVtZW50KSB7XG4gICAgICAgICAgaW5wdXRGaWVsZC52YWx1ZSA9IHRleHQ7XG4gICAgICAgICAgLy8gdG9kbyBkaXJ0eSBoYWNrIVxuICAgICAgICAgIGlucHV0RmllbGQuY2xhc3NMaXN0LnJlbW92ZSgnaGlkZGVuJyk7XG4gICAgICAgICAgKGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdmaW5kSW5wdXRNdWx0aWxpbmUnKSBhcyBIVE1MSW5wdXRFbGVtZW50KS5jbGFzc0xpc3QuYWRkKCdoaWRkZW4nKTtcbiAgICAgICAgICAoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2luZGl2aWR1YWxXb3Jkc01vZGVMYWJlbCcpIGFzIEhUTUxJbnB1dEVsZW1lbnQpLmNsYXNzTGlzdC5hZGQoJ2hpZGRlbicpO1xuICAgICAgICAgIChkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnaW5kaXZpZHVhbFdvcmRzTW9kZScpIGFzIEhUTUxJbnB1dEVsZW1lbnQpLmNsYXNzTGlzdC5hZGQoJ2hpZGRlbicpO1xuICAgICAgICAgIC8vIGVuZCBvZiB0aGUgZGlydHkgaGFja1xuICAgICAgICB9XG4gICAgICAgIGlucHV0RmllbGQuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnQoJ2lucHV0JykpO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpxdW90ZW1hcmtcbiAgICAgICAgY29uc29sZS5lcnJvcihcIlVuZXhwZWN0ZWQgZXJyb3I6IHRoZSBpbnB1dCBmaWVsZCB1c2VkIHRvIHNlYXJjaCBpc24ndCBwYXJ0IG9mIHRoZSBET00uXCIpO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGZpbmROZXh0KCk6IGJvb2xlYW4ge1xuICAgIGlmICghTmd4RXh0ZW5kZWRQZGZWaWV3ZXJDb21wb25lbnQubmd4RXh0ZW5kZWRQZGZWaWV3ZXJJbml0aWFsaXplZCkge1xuICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOnF1b3RlbWFya1xuICAgICAgY29uc29sZS5lcnJvcihcIlRoZSBQREYgdmlld2VyIGhhc24ndCBmaW5pc2hlZCBpbml0aWFsaXppbmcuIFBsZWFzZSBjYWxsIGZpbmROZXh0KCkgbGF0ZXIuXCIpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBidXR0b24gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZmluZE5leHQnKTtcbiAgICAgIGlmIChidXR0b24pIHtcbiAgICAgICAgYnV0dG9uLmNsaWNrKCk7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBmaW5kUHJldmlvdXMoKTogYm9vbGVhbiB7XG4gICAgaWYgKCFOZ3hFeHRlbmRlZFBkZlZpZXdlckNvbXBvbmVudC5uZ3hFeHRlbmRlZFBkZlZpZXdlckluaXRpYWxpemVkKSB7XG4gICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6cXVvdGVtYXJrXG4gICAgICBjb25zb2xlLmVycm9yKFwiVGhlIFBERiB2aWV3ZXIgaGFzbid0IGZpbmlzaGVkIGluaXRpYWxpemluZy4gUGxlYXNlIGNhbGwgZmluZFByZXZpb3VzKCkgbGF0ZXIuXCIpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBidXR0b24gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZmluZFByZXZpb3VzJyk7XG4gICAgICBpZiAoYnV0dG9uKSB7XG4gICAgICAgIGJ1dHRvbi5jbGljaygpO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgcHJpbnQocHJpbnRSYW5nZT86IFBERlByaW50UmFuZ2UpIHtcbiAgICBjb25zdCBQREZWaWV3ZXJBcHBsaWNhdGlvbjogSVBERlZpZXdlckFwcGxpY2F0aW9uID0gKHdpbmRvdyBhcyBhbnkpLlBERlZpZXdlckFwcGxpY2F0aW9uO1xuICAgIGNvbnN0IGFscmVhZHlUaGVyZSA9ICEhd2luZG93Wydpc0luUERGUHJpbnRSYW5nZSddICYmICFwcmludFJhbmdlO1xuICAgIGlmICghYWxyZWFkeVRoZXJlKSB7XG4gICAgICBpZiAoIXByaW50UmFuZ2UpIHtcbiAgICAgICAgcHJpbnRSYW5nZSA9IHt9IGFzIFBERlByaW50UmFuZ2U7XG4gICAgICB9XG4gICAgICB0aGlzLnNldFByaW50UmFuZ2UocHJpbnRSYW5nZSk7XG4gICAgfVxuICAgICh3aW5kb3cgYXMgYW55KS5wcmludFBERigpO1xuICAgIGlmICghYWxyZWFkeVRoZXJlKSB7XG4gICAgICBQREZWaWV3ZXJBcHBsaWNhdGlvbi5ldmVudEJ1cy5vbignYWZ0ZXJwcmludCcsICgpID0+IHtcbiAgICAgICAgdGhpcy5yZW1vdmVQcmludFJhbmdlKCk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgcmVtb3ZlUHJpbnRSYW5nZSgpIHtcbiAgICB3aW5kb3dbJ2lzSW5QREZQcmludFJhbmdlJ10gPSB1bmRlZmluZWQ7XG4gICAgd2luZG93WydmaWx0ZXJlZFBhZ2VDb3VudCddID0gdW5kZWZpbmVkO1xuICB9XG5cbiAgcHVibGljIHNldFByaW50UmFuZ2UocHJpbnRSYW5nZTogUERGUHJpbnRSYW5nZSkge1xuICAgIGNvbnN0IFBERlZpZXdlckFwcGxpY2F0aW9uOiBJUERGVmlld2VyQXBwbGljYXRpb24gPSAod2luZG93IGFzIGFueSkuUERGVmlld2VyQXBwbGljYXRpb247XG4gICAgd2luZG93Wydpc0luUERGUHJpbnRSYW5nZSddID0gKHBhZ2U6IG51bWJlcikgPT4gdGhpcy5pc0luUERGUHJpbnRSYW5nZShwYWdlLCBwcmludFJhbmdlIGFzIFBERlByaW50UmFuZ2UpO1xuICAgIHdpbmRvd1snZmlsdGVyZWRQYWdlQ291bnQnXSA9IHRoaXMuZmlsdGVyZWRQYWdlQ291bnQoUERGVmlld2VyQXBwbGljYXRpb24ucGFnZXNDb3VudCwgcHJpbnRSYW5nZSk7XG4gIH1cblxuICBwdWJsaWMgZmlsdGVyZWRQYWdlQ291bnQocGFnZUNvdW50OiBudW1iZXIsIHJhbmdlOiBQREZQcmludFJhbmdlKTogbnVtYmVyIHtcbiAgICBsZXQgcmVzdWx0ID0gMDtcbiAgICBmb3IgKGxldCBwYWdlID0gMTsgcGFnZSA8PSBwYWdlQ291bnQ7IHBhZ2UrKykge1xuICAgICAgaWYgKHRoaXMuaXNJblBERlByaW50UmFuZ2UocGFnZSwgcmFuZ2UpKSB7XG4gICAgICAgIHJlc3VsdCsrO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgcHVibGljIGlzSW5QREZQcmludFJhbmdlKHBhZ2VJbmRleDogbnVtYmVyLCBwcmludFJhbmdlOiBQREZQcmludFJhbmdlKSB7XG4gICAgY29uc3QgcGFnZSA9IHBhZ2VJbmRleCArIDE7XG4gICAgaWYgKHByaW50UmFuZ2UuZnJvbSkge1xuICAgICAgaWYgKHBhZ2UgPCBwcmludFJhbmdlLmZyb20pIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAocHJpbnRSYW5nZS50bykge1xuICAgICAgaWYgKHBhZ2UgPiBwcmludFJhbmdlLnRvKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKHByaW50UmFuZ2UuZXhjbHVkZWQpIHtcbiAgICAgIGxldCBlID0gcHJpbnRSYW5nZS5leGNsdWRlZCBhcyBBcnJheTxudW1iZXI+O1xuICAgICAgaWYgKGUuc29tZSgocCkgPT4gcCA9PT0gcGFnZSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAocHJpbnRSYW5nZS5pbmNsdWRlZCkge1xuICAgICAgaWYgKCFwcmludFJhbmdlLmluY2x1ZGVkLnNvbWUoKHApID0+IHAgPT09IHBhZ2UpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBwdWJsaWMgZ2V0UGFnZUFzVGV4dChwYWdlTnVtYmVyOiBudW1iZXIpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IFBERlZpZXdlckFwcGxpY2F0aW9uOiBJUERGVmlld2VyQXBwbGljYXRpb24gPSAod2luZG93IGFzIGFueSkuUERGVmlld2VyQXBwbGljYXRpb247XG4gICAgY29uc3QgcGRmRG9jdW1lbnQgPSBQREZWaWV3ZXJBcHBsaWNhdGlvbi5wZGZEb2N1bWVudDtcblxuICAgIGNvbnN0IHBhZ2VQcm9taXNlOiBQcm9taXNlPGFueT4gPSBwZGZEb2N1bWVudC5nZXRQYWdlKHBhZ2VOdW1iZXIpO1xuXG4gICAgY29uc3QgZXh0cmFjdFRleHRTbmlwcGV0cyA9IChwZGZQYWdlKSA9PlxuICAgICAgbmV3IFByb21pc2U8YW55PigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIGNvbnN0IHRleHRTbmlwcGV0cyA9IHBkZlBhZ2UuZ2V0VGV4dENvbnRlbnQoKTtcbiAgICAgICAgcmVzb2x2ZSh0ZXh0U25pcHBldHMpO1xuICAgICAgfSk7XG4gICAgY29uc3QgY29tYmluZVRleHRTbmlwcGV0cyA9ICh0ZXh0U25pcHBldHMpID0+XG4gICAgICBuZXcgUHJvbWlzZTxzdHJpbmc+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgY29uc3QgdGV4dCA9IHRoaXMuY29udmVydFRleHRJbmZvVG9UZXh0KHRleHRTbmlwcGV0cyk7XG4gICAgICAgIHJlc29sdmUodGV4dCk7XG4gICAgICB9KTtcbiAgICByZXR1cm4gcGFnZVByb21pc2UudGhlbihleHRyYWN0VGV4dFNuaXBwZXRzKS50aGVuKGNvbWJpbmVUZXh0U25pcHBldHMpO1xuICB9XG5cbiAgcHJpdmF0ZSBjb252ZXJ0VGV4dEluZm9Ub1RleHQodGV4dEluZm86IGFueSk6IHN0cmluZyB7XG4gICAgaWYgKCF0ZXh0SW5mbykge1xuICAgICAgcmV0dXJuICcnO1xuICAgIH1cbiAgICByZXR1cm4gdGV4dEluZm8uaXRlbXMubWFwKChpbmZvKSA9PiBpbmZvLnN0cikuam9pbignJyk7XG4gIH1cblxuICBwdWJsaWMgZ2V0UGFnZUFzSW1hZ2UocGFnZU51bWJlcjogbnVtYmVyLCBzY2FsZTogUERGRXhwb3J0U2NhbGVGYWN0b3IpOiBQcm9taXNlPGFueT4ge1xuICAgIGNvbnN0IFBERlZpZXdlckFwcGxpY2F0aW9uOiBJUERGVmlld2VyQXBwbGljYXRpb24gPSAod2luZG93IGFzIGFueSkuUERGVmlld2VyQXBwbGljYXRpb247XG4gICAgY29uc3QgcGRmRG9jdW1lbnQgPSBQREZWaWV3ZXJBcHBsaWNhdGlvbi5wZGZEb2N1bWVudDtcbiAgICBjb25zdCBwYWdlUHJvbWlzZTogUHJvbWlzZTxhbnk+ID0gcGRmRG9jdW1lbnQuZ2V0UGFnZShwYWdlTnVtYmVyKTtcbiAgICBjb25zdCBpbWFnZVByb21pc2UgPSAocGRmUGFnZSkgPT5cbiAgICAgIG5ldyBQcm9taXNlPGFueT4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICByZXNvbHZlKHRoaXMuZHJhdyhwZGZQYWdlLCBzY2FsZSkpO1xuICAgICAgfSk7XG5cbiAgICByZXR1cm4gcGFnZVByb21pc2UudGhlbihpbWFnZVByb21pc2UpO1xuICB9XG5cbiAgcHJpdmF0ZSBkcmF3KHBkZlBhZ2U6IGFueSwgc2NhbGU6IFBERkV4cG9ydFNjYWxlRmFjdG9yKTogUHJvbWlzZTxIVE1MQ2FudmFzRWxlbWVudD4ge1xuICAgIGxldCB6b29tRmFjdG9yID0gMTtcbiAgICBpZiAoc2NhbGUuc2NhbGUpIHtcbiAgICAgIHpvb21GYWN0b3IgPSBzY2FsZS5zY2FsZTtcbiAgICB9IGVsc2UgaWYgKHNjYWxlLndpZHRoKSB7XG4gICAgICB6b29tRmFjdG9yID0gc2NhbGUud2lkdGggLyBwZGZQYWdlLmdldFZpZXdwb3J0KHsgc2NhbGU6IDEgfSkud2lkdGg7XG4gICAgfSBlbHNlIGlmIChzY2FsZS5oZWlnaHQpIHtcbiAgICAgIHpvb21GYWN0b3IgPSBzY2FsZS5oZWlnaHQgLyBwZGZQYWdlLmdldFZpZXdwb3J0KHsgc2NhbGU6IDEgfSkuaGVpZ2h0O1xuICAgIH1cbiAgICBjb25zdCB2aWV3cG9ydCA9IHBkZlBhZ2UuZ2V0Vmlld3BvcnQoe1xuICAgICAgc2NhbGU6IHpvb21GYWN0b3IsXG4gICAgfSk7XG4gICAgY29uc3QgeyBjdHgsIGNhbnZhcyB9ID0gdGhpcy5nZXRQYWdlRHJhd0NvbnRleHQodmlld3BvcnQud2lkdGgsIHZpZXdwb3J0LmhlaWdodCk7XG4gICAgY29uc3QgZHJhd1ZpZXdwb3J0ID0gdmlld3BvcnQuY2xvbmUoKTtcblxuICAgIGNvbnN0IHJlbmRlckNvbnRleHQgPSB7XG4gICAgICBjYW52YXNDb250ZXh0OiBjdHgsXG4gICAgICB2aWV3cG9ydDogZHJhd1ZpZXdwb3J0LFxuICAgICAgLy8gICAgICBiYWNrZ3JvdW5kOiAncmdiYSgyNTUsIDAsIDI1NSwgMC4zKScsXG4gICAgfTtcbiAgICBjb25zdCByZW5kZXJUYXNrID0gcGRmUGFnZS5yZW5kZXIocmVuZGVyQ29udGV4dCk7XG5cbiAgICBjb25zdCBkYXRhVXJsUHJvbWlzZSA9ICgpID0+XG4gICAgICBuZXcgUHJvbWlzZTxzdHJpbmc+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgcmVzb2x2ZShjYW52YXMudG9EYXRhVVJMKCkpO1xuICAgICAgfSk7XG5cbiAgICByZXR1cm4gcmVuZGVyVGFzay5wcm9taXNlLnRoZW4oZGF0YVVybFByb21pc2UpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRQYWdlRHJhd0NvbnRleHQod2lkdGg6IG51bWJlciwgaGVpZ2h0OiBudW1iZXIpOiBEcmF3Q29udGV4dCB7XG4gICAgY29uc3QgY2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJykgYXMgSFRNTENhbnZhc0VsZW1lbnQ7XG4gICAgY29uc3QgY3R4ID0gY2FudmFzLmdldENvbnRleHQoJzJkJywgeyBhbHBoYTogZmFsc2UgfSk7XG4gICAgaWYgKCFjdHgpIHtcbiAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTogcXVvdGVtYXJrXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDb3VsZG4ndCBjcmVhdGUgdGhlIDJkIGNvbnRleHRcIik7XG4gICAgfVxuXG4gICAgY2FudmFzLndpZHRoID0gd2lkdGg7XG4gICAgY2FudmFzLmhlaWdodCA9IGhlaWdodDtcbiAgICBjYW52YXMuc3R5bGUud2lkdGggPSB3aWR0aCArICdweCc7XG4gICAgY2FudmFzLnN0eWxlLmhlaWdodCA9IGhlaWdodCArICdweCc7XG5cbiAgICByZXR1cm4geyBjdHgsIGNhbnZhcyB9O1xuICB9XG5cbiAgcHVibGljIGFzeW5jIGdldEN1cnJlbnREb2N1bWVudEFzQmxvYigpOiBQcm9taXNlPEJsb2I+IHtcbiAgICBjb25zdCBQREZWaWV3ZXJBcHBsaWNhdGlvbjogSVBERlZpZXdlckFwcGxpY2F0aW9uID0gKHdpbmRvdyBhcyBhbnkpLlBERlZpZXdlckFwcGxpY2F0aW9uO1xuICAgIGNvbnN0IGRhdGEgPSBhd2FpdCBQREZWaWV3ZXJBcHBsaWNhdGlvbi5wZGZEb2N1bWVudC5zYXZlRG9jdW1lbnQoUERGVmlld2VyQXBwbGljYXRpb24ucGRmRG9jdW1lbnQuYW5ub3RhdGlvblN0b3JhZ2UpO1xuICAgIHJldHVybiBuZXcgQmxvYihbZGF0YV0sIHsgdHlwZTogJ2FwcGxpY2F0aW9uL3BkZicgfSk7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgZ2V0Rm9ybURhdGEoKTogUHJvbWlzZTxBcnJheTxPYmplY3Q+PiB7XG4gICAgY29uc3QgUERGVmlld2VyQXBwbGljYXRpb246IElQREZWaWV3ZXJBcHBsaWNhdGlvbiA9ICh3aW5kb3cgYXMgYW55KS5QREZWaWV3ZXJBcHBsaWNhdGlvbjtcbiAgICBjb25zdCBwZGYgLyo6IFBERkRvY3VtZW50UHJveHkgKi8gPSBQREZWaWV3ZXJBcHBsaWNhdGlvbi5wZGZEb2N1bWVudDtcbiAgICAvLyBzY3JlZW4gRFBJIC8gUERGIERQSVxuICAgIGNvbnN0IGRwaVJhdGlvID0gOTYgLyA3MjtcbiAgICBjb25zdCByZXN1bHQ6IEFycmF5PE9iamVjdD4gPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMTsgaSA8PSBwZGYubnVtUGFnZXM7IGkrKykge1xuICAgICAgLy8gdHJhY2sgdGhlIGN1cnJlbnQgcGFnZVxuICAgICAgY29uc3QgY3VycmVudFBhZ2UgLyogOiBQREZQYWdlUHJveHkgKi8gPSBhd2FpdCBwZGYuZ2V0UGFnZShpKTtcbiAgICAgIGNvbnN0IGFubm90YXRpb25zID0gYXdhaXQgY3VycmVudFBhZ2UuZ2V0QW5ub3RhdGlvbnMoKTtcblxuICAgICAgYW5ub3RhdGlvbnNcbiAgICAgICAgLmZpbHRlcigoYSkgPT4gYS5zdWJ0eXBlID09PSAnV2lkZ2V0JykgLy8gZ2V0IHRoZSBmb3JtIGZpZWxkIGFubm90YXRpb25zIG9ubHlcbiAgICAgICAgLmZvckVhY2goKGEpID0+IHtcbiAgICAgICAgICAvLyBnZXQgdGhlIHJlY3RhbmdsZSB0aGF0IHJlcHJlc2VudCB0aGUgc2luZ2xlIGZpZWxkXG4gICAgICAgICAgLy8gYW5kIHJlc2l6ZSBpdCBhY2NvcmRpbmcgdG8gdGhlIGN1cnJlbnQgRFBJXG4gICAgICAgICAgY29uc3QgZmllbGRSZWN0OiBBcnJheTxudW1iZXI+ID0gY3VycmVudFBhZ2UuZ2V0Vmlld3BvcnQoeyBzY2FsZTogZHBpUmF0aW8gfSkuY29udmVydFRvVmlld3BvcnRSZWN0YW5nbGUoYS5yZWN0KTtcblxuICAgICAgICAgIC8vIGFkZCB0aGUgY29ycmVzcG9uZGluZyBpbnB1dFxuICAgICAgICAgIHJlc3VsdC5wdXNoKHsgZmllbGRBbm5vdGF0aW9uOiBhLCBmaWVsZFJlY3QsIHBhZ2VOdW1iZXI6IGkgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYSBwYWdlIHRvIHRoZSByZW5kZXJpbmcgcXVldWVcbiAgICogQHBhcmFtIHtudW1iZXJ9IHBhZ2VJbmRleCBJbmRleCBvZiB0aGUgcGFnZSB0byByZW5kZXJcbiAgICogQHJldHVybnMge2Jvb2xlYW59IGZhbHNlLCBpZiB0aGUgcGFnZSBoYXMgYWxyZWFkeSBiZWVuIHJlbmRlcmVkXG4gICAqIG9yIGlmIGl0J3Mgb3V0IG9mIHJhbmdlXG4gICAqL1xuICBwdWJsaWMgYWRkUGFnZVRvUmVuZGVyUXVldWUocGFnZUluZGV4OiBudW1iZXIpOiBib29sZWFuIHtcbiAgICBjb25zdCBQREZWaWV3ZXJBcHBsaWNhdGlvbjogSVBERlZpZXdlckFwcGxpY2F0aW9uID0gKHdpbmRvdyBhcyBhbnkpLlBERlZpZXdlckFwcGxpY2F0aW9uO1xuICAgIHJldHVybiBQREZWaWV3ZXJBcHBsaWNhdGlvbi5wZGZWaWV3ZXIuYWRkUGFnZVRvUmVuZGVyUXVldWUocGFnZUluZGV4KTtcbiAgfVxuXG4gIHB1YmxpYyBpc1JlbmRlclF1ZXVlRW1wdHkoKTogYm9vbGVhbiB7XG4gICAgY29uc3Qgc2Nyb2xsZWREb3duID0gdHJ1ZTtcbiAgICBjb25zdCByZW5kZXJFeHRyYSA9IGZhbHNlO1xuICAgIGNvbnN0IFBERlZpZXdlckFwcGxpY2F0aW9uOiBJUERGVmlld2VyQXBwbGljYXRpb24gPSAod2luZG93IGFzIGFueSkuUERGVmlld2VyQXBwbGljYXRpb247XG4gICAgY29uc3QgbmV4dFBhZ2UgPSBQREZWaWV3ZXJBcHBsaWNhdGlvbi5wZGZWaWV3ZXIucmVuZGVyaW5nUXVldWUuZ2V0SGlnaGVzdFByaW9yaXR5KFxuICAgICAgUERGVmlld2VyQXBwbGljYXRpb24ucGRmVmlld2VyLl9nZXRWaXNpYmxlUGFnZXMoKSxcbiAgICAgIFBERlZpZXdlckFwcGxpY2F0aW9uLnBkZlZpZXdlci5fcGFnZXMsXG4gICAgICBzY3JvbGxlZERvd24sXG4gICAgICByZW5kZXJFeHRyYVxuICAgICk7XG4gICAgcmV0dXJuICFuZXh0UGFnZTtcbiAgfVxuXG4gIHB1YmxpYyBoYXNQYWdlQmVlblJlbmRlcmVkKHBhZ2VJbmRleDogbnVtYmVyKTogYm9vbGVhbiB7XG4gICAgY29uc3QgUERGVmlld2VyQXBwbGljYXRpb246IElQREZWaWV3ZXJBcHBsaWNhdGlvbiA9ICh3aW5kb3cgYXMgYW55KS5QREZWaWV3ZXJBcHBsaWNhdGlvbjtcbiAgICBjb25zdCBwYWdlcyA9IFBERlZpZXdlckFwcGxpY2F0aW9uLnBkZlZpZXdlci5fcGFnZXM7XG4gICAgaWYgKHBhZ2VzLmxlbmd0aCA+IHBhZ2VJbmRleCAmJiBwYWdlSW5kZXggPj0gMCkge1xuICAgICAgY29uc3QgcGFnZVZpZXcgPSBwYWdlc1twYWdlSW5kZXhdO1xuICAgICAgY29uc3QgaXNMb2FkaW5nID0gcGFnZVZpZXcuZGl2LnF1ZXJ5U2VsZWN0b3IoJy5sb2FkaW5nSWNvbicpO1xuICAgICAgcmV0dXJuICFpc0xvYWRpbmc7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHB1YmxpYyBjdXJyZW50bHlSZW5kZXJlZFBhZ2VzKCk6IEFycmF5PG51bWJlcj4ge1xuICAgIGN