@firestitch/html-editor 12.7.5 → 12.7.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/modules/html-editor/classes/plugin.d.ts +7 -7
- package/app/modules/html-editor/components/html-editor/html-editor.component.d.ts +58 -58
- package/app/modules/html-editor/consts/paragraph-buttons.const.d.ts +1 -1
- package/app/modules/html-editor/consts/rich-buttons.const.d.ts +1 -1
- package/app/modules/html-editor/consts/text-buttons.const.d.ts +1 -1
- package/app/modules/html-editor/enums/default-plugin.enum.d.ts +16 -16
- package/app/modules/html-editor/fs-html-editor.module.d.ts +43 -43
- package/app/modules/html-editor/injects/config.inject.d.ts +3 -3
- package/app/modules/html-editor/interfaces/html-editor-config.d.ts +40 -40
- package/app/modules/html-editor/interfaces/plugin-button.d.ts +12 -12
- package/app/modules/html-editor/interfaces/plugin-config.d.ts +5 -5
- package/app/modules/html-editor/plugins/checklist.plugin.d.ts +7 -7
- package/app/modules/html-editor/plugins/code.plugin.d.ts +9 -9
- package/app/modules/html-editor/plugins/configs/mention-plugin.config.d.ts +13 -13
- package/app/modules/html-editor/plugins/configs/screen-record-plugin.config.d.ts +7 -7
- package/app/modules/html-editor/plugins/mention.plugin.d.ts +15 -15
- package/app/modules/html-editor/plugins/realtime.plugin.d.ts +7 -7
- package/app/modules/html-editor/plugins/screen-record.plugin.d.ts +11 -11
- package/app/modules/html-editor/services/froala-loader.service.d.ts +21 -21
- package/app/modules/html-renderer/components/html-renderer/html-renderer.component.d.ts +12 -12
- package/app/modules/html-renderer/fs-html-renderer.module.d.ts +8 -8
- package/bundles/firestitch-html-editor.umd.js +1345 -1345
- package/esm2015/app/modules/html-editor/classes/plugin.js +4 -4
- package/esm2015/app/modules/html-editor/components/html-editor/html-editor.component.js +479 -479
- package/esm2015/app/modules/html-editor/consts/paragraph-buttons.const.js +9 -9
- package/esm2015/app/modules/html-editor/consts/rich-buttons.const.js +6 -6
- package/esm2015/app/modules/html-editor/consts/text-buttons.const.js +18 -18
- package/esm2015/app/modules/html-editor/enums/default-plugin.enum.js +1 -1
- package/esm2015/app/modules/html-editor/fs-html-editor.module.js +68 -68
- package/esm2015/app/modules/html-editor/injects/config.inject.js +3 -3
- package/esm2015/app/modules/html-editor/interfaces/html-editor-config.js +1 -1
- package/esm2015/app/modules/html-editor/interfaces/plugin-button.js +1 -1
- package/esm2015/app/modules/html-editor/interfaces/plugin-config.js +1 -1
- package/esm2015/app/modules/html-editor/plugins/checklist.plugin.js +34 -34
- package/esm2015/app/modules/html-editor/plugins/code.plugin.js +62 -62
- package/esm2015/app/modules/html-editor/plugins/configs/mention-plugin.config.js +1 -1
- package/esm2015/app/modules/html-editor/plugins/configs/screen-record-plugin.config.js +1 -1
- package/esm2015/app/modules/html-editor/plugins/mention.plugin.js +86 -86
- package/esm2015/app/modules/html-editor/plugins/realtime.plugin.js +12 -12
- package/esm2015/app/modules/html-editor/plugins/screen-record.plugin.js +88 -88
- package/esm2015/app/modules/html-editor/services/froala-loader.service.js +89 -89
- package/esm2015/app/modules/html-renderer/components/html-renderer/html-renderer.component.js +28 -28
- package/esm2015/app/modules/html-renderer/fs-html-renderer.module.js +25 -25
- package/esm2015/firestitch-html-editor.js +4 -4
- package/esm2015/public_api.js +13 -13
- package/fesm2015/firestitch-html-editor.js +948 -948
- package/firestitch-html-editor.d.ts +5 -5
- package/package.json +1 -1
- package/public_api.d.ts +18 -18
- package/styles.scss +1 -1
|
@@ -1,480 +1,480 @@
|
|
|
1
|
-
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, forwardRef, HostBinding, Inject, Input, Optional, ViewChild } from '@angular/core';
|
|
2
|
-
import { ControlContainer, NG_VALIDATORS, NG_VALUE_ACCESSOR, NgForm } from '@angular/forms';
|
|
3
|
-
import { guid } from '@firestitch/common';
|
|
4
|
-
import { FileProcessor, FsFile } from '@firestitch/file';
|
|
5
|
-
import { BehaviorSubject, fromEventPattern, ReplaySubject, Subject } from 'rxjs';
|
|
6
|
-
import { distinctUntilChanged, filter, map, skip, startWith, switchMap, takeUntil, tap } from 'rxjs/operators';
|
|
7
|
-
import { merge } from 'lodash-es';
|
|
8
|
-
import { ParagraphButtons } from './../../consts/paragraph-buttons.const';
|
|
9
|
-
import { RichButtons } from './../../consts/rich-buttons.const';
|
|
10
|
-
import { TextButtons } from './../../consts/text-buttons.const';
|
|
11
|
-
import { FS_HTML_EDITOR_CONFIG } from '../../injects/config.inject';
|
|
12
|
-
import { FsFroalaLoaderService } from '../../services/froala-loader.service';
|
|
13
|
-
import * as i0 from "@angular/core";
|
|
14
|
-
import * as i1 from "../../services/froala-loader.service";
|
|
15
|
-
import * as i2 from "@firestitch/label";
|
|
16
|
-
import * as i3 from "@angular/common";
|
|
17
|
-
import * as i4 from "@firestitch/skeleton";
|
|
18
|
-
export class FsHtmlEditorComponent {
|
|
19
|
-
constructor(_defaultConfig, _cdRef, _fr) {
|
|
20
|
-
this._defaultConfig = _defaultConfig;
|
|
21
|
-
this._cdRef = _cdRef;
|
|
22
|
-
this._fr = _fr;
|
|
23
|
-
this.classFocused = false;
|
|
24
|
-
this.config = {};
|
|
25
|
-
this.disabled = false;
|
|
26
|
-
this.initialized = false;
|
|
27
|
-
this.containerID = `fs-html-editor-${guid('xxx')}`;
|
|
28
|
-
this._initialize$ = new ReplaySubject();
|
|
29
|
-
this._froalaReady$ = new BehaviorSubject(null);
|
|
30
|
-
this._destroy$ = new Subject();
|
|
31
|
-
this.onChange = (data) => { };
|
|
32
|
-
this.onTouched = () => { };
|
|
33
|
-
}
|
|
34
|
-
get el() {
|
|
35
|
-
return this.elRef.nativeElement;
|
|
36
|
-
}
|
|
37
|
-
get html() {
|
|
38
|
-
return this._html;
|
|
39
|
-
}
|
|
40
|
-
get editor() {
|
|
41
|
-
return this._editor;
|
|
42
|
-
}
|
|
43
|
-
get froalaLoaded$() {
|
|
44
|
-
return this._fr.loaded$;
|
|
45
|
-
}
|
|
46
|
-
ngOnInit() {
|
|
47
|
-
this.config = this.config || {};
|
|
48
|
-
this.config.autofocus = this.config.autofocus !== false && (!this.config.disabled || !this.disabled);
|
|
49
|
-
this._listenLazyInit();
|
|
50
|
-
}
|
|
51
|
-
ngAfterViewInit() {
|
|
52
|
-
this._initialize$.next();
|
|
53
|
-
}
|
|
54
|
-
hasContent() {
|
|
55
|
-
const el = document.createElement('div');
|
|
56
|
-
if (el.querySelector('img')) {
|
|
57
|
-
return true;
|
|
58
|
-
}
|
|
59
|
-
el.innerHTML = this._html;
|
|
60
|
-
return !!el.innerText.length;
|
|
61
|
-
}
|
|
62
|
-
initialize(options = {}) {
|
|
63
|
-
const config = this._createConfig();
|
|
64
|
-
this._initPlugins(config);
|
|
65
|
-
this._initButtons(config);
|
|
66
|
-
this._editor = new this._fr.FroalaEditor(this.el, this._createOptions(), () => {
|
|
67
|
-
this._froalaReady$.next({ config, options });
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
_processImageUpload(blob) {
|
|
71
|
-
const processor = new FileProcessor();
|
|
72
|
-
const file = new FsFile(blob);
|
|
73
|
-
const config = {
|
|
74
|
-
orientate: true,
|
|
75
|
-
quality: this.config.image.quality,
|
|
76
|
-
format: this.config.image.format,
|
|
77
|
-
maxWidth: this.config.image.width,
|
|
78
|
-
maxHeight: this.config.image.height,
|
|
79
|
-
minWidth: this.config.image.minWidth,
|
|
80
|
-
minHeight: this.config.image.minHeight,
|
|
81
|
-
};
|
|
82
|
-
return processor.processFile(file, config)
|
|
83
|
-
.pipe(switchMap((fsFile) => {
|
|
84
|
-
return this.config.image.upload(fsFile.file);
|
|
85
|
-
}));
|
|
86
|
-
}
|
|
87
|
-
updateSize() {
|
|
88
|
-
// Hack: To trigger the toolbar button size modes
|
|
89
|
-
window.dispatchEvent(new Event('resize'));
|
|
90
|
-
}
|
|
91
|
-
validate(control) {
|
|
92
|
-
const err = {};
|
|
93
|
-
if (this.config.maxLength && this._html) {
|
|
94
|
-
const maxLength = this.config.maxLength;
|
|
95
|
-
const length = this._html.length;
|
|
96
|
-
if (length > maxLength) {
|
|
97
|
-
err.maxLengthError = `Must be ${maxLength} characters or fewer. You entered ${length} characters.`;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
return Object.keys(err).length ? err : null;
|
|
101
|
-
}
|
|
102
|
-
focus(options) {
|
|
103
|
-
options = options ? options : {};
|
|
104
|
-
if (options.cursorPosition === 'end') {
|
|
105
|
-
this.editor.selection.setAtEnd(this.editor.$el.get(0));
|
|
106
|
-
}
|
|
107
|
-
else {
|
|
108
|
-
this.editor.selection.setAtStart(this.editor.$el.get(0));
|
|
109
|
-
}
|
|
110
|
-
this.editor.selection.restore();
|
|
111
|
-
const elSelection = this.editor.selection.element();
|
|
112
|
-
if (elSelection) {
|
|
113
|
-
elSelection.scrollIntoView({ block: 'center' });
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
clear() {
|
|
117
|
-
this.writeValue('');
|
|
118
|
-
}
|
|
119
|
-
disable() {
|
|
120
|
-
this.disabled = true;
|
|
121
|
-
}
|
|
122
|
-
setHtml(html) {
|
|
123
|
-
this.writeValue(html);
|
|
124
|
-
}
|
|
125
|
-
writeValue(html) {
|
|
126
|
-
this._html = html || '';
|
|
127
|
-
if (Array.isArray(this._html)) {
|
|
128
|
-
this._html = this._html.pop();
|
|
129
|
-
}
|
|
130
|
-
this._html = this._html
|
|
131
|
-
.replace(/<(li)>\s?<(div)>/g, '<li>')
|
|
132
|
-
.replace(/<\/(div)><\/(li)>/g, '</li>');
|
|
133
|
-
if (this.editor && this.editor.html) {
|
|
134
|
-
try {
|
|
135
|
-
this.editor.html.set(this._html);
|
|
136
|
-
}
|
|
137
|
-
catch (e) {
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
this._cdRef.markForCheck();
|
|
141
|
-
}
|
|
142
|
-
registerOnChange(fn) {
|
|
143
|
-
this.onChange = fn;
|
|
144
|
-
}
|
|
145
|
-
registerOnTouched(fn) {
|
|
146
|
-
this.onTouched = fn;
|
|
147
|
-
}
|
|
148
|
-
ngOnDestroy() {
|
|
149
|
-
this._initialize$.complete();
|
|
150
|
-
this._destroy$.next();
|
|
151
|
-
this._destroy$.complete();
|
|
152
|
-
this.destroy();
|
|
153
|
-
}
|
|
154
|
-
destroy() {
|
|
155
|
-
if (this.editor) {
|
|
156
|
-
this.editor.destroy();
|
|
157
|
-
}
|
|
158
|
-
this.initialized = false;
|
|
159
|
-
this._cdRef.markForCheck();
|
|
160
|
-
this.el.innerHTML = '';
|
|
161
|
-
}
|
|
162
|
-
_createConfig() {
|
|
163
|
-
return merge({ froalaConfig: {} }, this._defaultConfig, this.config);
|
|
164
|
-
}
|
|
165
|
-
_change(html) {
|
|
166
|
-
this._html = html;
|
|
167
|
-
this.onChange(html);
|
|
168
|
-
}
|
|
169
|
-
_initButtons(config) {
|
|
170
|
-
(config.buttons || [])
|
|
171
|
-
.forEach((button) => {
|
|
172
|
-
/*
|
|
173
|
-
Svg Keys:
|
|
174
|
-
["add", "advancedImageEditor", "alignCenter", "alignJustify", "alignLeft", "alignRight",
|
|
175
|
-
"anchors", "back", "backgroundColor", "blockquote", "bold", "cellBackground",
|
|
176
|
-
"cellBorderColor", "cellOptions", "cellStyle", "clearFormatting", "close", "codeView",
|
|
177
|
-
"cogs", "columns", "editLink", "exitFullscreen", "fontAwesome", "fontFamily",
|
|
178
|
-
"fontSize", "fullscreen", "help", "horizontalLine", "imageAltText", "imageCaption",
|
|
179
|
-
"imageClass", "imageDisplay", "imageManager", "imageSize", "indent", "inlineClass",
|
|
180
|
-
"inlineStyle", "insertEmbed", "insertFile", "insertImage", "insertLink", "insertMore",
|
|
181
|
-
"insertTable", "insertVideo", "upload", "italic", "search", "lineHeight", "linkStyles",
|
|
182
|
-
"mention", "more", "openLink", "orderedList", "outdent", "pageBreaker",
|
|
183
|
-
"paragraphFormat", "paragraphMore", "paragraphStyle", "pdfExport", "print",
|
|
184
|
-
"redo", "removeTable", "remove", "replaceImage", "row", "selectAll", "smile",
|
|
185
|
-
"spellcheck", "star", "strikeThrough", "subscript", "superscript", "symbols", "tags",
|
|
186
|
-
"tableHeader", "tableStyle", "textColor", "textMore", "underline", "undo", "unlink",
|
|
187
|
-
"unorderedList", "verticalAlignBottom", "verticalAlignMiddle", "verticalAlignTop"]
|
|
188
|
-
*/
|
|
189
|
-
var _a, _b, _c;
|
|
190
|
-
if (button.svgKey) {
|
|
191
|
-
this._fr.FroalaEditor.DefineIcon(button.name, { SVG_KEY: button.svgKey });
|
|
192
|
-
}
|
|
193
|
-
this._fr.FroalaEditor.RegisterCommand(button.name, {
|
|
194
|
-
title: button.title,
|
|
195
|
-
focus: (_a = button.focus) !== null && _a !== void 0 ? _a : true,
|
|
196
|
-
undo: (_b = button.undo) !== null && _b !== void 0 ? _b : true,
|
|
197
|
-
refreshAfterCallback: (_c = button.refreshAfterCallback) !== null && _c !== void 0 ? _c : true,
|
|
198
|
-
callback: function () {
|
|
199
|
-
button.click(this);
|
|
200
|
-
}
|
|
201
|
-
});
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
_initPlugins(config) {
|
|
205
|
-
(config.plugins || []).forEach((plugin) => {
|
|
206
|
-
this._fr.FroalaEditor.PLUGINS[plugin.config.name] = function (editor) {
|
|
207
|
-
plugin.editor = editor;
|
|
208
|
-
plugin.initialize();
|
|
209
|
-
return plugin;
|
|
210
|
-
};
|
|
211
|
-
(plugin.config.buttons || []).forEach((button) => {
|
|
212
|
-
this._fr.FroalaEditor.DefineIcon(button.name, {
|
|
213
|
-
NAME: button.name,
|
|
214
|
-
PATH: button.svgPath,
|
|
215
|
-
});
|
|
216
|
-
this._fr.FroalaEditor.RegisterCommand(button.name, {
|
|
217
|
-
icon: button.name,
|
|
218
|
-
title: button.tooltip,
|
|
219
|
-
undo: button.undo,
|
|
220
|
-
focus: button.focus,
|
|
221
|
-
showOnMobile: button.showOnMobile,
|
|
222
|
-
refreshAfterCallback: button.refreshAfterCallback,
|
|
223
|
-
callback: function () {
|
|
224
|
-
if (button.click) {
|
|
225
|
-
button.click(this);
|
|
226
|
-
}
|
|
227
|
-
},
|
|
228
|
-
refresh: function (button) {
|
|
229
|
-
if (button.refresh) {
|
|
230
|
-
button.refresh(this, button);
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
});
|
|
234
|
-
});
|
|
235
|
-
});
|
|
236
|
-
}
|
|
237
|
-
_createOptions() {
|
|
238
|
-
var _a, _b;
|
|
239
|
-
const config = this._createConfig();
|
|
240
|
-
return merge(
|
|
241
|
-
// For some reason editor store somewhere pointer on default config object and dublicate options each time on init
|
|
242
|
-
// Extra merge level fixed this problem and allow to init config properly without legacy data
|
|
243
|
-
{}, {
|
|
244
|
-
shortcutsEnabled: ['show', 'bold', 'italic', 'underline', 'indent', 'outdent', 'undo', 'redo', 'insertImage', 'createLink'],
|
|
245
|
-
key: config.activationKey,
|
|
246
|
-
placeholderText: config.placeholder,
|
|
247
|
-
linkAlwaysBlank: true,
|
|
248
|
-
tabSpaces: 2,
|
|
249
|
-
typingTimer: 250,
|
|
250
|
-
tooltips: false,
|
|
251
|
-
wordPasteModal: false,
|
|
252
|
-
imageDefaultWidth: 0,
|
|
253
|
-
imageDefaultAlign: 'left',
|
|
254
|
-
quickInsertEnabled: false,
|
|
255
|
-
scrollableContainer: `#${this.containerID}`,
|
|
256
|
-
paragraphDefaultSelection: 'Format',
|
|
257
|
-
videoUpload: false,
|
|
258
|
-
imagePaste: !!((_a = config.image) === null || _a === void 0 ? void 0 : _a.upload),
|
|
259
|
-
imageUpload: !!((_b = config.image) === null || _b === void 0 ? void 0 : _b.upload),
|
|
260
|
-
paragraphFormat: {
|
|
261
|
-
N: 'Normal',
|
|
262
|
-
H1: 'Heading 1',
|
|
263
|
-
H2: 'Heading 2',
|
|
264
|
-
H3: 'Heading 3',
|
|
265
|
-
H4: 'Heading 4',
|
|
266
|
-
BLOCKQUOTE: 'Quote',
|
|
267
|
-
},
|
|
268
|
-
lineHeights: {
|
|
269
|
-
Default: '',
|
|
270
|
-
'0.5': '0.5',
|
|
271
|
-
'Single': '1',
|
|
272
|
-
'1.15': '1.15',
|
|
273
|
-
'1.5': '1.5',
|
|
274
|
-
'Double': '2'
|
|
275
|
-
},
|
|
276
|
-
paragraphFormatSelection: true,
|
|
277
|
-
toolbarButtonsXS: {
|
|
278
|
-
moreText: {
|
|
279
|
-
buttons: TextButtons,
|
|
280
|
-
buttonsVisible: 1,
|
|
281
|
-
},
|
|
282
|
-
moreParagraph: {
|
|
283
|
-
buttons: ParagraphButtons,
|
|
284
|
-
buttonsVisible: 2,
|
|
285
|
-
},
|
|
286
|
-
moreRich: {
|
|
287
|
-
buttons: RichButtons,
|
|
288
|
-
buttonsVisible: 0,
|
|
289
|
-
},
|
|
290
|
-
},
|
|
291
|
-
toolbarButtons: {
|
|
292
|
-
moreText: {
|
|
293
|
-
buttons: TextButtons,
|
|
294
|
-
buttonsVisible: 3,
|
|
295
|
-
},
|
|
296
|
-
moreParagraph: {
|
|
297
|
-
buttons: ParagraphButtons,
|
|
298
|
-
buttonsVisible: 5,
|
|
299
|
-
},
|
|
300
|
-
moreRich: {
|
|
301
|
-
buttons: RichButtons,
|
|
302
|
-
buttonsVisible: 3,
|
|
303
|
-
},
|
|
304
|
-
},
|
|
305
|
-
}, config.froalaConfig);
|
|
306
|
-
}
|
|
307
|
-
_listenLazyInit() {
|
|
308
|
-
this.froalaLoaded$
|
|
309
|
-
.pipe(filter((ready) => ready), switchMap(() => this._initialize$), tap(() => {
|
|
310
|
-
const selection = window.getSelection();
|
|
311
|
-
const options = {};
|
|
312
|
-
if (selection.baseNode) {
|
|
313
|
-
options.selection = {
|
|
314
|
-
node: selection.baseNode.nodeValue,
|
|
315
|
-
offset: selection.baseOffset,
|
|
316
|
-
};
|
|
317
|
-
}
|
|
318
|
-
this.initialize(options);
|
|
319
|
-
}), switchMap(() => this._froalaReady$), filter((data) => !!data), tap(({ config, options }) => {
|
|
320
|
-
this._setupFroala(config, options);
|
|
321
|
-
}))
|
|
322
|
-
.subscribe();
|
|
323
|
-
}
|
|
324
|
-
_contentChanged() {
|
|
325
|
-
const editorHTML = this._editor.html.get();
|
|
326
|
-
if (this.html !== editorHTML) {
|
|
327
|
-
this._change(editorHTML);
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
_setupFroala(config, options) {
|
|
331
|
-
this._cdRef.markForCheck();
|
|
332
|
-
this.setHtml(this._html);
|
|
333
|
-
if (config.disabled) {
|
|
334
|
-
this.disable();
|
|
335
|
-
}
|
|
336
|
-
if (config.froalaConfig.events) {
|
|
337
|
-
if (config.froalaConfig.events.initialized) {
|
|
338
|
-
config.froalaConfig.events.initialized();
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
this._editor.events.on('focus', () => {
|
|
342
|
-
this.classFocused = true;
|
|
343
|
-
this._cdRef.markForCheck();
|
|
344
|
-
});
|
|
345
|
-
this._editor.events.on('blur', () => {
|
|
346
|
-
this.classFocused = false;
|
|
347
|
-
this._cdRef.markForCheck();
|
|
348
|
-
});
|
|
349
|
-
this._editor.events.on('click', () => {
|
|
350
|
-
if (this.config.initOnClick && !this.initialized) {
|
|
351
|
-
this.initialized = true;
|
|
352
|
-
this._cdRef.markForCheck();
|
|
353
|
-
}
|
|
354
|
-
});
|
|
355
|
-
fromEventPattern((handler) => {
|
|
356
|
-
this._editor.events.on('contentChanged', handler);
|
|
357
|
-
}, () => { })
|
|
358
|
-
.pipe(startWith(this._html), map(() => this.editor.html.get()), distinctUntilChanged(), skip(1))
|
|
359
|
-
.subscribe(() => {
|
|
360
|
-
this._contentChanged();
|
|
361
|
-
});
|
|
362
|
-
this._editor.events.on('paste.afterCleanup', (html) => {
|
|
363
|
-
var div = document.createElement('div');
|
|
364
|
-
div.innerHTML = html;
|
|
365
|
-
div.querySelectorAll('*')
|
|
366
|
-
.forEach((el) => {
|
|
367
|
-
for (var i = 0; i < el.attributes.length; i++) {
|
|
368
|
-
const name = el.attributes[0].name;
|
|
369
|
-
if (name !== 'href') {
|
|
370
|
-
el.removeAttribute(name);
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
});
|
|
374
|
-
return div.innerHTML;
|
|
375
|
-
});
|
|
376
|
-
this._editor.events.on('keydown', () => {
|
|
377
|
-
this.onTouched();
|
|
378
|
-
});
|
|
379
|
-
if (this.config.image && this.config.image.upload) {
|
|
380
|
-
this._editor.events.on('image.beforePasteUpload', (image) => {
|
|
381
|
-
fetch(image.getAttribute('src'))
|
|
382
|
-
.then((res) => {
|
|
383
|
-
res.blob()
|
|
384
|
-
.then((blob) => {
|
|
385
|
-
this._processImageUpload(blob)
|
|
386
|
-
.pipe(takeUntil(this._destroy$))
|
|
387
|
-
.subscribe((url) => {
|
|
388
|
-
image.setAttribute('src', url);
|
|
389
|
-
image.removeAttribute('data-fr-image-pasted');
|
|
390
|
-
this._contentChanged();
|
|
391
|
-
});
|
|
392
|
-
});
|
|
393
|
-
});
|
|
394
|
-
return false;
|
|
395
|
-
});
|
|
396
|
-
this._editor.events.on('image.beforeUpload', (blobs) => {
|
|
397
|
-
this._processImageUpload(blobs[0])
|
|
398
|
-
.pipe(takeUntil(this._destroy$))
|
|
399
|
-
.subscribe((url) => {
|
|
400
|
-
this.editor.image.insert(url, null, null, this.editor.image.get());
|
|
401
|
-
});
|
|
402
|
-
return false;
|
|
403
|
-
});
|
|
404
|
-
}
|
|
405
|
-
if (this.el.querySelector('.fr-second-toolbar')) {
|
|
406
|
-
this.el.querySelector('.fr-second-toolbar').remove();
|
|
407
|
-
}
|
|
408
|
-
if (this.config.autofocus && !this.config.initOnClick) {
|
|
409
|
-
this.focus();
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
FsHtmlEditorComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: FsHtmlEditorComponent, deps: [{ token: FS_HTML_EDITOR_CONFIG, optional: true }, { token: i0.ChangeDetectorRef }, { token: i1.FsFroalaLoaderService }], target: i0.ɵɵFactoryTarget.Component });
|
|
414
|
-
FsHtmlEditorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.16", type: FsHtmlEditorComponent, selector: "fs-html-editor", inputs: { config: "config", hint: "hint", disabled: "disabled" }, host: { properties: { "class.focused": "this.classFocused", "class.disabled": "this.disabled" } }, providers: [
|
|
415
|
-
{
|
|
416
|
-
provide: NG_VALUE_ACCESSOR,
|
|
417
|
-
useExisting: forwardRef(() => FsHtmlEditorComponent),
|
|
418
|
-
multi: true
|
|
419
|
-
},
|
|
420
|
-
{
|
|
421
|
-
provide: NG_VALIDATORS,
|
|
422
|
-
useExisting: forwardRef(() => FsHtmlEditorComponent),
|
|
423
|
-
multi: true
|
|
424
|
-
},
|
|
425
|
-
], viewQueries: [{ propertyName: "elRef", first: true, predicate: ["elRef"], descendants: true }], ngImport: i0, template: "<fs-label-field>\n <fs-label *ngIf=\"config.label\">{{config.label}}</fs-label>\n <div\n class=\"html-editor-container fs-html-editor-default\"\n [id]=\"containerID\"\n [ngClass]=\"{\n initialized: initialized,\n 'init-on-click': config.initOnClick\n }\">\n <ng-container *fsSkeleton=\"(froalaLoaded$ | async) !== false\"></ng-container>\n <div #elRef></div>\n\n <div class=\"bottom-line\"></div>\n <div class=\"disabled-line\"></div>\n </div>\n\n <fs-label-message>\n <div class=\"fs-form-message\">\n <div class=\"fs-form-hint\">{{hint}}</div>\n </div>\n </fs-label-message>\n</fs-label-field>\n", styles: [":host ::ng-deep .fr-box.fr-basic .fr-wrapper{border:0;border-bottom:1px solid #949494;margin-bottom:1px;background-color:transparent}:host ::ng-deep .fr-box.fr-basic .fr-element{padding:0;font-family:inherit;color:inherit;font-size:inherit;line-height:inherit;min-height:auto}:host ::ng-deep .fr-more-toolbar,:host ::ng-deep .fr-toolbar,:host ::ng-deep .fr-dropdown:after,:host ::ng-deep .fr-dropdown-menu .fr-dropdown-wrapper{transition:none!important}:host ::ng-deep .fr-toolbar-open .fr-more-toolbar{display:block}:host ::ng-deep .fr-more-toolbar{display:none}:host ::ng-deep .fr-toolbar.fr-top{position:sticky;z-index:2;border-radius:0;background-color:#fff}:host ::ng-deep .fr-toolbar.fr-top .fr-btn-grp{margin:0 20px 0 0}:host ::ng-deep .fr-toolbar.fr-top .fr-btn-grp:nth-child(1):after,:host ::ng-deep .fr-toolbar.fr-top .fr-btn-grp:nth-child(2):after{content:\"\";position:absolute;top:9px;height:30px;border-left:1px solid #e5e5e5;margin-left:10px}:host ::ng-deep .fr-toolbar.fr-top div:first-of-type:before{border:none}:host ::ng-deep .fr-toolbar.fr-top.fr-toolbar-open .fr-newline{height:auto}:host ::ng-deep .fr-toolbar.fr-top .fr-btn-grp:first-child{margin-left:0}:host ::ng-deep .fr-toolbar.fr-top.fr-top{border:0}:host ::ng-deep .fr-toolbar.fr-top .fr-newline{margin:0}:host ::ng-deep .fr-toolbar.fr-top .fr-more-toolbar{z-index:auto;display:flex;justify-content:center;padding-left:0!important}:host ::ng-deep .fr-toolbar.fr-top .fr-command.fr-btn{z-index:auto}:host ::ng-deep .fr-toolbar.fr-top .fr-command.fr-btn.fr-dropdown:after{right:3px}:host ::ng-deep .fr-toolbar.fr-top .fr-command.fr-btn.fr-dropdown.fr-selection span{margin-right:24px}:host ::ng-deep .fr-toolbar.fr-top .fr-command.fr-btn.fr-open{border-radius:4px;margin:4px 2px}:host ::ng-deep .fr-view ol,:host ::ng-deep .fr-view ul{list-style-position:unset}:host ::ng-deep .html-editor-container.init-on-click:not(.initialized) .fr-toolbar{display:none}:host.disabled ::ng-deep .fr-box.fr-basic{opacity:.5;pointer-events:none}:host.disabled ::ng-deep .fr-box.fr-basic .fr-wrapper{border:none}:host.disabled ::ng-deep .disabled-line{display:block}::ng-deep .fr-popup{z-index:1001!important}::ng-deep .fr-video-by-url-layer .fr-checkbox-line{display:none}.disabled-line{display:none;position:absolute;bottom:-1px;z-index:1;background-image:linear-gradient(90deg,rgba(0,0,0,.42) 0,rgba(0,0,0,.42) 33%,transparent 0);background-size:4px 100%;background-repeat:repeat-x;height:1px;width:100%}.bottom-line{opacity:0;transform-origin:50%;transform:scaleX(.5);transition:background-color .3s cubic-bezier(.55,0,.55,.2);width:100%;border-bottom:2px solid #949494;position:absolute;bottom:-1px;z-index:1}:host{position:relative;display:block}:host.focused .bottom-line{opacity:1;display:block;transform:scaleX(1);transition:transform .3s cubic-bezier(.25,.8,.25,1),opacity .1s cubic-bezier(.25,.8,.25,1),background-color .3s cubic-bezier(.25,.8,.25,1)}::ng-deep .fs-html-editor-mention-container{position:absolute;top:0;left:0;height:auto;max-height:300px;max-width:500px;overflow:auto;display:block;z-index:999999;box-shadow:0 2px 4px -1px #0003,0 4px 5px #00000024,0 1px 10px #0000001f;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background:#fff}::ng-deep .fs-html-editor-mention-container ul{margin:0;padding:0;list-style:none}::ng-deep .fs-html-editor-mention-container li{padding:0 16px;cursor:pointer;line-height:48px}::ng-deep .fs-html-editor-mention-container li.highlight,::ng-deep .fs-html-editor-mention-container li:hover{background:#F5F5F5}::ng-deep .fs-html-editor-mention-container li.no-match{cursor:default}\n"], components: [{ type: i2.FsLabelFieldComponent, selector: "fs-label-field", inputs: ["bottomMargin", "topMargin", "labelMargin"] }, { type: i2.FsLabelComponent, selector: "fs-label" }, { type: i2.FsLabelMessageComponent, selector: "fs-label-message" }], directives: [{ type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i4.FsSkeletonContentDirective, selector: "[fsSkeleton]", inputs: ["fsSkeleton", "fsSkeletonPattern"] }], pipes: { "async": i3.AsyncPipe }, viewProviders: [
|
|
426
|
-
{
|
|
427
|
-
provide: ControlContainer,
|
|
428
|
-
deps: [[Optional, NgForm]],
|
|
429
|
-
useFactory: (ngForm) => ngForm,
|
|
430
|
-
},
|
|
431
|
-
], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
432
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: FsHtmlEditorComponent, decorators: [{
|
|
433
|
-
type: Component,
|
|
434
|
-
args: [{
|
|
435
|
-
selector: 'fs-html-editor',
|
|
436
|
-
templateUrl: 'html-editor.component.html',
|
|
437
|
-
styleUrls: ['html-editor.component.scss'],
|
|
438
|
-
providers: [
|
|
439
|
-
{
|
|
440
|
-
provide: NG_VALUE_ACCESSOR,
|
|
441
|
-
useExisting: forwardRef(() => FsHtmlEditorComponent),
|
|
442
|
-
multi: true
|
|
443
|
-
},
|
|
444
|
-
{
|
|
445
|
-
provide: NG_VALIDATORS,
|
|
446
|
-
useExisting: forwardRef(() => FsHtmlEditorComponent),
|
|
447
|
-
multi: true
|
|
448
|
-
},
|
|
449
|
-
],
|
|
450
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
451
|
-
viewProviders: [
|
|
452
|
-
{
|
|
453
|
-
provide: ControlContainer,
|
|
454
|
-
deps: [[Optional, NgForm]],
|
|
455
|
-
useFactory: (ngForm) => ngForm,
|
|
456
|
-
},
|
|
457
|
-
],
|
|
458
|
-
}]
|
|
459
|
-
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
|
|
460
|
-
type: Optional
|
|
461
|
-
}, {
|
|
462
|
-
type: Inject,
|
|
463
|
-
args: [FS_HTML_EDITOR_CONFIG]
|
|
464
|
-
}] }, { type: i0.ChangeDetectorRef }, { type: i1.FsFroalaLoaderService }]; }, propDecorators: { classFocused: [{
|
|
465
|
-
type: HostBinding,
|
|
466
|
-
args: ['class.focused']
|
|
467
|
-
}], elRef: [{
|
|
468
|
-
type: ViewChild,
|
|
469
|
-
args: ['elRef']
|
|
470
|
-
}], config: [{
|
|
471
|
-
type: Input
|
|
472
|
-
}], hint: [{
|
|
473
|
-
type: Input
|
|
474
|
-
}], disabled: [{
|
|
475
|
-
type: Input
|
|
476
|
-
}, {
|
|
477
|
-
type: HostBinding,
|
|
478
|
-
args: ['class.disabled']
|
|
479
|
-
}] } });
|
|
1
|
+
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, forwardRef, HostBinding, Inject, Input, Optional, ViewChild } from '@angular/core';
|
|
2
|
+
import { ControlContainer, NG_VALIDATORS, NG_VALUE_ACCESSOR, NgForm } from '@angular/forms';
|
|
3
|
+
import { guid } from '@firestitch/common';
|
|
4
|
+
import { FileProcessor, FsFile } from '@firestitch/file';
|
|
5
|
+
import { BehaviorSubject, fromEventPattern, ReplaySubject, Subject } from 'rxjs';
|
|
6
|
+
import { distinctUntilChanged, filter, map, skip, startWith, switchMap, takeUntil, tap } from 'rxjs/operators';
|
|
7
|
+
import { merge } from 'lodash-es';
|
|
8
|
+
import { ParagraphButtons } from './../../consts/paragraph-buttons.const';
|
|
9
|
+
import { RichButtons } from './../../consts/rich-buttons.const';
|
|
10
|
+
import { TextButtons } from './../../consts/text-buttons.const';
|
|
11
|
+
import { FS_HTML_EDITOR_CONFIG } from '../../injects/config.inject';
|
|
12
|
+
import { FsFroalaLoaderService } from '../../services/froala-loader.service';
|
|
13
|
+
import * as i0 from "@angular/core";
|
|
14
|
+
import * as i1 from "../../services/froala-loader.service";
|
|
15
|
+
import * as i2 from "@firestitch/label";
|
|
16
|
+
import * as i3 from "@angular/common";
|
|
17
|
+
import * as i4 from "@firestitch/skeleton";
|
|
18
|
+
export class FsHtmlEditorComponent {
|
|
19
|
+
constructor(_defaultConfig, _cdRef, _fr) {
|
|
20
|
+
this._defaultConfig = _defaultConfig;
|
|
21
|
+
this._cdRef = _cdRef;
|
|
22
|
+
this._fr = _fr;
|
|
23
|
+
this.classFocused = false;
|
|
24
|
+
this.config = {};
|
|
25
|
+
this.disabled = false;
|
|
26
|
+
this.initialized = false;
|
|
27
|
+
this.containerID = `fs-html-editor-${guid('xxx')}`;
|
|
28
|
+
this._initialize$ = new ReplaySubject();
|
|
29
|
+
this._froalaReady$ = new BehaviorSubject(null);
|
|
30
|
+
this._destroy$ = new Subject();
|
|
31
|
+
this.onChange = (data) => { };
|
|
32
|
+
this.onTouched = () => { };
|
|
33
|
+
}
|
|
34
|
+
get el() {
|
|
35
|
+
return this.elRef.nativeElement;
|
|
36
|
+
}
|
|
37
|
+
get html() {
|
|
38
|
+
return this._html;
|
|
39
|
+
}
|
|
40
|
+
get editor() {
|
|
41
|
+
return this._editor;
|
|
42
|
+
}
|
|
43
|
+
get froalaLoaded$() {
|
|
44
|
+
return this._fr.loaded$;
|
|
45
|
+
}
|
|
46
|
+
ngOnInit() {
|
|
47
|
+
this.config = this.config || {};
|
|
48
|
+
this.config.autofocus = this.config.autofocus !== false && (!this.config.disabled || !this.disabled);
|
|
49
|
+
this._listenLazyInit();
|
|
50
|
+
}
|
|
51
|
+
ngAfterViewInit() {
|
|
52
|
+
this._initialize$.next();
|
|
53
|
+
}
|
|
54
|
+
hasContent() {
|
|
55
|
+
const el = document.createElement('div');
|
|
56
|
+
if (el.querySelector('img')) {
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
el.innerHTML = this._html;
|
|
60
|
+
return !!el.innerText.length;
|
|
61
|
+
}
|
|
62
|
+
initialize(options = {}) {
|
|
63
|
+
const config = this._createConfig();
|
|
64
|
+
this._initPlugins(config);
|
|
65
|
+
this._initButtons(config);
|
|
66
|
+
this._editor = new this._fr.FroalaEditor(this.el, this._createOptions(), () => {
|
|
67
|
+
this._froalaReady$.next({ config, options });
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
_processImageUpload(blob) {
|
|
71
|
+
const processor = new FileProcessor();
|
|
72
|
+
const file = new FsFile(blob);
|
|
73
|
+
const config = {
|
|
74
|
+
orientate: true,
|
|
75
|
+
quality: this.config.image.quality,
|
|
76
|
+
format: this.config.image.format,
|
|
77
|
+
maxWidth: this.config.image.width,
|
|
78
|
+
maxHeight: this.config.image.height,
|
|
79
|
+
minWidth: this.config.image.minWidth,
|
|
80
|
+
minHeight: this.config.image.minHeight,
|
|
81
|
+
};
|
|
82
|
+
return processor.processFile(file, config)
|
|
83
|
+
.pipe(switchMap((fsFile) => {
|
|
84
|
+
return this.config.image.upload(fsFile.file);
|
|
85
|
+
}));
|
|
86
|
+
}
|
|
87
|
+
updateSize() {
|
|
88
|
+
// Hack: To trigger the toolbar button size modes
|
|
89
|
+
window.dispatchEvent(new Event('resize'));
|
|
90
|
+
}
|
|
91
|
+
validate(control) {
|
|
92
|
+
const err = {};
|
|
93
|
+
if (this.config.maxLength && this._html) {
|
|
94
|
+
const maxLength = this.config.maxLength;
|
|
95
|
+
const length = this._html.length;
|
|
96
|
+
if (length > maxLength) {
|
|
97
|
+
err.maxLengthError = `Must be ${maxLength} characters or fewer. You entered ${length} characters.`;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return Object.keys(err).length ? err : null;
|
|
101
|
+
}
|
|
102
|
+
focus(options) {
|
|
103
|
+
options = options ? options : {};
|
|
104
|
+
if (options.cursorPosition === 'end') {
|
|
105
|
+
this.editor.selection.setAtEnd(this.editor.$el.get(0));
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
this.editor.selection.setAtStart(this.editor.$el.get(0));
|
|
109
|
+
}
|
|
110
|
+
this.editor.selection.restore();
|
|
111
|
+
const elSelection = this.editor.selection.element();
|
|
112
|
+
if (elSelection) {
|
|
113
|
+
elSelection.scrollIntoView({ block: 'center' });
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
clear() {
|
|
117
|
+
this.writeValue('');
|
|
118
|
+
}
|
|
119
|
+
disable() {
|
|
120
|
+
this.disabled = true;
|
|
121
|
+
}
|
|
122
|
+
setHtml(html) {
|
|
123
|
+
this.writeValue(html);
|
|
124
|
+
}
|
|
125
|
+
writeValue(html) {
|
|
126
|
+
this._html = html || '';
|
|
127
|
+
if (Array.isArray(this._html)) {
|
|
128
|
+
this._html = this._html.pop();
|
|
129
|
+
}
|
|
130
|
+
this._html = this._html
|
|
131
|
+
.replace(/<(li)>\s?<(div)>/g, '<li>')
|
|
132
|
+
.replace(/<\/(div)><\/(li)>/g, '</li>');
|
|
133
|
+
if (this.editor && this.editor.html) {
|
|
134
|
+
try {
|
|
135
|
+
this.editor.html.set(this._html);
|
|
136
|
+
}
|
|
137
|
+
catch (e) {
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
this._cdRef.markForCheck();
|
|
141
|
+
}
|
|
142
|
+
registerOnChange(fn) {
|
|
143
|
+
this.onChange = fn;
|
|
144
|
+
}
|
|
145
|
+
registerOnTouched(fn) {
|
|
146
|
+
this.onTouched = fn;
|
|
147
|
+
}
|
|
148
|
+
ngOnDestroy() {
|
|
149
|
+
this._initialize$.complete();
|
|
150
|
+
this._destroy$.next();
|
|
151
|
+
this._destroy$.complete();
|
|
152
|
+
this.destroy();
|
|
153
|
+
}
|
|
154
|
+
destroy() {
|
|
155
|
+
if (this.editor) {
|
|
156
|
+
this.editor.destroy();
|
|
157
|
+
}
|
|
158
|
+
this.initialized = false;
|
|
159
|
+
this._cdRef.markForCheck();
|
|
160
|
+
this.el.innerHTML = '';
|
|
161
|
+
}
|
|
162
|
+
_createConfig() {
|
|
163
|
+
return merge({ froalaConfig: {} }, this._defaultConfig, this.config);
|
|
164
|
+
}
|
|
165
|
+
_change(html) {
|
|
166
|
+
this._html = html;
|
|
167
|
+
this.onChange(html);
|
|
168
|
+
}
|
|
169
|
+
_initButtons(config) {
|
|
170
|
+
(config.buttons || [])
|
|
171
|
+
.forEach((button) => {
|
|
172
|
+
/*
|
|
173
|
+
Svg Keys:
|
|
174
|
+
["add", "advancedImageEditor", "alignCenter", "alignJustify", "alignLeft", "alignRight",
|
|
175
|
+
"anchors", "back", "backgroundColor", "blockquote", "bold", "cellBackground",
|
|
176
|
+
"cellBorderColor", "cellOptions", "cellStyle", "clearFormatting", "close", "codeView",
|
|
177
|
+
"cogs", "columns", "editLink", "exitFullscreen", "fontAwesome", "fontFamily",
|
|
178
|
+
"fontSize", "fullscreen", "help", "horizontalLine", "imageAltText", "imageCaption",
|
|
179
|
+
"imageClass", "imageDisplay", "imageManager", "imageSize", "indent", "inlineClass",
|
|
180
|
+
"inlineStyle", "insertEmbed", "insertFile", "insertImage", "insertLink", "insertMore",
|
|
181
|
+
"insertTable", "insertVideo", "upload", "italic", "search", "lineHeight", "linkStyles",
|
|
182
|
+
"mention", "more", "openLink", "orderedList", "outdent", "pageBreaker",
|
|
183
|
+
"paragraphFormat", "paragraphMore", "paragraphStyle", "pdfExport", "print",
|
|
184
|
+
"redo", "removeTable", "remove", "replaceImage", "row", "selectAll", "smile",
|
|
185
|
+
"spellcheck", "star", "strikeThrough", "subscript", "superscript", "symbols", "tags",
|
|
186
|
+
"tableHeader", "tableStyle", "textColor", "textMore", "underline", "undo", "unlink",
|
|
187
|
+
"unorderedList", "verticalAlignBottom", "verticalAlignMiddle", "verticalAlignTop"]
|
|
188
|
+
*/
|
|
189
|
+
var _a, _b, _c;
|
|
190
|
+
if (button.svgKey) {
|
|
191
|
+
this._fr.FroalaEditor.DefineIcon(button.name, { SVG_KEY: button.svgKey });
|
|
192
|
+
}
|
|
193
|
+
this._fr.FroalaEditor.RegisterCommand(button.name, {
|
|
194
|
+
title: button.title,
|
|
195
|
+
focus: (_a = button.focus) !== null && _a !== void 0 ? _a : true,
|
|
196
|
+
undo: (_b = button.undo) !== null && _b !== void 0 ? _b : true,
|
|
197
|
+
refreshAfterCallback: (_c = button.refreshAfterCallback) !== null && _c !== void 0 ? _c : true,
|
|
198
|
+
callback: function () {
|
|
199
|
+
button.click(this);
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
_initPlugins(config) {
|
|
205
|
+
(config.plugins || []).forEach((plugin) => {
|
|
206
|
+
this._fr.FroalaEditor.PLUGINS[plugin.config.name] = function (editor) {
|
|
207
|
+
plugin.editor = editor;
|
|
208
|
+
plugin.initialize();
|
|
209
|
+
return plugin;
|
|
210
|
+
};
|
|
211
|
+
(plugin.config.buttons || []).forEach((button) => {
|
|
212
|
+
this._fr.FroalaEditor.DefineIcon(button.name, {
|
|
213
|
+
NAME: button.name,
|
|
214
|
+
PATH: button.svgPath,
|
|
215
|
+
});
|
|
216
|
+
this._fr.FroalaEditor.RegisterCommand(button.name, {
|
|
217
|
+
icon: button.name,
|
|
218
|
+
title: button.tooltip,
|
|
219
|
+
undo: button.undo,
|
|
220
|
+
focus: button.focus,
|
|
221
|
+
showOnMobile: button.showOnMobile,
|
|
222
|
+
refreshAfterCallback: button.refreshAfterCallback,
|
|
223
|
+
callback: function () {
|
|
224
|
+
if (button.click) {
|
|
225
|
+
button.click(this);
|
|
226
|
+
}
|
|
227
|
+
},
|
|
228
|
+
refresh: function (button) {
|
|
229
|
+
if (button.refresh) {
|
|
230
|
+
button.refresh(this, button);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
_createOptions() {
|
|
238
|
+
var _a, _b;
|
|
239
|
+
const config = this._createConfig();
|
|
240
|
+
return merge(
|
|
241
|
+
// For some reason editor store somewhere pointer on default config object and dublicate options each time on init
|
|
242
|
+
// Extra merge level fixed this problem and allow to init config properly without legacy data
|
|
243
|
+
{}, {
|
|
244
|
+
shortcutsEnabled: ['show', 'bold', 'italic', 'underline', 'indent', 'outdent', 'undo', 'redo', 'insertImage', 'createLink'],
|
|
245
|
+
key: config.activationKey,
|
|
246
|
+
placeholderText: config.placeholder,
|
|
247
|
+
linkAlwaysBlank: true,
|
|
248
|
+
tabSpaces: 2,
|
|
249
|
+
typingTimer: 250,
|
|
250
|
+
tooltips: false,
|
|
251
|
+
wordPasteModal: false,
|
|
252
|
+
imageDefaultWidth: 0,
|
|
253
|
+
imageDefaultAlign: 'left',
|
|
254
|
+
quickInsertEnabled: false,
|
|
255
|
+
scrollableContainer: `#${this.containerID}`,
|
|
256
|
+
paragraphDefaultSelection: 'Format',
|
|
257
|
+
videoUpload: false,
|
|
258
|
+
imagePaste: !!((_a = config.image) === null || _a === void 0 ? void 0 : _a.upload),
|
|
259
|
+
imageUpload: !!((_b = config.image) === null || _b === void 0 ? void 0 : _b.upload),
|
|
260
|
+
paragraphFormat: {
|
|
261
|
+
N: 'Normal',
|
|
262
|
+
H1: 'Heading 1',
|
|
263
|
+
H2: 'Heading 2',
|
|
264
|
+
H3: 'Heading 3',
|
|
265
|
+
H4: 'Heading 4',
|
|
266
|
+
BLOCKQUOTE: 'Quote',
|
|
267
|
+
},
|
|
268
|
+
lineHeights: {
|
|
269
|
+
Default: '',
|
|
270
|
+
'0.5': '0.5',
|
|
271
|
+
'Single': '1',
|
|
272
|
+
'1.15': '1.15',
|
|
273
|
+
'1.5': '1.5',
|
|
274
|
+
'Double': '2'
|
|
275
|
+
},
|
|
276
|
+
paragraphFormatSelection: true,
|
|
277
|
+
toolbarButtonsXS: {
|
|
278
|
+
moreText: {
|
|
279
|
+
buttons: TextButtons,
|
|
280
|
+
buttonsVisible: 1,
|
|
281
|
+
},
|
|
282
|
+
moreParagraph: {
|
|
283
|
+
buttons: ParagraphButtons,
|
|
284
|
+
buttonsVisible: 2,
|
|
285
|
+
},
|
|
286
|
+
moreRich: {
|
|
287
|
+
buttons: RichButtons,
|
|
288
|
+
buttonsVisible: 0,
|
|
289
|
+
},
|
|
290
|
+
},
|
|
291
|
+
toolbarButtons: {
|
|
292
|
+
moreText: {
|
|
293
|
+
buttons: TextButtons,
|
|
294
|
+
buttonsVisible: 3,
|
|
295
|
+
},
|
|
296
|
+
moreParagraph: {
|
|
297
|
+
buttons: ParagraphButtons,
|
|
298
|
+
buttonsVisible: 5,
|
|
299
|
+
},
|
|
300
|
+
moreRich: {
|
|
301
|
+
buttons: RichButtons,
|
|
302
|
+
buttonsVisible: 3,
|
|
303
|
+
},
|
|
304
|
+
},
|
|
305
|
+
}, config.froalaConfig);
|
|
306
|
+
}
|
|
307
|
+
_listenLazyInit() {
|
|
308
|
+
this.froalaLoaded$
|
|
309
|
+
.pipe(filter((ready) => ready), switchMap(() => this._initialize$), tap(() => {
|
|
310
|
+
const selection = window.getSelection();
|
|
311
|
+
const options = {};
|
|
312
|
+
if (selection.baseNode) {
|
|
313
|
+
options.selection = {
|
|
314
|
+
node: selection.baseNode.nodeValue,
|
|
315
|
+
offset: selection.baseOffset,
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
this.initialize(options);
|
|
319
|
+
}), switchMap(() => this._froalaReady$), filter((data) => !!data), tap(({ config, options }) => {
|
|
320
|
+
this._setupFroala(config, options);
|
|
321
|
+
}))
|
|
322
|
+
.subscribe();
|
|
323
|
+
}
|
|
324
|
+
_contentChanged() {
|
|
325
|
+
const editorHTML = this._editor.html.get();
|
|
326
|
+
if (this.html !== editorHTML) {
|
|
327
|
+
this._change(editorHTML);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
_setupFroala(config, options) {
|
|
331
|
+
this._cdRef.markForCheck();
|
|
332
|
+
this.setHtml(this._html);
|
|
333
|
+
if (config.disabled) {
|
|
334
|
+
this.disable();
|
|
335
|
+
}
|
|
336
|
+
if (config.froalaConfig.events) {
|
|
337
|
+
if (config.froalaConfig.events.initialized) {
|
|
338
|
+
config.froalaConfig.events.initialized();
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
this._editor.events.on('focus', () => {
|
|
342
|
+
this.classFocused = true;
|
|
343
|
+
this._cdRef.markForCheck();
|
|
344
|
+
});
|
|
345
|
+
this._editor.events.on('blur', () => {
|
|
346
|
+
this.classFocused = false;
|
|
347
|
+
this._cdRef.markForCheck();
|
|
348
|
+
});
|
|
349
|
+
this._editor.events.on('click', () => {
|
|
350
|
+
if (this.config.initOnClick && !this.initialized) {
|
|
351
|
+
this.initialized = true;
|
|
352
|
+
this._cdRef.markForCheck();
|
|
353
|
+
}
|
|
354
|
+
});
|
|
355
|
+
fromEventPattern((handler) => {
|
|
356
|
+
this._editor.events.on('contentChanged', handler);
|
|
357
|
+
}, () => { })
|
|
358
|
+
.pipe(startWith(this._html), map(() => this.editor.html.get()), distinctUntilChanged(), skip(1))
|
|
359
|
+
.subscribe(() => {
|
|
360
|
+
this._contentChanged();
|
|
361
|
+
});
|
|
362
|
+
this._editor.events.on('paste.afterCleanup', (html) => {
|
|
363
|
+
var div = document.createElement('div');
|
|
364
|
+
div.innerHTML = html;
|
|
365
|
+
div.querySelectorAll('*')
|
|
366
|
+
.forEach((el) => {
|
|
367
|
+
for (var i = 0; i < el.attributes.length; i++) {
|
|
368
|
+
const name = el.attributes[0].name;
|
|
369
|
+
if (name !== 'href') {
|
|
370
|
+
el.removeAttribute(name);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
});
|
|
374
|
+
return div.innerHTML;
|
|
375
|
+
});
|
|
376
|
+
this._editor.events.on('keydown', () => {
|
|
377
|
+
this.onTouched();
|
|
378
|
+
});
|
|
379
|
+
if (this.config.image && this.config.image.upload) {
|
|
380
|
+
this._editor.events.on('image.beforePasteUpload', (image) => {
|
|
381
|
+
fetch(image.getAttribute('src'))
|
|
382
|
+
.then((res) => {
|
|
383
|
+
res.blob()
|
|
384
|
+
.then((blob) => {
|
|
385
|
+
this._processImageUpload(blob)
|
|
386
|
+
.pipe(takeUntil(this._destroy$))
|
|
387
|
+
.subscribe((url) => {
|
|
388
|
+
image.setAttribute('src', url);
|
|
389
|
+
image.removeAttribute('data-fr-image-pasted');
|
|
390
|
+
this._contentChanged();
|
|
391
|
+
});
|
|
392
|
+
});
|
|
393
|
+
});
|
|
394
|
+
return false;
|
|
395
|
+
});
|
|
396
|
+
this._editor.events.on('image.beforeUpload', (blobs) => {
|
|
397
|
+
this._processImageUpload(blobs[0])
|
|
398
|
+
.pipe(takeUntil(this._destroy$))
|
|
399
|
+
.subscribe((url) => {
|
|
400
|
+
this.editor.image.insert(url, null, null, this.editor.image.get());
|
|
401
|
+
});
|
|
402
|
+
return false;
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
if (this.el.querySelector('.fr-second-toolbar')) {
|
|
406
|
+
this.el.querySelector('.fr-second-toolbar').remove();
|
|
407
|
+
}
|
|
408
|
+
if (this.config.autofocus && !this.config.initOnClick) {
|
|
409
|
+
this.focus();
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
FsHtmlEditorComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: FsHtmlEditorComponent, deps: [{ token: FS_HTML_EDITOR_CONFIG, optional: true }, { token: i0.ChangeDetectorRef }, { token: i1.FsFroalaLoaderService }], target: i0.ɵɵFactoryTarget.Component });
|
|
414
|
+
FsHtmlEditorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.16", type: FsHtmlEditorComponent, selector: "fs-html-editor", inputs: { config: "config", hint: "hint", disabled: "disabled" }, host: { properties: { "class.focused": "this.classFocused", "class.disabled": "this.disabled" } }, providers: [
|
|
415
|
+
{
|
|
416
|
+
provide: NG_VALUE_ACCESSOR,
|
|
417
|
+
useExisting: forwardRef(() => FsHtmlEditorComponent),
|
|
418
|
+
multi: true
|
|
419
|
+
},
|
|
420
|
+
{
|
|
421
|
+
provide: NG_VALIDATORS,
|
|
422
|
+
useExisting: forwardRef(() => FsHtmlEditorComponent),
|
|
423
|
+
multi: true
|
|
424
|
+
},
|
|
425
|
+
], viewQueries: [{ propertyName: "elRef", first: true, predicate: ["elRef"], descendants: true }], ngImport: i0, template: "<fs-label-field>\n <fs-label *ngIf=\"config.label\">{{config.label}}</fs-label>\n <div\n class=\"html-editor-container fs-html-editor-default\"\n [id]=\"containerID\"\n [ngClass]=\"{\n initialized: initialized,\n 'init-on-click': config.initOnClick\n }\">\n <ng-container *fsSkeleton=\"(froalaLoaded$ | async) !== false\"></ng-container>\n <div #elRef></div>\n\n <div class=\"bottom-line\"></div>\n <div class=\"disabled-line\"></div>\n </div>\n\n <fs-label-message>\n <div class=\"fs-form-message\">\n <div class=\"fs-form-hint\">{{hint}}</div>\n </div>\n </fs-label-message>\n</fs-label-field>\n", styles: [":host ::ng-deep .fr-box.fr-basic .fr-wrapper{border:0;border-bottom:1px solid #949494;margin-bottom:1px;background-color:transparent}:host ::ng-deep .fr-box.fr-basic .fr-element{padding:0;font-family:inherit;color:inherit;font-size:inherit;line-height:inherit;min-height:auto}:host ::ng-deep .fr-more-toolbar,:host ::ng-deep .fr-toolbar,:host ::ng-deep .fr-dropdown:after,:host ::ng-deep .fr-dropdown-menu .fr-dropdown-wrapper{transition:none!important}:host ::ng-deep .fr-toolbar-open .fr-more-toolbar{display:block}:host ::ng-deep .fr-more-toolbar{display:none}:host ::ng-deep .fr-toolbar.fr-top{position:sticky;z-index:2;border-radius:0;background-color:#fff}:host ::ng-deep .fr-toolbar.fr-top .fr-btn-grp{margin:0 20px 0 0}:host ::ng-deep .fr-toolbar.fr-top .fr-btn-grp:nth-child(1):after,:host ::ng-deep .fr-toolbar.fr-top .fr-btn-grp:nth-child(2):after{content:\"\";position:absolute;top:9px;height:30px;border-left:1px solid #e5e5e5;margin-left:10px}:host ::ng-deep .fr-toolbar.fr-top div:first-of-type:before{border:none}:host ::ng-deep .fr-toolbar.fr-top.fr-toolbar-open .fr-newline{height:auto}:host ::ng-deep .fr-toolbar.fr-top .fr-btn-grp:first-child{margin-left:0}:host ::ng-deep .fr-toolbar.fr-top.fr-top{border:0}:host ::ng-deep .fr-toolbar.fr-top .fr-newline{margin:0}:host ::ng-deep .fr-toolbar.fr-top .fr-more-toolbar{z-index:auto;display:flex;justify-content:center;padding-left:0!important}:host ::ng-deep .fr-toolbar.fr-top .fr-command.fr-btn{z-index:auto}:host ::ng-deep .fr-toolbar.fr-top .fr-command.fr-btn.fr-dropdown:after{right:3px}:host ::ng-deep .fr-toolbar.fr-top .fr-command.fr-btn.fr-dropdown.fr-selection span{margin-right:24px}:host ::ng-deep .fr-toolbar.fr-top .fr-command.fr-btn.fr-open{border-radius:4px;margin:4px 2px}:host ::ng-deep .fr-view ol,:host ::ng-deep .fr-view ul{list-style-position:unset}:host ::ng-deep .html-editor-container.init-on-click:not(.initialized) .fr-toolbar{display:none}:host.disabled ::ng-deep .fr-box.fr-basic{opacity:.5;pointer-events:none}:host.disabled ::ng-deep .fr-box.fr-basic .fr-wrapper{border:none}:host.disabled ::ng-deep .disabled-line{display:block}::ng-deep .fr-popup{z-index:1001!important}::ng-deep .fr-video-by-url-layer .fr-checkbox-line{display:none}.disabled-line{display:none;position:absolute;bottom:-1px;z-index:1;background-image:linear-gradient(90deg,rgba(0,0,0,.42) 0,rgba(0,0,0,.42) 33%,transparent 0);background-size:4px 100%;background-repeat:repeat-x;height:1px;width:100%}.bottom-line{opacity:0;transform-origin:50%;transform:scaleX(.5);transition:background-color .3s cubic-bezier(.55,0,.55,.2);width:100%;border-bottom:2px solid #949494;position:absolute;bottom:-1px;z-index:1}:host{position:relative;display:block}:host.focused .bottom-line{opacity:1;display:block;transform:scaleX(1);transition:transform .3s cubic-bezier(.25,.8,.25,1),opacity .1s cubic-bezier(.25,.8,.25,1),background-color .3s cubic-bezier(.25,.8,.25,1)}::ng-deep .fs-html-editor-mention-container{position:absolute;top:0;left:0;height:auto;max-height:300px;max-width:500px;overflow:auto;display:block;z-index:999999;box-shadow:0 2px 4px -1px #0003,0 4px 5px #00000024,0 1px 10px #0000001f;border-bottom-left-radius:4px;border-bottom-right-radius:4px;background:#fff}::ng-deep .fs-html-editor-mention-container ul{margin:0;padding:0;list-style:none}::ng-deep .fs-html-editor-mention-container li{padding:0 16px;cursor:pointer;line-height:48px}::ng-deep .fs-html-editor-mention-container li.highlight,::ng-deep .fs-html-editor-mention-container li:hover{background:#F5F5F5}::ng-deep .fs-html-editor-mention-container li.no-match{cursor:default}\n"], components: [{ type: i2.FsLabelFieldComponent, selector: "fs-label-field", inputs: ["bottomMargin", "topMargin", "labelMargin"] }, { type: i2.FsLabelComponent, selector: "fs-label" }, { type: i2.FsLabelMessageComponent, selector: "fs-label-message" }], directives: [{ type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i4.FsSkeletonContentDirective, selector: "[fsSkeleton]", inputs: ["fsSkeleton", "fsSkeletonPattern"] }], pipes: { "async": i3.AsyncPipe }, viewProviders: [
|
|
426
|
+
{
|
|
427
|
+
provide: ControlContainer,
|
|
428
|
+
deps: [[Optional, NgForm]],
|
|
429
|
+
useFactory: (ngForm) => ngForm,
|
|
430
|
+
},
|
|
431
|
+
], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
432
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: FsHtmlEditorComponent, decorators: [{
|
|
433
|
+
type: Component,
|
|
434
|
+
args: [{
|
|
435
|
+
selector: 'fs-html-editor',
|
|
436
|
+
templateUrl: 'html-editor.component.html',
|
|
437
|
+
styleUrls: ['html-editor.component.scss'],
|
|
438
|
+
providers: [
|
|
439
|
+
{
|
|
440
|
+
provide: NG_VALUE_ACCESSOR,
|
|
441
|
+
useExisting: forwardRef(() => FsHtmlEditorComponent),
|
|
442
|
+
multi: true
|
|
443
|
+
},
|
|
444
|
+
{
|
|
445
|
+
provide: NG_VALIDATORS,
|
|
446
|
+
useExisting: forwardRef(() => FsHtmlEditorComponent),
|
|
447
|
+
multi: true
|
|
448
|
+
},
|
|
449
|
+
],
|
|
450
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
451
|
+
viewProviders: [
|
|
452
|
+
{
|
|
453
|
+
provide: ControlContainer,
|
|
454
|
+
deps: [[Optional, NgForm]],
|
|
455
|
+
useFactory: (ngForm) => ngForm,
|
|
456
|
+
},
|
|
457
|
+
],
|
|
458
|
+
}]
|
|
459
|
+
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
|
|
460
|
+
type: Optional
|
|
461
|
+
}, {
|
|
462
|
+
type: Inject,
|
|
463
|
+
args: [FS_HTML_EDITOR_CONFIG]
|
|
464
|
+
}] }, { type: i0.ChangeDetectorRef }, { type: i1.FsFroalaLoaderService }]; }, propDecorators: { classFocused: [{
|
|
465
|
+
type: HostBinding,
|
|
466
|
+
args: ['class.focused']
|
|
467
|
+
}], elRef: [{
|
|
468
|
+
type: ViewChild,
|
|
469
|
+
args: ['elRef']
|
|
470
|
+
}], config: [{
|
|
471
|
+
type: Input
|
|
472
|
+
}], hint: [{
|
|
473
|
+
type: Input
|
|
474
|
+
}], disabled: [{
|
|
475
|
+
type: Input
|
|
476
|
+
}, {
|
|
477
|
+
type: HostBinding,
|
|
478
|
+
args: ['class.disabled']
|
|
479
|
+
}] } });
|
|
480
480
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaHRtbC1lZGl0b3IuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9tb2R1bGVzL2h0bWwtZWRpdG9yL2NvbXBvbmVudHMvaHRtbC1lZGl0b3IvaHRtbC1lZGl0b3IuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9tb2R1bGVzL2h0bWwtZWRpdG9yL2NvbXBvbmVudHMvaHRtbC1lZGl0b3IvaHRtbC1lZGl0b3IuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUVMLHVCQUF1QixFQUN2QixpQkFBaUIsRUFDakIsU0FBUyxFQUNULFVBQVUsRUFDVixVQUFVLEVBQ1YsV0FBVyxFQUNYLE1BQU0sRUFDTixLQUFLLEVBR0wsUUFBUSxFQUNSLFNBQVMsRUFDVixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBRUwsZ0JBQWdCLEVBRWhCLGFBQWEsRUFDYixpQkFBaUIsRUFDakIsTUFBTSxFQUdQLE1BQU0sZ0JBQWdCLENBQUM7QUFFeEIsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQzFDLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxFQUF1QixNQUFNLGtCQUFrQixDQUFDO0FBRTlFLE9BQU8sRUFBRSxlQUFlLEVBQUUsZ0JBQWdCLEVBQWMsYUFBYSxFQUFFLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUM3RixPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFL0csT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUdsQyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSx3Q0FBd0MsQ0FBQztBQUMxRSxPQUFPLEVBQUUs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TUFBTTt5QkFDdkM7cUJBQ0Y7aUJBQ0Y7OzBCQXdCSSxRQUFROzswQkFBSSxNQUFNOzJCQUFDLHFCQUFxQjtnSEFyQmIsWUFBWTtzQkFBekMsV0FBVzt1QkFBQyxlQUFlO2dCQUVELEtBQUs7c0JBQS9CLFNBQVM7dUJBQUMsT0FBTztnQkFFRixNQUFNO3NCQUFyQixLQUFLO2dCQUNVLElBQUk7c0JBQW5CLEtBQUs7Z0JBSUMsUUFBUTtzQkFGZCxLQUFLOztzQkFDTCxXQUFXO3VCQUFDLGdCQUFnQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEFmdGVyVmlld0luaXQsXG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICBDaGFuZ2VEZXRlY3RvclJlZixcbiAgQ29tcG9uZW50LFxuICBFbGVtZW50UmVmLFxuICBmb3J3YXJkUmVmLFxuICBIb3N0QmluZGluZyxcbiAgSW5qZWN0LFxuICBJbnB1dCxcbiAgT25EZXN0cm95LFxuICBPbkluaXQsXG4gIE9wdGlvbmFsLFxuICBWaWV3Q2hpbGRcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge1xuICBBYnN0cmFjdENvbnRyb2wsXG4gIENvbnRyb2xDb250YWluZXIsXG4gIENvbnRyb2xWYWx1ZUFjY2Vzc29yLFxuICBOR19WQUxJREFUT1JTLFxuICBOR19WQUxVRV9BQ0NFU1NPUixcbiAgTmdGb3JtLFxuICBWYWxpZGF0aW9uRXJyb3JzLFxuICBWYWxpZGF0b3Jcbn0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuXG5pbXBvcnQgeyBndWlkIH0gZnJvbSAnQGZpcmVzdGl0Y2gvY29tbW9uJztcbmltcG9ydCB7IEZpbGVQcm9jZXNzb3IsIEZzRmlsZSwgRnNGaWxlUHJvY2Vzc0NvbmZpZyB9IGZyb20gJ0BmaXJlc3RpdGNoL2ZpbGUnO1xuXG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QsIGZyb21FdmVudFBhdHRlcm4sIE9ic2VydmFibGUsIFJlcGxheVN1YmplY3QsIFN1YmplY3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IGRpc3RpbmN0VW50aWxDaGFuZ2VkLCBmaWx0ZXIsIG1hcCwgc2tpcCwgc3RhcnRXaXRoLCBzd2l0Y2hNYXAsIHRha2VVbnRpbCwgdGFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5pbXBvcnQgeyBtZXJnZSB9IGZyb20gJ2xvZGFzaC1lcyc7XG5cbmltcG9ydCB7IEZzSHRtbEVkaXRvckNvbmZpZyB9IGZyb20gJy4uLy4uL2ludGVyZmFjZXMvaHRtbC1lZGl0b3ItY29uZmlnJztcbmltcG9ydCB7IFBhcmFncmFwaEJ1dHRvbnMgfSBmcm9tICcuLy4uLy4uL2NvbnN0cy9wYXJhZ3JhcGgtYnV0dG9ucy5jb25zdCc7XG5pbXBvcnQgeyBSaWNoQnV0dG9ucyB9IGZyb20gJy4vLi4vLi4vY29uc3RzL3JpY2gtYnV0dG9ucy5jb25zdCc7XG5pbXBvcnQgeyBUZXh0QnV0dG9ucyB9IGZyb20gJy4vLi4vLi4vY29uc3RzL3RleHQtYnV0dG9ucy5jb25zdCc7XG5pbXBvcnQgeyBQbHVnaW5CdXR0b24gfSBmcm9tICcuLy4uLy4uL2ludGVyZmFjZXMvcGx1Z2luLWJ1dHRvbic7XG5cbmltcG9ydCB7IEZTX0hUTUxfRURJVE9SX0NPTkZJRyB9IGZyb20gJy4uLy4uL2luamVjdHMvY29uZmlnLmluamVjdCc7XG5pbXBvcnQgeyBQbHVnaW4gfSBmcm9tICcuLy4uLy4uL2NsYXNzZXMvcGx1Z2luJztcblxuaW1wb3J0IHsgRnNGcm9hbGFMb2FkZXJTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvZnJvYWxhLWxvYWRlci5zZXJ2aWNlJztcblxuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdmcy1odG1sLWVkaXRvcicsXG4gIHRlbXBsYXRlVXJsOiAnaHRtbC1lZGl0b3IuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnaHRtbC1lZGl0b3IuY29tcG9uZW50LnNjc3MnXSxcbiAgcHJvdmlkZXJzOiBbXG4gICAge1xuICAgICAgcHJvdmlkZTogTkdfVkFMVUVfQUNDRVNTT1IsXG4gICAgICB1c2VFeGlzdGluZzogZm9yd2FyZFJlZigoKSA9PiBGc0h0bWxFZGl0b3JDb21wb25lbnQpLFxuICAgICAgbXVsdGk6IHRydWVcbiAgICB9LFxuICAgIHtcbiAgICAgIHByb3ZpZGU6IE5HX1ZBTElEQVRPUlMsXG4gICAgICB1c2VFeGlzdGluZzogZm9yd2FyZFJlZigoKSA9PiBGc0h0bWxFZGl0b3JDb21wb25lbnQpLFxuICAgICAgbXVsdGk6IHRydWVcbiAgICB9LFxuICBdLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgdmlld1Byb3ZpZGVyczogW1xuICAgIHtcbiAgICAgIHByb3ZpZGU6IENvbnRyb2xDb250YWluZXIsXG4gICAgICBkZXBzOiBbW09wdGlvbmFsLCBOZ0Zvcm1dXSxcbiAgICAgIHVzZUZhY3Rvcnk6IChuZ0Zvcm06IE5nRm9ybSkgPT4gbmdGb3JtLFxuICAgIH0sXG4gIF0sXG59KVxuZXhwb3J0IGNsYXNzIEZzSHRtbEVkaXRvckNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgQWZ0ZXJWaWV3SW5pdCwgQ29udHJvbFZhbHVlQWNjZXNzb3IsIFZhbGlkYXRvciwgT25EZXN0cm95IHtcblxuICBASG9zdEJpbmRpbmcoJ2NsYXNzLmZvY3VzZWQnKSBjbGFzc0ZvY3VzZWQgPSBmYWxzZTtcblxuICBAVmlld0NoaWxkKCdlbFJlZicpIHB1YmxpYyBlbFJlZjogRWxlbWVudFJlZjtcblxuICBASW5wdXQoKSBwdWJsaWMgY29uZmlnOiBGc0h0bWxFZGl0b3JDb25maWcgPSB7fTtcbiAgQElucHV0KCkgcHVibGljIGhpbnQ6IHN0cmluZztcblxuICBASW5wdXQoKVxuICBASG9zdEJpbmRpbmcoJ2NsYXNzLmRpc2FibGVkJylcbiAgcHVibGljIGRpc2FibGVkID0gZmFsc2U7XG5cbiAgcHVibGljIGluaXRpYWxpemVkID0gZmFsc2U7XG4gIHB1YmxpYyByZWFkb25seSBjb250YWluZXJJRCA9IGBmcy1odG1sLWVkaXRvci0ke2d1aWQoJ3h4eCcpfWA7XG5cbiAgcHJpdmF0ZSBfZWRpdG9yOiBhbnk7XG4gIHByaXZhdGUgX2h0bWw6IHN0cmluZztcbiAgcHJpdmF0ZSBfaW5pdGlhbGl6ZSQgPSBuZXcgUmVwbGF5U3ViamVjdCgpO1xuICBwcml2YXRlIF9mcm9hbGFSZWFkeSQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0KG51bGwpO1xuICBwcml2YXRlIF9kZXN0cm95JCA9IG5ldyBTdWJqZWN0KCk7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgQE9wdGlvbmFsKCkgQEluamVjdChGU19IVE1MX0VESVRPUl9DT05GSUcpIHByaXZhdGUgX2RlZmF1bHRDb25maWcsXG4gICAgcHJpdmF0ZSBfY2RSZWY6IENoYW5nZURldGVjdG9yUmVmLFxuICAgIHByaXZhdGUgX2ZyOiBGc0Zyb2FsYUxvYWRlclNlcnZpY2UsXG4gICkgeyB9XG5cbiAgcHVibGljIG9uQ2hhbmdlID0gKGRhdGE6IGFueSkgPT4geyB9XG4gIHB1YmxpYyBvblRvdWNoZWQgPSAoKSA9PiB7IH1cblxuICBwdWJsaWMgZ2V0IGVsKCk6IGFueSB7XG4gICAgcmV0dXJuIHRoaXMuZWxSZWYubmF0aXZlRWxlbWVudDtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgaHRtbCgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLl9odG1sO1xuICB9XG5cbiAgcHVibGljIGdldCBlZGl0b3IoKTogYW55IHtcbiAgICByZXR1cm4gdGhpcy5fZWRpdG9yO1xuICB9XG5cbiAgcHVibGljIGdldCBmcm9hbGFMb2FkZWQkKCk6IE9ic2VydmFibGU8Ym9vbGVhbj4ge1xuICAgIHJldHVybiB0aGlzLl9mci5sb2FkZWQkO1xuICB9XG5cbiAgcHVibGljIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIHRoaXMuY29uZmlnID0gdGhpcy5jb25maWcgfHwge307XG4gICAgdGhpcy5jb25maWcuYXV0b2ZvY3VzID0gdGhpcy5jb25maWcuYXV0b2ZvY3VzICE9PSBmYWxzZSAmJiAoIXRoaXMuY29uZmlnLmRpc2FibGVkIHx8ICF0aGlzLmRpc2FibGVkKTtcbiAgICB0aGlzLl9saXN0ZW5MYXp5SW5pdCgpO1xuICB9XG5cbiAgcHVibGljIG5nQWZ0ZXJWaWV3SW5pdCgpIHtcbiAgICB0aGlzLl9pbml0aWFsaXplJC5uZXh0KCk7XG4gIH1cblxuICBwdWJsaWMgaGFzQ29udGVudCgpIHtcbiAgICBjb25zdCBlbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuXG4gICAgaWYgKGVsLnF1ZXJ5U2VsZWN0b3IoJ2ltZycpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBlbC5pbm5lckhUTUwgPSB0aGlzLl9odG1sO1xuICAgIHJldHVybiAhIWVsLmlubmVyVGV4dC5sZW5ndGg7XG4gIH1cblxuICBwdWJsaWMgaW5pdGlhbGl6ZShvcHRpb25zOiBhbnkgPSB7fSkge1xuICAgIGNvbnN0IGNvbmZpZyA9IHRoaXMuX2NyZWF0ZUNvbmZpZygpO1xuICAgIHRoaXMuX2luaXRQbHVnaW5zKGNvbmZpZyk7XG4gICAgdGhpcy5faW5pdEJ1dHRvbnMoY29uZmlnKTtcbiAgICB0aGlzLl9lZGl0b3IgPSBuZXcgdGhpcy5fZnIuRnJvYWxhRWRpdG9yKHRoaXMuZWwsIHRoaXMuX2NyZWF0ZU9wdGlvbnMoKSwgKCkgPT4ge1xuICAgICAgdGhpcy5fZnJvYWxhUmVhZHkkLm5leHQoeyBjb25maWcsIG9wdGlvbnMgfSk7XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIF9wcm9jZXNzSW1hZ2VVcGxvYWQoYmxvYikge1xuICAgIGNvbnN0IHByb2Nlc3NvciA9IG5ldyBGaWxlUHJvY2Vzc29yKCk7XG4gICAgY29uc3QgZmlsZSA9IG5ldyBGc0ZpbGUoYmxvYik7XG5cbiAgICBjb25zdCBjb25maWc6IEZzRmlsZVByb2Nlc3NDb25maWcgPSB7XG4gICAgICBvcmllbnRhdGU6IHRydWUsXG4gICAgICBxdWFsaXR5OiB0aGlzLmNvbmZpZy5pbWFnZS5xdWFsaXR5LFxuICAgICAgZm9ybWF0OiB0aGlzLmNvbmZpZy5pbWFnZS5mb3JtYXQgYXMgYW55LFxuICAgICAgbWF4V2lkdGg6IHRoaXMuY29uZmlnLmltYWdlLndpZHRoLFxuICAgICAgbWF4SGVpZ2h0OiB0aGlzLmNvbmZpZy5pbWFnZS5oZWlnaHQsXG4gICAgICBtaW5XaWR0aDogdGhpcy5jb25maWcuaW1hZ2UubWluV2lkdGgsXG4gICAgICBtaW5IZWlnaHQ6IHRoaXMuY29uZmlnLmltYWdlLm1pbkhlaWdodCxcbiAgICB9O1xuXG4gICAgcmV0dXJuIHByb2Nlc3Nvci5wcm9jZXNzRmlsZShmaWxlLCBjb25maWcpXG4gICAgICAucGlwZShcbiAgICAgICAgc3dpdGNoTWFwKChmc0ZpbGU6IEZzRmlsZSkgPT4ge1xuICAgICAgICAgIHJldHVybiB0aGlzLmNvbmZpZy5pbWFnZS51cGxvYWQoZnNGaWxlLmZpbGUpXG4gICAgICAgIH0pLFxuICAgICAgKTtcbiAgfVxuXG4gIHB1YmxpYyB1cGRhdGVTaXplKCkge1xuICAgIC8vIEhhY2s6IFRvIHRyaWdnZXIgdGhlIHRvb2xiYXIgYnV0dG9uIHNpemUgbW9kZXNcbiAgICB3aW5kb3cuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnQoJ3Jlc2l6ZScpKTtcbiAgfVxuXG4gIHB1YmxpYyB2YWxpZGF0ZShjb250cm9sOiBBYnN0cmFjdENvbnRyb2wpOiBWYWxpZGF0aW9uRXJyb3JzIHwgbnVsbCB7XG4gICAgY29uc3QgZXJyOiBhbnkgPSB7fTtcbiAgICBpZiAodGhpcy5jb25maWcubWF4TGVuZ3RoICYmIHRoaXMuX2h0bWwpIHtcbiAgICAgIGNvbnN0IG1heExlbmd0aCA9IHRoaXMuY29uZmlnLm1heExlbmd0aDtcbiAgICAgIGNvbnN0IGxlbmd0aCA9IHRoaXMuX2h0bWwubGVuZ3RoO1xuICAgICAgaWYgKGxlbmd0aCA+IG1heExlbmd0aCkge1xuICAgICAgICBlcnIubWF4TGVuZ3RoRXJyb3IgPSBgTXVzdCBiZSAke21heExlbmd0aH0gY2hhcmFjdGVycyBvciBmZXdlci4gWW91IGVudGVyZWQgJHtsZW5ndGh9IGNoYXJhY3RlcnMuYDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gT2JqZWN0LmtleXMoZXJyKS5sZW5ndGggPyBlcnIgOiBudWxsO1xuICB9XG5cbiAgcHVibGljIGZvY3VzKG9wdGlvbnM/OiB7IGN1cnNvclBvc2l0aW9uPzogJ3N0YXJ0JyB8ICdlbmQnIH0pIHtcbiAgICBvcHRpb25zID0gb3B0aW9ucyA/IG9wdGlvbnMgOiB7fTtcblxuICAgIGlmIChvcHRpb25zLmN1cnNvclBvc2l0aW9uID09PSAnZW5kJykge1xuICAgICAgdGhpcy5lZGl0b3Iuc2VsZWN0aW9uLnNldEF0RW5kKHRoaXMuZWRpdG9yLiRlbC5nZXQoMCkpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmVkaXRvci5zZWxlY3Rpb24uc2V0QXRTdGFydCh0aGlzLmVkaXRvci4kZWwuZ2V0KDApKTtcbiAgICB9XG5cbiAgICB0aGlzLmVkaXRvci5zZWxlY3Rpb24ucmVzdG9yZSgpO1xuXG4gICAgY29uc3QgZWxTZWxlY3Rpb24gPSB0aGlzLmVkaXRvci5zZWxlY3Rpb24uZWxlbWVudCgpO1xuICAgIGlmIChlbFNlbGVjdGlvbikge1xuICAgICAgZWxTZWxlY3Rpb24uc2Nyb2xsSW50b1ZpZXcoeyBibG9jazogJ2NlbnRlcicgfSk7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGNsZWFyKCkge1xuICAgIHRoaXMud3JpdGVWYWx1ZSgnJyk7XG4gIH1cblxuICBwdWJsaWMgZGlzYWJsZSgpIHtcbiAgICB0aGlzLmRpc2FibGVkID0gdHJ1ZTtcbiAgfVxuXG4gIHB1YmxpYyBzZXRIdG1sKGh0bWwpIHtcbiAgICB0aGlzLndyaXRlVmFsdWUoaHRtbCk7XG4gIH1cblxuICBwdWJsaWMgd3JpdGVWYWx1ZShodG1sOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLl9odG1sID0gaHRtbCB8fCAnJztcblxuICAgIGlmIChBcnJheS5pc0FycmF5KHRoaXMuX2h0bWwpKSB7XG4gICAgICB0aGlzLl9odG1sID0gdGhpcy5faHRtbC5wb3AoKTtcbiAgICB9XG5cbiAgICB0aGlzLl9odG1sID0gdGhpcy5faHRtbFxuICAgICAgLnJlcGxhY2UoLzwobGkpPlxccz88KGRpdik+L2csICc8bGk+JylcbiAgICAgIC5yZXBsYWNlKC88XFwvKGRpdik+PFxcLyhsaSk+L2csICc8L2xpPicpO1xuXG4gICAgaWYgKHRoaXMuZWRpdG9yICYmIHRoaXMuZWRpdG9yLmh0bWwpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHRoaXMuZWRpdG9yLmh0bWwuc2V0KHRoaXMuX2h0bWwpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuX2NkUmVmLm1hcmtGb3JDaGVjaygpO1xuICB9XG5cbiAgcHVibGljIHJlZ2lzdGVyT25DaGFuZ2UoZm46IChkYXRhOiBhbnkpID0+IHZvaWQpOiB2b2lkIHtcbiAgICB0aGlzLm9uQ2hhbmdlID0gZm47XG4gIH1cblxuICBwdWJsaWMgcmVnaXN0ZXJPblRvdWNoZWQoZm46ICgpID0+IHZvaWQpOiB2b2lkIHtcbiAgICB0aGlzLm9uVG91Y2hlZCA9IGZuO1xuICB9XG5cbiAgcHVibGljIG5nT25EZXN0cm95KCkge1xuICAgIHRoaXMuX2luaXRpYWxpemUkLmNvbXBsZXRlKCk7XG4gICAgdGhpcy5fZGVzdHJveSQubmV4dCgpO1xuICAgIHRoaXMuX2Rlc3Ryb3kkLmNvbXBsZXRlKCk7XG4gICAgdGhpcy5kZXN0cm95KCk7XG4gIH1cblxuICBwdWJsaWMgZGVzdHJveSgpIHtcbiAgICBpZiAodGhpcy5lZGl0b3IpIHtcbiAgICAgIHRoaXMuZWRpdG9yLmRlc3Ryb3koKTtcbiAgICB9XG5cbiAgICB0aGlzLmluaXRpYWxpemVkID0gZmFsc2U7XG4gICAgdGhpcy5fY2RSZWYubWFya0ZvckNoZWNrKCk7XG4gICAgdGhpcy5lbC5pbm5lckhUTUwgPSAnJztcbiAgfVxuXG4gIHByaXZhdGUgX2NyZWF0ZUNvbmZpZygpOiBGc0h0bWxFZGl0b3JDb25maWcge1xuICAgIHJldHVybiBtZXJnZSh7IGZyb2FsYUNvbmZpZzoge30gfSwgdGhpcy5fZGVmYXVsdENvbmZpZywgdGhpcy5jb25maWcpO1xuICB9XG5cbiAgcHJpdmF0ZSBfY2hhbmdlKGh0bWwpOiB2b2lkIHtcbiAgICB0aGlzLl9odG1sID0gaHRtbDtcbiAgICB0aGlzLm9uQ2hhbmdlKGh0bWwpO1xuICB9XG5cbiAgcHJpdmF0ZSBfaW5pdEJ1dHRvbnMoY29uZmlnOiBGc0h0bWxFZGl0b3JDb25maWcpIHtcbiAgICAoY29uZmlnLmJ1dHRvbnMgfHwgW10pXG4gICAgICAuZm9yRWFjaCgoYnV0dG9uKSA9PiB7XG4gICAgICAgIC8qXG4gICAgICAgICAgU3ZnIEtleXM6XG4gICAgICAgICAgW1wiYWRkXCIsIFwiYWR2YW5jZWRJbWFnZUVkaXRvclwiLCBcImFsaWduQ2VudGVyXCIsIFwiYWxpZ25KdXN0aWZ5XCIsIFwiYWxpZ25MZWZ0XCIsIFwiYWxpZ25SaWdodFwiLFxuICAgICAgICAgIFwiYW5jaG9yc1wiLCBcImJhY2tcIiwgXCJiYWNrZ3JvdW5kQ29sb3JcIiwgXCJibG9ja3F1b3RlXCIsIFwiYm9sZFwiLCBcImNlbGxCYWNrZ3JvdW5kXCIsXG4gICAgICAgICAgXCJjZWxsQm9yZGVyQ29sb3JcIiwgXCJjZWxsT3B0aW9uc1wiLCBcImNlbGxTdHlsZVwiLCBcImNsZWFyRm9ybWF0dGluZ1wiLCBcImNsb3NlXCIsIFwiY29kZVZpZXdcIixcbiAgICAgICAgICBcImNvZ3NcIiwgXCJjb2x1bW5zXCIsIFwiZWRpdExpbmtcIiwgXCJleGl0RnVsbHNjcmVlblwiLCBcImZvbnRBd2Vzb21lXCIsIFwiZm9udEZhbWlseVwiLFxuICAgICAgICAgIFwiZm9udFNpemVcIiwgXCJmdWxsc2NyZWVuXCIsIFwiaGVscFwiLCBcImhvcml6b250YWxMaW5lXCIsIFwiaW1hZ2VBbHRUZXh0XCIsIFwiaW1hZ2VDYXB0aW9uXCIsXG4gICAgICAgICAgXCJpbWFnZUNsYXNzXCIsIFwiaW1hZ2VEaXNwbGF5XCIsIFwiaW1hZ2VNYW5hZ2VyXCIsIFwiaW1hZ2VTaXplXCIsIFwiaW5kZW50XCIsIFwiaW5saW5lQ2xhc3NcIixcbiAgICAgICAgICBcImlubGluZVN0eWxlXCIsIFwiaW5zZXJ0RW1iZWRcIiwgXCJpbnNlcnRGaWxlXCIsIFwiaW5zZXJ0SW1hZ2VcIiwgXCJpbnNlcnRMaW5rXCIsIFwiaW5zZXJ0TW9yZVwiLFxuICAgICAgICAgIFwiaW5zZXJ0VGFibGVcIiwgXCJpbnNlcnRWaWRlb1wiLCBcInVwbG9hZFwiLCBcIml0YWxpY1wiLCBcInNlYXJjaFwiLCBcImxpbmVIZWlnaHRcIiwgXCJsaW5rU3R5bGVzXCIsXG4gICAgICAgICAgXCJtZW50aW9uXCIsIFwibW9yZVwiLCBcIm9wZW5MaW5rXCIsIFwib3JkZXJlZExpc3RcIiwgXCJvdXRkZW50XCIsIFwicGFnZUJyZWFrZXJcIixcbiAgICAgICAgICBcInBhcmFncmFwaEZvcm1hdFwiLCBcInBhcmFncmFwaE1vcmVcIiwgXCJwYXJhZ3JhcGhTdHlsZVwiLCBcInBkZkV4cG9ydFwiLCBcInByaW50XCIsXG4gICAgICAgICAgXCJyZWRvXCIsIFwicmVtb3ZlVGFibGVcIiwgXCJyZW1vdmVcIiwgXCJyZXBsYWNlSW1hZ2VcIiwgXCJyb3dcIiwgXCJzZWxlY3RBbGxcIiwgXCJzbWlsZVwiLFxuICAgICAgICAgIFwic3BlbGxjaGVja1wiLCBcInN0YXJcIiwgXCJzdHJpa2VUaHJvdWdoXCIsIFwic3Vic2NyaXB0XCIsIFwic3VwZXJzY3JpcHRcIiwgXCJzeW1ib2xzXCIsIFwidGFnc1wiLFxuICAgICAgICAgIFwidGFibGVIZWFkZXJcIiwgXCJ0YWJsZVN0eWxlXCIsIFwidGV4dENvbG9yXCIsIFwidGV4dE1vcmVcIiwgXCJ1bmRlcmxpbmVcIiwgXCJ1bmRvXCIsIFwidW5saW5rXCIsXG4gICAgICAgICAgXCJ1bm9yZGVyZWRMaXN0XCIsIFwidmVydGljYWxBbGlnbkJvdHRvbVwiLCBcInZlcnRpY2FsQWxpZ25NaWRkbGVcIiwgXCJ2ZXJ0aWNhbEFsaWduVG9wXCJdXG4gICAgICAgICovXG5cbiAgICAgICAgaWYgKGJ1dHRvbi5zdmdLZXkpIHtcbiAgICAgICAgICB0aGlzLl9mci5Gcm9hbGFFZGl0b3IuRGVmaW5lSWNvbihidXR0b24ubmFtZSwgeyBTVkdfS0VZOiBidXR0b24uc3ZnS2V5IH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fZnIuRnJvYWxhRWRpdG9yLlJlZ2lzdGVyQ29tbWFuZChidXR0b24ubmFtZSwge1xuICAgICAgICAgIHRpdGxlOiBidXR0b24udGl0bGUsXG4gICAgICAgICAgZm9jdXM6IGJ1dHRvbi5mb2N1cyA/PyB0cnVlLFxuICAgICAgICAgIHVuZG86IGJ1dHRvbi51bmRvID8/IHRydWUsXG4gICAgICAgICAgcmVmcmVzaEFmdGVyQ2FsbGJhY2s6IGJ1dHRvbi5yZWZyZXNoQWZ0ZXJDYWxsYmFjayA/PyB0cnVlLFxuICAgICAgICAgIGNhbGxiYWNrOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBidXR0b24uY2xpY2sodGhpcyk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBfaW5pdFBsdWdpbnMoY29uZmlnKSB7XG4gICAgKGNvbmZpZy5wbHVnaW5zIHx8IFtdKS5mb3JFYWNoKChwbHVnaW46IFBsdWdpbikgPT4ge1xuICAgICAgdGhpcy5fZnIuRnJvYWxhRWRpdG9yLlBMVUdJTlNbcGx1Z2luLmNvbmZpZy5uYW1lXSA9IGZ1bmN0aW9uIChlZGl0b3IpIHtcbiAgICAgICAgcGx1Z2luLmVkaXRvciA9IGVkaXRvcjtcbiAgICAgICAgcGx1Z2luLmluaXRpYWxpemUoKTtcbiAgICAgICAgcmV0dXJuIHBsdWdpbjtcbiAgICAgIH07XG5cbiAgICAgIChwbHVnaW4uY29uZmlnLmJ1dHRvbnMgfHwgW10pLmZvckVhY2goKGJ1dHRvbjogUGx1Z2luQnV0dG9uKSA9PiB7XG4gICAgICAgIHRoaXMuX2ZyLkZyb2FsYUVkaXRvci5EZWZpbmVJY29uKGJ1dHRvbi5uYW1lLCB7XG4gICAgICAgICAgTkFNRTogYnV0dG9uLm5hbWUsXG4gICAgICAgICAgUEFUSDogYnV0dG9uLnN2Z1BhdGgsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMuX2ZyLkZyb2FsYUVkaXRvci5SZWdpc3RlckNvbW1hbmQoYnV0dG9uLm5hbWUsIHtcbiAgICAgICAgICBpY29uOiBidXR0b24ubmFtZSxcbiAgICAgICAgICB0aXRsZTogYnV0dG9uLnRvb2x0aXAsXG4gICAgICAgICAgdW5kbzogYnV0dG9uLnVuZG8sXG4gICAgICAgICAgZm9jdXM6IGJ1dHRvbi5mb2N1cyxcbiAgICAgICAgICBzaG93T25Nb2JpbGU6IGJ1dHRvbi5zaG93T25Nb2JpbGUsXG4gICAgICAgICAgcmVmcmVzaEFmdGVyQ2FsbGJhY2s6IGJ1dHRvbi5yZWZyZXNoQWZ0ZXJDYWxsYmFjayxcbiAgICAgICAgICBjYWxsYmFjazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKGJ1dHRvbi5jbGljaykge1xuICAgICAgICAgICAgICBidXR0b24uY2xpY2sodGhpcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSxcbiAgICAgICAgICByZWZyZXNoOiBmdW5jdGlvbiAoYnV0dG9uKSB7XG4gICAgICAgICAgICBpZiAoYnV0dG9uLnJlZnJlc2gpIHtcbiAgICAgICAgICAgICAgYnV0dG9uLnJlZnJlc2godGhpcywgYnV0dG9uKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgX2NyZWF0ZU9wdGlvbnMoKSB7XG4gICAgY29uc3QgY29uZmlnID0gdGhpcy5fY3JlYXRlQ29uZmlnKCk7XG5cbiAgICByZXR1cm4gbWVyZ2UoXG4gICAgICAvLyBGb3Igc29tZSByZWFzb24gZWRpdG9yIHN0b3JlIHNvbWV3aGVyZSBwb2ludGVyIG9uIGRlZmF1bHQgY29uZmlnIG9iamVjdCBhbmQgZHVibGljYXRlIG9wdGlvbnMgZWFjaCB0aW1lIG9uIGluaXRcbiAgICAgIC8vIEV4dHJhIG1lcmdlIGxldmVsIGZpeGVkIHRoaXMgcHJvYmxlbSBhbmQgYWxsb3cgdG8gaW5pdCBjb25maWcgcHJvcGVybHkgd2l0aG91dCBsZWdhY3kgZGF0YVxuICAgICAge30sXG4gICAgICB7XG4gICAgICAgIHNob3J0Y3V0c0VuYWJsZWQ6IFsnc2hvdycsICdib2xkJywgJ2l0YWxpYycsICd1bmRlcmxpbmUnLCAnaW5kZW50JywgJ291dGRlbnQnLCAndW5kbycsICdyZWRvJywgJ2luc2VydEltYWdlJywgJ2NyZWF0ZUxpbmsnXSxcbiAgICAgICAga2V5OiBjb25maWcuYWN0aXZhdGlvbktleSxcbiAgICAgICAgcGxhY2Vob2xkZXJUZXh0OiBjb25maWcucGxhY2Vob2xkZXIsXG4gICAgICAgIGxpbmtBbHdheXNCbGFuazogdHJ1ZSxcbiAgICAgICAgdGFiU3BhY2VzOiAyLFxuICAgICAgICB0eXBpbmdUaW1lcjogMjUwLFxuICAgICAgICB0b29sdGlwczogZmFsc2UsXG4gICAgICAgIHdvcmRQYXN0ZU1vZGFsOiBmYWxzZSxcbiAgICAgICAgaW1hZ2VEZWZhdWx0V2lkdGg6IDAsXG4gICAgICAgIGltYWdlRGVmYXVsdEFsaWduOiAnbGVmdCcsXG4gICAgICAgIHF1aWNrSW5zZXJ0RW5hYmxlZDogZmFsc2UsXG4gICAgICAgIHNjcm9sbGFibGVDb250YWluZXI6IGAjJHt0aGlzLmNvbnRhaW5lcklEfWAsXG4gICAgICAgIHBhcmFncmFwaERlZmF1bHRTZWxlY3Rpb246ICdGb3JtYXQnLFxuICAgICAgICB2aWRlb1VwbG9hZDogZmFsc2UsXG4gICAgICAgIGltYWdlUGFzdGU6ICEhY29uZmlnLmltYWdlPy51cGxvYWQsXG4gICAgICAgIGltYWdlVXBsb2FkOiAhIWNvbmZpZy5pbWFnZT8udXBsb2FkLFxuICAgICAgICBwYXJhZ3JhcGhGb3JtYXQ6IHtcbiAgICAgICAgICBOOiAnTm9ybWFsJyxcbiAgICAgICAgICBIMTogJ0hlYWRpbmcgMScsXG4gICAgICAgICAgSDI6ICdIZWFkaW5nIDInLFxuICAgICAgICAgIEgzOiAnSGVhZGluZyAzJyxcbiAgICAgICAgICBINDogJ0hlYWRpbmcgNCcsXG4gICAgICAgICAgQkxPQ0tRVU9URTogJ1F1b3RlJyxcbiAgICAgICAgfSxcbiAgICAgICAgbGluZUhlaWdodHM6IHtcbiAgICAgICAgICBEZWZhdWx0OiAnJyxcbiAgICAgICAgICAnMC41JzogJzAuNScsXG4gICAgICAgICAgJ1NpbmdsZSc6ICcxJyxcbiAgICAgICAgICAnMS4xNSc6ICcxLjE1JyxcbiAgICAgICAgICAnMS41JzogJzEuNScsXG4gICAgICAgICAgJ0RvdWJsZSc6ICcyJ1xuICAgICAgICB9LFxuICAgICAgICBwYXJhZ3JhcGhGb3JtYXRTZWxlY3Rpb246IHRydWUsXG4gICAgICAgIHRvb2xiYXJCdXR0b25zWFM6IHtcbiAgICAgICAgICBtb3JlVGV4dDoge1xuICAgICAgICAgICAgYnV0dG9uczogVGV4dEJ1dHRvbnMsXG4gICAgICAgICAgICBidXR0b25zVmlzaWJsZTogMSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIG1vcmVQYXJhZ3JhcGg6IHtcbiAgICAgICAgICAgIGJ1dHRvbnM6IFBhcmFncmFwaEJ1dHRvbnMsXG4gICAgICAgICAgICBidXR0b25zVmlzaWJsZTogMixcbiAgICAgICAgICB9LFxuICAgICAgICAgIG1vcmVSaWNoOiB7XG4gICAgICAgICAgICBidXR0b25zOiBSaWNoQnV0dG9ucyxcbiAgICAgICAgICAgIGJ1dHRvbnNWaXNpYmxlOiAwLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIHRvb2xiYXJCdXR0b25zOiB7XG4gICAgICAgICAgbW9yZVRleHQ6IHtcbiAgICAgICAgICAgIGJ1dHRvbnM6IFRleHRCdXR0b25zLFxuICAgICAgICAgICAgYnV0dG9uc1Zpc2libGU6IDMsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBtb3JlUGFyYWdyYXBoOiB7XG4gICAgICAgICAgICBidXR0b25zOiBQYXJhZ3JhcGhCdXR0b25zLFxuICAgICAgICAgICAgYnV0dG9uc1Zpc2libGU6IDUsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBtb3JlUmljaDoge1xuICAgICAgICAgICAgYnV0dG9uczogUmljaEJ1dHRvbnMsXG4gICAgICAgICAgICBidXR0b25zVmlzaWJsZTogMyxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIGNvbmZpZy5mcm9hbGFDb25maWcsXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgX2xpc3RlbkxhenlJbml0KCkge1xuICAgIHRoaXMuZnJvYWxhTG9hZGVkJFxuICAgICAgLnBpcGUoXG4gICAgICAgIGZpbHRlcigocmVhZHkpID0+IHJlYWR5KSxcbiAgICAgICAgc3dpdGNoTWFwKCgpID0+IHRoaXMuX2luaXRpYWxpemUkKSxcbiAgICAgICAgdGFwKCgpID0+IHtcbiAgICAgICAgICBjb25zdCBzZWxlY3Rpb246IGFueSA9IHdpbmRvdy5nZXRTZWxlY3Rpb24oKTtcbiAgICAgICAgICBjb25zdCBvcHRpb25zOiBhbnkgPSB7fTtcbiAgICAgICAgICBpZiAoc2VsZWN0aW9uLmJhc2VOb2RlKSB7XG4gICAgICAgICAgICBvcHRpb25zLnNlbGVjdGlvbiA9IHtcbiAgICAgICAgICAgICAgbm9kZTogc2VsZWN0aW9uLmJhc2VOb2RlLm5vZGVWYWx1ZSxcbiAgICAgICAgICAgICAgb2Zmc2V0OiBzZWxlY3Rpb24uYmFzZU9mZnNldCxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICAgIHRoaXMuaW5pdGlhbGl6ZShvcHRpb25zKTtcbiAgICAgICAgfSksXG4gICAgICAgIHN3aXRjaE1hcCgoKSA9PiB0aGlzLl9mcm9hbGFSZWFkeSQpLFxuICAgICAgICBmaWx0ZXIoKGRhdGEpID0+ICEhZGF0YSksXG4gICAgICAgIHRhcCgoeyBjb25maWcsIG9wdGlvbnMgfSkgPT4ge1xuICAgICAgICAgIHRoaXMuX3NldHVwRnJvYWxhKGNvbmZpZywgb3B0aW9ucyk7XG4gICAgICAgIH0pXG4gICAgICApXG4gICAgICAuc3Vic2NyaWJlKCk7XG4gIH1cblxuICBwcml2YXRlIF9jb250ZW50Q2hhbmdlZCgpOiB2b2lkIHtcbiAgICBjb25zdCBlZGl0b3JIVE1MID0gdGhpcy5fZWRpdG9yLmh0bWwuZ2V0KCk7XG5cbiAgICBpZiAodGhpcy5odG1sICE9PSBlZGl0b3JIVE1MKSB7XG4gICAgICB0aGlzLl9jaGFuZ2UoZWRpdG9ySFRNTCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfc2V0dXBGcm9hbGEoY29uZmlnOiBGc0h0bWxFZGl0b3JDb25maWcsIG9wdGlvbnM6IGFueSk6IHZvaWQge1xuICAgIHRoaXMuX2NkUmVmLm1hcmtGb3JDaGVjaygpO1xuXG4gICAgdGhpcy5zZXRIdG1sKHRoaXMuX2h0bWwpO1xuXG4gICAgaWYgKGNvbmZpZy5kaXNhYmxlZCkge1xuICAgICAgdGhpcy5kaXNhYmxlKCk7XG4gICAgfVxuXG4gICAgaWYgKGNvbmZpZy5mcm9hbGFDb25maWcuZXZlbnRzKSB7XG4gICAgICBpZiAoY29uZmlnLmZyb2FsYUNvbmZpZy5ldmVudHMuaW5pdGlhbGl6ZWQpIHtcbiAgICAgICAgY29uZmlnLmZyb2FsYUNvbmZpZy5ldmVudHMuaW5pdGlhbGl6ZWQoKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLl9lZGl0b3IuZXZlbnRzLm9uKCdmb2N1cycsICgpID0+IHtcbiAgICAgIHRoaXMuY2xhc3NGb2N1c2VkID0gdHJ1ZTtcbiAgICAgIHRoaXMuX2NkUmVmLm1hcmtGb3JDaGVjaygpO1xuICAgIH0pO1xuXG4gICAgdGhpcy5fZWRpdG9yLmV2ZW50cy5vbignYmx1cicsICgpID0+IHtcbiAgICAgIHRoaXMuY2xhc3NGb2N1c2VkID0gZmFsc2U7XG4gICAgICB0aGlzLl9jZFJlZi5tYXJrRm9yQ2hlY2soKTtcbiAgICB9KTtcblxuICAgIHRoaXMuX2VkaXRvci5ldmVudHMub24oJ2NsaWNrJywgKCkgPT4ge1xuICAgICAgaWYgKHRoaXMuY29uZmlnLmluaXRPbkNsaWNrICYmICF0aGlzLmluaXRpYWxpemVkKSB7XG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZWQgPSB0cnVlO1xuICAgICAgICB0aGlzLl9jZFJlZi5tYXJrRm9yQ2hlY2soKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGZyb21FdmVudFBhdHRlcm4oXG4gICAgICAoaGFuZGxlcikgPT4ge1xuICAgICAgICB0aGlzLl9lZGl0b3IuZXZlbnRzLm9uKCdjb250ZW50Q2hhbmdlZCcsIGhhbmRsZXIpO1xuICAgICAgfSxcbiAgICAgICgpID0+IHsgfVxuICAgIClcbiAgICAgIC5waXBlKFxuICAgICAgICBzdGFydFdpdGgodGhpcy5faHRtbCksXG4gICAgICAgIG1hcCgoKSA9PiB0aGlzLmVkaXRvci5odG1sLmdldCgpKSxcbiAgICAgICAgZGlzdGluY3RVbnRpbENoYW5nZWQoKSxcbiAgICAgICAgc2tpcCgxKSxcbiAgICAgIClcbiAgICAgIC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICB0aGlzLl9jb250ZW50Q2hhbmdlZCgpO1xuICAgICAgfSk7XG5cbiAgICB0aGlzLl9lZGl0b3IuZXZlbnRzLm9uKCdwYXN0ZS5hZnRlckNsZWFudXAnLCAoaHRtbCkgPT4ge1xuICAgICAgdmFyIGRpdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgZGl2LmlubmVySFRNTCA9IGh0bWw7XG4gICAgICBkaXYucXVlcnlTZWxlY3RvckFsbCgnKicpXG4gICAgICAgIC5mb3JFYWNoKChlbCkgPT4ge1xuICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZWwuYXR0cmlidXRlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY29uc3QgbmFtZSA9IGVsLmF0dHJpYnV0ZXNbMF0ubmFtZTtcbiAgICAgICAgICAgIGlmIChuYW1lICE9PSAnaHJlZicpIHtcbiAgICAgICAgICAgICAgZWwucmVtb3ZlQXR0cmlidXRlKG5hbWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICByZXR1cm4gZGl2LmlubmVySFRNTDtcbiAgICB9KTtcblxuICAgIHRoaXMuX2VkaXRvci5ldmVudHMub24oJ2tleWRvd24nLCAoKSA9PiB7XG4gICAgICB0aGlzLm9uVG91Y2hlZCgpO1xuICAgIH0pO1xuXG4gICAgaWYgKHRoaXMuY29uZmlnLmltYWdlICYmIHRoaXMuY29uZmlnLmltYWdlLnVwbG9hZCkge1xuICAgICAgdGhpcy5fZWRpdG9yLmV2ZW50cy5vbignaW1hZ2UuYmVmb3JlUGFzdGVVcGxvYWQnLCAoaW1hZ2UpID0+IHtcblxuICAgICAgICBmZXRjaChpbWFnZS5nZXRBdHRyaWJ1dGUoJ3NyYycpKVxuICAgICAgICAgIC50aGVuKChyZXMpID0+IHtcbiAgICAgICAgICAgIHJlcy5ibG9iKClcbiAgICAgICAgICAgICAgLnRoZW4oKGJsb2IpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLl9wcm9jZXNzSW1hZ2VVcGxvYWQoYmxvYilcbiAgICAgICAgICAgICAgICAgIC5waXBlKFxuICAgICAgICAgICAgICAgICAgICB0YWtlVW50aWwodGhpcy5fZGVzdHJveSQpLFxuICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgLnN1YnNjcmliZSgodXJsKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGltYWdlLnNldEF0dHJpYnV0ZSgnc3JjJywgdXJsKTtcbiAgICAgICAgICAgICAgICAgICAgaW1hZ2UucmVtb3ZlQXR0cmlidXRlKCdkYXRhLWZyLWltYWdlLXBhc3RlZCcpO1xuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2NvbnRlbnRDaGFuZ2VkKCk7XG4gICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfSk7XG5cbiAgICAgIHRoaXMuX2VkaXRvci5ldmVudHMub24oJ2ltYWdlLmJlZm9yZVVwbG9hZCcsIChibG9icykgPT4ge1xuICAgICAgICB0aGlzLl9wcm9jZXNzSW1hZ2VVcGxvYWQoYmxvYnNbMF0pXG4gICAgICAgICAgLnBpcGUoXG4gICAgICAgICAgICB0YWtlVW50aWwodGhpcy5fZGVzdHJveSQpLFxuICAgICAgICAgIClcbiAgICAgICAgICAuc3Vic2NyaWJlKCh1cmwpID0+IHtcbiAgICAgICAgICAgIHRoaXMuZWRpdG9yLmltYWdlLmluc2VydCh1cmwsIG51bGwsIG51bGwsIHRoaXMuZWRpdG9yLmltYWdlLmdldCgpKTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5lbC5xdWVyeVNlbGVjdG9yKCcuZnItc2Vjb25kLXRvb2xiYXInKSkge1xuICAgICAgdGhpcy5lbC5xdWVyeVNlbGVjdG9yKCcuZnItc2Vjb25kLXRvb2xiYXInKS5yZW1vdmUoKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5jb25maWcuYXV0b2ZvY3VzICYmICF0aGlzLmNvbmZpZy5pbml0T25DbGljaykge1xuICAgICAgdGhpcy5mb2N1cygpO1xuICAgIH1cbiAgfVxufVxuIiwiPGZzLWxhYmVsLWZpZWxkPlxuICA8ZnMtbGFiZWwgKm5nSWY9XCJjb25maWcubGFiZWxcIj57e2NvbmZpZy5sYWJlbH19PC9mcy1sYWJlbD5cbiAgPGRpdlxuICAgICAgY2xhc3M9XCJodG1sLWVkaXRvci1jb250YWluZXIgZnMtaHRtbC1lZGl0b3ItZGVmYXVsdFwiXG4gICAgICBbaWRdPVwiY29udGFpbmVySURcIlxuICAgICAgW25nQ2xhc3NdPVwie1xuICAgICAgICBpbml0aWFsaXplZDogaW5pdGlhbGl6ZWQsXG4gICAgICAgICdpbml0LW9uLWNsaWNrJzogY29uZmlnLmluaXRPbkNsaWNrXG4gICAgICB9XCI+XG4gICAgPG5nLWNvbnRhaW5lciAqZnNTa2VsZXRvbj1cIihmcm9hbGFMb2FkZWQkIHwgYXN5bmMpICE9PSBmYWxzZVwiPjwvbmctY29udGFpbmVyPlxuICAgIDxkaXYgI2VsUmVmPjwvZGl2PlxuXG4gICAgPGRpdiBjbGFzcz1cImJvdHRvbS1saW5lXCI+PC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImRpc2FibGVkLWxpbmVcIj48L2Rpdj5cbiAgPC9kaXY+XG5cbiAgPGZzLWxhYmVsLW1lc3NhZ2U+XG4gICAgPGRpdiBjbGFzcz1cImZzLWZvcm0tbWVzc2FnZVwiPlxuICAgICAgPGRpdiBjbGFzcz1cImZzLWZvcm0taGludFwiPnt7aGludH19PC9kaXY+XG4gICAgPC9kaXY+XG4gIDwvZnMtbGFiZWwtbWVzc2FnZT5cbjwvZnMtbGFiZWwtZmllbGQ+XG4iXX0=
|