ngx-markdown
Version:
Angular library that uses marked to parse markdown to html combined with Prism.js for synthax highlights
468 lines (456 loc) • 36.8 kB
JavaScript
import { Pipe, Inject, Injectable, Optional, PLATFORM_ID, SecurityContext, Component, ElementRef, EventEmitter, Input, Output, NgZone, NgModule } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
import { HttpClient } from '@angular/common/http';
import { DomSanitizer } from '@angular/platform-browser';
import { parse, Renderer } from 'marked';
import { map, first } from 'rxjs/operators';
import { __spread, __extends } from 'tslib';
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
var LanguagePipe = /** @class */ (function () {
function LanguagePipe() {
}
/**
* @param {?} value
* @param {?} language
* @return {?}
*/
LanguagePipe.prototype.transform = /**
* @param {?} value
* @param {?} language
* @return {?}
*/
function (value, language) {
if (typeof value !== 'string') {
console.error("LanguagePipe has been invoked with an invalid value type [" + value + "]");
return value;
}
if (typeof language !== 'string') {
console.error("LanguagePipe has been invoked with an invalid parameter [" + language + "]");
return value;
}
return '```' + language + '\n' + value + '\n```';
};
LanguagePipe.decorators = [
{ type: Pipe, args: [{
name: 'language',
},] },
];
return LanguagePipe;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
var MarkedOptions = /** @class */ (function () {
function MarkedOptions() {
}
return MarkedOptions;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
/** @type {?} */
var errorSrcWithoutHttpClient = '[ngx-markdown] When using the [src] attribute you *have to* pass the `HttpClient` as a parameter of the `forRoot` method. See README for more information';
var MarkdownService = /** @class */ (function () {
function MarkdownService(platform, http, domSanitizer, options) {
this.platform = platform;
this.http = http;
this.domSanitizer = domSanitizer;
this.options = options;
if (!this.renderer) {
this.renderer = new Renderer();
}
}
Object.defineProperty(MarkdownService.prototype, "renderer", {
get: /**
* @return {?}
*/
function () { return this.options.renderer; },
set: /**
* @param {?} value
* @return {?}
*/
function (value) {
this.options.renderer = value;
},
enumerable: true,
configurable: true
});
/**
* @param {?} markdown
* @param {?=} decodeHtml
* @param {?=} markedOptions
* @return {?}
*/
MarkdownService.prototype.compile = /**
* @param {?} markdown
* @param {?=} decodeHtml
* @param {?=} markedOptions
* @return {?}
*/
function (markdown, decodeHtml, markedOptions) {
if (decodeHtml === void 0) { decodeHtml = false; }
if (markedOptions === void 0) { markedOptions = this.options; }
/** @type {?} */
var precompiled = this.precompile(markdown);
/** @type {?} */
var compiled = parse(decodeHtml ? this.decodeHtml(precompiled) : precompiled, markedOptions);
return markedOptions.sanitize && !markedOptions.sanitizer
? this.domSanitizer.sanitize(SecurityContext.HTML, compiled)
: compiled;
};
/**
* @param {?} src
* @return {?}
*/
MarkdownService.prototype.getSource = /**
* @param {?} src
* @return {?}
*/
function (src) {
var _this = this;
if (!this.http) {
throw new Error(errorSrcWithoutHttpClient);
}
return this.http
.get(src, { responseType: 'text' })
.pipe(map(function (markdown) { return _this.handleExtension(src, markdown); }));
};
/**
* @return {?}
*/
MarkdownService.prototype.highlight = /**
* @return {?}
*/
function () {
if (isPlatformBrowser(this.platform) && typeof Prism !== 'undefined') {
Prism.highlightAll(false);
}
};
/**
* @param {?} html
* @return {?}
*/
MarkdownService.prototype.decodeHtml = /**
* @param {?} html
* @return {?}
*/
function (html) {
if (isPlatformBrowser(this.platform)) {
/** @type {?} */
var textarea = document.createElement('textarea');
textarea.innerHTML = html;
return textarea.value;
}
return html;
};
/**
* @param {?} src
* @param {?} markdown
* @return {?}
*/
MarkdownService.prototype.handleExtension = /**
* @param {?} src
* @param {?} markdown
* @return {?}
*/
function (src, markdown) {
/** @type {?} */
var extension = src
? src.split('.').splice(-1).join()
: null;
return extension !== 'md'
? '```' + extension + '\n' + markdown + '\n```'
: markdown;
};
/**
* @param {?} markdown
* @return {?}
*/
MarkdownService.prototype.precompile = /**
* @param {?} markdown
* @return {?}
*/
function (markdown) {
if (!markdown) {
return '';
}
/** @type {?} */
var indentStart;
return markdown
.split('\n')
.map(function (line) {
/** @type {?} */
var lineIdentStart = indentStart;
// find position of 1st non-whitespace character
// to determine the current line indentation start
if (line.length > 0) {
lineIdentStart = isNaN(lineIdentStart)
? line.search(/\S|$/)
: Math.min(line.search(/\S|$/), lineIdentStart);
}
// keep 1st non-whitespace line indentation
// as base reference for other lines
if (isNaN(indentStart)) {
indentStart = lineIdentStart;
}
// remove whitespaces before current line indentation
return !!lineIdentStart
? line.substring(lineIdentStart)
: line;
}).join('\n');
};
MarkdownService.decorators = [
{ type: Injectable },
];
/** @nocollapse */
MarkdownService.ctorParameters = function () { return [
{ type: Object, decorators: [{ type: Inject, args: [PLATFORM_ID,] }] },
{ type: HttpClient, decorators: [{ type: Optional }] },
{ type: DomSanitizer },
{ type: MarkedOptions }
]; };
return MarkdownService;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
var MarkdownComponent = /** @class */ (function () {
function MarkdownComponent(element, markdownService) {
this.element = element;
this.markdownService = markdownService;
this.error = new EventEmitter();
this.load = new EventEmitter();
}
Object.defineProperty(MarkdownComponent.prototype, "_isTranscluded", {
get: /**
* @return {?}
*/
function () {
return !this._data && !this._src;
},
enumerable: true,
configurable: true
});
Object.defineProperty(MarkdownComponent.prototype, "data", {
get: /**
* @return {?}
*/
function () { return this._data; },
set: /**
* @param {?} value
* @return {?}
*/
function (value) {
this._data = value;
this.render(value);
},
enumerable: true,
configurable: true
});
Object.defineProperty(MarkdownComponent.prototype, "src", {
get: /**
* @return {?}
*/
function () { return this._src; },
set: /**
* @param {?} value
* @return {?}
*/
function (value) {
var _this = this;
this._src = value;
this.markdownService
.getSource(value)
.subscribe(function (markdown) {
_this.render(markdown);
_this.load.emit(markdown);
}, function (error) { return _this.error.emit(error); });
},
enumerable: true,
configurable: true
});
/**
* @return {?}
*/
MarkdownComponent.prototype.ngAfterViewInit = /**
* @return {?}
*/
function () {
if (this._isTranscluded) {
this.render(this.element.nativeElement.innerHTML, true);
}
};
/**
* @param {?} markdown
* @param {?=} decodeHtml
* @return {?}
*/
MarkdownComponent.prototype.render = /**
* @param {?} markdown
* @param {?=} decodeHtml
* @return {?}
*/
function (markdown, decodeHtml) {
if (decodeHtml === void 0) { decodeHtml = false; }
this.element.nativeElement.innerHTML = this.markdownService.compile(markdown, decodeHtml);
this.markdownService.highlight();
};
MarkdownComponent.decorators = [
{ type: Component, args: [{
// tslint:disable-next-line:component-selector
selector: 'markdown, [markdown]',
template: '<ng-content></ng-content>',
},] },
];
/** @nocollapse */
MarkdownComponent.ctorParameters = function () { return [
{ type: ElementRef },
{ type: MarkdownService }
]; };
MarkdownComponent.propDecorators = {
data: [{ type: Input }],
src: [{ type: Input }],
error: [{ type: Output }],
load: [{ type: Output }]
};
return MarkdownComponent;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
var MarkdownPipe = /** @class */ (function () {
function MarkdownPipe(markdownService, zone) {
this.markdownService = markdownService;
this.zone = zone;
}
/**
* @param {?} value
* @return {?}
*/
MarkdownPipe.prototype.transform = /**
* @param {?} value
* @return {?}
*/
function (value) {
var _this = this;
if (typeof value !== 'string') {
console.error("MarkdownPipe has been invoked with an invalid value type [" + value + "]");
return value;
}
/** @type {?} */
var markdown = this.markdownService.compile(value);
this.zone.onStable
.pipe(first())
.subscribe(function () { return _this.markdownService.highlight(); });
return markdown;
};
MarkdownPipe.decorators = [
{ type: Pipe, args: [{
name: 'markdown',
},] },
];
/** @nocollapse */
MarkdownPipe.ctorParameters = function () { return [
{ type: MarkdownService },
{ type: NgZone }
]; };
return MarkdownPipe;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
/** @type {?} */
var initialMarkedOptions = {
provide: MarkedOptions,
useValue: {
gfm: true,
tables: true,
breaks: false,
pedantic: false,
sanitize: false,
smartLists: true,
smartypants: false,
},
};
/** @type {?} */
var sharedDeclarations = [
LanguagePipe,
MarkdownComponent,
MarkdownPipe,
];
var MarkdownModule = /** @class */ (function () {
function MarkdownModule() {
}
/**
* @param {?=} markdownModuleConfig
* @return {?}
*/
MarkdownModule.forRoot = /**
* @param {?=} markdownModuleConfig
* @return {?}
*/
function (markdownModuleConfig) {
return {
ngModule: MarkdownModule,
providers: __spread([
MarkdownService
], (markdownModuleConfig
? [
markdownModuleConfig.loader || [],
markdownModuleConfig.markedOptions || initialMarkedOptions,
]
: [initialMarkedOptions])),
};
};
/**
* @return {?}
*/
MarkdownModule.forChild = /**
* @return {?}
*/
function () {
return {
ngModule: MarkdownModule,
};
};
MarkdownModule.decorators = [
{ type: NgModule, args: [{
exports: __spread(sharedDeclarations),
declarations: __spread(sharedDeclarations),
},] },
];
return MarkdownModule;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
var MarkedRenderer = /** @class */ (function (_super) {
__extends(MarkedRenderer, _super);
function MarkedRenderer() {
return _super !== null && _super.apply(this, arguments) || this;
}
return MarkedRenderer;
}(Renderer));
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
export { LanguagePipe, MarkdownComponent, initialMarkedOptions, MarkdownModule, MarkdownPipe, errorSrcWithoutHttpClient, MarkdownService, MarkedOptions, MarkedRenderer };
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LW1hcmtkb3duLmpzLm1hcCIsInNvdXJjZXMiOlsibmc6Ly9uZ3gtbWFya2Rvd24vc3JjL2xhbmd1YWdlLnBpcGUudHMiLCJuZzovL25neC1tYXJrZG93bi9zcmMvbWFya2VkLW9wdGlvbnMudHMiLCJuZzovL25neC1tYXJrZG93bi9zcmMvbWFya2Rvd24uc2VydmljZS50cyIsIm5nOi8vbmd4LW1hcmtkb3duL3NyYy9tYXJrZG93bi5jb21wb25lbnQudHMiLCJuZzovL25neC1tYXJrZG93bi9zcmMvbWFya2Rvd24ucGlwZS50cyIsIm5nOi8vbmd4LW1hcmtkb3duL3NyYy9tYXJrZG93bi5tb2R1bGUudHMiLCJuZzovL25neC1tYXJrZG93bi9zcmMvbWFya2VkLXJlbmRlcmVyLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFBpcGUsIFBpcGVUcmFuc2Zvcm0gfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuXHJcbkBQaXBlKHtcclxuICBuYW1lOiAnbGFuZ3VhZ2UnLFxyXG59KVxyXG5leHBvcnQgY2xhc3MgTGFuZ3VhZ2VQaXBlIGltcGxlbWVudHMgUGlwZVRyYW5zZm9ybSB7XHJcblxyXG4gIHRyYW5zZm9ybSh2YWx1ZTogc3RyaW5nLCBsYW5ndWFnZTogc3RyaW5nKTogc3RyaW5nIHtcclxuICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICdzdHJpbmcnKSB7XHJcbiAgICAgIGNvbnNvbGUuZXJyb3IoYExhbmd1YWdlUGlwZSBoYXMgYmVlbiBpbnZva2VkIHdpdGggYW4gaW52YWxpZCB2YWx1ZSB0eXBlIFske3ZhbHVlfV1gKTtcclxuICAgICAgcmV0dXJuIHZhbHVlO1xyXG4gICAgfVxyXG4gICAgaWYgKHR5cGVvZiBsYW5ndWFnZSAhPT0gJ3N0cmluZycpIHtcclxuICAgICAgY29uc29sZS5lcnJvcihgTGFuZ3VhZ2VQaXBlIGhhcyBiZWVuIGludm9rZWQgd2l0aCBhbiBpbnZhbGlkIHBhcmFtZXRlciBbJHtsYW5ndWFnZX1dYCk7XHJcbiAgICAgIHJldHVybiB2YWx1ZTtcclxuICAgIH1cclxuICAgIHJldHVybiAnYGBgJyArIGxhbmd1YWdlICsgJ1xcbicgKyAgdmFsdWUgKyAnXFxuYGBgJztcclxuICB9XHJcbn1cclxuIiwiaW1wb3J0IHsgUmVuZGVyZXIgfSBmcm9tICdtYXJrZWQnO1xyXG5cclxuZXhwb3J0IGNsYXNzIE1hcmtlZE9wdGlvbnMgaW1wbGVtZW50cyBtYXJrZWQuTWFya2VkT3B0aW9ucyB7XHJcbiAgLyoqXHJcbiAgICogQSBwcmVmaXggVVJMIGZvciBhbnkgcmVsYXRpdmUgbGluay5cclxuICAgKi9cclxuICBiYXNlVXJsPzogc3RyaW5nO1xyXG5cclxuICAvKipcclxuICAgKiBFbmFibGUgR0ZNIGxpbmUgYnJlYWtzLiBUaGlzIG9wdGlvbiByZXF1aXJlcyB0aGUgZ2ZtIG9wdGlvbiB0byBiZSB0cnVlLlxyXG4gICAqL1xyXG4gIGJyZWFrcz86IGJvb2xlYW47XHJcblxyXG4gIC8qKlxyXG4gICAqIEVuYWJsZSBHaXRIdWIgZmxhdm9yZWQgbWFya2Rvd24uXHJcbiAgICovXHJcbiAgZ2ZtPzogYm9vbGVhbjtcclxuXHJcbiAgLyoqXHJcbiAgICogSW5jbHVkZSBhbiBpZCBhdHRyaWJ1dGUgd2hlbiBlbWl0dGluZyBoZWFkaW5ncy5cclxuICAgKi9cclxuICBoZWFkZXJJZHM/OiBib29sZWFuO1xyXG5cclxuICAvKipcclxuICAgKiBTZXQgdGhlIHByZWZpeCBmb3IgaGVhZGVyIHRhZyBpZHMuXHJcbiAgICovXHJcbiAgaGVhZGVyUHJlZml4Pzogc3RyaW5nO1xyXG5cclxuICAvKipcclxuICAgKiBTZXQgdGhlIHByZWZpeCBmb3IgY29kZSBibG9jayBjbGFzc2VzLlxyXG4gICAqL1xyXG4gIGxhbmdQcmVmaXg/OiBzdHJpbmc7XHJcblxyXG4gIC8qKlxyXG4gICAqIE1hbmdsZSBhdXRvbGlua3MgKDxlbWFpbEBkb21haW4uY29tPikuXHJcbiAgICovXHJcbiAgbWFuZ2xlPzogYm9vbGVhbjtcclxuXHJcbiAgLyoqXHJcbiAgICogQ29uZm9ybSB0byBvYnNjdXJlIHBhcnRzIG9mIG1hcmtkb3duLnBsIGFzIG11Y2ggYXMgcG9zc2libGUuIERvbid0IGZpeCBhbnkgb2YgdGhlIG9yaWdpbmFsIG1hcmtkb3duIGJ1Z3Mgb3IgcG9vciBiZWhhdmlvci5cclxuICAgKi9cclxuICBwZWRhbnRpYz86IGJvb2xlYW47XHJcblxyXG4gIC8qKlxyXG4gICAqIFR5cGU6IG9iamVjdCBEZWZhdWx0OiBuZXcgUmVuZGVyZXIoKVxyXG4gICAqXHJcbiAgICogQW4gb2JqZWN0IGNvbnRhaW5pbmcgZnVuY3Rpb25zIHRvIHJlbmRlciB0b2tlbnMgdG8gSFRNTC5cclxuICAgKi9cclxuICByZW5kZXJlcj86IFJlbmRlcmVyO1xyXG5cclxuICAvKipcclxuICAgKiBTYW5pdGl6ZSB0aGUgb3V0cHV0LiBJZ25vcmUgYW55IEhUTUwgdGhhdCBoYXMgYmVlbiBpbnB1dC5cclxuICAgKi9cclxuICBzYW5pdGl6ZT86IGJvb2xlYW47XHJcblxyXG4gIC8qKlxyXG4gICAqIFNob3dzIGFuIEhUTUwgZXJyb3IgbWVzc2FnZSB3aGVuIHJlbmRlcmluZyBmYWlscy5cclxuICAgKi9cclxuICBzaWxlbnQ/OiBib29sZWFuO1xyXG5cclxuICAvKipcclxuICAgKiBVc2Ugc21hcnRlciBsaXN0IGJlaGF2aW9yIHRoYW4gdGhlIG9yaWdpbmFsIG1hcmtkb3duLiBNYXkgZXZlbnR1YWxseSBiZSBkZWZhdWx0IHdpdGggdGhlIG9sZCBiZWhhdmlvciBtb3ZlZCBpbnRvIHBlZGFudGljLlxyXG4gICAqL1xyXG4gIHNtYXJ0TGlzdHM/OiBib29sZWFuO1xyXG5cclxuICAvKipcclxuICAgKiBVc2UgXCJzbWFydFwiIHR5cG9ncmFoaWMgcHVuY3R1YXRpb24gZm9yIHRoaW5ncyBsaWtlIHF1b3RlcyBhbmQgZGFzaGVzLlxyXG4gICAqL1xyXG4gIHNtYXJ0eXBhbnRzPzogYm9vbGVhbjtcclxuXHJcbiAgLyoqXHJcbiAgICogRW5hYmxlIEdGTSB0YWJsZXMuIFRoaXMgb3B0aW9uIHJlcXVpcmVzIHRoZSBnZm0gb3B0aW9uIHRvIGJlIHRydWUuXHJcbiAgICovXHJcbiAgdGFibGVzPzogYm9vbGVhbjtcclxuXHJcbiAgLyoqXHJcbiAgICogR2VuZXJhdGUgY2xvc2luZyBzbGFzaCBmb3Igc2VsZi1jbG9zaW5nIHRhZ3MgKDxici8+IGluc3RlYWQgb2YgPGJyPilcclxuICAgKi9cclxuICB4aHRtbD86IGJvb2xlYW47XHJcblxyXG4gIC8qKlxyXG4gICAqIEEgZnVuY3Rpb24gdG8gaGlnaGxpZ2h0IGNvZGUgYmxvY2tzLiBUaGUgZnVuY3Rpb24gdGFrZXMgdGhyZWUgYXJndW1lbnRzOiBjb2RlLCBsYW5nLCBhbmQgY2FsbGJhY2suXHJcbiAgICovXHJcbiAgaGlnaGxpZ2h0Pyhjb2RlOiBzdHJpbmcsIGxhbmc6IHN0cmluZywgY2FsbGJhY2s/OiAoZXJyb3I6IGFueSB8IHVuZGVmaW5lZCwgY29kZTogc3RyaW5nKSA9PiB2b2lkKTogc3RyaW5nO1xyXG5cclxuICAvKipcclxuICAgKiBPcHRpb25hbGx5IHNhbml0aXplIGZvdW5kIEhUTUwgd2l0aCBhIHNhbml0aXplciBmdW5jdGlvbi5cclxuICAgKi9cclxuICBzYW5pdGl6ZXI/KGh0bWw6IHN0cmluZyk6IHN0cmluZztcclxufVxyXG4iLCJpbXBvcnQgeyBpc1BsYXRmb3JtQnJvd3NlciB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XHJcbmltcG9ydCB7IEh0dHBDbGllbnQgfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XHJcbmltcG9ydCB7IEluamVjdCwgSW5qZWN0YWJsZSwgT3B0aW9uYWwsIFBMQVRGT1JNX0lELCBTZWN1cml0eUNvbnRleHQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgRG9tU2FuaXRpemVyIH0gZnJvbSAnQGFuZ3VsYXIvcGxhdGZvcm0tYnJvd3Nlcic7XHJcbmltcG9ydCB7IHBhcnNlLCBSZW5kZXJlciB9IGZyb20gJ21hcmtlZCc7XHJcbmltcG9ydCB7IE9ic2VydmFibGUgfSBmcm9tICdyeGpzJztcclxuaW1wb3J0IHsgbWFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xyXG5cclxuaW1wb3J0IHsgTWFya2VkT3B0aW9ucyB9IGZyb20gJy4vbWFya2VkLW9wdGlvbnMnO1xyXG5cclxuZGVjbGFyZSB2YXIgUHJpc206IHtcclxuICBoaWdobGlnaHRBbGw6IChhc3luYzogYm9vbGVhbikgPT4gdm9pZDtcclxufTtcclxuXHJcbi8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTptYXgtbGluZS1sZW5ndGhcclxuZXhwb3J0IGNvbnN0IGVycm9yU3JjV2l0aG91dEh0dHBDbGllbnQgPSAnW25neC1tYXJrZG93bl0gV2hlbiB1c2luZyB0aGUgW3NyY10gYXR0cmlidXRlIHlvdSAqaGF2ZSB0byogcGFzcyB0aGUgYEh0dHBDbGllbnRgIGFzIGEgcGFyYW1ldGVyIG9mIHRoZSBgZm9yUm9vdGAgbWV0aG9kLiBTZWUgUkVBRE1FIGZvciBtb3JlIGluZm9ybWF0aW9uJztcclxuXHJcbkBJbmplY3RhYmxlKClcclxuZXhwb3J0IGNsYXNzIE1hcmtkb3duU2VydmljZSB7XHJcbiAgZ2V0IHJlbmRlcmVyKCk6IFJlbmRlcmVyIHsgcmV0dXJuIHRoaXMub3B0aW9ucy5yZW5kZXJlcjsgfVxyXG4gIHNldCByZW5kZXJlcih2YWx1ZTogbWFya2VkLlJlbmRlcmVyKSB7XHJcbiAgICB0aGlzLm9wdGlvbnMucmVuZGVyZXIgPSB2YWx1ZTtcclxuICB9XHJcblxyXG4gIGNvbnN0cnVjdG9yKFxyXG4gICAgQEluamVjdChQTEFURk9STV9JRCkgcHJpdmF0ZSBwbGF0Zm9ybTogT2JqZWN0LFxyXG4gICAgQE9wdGlvbmFsKCkgcHJpdmF0ZSBodHRwOiBIdHRwQ2xpZW50LFxyXG4gICAgcHJpdmF0ZSBkb21TYW5pdGl6ZXI6IERvbVNhbml0aXplcixcclxuICAgIHB1YmxpYyBvcHRpb25zOiBNYXJrZWRPcHRpb25zLFxyXG4gICkge1xyXG4gICAgaWYgKCF0aGlzLnJlbmRlcmVyKSB7XHJcbiAgICAgIHRoaXMucmVuZGVyZXIgPSBuZXcgUmVuZGVyZXIoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGNvbXBpbGUobWFya2Rvd246IHN0cmluZywgZGVjb2RlSHRtbCA9IGZhbHNlLCBtYXJrZWRPcHRpb25zID0gdGhpcy5vcHRpb25zKTogc3RyaW5nIHtcclxuICAgIGNvbnN0IHByZWNvbXBpbGVkID0gdGhpcy5wcmVjb21waWxlKG1hcmtkb3duKTtcclxuICAgIGNvbnN0IGNvbXBpbGVkID0gcGFyc2UoXHJcbiAgICAgIGRlY29kZUh0bWwgPyB0aGlzLmRlY29kZUh0bWwocHJlY29tcGlsZWQpIDogcHJlY29tcGlsZWQsXHJcbiAgICAgIG1hcmtlZE9wdGlvbnMpO1xyXG4gICAgcmV0dXJuIG1hcmtlZE9wdGlvbnMuc2FuaXRpemUgJiYgIW1hcmtlZE9wdGlvbnMuc2FuaXRpemVyXHJcbiAgICAgID8gdGhpcy5kb21TYW5pdGl6ZXIuc2FuaXRpemUoU2VjdXJpdHlDb250ZXh0LkhUTUwsIGNvbXBpbGVkKVxyXG4gICAgICA6IGNvbXBpbGVkO1xyXG4gIH1cclxuXHJcbiAgZ2V0U291cmNlKHNyYzogc3RyaW5nKTogT2JzZXJ2YWJsZTxzdHJpbmc+IHtcclxuICAgIGlmICghdGhpcy5odHRwKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihlcnJvclNyY1dpdGhvdXRIdHRwQ2xpZW50KTtcclxuICAgIH1cclxuICAgIHJldHVybiB0aGlzLmh0dHBcclxuICAgICAgLmdldChzcmMsIHsgcmVzcG9uc2VUeXBlOiAndGV4dCcgfSlcclxuICAgICAgLnBpcGUobWFwKG1hcmtkb3duID0+IHRoaXMuaGFuZGxlRXh0ZW5zaW9uKHNyYywgbWFya2Rvd24pKSk7XHJcbiAgfVxyXG5cclxuICBoaWdobGlnaHQoKSB7XHJcbiAgICBpZiAoaXNQbGF0Zm9ybUJyb3dzZXIodGhpcy5wbGF0Zm9ybSkgJiYgdHlwZW9mIFByaXNtICE9PSAndW5kZWZpbmVkJykge1xyXG4gICAgICBQcmlzbS5oaWdobGlnaHRBbGwoZmFsc2UpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBkZWNvZGVIdG1sKGh0bWw6IHN0cmluZykge1xyXG4gICAgaWYgKGlzUGxhdGZvcm1Ccm93c2VyKHRoaXMucGxhdGZvcm0pKSB7XHJcbiAgICAgIGNvbnN0IHRleHRhcmVhID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndGV4dGFyZWEnKTtcclxuICAgICAgdGV4dGFyZWEuaW5uZXJIVE1MID0gaHRtbDtcclxuICAgICAgcmV0dXJuIHRleHRhcmVhLnZhbHVlO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIGh0bWw7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGhhbmRsZUV4dGVuc2lvbihzcmM6IHN0cmluZywgbWFya2Rvd246IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICBjb25zdCBleHRlbnNpb24gPSBzcmNcclxuICAgICAgPyBzcmMuc3BsaXQoJy4nKS5zcGxpY2UoLTEpLmpvaW4oKVxyXG4gICAgICA6IG51bGw7XHJcbiAgICByZXR1cm4gZXh0ZW5zaW9uICE9PSAnbWQnXHJcbiAgICAgID8gJ2BgYCcgKyBleHRlbnNpb24gKyAnXFxuJyArIG1hcmtkb3duICsgJ1xcbmBgYCdcclxuICAgICAgOiBtYXJrZG93bjtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgcHJlY29tcGlsZShtYXJrZG93bjogc3RyaW5nKTogc3RyaW5nIHtcclxuICAgIGlmICghbWFya2Rvd24pIHtcclxuICAgICAgcmV0dXJuICcnO1xyXG4gICAgfVxyXG4gICAgbGV0IGluZGVudFN0YXJ0OiBudW1iZXI7XHJcbiAgICByZXR1cm4gbWFya2Rvd25cclxuICAgICAgLnNwbGl0KCdcXG4nKVxyXG4gICAgICAubWFwKGxpbmUgPT4ge1xyXG4gICAgICAgIC8vIHNldCBjdXJyZW50IGxpbmUgaWRlbnQgc3RhcnQgdG8gYmFzZSByZWZlcmVuY2UgaW5kZW50YXRpb25cclxuICAgICAgICBsZXQgbGluZUlkZW50U3RhcnQgPSBpbmRlbnRTdGFydDtcclxuICAgICAgICAvLyBmaW5kIHBvc2l0aW9uIG9mIDFzdCBub24td2hpdGVzcGFjZSBjaGFyYWN0ZXJcclxuICAgICAgICAvLyB0byBkZXRlcm1pbmUgdGhlIGN1cnJlbnQgbGluZSBpbmRlbnRhdGlvbiBzdGFydFxyXG4gICAgICAgIGlmIChsaW5lLmxlbmd0aCA+IDApIHtcclxuICAgICAgICAgIGxpbmVJZGVudFN0YXJ0ID0gaXNOYU4obGluZUlkZW50U3RhcnQpXHJcbiAgICAgICAgICAgID8gbGluZS5zZWFyY2goL1xcU3wkLylcclxuICAgICAgICAgICAgOiBNYXRoLm1pbihsaW5lLnNlYXJjaCgvXFxTfCQvKSwgbGluZUlkZW50U3RhcnQpO1xyXG4gICAgICAgIH1cclxuICAgICAgICAvLyBrZWVwIDFzdCBub24td2hpdGVzcGFjZSBsaW5lIGluZGVudGF0aW9uXHJcbiAgICAgICAgLy8gYXMgYmFzZSByZWZlcmVuY2UgZm9yIG90aGVyIGxpbmVzXHJcbiAgICAgICAgaWYgKGlzTmFOKGluZGVudFN0YXJ0KSkge1xyXG4gICAgICAgICAgaW5kZW50U3RhcnQgPSBsaW5lSWRlbnRTdGFydDtcclxuICAgICAgICB9XHJcbiAgICAgICAgLy8gcmVtb3ZlIHdoaXRlc3BhY2VzIGJlZm9yZSBjdXJyZW50IGxpbmUgaW5kZW50YXRpb25cclxuICAgICAgICByZXR1cm4gISFsaW5lSWRlbnRTdGFydFxyXG4gICAgICAgICAgPyBsaW5lLnN1YnN0cmluZyhsaW5lSWRlbnRTdGFydClcclxuICAgICAgICAgIDogbGluZTtcclxuICAgICAgfSkuam9pbignXFxuJyk7XHJcbiAgfVxyXG59XHJcbiIsImltcG9ydCB7IEFmdGVyVmlld0luaXQsIENvbXBvbmVudCwgRWxlbWVudFJlZiwgRXZlbnRFbWl0dGVyLCBJbnB1dCwgT3V0cHV0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcblxyXG5pbXBvcnQgeyBNYXJrZG93blNlcnZpY2UgfSBmcm9tICcuL21hcmtkb3duLnNlcnZpY2UnO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOmNvbXBvbmVudC1zZWxlY3RvclxyXG4gIHNlbGVjdG9yOiAnbWFya2Rvd24sIFttYXJrZG93bl0nLFxyXG4gIHRlbXBsYXRlOiAnPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PicsXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBNYXJrZG93bkNvbXBvbmVudCBpbXBsZW1lbnRzIEFmdGVyVmlld0luaXQge1xyXG4gIHByaXZhdGUgX2RhdGE6IHN0cmluZztcclxuICBwcml2YXRlIF9zcmM6IHN0cmluZztcclxuXHJcbiAgcHJpdmF0ZSBnZXQgX2lzVHJhbnNjbHVkZWQoKSB7XHJcbiAgICByZXR1cm4gIXRoaXMuX2RhdGEgJiYgIXRoaXMuX3NyYztcclxuICB9XHJcblxyXG4gIEBJbnB1dCgpXHJcbiAgZ2V0IGRhdGEoKTogc3RyaW5nIHsgcmV0dXJuIHRoaXMuX2RhdGE7IH1cclxuICBzZXQgZGF0YSh2YWx1ZTogc3RyaW5nKSB7XHJcbiAgICB0aGlzLl9kYXRhID0gdmFsdWU7XHJcbiAgICB0aGlzLnJlbmRlcih2YWx1ZSk7XHJcbiAgfVxyXG5cclxuICBASW5wdXQoKVxyXG4gIGdldCBzcmMoKTogc3RyaW5nIHsgcmV0dXJuIHRoaXMuX3NyYzsgfVxyXG4gIHNldCBzcmModmFsdWU6IHN0cmluZykge1xyXG4gICAgdGhpcy5fc3JjID0gdmFsdWU7XHJcbiAgICB0aGlzLm1hcmtkb3duU2VydmljZVxyXG4gICAgICAuZ2V0U291cmNlKHZhbHVlKVxyXG4gICAgICAuc3Vic2NyaWJlKFxyXG4gICAgICAgIG1hcmtkb3duID0+IHtcclxuICAgICAgICAgIHRoaXMucmVuZGVyKG1hcmtkb3duKTtcclxuICAgICAgICAgIHRoaXMubG9hZC5lbWl0KG1hcmtkb3duKTtcclxuICAgICAgICB9LFxyXG4gICAgICAgIGVycm9yID0+IHRoaXMuZXJyb3IuZW1pdChlcnJvciksXHJcbiAgICAgICk7XHJcbiAgfVxyXG5cclxuICBAT3V0cHV0KCkgZXJyb3IgPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZz4oKTtcclxuICBAT3V0cHV0KCkgbG9hZCA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xyXG5cclxuICBjb25zdHJ1Y3RvcihcclxuICAgIHB1YmxpYyBlbGVtZW50OiBFbGVtZW50UmVmLFxyXG4gICAgcHVibGljIG1hcmtkb3duU2VydmljZTogTWFya2Rvd25TZXJ2aWNlLFxyXG4gICkgeyB9XHJcblxyXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpIHtcclxuICAgIGlmICh0aGlzLl9pc1RyYW5zY2x1ZGVkKSB7XHJcbiAgICAgIHRoaXMucmVuZGVyKHRoaXMuZWxlbWVudC5uYXRpdmVFbGVtZW50LmlubmVySFRNTCwgdHJ1ZSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICByZW5kZXIobWFya2Rvd246IHN0cmluZywgZGVjb2RlSHRtbCA9IGZhbHNlKSB7XHJcbiAgICB0aGlzLmVsZW1lbnQubmF0aXZlRWxlbWVudC5pbm5lckhUTUwgPSB0aGlzLm1hcmtkb3duU2VydmljZS5jb21waWxlKG1hcmtkb3duLCBkZWNvZGVIdG1sKTtcclxuICAgIHRoaXMubWFya2Rvd25TZXJ2aWNlLmhpZ2hsaWdodCgpO1xyXG4gIH1cclxufVxyXG4iLCJpbXBvcnQgeyBOZ1pvbmUsIFBpcGUsIFBpcGVUcmFuc2Zvcm0gfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgZmlyc3QgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XHJcblxyXG5pbXBvcnQgeyBNYXJrZG93blNlcnZpY2UgfSBmcm9tICcuL21hcmtkb3duLnNlcnZpY2UnO1xyXG5cclxuQFBpcGUoe1xyXG4gIG5hbWU6ICdtYXJrZG93bicsXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBNYXJrZG93blBpcGUgaW1wbGVtZW50cyBQaXBlVHJhbnNmb3JtIHtcclxuXHJcbiAgY29uc3RydWN0b3IoXHJcbiAgICBwcml2YXRlIG1hcmtkb3duU2VydmljZTogTWFya2Rvd25TZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSB6b25lOiBOZ1pvbmUsXHJcbiAgKSB7IH1cclxuXHJcbiAgdHJhbnNmb3JtKHZhbHVlOiBzdHJpbmcpOiBzdHJpbmcge1xyXG4gICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ3N0cmluZycpIHtcclxuICAgICAgY29uc29sZS5lcnJvcihgTWFya2Rvd25QaXBlIGhhcyBiZWVuIGludm9rZWQgd2l0aCBhbiBpbnZhbGlkIHZhbHVlIHR5cGUgWyR7dmFsdWV9XWApO1xyXG4gICAgICByZXR1cm4gdmFsdWU7XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgbWFya2Rvd24gPSB0aGlzLm1hcmtkb3duU2VydmljZS5jb21waWxlKHZhbHVlKTtcclxuXHJcbiAgICB0aGlzLnpvbmUub25TdGFibGVcclxuICAgICAgLnBpcGUoZmlyc3QoKSlcclxuICAgICAgLnN1YnNjcmliZSgoKSA9PiB0aGlzLm1hcmtkb3duU2VydmljZS5oaWdobGlnaHQoKSk7XHJcblxyXG4gICAgcmV0dXJuIG1hcmtkb3duO1xyXG4gIH1cclxufVxyXG4iLCJpbXBvcnQgeyBNb2R1bGVXaXRoUHJvdmlkZXJzLCBOZ01vZHVsZSwgUHJvdmlkZXIgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuXHJcbmltcG9ydCB7IExhbmd1YWdlUGlwZSB9IGZyb20gJy4vbGFuZ3VhZ2UucGlwZSc7XHJcbmltcG9ydCB7IE1hcmtkb3duQ29tcG9uZW50IH0gZnJvbSAnLi9tYXJrZG93bi5jb21wb25lbnQnO1xyXG5pbXBvcnQgeyBNYXJrZG93blBpcGUgfSBmcm9tICcuL21hcmtkb3duLnBpcGUnO1xyXG5pbXBvcnQgeyBNYXJrZG93blNlcnZpY2UgfSBmcm9tICcuL21hcmtkb3duLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBNYXJrZWRPcHRpb25zIH0gZnJvbSAnLi9tYXJrZWQtb3B0aW9ucyc7XHJcblxyXG4vLyBoYXZpbmcgYSBkZXBlbmRlbmN5IG9uIGBIdHRwQ2xpZW50TW9kdWxlYCB3aXRoaW4gYSBsaWJyYXJ5XHJcbi8vIGJyZWFrcyBhbGwgdGhlIGludGVyY2VwdG9ycyBmcm9tIHRoZSBhcHAgY29uc3VtaW5nIHRoZSBsaWJyYXJ5XHJcbi8vIGhlcmUsIHdlIGV4cGxpY2l0ZWx5IGFzayB0aGUgdXNlciB0byBwYXNzIGEgcHJvdmlkZXIgd2l0aFxyXG4vLyB0aGVpciBvd24gaW5zdGFuY2Ugb2YgYEh0dHBDbGllbnRNb2R1bGVgXHJcbmV4cG9ydCBpbnRlcmZhY2UgTWFya2Rvd25Nb2R1bGVDb25maWcge1xyXG4gIGxvYWRlcj86IFByb3ZpZGVyO1xyXG4gIG1hcmtlZE9wdGlvbnM/OiBQcm92aWRlcjtcclxufVxyXG5cclxuZXhwb3J0IGNvbnN0IGluaXRpYWxNYXJrZWRPcHRpb25zOiBQcm92aWRlciA9IHtcclxuICBwcm92aWRlOiBNYXJrZWRPcHRpb25zLFxyXG4gIHVzZVZhbHVlOiB7XHJcbiAgICBnZm06IHRydWUsXHJcbiAgICB0YWJsZXM6IHRydWUsXHJcbiAgICBicmVha3M6IGZhbHNlLFxyXG4gICAgcGVkYW50aWM6IGZhbHNlLFxyXG4gICAgc2FuaXRpemU6IGZhbHNlLFxyXG4gICAgc21hcnRMaXN0czogdHJ1ZSxcclxuICAgIHNtYXJ0eXBhbnRzOiBmYWxzZSxcclxuICB9LFxyXG59O1xyXG5cclxuY29uc3Qgc2hhcmVkRGVjbGFyYXRpb25zID0gW1xyXG4gIExhbmd1YWdlUGlwZSxcclxuICBNYXJrZG93bkNvbXBvbmVudCxcclxuICBNYXJrZG93blBpcGUsXHJcbl07XHJcblxyXG5ATmdNb2R1bGUoe1xyXG4gIGV4cG9ydHM6IFtcclxuICAgIC4uLnNoYXJlZERlY2xhcmF0aW9ucyxcclxuICBdLFxyXG4gIGRlY2xhcmF0aW9uczogW1xyXG4gICAgLi4uc2hhcmVkRGVjbGFyYXRpb25zLFxyXG4gIF0sXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBNYXJrZG93bk1vZHVsZSB7XHJcbiAgc3RhdGljIGZvclJvb3QobWFya2Rvd25Nb2R1bGVDb25maWc/OiBNYXJrZG93bk1vZHVsZUNvbmZpZyk6IE1vZHVsZVdpdGhQcm92aWRlcnMge1xyXG4gICAgcmV0dXJuIHtcclxuICAgICAgbmdNb2R1bGU6IE1hcmtkb3duTW9kdWxlLFxyXG4gICAgICBwcm92aWRlcnM6IFtcclxuICAgICAgICBNYXJrZG93blNlcnZpY2UsXHJcbiAgICAgICAgLi4uKG1hcmtkb3duTW9kdWxlQ29uZmlnXHJcbiAgICAgICAgICA/IFtcclxuICAgICAgICAgICAgICBtYXJrZG93bk1vZHVsZUNvbmZpZy5sb2FkZXIgfHwgW10sXHJcbiAgICAgICAgICAgICAgbWFya2Rvd25Nb2R1bGVDb25maWcubWFya2VkT3B0aW9ucyB8fCBpbml0aWFsTWFya2VkT3B0aW9ucyxcclxuICAgICAgICAgICAgXVxyXG4gICAgICAgICAgOiBbaW5pdGlhbE1hcmtlZE9wdGlvbnNdKSxcclxuICAgICAgXSxcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICBzdGF0aWMgZm9yQ2hpbGQoKTogTW9kdWxlV2l0aFByb3ZpZGVycyB7XHJcbiAgICByZXR1cm4ge1xyXG4gICAgICBuZ01vZHVsZTogTWFya2Rvd25Nb2R1bGUsXHJcbiAgICB9O1xyXG4gIH1cclxufVxyXG4iLCJpbXBvcnQgeyBSZW5kZXJlciB9IGZyb20gJ21hcmtlZCc7XHJcblxyXG5leHBvcnQgY2xhc3MgTWFya2VkUmVuZGVyZXIgZXh0ZW5kcyBSZW5kZXJlciB7IH1cclxuIl0sIm5hbWVzIjpbInRzbGliXzEuX19leHRlbmRzIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7QUFBQTs7Ozs7Ozs7SUFPRSxnQ0FBUzs7Ozs7SUFBVCxVQUFVLEtBQWEsRUFBRSxRQUFnQjtRQUN2QyxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsRUFBRTtZQUM3QixPQUFPLENBQUMsS0FBSyxDQUFDLCtEQUE2RCxLQUFLLE1BQUcsQ0FBQyxDQUFDO1lBQ3JGLE9BQU8sS0FBSyxDQUFDO1NBQ2Q7UUFDRCxJQUFJLE9BQU8sUUFBUSxLQUFLLFFBQVEsRUFBRTtZQUNoQyxPQUFPLENBQUMsS0FBSyxDQUFDLDhEQUE0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