@ethlete/contentful 2.1.2 → 3.0.0
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/CHANGELOG.md +19 -0
- package/esm2022/index.mjs +2 -1
- package/esm2022/lib/components/audio/contentful-audio.component.mjs +18 -47
- package/esm2022/lib/components/file/contentful-file.component.mjs +14 -36
- package/esm2022/lib/components/image/contentful-image.component.mjs +64 -113
- package/esm2022/lib/components/image/contentful-image.component.utils.mjs +15 -19
- package/esm2022/lib/components/rich-text-renderer/index.mjs +1 -3
- package/esm2022/lib/components/rich-text-renderer/rich-text-renderer.component.mjs +683 -78
- package/esm2022/lib/components/rich-text-renderer/rich-text-renderer.errors.mjs +21 -0
- package/esm2022/lib/components/rich-text-renderer/rich-text-renderer.util.mjs +4 -133
- package/esm2022/lib/components/video/contentful-video.component.mjs +14 -39
- package/esm2022/lib/gql/asset.fragments.mjs +1 -17
- package/esm2022/lib/types/contentful.types.mjs +1 -1
- package/esm2022/lib/utils/contentful.util.mjs +1 -7
- package/fesm2022/ethlete-contentful.mjs +835 -484
- package/fesm2022/ethlete-contentful.mjs.map +1 -1
- package/lib/components/audio/contentful-audio.component.d.ts +6 -11
- package/lib/components/file/contentful-file.component.d.ts +4 -9
- package/lib/components/image/contentful-image.component.d.ts +19 -24
- package/lib/components/image/contentful-image.component.utils.d.ts +2 -2
- package/lib/components/rich-text-renderer/index.d.ts +0 -2
- package/lib/components/rich-text-renderer/rich-text-renderer.component.d.ts +160 -15
- package/lib/components/rich-text-renderer/rich-text-renderer.errors.d.ts +12 -0
- package/lib/components/rich-text-renderer/rich-text-renderer.util.d.ts +4 -17
- package/lib/components/video/contentful-video.component.d.ts +4 -9
- package/lib/gql/asset.fragments.d.ts +0 -1
- package/lib/types/contentful.types.d.ts +92 -48
- package/lib/utils/contentful.util.d.ts +1 -3
- package/package.json +4 -4
- package/esm2022/lib/components/rich-text-renderer/rich-text-renderer.constants.mjs +0 -3
- package/esm2022/lib/components/rich-text-renderer/rich-text-renderer.types.mjs +0 -2
- package/lib/components/rich-text-renderer/rich-text-renderer.constants.d.ts +0 -2
- package/lib/components/rich-text-renderer/rich-text-renderer.types.d.ts +0 -12
|
@@ -1,100 +1,693 @@
|
|
|
1
|
-
import { ComponentPortal, DomPortalOutlet } from '@angular/cdk/portal';
|
|
2
1
|
import { DOCUMENT } from '@angular/common';
|
|
3
|
-
import {
|
|
2
|
+
import { ChangeDetectionStrategy, Component, ElementRef, Renderer2, ViewContainerRef, ViewEncapsulation, computed, inject, input, } from '@angular/core';
|
|
3
|
+
import { takeUntilDestroyed, toObservable, toSignal } from '@angular/core/rxjs-interop';
|
|
4
|
+
import { BLOCKS, INLINES } from '@contentful/rich-text-types';
|
|
5
|
+
import { getObjectProperty, isObject } from '@ethlete/core';
|
|
6
|
+
import { pairwise, startWith, tap } from 'rxjs';
|
|
4
7
|
import { CONTENTFUL_CONFIG } from '../../constants/contentful.constants';
|
|
5
8
|
import { createContentfulConfig } from '../../utils/contentful-config';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { createRenderCommandsFromContentfulRichText } from './rich-text-renderer.util';
|
|
9
|
+
import { richTextRendererError } from './rich-text-renderer.errors';
|
|
10
|
+
import { isRichTextRootNode, translateContentfulNodeTypeToHtmlTag } from './rich-text-renderer.util';
|
|
9
11
|
import * as i0 from "@angular/core";
|
|
12
|
+
export const RENDER_COMMAND_TYPE = {
|
|
13
|
+
HTML_OPEN: 0,
|
|
14
|
+
HTML_CLOSE: 1,
|
|
15
|
+
TEXT: 2,
|
|
16
|
+
COMPONENT: 3,
|
|
17
|
+
};
|
|
18
|
+
export const RENDER_COMMAND_POSITION = {
|
|
19
|
+
TYPE: 0,
|
|
20
|
+
NESTING_LEVEL: 1,
|
|
21
|
+
DOM_POSITION: 2,
|
|
22
|
+
INDEX: 3,
|
|
23
|
+
};
|
|
24
|
+
export const HTML_OPEN_RENDER_COMMAND_POSITION = {
|
|
25
|
+
ATTRIBUTES: 4,
|
|
26
|
+
TAG_NAME: 5,
|
|
27
|
+
ELEMENT_ID: 6,
|
|
28
|
+
};
|
|
29
|
+
export const HTML_CLOSE_RENDER_COMMAND_POSITION = {
|
|
30
|
+
TAG_NAME: 4,
|
|
31
|
+
ELEMENT_ID: 5,
|
|
32
|
+
};
|
|
33
|
+
export const TEXT_RENDER_COMMAND_POSITION = {
|
|
34
|
+
TEXT: 4,
|
|
35
|
+
};
|
|
36
|
+
export const COMPONENT_RENDER_COMMAND_POSITION = {
|
|
37
|
+
ATTRIBUTES: 4,
|
|
38
|
+
COMPONENT: 5,
|
|
39
|
+
INPUTS: 6,
|
|
40
|
+
COMPONENT_TYPE: 7,
|
|
41
|
+
};
|
|
42
|
+
export const RENDER_INSTRUCTION_POSITION = {
|
|
43
|
+
TYPE: 0,
|
|
44
|
+
COMMAND: 1,
|
|
45
|
+
};
|
|
46
|
+
export const RENDER_INSTRUCTION_TYPE = {
|
|
47
|
+
CREATE: 0,
|
|
48
|
+
UPDATE: 1,
|
|
49
|
+
DELETE: 2,
|
|
50
|
+
MOVE: 3,
|
|
51
|
+
};
|
|
52
|
+
const MARK_TAILWIND_MAP = {
|
|
53
|
+
bold: 'font-bold',
|
|
54
|
+
italic: 'italic',
|
|
55
|
+
underline: 'underline',
|
|
56
|
+
code: 'font-mono',
|
|
57
|
+
};
|
|
58
|
+
export const marksToClass = (marks) => {
|
|
59
|
+
const classes = [];
|
|
60
|
+
for (const mark of marks) {
|
|
61
|
+
let klass = MARK_TAILWIND_MAP[mark.type];
|
|
62
|
+
if (!klass) {
|
|
63
|
+
console.warn(`No class found for mark type! Falling back to "${mark.type}".`, mark);
|
|
64
|
+
klass = mark.type;
|
|
65
|
+
}
|
|
66
|
+
classes.push(klass);
|
|
67
|
+
}
|
|
68
|
+
return classes.join(' ');
|
|
69
|
+
};
|
|
70
|
+
export const isHtmlOpenRenderCommand = (command) => {
|
|
71
|
+
return command[RENDER_COMMAND_POSITION.TYPE] === RENDER_COMMAND_TYPE.HTML_OPEN;
|
|
72
|
+
};
|
|
73
|
+
export const isHtmlCloseRenderCommand = (command) => {
|
|
74
|
+
return command[RENDER_COMMAND_POSITION.TYPE] === RENDER_COMMAND_TYPE.HTML_CLOSE;
|
|
75
|
+
};
|
|
76
|
+
export const isTextRenderCommand = (command) => {
|
|
77
|
+
return command[RENDER_COMMAND_POSITION.TYPE] === RENDER_COMMAND_TYPE.TEXT;
|
|
78
|
+
};
|
|
79
|
+
export const isComponentRenderCommand = (command) => {
|
|
80
|
+
return command[RENDER_COMMAND_POSITION.TYPE] === RENDER_COMMAND_TYPE.COMPONENT;
|
|
81
|
+
};
|
|
82
|
+
export const getRenderCommandId = (command) => {
|
|
83
|
+
if (isHtmlOpenRenderCommand(command)) {
|
|
84
|
+
return command[HTML_OPEN_RENDER_COMMAND_POSITION.ELEMENT_ID];
|
|
85
|
+
}
|
|
86
|
+
else if (isHtmlCloseRenderCommand(command)) {
|
|
87
|
+
return command[HTML_CLOSE_RENDER_COMMAND_POSITION.ELEMENT_ID];
|
|
88
|
+
}
|
|
89
|
+
else if (isTextRenderCommand(command)) {
|
|
90
|
+
return command[TEXT_RENDER_COMMAND_POSITION.TEXT];
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
return command[COMPONENT_RENDER_COMMAND_POSITION.COMPONENT_TYPE];
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
const CLASS_ATTR = 'class';
|
|
97
|
+
const DEFAULT_COMPONENT_TYPES = {
|
|
98
|
+
IMAGE: '$$$_et-image',
|
|
99
|
+
VIDEO: '$$$_et-video',
|
|
100
|
+
AUDIO: '$$$_et-audio',
|
|
101
|
+
FILE: '$$$_et-file',
|
|
102
|
+
};
|
|
103
|
+
export const isExecutedComponentCommandCacheItem = (cache) => {
|
|
104
|
+
return isComponentRenderCommand(cache.command);
|
|
105
|
+
};
|
|
106
|
+
export const isExecutedHtmlOrTextCommandCacheItem = (cache) => {
|
|
107
|
+
return isHtmlCloseRenderCommand(cache.command) || isHtmlOpenRenderCommand(cache.command);
|
|
108
|
+
};
|
|
109
|
+
export const isExecutedTextCommandCacheItem = (cache) => {
|
|
110
|
+
return isTextRenderCommand(cache.command);
|
|
111
|
+
};
|
|
10
112
|
export class ContentfulRichTextRendererComponent {
|
|
11
113
|
constructor() {
|
|
12
|
-
this.
|
|
114
|
+
this._viewContainerRef = inject(ViewContainerRef);
|
|
13
115
|
this._renderer = inject(Renderer2);
|
|
14
116
|
this._elementRef = inject(ElementRef);
|
|
15
|
-
this._componentFactoryResolver = inject(ComponentFactoryResolver);
|
|
16
117
|
this._document = inject(DOCUMENT);
|
|
17
|
-
this._appRef = inject(ApplicationRef);
|
|
18
|
-
this._injector = inject(Injector);
|
|
19
118
|
this._config = inject(CONTENTFUL_CONFIG, { optional: true }) ?? createContentfulConfig();
|
|
119
|
+
/**
|
|
120
|
+
* A cache for all executed commands that are not deleted.
|
|
121
|
+
* This is used to keep track of all rendered elements and components.
|
|
122
|
+
* The key is the render command element ID.
|
|
123
|
+
*/
|
|
124
|
+
this._executedCommandsCache = new Map();
|
|
125
|
+
/**
|
|
126
|
+
* The contentful response gotten via their REST api.
|
|
127
|
+
* @see https://www.contentful.com/developers/docs/references/content-delivery-api/#/reference/entries/entries-collection
|
|
128
|
+
*/
|
|
129
|
+
this.content = input.required();
|
|
130
|
+
/**
|
|
131
|
+
* The path to where the rich text field is inside the contentful response. Dot and array notation is allowed.
|
|
132
|
+
* @default "items[0].fields.html"
|
|
133
|
+
*/
|
|
134
|
+
this.richTextPath = input.required();
|
|
135
|
+
/**
|
|
136
|
+
* A map of all includes in the contentful response.
|
|
137
|
+
* This is useful for looking up assets and entries that are referenced in the rich text without having to use loops.
|
|
138
|
+
*/
|
|
139
|
+
this.contentIncludesMap = computed(() => {
|
|
140
|
+
const content = this.content();
|
|
141
|
+
const assets = content?.includes.Asset;
|
|
142
|
+
const entries = content?.includes.Entry;
|
|
143
|
+
return {
|
|
144
|
+
assets: assets?.reduce((acc, asset) => {
|
|
145
|
+
acc[asset.sys.id] = asset;
|
|
146
|
+
return acc;
|
|
147
|
+
}, {}) ?? {},
|
|
148
|
+
entries: entries?.reduce((acc, entry) => {
|
|
149
|
+
acc[entry.sys.id] = entry;
|
|
150
|
+
return acc;
|
|
151
|
+
}, {}) ?? {},
|
|
152
|
+
};
|
|
153
|
+
});
|
|
154
|
+
/**
|
|
155
|
+
* The rich text data that should be rendered.
|
|
156
|
+
*/
|
|
157
|
+
this.richTextData = computed(() => {
|
|
158
|
+
const content = this.content();
|
|
159
|
+
const richTextPath = this.richTextPath();
|
|
160
|
+
if (!content) {
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
const richText = getObjectProperty(content, richTextPath);
|
|
164
|
+
if (!isObject(richText)) {
|
|
165
|
+
throw richTextRendererError('rich_text_undefined', false, { content, richTextPath });
|
|
166
|
+
}
|
|
167
|
+
if (!isRichTextRootNode(richText)) {
|
|
168
|
+
throw richTextRendererError('rich_text_wrong_type', false, { content, richTextPath });
|
|
169
|
+
}
|
|
170
|
+
return richText;
|
|
171
|
+
});
|
|
172
|
+
this.renderCommands = computed(() => {
|
|
173
|
+
const richTextData = this.richTextData();
|
|
174
|
+
if (!richTextData) {
|
|
175
|
+
return [];
|
|
176
|
+
}
|
|
177
|
+
return this._createRenderCommands(richTextData);
|
|
178
|
+
});
|
|
179
|
+
this.renderCommandHistory = toSignal(toObservable(this.renderCommands).pipe(startWith([]), pairwise()), { initialValue: [[], []] });
|
|
180
|
+
this.previousRenderCommandMap = computed(() => {
|
|
181
|
+
const [prevCommands] = this.renderCommandHistory();
|
|
182
|
+
const map = new Map();
|
|
183
|
+
for (const command of prevCommands) {
|
|
184
|
+
map.set(getRenderCommandId(command), command);
|
|
185
|
+
}
|
|
186
|
+
return map;
|
|
187
|
+
});
|
|
188
|
+
this.renderInstructions = computed(() => {
|
|
189
|
+
const commands = this.renderCommands();
|
|
190
|
+
const previousRenderCommandMap = new Map(this.previousRenderCommandMap());
|
|
191
|
+
const instructions = [];
|
|
192
|
+
// remove deleted components as well as all other elements
|
|
193
|
+
for (const [, command] of previousRenderCommandMap) {
|
|
194
|
+
if (isComponentRenderCommand(command)) {
|
|
195
|
+
// keep the component around if it's still in the new commands
|
|
196
|
+
if (commands.some((c) => getRenderCommandId(c) === getRenderCommandId(command))) {
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
instructions.push([RENDER_INSTRUCTION_TYPE.DELETE, command]);
|
|
201
|
+
// remove from map to mark as used
|
|
202
|
+
previousRenderCommandMap.delete(getRenderCommandId(command));
|
|
203
|
+
}
|
|
204
|
+
// Find the indexes of the commands remaining in the previousRenderCommandMap in the new commands array.
|
|
205
|
+
const lastComponentIndexes = [];
|
|
206
|
+
for (const [id, command] of previousRenderCommandMap) {
|
|
207
|
+
const index = commands.findIndex((c) => getRenderCommandId(c) === id);
|
|
208
|
+
const newCommand = commands[index];
|
|
209
|
+
if (index === -1) {
|
|
210
|
+
throw new Error('Command not found!');
|
|
211
|
+
}
|
|
212
|
+
lastComponentIndexes.push({
|
|
213
|
+
newIndex: index,
|
|
214
|
+
prevIndex: command[RENDER_COMMAND_POSITION.INDEX],
|
|
215
|
+
command: newCommand,
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
lastComponentIndexes.sort((a, b) => a.newIndex - b.newIndex);
|
|
219
|
+
// check if the prevIndex are in order ascending
|
|
220
|
+
// for indexes that are not in order, create a move instruction
|
|
221
|
+
// for indexes that are in order, create an update instruction
|
|
222
|
+
let moveCheckIndex = 0;
|
|
223
|
+
while (moveCheckIndex < lastComponentIndexes.length - 1) {
|
|
224
|
+
const moveCurr = lastComponentIndexes[moveCheckIndex];
|
|
225
|
+
const moveNext = lastComponentIndexes[moveCheckIndex + 1];
|
|
226
|
+
if (!moveCurr || !moveNext) {
|
|
227
|
+
break;
|
|
228
|
+
}
|
|
229
|
+
if (moveCurr.prevIndex > moveNext.prevIndex) {
|
|
230
|
+
lastComponentIndexes.splice(moveCheckIndex + 1, 1);
|
|
231
|
+
instructions.push([RENDER_INSTRUCTION_TYPE.MOVE, moveNext.command]);
|
|
232
|
+
}
|
|
233
|
+
else {
|
|
234
|
+
instructions.push([RENDER_INSTRUCTION_TYPE.UPDATE, moveNext.command]);
|
|
235
|
+
moveCheckIndex++;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
for (const command of commands) {
|
|
239
|
+
const id = getRenderCommandId(command);
|
|
240
|
+
if (isComponentRenderCommand(command)) {
|
|
241
|
+
const previousCommand = previousRenderCommandMap.get(id);
|
|
242
|
+
if (!previousCommand) {
|
|
243
|
+
// create
|
|
244
|
+
instructions.push([RENDER_INSTRUCTION_TYPE.CREATE, command]);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
// create
|
|
249
|
+
instructions.push([RENDER_INSTRUCTION_TYPE.CREATE, command]);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return instructions;
|
|
253
|
+
});
|
|
254
|
+
toObservable(this.renderInstructions)
|
|
255
|
+
.pipe(takeUntilDestroyed(), tap((instructions) => {
|
|
256
|
+
this._execInstructions(instructions);
|
|
257
|
+
}))
|
|
258
|
+
.subscribe();
|
|
259
|
+
}
|
|
260
|
+
_createRenderCommands(richTextData) {
|
|
261
|
+
/** List of all render commands */
|
|
262
|
+
const rootCommands = [];
|
|
263
|
+
/** Counter for generating unique html element IDs. */
|
|
264
|
+
let elementId = 0;
|
|
265
|
+
/** Counter for generating unique component IDs. */
|
|
266
|
+
const componentIdMap = new Map();
|
|
267
|
+
/** The nesting level of the current node. */
|
|
268
|
+
let nestingLevel = 0;
|
|
269
|
+
/** The position (index) of the current node inside the parent node. */
|
|
270
|
+
let domPosition = 0;
|
|
271
|
+
let commandIndex = 0;
|
|
272
|
+
const traverse = (node, parent = null) => {
|
|
273
|
+
switch (node.nodeType) {
|
|
274
|
+
case 'text': {
|
|
275
|
+
// Render media
|
|
276
|
+
const type = RENDER_COMMAND_TYPE.TEXT;
|
|
277
|
+
const text = node.value;
|
|
278
|
+
if (!text)
|
|
279
|
+
break;
|
|
280
|
+
const command = [type, nestingLevel, domPosition, commandIndex++, text];
|
|
281
|
+
rootCommands.push(command);
|
|
282
|
+
domPosition++;
|
|
283
|
+
if (!parent) {
|
|
284
|
+
throw richTextRendererError('text_parent_not_found', false, { node });
|
|
285
|
+
}
|
|
286
|
+
if (!isHtmlOpenRenderCommand(parent) && !isComponentRenderCommand(parent)) {
|
|
287
|
+
throw richTextRendererError('text_parent_wrong_type', false, { node, parent });
|
|
288
|
+
}
|
|
289
|
+
const attributesPosition = parent[RENDER_COMMAND_POSITION.TYPE] === RENDER_COMMAND_TYPE.HTML_OPEN
|
|
290
|
+
? HTML_OPEN_RENDER_COMMAND_POSITION.ATTRIBUTES
|
|
291
|
+
: COMPONENT_RENDER_COMMAND_POSITION.ATTRIBUTES;
|
|
292
|
+
const attributes = parent[attributesPosition];
|
|
293
|
+
if (node.marks.length) {
|
|
294
|
+
const markClasses = marksToClass(node.marks);
|
|
295
|
+
if (CLASS_ATTR in attributes) {
|
|
296
|
+
attributes[CLASS_ATTR] += ` ${markClasses}`;
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
attributes[CLASS_ATTR] = markClasses;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
break;
|
|
303
|
+
}
|
|
304
|
+
case BLOCKS.EMBEDDED_ASSET: {
|
|
305
|
+
// Render media
|
|
306
|
+
const type = RENDER_COMMAND_TYPE.COMPONENT;
|
|
307
|
+
const assetId = node.data['target']?.sys?.id;
|
|
308
|
+
if (!assetId) {
|
|
309
|
+
throw richTextRendererError('asset_id_not_found', false, { node });
|
|
310
|
+
}
|
|
311
|
+
const asset = this.contentIncludesMap().assets[assetId];
|
|
312
|
+
if (!asset) {
|
|
313
|
+
throw richTextRendererError('asset_not_found', false, { assetId, node });
|
|
314
|
+
}
|
|
315
|
+
const contentType = asset.fields.file.contentType;
|
|
316
|
+
const assetComponents = this._config.components;
|
|
317
|
+
const isImage = contentType.startsWith('image/');
|
|
318
|
+
const isVideo = contentType.startsWith('video/');
|
|
319
|
+
const isAudio = contentType.startsWith('audio/');
|
|
320
|
+
const component = isImage
|
|
321
|
+
? assetComponents.image
|
|
322
|
+
: isVideo
|
|
323
|
+
? assetComponents.video
|
|
324
|
+
: isAudio
|
|
325
|
+
? assetComponents.audio
|
|
326
|
+
: assetComponents.file;
|
|
327
|
+
const componentType = isImage
|
|
328
|
+
? DEFAULT_COMPONENT_TYPES.IMAGE
|
|
329
|
+
: isVideo
|
|
330
|
+
? DEFAULT_COMPONENT_TYPES.VIDEO
|
|
331
|
+
: isAudio
|
|
332
|
+
? DEFAULT_COMPONENT_TYPES.AUDIO
|
|
333
|
+
: DEFAULT_COMPONENT_TYPES.FILE;
|
|
334
|
+
let componentId = componentIdMap.get(componentType) ?? -1;
|
|
335
|
+
const id = componentType + ++componentId;
|
|
336
|
+
componentIdMap.set(componentType, componentId);
|
|
337
|
+
const attributes = {};
|
|
338
|
+
const inputs = {
|
|
339
|
+
asset,
|
|
340
|
+
};
|
|
341
|
+
const command = [
|
|
342
|
+
type,
|
|
343
|
+
nestingLevel,
|
|
344
|
+
domPosition,
|
|
345
|
+
commandIndex++,
|
|
346
|
+
attributes,
|
|
347
|
+
component,
|
|
348
|
+
inputs,
|
|
349
|
+
id,
|
|
350
|
+
];
|
|
351
|
+
rootCommands.push(command);
|
|
352
|
+
domPosition++;
|
|
353
|
+
break;
|
|
354
|
+
}
|
|
355
|
+
case BLOCKS.EMBEDDED_ENTRY:
|
|
356
|
+
case INLINES.EMBEDDED_ENTRY: {
|
|
357
|
+
// Render component
|
|
358
|
+
const type = RENDER_COMMAND_TYPE.COMPONENT;
|
|
359
|
+
const entryId = node.data['target']?.sys?.id;
|
|
360
|
+
if (!entryId) {
|
|
361
|
+
throw richTextRendererError('entry_id_not_found', false, { node });
|
|
362
|
+
}
|
|
363
|
+
const entry = this.contentIncludesMap().entries[entryId];
|
|
364
|
+
if (!entry) {
|
|
365
|
+
throw richTextRendererError('entry_not_found', false, { entryId, node });
|
|
366
|
+
}
|
|
367
|
+
const componentType = entry.sys.contentType.sys.id;
|
|
368
|
+
const component = this._config.customComponents[componentType];
|
|
369
|
+
if (!component) {
|
|
370
|
+
throw richTextRendererError('custom_component_not_found', false, {
|
|
371
|
+
componentType,
|
|
372
|
+
customComponents: this._config.customComponents,
|
|
373
|
+
entry,
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
const attributes = {};
|
|
377
|
+
let componentId = componentIdMap.get(componentType) ?? -1;
|
|
378
|
+
const id = componentType + ++componentId;
|
|
379
|
+
componentIdMap.set(componentType, componentId);
|
|
380
|
+
const inputs = {
|
|
381
|
+
fields: entry.fields,
|
|
382
|
+
metadata: entry.metadata,
|
|
383
|
+
sys: entry.sys,
|
|
384
|
+
includes: this.contentIncludesMap(),
|
|
385
|
+
};
|
|
386
|
+
const command = [
|
|
387
|
+
type,
|
|
388
|
+
nestingLevel,
|
|
389
|
+
domPosition,
|
|
390
|
+
commandIndex++,
|
|
391
|
+
attributes,
|
|
392
|
+
component,
|
|
393
|
+
inputs,
|
|
394
|
+
id,
|
|
395
|
+
];
|
|
396
|
+
rootCommands.push(command);
|
|
397
|
+
domPosition++;
|
|
398
|
+
break;
|
|
399
|
+
}
|
|
400
|
+
default: {
|
|
401
|
+
const type = RENDER_COMMAND_TYPE.HTML_OPEN;
|
|
402
|
+
const tag = translateContentfulNodeTypeToHtmlTag(node.nodeType);
|
|
403
|
+
const attributes = {};
|
|
404
|
+
const id = 'e' + elementId++;
|
|
405
|
+
const command = [type, nestingLevel, domPosition, commandIndex++, attributes, tag, id];
|
|
406
|
+
rootCommands.push(command);
|
|
407
|
+
const domPositionAtThisLevel = domPosition;
|
|
408
|
+
// Normal html elements can have children
|
|
409
|
+
for (const child of node.content) {
|
|
410
|
+
domPosition = 0;
|
|
411
|
+
nestingLevel++;
|
|
412
|
+
traverse(child, command);
|
|
413
|
+
nestingLevel--;
|
|
414
|
+
domPosition = domPositionAtThisLevel;
|
|
415
|
+
}
|
|
416
|
+
const lastCommand = rootCommands[rootCommands.length - 1];
|
|
417
|
+
if (lastCommand?.[RENDER_COMMAND_POSITION.TYPE] === RENDER_COMMAND_TYPE.HTML_OPEN) {
|
|
418
|
+
// If the last command is an open command, we can remove it since it's empty
|
|
419
|
+
rootCommands.pop();
|
|
420
|
+
}
|
|
421
|
+
else {
|
|
422
|
+
const closeId = 'e' + elementId++;
|
|
423
|
+
const closeCommand = [
|
|
424
|
+
RENDER_COMMAND_TYPE.HTML_CLOSE,
|
|
425
|
+
nestingLevel,
|
|
426
|
+
domPosition,
|
|
427
|
+
commandIndex++,
|
|
428
|
+
tag,
|
|
429
|
+
closeId,
|
|
430
|
+
];
|
|
431
|
+
rootCommands.push(closeCommand);
|
|
432
|
+
domPosition++;
|
|
433
|
+
}
|
|
434
|
+
if (node.nodeType === INLINES.HYPERLINK) {
|
|
435
|
+
const uri = node.data['uri'];
|
|
436
|
+
attributes['href'] = uri;
|
|
437
|
+
const host = this._document.location.host;
|
|
438
|
+
const isExternal = !uri.includes(host);
|
|
439
|
+
if (isExternal) {
|
|
440
|
+
attributes['target'] = '_blank';
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
break;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
};
|
|
447
|
+
for (const node of richTextData.content) {
|
|
448
|
+
traverse(node, null);
|
|
449
|
+
}
|
|
450
|
+
return rootCommands;
|
|
451
|
+
}
|
|
452
|
+
_execInstructions(instructions) {
|
|
453
|
+
for (const instruction of instructions) {
|
|
454
|
+
const type = instruction[RENDER_INSTRUCTION_POSITION.TYPE];
|
|
455
|
+
const command = instruction[RENDER_INSTRUCTION_POSITION.COMMAND];
|
|
456
|
+
switch (type) {
|
|
457
|
+
case RENDER_INSTRUCTION_TYPE.CREATE:
|
|
458
|
+
this._runCreateInstruction(command);
|
|
459
|
+
break;
|
|
460
|
+
case RENDER_INSTRUCTION_TYPE.UPDATE:
|
|
461
|
+
this._runUpdateInstruction(command);
|
|
462
|
+
break;
|
|
463
|
+
case RENDER_INSTRUCTION_TYPE.MOVE:
|
|
464
|
+
this._runMoveInstruction(command);
|
|
465
|
+
break;
|
|
466
|
+
case RENDER_INSTRUCTION_TYPE.DELETE:
|
|
467
|
+
this._runDeleteInstruction(command);
|
|
468
|
+
break;
|
|
469
|
+
}
|
|
470
|
+
}
|
|
20
471
|
}
|
|
21
|
-
|
|
22
|
-
|
|
472
|
+
_runCreateInstruction(command) {
|
|
473
|
+
const id = getRenderCommandId(command);
|
|
474
|
+
const parentElement = this._findParent(command);
|
|
475
|
+
const nextElement = this._findFollowingElement(command);
|
|
476
|
+
if (isComponentRenderCommand(command)) {
|
|
477
|
+
const componentRef = this._viewContainerRef.createComponent(command[COMPONENT_RENDER_COMMAND_POSITION.COMPONENT]);
|
|
478
|
+
this._updateComponentInputs(command, componentRef);
|
|
479
|
+
const rootNode = this._getComponentRootNode(componentRef);
|
|
480
|
+
this._renderInsertOrAppend(rootNode, parentElement, nextElement);
|
|
481
|
+
this._executedCommandsCache.set(id, {
|
|
482
|
+
command,
|
|
483
|
+
componentRef,
|
|
484
|
+
element: rootNode,
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
else if (isTextRenderCommand(command)) {
|
|
488
|
+
const text = command[TEXT_RENDER_COMMAND_POSITION.TEXT];
|
|
489
|
+
const textNode = this._renderer.createText(text);
|
|
490
|
+
const span = this._renderer.createElement('span');
|
|
491
|
+
this._renderer.appendChild(span, textNode);
|
|
492
|
+
this._renderInsertOrAppend(span, parentElement, nextElement);
|
|
493
|
+
this._executedCommandsCache.set(id, {
|
|
494
|
+
command,
|
|
495
|
+
element: span,
|
|
496
|
+
textNode,
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
else if (isHtmlOpenRenderCommand(command)) {
|
|
500
|
+
const tag = command[HTML_OPEN_RENDER_COMMAND_POSITION.TAG_NAME];
|
|
501
|
+
const attributes = command[HTML_OPEN_RENDER_COMMAND_POSITION.ATTRIBUTES];
|
|
502
|
+
const element = this._renderer.createElement(tag);
|
|
503
|
+
for (const [key, value] of Object.entries(attributes)) {
|
|
504
|
+
this._renderer.setAttribute(element, key, value);
|
|
505
|
+
}
|
|
506
|
+
this._renderInsertOrAppend(element, parentElement, nextElement);
|
|
507
|
+
this._executedCommandsCache.set(id, {
|
|
508
|
+
command,
|
|
509
|
+
element,
|
|
510
|
+
});
|
|
511
|
+
}
|
|
23
512
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
this.
|
|
513
|
+
_runUpdateInstruction(command) {
|
|
514
|
+
const id = getRenderCommandId(command);
|
|
515
|
+
const cached = this._executedCommandsCache.get(id);
|
|
516
|
+
if (!cached) {
|
|
517
|
+
throw new Error('Cached command not found!');
|
|
518
|
+
}
|
|
519
|
+
if (isComponentRenderCommand(command)) {
|
|
520
|
+
if (!isExecutedComponentCommandCacheItem(cached)) {
|
|
521
|
+
throw new Error('Cached command is not a component command!');
|
|
522
|
+
}
|
|
523
|
+
const componentRef = cached.componentRef;
|
|
524
|
+
if (!componentRef) {
|
|
525
|
+
throw new Error('Component ref not found!');
|
|
526
|
+
}
|
|
527
|
+
this._updateComponentInputs(command, componentRef);
|
|
528
|
+
}
|
|
529
|
+
this._executedCommandsCache.set(id, {
|
|
530
|
+
...cached,
|
|
531
|
+
command: command,
|
|
532
|
+
});
|
|
27
533
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
534
|
+
_runMoveInstruction(command) {
|
|
535
|
+
const id = getRenderCommandId(command);
|
|
536
|
+
const cached = this._executedCommandsCache.get(id);
|
|
537
|
+
if (!cached) {
|
|
538
|
+
throw new Error('Cached command not found!');
|
|
33
539
|
}
|
|
34
|
-
if (
|
|
35
|
-
|
|
540
|
+
if (isComponentRenderCommand(command)) {
|
|
541
|
+
if (!isExecutedComponentCommandCacheItem(cached)) {
|
|
542
|
+
throw new Error('Cached command is not a component command!');
|
|
543
|
+
}
|
|
544
|
+
const componentRef = cached.componentRef;
|
|
545
|
+
if (!componentRef) {
|
|
546
|
+
throw new Error('Component ref not found!');
|
|
547
|
+
}
|
|
548
|
+
const rootNode = cached.element;
|
|
549
|
+
const oldParentElement = cached.element.parentElement;
|
|
550
|
+
this._renderer.removeChild(oldParentElement, rootNode);
|
|
551
|
+
const newParentElement = this._findParent(command);
|
|
552
|
+
const nextElement = this._findFollowingElement(command);
|
|
553
|
+
this._renderInsertOrAppend(rootNode, newParentElement, nextElement);
|
|
554
|
+
this._updateComponentInputs(command, componentRef);
|
|
555
|
+
this._executedCommandsCache.set(id, {
|
|
556
|
+
...cached,
|
|
557
|
+
command: command,
|
|
558
|
+
});
|
|
36
559
|
}
|
|
37
|
-
const commands = createRenderCommandsFromContentfulRichText({ data: this._richText, config: this._config });
|
|
38
|
-
this._render(commands);
|
|
39
560
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
if (command
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
561
|
+
_runDeleteInstruction(command) {
|
|
562
|
+
const id = getRenderCommandId(command);
|
|
563
|
+
const cached = this._executedCommandsCache.get(id);
|
|
564
|
+
if (!cached) {
|
|
565
|
+
if (isHtmlCloseRenderCommand(command)) {
|
|
566
|
+
return;
|
|
567
|
+
}
|
|
568
|
+
throw new Error('Cached command not found!');
|
|
569
|
+
}
|
|
570
|
+
if (isComponentRenderCommand(command)) {
|
|
571
|
+
if (!isExecutedComponentCommandCacheItem(cached)) {
|
|
572
|
+
throw new Error('Cached command is not a component command!');
|
|
573
|
+
}
|
|
574
|
+
cached.componentRef?.destroy();
|
|
575
|
+
}
|
|
576
|
+
else if (isTextRenderCommand(command)) {
|
|
577
|
+
this._renderer.removeChild(cached.element?.parentElement, cached.element);
|
|
578
|
+
}
|
|
579
|
+
else if (isHtmlOpenRenderCommand(command)) {
|
|
580
|
+
this._renderer.removeChild(cached.element?.parentElement, cached.element);
|
|
581
|
+
}
|
|
582
|
+
this._executedCommandsCache.delete(id);
|
|
583
|
+
}
|
|
584
|
+
_getComponentRootNode(componentRef) {
|
|
585
|
+
return componentRef.hostView.rootNodes[0];
|
|
586
|
+
}
|
|
587
|
+
_updateComponentInputs(command, componentRef) {
|
|
588
|
+
for (const [key, value] of Object.entries(command[COMPONENT_RENDER_COMMAND_POSITION.INPUTS])) {
|
|
589
|
+
if (!componentRef.instance[key])
|
|
590
|
+
continue;
|
|
591
|
+
componentRef.setInput(key, value);
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
_findParent(command) {
|
|
595
|
+
const hostElement = this._elementRef.nativeElement;
|
|
596
|
+
const nestingLevel = command[RENDER_COMMAND_POSITION.NESTING_LEVEL];
|
|
597
|
+
let parentElement = undefined;
|
|
598
|
+
if (nestingLevel === 0) {
|
|
599
|
+
parentElement = hostElement;
|
|
600
|
+
}
|
|
601
|
+
else {
|
|
602
|
+
// Reverse search all render commands beginning from the current one using a for loop.
|
|
603
|
+
// The parent is found when the command's nesting level ist the same as the current nesting level minus 1.
|
|
604
|
+
// If the parent is not found, throw an error.
|
|
605
|
+
const allCommands = this.renderCommands();
|
|
606
|
+
const currentCommandIndex = command[RENDER_COMMAND_POSITION.INDEX];
|
|
607
|
+
let parentCommand = null;
|
|
608
|
+
for (let i = currentCommandIndex - 1; i >= 0; i--) {
|
|
609
|
+
const cmd = allCommands[i];
|
|
610
|
+
if (!cmd) {
|
|
611
|
+
throw new Error('Command not found!');
|
|
65
612
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
const injector = Injector.create({
|
|
70
|
-
providers: [
|
|
71
|
-
{
|
|
72
|
-
provide: RICH_TEXT_RENDERER_COMPONENT_DATA,
|
|
73
|
-
useValue: command.data,
|
|
74
|
-
},
|
|
75
|
-
],
|
|
76
|
-
parent: this._injector,
|
|
77
|
-
});
|
|
78
|
-
const portal = new DomPortalOutlet(parent, this._componentFactoryResolver, this._appRef, injector, this._document);
|
|
79
|
-
const comp = new ComponentPortal(command.payload);
|
|
80
|
-
const ref = comp.attach(portal);
|
|
81
|
-
if (ref.instance instanceof ContentfulImageComponent) {
|
|
82
|
-
ref.instance.sizes = this._config.imageOptions.sizes;
|
|
83
|
-
ref.instance.srcsetSizes = this._config.imageOptions.srcsetSizes;
|
|
84
|
-
ref.instance.backgroundColor = this._config.imageOptions.backgroundColor;
|
|
613
|
+
if (cmd[RENDER_COMMAND_POSITION.NESTING_LEVEL] === nestingLevel - 1) {
|
|
614
|
+
parentCommand = cmd;
|
|
615
|
+
break;
|
|
85
616
|
}
|
|
86
|
-
|
|
617
|
+
}
|
|
618
|
+
if (!parentCommand) {
|
|
619
|
+
throw new Error('Parent command not found!');
|
|
620
|
+
}
|
|
621
|
+
parentElement = this._executedCommandsCache.get(getRenderCommandId(parentCommand))?.element;
|
|
622
|
+
}
|
|
623
|
+
if (!parentElement) {
|
|
624
|
+
throw new Error('Parent element not found!');
|
|
625
|
+
}
|
|
626
|
+
return parentElement;
|
|
627
|
+
}
|
|
628
|
+
_findFollowingElement(command) {
|
|
629
|
+
const cacheArray = Array.from(this._executedCommandsCache.values());
|
|
630
|
+
let nextElement = undefined;
|
|
631
|
+
const domPosition = command[RENDER_COMMAND_POSITION.DOM_POSITION];
|
|
632
|
+
const nestingLevel = command[RENDER_COMMAND_POSITION.NESTING_LEVEL];
|
|
633
|
+
const type = command[RENDER_COMMAND_POSITION.TYPE];
|
|
634
|
+
// Try to find an already rendered element with a domPosition that is greater than the current domPosition. If there are multiple, use the one with the smallest domPosition.
|
|
635
|
+
// If it does not exist, use .appendChild to simply append the element to the end of the parent element.
|
|
636
|
+
// If it does exist, use .insertBefore to insert the element before the found element.
|
|
637
|
+
for (const cached of cacheArray) {
|
|
638
|
+
if (cached.command[RENDER_COMMAND_POSITION.DOM_POSITION] > domPosition &&
|
|
639
|
+
cached.command[RENDER_COMMAND_POSITION.NESTING_LEVEL] === nestingLevel &&
|
|
640
|
+
// Make sure the element does not find itself
|
|
641
|
+
cached.command[RENDER_COMMAND_POSITION.TYPE] !== type) {
|
|
642
|
+
nextElement = cached.element;
|
|
643
|
+
break;
|
|
87
644
|
}
|
|
88
645
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
646
|
+
return nextElement;
|
|
647
|
+
}
|
|
648
|
+
_renderInsertOrAppend(nodeToRender, parentElement, nextElement) {
|
|
649
|
+
if (nextElement) {
|
|
650
|
+
this._renderer.insertBefore(parentElement, nodeToRender, nextElement);
|
|
651
|
+
}
|
|
652
|
+
else {
|
|
653
|
+
this._renderer.appendChild(parentElement, nodeToRender);
|
|
92
654
|
}
|
|
93
655
|
}
|
|
94
|
-
|
|
95
|
-
|
|
656
|
+
_debugVisualizeRenderCommands(commands) {
|
|
657
|
+
const debug = commands.map((command) => this._stringifyRenderCommand(command)).flat();
|
|
658
|
+
const prettified = formatHTML(debug);
|
|
659
|
+
return prettified;
|
|
660
|
+
}
|
|
661
|
+
_stringifyRenderCommand(command) {
|
|
662
|
+
const nestAttr = `nest="${command[RENDER_COMMAND_POSITION.NESTING_LEVEL]}"`;
|
|
663
|
+
const domAttr = `dom="${command[RENDER_COMMAND_POSITION.DOM_POSITION]}"`;
|
|
664
|
+
if (isHtmlOpenRenderCommand(command)) {
|
|
665
|
+
return `<${command[HTML_OPEN_RENDER_COMMAND_POSITION.TAG_NAME]} ${nestAttr} ${domAttr}>`;
|
|
666
|
+
}
|
|
667
|
+
else if (isHtmlCloseRenderCommand(command)) {
|
|
668
|
+
return `</${command[HTML_CLOSE_RENDER_COMMAND_POSITION.TAG_NAME]} ${nestAttr} ${domAttr}>`;
|
|
669
|
+
}
|
|
670
|
+
else if (isTextRenderCommand(command)) {
|
|
671
|
+
return [`<span ${nestAttr} ${domAttr}>`, command[TEXT_RENDER_COMMAND_POSITION.TEXT], '</span>'];
|
|
672
|
+
}
|
|
673
|
+
else if (isComponentRenderCommand(command)) {
|
|
674
|
+
const selector = command[COMPONENT_RENDER_COMMAND_POSITION.COMPONENT_TYPE];
|
|
675
|
+
return [`<${selector} ${nestAttr} ${domAttr}>`, `</${selector}>`];
|
|
676
|
+
}
|
|
677
|
+
else {
|
|
678
|
+
return 'UNKNOWN';
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
_stringifyRenderInstruction(instruction) {
|
|
682
|
+
const type = instruction[RENDER_INSTRUCTION_POSITION.TYPE];
|
|
683
|
+
const translatedType = Object.entries(RENDER_INSTRUCTION_TYPE).find(([, value]) => value === type)?.[0];
|
|
684
|
+
const command = this._stringifyRenderCommand(instruction[RENDER_INSTRUCTION_POSITION.COMMAND]);
|
|
685
|
+
return `${translatedType}: ${command}`;
|
|
686
|
+
}
|
|
687
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.3", ngImport: i0, type: ContentfulRichTextRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
688
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "17.3.3", type: ContentfulRichTextRendererComponent, isStandalone: true, selector: "et-contentful-rich-text-renderer", inputs: { content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: true, transformFunction: null }, richTextPath: { classPropertyName: "richTextPath", publicName: "richTextPath", isSignal: true, isRequired: true, transformFunction: null } }, host: { classAttribute: "et-contentful-rich-text-renderer" }, ngImport: i0, template: ``, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
96
689
|
}
|
|
97
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.
|
|
690
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.3", ngImport: i0, type: ContentfulRichTextRendererComponent, decorators: [{
|
|
98
691
|
type: Component,
|
|
99
692
|
args: [{
|
|
100
693
|
selector: 'et-contentful-rich-text-renderer',
|
|
@@ -106,7 +699,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.0", ngImpor
|
|
|
106
699
|
class: 'et-contentful-rich-text-renderer',
|
|
107
700
|
},
|
|
108
701
|
}]
|
|
109
|
-
}],
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmljaC10ZXh0LXJlbmRlcmVyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL2xpYnMvY29udGVudGZ1bC9zcmMvbGliL2NvbXBvbmVudHMvcmljaC10ZXh0LXJlbmRlcmVyL3JpY2gtdGV4dC1yZW5kZXJlci5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGVBQWUsRUFBRSxlQUFlLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUN2RSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDM0MsT0FBTyxFQUNMLGNBQWMsRUFDZCx1QkFBdUIsRUFDdkIsU0FBUyxFQUNULHdCQUF3QixFQUN4QixVQUFVLEVBQ1YsUUFBUSxFQUNSLEtBQUssRUFDTCxTQUFTLEVBQ1QsaUJBQWlCLEVBQ2pCLE1BQU0sR0FDUCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxzQ0FBc0MsQ0FBQztBQUV6RSxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUN2RSxPQUFPLEVBQUUsd0JBQXdCLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDcEQsT0FBTyxFQUFFLGlDQUFpQyxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFFbkYsT0FBTyxFQUFFLDBDQUEwQyxFQUFFLE1BQU0sMkJBQTJCLENBQUM7O0FBWXZGLE1BQU0sT0FBTyxtQ0FBbUM7SUFWaEQ7UUFvQlUsY0FBUyxHQUE0QixJQUFJLENBQUM7UUFFMUMsY0FBUyxHQUFHLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUM5QixnQkFBVyxHQUFHLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUNqQyw4QkFBeUIsR0FBRyxNQUFNLENBQUMsd0JBQXdCLENBQUMsQ0FBQztRQUM3RCxjQUFTLEdBQUcsTUFBTSxDQUFXLFFBQVEsQ0FBQyxDQUFDO1FB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O1lBQzVDLElBQUksQ0FBQyxlQUFlLENBQUMsRUFBRSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxPQUFPLElBQUksTUFBTSxFQUFFLENBQUMsQ0FBQztRQUM3RSxDQUFDO0lBQ0gsQ0FBQzs4R0ExR1UsbUNBQW1DO2tHQUFuQyxtQ0FBbUMsNExBUnBDLEVBQUU7OzJGQVFELG1DQUFtQztrQkFWL0MsU0FBUzttQkFBQztvQkFDVCxRQUFRLEVBQUUsa0NBQWtDO29CQUM1QyxRQUFRLEVBQUUsRUFBRTtvQkFDWixhQUFhLEVBQUUsaUJBQWlCLENBQUMsSUFBSTtvQkFDckMsZUFBZSxFQUFFLHVCQUF1QixDQUFDLE1BQU07b0JBQy9DLFVBQVUsRUFBRSxJQUFJO29CQUNoQixJQUFJLEVBQUU7d0JBQ0osS0FBSyxFQUFFLGtDQUFrQztxQkFDMUM7aUJBQ0Y7OEJBR0ssUUFBUTtzQkFEWCxLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50UG9ydGFsLCBEb21Qb3J0YWxPdXRsZXQgfSBmcm9tICdAYW5ndWxhci9jZGsvcG9ydGFsJztcbmltcG9ydCB7IERPQ1VNRU5UIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7XG4gIEFwcGxpY2F0aW9uUmVmLFxuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgQ29tcG9uZW50LFxuICBDb21wb25lbnRGYWN0b3J5UmVzb2x2ZXIsXG4gIEVsZW1lbnRSZWYsXG4gIEluamVjdG9yLFxuICBJbnB1dCxcbiAgUmVuZGVyZXIyLFxuICBWaWV3RW5jYXBzdWxhdGlvbixcbiAgaW5qZWN0LFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENPTlRFTlRGVUxfQ09ORklHIH0gZnJvbSAnLi4vLi4vY29uc3RhbnRzL2NvbnRlbnRmdWwuY29uc3RhbnRzJztcbmltcG9ydCB7IFJpY2hUZXh0UmVzcG9uc2UgfSBmcm9tICcuLi8uLi90eXBlcyc7XG5pbXBvcnQgeyBjcmVhdGVDb250ZW50ZnVsQ29uZmlnIH0gZnJvbSAnLi4vLi4vdXRpbHMvY29udGVudGZ1bC1jb25maWcnO1xuaW1wb3J0IHsgQ29udGVudGZ1bEltYWdlQ29tcG9uZW50IH0gZnJvbSAnLi4vaW1hZ2UnO1xuaW1wb3J0IHsgUklDSF9URVhUX1JFTkRFUkVSX0NPTVBPTkVOVF9EQVRBIH0gZnJvbSAnLi9yaWNoLXRleHQtcmVuZGVyZXIuY29uc3RhbnRzJztcbmltcG9ydCB7IFJpY2hUZXh0UmVuZGVyQ29tbWFuZCB9IGZyb20gJy4vcmljaC10ZXh0LXJlbmRlcmVyLnR5cGVzJztcbmltcG9ydCB7IGNyZWF0ZVJlbmRlckNvbW1hbmRzRnJvbUNvbnRlbnRmdWxSaWNoVGV4dCB9IGZyb20gJy4vcmljaC10ZXh0LXJlbmRlcmVyLnV0aWwnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdldC1jb250ZW50ZnVsLXJpY2gtdGV4dC1yZW5kZXJlcicsXG4gIHRlbXBsYXRlOiBgYCxcbiAgZW5jYXBzdWxhdGlvbjogVmlld0VuY2Fwc3VsYXRpb24uTm9uZSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGhvc3Q6IHtcbiAgICBjbGFzczogJ2V0LWNvbnRlbnRmdWwtcmljaC10ZXh0LXJlbmRlcmVyJyxcbiAgfSxcbn0pXG5leHBvcnQgY2xhc3MgQ29udGVudGZ1bFJpY2hUZXh0UmVuZGVyZXJDb21wb25lbnQge1xuICBASW5wdXQoKVxuICBnZXQgcmljaFRleHQoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3JpY2hUZXh0O1xuICB9XG4gIHNldCByaWNoVGV4dCh2OiBSaWNoVGV4dFJlc3BvbnNlIHwgbnVsbCB8IHVuZGVmaW5lZCkge1xuICAgIHRoaXMuX3JpY2hUZXh0ID0gdiA/PyBudWxsO1xuXG4gICAgdGhpcy5yZXNldEFuZFJlbmRlcigpO1xuICB9XG4gIHByaXZhdGUgX3JpY2hUZXh0OiBSaWNoVGV4dFJlc3BvbnNlIHwgbnVsbCA9IG51bGw7XG5cbiAgcHJpdmF0ZSBfcmVuZGVyZXIgPSBpbmplY3QoUmVuZGVyZXIyKTtcbiAgcHJpdmF0ZSBfZWxlbWVudFJlZiA9IGluamVjdChFbGVtZW50UmVmKTtcbiAgcHJpdmF0ZSBfY29tcG9uZW50RmFjdG9yeVJlc29sdmVyID0gaW5qZWN0KENvbXBvbmVudEZhY3RvcnlSZXNvbHZlcik7XG4gIHByaXZhdGUgX2RvY3VtZW50ID0gaW5qZWN0PERvY3VtZW50PihET0NVTUVOVCk7XG4gIHByaXZhdGUgX2FwcFJlZiA9IGluamVjdChBcHBsaWNhdGlvblJlZik7XG4gIHByaXZhdGUgX2luamVjdG9yID0gaW5qZWN0KEluamVjdG9yKTtcbiAgcHJpdmF0ZSBfY29uZmlnID0gaW5qZWN0KENPTlRFTlRGVUxfQ09ORklHLCB7IG9wdGlvbmFsOiB0cnVlIH0pID8/IGNyZWF0ZUNvbnRlbnRmdWxDb25maWcoKTtcblxuICByZXNldEFuZFJlbmRlcigpIHtcbiAgICAvLyBjbGVhciBjaGlsZE5vZGVzIHRvIHByZXZlbnQgYXBwZW5kaW5nIG5ldyByaWNodGV4dCBlbGVtZW50cyB0byBleGlzdGluZyBvbmVcbiAgICBjb25zdCBjaGlsZEVsZW1lbnRzID0gdGhpcy5fZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LmNoaWxkTm9kZXM7XG4gICAgZm9yIChjb25zdCBjaGlsZCBvZiBjaGlsZEVsZW1lbnRzKSB7XG4gICAgICB0aGlzLl9yZW5kZXJlci5yZW1vdmVDaGlsZCh0aGlzLl9lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQsIGNoaWxkKTtcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuX3JpY2hUZXh0KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgY29tbWFuZHMgPSBjcmVhdGVSZW5kZXJDb21tYW5kc0Zyb21Db250ZW50ZnVsUmljaFRleHQoeyBkYXRhOiB0aGlzLl9yaWNoVGV4dCwgY29uZmlnOiB0aGlzLl9jb25maWcgfSk7XG5cbiAgICB0aGlzLl9yZW5kZXIoY29tbWFuZHMpO1xuICB9XG5cbiAgcHJpdmF0ZSBfcmVuZGVyKGNvbW1hbmRzOiBSaWNoVGV4dFJlbmRlckNvbW1hbmRbXSkge1xuICAgIC8vIGNyZWF0ZSBhIGRvY3VtZW50IGZyYWdtZW50IHRvIGhvbGQgdGhlIGVsZW1lbnRzIHdoaWxlIHdlIGNyZWF0ZSB0aGVtXG4gICAgY29uc3QgZnJhZ21lbnQgPSBkb2N1bWVudC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCk7XG5cbiAgICBjb25zdCBob3N0Q29tbWFuZDogUmljaFRleHRSZW5kZXJDb21tYW5kID0ge1xuICAgICAgcGF5bG9hZDogJ2RvY3VtZW50JyxcbiAgICAgIGNoaWxkcmVuOiBjb21tYW5kcyxcbiAgICB9O1xuXG4gICAgLy8gbG9vcCBvdmVyIHRoZSBjb21tYW5kc1xuICAgIHRoaXMuX2V4ZWN1dGVDb21tYW5kKHsgY29tbWFuZDogaG9zdENvbW1hbmQsIHBhcmVudDogZnJhZ21lbnQgfSk7XG5cbiAgICAvLyBhcHBlbmQgdGhlIGZyYWdtZW50IHRvIHRoZSBob3N0IGVsZW1lbnRcbiAgICB0aGlzLl9yZW5kZXJlci5hcHBlbmRDaGlsZCh0aGlzLl9lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQsIGZyYWdtZW50KTtcbiAgfVxuXG4gIHByaXZhdGUgX2V4ZWN1dGVDb21tYW5kKGRhdGE6IHsgY29tbWFuZDogUmljaFRleHRSZW5kZXJDb21tYW5kOyBwYXJlbnQ6IEVsZW1lbnQgfCBEb2N1bWVudEZyYWdtZW50IH0pIHtcbiAgICBjb25zdCB7IGNvbW1hbmQsIHBhcmVudCB9ID0gZGF0YTtcblxuICAgIGxldCBlbGVtZW50OiBFbGVtZW50IHwgbnVsbCA9IG51bGw7XG4gICAgaWYgKGNvbW1hbmQucGF5bG9hZCAhPT0gJ2RvY3VtZW50Jykge1xuICAgICAgaWYgKHR5cGVvZiBjb21tYW5kLnBheWxvYWQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGVsZW1lbnQgPSB0aGlzLl9yZW5kZXJlci5jcmVhdGVFbGVtZW50KGNvbW1hbmQucGF5bG9hZCk7XG5cbiAgICAgICAgaWYgKGNvbW1hbmQuZGF0YSkge1xuICAgICAgICAgIHRoaXMuX3JlbmRlcmVyLnNldFByb3BlcnR5KGVsZW1lbnQsICdpbm5lclRleHQnLCBjb21tYW5kLmRhdGEpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGNvbW1hbmQuYXR0cmlidXRlcykge1xuICAgICAgICAgIGZvciAoY29uc3QgW25hbWUsIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhjb21tYW5kLmF0dHJpYnV0ZXMpKSB7XG4gICAgICAgICAgICB0aGlzLl9yZW5kZXJlci5zZXRBdHRyaWJ1dGUoZWxlbWVudCwgbmFtZSwgdmFsdWUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9yZW5kZXJlci5hcHBlbmRDaGlsZChwYXJlbnQsIGVsZW1lbnQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgaW5qZWN0b3IgPSBJbmplY3Rvci5jcmVhdGUoe1xuICAgICAgICAgIHByb3ZpZGVyczogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBwcm92aWRlOiBSSUNIX1RFWFRfUkVOREVSRVJfQ09NUE9ORU5UX0RBVEEsXG4gICAgICAgICAgICAgIHVzZVZhbHVlOiBjb21tYW5kLmRhdGEsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0sXG4gICAgICAgICAgcGFyZW50OiB0aGlzLl9pbmplY3RvcixcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc3QgcG9ydGFsID0gbmV3IERvbVBvcnRhbE91dGxldChcbiAgICAgICAgICBwYXJlbnQgYXMgRWxlbWVudCxcbiAgICAgICAgICB0aGlzLl9jb21wb25lbnRGYWN0b3J5UmVzb2x2ZXIsXG4gICAgICAgICAgdGhpcy5fYXBwUmVmLFxuICAgICAgICAgIGluamVjdG9yLFxuICAgICAgICAgIHRoaXMuX2RvY3VtZW50LFxuICAgICAgICApO1xuXG4gICAgICAgIGNvbnN0IGNvbXAgPSBuZXcgQ29tcG9uZW50UG9ydGFsKGNvbW1hbmQucGF5bG9hZCk7XG4gICAgICAgIGNvbnN0IHJlZiA9IGNvbXAuYXR0YWNoKHBvcnRhbCk7XG5cbiAgICAgICAgaWYgKHJlZi5pbnN0YW5jZSBpbnN0YW5jZW9mIENvbnRlbnRmdWxJbWFnZUNvbXBvbmVudCkge1xuICAgICAgICAgIHJlZi5pbnN0YW5jZS5zaXplcyA9IHRoaXMuX2NvbmZpZy5pbWFnZU9wdGlvbnMuc2l6ZXM7XG4gICAgICAgICAgcmVmLmluc3RhbmNlLnNyY3NldFNpemVzID0gdGhpcy5fY29uZmlnLmltYWdlT3B0aW9ucy5zcmNzZXRTaXplcztcbiAgICAgICAgICByZWYuaW5zdGFuY2UuYmFja2dyb3VuZENvbG9yID0gdGhpcy5fY29uZmlnLmltYWdlT3B0aW9ucy5iYWNrZ3JvdW5kQ29sb3I7XG4gICAgICAgIH1cblxuICAgICAgICBlbGVtZW50ID0gcmVmLmxvY2F0aW9uLm5hdGl2ZUVsZW1lbnQ7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gbG9vcCBvdmVyIHRoZSBjb21tYW5kc1xuICAgIGZvciAoY29uc3QgY2hpbGRDb21tYW5kIG9mIGNvbW1hbmQuY2hpbGRyZW4pIHtcbiAgICAgIHRoaXMuX2V4ZWN1dGVDb21tYW5kKHsgY29tbWFuZDogY2hpbGRDb21tYW5kLCBwYXJlbnQ6IGVsZW1lbnQgPz8gcGFyZW50IH0pO1xuICAgIH1cbiAgfVxufVxuIl19
|
|
702
|
+
}], ctorParameters: () => [] });
|
|
703
|
+
function formatHTML(html) {
|
|
704
|
+
const result = [];
|
|
705
|
+
let indent = 0;
|
|
706
|
+
for (const tag of html) {
|
|
707
|
+
if (tag.startsWith('</')) {
|
|
708
|
+
indent--;
|
|
709
|
+
}
|
|
710
|
+
result.push(' '.repeat(indent * 2) + tag);
|
|
711
|
+
if (tag.startsWith('<') && !tag.startsWith('</')) {
|
|
712
|
+
indent++;
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
return result.join('\n');
|
|
716
|
+
}
|
|
717
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmljaC10ZXh0LXJlbmRlcmVyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL2xpYnMvY29udGVudGZ1bC9zcmMvbGliL2NvbXBvbmVudHMvcmljaC10ZXh0LXJlbmRlcmVyL3JpY2gtdGV4dC1yZW5kZXJlci5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQzNDLE9BQU8sRUFDTCx1QkFBdUIsRUFDdkIsU0FBUyxFQUVULFVBQVUsRUFFVixTQUFTLEVBQ1QsZ0JBQWdCLEVBQ2hCLGlCQUFpQixFQUNqQixRQUFRLEVBQ1IsTUFBTSxFQUNOLEtBQUssR0FDTixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsa0JBQWtCLEVBQUUsWUFBWSxFQUFFLFFBQVEsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ3hGLE9BQU8sRUFBRSxNQUFNLEVBQVMsT0FBTyxFQUFzQixNQUFNLDZCQUE2QixDQUFDO0FBQ3pGLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxRQUFRLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDNUQsT0FBTyxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ2hELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHNDQUFzQyxDQUFDO0FBRXpFLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQ3ZFLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQ3BFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxvQ0FBb0MsRUFBRSxNQUFNLDJCQUEyQixDQUFDOztBQUVyRyxNQUFNLENBQUMsTUFBTSxtQkFBbUIsR0FBRztJQUNqQyxTQUFTLEVBQUUsQ0FBQztJQUNaLFVBQVUsRUFBRSxDQUFDO0lBQ2IsSUFBSSxFQUFF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O21CQUFDO29CQUNULFFBQVEsRUFBRSxrQ0FBa0M7b0JBQzVDLFFBQVEsRUFBRSxFQUFFO29CQUNaLGFBQWEsRUFBRSxpQkFBaUIsQ0FBQyxJQUFJO29CQUNyQyxlQUFlLEVBQUUsdUJBQXVCLENBQUMsTUFBTTtvQkFDL0MsVUFBVSxFQUFFLElBQUk7b0JBQ2hCLElBQUksRUFBRTt3QkFDSixLQUFLLEVBQUUsa0NBQWtDO3FCQUMxQztpQkFDRjs7QUFvdUJELFNBQVMsVUFBVSxDQUFDLElBQWM7SUFDaEMsTUFBTSxNQUFNLEdBQWEsRUFBRSxDQUFDO0lBQzVCLElBQUksTUFBTSxHQUFHLENBQUMsQ0FBQztJQUVmLEtBQUssTUFBTSxHQUFHLElBQUksSUFBSSxFQUFFLENBQUM7UUFDdkIsSUFBSSxHQUFHLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7WUFDekIsTUFBTSxFQUFFLENBQUM7UUFDWCxDQUFDO1FBRUQsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQztRQUUxQyxJQUFJLEdBQUcsQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7WUFDakQsTUFBTSxFQUFFLENBQUM7UUFDWCxDQUFDO0lBQ0gsQ0FBQztJQUVELE9BQU8sTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztBQUMzQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50VHlwZSB9IGZyb20gJ0Bhbmd1bGFyL2Nkay9wb3J0YWwnO1xuaW1wb3J0IHsgRE9DVU1FTlQgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENvbXBvbmVudCxcbiAgQ29tcG9uZW50UmVmLFxuICBFbGVtZW50UmVmLFxuICBFbWJlZGRlZFZpZXdSZWYsXG4gIFJlbmRlcmVyMixcbiAgVmlld0NvbnRhaW5lclJlZixcbiAgVmlld0VuY2Fwc3VsYXRpb24sXG4gIGNvbXB1dGVkLFxuICBpbmplY3QsXG4gIGlucHV0LFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IHRha2VVbnRpbERlc3Ryb3llZCwgdG9PYnNlcnZhYmxlLCB0b1NpZ25hbCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUvcnhqcy1pbnRlcm9wJztcbmltcG9ydCB7IEJMT0NLUywgQmxvY2ssIElOTElORVMsIElubGluZSwgTWFyaywgVGV4dCB9IGZyb20gJ0Bjb250ZW50ZnVsL3JpY2gtdGV4dC10eXBlcyc7XG5pbXBvcnQgeyBnZXRPYmplY3RQcm9wZXJ0eSwgaXNPYmplY3QgfSBmcm9tICdAZXRobGV0ZS9jb3JlJztcbmltcG9ydCB7IHBhaXJ3aXNlLCBzdGFydFdpdGgsIHRhcCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgQ09OVEVOVEZVTF9DT05GSUcgfSBmcm9tICcuLi8uLi9jb25zdGFudHMvY29udGVudGZ1bC5jb25zdGFudHMnO1xuaW1wb3J0IHsgQ29udGVudGZ1bEFzc2V0LCBDb250ZW50ZnVsQ29sbGVjdGlvbiwgQ29udGVudGZ1bEVudHJ5LCBSaWNoVGV4dFJlc3BvbnNlIH0gZnJvbSAnLi4vLi4vdHlwZXMnO1xuaW1wb3J0IHsgY3JlYXRlQ29udGVudGZ1bENvbmZpZyB9IGZyb20gJy4uLy4uL3V0aWxzL2NvbnRlbnRmdWwtY29uZmlnJztcbmltcG9ydCB7IHJpY2hUZXh0UmVuZGVyZXJFcnJvciB9IGZyb20gJy4vcmljaC10ZXh0LXJlbmRlcmVyLmVycm9ycyc7XG5pbXBvcnQgeyBpc1JpY2hUZXh0Um9vdE5vZGUsIHRyYW5zbGF0ZUNvbnRlbnRmdWxOb2RlVHlwZVRvSHRtbFRhZyB9IGZyb20gJy4vcmljaC10ZXh0LXJlbmRlcmVyLnV0aWwnO1xuXG5leHBvcnQgY29uc3QgUkVOREVSX0NPTU1BTkRfVFlQRSA9IHtcbiAgSFRNTF9PUEVOOiAwLFxuICBIVE1MX0NMT1NFOiAxLFxuICBURVhUOiAyLFxuICBDT01QT05FTlQ6IDMsXG59IGFzIGNvbnN0O1xuXG5leHBvcnQgY29uc3QgUkVOREVSX0NPTU1BTkRfUE9TSVRJT04gPSB7XG4gIFRZUEU6IDAsXG4gIE5FU1RJTkdfTEVWRUw6IDEsXG4gIERPTV9QT1NJVElPTjogMixcbiAgSU5ERVg6IDMsXG59IGFzIGNvbnN0O1xuXG5leHBvcnQgY29uc3QgSFRNTF9PUEVOX1JFTkRFUl9DT01NQU5EX1BPU0lUSU9OID0ge1xuICBBVFRSSUJVVEVTOiA0LFxuICBUQUdfTkFNRTogNSxcbiAgRUxFTUVOVF9JRDogNixcbn0gYXMgY29uc3Q7XG5cbmV4cG9ydCBjb25zdCBIVE1MX0NMT1NFX1JFTkRFUl9DT01NQU5EX1BPU0lUSU9OID0ge1xuICBUQUdfTkFNRTogNCxcbiAgRUxFTUVOVF9JRDogNSxcbn0gYXMgY29uc3Q7XG5cbmV4cG9ydCBjb25zdCBURVhUX1JFTkRFUl9DT01NQU5EX1BPU0lUSU9OID0ge1xuICBURVhUOiA0LFxufSBhcyBjb25zdDtcblxuZXhwb3J0IGNvbnN0IENPTVBPTkVOVF9SRU5ERVJfQ09NTUFORF9QT1NJVElPTiA9IHtcbiAgQVRUUklCVVRFUzogNCxcbiAgQ09NUE9ORU5UOiA1LFxuICBJTlBVVFM6IDYsXG4gIENPTVBPTkVOVF9UWVBFOiA3LFxufSBhcyBjb25zdDtcblxudHlwZSBIdG1sT3BlblJlbmRlckNvbW1hbmQgPSBbXG4gIHR5cGU6IHR5cGVvZiBSRU5ERVJfQ09NTUFORF9UWVBFLkhUTUxfT1BFTixcbiAgbmVzdGluZ0xldmVsOiBudW1iZXIsXG4gIGRvbVBvc2l0aW9uOiBudW1iZXIsXG4gIGluZGV4OiBudW1iZXIsXG4gIGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4sXG4gIHRhZ05hbWU6IHN0cmluZyxcbiAgZWxlbWVudElkOiBzdHJpbmcsXG5dO1xuXG50eXBlIEh0bWxDbG9zZVJlbmRlckNvbW1hbmQgPSBbXG4gIHR5cGU6IHR5cGVvZiBSRU5ERVJfQ09NTUFORF9UWVBFLkhUTUxfQ0xPU0UsXG4gIG5lc3RpbmdMZXZlbDogbnVtYmVyLFxuICBkb21Qb3NpdGlvbjogbnVtYmVyLFxuICBpbmRleDogbnVtYmVyLFxuICB0YWdOYW1lOiBzdHJpbmcsXG4gIGVsZW1lbnRJZDogc3RyaW5nLFxuXTtcblxudHlwZSBUZXh0UmVuZGVyQ29tbWFuZCA9IFtcbiAgdHlwZTogdHlwZW9mIFJFTkRFUl9DT01NQU5EX1RZUEUuVEVYVCxcbiAgbmVzdGluZ0xldmVsOiBudW1iZXIsXG4gIGRvbVBvc2l0aW9uOiBudW1iZXIsXG4gIGluZGV4OiBudW1iZXIsXG4gIHRleHQ6IHN0cmluZyxcbl07XG5cbnR5cGUgQ29tcG9uZW50UmVuZGVyQ29tbWFuZCA9IFtcbiAgdHlwZTogdHlwZW9mIFJFTkRFUl9DT01NQU5EX1RZUEUuQ09NUE9ORU5ULFxuICBuZXN0aW5nTGV2ZWw6IG51bWJlcixcbiAgZG9tUG9zaXRpb246IG51bWJlcixcbiAgaW5kZXg6IG51bWJlcixcbiAgYXR0cmlidXRlczogUmVjb3JkPHN0cmluZywgc3RyaW5nPixcbiAgY29tcG9uZW50OiBDb21wb25lbnRUeXBlPHVua25vd24+LFxuICBpbnB1dHM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuICBjb21wb25lbnRUeXBlOiBzdHJpbmcsXG5dO1xuXG50eXBlIFJlbmRlckNvbW1hbmQgPSBIdG1sT3BlblJlbmRlckNvbW1hbmQgfCBIdG1sQ2xvc2VSZW5kZXJDb21tYW5kIHwgVGV4dFJlbmRlckNvbW1hbmQgfCBDb21wb25lbnRSZW5kZXJDb21tYW5kO1xuXG5leHBvcnQgY29uc3QgUkVOREVSX0lOU1RSVUNUSU9OX1BPU0lUSU9OID0ge1xuICBUWVBFOiAwLFxuICBDT01NQU5EOiAxLFxufSBhcyBjb25zdDtcblxuZXhwb3J0IGNvbnN0IFJFTkRFUl9JTlNUUlVDVElPTl9UWVBFID0ge1xuICBDUkVBVEU6IDAsXG4gIFVQREFURTogMSxcbiAgREVMRVRFOiAyLFxuICBNT1ZFOiAzLFxufSBhcyBjb25zdDtcblxudHlwZSBSZW5kZXJJbnN0cnVjdGlvblR5cGVWYWx1ZSA9ICh0eXBlb2YgUkVOREVSX0lOU1RSVUNUSU9OX1RZUEUpW2tleW9mIHR5cGVvZiBSRU5ERVJfSU5TVFJVQ1RJT05fVFlQRV07XG5cbnR5cGUgUmVuZGVySW5zdHJ1Y3Rpb24gPSBbUmVuZGVySW5zdHJ1Y3Rpb25UeXBlVmFsdWUsIFJlbmRlckNvbW1hbmRdO1xuXG5jb25zdCBNQVJLX1RBSUxXSU5EX01BUDogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHtcbiAgYm9sZDogJ2ZvbnQtYm9sZCcsXG4gIGl0YWxpYzogJ2l0YWxpYycsXG4gIHVuZGVybGluZTogJ3VuZGVybGluZScsXG4gIGNvZGU6ICdmb250LW1vbm8nLFxufTtcblxuZXhwb3J0IGNvbnN0IG1hcmtzVG9DbGFzcyA9IChtYXJrczogTWFya1tdKSA9PiB7XG4gIGNvbnN0IGNsYXNzZXM6IHN0cmluZ1tdID0gW107XG5cbiAgZm9yIChjb25zdCBtYXJrIG9mIG1hcmtzKSB7XG4gICAgbGV0IGtsYXNzID0gTUFSS19UQUlMV0lORF9NQVBbbWFyay50eXBlXTtcblxuICAgIGlmICgha2xhc3MpIHtcbiAgICAgIGNvbnNvbGUud2FybihgTm8gY2xhc3MgZm91bmQgZm9yIG1hcmsgdHlwZSEgRmFsbGluZyBiYWNrIHRvIFwiJHttYXJrLnR5cGV9XCIuYCwgbWFyayk7XG5cbiAgICAgIGtsYXNzID0gbWFyay50eXBlO1xuICAgIH1cblxuICAgIGNsYXNzZXMucHVzaChrbGFzcyk7XG4gIH1cblxuICByZXR1cm4gY2xhc3Nlcy5qb2luKCcgJyk7XG59O1xuXG5leHBvcnQgY29uc3QgaXNIdG1sT3BlblJlbmRlckNvbW1hbmQgPSAoY29tbWFuZDogUmVuZGVyQ29tbWFuZCk6IGNvbW1hbmQgaXMgSHRtbE9wZW5SZW5kZXJDb21tYW5kID0+IHtcbiAgcmV0dXJuIGNvbW1hbmRbUkVOREVSX0NPTU1BTkRfUE9TSVRJT04uVFlQRV0gPT09IFJFTkRFUl9DT01NQU5EX1RZUEUuSFRNTF9PUEVOO1xufTtcblxuZXhwb3J0IGNvbnN0IGlzSHRtbENsb3NlUmVuZGVyQ29tbWFuZCA9IChjb21tYW5kOiBSZW5kZXJDb21tYW5kKTogY29tbWFuZCBpcyBIdG1sQ2xvc2VSZW5kZXJDb21tYW5kID0+IHtcbiAgcmV0dXJuIGNvbW1hbmRbUkVOREVSX0NPTU1BTkRfUE9TSVRJT04uVFlQRV0gPT09IFJFTkRFUl9DT01NQU5EX1RZUEUuSFRNTF9DTE9TRTtcbn07XG5cbmV4cG9ydCBjb25zdCBpc1RleHRSZW5kZXJDb21tYW5kID0gKGNvbW1hbmQ6IFJlbmRlckNvbW1hbmQpOiBjb21tYW5kIGlzIFRleHRSZW5kZXJDb21tYW5kID0+IHtcbiAgcmV0dXJuIGNvbW1hbmRbUkVOREVSX0NPTU1BTkRfUE9TSVRJT04uVFlQRV0gPT09IFJFTkRFUl9DT01NQU5EX1RZUEUuVEVYVDtcbn07XG5cbmV4cG9ydCBjb25zdCBpc0NvbXBvbmVudFJlbmRlckNvbW1hbmQgPSAoY29tbWFuZDogUmVuZGVyQ29tbWFuZCk6IGNvbW1hbmQgaXMgQ29tcG9uZW50UmVuZGVyQ29tbWFuZCA9PiB7XG4gIHJldHVybiBjb21tYW5kW1JFTkRFUl9DT01NQU5EX1BPU0lUSU9OLlRZUEVdID09PSBSRU5ERVJfQ09NTUFORF9UWVBFLkNPTVBPTkVOVDtcbn07XG5cbmV4cG9ydCBjb25zdCBnZXRSZW5kZXJDb21tYW5kSWQgPSAoY29tbWFuZDogUmVuZGVyQ29tbWFuZCkgPT4ge1xuICBpZiAoaXNIdG1sT3BlblJlbmRlckNvbW1hbmQoY29tbWFuZCkpIHtcbiAgICByZXR1cm4gY29tbWFuZFtIVE1MX09QRU5fUkVOREVSX0NPTU1BTkRfUE9TSVRJT04uRUxFTUVOVF9JRF07XG4gIH0gZWxzZSBpZiAoaXNIdG1sQ2xvc2VSZW5kZXJDb21tYW5kKGNvbW1hbmQpKSB7XG4gICAgcmV0dXJuIGNvbW1hbmRbSFRNTF9DTE9TRV9SRU5ERVJfQ09NTUFORF9QT1NJVElPTi5FTEVNRU5UX0lEXTtcbiAgfSBlbHNlIGlmIChpc1RleHRSZW5kZXJDb21tYW5kKGNvbW1hbmQpKSB7XG4gICAgcmV0dXJuIGNvbW1hbmRbVEVYVF9SRU5ERVJfQ09NTUFORF9QT1NJVElPTi5URVhUXTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gY29tbWFuZFtDT01QT05FTlRfUkVOREVSX0NPTU1BTkRfUE9TSVRJT04uQ09NUE9ORU5UX1RZUEVdO1xuICB9XG59O1xuXG5jb25zdCBDTEFTU19BVFRSID0gJ2NsYXNzJztcbmNvbnN0IERFRkFVTFRfQ09NUE9ORU5UX1RZUEVTID0ge1xuICBJTUFHRTogJyQkJF9ldC1pbWFnZScsXG4gIFZJREVPOiAnJCQkX2V0LXZpZGVvJyxcbiAgQVVESU86ICckJCRfZXQtYXVkaW8nLFxuICBGSUxFOiAnJCQkX2V0LWZpbGUnLFxufTtcblxudHlwZSBFeGVjdXRlZENvbW1hbmRDYWNoZUl0ZW1CYXNlID0ge1xuICBlbGVtZW50OiBIVE1MRWxlbWVudDtcbn07XG5cbnR5cGUgRXhlY3V0ZWRDb21wb25lbnRDb21tYW5kQ2FjaGVJdGVtID0ge1xuICBjb21tYW5kOiBDb21wb25lbnRSZW5kZXJDb21tYW5kO1xuICBjb21wb25lbnRSZWY6IENvbXBvbmVudFJlZjx1bmtub3duPjtcbn0gJiBFeGVjdXRlZENvbW1hbmRDYWNoZUl0ZW1CYXNlO1xuXG50eXBlIEV4ZWN1dGVkSHRtbENvbW1hbmRDYWNoZUl0ZW0gPSB7XG4gIGNvbW1hbmQ6IEh0bWxPcGVuUmVuZGVyQ29tbWFuZCB8IEh0bWxDbG9zZVJlbmRlckNvbW1hbmQ7XG59ICYgRXhlY3V0ZWRDb21tYW5kQ2FjaGVJdGVtQmFzZTtcblxudHlwZSBFeGVjdXRlZFRleHRDb21tYW5kQ2FjaGVJdGVtID0ge1xuICBjb21tYW5kOiBUZXh0UmVuZGVyQ29tbWFuZDtcbiAgdGV4dE5vZGU6IHVua25vd247XG59ICYgRXhlY3V0ZWRDb21tYW5kQ2FjaGVJdGVtQmFzZTtcblxudHlwZSBFeGVjdXRlZENvbW1hbmRDYWNoZUl0ZW0gPVxuICB8IEV4ZWN1dGVkQ29tcG9uZW50Q29tbWFuZENhY2hlSXRlbVxuICB8IEV4ZWN1dGVkSHRtbENvbW1hbmRDYWNoZUl0ZW1cbiAgfCBFeGVjdXRlZFRleHRDb21tYW5kQ2FjaGVJdGVtO1xuXG5leHBvcnQgY29uc3QgaXNFeGVjdXRlZENvbXBvbmVudENvbW1hbmRDYWNoZUl0ZW0gPSAoXG4gIGNhY2hlOiBFeGVjdXRlZENvbW1hbmRDYWNoZUl0ZW0sXG4pOiBjYWNoZSBpcyBFeGVjdXRlZENvbXBvbmVudENvbW1hbmRDYWNoZUl0ZW0gPT4ge1xuICByZXR1cm4gaXNDb21wb25lbnRSZW5kZXJDb21tYW5kKGNhY2hlLmNvbW1hbmQpO1xufTtcblxuZXhwb3J0IGNvbnN0IGlzRXhlY3V0ZWRIdG1sT3JUZXh0Q29tbWFuZENhY2hlSXRlbSA9IChcbiAgY2FjaGU6IEV4ZWN1dGVkQ29tbWFuZENhY2hlSXRlbSxcbik6IGNhY2hlIGlzIEV4ZWN1dGVkSHRtbENvbW1hbmRDYWNoZUl0ZW0gPT4ge1xuICByZXR1cm4gaXNIdG1sQ2xvc2VSZW5kZXJDb21tYW5kKGNhY2hlLmNvbW1hbmQpIHx8IGlzSHRtbE9wZW5SZW5kZXJDb21tYW5kKGNhY2hlLmNvbW1hbmQpO1xufTtcblxuZXhwb3J0IGNvbnN0IGlzRXhlY3V0ZWRUZXh0Q29tbWFuZENhY2hlSXRlbSA9IChcbiAgY2FjaGU6IEV4ZWN1dGVkQ29tbWFuZENhY2hlSXRlbSxcbik6IGNhY2hlIGlzIEV4ZWN1dGVkVGV4dENvbW1hbmRDYWNoZUl0ZW0gPT4ge1xuICByZXR1cm4gaXNUZXh0UmVuZGVyQ29tbWFuZChjYWNoZS5jb21tYW5kKTtcbn07XG5cbmV4cG9ydCB0eXBlIENvbnRlbnRmdWxJbmNsdWRlTWFwID0ge1xuICBhc3NldHM6IFJlY29yZDxzdHJpbmcsIENvbnRlbnRmdWxBc3NldD47XG4gIGVudHJpZXM6IFJlY29yZDxzdHJpbmcsIENvbnRlbnRmdWxFbnRyeT47XG59O1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdldC1jb250ZW50ZnVsLXJpY2gtdGV4dC1yZW5kZXJlcicsXG4gIHRlbXBsYXRlOiBgYCxcbiAgZW5jYXBzdWxhdGlvbjogVmlld0VuY2Fwc3VsYXRpb24uTm9uZSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGhvc3Q6IHtcbiAgICBjbGFzczogJ2V0LWNvbnRlbnRmdWwtcmljaC10ZXh0LXJlbmRlcmVyJyxcbiAgfSxcbn0pXG5leHBvcnQgY2xhc3MgQ29udGVudGZ1bFJpY2hUZXh0UmVuZGVyZXJDb21wb25lbnQge1xuICBfdmlld0NvbnRhaW5lclJlZiA9IGluamVjdChWaWV3Q29udGFpbmVyUmVmKTtcbiAgX3JlbmRlcmVyID0gaW5qZWN0KFJlbmRlcmVyMik7XG4gIF9lbGVtZW50UmVmID0gaW5qZWN0PEVsZW1lbnRSZWY8SFRNTEVsZW1lbnQ+PihFbGVtZW50UmVmKTtcbiAgX2RvY3VtZW50ID0gaW5qZWN0KERPQ1VNRU5UKTtcbiAgX2NvbmZpZyA9IGluamVjdChDT05URU5URlVMX0NPTkZJRywgeyBvcHRpb25hbDogdHJ1ZSB9KSA/PyBjcmVhdGVDb250ZW50ZnVsQ29uZmlnKCk7XG5cbiAgLyoqXG4gICAqIEEgY2FjaGUgZm9yIGFsbCBleGVjdXRlZCBjb21tYW5kcyB0aGF0IGFyZSBub3QgZGVsZXRlZC5cbiAgICogVGhpcyBpcyB1c2VkIHRvIGtlZXAgdHJhY2sgb2YgYWxsIHJlbmRlcmVkIGVsZW1lbnRzIGFuZCBjb21wb25lbnRzLlxuICAgKiBUaGUga2V5IGlzIHRoZSByZW5kZXIgY29tbWFuZCBlbGVtZW50IElELlxuICAgKi9cbiAgX2V4ZWN1dGVkQ29tbWFuZHNDYWNoZSA9IG5ldyBNYXA8c3RyaW5nLCBFeGVjdXRlZENvbW1hbmRDYWNoZUl0ZW0+KCk7XG5cbiAgLyoqXG4gICAqIFRoZSBjb250ZW50ZnVsIHJlc3BvbnNlIGdvdHRlbiB2aWEgdGhlaXIgUkVTVCBhcGkuXG4gICAqIEBzZWUgaHR0cHM6Ly93d3cuY29udGVudGZ1bC5jb20vZGV2ZWxvcGVycy9kb2NzL3JlZmVyZW5jZXMvY29udGVudC1kZWxpdmVyeS1hcGkvIy9yZWZlcmVuY2UvZW50cmllcy9lbnRyaWVzLWNvbGxlY3Rpb25cbiAgICovXG4gIGNvbnRlbnQgPSBpbnB1dC5yZXF1aXJlZDxDb250ZW50ZnVsQ29sbGVjdGlvbiB8IG51bGwgfCB1bmRlZmluZWQ+KCk7XG5cbiAgLyoqXG4gICAqIFRoZSBwYXRoIHRvIHdoZXJlIHRoZSByaWNoIHRleHQgZmllbGQgaXMgaW5zaWRlIHRoZSBjb250ZW50ZnVsIHJlc3BvbnNlLiBEb3QgYW5kIGFycmF5IG5vdGF0aW9uIGlzIGFsbG93ZWQuXG4gICAqIEBkZWZhdWx0IFwiaXRlbXNbMF0uZmllbGRzLmh0bWxcIlxuICAgKi9cbiAgcmljaFRleHRQYXRoID0gaW5wdXQucmVxdWlyZWQ8c3RyaW5nPigpO1xuXG4gIC8qKlxuICAgKiBBIG1hcCBvZiBhbGwgaW5jbHVkZXMgaW4gdGhlIGNvbnRlbnRmdWwgcmVzcG9uc2UuXG4gICAqIFRoaXMgaXMgdXNlZnVsIGZvciBsb29raW5nIHVwIGFzc2V0cyBhbmQgZW50cmllcyB0aGF0IGFyZSByZWZlcmVuY2VkIGluIHRoZSByaWNoIHRleHQgd2l0aG91dCBoYXZpbmcgdG8gdXNlIGxvb3BzLlxuICAgKi9cbiAgY29udGVudEluY2x1ZGVzTWFwID0gY29tcHV0ZWQ8Q29udGVudGZ1bEluY2x1ZGVNYXA+KCgpID0+IHtcbiAgICBjb25zdCBjb250ZW50ID0gdGhpcy5jb250ZW50KCk7XG4gICAgY29uc3QgYXNzZXRzID0gY29udGVudD8uaW5jbHVkZXMuQXNzZXQ7XG4gICAgY29uc3QgZW50cmllcyA9IGNvbnRlbnQ/LmluY2x1ZGVzLkVudHJ5O1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGFzc2V0czpcbiAgICAgICAgYXNzZXRzPy5yZWR1Y2UoXG4gICAgICAgICAgKGFjYywgYXNzZXQpID0+IHtcbiAgICAgICAgICAgIGFjY1thc3NldC5zeXMuaWRdID0gYXNzZXQ7XG4gICAgICAgICAgICByZXR1cm4gYWNjO1xuICAgICAgICAgIH0sXG4gICAgICAgICAge30gYXMgUmVjb3JkPHN0cmluZywgQ29udGVudGZ1bEFzc2V0PixcbiAgICAgICAgKSA/PyB7fSxcbiAgICAgIGVudHJpZXM6XG4gICAgICAgIGVudHJpZXM/LnJlZHVjZShcbiAgICAgICAgICAoYWNjLCBlbnRyeSkgPT4ge1xuICAgICAgICAgICAgYWNjW2VudHJ5LnN5cy5pZF0gPSBlbnRyeTtcbiAgICAgICAgICAgIHJldHVybiBhY2M7XG4gICAgICAgICAgfSxcbiAgICAgICAgICB7fSBhcyBSZWNvcmQ8c3RyaW5nLCBDb250ZW50ZnVsRW50cnk+LFxuICAgICAgICApID8/IHt9LFxuICAgIH07XG4gIH0pO1xuXG4gIC8qKlxuICAgKiBUaGUgcmljaCB0ZXh0IGRhdGEgdGhhdCBzaG91bGQgYmUgcmVuZGVyZWQuXG4gICAqL1xuICByaWNoVGV4dERhdGEgPSBjb21wdXRlZCgoKSA9PiB7XG4gICAgY29uc3QgY29udGVudCA9IHRoaXMuY29udGVudCgpO1xuICAgIGNvbnN0IHJpY2hUZXh0UGF0aCA9IHRoaXMucmljaFRleHRQYXRoKCk7XG5cbiAgICBpZiAoIWNvbnRlbnQpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGNvbnN0IHJpY2hUZXh0ID0gZ2V0T2JqZWN0UHJvcGVydHkoY29udGVudCBhcyB1bmtub3duIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+LCByaWNoVGV4dFBhdGgpO1xuXG4gICAgaWYgKCFpc09iamVjdChyaWNoVGV4dCkpIHtcbiAgICAgIHRocm93IHJpY2hUZXh0UmVuZGVyZXJFcnJvcigncmljaF90ZXh0X3VuZGVmaW5lZCcsIGZhbHNlLCB7IGNvbnRlbnQsIHJpY2hUZXh0UGF0aCB9KTtcbiAgICB9XG5cbiAgICBpZiAoIWlzUmljaFRleHRSb290Tm9kZShyaWNoVGV4dCkpIHtcbiAgICAgIHRocm93IHJpY2hUZXh0UmVuZGVyZXJFcnJvcigncmljaF90ZXh0X3dyb25nX3R5cGUnLCBmYWxzZSwgeyBjb250ZW50LCByaWNoVGV4dFBhdGggfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJpY2hUZXh0IGFzIFJpY2hUZXh0UmVzcG9uc2U7XG4gIH0pO1xuXG4gIHJlbmRlckNvbW1hbmRzID0gY29tcHV0ZWQoKCkgPT4ge1xuICAgIGNvbnN0IHJpY2hUZXh0RGF0YSA9IHRoaXMucmljaFRleHREYXRhKCk7XG5cbiAgICBpZiAoIXJpY2hUZXh0RGF0YSkge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLl9jcmVhdGVSZW5kZXJDb21tYW5kcyhyaWNoVGV4dERhdGEpO1xuICB9KTtcblxuICByZW5kZXJDb21tYW5kSGlzdG9yeSA9IHRvU2lnbmFsKFxuICAgIHRvT2JzZXJ2YWJsZSh0aGlzLnJlbmRlckNvbW1hbmRzKS5waXBlKHN0YXJ0V2l0aChbXSBhcyBSZW5kZXJDb21tYW5kW10pLCBwYWlyd2lzZSgpKSxcbiAgICB7IGluaXRpYWxWYWx1ZTogW1tdLCBbXV0gfSxcbiAgKTtcblxuICBwcmV2aW91c1JlbmRlckNvbW1hbmRNYXAgPSBjb21wdXRlZCgoKSA9PiB7XG4gICAgY29uc3QgW3ByZXZDb21tYW5kc10gPSB0aGlzLnJlbmRlckNvbW1hbmRIaXN0b3J5KCk7XG5cbiAgICBjb25zdCBtYXAgPSBuZXcgTWFwPHN0cmluZyB8IG51bWJlciwgUmVuZGVyQ29tbWFuZD4oKTtcblxuICAgIGZvciAoY29uc3QgY29tbWFuZCBvZiBwcmV2Q29tbWFuZHMpIHtcbiAgICAgIG1hcC5zZXQoZ2V0UmVuZGVyQ29tbWFuZElkKGNvbW1hbmQpLCBjb21tYW5kKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbWFwO1xuICB9KTtcblxuICByZW5kZXJJbnN0cnVjdGlvbnMgPSBjb21wdXRlZCgoKSA9PiB7XG4gICAgY29uc3QgY29tbWFuZHMgPSB0aGlzLnJlbmRlckNvbW1hbmRzKCk7XG4gICAgY29uc3QgcHJldmlvdXNSZW5kZXJDb21tYW5kTWFwID0gbmV3IE1hcCh0aGlzLnByZXZpb3VzUmVuZGVyQ29tbWFuZE1hcCgpKTtcblxuICAgIGNvbnN0IGluc3RydWN0aW9uczogUmVuZGVySW5zdHJ1Y3Rpb25bXSA9IFtdO1xuXG4gICAgLy8gcmVtb3ZlIGRlbGV0ZWQgY29tcG9uZW50cyBhcyB3ZWxsIGFzIGFsbCBvdGhlciBlbGVtZW50c1xuICAgIGZvciAoY29uc3QgWywgY29tbWFuZF0gb2YgcHJldmlvdXNSZW5kZXJDb21tYW5kTWFwKSB7XG4gICAgICBpZiAoaXNDb21wb25lbnRSZW5kZXJDb21tYW5kKGNvbW1hbmQpKSB7XG4gICAgICAgIC8vIGtlZXAgdGhlIGNvbXBvbmVudCBhcm91bmQgaWYgaXQncyBzdGlsbCBpbiB0aGUgbmV3IGNvbW1hbmRzXG4gICAgICAgIGlmIChjb21tYW5kcy5zb21lKChjKSA9PiBnZXRSZW5kZXJDb21tYW5kSWQoYykgPT09IGdldFJlbmRlckNvbW1hbmRJZChjb21tYW5kKSkpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpbnN0cnVjdGlvbnMucHVzaChbUkVOREVSX0lOU1RSVUNUSU9OX1RZUEUuREVMRVRFLCBjb21tYW5kXSk7XG5cbiAgICAgIC8vIHJlbW92ZSBmcm9tIG1hcCB0byBtYXJrIGFzIHVzZWRcbiAgICAgIHByZXZpb3VzUmVuZGVyQ29tbWFuZE1hcC5kZWxldGUoZ2V0UmVuZGVyQ29tbWFuZElkKGNvbW1hbmQpKTtcbiAgICB9XG5cbiAgICAvLyBGaW5kIHRoZSBpbmRleGVzIG9mIHRoZSBjb21tYW5kcyByZW1haW5pbmcgaW4gdGhlIHByZXZpb3VzUmVuZGVyQ29tbWFuZE1hcCBpbiB0aGUgbmV3IGNvbW1hbmRzIGFycmF5LlxuICAgIGNvbnN0IGxhc3RDb21wb25lbnRJbmRleGVzOiB7IG5ld0luZGV4OiBudW1iZXI7IHByZXZJbmRleDogbnVtYmVyOyBjb21tYW5kOiBSZW5kZXJDb21tYW5kIH1bXSA9IFtdO1xuICAgIGZvciAoY29uc3QgW2lkLCBjb21tYW5kXSBvZiBwcmV2aW91c1JlbmRlckNvbW1hbmRNYXApIHtcbiAgICAgIGNvbnN0IGluZGV4ID0gY29tbWFuZHMuZmluZEluZGV4KChjKSA9PiBnZXRSZW5kZXJDb21tYW5kSWQoYykgPT09IGlkKTtcbiAgICAgIGNvbnN0IG5ld0NvbW1hbmQgPSBjb21tYW5kc1tpbmRleF0hO1xuXG4gICAgICBpZiAoaW5kZXggPT09IC0xKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignQ29tbWFuZCBub3QgZm91bmQhJyk7XG4gICAgICB9XG5cbiAgICAgIGxhc3RDb21wb25lbnRJbmRleGVzLnB1c2goe1xuICAgICAgICBuZXdJbmRleDogaW5kZXgsXG4gICAgICAgIHByZXZJbmRleDogY29tbWFuZFtSRU5ERVJfQ09NTUFORF9QT1NJVElPTi5JTkRFWF0sXG4gICAgICAgIGNvbW1hbmQ6IG5ld0NvbW1hbmQsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBsYXN0Q29tcG9uZW50SW5kZXhlcy5zb3J0KChhLCBiKSA9PiBhLm5ld0luZGV4IC0gYi5uZXdJbmRleCk7XG5cbiAgICAvLyBjaGVjayBpZiB0aGUgcHJldkluZGV4IGFyZSBpbiBvcmRlciBhc2NlbmRpbmdcbiAgICAvLyBmb3IgaW5kZXhlcyB0aGF0IGFyZSBub3QgaW4gb3JkZXIsIGNyZWF0ZSBhIG1vdmUgaW5zdHJ1Y3Rpb25cbiAgICAvLyBmb3IgaW5kZXhlcyB0aGF0IGFyZSBpbiBvcmRlciwgY3JlYXRlIGFuIHVwZGF0ZSBpbnN0cnVjdGlvblxuICAgIGxldCBtb3ZlQ2hlY2tJbmRleCA9IDA7XG4gICAgd2hpbGUgKG1vdmVDaGVja0luZGV4IDwgbGFzdENvbXBvbmVudEluZGV4ZXMubGVuZ3RoIC0gMSkge1xuICAgICAgY29uc3QgbW92ZUN1cnIgPSBsYXN0Q29tcG9uZW50SW5kZXhlc1ttb3ZlQ2hlY2tJbmRleF07XG4gICAgICBjb25zdCBtb3ZlTmV4dCA9IGxhc3RDb21wb25lbnRJbmRleGVzW21vdmVDaGVja0luZGV4ICsgMV07XG5cbiAgICAgIGlmICghbW92ZUN1cnIgfHwgIW1vdmVOZXh0KSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuXG4gICAgICBpZiAobW92ZUN1cnIucHJldkluZGV4ID4gbW92ZU5leHQucHJldkluZGV4KSB7XG4gICAgICAgIGxhc3RDb21wb25lbnRJbmRleGVzLnNwbGljZShtb3ZlQ2hlY2tJbmRleCArIDEsIDEpO1xuICAgICAgICBpbnN0cnVjdGlvbnMucHVzaChbUkVOREVSX0lOU1RSVUNUSU9OX1RZUEUuTU9WRSwgbW92ZU5leHQuY29tbWFuZF0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaW5zdHJ1Y3Rpb25zLnB1c2goW1JFTkRFUl9JTlNUUlVDVElPTl9UWVBFLlVQREFURSwgbW92ZU5leHQuY29tbWFuZF0pO1xuICAgICAgICBtb3ZlQ2hlY2tJbmRleCsrO1xuICAgICAgfVxuICAgIH1cblxuICAgIGZvciAoY29uc3QgY29tbWFuZCBvZiBjb21tYW5kcykge1xuICAgICAgY29uc3QgaWQgPSBnZXRSZW5kZXJDb21tYW5kSWQoY29tbWFuZCk7XG5cbiAgICAgIGlmIChpc0NvbXBvbmVudFJlbmRlckNvbW1hbmQoY29tbWFuZCkpIHtcbiAgICAgICAgY29uc3QgcHJldmlvdXNDb21tYW5kID0gcHJldmlvdXNSZW5kZXJDb21tYW5kTWFwLmdldChpZCk7XG5cbiAgICAgICAgaWYgKCFwcmV2aW91c0NvbW1hbmQpIHtcbiAgICAgICAgICAvLyBjcmVhdGVcbiAgICAgICAgICBpbnN0cnVjdGlvbnMucHVzaChbUkVOREVSX0lOU1RSVUNUSU9OX1RZUEUuQ1JFQVRFLCBjb21tYW5kXSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIGNyZWF0ZVxuICAgICAgICBpbnN0cnVjdGlvbnMucHVzaChbUkVOREVSX0lOU1RSVUNUSU9OX1RZUEUuQ1JFQVRFLCBjb21tYW5kXSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGluc3RydWN0aW9ucztcbiAgfSk7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdG9PYnNlcnZhYmxlKHRoaXMucmVuZGVySW5zdHJ1Y3Rpb25zKVxuICAgICAgLnBpcGUoXG4gICAgICAgIHRha2VVbnRpbERlc3Ryb3llZCgpLFxuICAgICAgICB0YXAoKGluc3RydWN0aW9ucykgPT4ge1xuICAgICAgICAgIHRoaXMuX2V4ZWNJbnN0cnVjdGlvbnMoaW5zdHJ1Y3Rpb25zKTtcbiAgICAgICAgfSksXG4gICAgICApXG4gICAgICAuc3Vic2NyaWJlKCk7XG4gIH1cblxuICBwcml2YXRlIF9jcmVhdGVSZW5kZXJDb21tYW5kcyhyaWNoVGV4dERhdGE6IFJpY2hUZXh0UmVzcG9uc2UpIHtcbiAgICAvKiogTGlzdCBvZiBhbGwgcmVuZGVyIGNvbW1hbmRzICovXG4gICAgY29uc3Qgcm9vdENvbW1hbmRzOiBSZW5kZXJDb21tYW5kW10gPSBbXTtcblxuICAgIC8qKiBDb3VudGVyIGZvciBnZW5lcmF0aW5nIHVuaXF1ZSBodG1sIGVsZW1lbnQgSURzLiAqL1xuICAgIGxldCBlbGVtZW50SWQgPSAwO1xuXG4gICAgLyoqIENvdW50ZXIgZm9yIGdlbmVyYXRpbmcgdW5pcXVlIGNvbXBvbmVudCBJRHMuICovXG4gICAgY29uc3QgY29tcG9uZW50SWRNYXAgPSBuZXcgTWFwPHN0cmluZywgbnVtYmVyPigpO1xuXG4gICAgLyoqIFRoZSBuZXN0aW5nIGxldmVsIG9mIHRoZSBjdXJyZW50IG5vZGUuICovXG4gICAgbGV0IG5lc3RpbmdMZXZlbCA9IDA7XG5cbiAgICAvKiogVGhlIHBvc2l0aW9uIChpbmRleCkgb2YgdGhlIGN1cnJlbnQgbm9kZSBpbnNpZGUgdGhlIHBhcmVudCBub2RlLiAqL1xuICAgIGxldCBkb21Qb3NpdGlvbiA9IDA7XG5cbiAgICBsZXQgY29tbWFuZEluZGV4ID0gMDtcblxuICAgIGNvbnN0IHRyYXZlcnNlID0gKG5vZGU6IEJsb2NrIHwgSW5saW5lIHwgVGV4dCwgcGFyZW50OiBSZW5kZXJDb21tYW5kIHwgbnVsbCA9IG51bGwpID0+IHtcbiAgICAgIHN3aXRjaCAobm9kZS5ub2RlVHlwZSkge1xuICAgICAgICBjYXNlICd0ZXh0Jzoge1xuICAgICAgICAgIC8vIFJlbmRlciBtZWRpYVxuICAgICAgICAgIGNvbnN0IHR5cGUgPSBSRU5ERVJfQ09NTUFORF9UWVBFLlRFWFQ7XG4gICAgICAgICAgY29uc3QgdGV4dCA9IG5vZGUudmFsdWU7XG5cbiAgICAgICAgICBpZiAoIXRleHQpIGJyZWFrO1xuXG4gICAgICAgICAgY29uc3QgY29tbWFuZDogVGV4dFJlbmRlckNvbW1hbmQgPSBbdHlwZSwgbmVzdGluZ0xldmVsLCBkb21Qb3NpdGlvbiwgY29tbWFuZEluZGV4KyssIHRleHRdO1xuXG4gICAgICAgICAgcm9vdENvbW1hbmRzLnB1c2goY29tbWFuZCk7XG4gICAgICAgICAgZG9tUG9zaXRpb24rKztcblxuICAgICAgICAgIGlmICghcGFyZW50KSB7XG4gICAgICAgICAgICB0aHJvdyByaWNoVGV4dFJlbmRlcmVyRXJyb3IoJ3RleHRfcGFyZW50X25vdF9mb3VuZCcsIGZhbHNlLCB7IG5vZGUgfSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICghaXNIdG1sT3BlblJlbmRlckNvbW1hbmQocGFyZW50KSAmJiAhaXNDb21wb25lbnRSZW5kZXJDb21tYW5kKHBhcmVudCkpIHtcbiAgICAgICAgICAgIHRocm93IHJpY2hUZXh0UmVuZGVyZXJFcnJvcigndGV4dF9wYXJlbnRfd3JvbmdfdHlwZScsIGZhbHNlLCB7IG5vZGUsIHBhcmVudCB9KTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCBhdHRyaWJ1dGVzUG9zaXRpb24gPVxuICAgICAgICAgICAgcGFyZW50W1JFTkRFUl9DT01NQU5EX1BPU0lUSU9OLlRZUEVdID09PSBSRU5ERVJfQ09NTUFORF9UWVBFLkhUTUxfT1BFTlxuICAgICAgICAgICAgICA/IEhUTUxfT1BFTl9SRU5ERVJfQ09NTUFORF9QT1NJVElPTi5BVFRSSUJVVEVTXG4gICAgICAgICAgICAgIDogQ09NUE9ORU5UX1JFTkRFUl9DT01NQU5EX1BPU0lUSU9OLkFUVFJJQlVURVM7XG5cbiAgICAgICAgICBjb25zdCBhdHRyaWJ1dGVzID0gcGFyZW50W2F0dHJpYnV0ZXNQb3NpdGlvbl07XG5cbiAgICAgICAgICBpZiAobm9kZS5tYXJrcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIGNvbnN0IG1hcmtDbGFzc2VzID0gbWFya3NUb0NsYXNzKG5vZGUubWFya3MpO1xuXG4gICAgICAgICAgICBpZiAoQ0xBU1NfQVRUUiBpbiBhdHRyaWJ1dGVzKSB7XG4gICAgICAgICAgICAgIGF0dHJpYnV0ZXNbQ0xBU1NfQVRUUl0gKz0gYCAke21hcmtDbGFzc2VzfWA7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBhdHRyaWJ1dGVzW0NMQVNTX0FUVFJdID0gbWFya0NsYXNzZXM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICBjYXNlIEJMT0NLUy5FTUJFRERFRF9BU1NFVDoge1xuICAgICAgICAgIC8vIFJlbmRlciBtZWRpYVxuICAgICAgICAgIGNvbnN0IHR5cGUgPSBSRU5ERVJfQ09NTUFORF9UWVBFLkNPTVBPTkVOVDtcbiAgICAgICAgICBjb25zdCBhc3NldElkID0gbm9kZS5kYXRhWyd0YXJnZXQnXT8uc3lzPy5pZDtcblxuICAgICAgICAgIGlmICghYXNzZXRJZCkge1xuICAgICAgICAgICAgdGhyb3cgcmljaFRleHRSZW5kZXJlckVycm9yKCdhc3NldF9pZF9ub3RfZm91bmQnLCBmYWxzZSwgeyBub2RlIH0pO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IGFzc2V0ID0gdGhpcy5jb250ZW50SW5jbHVkZXNNYXAoKS5hc3NldHNbYXNzZXRJZF07XG5cbiAgICAgICAgICBpZiAoIWFzc2V0KSB7XG4gICAgICAgICAgICB0aHJvdyByaWNoVGV4dFJlbmRlcmVyRXJyb3IoJ2Fzc2V0X25vdF9mb3VuZCcsIGZhbHNlLCB7IGFzc2V0SWQsIG5vZGUgfSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgY29udGVudFR5cGUgPSBhc3NldC5maWVsZHMuZmlsZS5jb250ZW50VHlwZTtcbiAgICAgICAgICBjb25zdCBhc3NldENvbXBvbmVudHMgPSB0aGlzLl9jb25maWcuY29tcG9uZW50cztcblxuICAgICAgICAgIGNvbnN0IGlzSW1hZ2UgPSBjb250ZW50VHlwZS5zdGFydHNXaXRoKCdpbWFnZS8nKTtcbiAgICAgICAgICBjb25zdCBpc1ZpZGVvID0gY29udGVudFR5cGUuc3RhcnRzV2l0aCgndmlkZW8vJyk7XG4gICAgICAgICAgY29uc3QgaXNBdWRpbyA9IGNvbnRlbnRUeXBlLnN0YXJ0c1dpdGgoJ2F1ZGlvLycpO1xuXG4gICAgICAgICAgY29uc3QgY29tcG9uZW50ID0gaXNJbWFnZVxuICAgICAgICAgICAgPyBhc3NldENvbXBvbmVudHMuaW1hZ2VcbiAgICAgICAgICAgIDogaXNWaWRlb1xuICAgICAgICAgICAgICA/IGFzc2V0Q29tcG9uZW50cy52aWRlb1xuICAgICAgICAgICAgICA6IGlzQXVkaW9cbiAgICAgICAgICAgICAgICA/IGFzc2V0Q29tcG9uZW50cy5hdWRpb1xuICAgICAgICAgICAgICAgIDogYXNzZXRDb21wb25lbnRzLmZpbGU7XG5cbiAgICAgICAgICBjb25zdCBjb21wb25lbnRUeXBlID0gaXNJbWFnZVxuICAgICAgICAgICAgPyBERUZBVUxUX0NPTVBPTkVOVF9UWVBFUy5JTUFHRVxuICAgICAgICAgICAgOiBpc1ZpZGVvXG4gICAgICAgICAgICAgID8gREVGQVVMVF9DT01QT05FTlRfVFlQRVMuVklERU9cbiAgICAgICAgICAgICAgOiBpc0F1ZGlvXG4gICAgICAgICAgICAgICAgPyBERUZBVUxUX0NPTVBPTkVOVF9UWVBFUy5BVURJT1xuICAgICAgICAgICAgICAgIDogREVGQVVMVF9DT01QT05FTlRfVFlQRVMuRklMRTtcblxuICAgICAgICAgIGxldCBjb21wb25lbnRJZCA9IGNvbXBvbmVudElkTWFwLmdldChjb21wb25lbnRUeXBlKSA/PyAtMTtcbiAgICAgICAgICBjb25zdCBpZCA9IGNvbXBvbmVudFR5cGUgKyArK2NvbXBvbmVudElkO1xuICAgICAgICAgIGNvbXBvbmVudElkTWFwLnNldChjb21wb25lbnRUeXBlLCBjb21wb25lbnRJZCk7XG5cbiAgICAgICAgICBjb25zdCBhdHRyaWJ1dGVzID0ge307XG5cbiAgICAgICAgICBjb25zdCBpbnB1dHMgPSB7XG4gICAgICAgICAgICBhc3NldCxcbiAgICAgICAgICB9O1xuXG4gICAgICAgICAgY29uc3QgY29tbWFuZDogQ29tcG9uZW50UmVuZGVyQ29tbWFuZCA9IFtcbiAgICAgICAgICAgIHR5cGUsXG4gICAgICAgICAgICBuZXN0aW5nTGV2ZWwsXG4gICAgICAgICAgICBkb21Qb3NpdGlvbixcbiAgICAgICAgICAgIGNvbW1hbmRJbmRleCsrLFxuICAgICAgICAgICAgYXR0cmlidXRlcyxcbiAgICAgICAgICAgIGNvbXBvbmVudCxcbiAgICAgICAgICAgIGlucHV0cyxcbiAgICAgICAgICAgIGlkLFxuICAgICAgICAgIF07XG5cbiAgICAgICAgICByb290Q29tbWFuZHMucHVzaChjb21tYW5kKTtcblxuICAgICAgICAgIGRvbVBvc2l0aW9uKys7XG5cbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIGNhc2UgQkxPQ0tTLkVNQkVEREVEX0VOVFJZOlxuICAgICAgICBjYXNlIElOTElORVMuRU1CRURERURfRU5UUlk6IHtcbiAgICAgICAgICAvLyBSZW5kZXIgY29tcG9uZW50XG4gICAgICAgICAgY29uc3QgdHlwZSA9IFJFTkRFUl9DT01NQU5EX1RZUEUuQ09NUE9ORU5UO1xuICAgICAgICAgIGNvbnN0IGVudHJ5SWQgPSBub2RlLmRhdGFbJ3RhcmdldCddPy5zeXM/LmlkO1xuXG4gICAgICAgICAgaWYgKCFlbnRyeUlkKSB7XG4gICAgICAgICAgICB0aHJvdyByaWNoVGV4dFJlbmRlcmVyRXJyb3IoJ2VudHJ5X2lkX25vdF9mb3VuZCcsIGZhbHNlLCB7IG5vZGUgfSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgZW50cnkgPSB0aGlzLmNvbnRlbnRJbmNsdWRlc01hcCgpLmVudHJpZXNbZW50cnlJZF07XG5cbiAgICAgICAgICBpZiAoIWVudHJ5KSB7XG4gICAgICAgICAgICB0aHJvdyByaWNoVGV4dFJlbmRlcmVyRXJyb3IoJ2VudHJ5X25vdF9mb3VuZCcsIGZhbHNlLCB7IGVudHJ5SWQsIG5vZGUgfSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgY29tcG9uZW50VHlwZSA9IGVudHJ5LnN5cy5jb250ZW50VHlwZS5zeXMuaWQ7XG5cbiAgICAgICAgICBjb25zdCBjb21wb25lbnQgPSB0aGlzLl9jb25maWcuY3VzdG9tQ29tcG9uZW50c1tjb21wb25lbnRUeXBlXTtcblxuICAgICAgICAgIGlmICghY29tcG9uZW50KSB7XG4gICAgICAgICAgICB0aHJvdyByaWNoVGV4dFJlbmRlcmVyRXJyb3IoJ2N1c3RvbV9jb21wb25lbnRfbm90X2ZvdW5kJywgZmFsc2UsIHtcbiAgICAgICAgICAgICAgY29tcG9uZW50VHlwZSxcbiAgICAgICAgICAgICAgY3VzdG9tQ29tcG9uZW50czogdGhpcy5fY29uZmlnLmN1c3RvbUNvbXBvbmVudHMsXG4gICAgICAgICAgICAgIGVudHJ5LFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgYXR0cmlidXRlcyA9IHt9O1xuICAgICAgICAgIGxldCBjb21wb25lbnRJZCA9IGNvbXBvbmVudElkTWFwLmdldChjb21wb25lbnRUeXBlKSA/PyAtMTtcbiAgICAgICAgICBjb25zdCBpZCA9IGNvbXBvbmVudFR5cGUgKyArK2NvbXBvbmVudElkO1xuICAgICAgICAgIGNvbXBvbmVudElkTWFwLnNldChjb21wb25lbnRUeXBlLCBjb21wb25lbnRJZCk7XG5cbiAgICAgICAgICBjb25zdCBpbnB1dHMgPSB7XG4gICAgICAgICAgICBmaWVsZHM6IGVudHJ5LmZpZWxkcyxcbiAgICAgICAgICAgIG1ldGFkYXRhOiBlbnRyeS5tZXRhZGF0YSxcbiAgICAgICAgICAgIHN5czogZW50cnkuc3lzLFxuICAgICAgICAgICAgaW5jbHVkZXM6IHRoaXMuY29udGVudEluY2x1ZGVzTWFwKCksXG4gICAgICAgICAgfTtcblxuICAgICAgICAgIGNvbnN0IGNvbW1hbmQ6IENvbXBvbmVudFJlbmRlckNvbW1hbmQgPSBbXG4gICAgICAgICAgICB0eXBlLFxuICAgICAgICAgICAgbmVzdGluZ0xldmVsLFxuICAgICAgICAgICAgZG9tUG9zaXRpb24sXG4gICAgICAgICAgICBjb21tYW5kSW5kZXgrKyxcbiAgICAgICAgICAgIGF0dHJpYnV0ZXMsXG4gICAgICAgICAgICBjb21wb25lbnQsXG4gICAgICAgICAgICBpbnB1dHMsXG4gICAgICAgICAgICBpZCxcbiAgICAgICAgICBdO1xuXG4gICAgICAgICAgcm9vdENvbW1hbmRzLnB1c2goY29tbWFuZCk7XG5cbiAgICAgICAgICBkb21Qb3NpdGlvbisrO1xuXG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICBkZWZhdWx0OiB7XG4gICAgICAgICAgY29uc3QgdHlwZSA9IFJFTkRFUl9DT01NQU5EX1RZUEUuSFRNTF9PUEVOO1xuICAgICAgICAgIGNvbnN0IHRhZyA9IHRyYW5zbGF0ZUNvbnRlbnRmdWxOb2RlVHlwZVRvSHRtbFRhZyhub2RlLm5vZGVUeXBlKTtcbiAgICAgICAgICBjb25zdCBhdHRyaWJ1dGVzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG4gICAgICAgICAgY29uc3QgaWQgPSAnZScgKyBlbGVtZW50SWQrKztcblxuICAgICAgICAgIGNvbnN0IGNvbW1hbmQ6IEh0bWxPcGVuUmVuZGVyQ29tbWFuZCA9IFt0eXBlLCBuZXN0aW5nTGV2ZWwsIGRvbVBvc2l0aW9uLCBjb21tYW5kSW5kZXgrKywgYXR0cmlidXRlcywgdGFnLCBpZF07XG5cbiAgICAgICAgICByb290Q29tbWFuZHMucHVzaChjb21tYW5kKTtcblxuICAgICAgICAgIGNvbnN0IGRvbVBvc2l0aW9uQXRUaGlzTGV2ZWwgPSBkb21Qb3NpdGlvbjtcbiAgICAgICAgICAvLyBOb3JtYWwgaHRtbCBlbGVtZW50cyBjYW4gaGF2ZSBjaGlsZHJlblxuICAgICAgICAgIGZvciAoY29uc3QgY2hpbGQgb2Ygbm9kZS5jb250ZW50KSB7XG4gICAgICAgICAgICBkb21Qb3NpdGlvbiA9IDA7XG4gICAgICAgICAgICBuZXN0aW5nTGV2ZWwrKztcbiAgICAgICAgICAgIHRyYXZlcnNlKGNoaWxkLCBjb21tYW5kKTtcbiAgICAgICAgICAgIG5lc3RpbmdMZXZlbC0tO1xuICAgICAgICAgICAgZG9tUG9zaXRpb24gPSBkb21Qb3NpdGlvbkF0VGhpc0xldmVsO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IGxhc3RDb21tYW5kID0gcm9vdENvbW1hbmRzW3Jvb3RDb21tYW5kcy5sZW5ndGggLSAxXTtcblxuICAgICAgICAgIGlmIChsYXN0Q29tbWFuZD8uW1JFTkRFUl9DT01NQU5EX1BPU0lUSU9OLlRZUEVdID09PSBSRU5ERVJfQ09NTUFORF9UWVBFLkhUTUxfT1BFTikge1xuICAgICAgICAgICAgLy8gSWYgdGhlIGxhc3QgY29tbWFuZCBpcyBhbiBvcGVuIGNvbW1hbmQsIHdlIGNhbiByZW1vdmUgaXQgc2luY2UgaXQncyBlbXB0eVxuICAgICAgICAgICAgcm9vdENvbW1hbmRzLnBvcCgpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBjbG9zZUlkID0gJ2UnICsgZWxlbWVudElkKys7XG5cbiAgICAgICAgICAgIGNvbnN0IGNsb3NlQ29tbWFuZDogSHRtbENsb3NlUmVuZGVyQ29tbWFuZCA9IFtcbiAgICAgICAgICAgICAgUkVOREVSX0NPTU1BTkRfVFlQRS5IVE1MX0NMT1NFLFxuICAgICAgICAgICAgICBuZXN0aW5nTGV2ZWwsXG4gICAgICAgICAgICAgIGRvbVBvc2l0aW9uLFxuICAgICAgICAgICAgICBjb21tYW5kSW5kZXgrKyxcbiAgICAgICAgICAgICAgdGFnLFxuICAgICAgICAgICAgICBjbG9zZUlkLFxuICAgICAgICAgICAgXTtcbiAgICAgICAgICAgIHJvb3RDb21tYW5kcy5wdXNoKGNsb3NlQ29tbWFuZCk7XG5cbiAgICAgICAgICAgIGRvbVBvc2l0aW9uKys7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKG5vZGUubm9kZVR5cGUgPT09IElOTElORVMuSFlQRVJMSU5LKSB7XG4gICAgICAgICAgICBjb25zdCB1cmkgPSBub2RlLmRhdGFbJ3VyaSddO1xuICAgICAgICAgICAgYXR0cmlidXRlc1snaHJlZiddID0gdXJpO1xuXG4gICAgICAgICAgICBjb25zdCBob3N0ID0gdGhpcy5fZG9jdW1lbnQubG9jYXRpb24uaG9zdDtcbiAgICAgICAgICAgIGNvbnN0IGlzRXh0ZXJuYWwgPSAhdXJpLmluY2x1ZGVzKGhvc3QpO1xuXG4gICAgICAgICAgICBpZiAoaXNFeHRlcm5hbCkge1xuICAgICAgICAgICAgICBhdHRyaWJ1dGVzWyd0YXJnZXQnXSA9ICdfYmxhbmsnO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfTtcblxuICAgIGZvciAoY29uc3Qgbm9kZSBvZiByaWNoVGV4dERhdGEuY29udGVudCkge1xuICAgICAgdHJhdmVyc2Uobm9kZSwgbnVsbCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJvb3RDb21tYW5kcztcbiAgfVxuXG4gIHByaXZhdGUgX2V4ZWNJbnN0cnVjdGlvbnMoaW5zdHJ1Y3Rpb25zOiBSZW5kZXJJbnN0cnVjdGlvbltdKSB7XG4gICAgZm9yIChjb25zdCBpbnN0cnVjdGlvbiBvZiBpbnN0cnVjdGlvbnMpIHtcbiAgICAgIGNvbnN0IHR5cGUgPSBpbnN0cnVjdGlvbltSRU5ERVJfSU5TVFJVQ1RJT05fUE9TSVRJT04uVFlQRV07XG4gICAgICBjb25zdCBjb21tYW5kID0gaW5zdHJ1Y3Rpb25bUkVOREVSX0lOU1RSVUNUSU9OX1BPU0lUSU9OLkNPTU1BTkRdO1xuXG4gICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgY2FzZSBSRU5ERVJfSU5TVFJVQ1RJT05fVFlQRS5DUkVBVEU6XG4gICAgICAgICAgdGhpcy5fcnVuQ3JlYXRlSW5zdHJ1Y3Rpb24oY29tbWFuZCk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgUkVOREVSX0lOU1RSVUNUSU9OX1RZUEUuVVBEQVRFOlxuICAgICAgICAgIHRoaXMuX3J1blVwZGF0ZUluc3RydWN0aW9uKGNvbW1hbmQpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIFJFTkRFUl9JTlNUUlVDVElPTl9UWVBFLk1PVkU6XG4gICAgICAgICAgdGhpcy5fcnVuTW92ZUluc3RydWN0aW9uKGNvbW1hbmQpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIFJFTkRFUl9JTlNUUlVDVElPTl9UWVBFLkRFTEVURTpcbiAgICAgICAgICB0aGlzLl9ydW5EZWxldGVJbnN0cnVjdGlvbihjb21tYW5kKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9ydW5DcmVhdGVJbnN0cnVjdGlvbihjb21tYW5kOiBSZW5kZXJDb21tYW5kKSB7XG4gICAgY29uc3QgaWQgPSBnZXRSZW5kZXJDb21tYW5kSWQoY29tbWFuZCk7XG4gICAgY29uc3QgcGFyZW50RWxlbWVudCA9IHRoaXMuX2ZpbmRQYXJlbnQoY29tbWFuZCk7XG4gICAgY29uc3QgbmV4dEVsZW1lbnQgPSB0aGlzLl9maW5kRm9sbG93aW5nRWxlbWVudChjb21tYW5kKTtcblxuICAgIGlmIChpc0NvbXBvbmVudFJlbmRlckNvbW1hbmQoY29tbWFuZCkpIHtcbiAgICAgIGNvbnN0IGNvbXBvbmVudFJlZiA9IHRoaXMuX3ZpZXdDb250YWluZXJSZWYuY3JlYXRlQ29tcG9uZW50KGNvbW1hbmRbQ09NUE9ORU5UX1JFTkRFUl9DT01NQU5EX1BPU0lUSU9OLkNPTVBPTkVOVF0pO1xuXG4gICAgICB0aGlzLl91cGRhdGVDb21wb25lbnRJbnB1dHMoY29tbWFuZCwgY29tcG9uZW50UmVmKTtcblxuICAgICAgY29uc3Qgcm9vdE5vZGUgPSB0aGlzLl9nZXRDb21wb25lbnRSb290Tm9kZShjb21wb25lbnRSZWYpO1xuXG4gICAgICB0aGlzLl9yZW5kZXJJbnNlcnRPckFwcGVuZChyb290Tm9kZSwgcGFyZW50RWxlbWVudCwgbmV4dEVsZW1lbnQpO1xuXG4gICAgICB0aGlzLl9leGVjdXRlZENvbW1hbmRzQ2FjaGUuc2V0KGlkLCB7XG4gICAgICAgIGNvbW1hbmQsXG4gICAgICAgIGNvbXBvbmVudFJlZixcbiAgICAgICAgZWxlbWVudDogcm9vdE5vZGUsXG4gICAgICB9KTtcbiAgICB9IGVsc2UgaWYgKGlzVGV4dFJlbmRlckNvbW1hbmQoY29tbWFuZCkpIHtcbiAgICAgIGNvbnN0IHRleHQgPSBjb21tYW5kW1RFWFRfUkVOREVSX0NPTU1BTkRfUE9TSVRJT04uVEVYVF07XG4gICAgICBjb25zdCB0ZXh0Tm9kZSA9IHRoaXMuX3JlbmRlcmVyLmNyZWF0ZVRleHQodGV4dCk7XG4gICAgICBjb25zdCBzcGFuID0gdGhpcy5fcmVuZGVyZXIuY3JlYXRlRWxlbWVudCgnc3BhbicpO1xuICAgICAgdGhpcy5fcmVuZGVyZXIuYXBwZW5kQ2hpbGQoc3BhbiwgdGV4dE5vZGUpO1xuXG4gICAgICB0aGlzLl9yZW5kZXJJbnNlcnRPckFwcGVuZChzcGFuLCBwYXJlbnRFbGVtZW50LCBuZXh0RWxlbWVudCk7XG5cbiAgICAgIHRoaXMuX2V4ZWN1dGVkQ29tbWFuZHNDYWNoZS5zZXQoaWQsIHtcbiAgICAgICAgY29tbWFuZCxcbiAgICAgICAgZWxlbWVudDogc3BhbixcbiAgICAgICAgdGV4dE5vZGUsXG4gICAgICB9KTtcbiAgICB9IGVsc2UgaWYgKGlzSHRtbE9wZW5SZW5kZXJDb21tYW5kKGNvbW1hbmQpKSB7XG4gICAgICBjb25zdCB0YWcgPSBjb21tYW5kW0hUTUxfT1BFTl9SRU5ERVJfQ09NTUFORF9QT1NJVElPTi5UQUdfTkFNRV07XG4gICAgICBjb25zdCBhdHRyaWJ1dGVzID0gY29tbWFuZFtIVE1MX09QRU5fUkVOREVSX0NPTU1BTkRfUE9TSVRJT04uQVRUUklCVVRFU107XG4gICAgICBjb25zdCBlbGVtZW50ID0gdGhpcy5fcmVuZGVyZXIuY3JlYXRlRWxlbWVudCh0YWcpO1xuXG4gICAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhhdHRyaWJ1dGVzKSkge1xuICAgICAgICB0aGlzLl9yZW5kZXJlci5zZXRBdHRyaWJ1dGUoZWxlbWVudCwga2V5LCB2YWx1ZSk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX3JlbmRlckluc2VydE9yQXBwZW5kKGVsZW1lbnQsIHBhcmVudEVsZW1lbnQsIG5leHRFbGVtZW50KTtcblxuICAgICAgdGhpcy5fZXhlY3V0ZWRDb21tYW5kc0NhY2hlLnNldChpZCwge1xuICAgICAgICBjb21tYW5kLFxuICAgICAgICBlbGVtZW50LFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfcnVuVXBkYXRlSW5zdHJ1Y3Rpb24oY29tbWFuZDogUmVuZGVyQ29tbWFuZCkge1xuICAgIGNvbnN0IGlkID0gZ2V0UmVuZGVyQ29tbWFuZElkKGNvbW1hbmQpO1xuICAgIGNvbnN0IGNhY2hlZCA9IHRoaXMuX2V4ZWN1dGVkQ29tbWFuZHNDYWNoZS5nZXQoaWQpO1xuXG4gICAgaWYgKCFjYWNoZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2FjaGVkIGNvbW1hbmQgbm90IGZvdW5kIScpO1xuICAgIH1cblxuICAgIGlmIChpc0NvbXBvbmVudFJlbmRlckNvbW1hbmQoY29tbWFuZCkpIHtcbiAgICAgIGlmICghaXNFeGVjdXRlZENvbXBvbmVudENvbW1hbmRDYWNoZUl0ZW0oY2FjaGVkKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhY2hlZCBjb21tYW5kIGlzIG5vdCBhIGNvbXBvbmVudCBjb21tYW5kIScpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBjb21wb25lbnRSZWYgPSBjYWNoZWQuY29tcG9uZW50UmVmO1xuXG4gICAgICBpZiAoIWNvbXBvbmVudFJlZikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NvbXBvbmVudCByZWYgbm90IGZvdW5kIScpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl91cGRhdGVDb21wb25lbnRJbnB1dHMoY29tbWFuZCwgY29tcG9uZW50UmVmKTtcbiAgICB9XG5cbiAgICB0aGlzLl9leGVjdXRlZENvbW1hbmRzQ2FjaGUuc2V0KGlkLCB7XG4gICAgICAuLi5jYWNoZWQsXG4gICAgICBjb21tYW5kOiBjb21tYW5kIGFzIGFueSxcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgX3J1bk1vdmVJbnN0cnVjdGlvbihjb21tYW5kOiBSZW5kZXJDb21tYW5kKSB7XG4gICAgY29uc3QgaWQgPSBnZXRSZW5kZXJDb21tYW5kSWQoY29tbWFuZCk7XG4gICAgY29uc3QgY2FjaGVkID0gdGhpcy5fZXhlY3V0ZWRDb21tYW5kc0NhY2hlLmdldChpZCk7XG5cbiAgICBpZiAoIWNhY2hlZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYWNoZWQgY29tbWFuZCBub3QgZm91bmQhJyk7XG4gICAgfVxuXG4gICAgaWYgKGlzQ29tcG9uZW50UmVuZGVyQ29tbWFuZChjb21tYW5kKSkge1xuICAgICAgaWYgKCFpc0V4ZWN1dGVkQ29tcG9uZW50Q29tbWFuZENhY2hlSXRlbShjYWNoZWQpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignQ2FjaGVkIGNvbW1hbmQgaXMgbm90IGEgY29tcG9uZW50IGNvbW1hbmQhJyk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGNvbXBvbmVudFJlZiA9IGNhY2hlZC5jb21wb25lbnRSZWY7XG5cbiAgICAgIGlmICghY29tcG9uZW50UmVmKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignQ29tcG9uZW50IHJlZiBub3QgZm91bmQhJyk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHJvb3ROb2RlID0gY2FjaGVkLmVsZW1lbnQ7XG4gICAgICBjb25zdCBvbGRQYXJlbnRFbGVtZW50ID0gY2FjaGVkLmVsZW1lbnQucGFyZW50RWxlbWVudDtcblxuICAgICAgdGhpcy5fcmVuZGVyZXIucmVtb3ZlQ2hpbGQob2xkUGFyZW50RWxlbWVudCwgcm9vdE5vZGUpO1xuXG4gICAgICBjb25zdCBuZXdQYXJlbnRFbGVtZW50ID0gdGhpcy5fZmluZFBhcmVudChjb21tYW5kKTtcbiAgICAgIGNvbnN0IG5leHRFbGVtZW50ID0gdGhpcy5fZmluZEZvbGxvd2luZ0VsZW1lbnQoY29tbWFuZCk7XG5cbiAgICAgIHRoaXMuX3JlbmRlckluc2VydE9yQXBwZW5kKHJvb3ROb2RlLCBuZXdQYXJlbnRFbGVtZW50LCBuZXh0RWxlbWVudCk7XG5cbiAgICAgIHRoaXMuX3VwZGF0ZUNvbXBvbmVudElucHV0cyhjb21tYW5kLCBjb21wb25lbnRSZWYpO1xuXG4gICAgICB0aGlzLl9leGVjdXRlZENvbW1hbmRzQ2FjaGUuc2V0KGlkLCB7XG4gICAgICAgIC4uLmNhY2hlZCxcbiAgICAgICAgY29tbWFuZDogY29tbWFuZCBhcyBhbnksXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9ydW5EZWxldGVJbnN0cnVjdGlvbihjb21tYW5kOiBSZW5kZXJDb21tYW5kKSB7XG4gICAgY29uc3QgaWQgPSBnZXRSZW5kZXJDb21tYW5kSWQoY29tbWFuZCk7XG4gICAgY29uc3QgY2FjaGVkID0gdGhpcy5fZXhlY3V0ZWRDb21tYW5kc0NhY2hlLmdldChpZCk7XG5cbiAgICBpZiAoIWNhY2hlZCkge1xuICAgICAgaWYgKGlzSHRtbENsb3NlUmVuZGVyQ29tbWFuZChjb21tYW5kKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2FjaGVkIGNvbW1hbmQgbm90IGZvdW5kIScpO1xuICAgIH1cblxuICAgIGlmIChpc0NvbXBvbmVudFJlbmRlckNvbW1hbmQoY29tbWFuZCkpIHtcbiAgICAgIGlmICghaXNFeGVjdXRlZENvbXBvbmVudENvbW1hbmRDYWNoZUl0ZW0oY2FjaGVkKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhY2hlZCBjb21tYW5kIGlzIG5vdCBhIGNvbXBvbmVudCBjb21tYW5kIScpO1xuICAgICAgfVxuXG4gICAgICBjYWNoZWQuY29tcG9uZW50UmVmPy5kZXN0cm95KCk7XG4gICAgfSBlbHNlIGlmIChpc1RleHRSZW5kZXJDb21tYW5kKGNvbW1hbmQpKSB7XG4gICAgICB0aGlzLl9yZW5kZXJlci5yZW1vdmVDaGlsZChjYWNoZWQuZWxlbWVudD8ucGFyZW50RWxlbWVudCwgY2FjaGVkLmVsZW1lbnQpO1xuICAgIH0gZWxzZSBpZiAoaXNIdG1sT3BlblJlbmRlckNvbW1hbmQoY29tbWFuZCkpIHtcbiAgICAgIHRoaXMuX3JlbmRlcmVyLnJlbW92ZUNoaWxkKGNhY2hlZC5lbGVtZW50Py5wYXJlbnRFbGVtZW50LCBjYWNoZWQuZWxlbWVudCk7XG4gICAgfVxuXG4gICAgdGhpcy5fZXhlY3V0ZWRDb21tYW5kc0NhY2hlLmRlbGV0ZShpZCk7XG4gIH1cblxuICBwcml2YXRlIF9nZXRDb21wb25lbnRSb290Tm9kZShjb21wb25lbnRSZWY6IENvbXBvbmVudFJlZjxhbnk+KTogSFRNTEVsZW1lbnQge1xuICAgIHJldHVybiAoY29tcG9uZW50UmVmLmhvc3RWaWV3IGFzIEVtYmVkZGVkVmlld1JlZjxhbnk+KS5yb290Tm9kZXNbMF0gYXMgSFRNTEVsZW1lbnQ7XG4gIH1cblxuICBwcml2YXRlIF91cGRhdGVDb21wb25lbnRJbnB1dHMoY29tbWFuZDogQ29tcG9uZW50UmVuZGVyQ29tbWFuZCwgY29tcG9uZW50UmVmOiBDb21wb25lbnRSZWY8YW55Pikge1xuICAgIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKGNvbW1hbmRbQ09NUE9ORU5UX1JFTkRFUl9DT01NQU5EX1BPU0lUSU9OLklOUFVUU10pKSB7XG4gICAgICBpZiAoIWNvbXBvbmVudFJlZi5pbnN0YW5jZVtrZXldKSBjb250aW51ZTtcblxuICAgICAgY29tcG9uZW50UmVmLnNldElucHV0KGtleSwgdmFsdWUpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX2ZpbmRQYXJlbnQoY29tbWFuZDogUmVuZGVyQ29tbWFuZCkge1xuICAgIGNvbnN0IGhvc3RFbGVtZW50ID0gdGhpcy5fZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50O1xuICAgIGNvbnN0IG5lc3RpbmdMZXZlbCA9IGNvbW1hbmRbUkVOREVSX0NPTU1BTkRfUE9TSVRJT04uTkVTVElOR19MRVZFTF07XG4gICAgbGV0IHBhcmVudEVsZW1lbnQ6IEhUTUxFbGVtZW50IHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkO1xuXG4gICAgaWYgKG5lc3RpbmdMZXZlbCA9PT0gMCkge1xuICAgICAgcGFyZW50RWxlbWVudCA9IGhvc3RFbGVtZW50O1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBSZXZlcnNlIHNlYXJjaCBhbGwgcmVuZGVyIGNvbW1hbmRzIGJlZ2lubmluZyBmcm9tIHRoZSBjdXJyZW50IG9uZSB1c2luZyBhIGZvciBsb29wLlxuICAgICAgLy8gVGhlIHBhcmVudCBpcyBmb3VuZCB3aGVuIHRoZSBjb21tYW5kJ3MgbmVzdGluZyBsZXZlbCBpc3QgdGhlIHNhbWUgYXMgdGhlIGN1cnJlbnQgbmVzdGluZyBsZXZlbCBtaW51cyAxLlxuICAgICAgLy8gSWYgdGhlIHBhcmVudCBpcyBub3QgZm91bmQsIHRocm93IGFuIGVycm9yLlxuICAgICAgY29uc3QgYWxsQ29tbWFuZHMgPSB0aGlzLnJlbmRlckNvbW1hbmRzKCk7XG4gICAgICBjb25zdCBjdXJyZW50Q29tbWFuZEluZGV4ID0gY29tbWFuZFtSRU5ERVJfQ09NTUFORF9QT1NJVElPTi5JTkRFWF07XG5cbiAgICAgIGxldCBwYXJlbnRDb21tYW5kOiBSZW5kZXJDb21tYW5kIHwgbnVsbCA9IG51bGw7XG5cbiAgICAgIGZvciAobGV0IGkgPSBjdXJyZW50Q29tbWFuZEluZGV4IC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgY29uc3QgY21kID0gYWxsQ29tbWFuZHNbaV07XG5cbiAgICAgICAgaWYgKCFjbWQpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NvbW1hbmQgbm90IGZvdW5kIScpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGNtZFtSRU5ERVJfQ09NTUFORF9QT1NJVElPTi5ORVNUSU5HX0xFVkVMXSA9PT0gbmVzdGluZ0xldmVsIC0gMSkge1xuICAgICAgICAgIHBhcmVudENvbW1hbmQgPSBjbWQ7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKCFwYXJlbnRDb21tYW5kKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignUGFyZW50IGNvbW1hbmQgbm90IGZvdW5kIScpO1xuICAgICAgfVxuXG4gICAgICBwYXJlbnRFbGVtZW50ID0gdGhpcy5fZXhlY3V0ZWRDb21tYW5kc0NhY2hlLmdldChnZXRSZW5kZXJDb21tYW5kSWQocGFyZW50Q29tbWFuZCkpPy5lbGVtZW50O1xuICAgIH1cblxuICAgIGlmICghcGFyZW50RWxlbWVudCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdQYXJlbnQgZWxlbWVudCBub3QgZm91bmQhJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHBhcmVudEVsZW1lbnQ7XG4gIH1cblxuICBwcml2YXRlIF9maW5kRm9sbG93aW5nRWxlbWVudChjb21tYW5kOiBSZW5kZXJDb21tYW5kKSB7XG4gICAgY29uc3QgY2FjaGVBcnJheSA9IEFycmF5LmZyb20odGhpcy5fZXhlY3V0ZWRDb21tYW5kc0NhY2hlLnZhbHVlcygpKTtcbiAgICBsZXQgbmV4dEVsZW1lbnQ6IEhUTUxFbGVtZW50IHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkO1xuXG4gICAgY29uc3QgZG9tUG9zaXRpb24gPSBjb21tYW5kW1JFTkRFUl9DT01NQU5EX1BPU0lUSU9OLkRPTV9QT1NJVElPTl07XG4gICAgY29uc3QgbmVzdGluZ0xldmVsID0gY29tbWFuZFtSRU5ERVJfQ09NTUFORF9QT1NJVElPTi5ORVNUSU5HX0xFVkVMXTtcbiAgICBjb25zdCB0eXBlID0gY29tbWFuZFtSRU5ERVJfQ09NTUFORF9QT1NJVElPTi5UWVBFXTtcblxuICAgIC8vICBUcnkgdG8gZmluZCBhbiBhbHJlYWR5IHJlbmRlcmVkIGVsZW1lbnQgd2l0aCBhIGRvbVBvc2l0aW9uIHRoYXQgaXMgZ3JlYXRlciB0aGFuIHRoZSBjdXJyZW50IGRvbVBvc2l0aW9uLiBJZiB0aGVyZSBhcmUgbXVsdGlwbGUsIHVzZSB0aGUgb25lIHdpdGggdGhlIHNtYWxsZXN0IGRvbVBvc2l0aW9uLlxuICAgIC8vIElmIGl0IGRvZXMgbm90IGV4aXN0LCB1c2UgLmFwcGVuZENoaWxkIHRvIHNpbXBseSBhcHBlbmQgdGhlIGVsZW1lbnQgdG8gdGhlIGVuZCBvZiB0aGUgcGFyZW50IGVsZW1lbnQuXG4gICAgLy8gSWYgaXQgZG9lcyBleGlzdCwgdXNlIC5pbnNlcnRCZWZvcmUgdG8gaW5zZXJ0IHRoZSBlbGVtZW50IGJlZm9yZSB0aGUgZm91bmQgZWxlbWVudC5cbiAgICBmb3IgKGNvbnN0IGNhY2hlZCBvZiBjYWNoZUFycmF5KSB7XG4gICAgICBpZiAoXG4gICAgICAgIGNhY2hlZC5jb21tYW5kW1JFTkRFUl9DT01NQU5EX1BPU0lUSU9OLkRPTV9QT1NJVElPTl0gPiBkb21Qb3NpdGlvbiAmJlxuICAgICAgICBjYWNoZWQuY29tbWFuZFtSRU5ERVJfQ09NTUFORF9QT1NJVElPTi5ORVNUSU5HX0xFVkVMXSA9PT0gbmVzdGluZ0xldmVsICYmXG4gICAgICAgIC8vIE1ha2Ugc3VyZSB0aGUgZWxlbWVudCBkb2VzIG5vdCBmaW5kIGl0c2VsZlxuICAgICAgICBjYWNoZWQuY29tbWFuZFtSRU5ERVJfQ09NTUFORF9QT1NJVElPTi5UWVBFXSAhPT0gdHlwZVxuICAgICAgKSB7XG4gICAgICAgIG5leHRFbGVtZW50ID0gY2FjaGVkLmVsZW1lbnQ7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBuZXh0RWxlbWVudDtcbiAgfVxuXG4gIHByaXZhdGUgX3JlbmRlckluc2VydE9yQXBwZW5kKFxuICAgIG5vZGVUb1JlbmRlcjogSFRNTEVsZW1lbnQsXG4gICAgcGFyZW50RWxlbWVudDogSFRNTEVsZW1lbnQsXG4gICAgbmV4dEVsZW1lbnQ6IEhUTUxFbGVtZW50IHwgdW5kZWZpbmVkLFxuICApIHtcbiAgICBpZiAobmV4dEVsZW1lbnQpIHtcbiAgICAgIHRoaXMuX3JlbmRlcmVyLmluc2VydEJlZm9yZShwYXJlbnRFbGVtZW50LCBub2RlVG9SZW5kZXIsIG5leHRFbGVtZW50KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fcmVuZGVyZXIuYXBwZW5kQ2hpbGQocGFyZW50RWxlbWVudCwgbm9kZVRvUmVuZGVyKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9kZWJ1Z1Zpc3VhbGl6ZVJlbmRlckNvbW1hbmRzKGNvbW1hbmRzOiBSZW5kZXJDb21tYW5kW10pIHtcbiAgICBjb25zdCBkZWJ1ZyA9IGNvbW1hbmRzLm1hcCgoY29tbWFuZCkgPT4gdGhpcy5fc3RyaW5naWZ5UmVuZGVyQ29tbWFuZChjb21tYW5kKSkuZmxhdCgpO1xuXG4gICAgY29uc3QgcHJldHRpZmllZCA9IGZvcm1hdEhUTUwoZGVidWcpO1xuXG4gICAgcmV0dXJuIHByZXR0aWZpZWQ7XG4gIH1cblxuICBwcml2YXRlIF9zdHJpbmdpZnlSZW5kZXJDb21tYW5kKGNvbW1hbmQ6IFJlbmRlckNvbW1hbmQpIHtcbiAgICBjb25zdCBuZXN0QXR0ciA9IGBuZXN0PVwiJHtjb21tYW5kW1JFTkRFUl9DT01NQU5EX1BPU0lUSU9OLk5FU1RJTkdfTEVWRUxdfVwiYDtcbiAgICBjb25zdCBkb21BdHRyID0gYGRvbT1cIiR7Y29tbWFuZFtSRU5ERVJfQ09NTUFORF9QT1NJVElPTi5ET01fUE9TSVRJT05dfVwiYDtcblxuICAgIGlmIChpc0h0bWxPcGVuUmVuZGVyQ29tbWFuZChjb21tYW5kKSkge1xuICAgICAgcmV0dXJuIGA8JHtjb21tYW5kW0hUTUxfT1BFTl9SRU5ERVJfQ09NTUFORF9QT1NJVElPTi5UQUdfTkFNRV19ICR7bmVzdEF0dHJ9ICR7ZG9tQXR0cn0+YDtcbiAgICB9IGVsc2UgaWYgKGlzSHRtbENsb3NlUmVuZGVyQ29tbWFuZChjb21tYW5kKSkge1xuICAgICAgcmV0dXJuIGA8LyR7Y29tbWFuZFtIVE1MX0NMT1NFX1JFTkRFUl9DT01NQU5EX1BPU0lUSU9OLlRBR19OQU1FXX0gJHtuZXN0QXR0cn0gJHtkb21BdHRyfT5gO1xuICAgIH0gZWxzZSBpZiAoaXNUZXh0UmVuZGVyQ29tbWFuZChjb21tYW5kKSkge1xuICAgICAgcmV0dXJuIFtgPHNwYW4gJHtuZXN0QXR0cn0gJHtkb21BdHRyfT5gLCBjb21tYW5kW1RFWFRfUkVOREVSX0NPTU1BTkRfUE9TSVRJT04uVEVYVF0sICc8L3NwYW4+J107XG4gICAgfSBlbHNlIGlmIChpc0NvbXBvbmVudFJlbmRlckNvbW1hbmQoY29tbWFuZCkpIHtcbiAgICAgIGNvbnN0IHNlbGVjdG9yID0gY29tbWFuZFtDT01QT05FTlRfUkVOREVSX0NPTU1BTkRfUE9TSVRJT04uQ09NUE9ORU5UX1RZUEVdO1xuICAgICAgcmV0dXJuIFtgPCR7c2VsZWN0b3J9ICR7bmVzdEF0dHJ9ICR7ZG9tQXR0cn0+YCwgYDwvJHtzZWxlY3Rvcn0+YF07XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiAnVU5LTk9XTic7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfc3RyaW5naWZ5UmVuZGVySW5zdHJ1Y3Rpb24oaW5zdHJ1Y3Rpb246IFJlbmRlckluc3RydWN0aW9uKSB7XG4gICAgY29uc3QgdHlwZSA9IGluc3RydWN0aW9uW1JFTkRFUl9JTlNUUlVDVElPTl9QT1NJVElPTi5UWVBFXTtcbiAgICBjb25zdCB0cmFuc2xhdGVkVHlwZSA9IE9iamVjdC5lbnRyaWVzKFJFTkRFUl9JTlNUUlVDVElPTl9UWVBFKS5maW5kKChbLCB2YWx1ZV0pID0+IHZhbHVlID09PSB0eXBlKT8uWzBdO1xuXG4gICAgY29uc3QgY29tbWFuZCA9IHRoaXMuX3N0cmluZ2lmeVJlbmRlckNvbW1hbmQoaW5zdHJ1Y3Rpb25bUkVOREVSX0lOU1RSVUNUSU9OX1BPU0lUSU9OLkNPTU1BTkRdKTtcblxuICAgIHJldHVybiBgJHt0cmFuc2xhdGVkVHlwZX06ICR7Y29tbWFuZH1gO1xuICB9XG59XG5cbmZ1bmN0aW9uIGZvcm1hdEhUTUwoaHRtbDogc3RyaW5nW10pIHtcbiAgY29uc3QgcmVzdWx0OiBzdHJpbmdbXSA9IFtdO1xuICBsZXQgaW5kZW50ID0gMDtcblxuICBmb3IgKGNvbnN0IHRhZyBvZiBodG1sKSB7XG4gICAgaWYgKHRhZy5zdGFydHNXaXRoKCc8LycpKSB7XG4gICAgICBpbmRlbnQtLTtcbiAgICB9XG5cbiAgICByZXN1bHQucHVzaCgnICcucmVwZWF0KGluZGVudCAqIDIpICsgdGFnKTtcblxuICAgIGlmICh0YWcuc3RhcnRzV2l0aCgnPCcpICYmICF0YWcuc3RhcnRzV2l0aCgnPC8nKSkge1xuICAgICAgaW5kZW50Kys7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJlc3VsdC5qb2luKCdcXG4nKTtcbn1cbiJdfQ==
|