@asoftwareworld/form-builder-pro
Version:
ASW Form Builder Pro helps you with rapid development and designed web forms which includes several controls. The key feature of Form Builder is to make your content attractive and effective. We can customize our control at run time and preview the same b
425 lines • 62.9 kB
JavaScript
import { DOCUMENT } from '@angular/common';
import { Attribute, Component, ContentChild, EventEmitter, forwardRef, HostBinding, HostListener, Inject, Input, Output, SecurityContext, ViewChild } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import { aswEditorConfig } from '@asoftwareworld/form-builder-pro/api';
import { isDefined } from '@asoftwareworld/form-builder-pro/utils';
import * as i0 from "@angular/core";
import * as i1 from "./editor.service";
import * as i2 from "@angular/platform-browser";
import * as i3 from "@angular/common";
import * as i4 from "./editor-toolbar/editor-toolbar";
export class AswEditor {
renderer;
aswEditorService;
doc;
sanitizer;
cdRef;
autoFocus;
elementDOM;
onChange;
onTouched;
modeVisual = true;
showPlaceholder = false;
disabled = false;
focused = false;
touched = false;
changed = false;
focusInstance;
blurInstance;
id = '';
config = aswEditorConfig;
placeholder = '';
tabIndex;
html;
textArea;
editorWrapper;
editorToolbar;
customButtonsTemplateRef;
executeCommandFn = this.executeCommand.bind(this);
viewMode = new EventEmitter();
/** emits `blur` event when focused out from the textarea */
blurEvent = new EventEmitter();
/** emits `focus` event when focused in to the textarea */
// eslint-disable-next-line @angular-eslint/no-output-rename, @angular-eslint/no-output-native
focusEvent = new EventEmitter();
tabindex = -1;
onFocus() {
this.focus();
}
constructor(renderer, aswEditorService, doc, sanitizer, cdRef, defaultTabIndex, autoFocus, elementDOM) {
this.renderer = renderer;
this.aswEditorService = aswEditorService;
this.doc = doc;
this.sanitizer = sanitizer;
this.cdRef = cdRef;
this.autoFocus = autoFocus;
this.elementDOM = elementDOM;
const parsedTabIndex = Number(defaultTabIndex);
this.tabIndex = parsedTabIndex || parsedTabIndex === 0 ? parsedTabIndex : null;
}
ngOnInit() {
this.config.toolbarPosition = this.config.toolbarPosition ? this.config.toolbarPosition : aswEditorConfig.toolbarPosition;
}
ngAfterViewInit() {
if (isDefined(this.autoFocus)) {
this.focus();
}
}
onPaste(event) {
if (this.config.rawPaste) {
event.preventDefault();
const text = event.clipboardData?.getData('text/plain');
document.execCommand('insertHTML', false, text);
return text;
}
}
/**
* Executed command from editor header buttons
* @param command string from triggerCommand
*/
executeCommand(command, value) {
this.focus();
if (command === 'focus') {
return;
}
if (command === 'toggleEditorMode') {
this.toggleEditorMode(this.modeVisual);
}
else if (command !== '') {
if (command === 'clear') {
this.aswEditorService.removeSelectedElements(this.getCustomTags());
this.onContentChange(this.textArea.nativeElement);
}
else if (command === 'default') {
this.aswEditorService.removeSelectedElements('h1,h2,h3,h4,h5,h6,p,pre');
this.onContentChange(this.textArea.nativeElement);
}
else {
this.aswEditorService.executeCommand(command, value);
}
this.exec();
}
}
/**
* focus event
*/
onTextAreaFocus(event) {
if (this.focused) {
event.stopPropagation();
return;
}
this.focused = true;
this.focusEvent.emit(event);
if (!this.touched || !this.changed) {
this.aswEditorService.executeInNextQueueIteration(() => {
this.configure();
this.touched = true;
});
}
}
/**
* @description fires when cursor leaves textarea
*/
onTextAreaMouseOut(event) {
this.aswEditorService.saveSelection();
}
/**
* blur event
*/
onTextAreaBlur(event) {
/**
* save selection if focussed out
*/
this.aswEditorService.executeInNextQueueIteration(this.aswEditorService.saveSelection);
if (typeof this.onTouched === 'function') {
this.onTouched();
}
if (event.relatedTarget !== null) {
const parent = event.relatedTarget.parentElement;
if (parent?.classList.contains('asw-editor-toolbar-set') && parent.classList.contains('asw-picker')) {
this.blurEvent.emit(event);
this.focused = false;
}
}
}
/**
* focus the text area when the editor is focused
*/
focus() {
if (this.modeVisual) {
this.textArea.nativeElement.focus();
}
else {
const sourceText = this.getChildById('sourceText' + this.id);
sourceText.focus();
this.focused = true;
}
}
/**
* Executed from the contenteditable section while the input property changes
* @param element html element from contenteditable
*/
onContentChange(element) {
element = element.target ? element.target : element;
let html = '';
if (this.modeVisual) {
html = element.innerHTML;
}
else {
html = element.innerText;
}
if (!html || html === '<br>') {
html = '';
}
if (typeof this.onChange === 'function') {
this.onChange(this.config.sanitize || this.config.sanitize === undefined ? this.sanitizer.sanitize(SecurityContext.HTML, html) : html);
if (!html !== this.showPlaceholder) {
this.togglePlaceholder(this.showPlaceholder);
}
}
this.changed = true;
}
/**
* Set the function to be called
* when the control receives a change event.
*
* @param fn a function
*/
registerOnChange(fn) {
this.onChange = (e) => (e === '<br>' ? fn('') : fn(e));
}
/**
* Set the function to be called
* when the control receives a touch event.
*
* @param fn a function
*/
registerOnTouched(fn) {
this.onTouched = fn;
}
/**
* Write a new value to the element.
*
* @param value value to be executed when there is a change in contenteditable
*/
writeValue(value) {
if ((!value || value === '<br>' || value === '') !== this.showPlaceholder) {
this.togglePlaceholder(this.showPlaceholder);
}
if (value === undefined || value === '' || value === '<br>') {
value = null;
}
this.refreshView(value);
}
/**
* refresh view/HTML of the editor
*
* @param value html string from the editor
*/
refreshView(value) {
const normalizedValue = value === null ? '' : value;
this.renderer.setProperty(this.textArea.nativeElement, 'innerHTML', normalizedValue);
return;
}
/**
* toggles placeholder based on input string
*
* @param value A HTML string from the editor
*/
togglePlaceholder(value) {
if (!value) {
this.renderer.addClass(this.editorWrapper.nativeElement, 'show-placeholder');
this.showPlaceholder = true;
}
else {
this.renderer.removeClass(this.editorWrapper.nativeElement, 'show-placeholder');
this.showPlaceholder = false;
}
}
/**
* Implements disabled state for this element
*
* @param isDisabled Disabled flag
*/
setDisabledState(isDisabled) {
const div = this.textArea.nativeElement;
const action = isDisabled ? 'addClass' : 'removeClass';
this.renderer[action](div, 'disabled');
this.disabled = isDisabled;
}
/**
* toggles editor mode based on bToSource bool
*
* @param bToSource A boolean value from the editor
*/
toggleEditorMode(bToSource) {
let oContent;
const editableElement = this.textArea.nativeElement;
if (bToSource) {
oContent = this.renderer.createText(editableElement.innerHTML);
this.renderer.setProperty(editableElement, 'innerHTML', '');
this.renderer.setProperty(editableElement, 'contentEditable', false);
const oPre = this.renderer.createElement('pre');
this.renderer.setStyle(oPre, 'margin', '0');
this.renderer.setStyle(oPre, 'outline', 'none');
const oCode = this.renderer.createElement('code');
this.renderer.setProperty(oCode, 'id', 'sourceText' + this.id);
this.renderer.setStyle(oCode, 'display', 'block');
this.renderer.setStyle(oCode, 'white-space', 'pre-wrap');
this.renderer.setStyle(oCode, 'word-break', 'keep-all');
this.renderer.setStyle(oCode, 'outline', 'none');
this.renderer.setStyle(oCode, 'margin', '0');
this.renderer.setStyle(oCode, 'background-color', '#e8f0fe');
this.renderer.setProperty(oCode, 'contentEditable', true);
this.renderer.appendChild(oCode, oContent);
this.focusInstance = this.renderer.listen(oCode, 'focus', (event) => this.onTextAreaFocus(event));
this.blurInstance = this.renderer.listen(oCode, 'blur', (event) => this.onTextAreaBlur(event));
this.renderer.appendChild(oPre, oCode);
this.renderer.appendChild(editableElement, oPre);
// ToDo move to service
this.doc.execCommand('defaultParagraphSeparator', false, 'div');
this.modeVisual = false;
this.viewMode.emit(false);
oCode.focus();
}
else {
if (this.doc.querySelectorAll) {
this.renderer.setProperty(editableElement, 'innerHTML', editableElement.innerText);
}
else {
oContent = this.doc.createRange();
oContent.selectNodeContents(editableElement.firstChild);
this.renderer.setProperty(editableElement, 'innerHTML', oContent.toString());
}
this.renderer.setProperty(editableElement, 'contentEditable', true);
this.modeVisual = true;
this.viewMode.emit(true);
this.onContentChange(editableElement);
editableElement.focus();
}
this.editorToolbar?.setEditorMode(!this.modeVisual);
}
/**
* toggles editor buttons when cursor moved or positioning
*
* Send a node array from the contentEditable of the editor
*/
exec() {
this.editorToolbar?.triggerButtons();
let userSelection;
if (this.doc.getSelection) {
userSelection = this.doc.getSelection();
this.aswEditorService.executeInNextQueueIteration(this.aswEditorService.saveSelection);
}
let a = userSelection.focusNode;
const els = [];
while (a && a.id !== 'editor') {
els.unshift(a);
a = a.parentNode;
}
this.editorToolbar?.triggerBlocks(els);
}
configure() {
this.aswEditorService.uploadUrl = this.config.uploadUrl;
this.aswEditorService.uploadWithCredentials = this.config.uploadWithCredentials;
if (this.config.defaultParagraphSeparator) {
this.aswEditorService.setDefaultParagraphSeparator(this.config.defaultParagraphSeparator);
}
if (this.config.defaultFontName) {
this.aswEditorService.setFontName(this.config.defaultFontName);
}
if (this.config.defaultFontSize) {
this.aswEditorService.setFontSize(this.config.defaultFontSize);
}
}
getCustomTags() {
const tags = ['span'];
this.config.customClasses?.forEach((x) => {
if (x.tag !== undefined) {
if (!tags.includes(x.tag)) {
tags.push(x.tag);
}
}
});
return tags.join(',');
}
ngOnDestroy() {
if (this.blurInstance) {
this.blurInstance();
}
if (this.focusInstance) {
this.focusInstance();
}
}
filterStyles(html) {
html = html.replace('position: fixed;', '');
return html;
}
getChildById(id) {
return this.elementDOM.nativeElement.querySelector(`#${id}`);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: AswEditor, deps: [{ token: i0.Renderer2 }, { token: i1.AswEditorService }, { token: DOCUMENT }, { token: i2.DomSanitizer }, { token: i0.ChangeDetectorRef }, { token: 'tabindex', attribute: true }, { token: 'autofocus', attribute: true }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.8", type: AswEditor, selector: "asw-editor", inputs: { id: "id", config: "config", placeholder: "placeholder", tabIndex: "tabIndex" }, outputs: { html: "html", viewMode: "viewMode", blurEvent: "blur", focusEvent: "focus" }, host: { listeners: { "focus": "onFocus()" }, properties: { "attr.tabindex": "this.tabindex" } }, providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => AswEditor),
multi: true
}
], queries: [{ propertyName: "customButtonsTemplateRef", first: true, predicate: ["customButtons"], descendants: true }], viewQueries: [{ propertyName: "textArea", first: true, predicate: ["editor"], descendants: true, static: true }, { propertyName: "editorWrapper", first: true, predicate: ["editorWrapper"], descendants: true, static: true }, { propertyName: "editorToolbar", first: true, predicate: ["editorToolbar"], descendants: true }], ngImport: i0, template: "<div\r\n class=\"asw-editor\"\r\n #aswEditor\r\n [style.width]=\"config.width\"\r\n [style.minWidth]=\"config.minWidth\"\r\n>\r\n <asw-editor-toolbar\r\n *ngIf=\"config.toolbarPosition === 'top'\"\r\n #editorToolbar\r\n [id]=\"id\"\r\n [uploadUrl]=\"config.uploadUrl\"\r\n [upload]=\"config.upload\"\r\n [showToolbar]=\"config.showToolbar !== undefined ? config.showToolbar : true\"\r\n [customClasses]=\"config.customClasses\"\r\n [defaultFontSize]=\"config.defaultFontSize\"\r\n [hiddenButtons]=\"config.toolbarHiddenButtons\"\r\n (execute)=\"executeCommand($event)\"\r\n >\r\n <ng-container\r\n [ngTemplateOutlet]=\"customButtonsTemplateRef\"\r\n [ngTemplateOutletContext]=\"{ executeCommandFn: this.executeCommandFn}\"\r\n >\r\n </ng-container>\r\n </asw-editor-toolbar>\r\n\r\n <div\r\n class=\"asw-editor-wrapper\"\r\n #editorWrapper\r\n >\r\n <div\r\n #editor\r\n class=\"asw-editor-textarea\"\r\n [attr.contenteditable]=\"config.editable\"\r\n [attr.tabindex]=\"disabled ? -1 : tabIndex\"\r\n [attr.translate]=\"config.translate\"\r\n [attr.spellcheck]=\"config.spellcheck\"\r\n [style.height]=\"config.height\"\r\n [style.minHeight]=\"config.minHeight\"\r\n [style.maxHeight]=\"config.maxHeight\"\r\n [style.outline]=\"config.outline === false ? 'none': undefined\"\r\n (input)=\"onContentChange($event)\"\r\n (focus)=\"onTextAreaFocus($event)\"\r\n (blur)=\"onTextAreaBlur($event)\"\r\n (click)=\"exec()\"\r\n (keyup)=\"exec()\"\r\n (mouseout)=\"onTextAreaMouseOut($event)\"\r\n (paste)=\"onPaste($event)\"\r\n >\r\n </div>\r\n <span class=\"asw-editor-placeholder\">{{ placeholder || config['placeholder'] }}</span>\r\n </div>\r\n <asw-editor-toolbar\r\n *ngIf=\"config.toolbarPosition === 'bottom'\"\r\n #editorToolbar\r\n [id]=\"id\"\r\n [uploadUrl]=\"config.uploadUrl\"\r\n [upload]=\"config.upload\"\r\n [showToolbar]=\"config.showToolbar !== undefined ? config.showToolbar : true\"\r\n [customClasses]=\"config.customClasses\"\r\n [defaultFontSize]=\"config.defaultFontSize\"\r\n [hiddenButtons]=\"config.toolbarHiddenButtons\"\r\n (execute)=\"executeCommand($event)\"\r\n ></asw-editor-toolbar>\r\n</div>", styles: [".asw-editor{position:relative}.asw-editor ::ng-deep [contenteditable=true]:empty:before{content:attr(placeholder);color:#868e96;opacity:1}.asw-editor .asw-editor-wrapper{position:relative}.asw-editor .asw-editor-wrapper .asw-editor-textarea{min-height:10rem;padding:.5rem .8rem 1rem;border:1px solid #ddd;background-color:transparent;overflow-x:hidden;overflow-y:auto;position:relative}.asw-editor .asw-editor-wrapper .asw-editor-textarea ::ng-deep blockquote{margin-left:1rem;border-left:.2em solid #dfe2e5;padding-left:.5rem}.asw-editor .asw-editor-wrapper ::ng-deep p{margin-bottom:0}.asw-editor .asw-editor-wrapper .asw-editor-placeholder{display:none;position:absolute;top:0;padding:.5rem .8rem 1rem .9rem;color:#6c757d;opacity:.75}.asw-editor .asw-editor-wrapper.show-placeholder .asw-editor-placeholder{display:block}.asw-editor .asw-editor-wrapper.disabled{cursor:not-allowed;opacity:.5;pointer-events:none}\n"], dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i4.AswEditorToolbar, selector: "asw-editor-toolbar", inputs: ["id", "uploadUrl", "upload", "showToolbar", "fonts", "customClasses", "defaultFontSize", "hiddenButtons"], outputs: ["execute"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: AswEditor, decorators: [{
type: Component,
args: [{ selector: 'asw-editor', providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => AswEditor),
multi: true
}
], template: "<div\r\n class=\"asw-editor\"\r\n #aswEditor\r\n [style.width]=\"config.width\"\r\n [style.minWidth]=\"config.minWidth\"\r\n>\r\n <asw-editor-toolbar\r\n *ngIf=\"config.toolbarPosition === 'top'\"\r\n #editorToolbar\r\n [id]=\"id\"\r\n [uploadUrl]=\"config.uploadUrl\"\r\n [upload]=\"config.upload\"\r\n [showToolbar]=\"config.showToolbar !== undefined ? config.showToolbar : true\"\r\n [customClasses]=\"config.customClasses\"\r\n [defaultFontSize]=\"config.defaultFontSize\"\r\n [hiddenButtons]=\"config.toolbarHiddenButtons\"\r\n (execute)=\"executeCommand($event)\"\r\n >\r\n <ng-container\r\n [ngTemplateOutlet]=\"customButtonsTemplateRef\"\r\n [ngTemplateOutletContext]=\"{ executeCommandFn: this.executeCommandFn}\"\r\n >\r\n </ng-container>\r\n </asw-editor-toolbar>\r\n\r\n <div\r\n class=\"asw-editor-wrapper\"\r\n #editorWrapper\r\n >\r\n <div\r\n #editor\r\n class=\"asw-editor-textarea\"\r\n [attr.contenteditable]=\"config.editable\"\r\n [attr.tabindex]=\"disabled ? -1 : tabIndex\"\r\n [attr.translate]=\"config.translate\"\r\n [attr.spellcheck]=\"config.spellcheck\"\r\n [style.height]=\"config.height\"\r\n [style.minHeight]=\"config.minHeight\"\r\n [style.maxHeight]=\"config.maxHeight\"\r\n [style.outline]=\"config.outline === false ? 'none': undefined\"\r\n (input)=\"onContentChange($event)\"\r\n (focus)=\"onTextAreaFocus($event)\"\r\n (blur)=\"onTextAreaBlur($event)\"\r\n (click)=\"exec()\"\r\n (keyup)=\"exec()\"\r\n (mouseout)=\"onTextAreaMouseOut($event)\"\r\n (paste)=\"onPaste($event)\"\r\n >\r\n </div>\r\n <span class=\"asw-editor-placeholder\">{{ placeholder || config['placeholder'] }}</span>\r\n </div>\r\n <asw-editor-toolbar\r\n *ngIf=\"config.toolbarPosition === 'bottom'\"\r\n #editorToolbar\r\n [id]=\"id\"\r\n [uploadUrl]=\"config.uploadUrl\"\r\n [upload]=\"config.upload\"\r\n [showToolbar]=\"config.showToolbar !== undefined ? config.showToolbar : true\"\r\n [customClasses]=\"config.customClasses\"\r\n [defaultFontSize]=\"config.defaultFontSize\"\r\n [hiddenButtons]=\"config.toolbarHiddenButtons\"\r\n (execute)=\"executeCommand($event)\"\r\n ></asw-editor-toolbar>\r\n</div>", styles: [".asw-editor{position:relative}.asw-editor ::ng-deep [contenteditable=true]:empty:before{content:attr(placeholder);color:#868e96;opacity:1}.asw-editor .asw-editor-wrapper{position:relative}.asw-editor .asw-editor-wrapper .asw-editor-textarea{min-height:10rem;padding:.5rem .8rem 1rem;border:1px solid #ddd;background-color:transparent;overflow-x:hidden;overflow-y:auto;position:relative}.asw-editor .asw-editor-wrapper .asw-editor-textarea ::ng-deep blockquote{margin-left:1rem;border-left:.2em solid #dfe2e5;padding-left:.5rem}.asw-editor .asw-editor-wrapper ::ng-deep p{margin-bottom:0}.asw-editor .asw-editor-wrapper .asw-editor-placeholder{display:none;position:absolute;top:0;padding:.5rem .8rem 1rem .9rem;color:#6c757d;opacity:.75}.asw-editor .asw-editor-wrapper.show-placeholder .asw-editor-placeholder{display:block}.asw-editor .asw-editor-wrapper.disabled{cursor:not-allowed;opacity:.5;pointer-events:none}\n"] }]
}], ctorParameters: () => [{ type: i0.Renderer2 }, { type: i1.AswEditorService }, { type: undefined, decorators: [{
type: Inject,
args: [DOCUMENT]
}] }, { type: i2.DomSanitizer }, { type: i0.ChangeDetectorRef }, { type: undefined, decorators: [{
type: Attribute,
args: ['tabindex']
}] }, { type: undefined, decorators: [{
type: Attribute,
args: ['autofocus']
}] }, { type: i0.ElementRef }], propDecorators: { id: [{
type: Input
}], config: [{
type: Input
}], placeholder: [{
type: Input
}], tabIndex: [{
type: Input
}], html: [{
type: Output
}], textArea: [{
type: ViewChild,
args: ['editor', { static: true }]
}], editorWrapper: [{
type: ViewChild,
args: ['editorWrapper', { static: true }]
}], editorToolbar: [{
type: ViewChild,
args: ['editorToolbar']
}], customButtonsTemplateRef: [{
type: ContentChild,
args: ['customButtons']
}], viewMode: [{
type: Output
}], blurEvent: [{
type: Output,
args: ['blur']
}], focusEvent: [{
type: Output,
args: ['focus']
}], tabindex: [{
type: HostBinding,
args: ['attr.tabindex']
}], onFocus: [{
type: HostListener,
args: ['focus']
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWRpdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvZWRpdG9yL2VkaXRvci50cyIsIi4uLy4uLy4uL3NyYy9jb21wb25lbnRzL2VkaXRvci9lZGl0b3IuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDM0MsT0FBTyxFQUVILFNBQVMsRUFFVCxTQUFTLEVBQ1QsWUFBWSxFQUVaLFlBQVksRUFDWixVQUFVLEVBQ1YsV0FBVyxFQUNYLFlBQVksRUFDWixNQUFNLEVBQ04sS0FBSyxFQUdMLE1BQU0sRUFFTixlQUFlLEVBRWYsU0FBUyxFQUNaLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBd0IsaUJBQWlCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUV6RSxPQUFPLEVBQW1CLGVBQWUsRUFBYyxNQUFNLHNDQUFzQyxDQUFDO0FBQ3BHLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSx3Q0FBd0MsQ0FBQzs7Ozs7O0FBZ0JuRSxNQUFNLE9BQU8sU0FBUztJQTRDTjtJQUNBO0lBQ2tCO0lBQ2xCO0lBQ0E7SUFFd0I7SUFDekI7SUFsREgsUUFBUSxDQUFrQztJQUMxQyxTQUFTLENBQWM7SUFFL0IsVUFBVSxHQUFHLElBQUksQ0FBQztJQUNsQixlQUFlLEdBQUcsS0FBSyxDQUFDO0lBQ3hCLFFBQVEsR0FBRyxLQUFLLENBQUM7SUFDakIsT0FBTyxHQUFHLEtBQUssQ0FBQztJQUNoQixPQUFPLEdBQUcsS0FBSyxDQUFDO0lBQ2hCLE9BQU8sR0FBRyxLQUFLLENBQUM7SUFFaEIsYUFBYSxDQUFNO0lBQ25CLFlBQVksQ0FBTTtJQUVULEVBQUUsR0FBRyxFQUFFLENBQUM7SUFDUixNQUFNLEdBQTBCLGVBQWUsQ0FBQztJQUNoRCxXQUFXLEdBQUcsRUFBRSxDQUFDO0lBQ2pCLFFBQVEsQ0FBZ0I7SUFFdkIsSUFBSSxDQUFNO0lBRW1C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SSxFQUFFO2dCQUNoQixhQUFhO3NCQUF4QyxTQUFTO3VCQUFDLGVBQWU7Z0JBQ0ssd0JBQXdCO3NCQUF0RCxZQUFZO3VCQUFDLGVBQWU7Z0JBR25CLFFBQVE7c0JBQWpCLE1BQU07Z0JBR1MsU0FBUztzQkFBeEIsTUFBTTt1QkFBQyxNQUFNO2dCQUlHLFVBQVU7c0JBQTFCLE1BQU07dUJBQUMsT0FBTztnQkFFZSxRQUFRO3NCQUFyQyxXQUFXO3VCQUFDLGVBQWU7Z0JBRzVCLE9BQU87c0JBRE4sWUFBWTt1QkFBQyxPQUFPIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRE9DVU1FTlQgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHtcbiAgICBBZnRlclZpZXdJbml0LFxuICAgIEF0dHJpYnV0ZSxcbiAgICBDaGFuZ2VEZXRlY3RvclJlZixcbiAgICBDb21wb25lbnQsXG4gICAgQ29udGVudENoaWxkLFxuICAgIEVsZW1lbnRSZWYsXG4gICAgRXZlbnRFbWl0dGVyLFxuICAgIGZvcndhcmRSZWYsXG4gICAgSG9zdEJpbmRpbmcsXG4gICAgSG9zdExpc3RlbmVyLFxuICAgIEluamVjdCxcbiAgICBJbnB1dCxcbiAgICBPbkRlc3Ryb3ksXG4gICAgT25Jbml0LFxuICAgIE91dHB1dCxcbiAgICBSZW5kZXJlcjIsXG4gICAgU2VjdXJpdHlDb250ZXh0LFxuICAgIFRlbXBsYXRlUmVmLFxuICAgIFZpZXdDaGlsZFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBOR19WQUxVRV9BQ0NFU1NPUiB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IERvbVNhbml0aXplciB9IGZyb20gJ0Bhbmd1bGFyL3BsYXRmb3JtLWJyb3dzZXInO1xuaW1wb3J0IHsgQXN3RWRpdG9yQ29uZmlnLCBhc3dFZGl0b3JDb25maWcsIEVsZW1lbnRET00gfSBmcm9tICdAYXNvZnR3YXJld29ybGQvZm9ybS1idWlsZGVyLXByby9hcGknO1xuaW1wb3J0IHsgaXNEZWZpbmVkIH0gZnJvbSAnQGFzb2Z0d2FyZXdvcmxkL2Zvcm0tYnVpbGRlci1wcm8vdXRpbHMnO1xuaW1wb3J0IHsgQXN3RWRpdG9yVG9vbGJhciB9IGZyb20gJy4vZWRpdG9yLXRvb2xiYXIvZWRpdG9yLXRvb2xiYXInO1xuaW1wb3J0IHsgQXN3RWRpdG9yU2VydmljZSB9IGZyb20gJy4vZWRpdG9yLnNlcnZpY2UnO1xuXG5AQ29tcG9uZW50KHtcbiAgICBzZWxlY3RvcjogJ2Fzdy1lZGl0b3InLFxuICAgIHRlbXBsYXRlVXJsOiAnLi9lZGl0b3IuaHRtbCcsXG4gICAgc3R5bGVVcmxzOiBbJy4vZWRpdG9yLnNjc3MnXSxcbiAgICBwcm92aWRlcnM6IFtcbiAgICAgICAge1xuICAgICAgICAgICAgcHJvdmlkZTogTkdfVkFMVUVfQUNDRVNTT1IsXG4gICAgICAgICAgICB1c2VFeGlzdGluZzogZm9yd2FyZFJlZigoKSA9PiBBc3dFZGl0b3IpLFxuICAgICAgICAgICAgbXVsdGk6IHRydWVcbiAgICAgICAgfVxuICAgIF1cbn0pXG5leHBvcnQgY2xhc3MgQXN3RWRpdG9yIGltcGxlbWVudHMgT25Jbml0LCBDb250cm9sVmFsdWVBY2Nlc3NvciwgQWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95LCBFbGVtZW50RE9NIHtcbiAgICBwcml2YXRlIG9uQ2hhbmdlOiAoKHZhbHVlOiBzdHJpbmcpID0+IHZvaWQpIHwgYW55O1xuICAgIHByaXZhdGUgb25Ub3VjaGVkITogKCkgPT4gdm9pZDtcblxuICAgIG1vZGVWaXN1YWwgPSB0cnVlO1xuICAgIHNob3dQbGFjZWhvbGRlciA9IGZhbHNlO1xuICAgIGRpc2FibGVkID0gZmFsc2U7XG4gICAgZm9jdXNlZCA9IGZhbHNlO1xuICAgIHRvdWNoZWQgPSBmYWxzZTtcbiAgICBjaGFuZ2VkID0gZmFsc2U7XG5cbiAgICBmb2N1c0luc3RhbmNlOiBhbnk7XG4gICAgYmx1ckluc3RhbmNlOiBhbnk7XG5cbiAgICBASW5wdXQoKSBpZCA9ICcnO1xuICAgIEBJbnB1dCgpIGNvbmZpZzogQXN3RWRpdG9yQ29uZmlnIHwgYW55ID0gYXN3RWRpdG9yQ29uZmlnO1xuICAgIEBJbnB1dCgpIHBsYWNlaG9sZGVyID0gJyc7XG4gICAgQElucHV0KCkgdGFiSW5kZXg6IG51bWJlciB8IG51bGw7XG5cbiAgICBAT3V0cHV0KCkgaHRtbDogYW55O1xuXG4gICAgQFZpZXdDaGlsZCgnZWRpdG9yJywgeyBzdGF0aWM6IHRydWUgfSkgdGV4dEFyZWEhOiBFbGVtZW50UmVmO1xuICAgIEBWaWV3Q2hpbGQoJ2VkaXRvcldyYXBwZXInLCB7IHN0YXRpYzogdHJ1ZSB9KSBlZGl0b3JXcmFwcGVyITogRWxlbWVudFJlZjtcbiAgICBAVmlld0NoaWxkKCdlZGl0b3JUb29sYmFyJykgZWRpdG9yVG9vbGJhcj86IEFzd0VkaXRvclRvb2xiYXI7XG4gICAgQENvbnRlbnRDaGlsZCgnY3VzdG9tQnV0dG9ucycpIGN1c3RvbUJ1dHRvbnNUZW1wbGF0ZVJlZjogVGVtcGxhdGVSZWY8YW55PiB8IGFueTtcbiAgICBleGVjdXRlQ29tbWFuZEZuID0gdGhpcy5leGVjdXRlQ29tbWFuZC5iaW5kKHRoaXMpO1xuXG4gICAgQE91dHB1dCgpIHZpZXdNb2RlID0gbmV3IEV2ZW50RW1pdHRlcjxib29sZWFuPigpO1xuXG4gICAgLyoqIGVtaXRzIGBibHVyYCBldmVudCB3aGVuIGZvY3VzZWQgb3V0IGZyb20gdGhlIHRleHRhcmVhICovXG4gICAgQE91dHB1dCgnYmx1cicpIGJsdXJFdmVudDogRXZlbnRFbWl0dGVyPEZvY3VzRXZlbnQ+ID0gbmV3IEV2ZW50RW1pdHRlcjxGb2N1c0V2ZW50PigpO1xuXG4gICAgLyoqIGVtaXRzIGBmb2N1c2AgZXZlbnQgd2hlbiBmb2N1c2VkIGluIHRvIHRoZSB0ZXh0YXJlYSAqL1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAYW5ndWxhci1lc2xpbnQvbm8tb3V0cHV0LXJlbmFtZSwgQGFuZ3VsYXItZXNsaW50L25vLW91dHB1dC1uYXRpdmVcbiAgICBAT3V0cHV0KCdmb2N1cycpIGZvY3VzRXZlbnQ6IEV2ZW50RW1pdHRlcjxGb2N1c0V2ZW50PiA9IG5ldyBFdmVudEVtaXR0ZXI8Rm9jdXNFdmVudD4oKTtcblxuICAgIEBIb3N0QmluZGluZygnYXR0ci50YWJpbmRleCcpIHRhYmluZGV4ID0gLTE7XG5cbiAgICBASG9zdExpc3RlbmVyKCdmb2N1cycpXG4gICAgb25Gb2N1cygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5mb2N1cygpO1xuICAgIH1cblxuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgICBwcml2YXRlIHJlbmRlcmVyOiBSZW5kZXJlcjIsXG4gICAgICAgIHByaXZhdGUgYXN3RWRpdG9yU2VydmljZTogQXN3RWRpdG9yU2VydmljZSxcbiAgICAgICAgQEluamVjdChET0NVTUVOVCkgcHJpdmF0ZSBkb2M6IGFueSxcbiAgICAgICAgcHJpdmF0ZSBzYW5pdGl6ZXI6IERvbVNhbml0aXplcixcbiAgICAgICAgcHJpdmF0ZSBjZFJlZjogQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gICAgICAgIEBBdHRyaWJ1dGUoJ3RhYmluZGV4JykgZGVmYXVsdFRhYkluZGV4OiBzdHJpbmcsXG4gICAgICAgIEBBdHRyaWJ1dGUoJ2F1dG9mb2N1cycpIHByaXZhdGUgYXV0b0ZvY3VzOiBhbnksXG4gICAgICAgIHB1YmxpYyBlbGVtZW50RE9NOiBFbGVtZW50UmVmPEhUTUxFbGVtZW50PlxuICAgICkge1xuICAgICAgICBjb25zdCBwYXJzZWRUYWJJbmRleCA9IE51bWJlcihkZWZhdWx0VGFiSW5kZXgpO1xuICAgICAgICB0aGlzLnRhYkluZGV4ID0gcGFyc2VkVGFiSW5kZXggfHwgcGFyc2VkVGFiSW5kZXggPT09IDAgPyBwYXJzZWRUYWJJbmRleCA6IG51bGw7XG4gICAgfVxuXG4gICAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuY29uZmlnLnRvb2xiYXJQb3NpdGlvbiA9IHRoaXMuY29uZmlnLnRvb2xiYXJQb3NpdGlvbiA/IHRoaXMuY29uZmlnLnRvb2xiYXJQb3NpdGlvbiA6IGFzd0VkaXRvckNvbmZpZy50b29sYmFyUG9zaXRpb247XG4gICAgfVxuXG4gICAgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xuICAgICAgICBpZiAoaXNEZWZpbmVkKHRoaXMuYXV0b0ZvY3VzKSkge1xuICAgICAgICAgICAgdGhpcy5mb2N1cygpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgb25QYXN0ZShldmVudDogQ2xpcGJvYXJkRXZlbnQpOiBhbnkge1xuICAgICAgICBpZiAodGhpcy5jb25maWcucmF3UGFzdGUpIHtcbiAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICBjb25zdCB0ZXh0ID0gZXZlbnQuY2xpcGJvYXJkRGF0YT8uZ2V0RGF0YSgndGV4dC9wbGFpbicpO1xuICAgICAgICAgICAgZG9jdW1lbnQuZXhlY0NvbW1hbmQoJ2luc2VydEhUTUwnLCBmYWxzZSwgdGV4dCk7XG4gICAgICAgICAgICByZXR1cm4gdGV4dDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEV4ZWN1dGVkIGNvbW1hbmQgZnJvbSBlZGl0b3IgaGVhZGVyIGJ1dHRvbnNcbiAgICAgKiBAcGFyYW0gY29tbWFuZCBzdHJpbmcgZnJvbSB0cmlnZ2VyQ29tbWFuZFxuICAgICAqL1xuICAgIGV4ZWN1dGVDb21tYW5kKGNvbW1hbmQ6IHN0cmluZywgdmFsdWU/OiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5mb2N1cygpO1xuICAgICAgICBpZiAoY29tbWFuZCA9PT0gJ2ZvY3VzJykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmIChjb21tYW5kID09PSAndG9nZ2xlRWRpdG9yTW9kZScpIHtcbiAgICAgICAgICAgIHRoaXMudG9nZ2xlRWRpdG9yTW9kZSh0aGlzLm1vZGVWaXN1YWwpO1xuICAgICAgICB9IGVsc2UgaWYgKGNvbW1hbmQgIT09ICcnKSB7XG4gICAgICAgICAgICBpZiAoY29tbWFuZCA9PT0gJ2NsZWFyJykge1xuICAgICAgICAgICAgICAgIHRoaXMuYXN3RWRpdG9yU2VydmljZS5yZW1vdmVTZWxlY3RlZEVsZW1lbnRzKHRoaXMuZ2V0Q3VzdG9tVGFncygpKTtcbiAgICAgICAgICAgICAgICB0aGlzLm9uQ29udGVudENoYW5nZSh0aGlzLnRleHRBcmVhLm5hdGl2ZUVsZW1lbnQpO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChjb21tYW5kID09PSAnZGVmYXVsdCcpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmFzd0VkaXRvclNlcnZpY2UucmVtb3ZlU2VsZWN0ZWRFbGVtZW50cygnaDEsaDIsaDMsaDQsaDUsaDYscCxwcmUnKTtcbiAgICAgICAgICAgICAgICB0aGlzLm9uQ29udGVudENoYW5nZSh0aGlzLnRleHRBcmVhLm5hdGl2ZUVsZW1lbnQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmFzd0VkaXRvclNlcnZpY2UuZXhlY3V0ZUNvbW1hbmQoY29tbWFuZCwgdmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5leGVjKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBmb2N1cyBldmVudFxuICAgICAqL1xuICAgIG9uVGV4dEFyZWFGb2N1cyhldmVudDogRm9jdXNFdmVudCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5mb2N1c2VkKSB7XG4gICAgICAgICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmZvY3VzZWQgPSB0cnVlO1xuICAgICAgICB0aGlzLmZvY3VzRXZlbnQuZW1pdChldmVudCk7XG4gICAgICAgIGlmICghdGhpcy50b3VjaGVkIHx8ICF0aGlzLmNoYW5nZWQpIHtcbiAgICAgICAgICAgIHRoaXMuYXN3RWRpdG9yU2VydmljZS5leGVjdXRlSW5OZXh0UXVldWVJdGVyYXRpb24oKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuY29uZmlndXJlKCk7XG4gICAgICAgICAgICAgICAgdGhpcy50b3VjaGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIGZpcmVzIHdoZW4gY3Vyc29yIGxlYXZlcyB0ZXh0YXJlYVxuICAgICAqL1xuICAgIHB1YmxpYyBvblRleHRBcmVhTW91c2VPdXQoZXZlbnQ6IE1vdXNlRXZlbnQpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5hc3dFZGl0b3JTZXJ2aWNlLnNhdmVTZWxlY3Rpb24oKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBibHVyIGV2ZW50XG4gICAgICovXG4gICAgb25UZXh0QXJlYUJsdXIoZXZlbnQ6IEZvY3VzRXZlbnQpOiB2b2lkIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIHNhdmUgc2VsZWN0aW9uIGlmIGZvY3Vzc2VkIG91dFxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5hc3dFZGl0b3JTZXJ2aWNlLmV4ZWN1dGVJbk5leHRRdWV1ZUl0ZXJhdGlvbih0aGlzLmFzd0VkaXRvclNlcnZpY2Uuc2F2ZVNlbGVjdGlvbik7XG5cbiAgICAgICAgaWYgKHR5cGVvZiB0aGlzLm9uVG91Y2hlZCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgdGhpcy5vblRvdWNoZWQoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChldmVudC5yZWxhdGVkVGFyZ2V0ICE9PSBudWxsKSB7XG4gICAgICAgICAgICBjb25zdCBwYXJlbnQgPSAoZXZlbnQucmVsYXRlZFRhcmdldCBhcyBIVE1MRWxlbWVudCkucGFyZW50RWxlbWVudDtcbiAgICAgICAgICAgIGlmIChwYXJlbnQ/LmNsYXNzTGlzdC5jb250YWlucygnYXN3LWVkaXRvci10b29sYmFyLXNldCcpICYmIHBhcmVudC5jbGFzc0xpc3QuY29udGFpbnMoJ2Fzdy1waWNrZXInKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuYmx1ckV2ZW50LmVtaXQoZXZlbnQpO1xuICAgICAgICAgICAgICAgIHRoaXMuZm9jdXNlZCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogIGZvY3VzIHRoZSB0ZXh0IGFyZWEgd2hlbiB0aGUgZWRpdG9yIGlzIGZvY3VzZWRcbiAgICAgKi9cbiAgICBmb2N1cygpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMubW9kZVZpc3VhbCkge1xuICAgICAgICAgICAgdGhpcy50ZXh0QXJlYS5uYXRpdmVFbGVtZW50LmZvY3VzKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBzb3VyY2VUZXh0ID0gdGhpcy5nZXRDaGlsZEJ5SWQoJ3NvdXJjZVRleHQnICsgdGhpcy5pZCk7XG4gICAgICAgICAgICBzb3VyY2VUZXh0LmZvY3VzKCk7XG4gICAgICAgICAgICB0aGlzLmZvY3VzZWQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRXhlY3V0ZWQgZnJvbSB0aGUgY29udGVudGVkaXRhYmxlIHNlY3Rpb24gd2hpbGUgdGhlIGlucHV0IHByb3BlcnR5IGNoYW5nZXNcbiAgICAgKiBAcGFyYW0gZWxlbWVudCBodG1sIGVsZW1lbnQgZnJvbSBjb250ZW50ZWRpdGFibGVcbiAgICAgKi9cbiAgICBvbkNvbnRlbnRDaGFuZ2UoZWxlbWVudDogYW55KTogdm9pZCB7XG4gICAgICAgIGVsZW1lbnQgPSBlbGVtZW50LnRhcmdldCA/IChlbGVtZW50LnRhcmdldCBhcyBIVE1MRWxlbWVudCkgOiAoZWxlbWVudCBhcyBIVE1MRWxlbWVudCk7XG4gICAgICAgIGxldCBodG1sID0gJyc7XG4gICAgICAgIGlmICh0aGlzLm1vZGVWaXN1YWwpIHtcbiAgICAgICAgICAgIGh0bWwgPSBlbGVtZW50LmlubmVySFRNTDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGh0bWwgPSBlbGVtZW50LmlubmVyVGV4dDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWh0bWwgfHwgaHRtbCA9PT0gJzxicj4nKSB7XG4gICAgICAgICAgICBodG1sID0gJyc7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGVvZiB0aGlzLm9uQ2hhbmdlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICB0aGlzLm9uQ2hhbmdlKHRoaXMuY29uZmlnLnNhbml0aXplIHx8IHRoaXMuY29uZmlnLnNhbml0aXplID09PSB1bmRlZmluZWQgPyB0aGlzLnNhbml0aXplci5zYW5pdGl6ZShTZWN1cml0eUNvbnRleHQuSFRNTCwgaHRtbCkgOiBodG1sKTtcbiAgICAgICAgICAgIGlmICghaHRtbCAhPT0gdGhpcy5zaG93UGxhY2Vob2xkZXIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRvZ2dsZVBsYWNlaG9sZGVyKHRoaXMuc2hvd1BsYWNlaG9sZGVyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNoYW5nZWQgPSB0cnVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqI