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