UNPKG

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.

278 lines (271 loc) 35.8 kB
import { CSP_NONCE, Inject, Injectable, effect, signal } from '@angular/core'; import { getVersionSuffix, pdfDefaultOptions } from './options/pdf-default-options'; import * as i0 from "@angular/core"; import * as i1 from "./pdf-csp-policy.service"; export class PDFScriptLoaderService { pdfCspPolicyService; csp_nonce; _forceUsingLegacyES5 = false; get forceUsingLegacyES5() { return this._forceUsingLegacyES5; } set forceUsingLegacyES5(value) { console.log('Please use the attribute `[forceUsingLegacyES5]` instead of setting the property in the service.'); this._forceUsingLegacyES5 = value; } // this event is fired when the pdf.js library has been loaded and objects like PDFApplication are available onPDFJSInitSignal = signal(undefined); pdfjsVersion = getVersionSuffix(pdfDefaultOptions.assetsFolder); shuttingDown = false; _needsES5 = undefined; PDFViewerApplication; PDFViewerApplicationOptions; // private PDFViewerApplicationConstants: any; webViewerLoad; ngxExtendedPdfViewerIncompletelyInitialized = true; constructor(pdfCspPolicyService, csp_nonce) { this.pdfCspPolicyService = pdfCspPolicyService; this.csp_nonce = csp_nonce; effect(() => { if (this.onPDFJSInitSignal()) { this.pdfjsVersion = getVersionSuffix(pdfDefaultOptions.assetsFolder); } }); } addScriptOpChainingSupport(useInlineScripts) { if (!useInlineScripts || this.isCSPApplied()) { return new Promise((resolve) => { const script = this.createScriptElement(pdfDefaultOptions.assetsFolder + '/op-chaining-support.js'); script.onload = () => { script.remove(); script.onload = null; resolve(globalThis.ngxExtendedPdfViewerCanRunModernJSCode); }; script.onerror = () => { script.remove(); globalThis.ngxExtendedPdfViewerCanRunModernJSCode = false; resolve(false); script.onerror = null; }; document.body.appendChild(script); }); } else { const code = ` new (function () { class BrowserCompatibilityTester { // Does your browser doesn't support private fields? #privateField; constructor() { // Does your browser support the logical assignment operators? let x = false; x ||= true; this.#privateMethod(); } // Does your browser doesn't support private methods? #privateMethod() { // check the the browser supports string.at() return 'hello'.at(4); } supportsOptionalChaining() { const optionalChaining = { support: true, }; return optionalChaining?.support; } } function supportsPromiseWithResolvers() { const iframe = document.createElement('iframe'); document.firstElementChild.append(iframe); const useLegacyPdfViewer = 'withResolvers' in iframe.contentWindow['Promise']; iframe.parentElement.removeChild(iframe); return useLegacyPdfViewer; } const supportsOptionalChaining = new BrowserCompatibilityTester().supportsOptionalChaining(); const supportModernPromises = supportsPromiseWithResolvers(); window.ngxExtendedPdfViewerCanRunModernJSCode = supportsOptionalChaining && supportModernPromises; })(); `; const script = this.createInlineScript(code); document.getElementsByTagName('head')[0].appendChild(script); return new Promise((resolve) => { const interval = setInterval(() => { if (globalThis.ngxExtendedPdfViewerCanRunModernJSCode !== undefined) { clearInterval(interval); resolve(globalThis.ngxExtendedPdfViewerCanRunModernJSCode); } }, 1); }); } } createInlineScript(code) { const script = document.createElement('script'); script.async = true; script.type = 'module'; script.className = `ngx-extended-pdf-viewer-script`; script.text = code; if (this.csp_nonce) { // assigning null to script.nonce results in a string "null", so let's add a null check script.nonce = this.csp_nonce; } return script; } isCSPAppliedViaMetaTag() { const metaTags = document.getElementsByTagName('meta'); for (let i = 0; i < metaTags.length; i++) { if (metaTags[i].getAttribute('http-equiv') === 'Content-Security-Policy') { return true; } } return false; } isCSPApplied() { if (this.isCSPAppliedViaMetaTag()) { return true; } return false; } createScriptElement(sourcePath) { const script = document.createElement('script'); script.async = true; script.type = sourcePath.includes('.mjs') ? 'module' : 'text/javascript'; script.className = `ngx-extended-pdf-viewer-script`; this.pdfCspPolicyService.addTrustedJavaScript(script, sourcePath); return script; } getPdfJsPath(artifact) { let suffix = pdfDefaultOptions._internalFilenameSuffix; if (this._needsES5) { suffix = ''; // we don't publish minified ES5 files } suffix += '.mjs'; const assets = pdfDefaultOptions.assetsFolder; const versionSuffix = getVersionSuffix(assets); const artifactPath = `/${artifact}-`; const es5 = this._needsES5 ? '-es5' : ''; return assets + artifactPath + versionSuffix + es5 + suffix; } async loadViewer(forceReload) { return new Promise((resolve) => { let viewerPath = this.getPdfJsPath('viewer'); if (forceReload) { viewerPath += '?v=' + new Date().getTime(); } const listener = (event) => { const { PDFViewerApplication, PDFViewerApplicationOptions, webViewerLoad } = event.detail; this.PDFViewerApplication = PDFViewerApplication; this.PDFViewerApplicationOptions = PDFViewerApplicationOptions; this.webViewerLoad = webViewerLoad; resolve(); document.removeEventListener('ngxViewerFileHasBeenLoaded', listener); }; document.addEventListener('ngxViewerFileHasBeenLoaded', listener, { once: true }); const script = this.createScriptElement(viewerPath); document.getElementsByTagName('head')[0].appendChild(script); }); } addFeatures() { return new Promise((resolve) => { const script = this.createScriptElement(pdfDefaultOptions.assetsFolder + '/additional-features.js'); script.onload = () => { script.remove(); }; script.onerror = () => { script.remove(); resolve(); }; document.body.appendChild(script); }); } async ensurePdfJsHasBeenLoaded(useInlineScripts, forceUsingLegacyES5, forceReload) { if (this.PDFViewerApplication) { return true; } this._needsES5 = forceUsingLegacyES5 || (await this.needsES5(useInlineScripts)); if (forceUsingLegacyES5) { pdfDefaultOptions.needsES5 = true; } await this.loadViewer(forceReload); return this.PDFViewerApplication !== undefined; } ngOnDestroy() { this.shuttingDown = true; if (typeof window === 'undefined') { return; // fast escape for server side rendering } delete globalThis['setNgxExtendedPdfViewerSource']; const w = window; delete w.pdfjsLib; document.querySelectorAll('.ngx-extended-pdf-viewer-script').forEach((e) => { e.onload = null; e.remove(); }); } iOSVersionRequiresES5() { if (typeof window === 'undefined') { // server-side rendering return false; } const match = navigator.appVersion.match(/OS (\d+)_(\d+)_?(\d+)?/); if (match !== undefined && match !== null) { return parseInt(match[1], 10) < 14; } return false; } async needsES5(useInlineScripts) { if (typeof window === 'undefined') { // server-side rendering return false; } if (this._needsES5 === undefined) { const isIE = !!globalThis.MSInputMethodContext && !!document.documentMode; const isEdge = /Edge\/\d./i.test(navigator.userAgent); const isIOs13OrBelow = this.iOSVersionRequiresES5(); let needsES5 = typeof ReadableStream === 'undefined' || typeof Promise['allSettled'] === 'undefined'; if (needsES5 || isIE || isEdge || isIOs13OrBelow || this.forceUsingLegacyES5) { this._needsES5 = true; return true; } this._needsES5 = !(await this.ngxExtendedPdfViewerCanRunModernJSCode(useInlineScripts)); this.polyfillPromiseWithResolversIfZoneJSOverwritesIt(); } return this._needsES5; } /** * Angular 16 uses zone.js 0.13.3, and this version has a problem with Promise.withResolvers. * If your browser supports Promise.withResolvers, zone.js accidentally overwrites it with "undefined". * This method adds a polyfill for Promise.withResolvers if it is not available. */ polyfillPromiseWithResolversIfZoneJSOverwritesIt() { const TypelessPromise = Promise; if (!TypelessPromise.withResolvers) { TypelessPromise.withResolvers = function withResolvers() { let a; let b; const c = new this(function (resolve, reject) { a = resolve; b = reject; }); return { resolve: a, reject: b, promise: c }; }; } } ngxExtendedPdfViewerCanRunModernJSCode(useInlineScripts) { return new Promise((resolve) => { const support = globalThis.ngxExtendedPdfViewerCanRunModernJSCode; support !== undefined ? resolve(support) : resolve(this.addScriptOpChainingSupport(useInlineScripts)); }); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PDFScriptLoaderService, deps: [{ token: i1.PdfCspPolicyService }, { token: CSP_NONCE }], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PDFScriptLoaderService, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PDFScriptLoaderService, decorators: [{ type: Injectable, args: [{ providedIn: 'root', }] }], ctorParameters: () => [{ type: i1.PdfCspPolicyService }, { type: undefined, decorators: [{ type: Inject, args: [CSP_NONCE] }] }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGRmLXNjcmlwdC1sb2FkZXIuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1leHRlbmRlZC1wZGYtdmlld2VyL3NyYy9saWIvcGRmLXNjcmlwdC1sb2FkZXIuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQWEsTUFBTSxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN6RixPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQzs7O0FBUXBGLE1BQU0sT0FBTyxzQkFBc0I7SUEyQnZCO0lBQ21CO0lBM0JyQixvQkFBb0IsR0FBRyxLQUFLLENBQUM7SUFDckMsSUFBVyxtQkFBbUI7UUFDNUIsT0FBTyxJQUFJLENBQUMsb0JBQW9CLENBQUM7SUFDbkMsQ0FBQztJQUNELElBQVcsbUJBQW1CLENBQUMsS0FBSztRQUNsQyxPQUFPLENBQUMsR0FBRyxDQUFDLGtHQUFrRyxDQUFDLENBQUM7UUFDaEgsSUFBSSxDQUFDLG9CQUFvQixHQUFHLEtBQUssQ0FBQztJQUNwQyxDQUFDO0lBRUQsNEdBQTRHO0lBQ3JHLGlCQUFpQixHQUFHLE1BQU0sQ0FBb0MsU0FBUyxDQUFDLENBQUM7SUFFekUsWUFBWSxHQUFHLGdCQUFnQixDQUFDLGlCQUFpQixDQUFDLFlBQVksQ0FBQyxDQUFDO0lBRWhFLFlBQVksR0FBRyxLQUFLLENBQUM7SUFFcEIsU0FBUyxHQUF3QixTQUFTLENBQUM7SUFFNUMsb0JBQW9CLENBQXlCO0lBQzdDLDJCQUEyQixDQUFnQztJQUNsRSw4Q0FBOEM7SUFDdkMsYUFBYSxDQUFrRDtJQUUvRCwyQ0FBMkMsR0FBRyxJQUFJLENBQUM7SUFFMUQsWUFDVSxtQkFBd0MsRUFDckIsU0FBaUI7UUFEcEMsd0JBQW1CLEdBQW5CLG1CQUFtQixDQUFxQjtRQUNyQixj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Q0FBc0MsQ0FBQyxnQkFBeUI7UUFDdEUsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFO1lBQzdCLE1BQU0sT0FBTyxHQUFTLFVBQVcsQ0FBQyxzQ0FBc0MsQ0FBQztZQUN6RSxPQUFPLEtBQUssU0FBUyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsMEJBQTBCLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDO1FBQ3hHLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQzt3R0E1UlUsc0JBQXNCLHFEQTRCdkIsU0FBUzs0R0E1QlIsc0JBQXNCLGNBRnJCLE1BQU07OzRGQUVQLHNCQUFzQjtrQkFIbEMsVUFBVTttQkFBQztvQkFDVixVQUFVLEVBQUUsTUFBTTtpQkFDbkI7OzBCQTZCSSxNQUFNOzJCQUFDLFNBQVMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDU1BfTk9OQ0UsIEluamVjdCwgSW5qZWN0YWJsZSwgT25EZXN0cm95LCBlZmZlY3QsIHNpZ25hbCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgZ2V0VmVyc2lvblN1ZmZpeCwgcGRmRGVmYXVsdE9wdGlvbnMgfSBmcm9tICcuL29wdGlvbnMvcGRmLWRlZmF1bHQtb3B0aW9ucyc7XG5pbXBvcnQgeyBJUERGVmlld2VyQXBwbGljYXRpb24gfSBmcm9tICcuL29wdGlvbnMvcGRmLXZpZXdlci1hcHBsaWNhdGlvbic7XG5pbXBvcnQgeyBJUERGVmlld2VyQXBwbGljYXRpb25PcHRpb25zIH0gZnJvbSAnLi9vcHRpb25zL3BkZi12aWV3ZXItYXBwbGljYXRpb24tb3B0aW9ucyc7XG5pbXBvcnQgeyBQZGZDc3BQb2xpY3lTZXJ2aWNlIH0gZnJvbSAnLi9wZGYtY3NwLXBvbGljeS5zZXJ2aWNlJztcblxuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCcsXG59KVxuZXhwb3J0IGNsYXNzIFBERlNjcmlwdExvYWRlclNlcnZpY2UgaW1wbGVtZW50cyBPbkRlc3Ryb3kge1xuICBwcml2YXRlIF9mb3JjZVVzaW5nTGVnYWN5RVM1ID0gZmFsc2U7XG4gIHB1YmxpYyBnZXQgZm9yY2VVc2luZ0xlZ2FjeUVTNSgpIHtcbiAgICByZXR1cm4gdGhpcy5fZm9yY2VVc2luZ0xlZ2FjeUVTNTtcbiAgfVxuICBwdWJsaWMgc2V0IGZvcmNlVXNpbmdMZWdhY3lFUzUodmFsdWUpIHtcbiAgICBjb25zb2xlLmxvZygnUGxlYXNlIHVzZSB0aGUgYXR0cmlidXRlIGBbZm9yY2VVc2luZ0xlZ2FjeUVTNV1gIGluc3RlYWQgb2Ygc2V0dGluZyB0aGUgcHJvcGVydHkgaW4gdGhlIHNlcnZpY2UuJyk7XG4gICAgdGhpcy5fZm9yY2VVc2luZ0xlZ2FjeUVTNSA9IHZhbHVlO1xuICB9XG5cbiAgLy8gdGhpcyBldmVudCBpcyBmaXJlZCB3aGVuIHRoZSBwZGYuanMgbGlicmFyeSBoYXMgYmVlbiBsb2FkZWQgYW5kIG9iamVjdHMgbGlrZSBQREZBcHBsaWNhdGlvbiBhcmUgYXZhaWxhYmxlXG4gIHB1YmxpYyBvblBERkpTSW5pdFNpZ25hbCA9IHNpZ25hbDxJUERGVmlld2VyQXBwbGljYXRpb24gfCB1bmRlZmluZWQ+KHVuZGVmaW5lZCk7XG5cbiAgcHVibGljIHBkZmpzVmVyc2lvbiA9IGdldFZlcnNpb25TdWZmaXgocGRmRGVmYXVsdE9wdGlvbnMuYXNzZXRzRm9sZGVyKTtcblxuICBwdWJsaWMgc2h1dHRpbmdEb3duID0gZmFsc2U7XG5cbiAgcHJpdmF0ZSBfbmVlZHNFUzU6IGJvb2xlYW4gfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XG5cbiAgcHVibGljIFBERlZpZXdlckFwcGxpY2F0aW9uITogSVBERlZpZXdlckFwcGxpY2F0aW9uO1xuICBwdWJsaWMgUERGVmlld2VyQXBwbGljYXRpb25PcHRpb25zITogSVBERlZpZXdlckFwcGxpY2F0aW9uT3B0aW9ucztcbiAgLy8gcHJpdmF0ZSBQREZWaWV3ZXJBcHBsaWNhdGlvbkNvbnN0YW50czogYW55O1xuICBwdWJsaWMgd2ViVmlld2VyTG9hZDogKGNzcFBvbGljeVNlcnZpY2U6IFBkZkNzcFBvbGljeVNlcnZpY2UpID0+IHZvaWQ7XG5cbiAgcHVibGljIG5neEV4dGVuZGVkUGRmVmlld2VySW5jb21wbGV0ZWx5SW5pdGlhbGl6ZWQgPSB0cnVlO1xuXG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHBkZkNzcFBvbGljeVNlcnZpY2U6IFBkZkNzcFBvbGljeVNlcnZpY2UsXG4gICAgQEluamVjdChDU1BfTk9OQ0UpIHByaXZhdGUgY3NwX25vbmNlOiBzdHJpbmcsXG4gICkge1xuICAgIGVmZmVjdCgoKSA9PiB7XG4gICAgICBpZiAodGhpcy5vblBERkpTSW5pdFNpZ25hbCgpKSB7XG4gICAgICAgIHRoaXMucGRmanNWZXJzaW9uID0gZ2V0VmVyc2lvblN1ZmZpeChwZGZEZWZhdWx0T3B0aW9ucy5hc3NldHNGb2xkZXIpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBhZGRTY3JpcHRPcENoYWluaW5nU3VwcG9ydCh1c2VJbmxpbmVTY3JpcHRzOiBib29sZWFuKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgaWYgKCF1c2VJbmxpbmVTY3JpcHRzIHx8IHRoaXMuaXNDU1BBcHBsaWVkKCkpIHtcbiAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICAgICAgICBjb25zdCBzY3JpcHQgPSB0aGlzLmNyZWF0ZVNjcmlwdEVsZW1lbnQocGRmRGVmYXVsdE9wdGlvbnMuYXNzZXRzRm9sZGVyICsgJy9vcC1jaGFpbmluZy1zdXBwb3J0LmpzJyk7XG4gICAgICAgIHNjcmlwdC5vbmxvYWQgPSAoKSA9PiB7XG4gICAgICAgICAgc2NyaXB0LnJlbW92ZSgpO1xuICAgICAgICAgIHNjcmlwdC5vbmxvYWQgPSBudWxsO1xuICAgICAgICAgIHJlc29sdmUoKDxhbnk+Z2xvYmFsVGhpcykubmd4RXh0ZW5kZWRQZGZWaWV3ZXJDYW5SdW5Nb2Rlcm5KU0NvZGUgYXMgYm9vbGVhbik7XG4gICAgICAgIH07XG4gICAgICAgIHNjcmlwdC5vbmVycm9yID0gKCkgPT4ge1xuICAgICAgICAgIHNjcmlwdC5yZW1vdmUoKTtcbiAgICAgICAgICAoPGFueT5nbG9iYWxUaGlzKS5uZ3hFeHRlbmRlZFBkZlZpZXdlckNhblJ1bk1vZGVybkpTQ29kZSA9IGZhbHNlO1xuICAgICAgICAgIHJlc29sdmUoZmFsc2UpO1xuICAgICAgICAgIHNjcmlwdC5vbmVycm9yID0gbnVsbDtcbiAgICAgICAgfTtcblxuICAgICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHNjcmlwdCk7XG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgY29kZSA9IGBcbm5ldyAoZnVuY3Rpb24gKCkge1xuICBjbGFzcyBCcm93c2VyQ29tcGF0aWJpbGl0eVRlc3RlciB7XG4gICAgLy8gRG9lcyB5b3VyIGJyb3dzZXIgZG9lc24ndCBzdXBwb3J0IHByaXZhdGUgZmllbGRzP1xuICAgICNwcml2YXRlRmllbGQ7XG5cbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgIC8vIERvZXMgeW91ciBicm93c2VyIHN1cHBvcnQgdGhlIGxvZ2ljYWwgYXNzaWdubWVudCBvcGVyYXRvcnM/XG4gICAgICBsZXQgeCA9IGZhbHNlO1xuICAgICAgeCB8fD0gdHJ1ZTtcblxuICAgICAgdGhpcy4jcHJpdmF0ZU1ldGhvZCgpO1xuICAgIH1cblxuICAgIC8vIERvZXMgeW91ciBicm93c2VyIGRvZXNuJ3Qgc3VwcG9ydCBwcml2YXRlIG1ldGhvZHM/XG4gICAgI3ByaXZhdGVNZXRob2QoKSB7XG4gICAgICAvLyBjaGVjayB0aGUgdGhlIGJyb3dzZXIgc3VwcG9ydHMgc3RyaW5nLmF0KClcbiAgICAgIHJldHVybiAnaGVsbG8nLmF0KDQpO1xuICAgIH1cblxuICAgIHN1cHBvcnRzT3B0aW9uYWxDaGFpbmluZygpIHtcbiAgICAgIGNvbnN0IG9wdGlvbmFsQ2hhaW5pbmcgPSB7XG4gICAgICAgIHN1cHBvcnQ6IHRydWUsXG4gICAgICB9O1xuICAgICAgcmV0dXJuIG9wdGlvbmFsQ2hhaW5pbmc/LnN1cHBvcnQ7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gc3VwcG9ydHNQcm9taXNlV2l0aFJlc29sdmVycygpIHtcbiAgICBjb25zdCBpZnJhbWUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpZnJhbWUnKTtcbiAgICBkb2N1bWVudC5maXJzdEVsZW1lbnRDaGlsZC5hcHBlbmQoaWZyYW1lKTtcbiAgICBjb25zdCB1c2VMZWdhY3lQZGZWaWV3ZXIgPSAnd2l0aFJlc29sdmVycycgaW4gaWZyYW1lLmNvbnRlbnRXaW5kb3dbJ1Byb21pc2UnXTtcbiAgICBpZnJhbWUucGFyZW50RWxlbWVudC5yZW1vdmVDaGlsZChpZnJhbWUpO1xuXG4gICAgcmV0dXJuIHVzZUxlZ2FjeVBkZlZpZXdlcjtcbiAgfVxuXG4gIGNvbnN0IHN1cHBvcnRzT3B0aW9uYWxDaGFpbmluZyA9IG5ldyBCcm93c2VyQ29tcGF0aWJpbGl0eVRlc3RlcigpLnN1cHBvcnRzT3B0aW9uYWxDaGFpbmluZygpO1xuICBjb25zdCBzdXBwb3J0TW9kZXJuUHJvbWlzZXMgPSBzdXBwb3J0c1Byb21pc2VXaXRoUmVzb2x2ZXJzKCk7XG4gIHdpbmRvdy5uZ3hFeHRlbmRlZFBkZlZpZXdlckNhblJ1bk1vZGVybkpTQ29kZSA9IHN1cHBvcnRzT3B0aW9uYWxDaGFpbmluZyAmJiBzdXBwb3J0TW9kZXJuUHJvbWlzZXM7XG59KSgpO1xuYDtcbiAgICAgIGNvbnN0IHNjcmlwdCA9IHRoaXMuY3JlYXRlSW5saW5lU2NyaXB0KGNvZGUpO1xuICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoJ2hlYWQnKVswXS5hcHBlbmRDaGlsZChzY3JpcHQpO1xuICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgICAgIGNvbnN0IGludGVydmFsID0gc2V0SW50ZXJ2YWwoKCkgPT4ge1xuICAgICAgICAgIGlmICgoZ2xvYmFsVGhpcyBhcyBhbnkpLm5neEV4dGVuZGVkUGRmVmlld2VyQ2FuUnVuTW9kZXJuSlNDb2RlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGNsZWFySW50ZXJ2YWwoaW50ZXJ2YWwpO1xuICAgICAgICAgICAgcmVzb2x2ZSgoZ2xvYmFsVGhpcyBhcyBhbnkpLm5neEV4dGVuZGVkUGRmVmlld2VyQ2FuUnVuTW9kZXJuSlNDb2RlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0sIDEpO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVJbmxpbmVTY3JpcHQoY29kZTogc3RyaW5nKTogSFRNTFNjcmlwdEVsZW1lbnQge1xuICAgIGNvbnN0IHNjcmlwdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NjcmlwdCcpO1xuICAgIHNjcmlwdC5hc3luYyA9IHRydWU7XG4gICAgc2NyaXB0LnR5cGUgPSAnbW9kdWxlJztcbiAgICBzY3JpcHQuY2xhc3NOYW1lID0gYG5neC1leHRlbmRlZC1wZGYtdmlld2VyLXNjcmlwdGA7XG4gICAgc2NyaXB0LnRleHQgPSBjb2RlO1xuICAgIGlmICh0aGlzLmNzcF9ub25jZSkge1xuICAgICAgLy8gYXNzaWduaW5nIG51bGwgdG8gc2NyaXB0Lm5vbmNlIHJlc3VsdHMgaW4gYSBzdHJpbmcgXCJudWxsXCIsIHNvIGxldCdzIGFkZCBhIG51bGwgY2hlY2tcbiAgICAgIHNjcmlwdC5ub25jZSA9IHRoaXMuY3NwX25vbmNlO1xuICAgIH1cbiAgICByZXR1cm4gc2NyaXB0O1xuICB9XG5cbiAgcHJpdmF0ZSBpc0NTUEFwcGxpZWRWaWFNZXRhVGFnKCk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IG1ldGFUYWdzID0gZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoJ21ldGEnKTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG1ldGFUYWdzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAobWV0YVRhZ3NbaV0uZ2V0QXR0cmlidXRlKCdodHRwLWVxdWl2JykgPT09ICdDb250ZW50LVNlY3VyaXR5LVBvbGljeScpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHByaXZhdGUgaXNDU1BBcHBsaWVkKCkge1xuICAgIGlmICh0aGlzLmlzQ1NQQXBwbGllZFZpYU1ldGFUYWcoKSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlU2NyaXB0RWxlbWVudChzb3VyY2VQYXRoOiBzdHJpbmcpOiBIVE1MU2NyaXB0RWxlbWVudCB7XG4gICAgY29uc3Qgc2NyaXB0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc2NyaXB0Jyk7XG4gICAgc2NyaXB0LmFzeW5jID0gdHJ1ZTtcbiAgICBzY3JpcHQudHlwZSA9IHNvdXJjZVBhdGguaW5jbHVkZXMoJy5tanMnKSA/ICdtb2R1bGUnIDogJ3RleHQvamF2YXNjcmlwdCc7XG4gICAgc2NyaXB0LmNsYXNzTmFtZSA9IGBuZ3gtZXh0ZW5kZWQtcGRmLXZpZXdlci1zY3JpcHRgO1xuICAgIHRoaXMucGRmQ3NwUG9saWN5U2VydmljZS5hZGRUcnVzdGVkSmF2YVNjcmlwdChzY3JpcHQsIHNvdXJjZVBhdGgpO1xuICAgIHJldHVybiBzY3JpcHQ7XG4gIH1cblxuICBwcml2YXRlIGdldFBkZkpzUGF0aChhcnRpZmFjdDogJ3BkZicgfCAndmlld2VyJykge1xuICAgIGxldCBzdWZmaXggPSBwZGZEZWZhdWx0T3B0aW9ucy5faW50ZXJuYWxGaWxlbmFtZVN1ZmZpeDtcbiAgICBpZiAodGhpcy5fbmVlZHNFUzUpIHtcbiAgICAgIHN1ZmZpeCA9ICcnOyAvLyB3ZSBkb24ndCBwdWJsaXNoIG1pbmlmaWVkIEVTNSBmaWxlc1xuICAgIH1cbiAgICBzdWZmaXggKz0gJy5tanMnO1xuICAgIGNvbnN0IGFzc2V0cyA9IHBkZkRlZmF1bHRPcHRpb25zLmFzc2V0c0ZvbGRlcjtcbiAgICBjb25zdCB2ZXJzaW9uU3VmZml4ID0gZ2V0VmVyc2lvblN1ZmZpeChhc3NldHMpO1xuICAgIGNvbnN0IGFydGlmYWN0UGF0aCA9IGAvJHthcnRpZmFjdH0tYDtcbiAgICBjb25zdCBlczUgPSB0aGlzLl9uZWVkc0VTNSA/ICctZXM1JyA6ICcnO1xuXG4gICAgcmV0dXJuIGFzc2V0cyArIGFydGlmYWN0UGF0aCArIHZlcnNpb25TdWZmaXggKyBlczUgKyBzdWZmaXg7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGxvYWRWaWV3ZXIoZm9yY2VSZWxvYWQ6IGJvb2xlYW4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICAgIGxldCB2aWV3ZXJQYXRoID0gdGhpcy5nZXRQZGZKc1BhdGgoJ3ZpZXdlcicpO1xuICAgICAgaWYgKGZvcmNlUmVsb2FkKSB7XG4gICAgICAgIHZpZXdlclBhdGggKz0gJz92PScgKyBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGxpc3RlbmVyID0gKGV2ZW50OiBDdXN0b21FdmVudCkgPT4ge1xuICAgICAgICBjb25zdCB7IFBERlZpZXdlckFwcGxpY2F0aW9uLCBQREZWaWV3ZXJBcHBsaWNhdGlvbk9wdGlvbnMsIHdlYlZpZXdlckxvYWQgfSA9IGV2ZW50LmRldGFpbDtcbiAgICAgICAgdGhpcy5QREZWaWV3ZXJBcHBsaWNhdGlvbiA9IFBERlZpZXdlckFwcGxpY2F0aW9uO1xuICAgICAgICB0aGlzLlBERlZpZXdlckFwcGxpY2F0aW9uT3B0aW9ucyA9IFBERlZpZXdlckFwcGxpY2F0aW9uT3B0aW9ucztcbiAgICAgICAgdGhpcy53ZWJWaWV3ZXJMb2FkID0gd2ViVmlld2VyTG9hZDtcbiAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCduZ3hWaWV3ZXJGaWxlSGFzQmVlbkxvYWRlZCcsIGxpc3RlbmVyKTtcbiAgICAgIH07XG4gICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCduZ3hWaWV3ZXJGaWxlSGFzQmVlbkxvYWRlZCcsIGxpc3RlbmVyLCB7IG9uY2U6IHRydWUgfSk7XG4gICAgICBjb25zdCBzY3JpcHQgPSB0aGlzLmNyZWF0ZVNjcmlwdEVsZW1lbnQodmlld2VyUGF0aCk7XG4gICAgICBkb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgnaGVhZCcpWzBdLmFwcGVuZENoaWxkKHNjcmlwdCk7XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIGFkZEZlYXR1cmVzKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICAgICAgY29uc3Qgc2NyaXB0ID0gdGhpcy5jcmVhdGVTY3JpcHRFbGVtZW50KHBkZkRlZmF1bHRPcHRpb25zLmFzc2V0c0ZvbGRlciArICcvYWRkaXRpb25hbC1mZWF0dXJlcy5qcycpO1xuICAgICAgc2NyaXB0Lm9ubG9hZCA9ICgpID0+IHtcbiAgICAgICAgc2NyaXB0LnJlbW92ZSgpO1xuICAgICAgfTtcbiAgICAgIHNjcmlwdC5vbmVycm9yID0gKCkgPT4ge1xuICAgICAgICBzY3JpcHQucmVtb3ZlKCk7XG4gICAgICAgIHJlc29sdmUoKTtcbiAgICAgIH07XG5cbiAgICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoc2NyaXB0KTtcbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBlbnN1cmVQZGZKc0hhc0JlZW5Mb2FkZWQodXNlSW5saW5lU2NyaXB0czogYm9vbGVhbiwgZm9yY2VVc2luZ0xlZ2FjeUVTNTogYm9vbGVhbiwgZm9yY2VSZWxvYWQ6IGJvb2xlYW4pOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBpZiAodGhpcy5QREZWaWV3ZXJBcHBsaWNhdGlvbikge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHRoaXMuX25lZWRzRVM1ID0gZm9yY2VVc2luZ0xlZ2FjeUVTNSB8fCAoYXdhaXQgdGhpcy5uZWVkc0VTNSh1c2VJbmxpbmVTY3JpcHRzKSk7XG4gICAgaWYgKGZvcmNlVXNpbmdMZWdhY3lFUzUpIHtcbiAgICAgIHBkZkRlZmF1bHRPcHRpb25zLm5lZWRzRVM1ID0gdHJ1ZTtcbiAgICB9XG4gICAgYXdhaXQgdGhpcy5sb2FkVmlld2VyKGZvcmNlUmVsb2FkKTtcbiAgICByZXR1cm4gdGhpcy5QREZWaWV3ZXJBcHBsaWNhdGlvbiAhPT0gdW5kZWZpbmVkO1xuICB9XG5cbiAgcHVibGljIG5nT25EZXN0cm95KCkge1xuICAgIHRoaXMuc2h1dHRpbmdEb3duID0gdHJ1ZTtcbiAgICBpZiAodHlwZW9mIHdpbmRvdyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHJldHVybjsgLy8gZmFzdCBlc2NhcGUgZm9yIHNlcnZlciBzaWRlIHJlbmRlcmluZ1xuICAgIH1cbiAgICBkZWxldGUgZ2xvYmFsVGhpc1snc2V0Tmd4RXh0ZW5kZWRQZGZWaWV3ZXJTb3VyY2UnXTtcblxuICAgIGNvbnN0IHcgPSB3aW5kb3cgYXMgYW55O1xuICAgIGRlbGV0ZSB3LnBkZmpzTGliO1xuICAgIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJy5uZ3gtZXh0ZW5kZWQtcGRmLXZpZXdlci1zY3JpcHQnKS5mb3JFYWNoKChlOiBIVE1MU2NyaXB0RWxlbWVudCkgPT4ge1xuICAgICAgZS5vbmxvYWQgPSBudWxsO1xuICAgICAgZS5yZW1vdmUoKTtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgaU9TVmVyc2lvblJlcXVpcmVzRVM1KCk6IGJvb2xlYW4ge1xuICAgIGlmICh0eXBlb2Ygd2luZG93ID09PSAndW5kZWZpbmVkJykge1xuICAgICAgLy8gc2VydmVyLXNpZGUgcmVuZGVyaW5nXG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGNvbnN0IG1hdGNoID0gbmF2aWdhdG9yLmFwcFZlcnNpb24ubWF0Y2goL09TIChcXGQrKV8oXFxkKylfPyhcXGQrKT8vKTtcbiAgICBpZiAobWF0Y2ggIT09IHVuZGVmaW5lZCAmJiBtYXRjaCAhPT0gbnVsbCkge1xuICAgICAgcmV0dXJuIHBhcnNlSW50KG1hdGNoWzFdLCAxMCkgPCAxNDtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIG5lZWRzRVM1KHVzZUlubGluZVNjcmlwdHM6IGJvb2xlYW4pOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBpZiAodHlwZW9mIHdpbmRvdyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIC8vIHNlcnZlci1zaWRlIHJlbmRlcmluZ1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBpZiAodGhpcy5fbmVlZHNFUzUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgY29uc3QgaXNJRSA9ICEhKDxhbnk+Z2xvYmFsVGhpcykuTVNJbnB1dE1ldGhvZENvbnRleHQgJiYgISEoPGFueT5kb2N1bWVudCkuZG9jdW1lbnRNb2RlO1xuICAgICAgY29uc3QgaXNFZGdlID0gL0VkZ2VcXC9cXGQuL2kudGVzdChuYXZpZ2F0b3IudXNlckFnZW50KTtcbiAgICAgIGNvbnN0IGlzSU9zMTNPckJlbG93ID0gdGhpcy5pT1NWZXJzaW9uUmVxdWlyZXNFUzUoKTtcbiAgICAgIGxldCBuZWVkc0VTNSA9IHR5cGVvZiBSZWFkYWJsZVN0cmVhbSA9PT0gJ3VuZGVmaW5lZCcgfHwgdHlwZW9mIFByb21pc2VbJ2FsbFNldHRsZWQnXSA9PT0gJ3VuZGVmaW5lZCc7XG4gICAgICBpZiAobmVlZHNFUzUgfHwgaXNJRSB8fCBpc0VkZ2UgfHwgaXNJT3MxM09yQmVsb3cgfHwgdGhpcy5mb3JjZVVzaW5nTGVnYWN5RVM1KSB7XG4gICAgICAgIHRoaXMuX25lZWRzRVM1ID0gdHJ1ZTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgICB0aGlzLl9uZWVkc0VTNSA9ICEoYXdhaXQgdGhpcy5uZ3hFeHRlbmRlZFBkZlZpZXdlckNhblJ1bk1vZGVybkpTQ29kZSh1c2VJbmxpbmVTY3JpcHRzKSk7XG4gICAgICB0aGlzLnBvbHlmaWxsUHJvbWlzZVdpdGhSZXNvbHZlcnNJZlpvbmVKU092ZXJ3cml0ZXNJdCgpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fbmVlZHNFUzU7XG4gIH1cblxuICAvKipcbiAgICogQW5ndWxhciAxNiB1c2VzIHpvbmUuanMgMC4xMy4zLCBhbmQgdGhpcyB2ZXJzaW9uIGhhcyBhIHByb2JsZW0gd2l0aCBQcm9taXNlLndpdGhSZXNvbHZlcnMuXG4gICAqIElmIHlvdXIgYnJvd3NlciBzdXBwb3J0cyBQcm9taXNlLndpdGhSZXNvbHZlcnMsIHpvbmUuanMgYWNjaWRlbnRhbGx5IG92ZXJ3cml0ZXMgaXQgd2l0aCBcInVuZGVmaW5lZFwiLlxuICAgKiBUaGlzIG1ldGhvZCBhZGRzIGEgcG9seWZpbGwgZm9yIFByb21pc2Uud2l0aFJlc29sdmVycyBpZiBpdCBpcyBub3QgYXZhaWxhYmxlLlxuICAgKi9cbiAgcHJpdmF0ZSBwb2x5ZmlsbFByb21pc2VXaXRoUmVzb2x2ZXJzSWZab25lSlNPdmVyd3JpdGVzSXQoKSB7XG4gICAgY29uc3QgVHlwZWxlc3NQcm9taXNlID0gUHJvbWlzZSBhcyBhbnk7XG4gICAgaWYgKCFUeXBlbGVzc1Byb21pc2Uud2l0aFJlc29sdmVycykge1xuICAgICAgVHlwZWxlc3NQcm9taXNlLndpdGhSZXNvbHZlcnMgPSBmdW5jdGlvbiB3aXRoUmVzb2x2ZXJzKCkge1xuICAgICAgICBsZXQgYTogdW5rbm93bjtcbiAgICAgICAgbGV0IGI6IHVua25vd247XG4gICAgICAgIGNvbnN0IGMgPSBuZXcgdGhpcyhmdW5jdGlvbiAocmVzb2x2ZTogdW5rbm93biwgcmVqZWN0OiB1bmtub3duKSB7XG4gICAgICAgICAgYSA9IHJlc29sdmU7XG4gICAgICAgICAgYiA9IHJlamVjdDtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB7IHJlc29sdmU6IGEsIHJlamVjdDogYiwgcHJvbWlzZTogYyB9O1xuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIG5neEV4dGVuZGVkUGRmVmlld2VyQ2FuUnVuTW9kZXJuSlNDb2RlKHVzZUlubGluZVNjcmlwdHM6IGJvb2xlYW4pOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICAgIGNvbnN0IHN1cHBvcnQgPSAoPGFueT5nbG9iYWxUaGlzKS5uZ3hFeHRlbmRlZFBkZlZpZXdlckNhblJ1bk1vZGVybkpTQ29kZTtcbiAgICAgIHN1cHBvcnQgIT09IHVuZGVmaW5lZCA/IHJlc29sdmUoc3VwcG9ydCkgOiByZXNvbHZlKHRoaXMuYWRkU2NyaXB0T3BDaGFpbmluZ1N1cHBvcnQodXNlSW5saW5lU2NyaXB0cykpO1xuICAgIH0pO1xuICB9XG59XG4iXX0=