@firestitch/report 18.8.1 → 18.10.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 (208) hide show
  1. package/app/reports/anchor-at-point.d.ts +14 -0
  2. package/app/reports/canvas-landing-page.d.ts +2 -0
  3. package/app/reports/components/component-chart/component-chart.component.d.ts +18 -2
  4. package/app/reports/components/component-kpi/component-kpi.component.d.ts +4 -1
  5. package/app/reports/components/component-text/component-text.component.d.ts +47 -2
  6. package/app/reports/components/component-text/value-embed.plugin.d.ts +67 -0
  7. package/app/reports/components/report-canvas/report-canvas.component.d.ts +37 -9
  8. package/app/reports/components/report-component/report-component.component.d.ts +45 -2
  9. package/app/reports/components/report-view-picker/report-view-picker.component.d.ts +21 -0
  10. package/app/reports/data/report.data.d.ts +18 -2
  11. package/app/reports/dialogs/component-settings/component-settings.component.d.ts +25 -2
  12. package/app/reports/dialogs/report-settings/report-settings.component.d.ts +15 -6
  13. package/app/reports/dialogs/report-view/report-view-dialog.component.d.ts +13 -0
  14. package/app/reports/drill-crumbs.d.ts +12 -0
  15. package/app/reports/enums/report-value-formula.enum.d.ts +6 -0
  16. package/app/reports/export/report-export-collector.service.d.ts +35 -4
  17. package/app/reports/export/report-export.service.d.ts +3 -1
  18. package/app/reports/export/report-filter-lines.d.ts +18 -0
  19. package/app/reports/export/report-pdf.service.d.ts +18 -2
  20. package/app/reports/export/report-pptx.service.d.ts +15 -2
  21. package/app/reports/export/report-text-layout.service.d.ts +35 -0
  22. package/app/reports/filter-settings-rules.d.ts +33 -0
  23. package/app/reports/format.d.ts +2 -1
  24. package/app/reports/interfaces/canvas-landing-input.interface.d.ts +8 -0
  25. package/app/reports/interfaces/component-data-applied.interface.d.ts +13 -0
  26. package/app/reports/interfaces/component-data-drill.interface.d.ts +22 -0
  27. package/app/reports/interfaces/filter-bar-placement.type.d.ts +1 -0
  28. package/app/reports/interfaces/filter-component-toggle-state.interface.d.ts +4 -0
  29. package/app/reports/interfaces/filter-settings-option.interface.d.ts +4 -0
  30. package/app/reports/interfaces/filter-type-select-state.interface.d.ts +5 -0
  31. package/app/reports/interfaces/report-chart-hit.interface.d.ts +5 -0
  32. package/app/reports/interfaces/report-chat-viewer-cross-filter-field.interface.d.ts +4 -0
  33. package/app/reports/interfaces/report-chat-viewer-cross-filter.interface.d.ts +7 -0
  34. package/app/reports/interfaces/report-chat-viewer-detail.interface.d.ts +4 -0
  35. package/app/reports/interfaces/report-chat-viewer-drill-step.interface.d.ts +5 -0
  36. package/app/reports/interfaces/report-chat-viewer-drill.interface.d.ts +5 -0
  37. package/app/reports/interfaces/report-chat-viewer-filter.interface.d.ts +3 -0
  38. package/app/reports/interfaces/report-chat-viewer-selection.interface.d.ts +5 -0
  39. package/app/reports/interfaces/report-chat-viewer-state.interface.d.ts +12 -0
  40. package/app/reports/interfaces/report-drill-crumb.interface.d.ts +6 -0
  41. package/app/reports/interfaces/report-drill-refusal.type.d.ts +1 -0
  42. package/app/reports/interfaces/report-drill-step.interface.d.ts +5 -0
  43. package/app/reports/interfaces/report-export-line-kind.type.d.ts +1 -0
  44. package/app/reports/interfaces/report-export-line.interface.d.ts +8 -0
  45. package/app/reports/interfaces/report-export-lines-input.interface.d.ts +9 -0
  46. package/app/reports/interfaces/report-export-snapshot.interface.d.ts +15 -0
  47. package/app/reports/interfaces/report-filter-line-context.interface.d.ts +8 -0
  48. package/app/reports/interfaces/report-filter-line-form.type.d.ts +1 -0
  49. package/app/reports/interfaces/report-filter-match.type.d.ts +1 -0
  50. package/app/reports/interfaces/report-filter-option-pair.interface.d.ts +4 -0
  51. package/app/reports/interfaces/report-filter-options-ask.interface.d.ts +6 -0
  52. package/app/reports/interfaces/report-filter-options-list.interface.d.ts +7 -0
  53. package/app/reports/interfaces/report-filter-options-request.interface.d.ts +6 -0
  54. package/app/reports/interfaces/report-filter-options-stream.interface.d.ts +11 -0
  55. package/app/reports/interfaces/report-filter-options.interface.d.ts +7 -0
  56. package/app/reports/interfaces/report-filter-skip.type.d.ts +1 -0
  57. package/app/reports/interfaces/report-mark-action.type.d.ts +1 -0
  58. package/app/reports/interfaces/report-mark-click.interface.d.ts +13 -0
  59. package/app/reports/interfaces/report-mark-context.interface.d.ts +6 -0
  60. package/app/reports/interfaces/report-mark-decision.interface.d.ts +6 -0
  61. package/app/reports/interfaces/report-mark-event.interface.d.ts +11 -0
  62. package/app/reports/interfaces/report-mark-point.interface.d.ts +8 -0
  63. package/app/reports/interfaces/report-temporary-state.interface.d.ts +4 -0
  64. package/app/reports/interfaces/report-tile-state.interface.d.ts +8 -0
  65. package/app/reports/interfaces/report-url-link.interface.d.ts +4 -0
  66. package/app/reports/interfaces/report-url-value-name.type.d.ts +1 -0
  67. package/app/reports/interfaces/report-url-write.interface.d.ts +4 -0
  68. package/app/reports/interfaces/report-view-config.interface.d.ts +11 -0
  69. package/app/reports/interfaces/report-view-create.interface.d.ts +7 -0
  70. package/app/reports/interfaces/report-view-deleted.interface.d.ts +4 -0
  71. package/app/reports/interfaces/report-view-dialog-data.interface.d.ts +7 -0
  72. package/app/reports/interfaces/report-view-dropped.interface.d.ts +5 -0
  73. package/app/reports/interfaces/report-view-menu-item.interface.d.ts +10 -0
  74. package/app/reports/interfaces/report-view-summary.interface.d.ts +11 -0
  75. package/app/reports/interfaces/report-view.interface.d.ts +7 -0
  76. package/app/reports/interfaces/report-viewer-feature.type.d.ts +1 -0
  77. package/app/reports/interfaces/report-views.interface.d.ts +7 -0
  78. package/app/reports/interfaces/report.interface.d.ts +48 -5
  79. package/app/reports/interfaces/tile-load-result.interface.d.ts +4 -0
  80. package/app/reports/layout.d.ts +2 -0
  81. package/app/reports/mark-click.d.ts +20 -0
  82. package/app/reports/option-builder.d.ts +12 -1
  83. package/app/reports/report-chat-viewer-state.d.ts +8 -0
  84. package/app/reports/report-date-presets.d.ts +2 -0
  85. package/app/reports/report-filter-items.d.ts +27 -22
  86. package/app/reports/report-tile.d.ts +2 -0
  87. package/app/reports/report-url-state.d.ts +27 -10
  88. package/app/reports/report-view-config.d.ts +36 -0
  89. package/app/reports/report-view-menu.d.ts +15 -0
  90. package/app/reports/report-viewer-features.d.ts +5 -0
  91. package/app/reports/services/report-filter-options.service.d.ts +26 -0
  92. package/app/reports/services/report-filter-state.service.d.ts +65 -2
  93. package/app/reports/services/report-view.service.d.ts +51 -0
  94. package/app/reports/text.d.ts +50 -0
  95. package/app/reports/tile-data-state.d.ts +7 -0
  96. package/app/reports/tile-loads.d.ts +4 -0
  97. package/app/reports/values.d.ts +17 -0
  98. package/app/reports/views/report/fs-ai-report.component.d.ts +9 -1
  99. package/app/reports/views/report/report.component.d.ts +6 -0
  100. package/esm2022/app/reports/anchor-at-point.mjs +49 -0
  101. package/esm2022/app/reports/canvas-landing-page.mjs +25 -0
  102. package/esm2022/app/reports/components/component-chart/component-chart.component.mjs +97 -5
  103. package/esm2022/app/reports/components/component-kpi/component-kpi.component.mjs +11 -4
  104. package/esm2022/app/reports/components/component-list/component-list.component.mjs +7 -1
  105. package/esm2022/app/reports/components/component-text/component-text.component.mjs +213 -16
  106. package/esm2022/app/reports/components/component-text/value-embed.plugin.mjs +484 -0
  107. package/esm2022/app/reports/components/report-canvas/report-canvas.component.mjs +296 -55
  108. package/esm2022/app/reports/components/report-component/report-component.component.mjs +318 -76
  109. package/esm2022/app/reports/components/report-view-picker/report-view-picker.component.mjs +115 -0
  110. package/esm2022/app/reports/data/report.data.mjs +103 -8
  111. package/esm2022/app/reports/dialogs/component-settings/component-settings.component.mjs +210 -44
  112. package/esm2022/app/reports/dialogs/report-settings/report-settings.component.mjs +86 -90
  113. package/esm2022/app/reports/dialogs/report-view/report-view-dialog.component.mjs +52 -0
  114. package/esm2022/app/reports/drill-crumbs.mjs +73 -0
  115. package/esm2022/app/reports/enums/report-value-formula.enum.mjs +14 -0
  116. package/esm2022/app/reports/export/report-export-collector.service.mjs +299 -125
  117. package/esm2022/app/reports/export/report-export.service.mjs +57 -19
  118. package/esm2022/app/reports/export/report-filter-lines.mjs +235 -0
  119. package/esm2022/app/reports/export/report-pdf.service.mjs +315 -71
  120. package/esm2022/app/reports/export/report-pptx.service.mjs +293 -71
  121. package/esm2022/app/reports/export/report-text-layout.service.mjs +241 -0
  122. package/esm2022/app/reports/filter-settings-rules.mjs +283 -0
  123. package/esm2022/app/reports/format.mjs +13 -30
  124. package/esm2022/app/reports/interfaces/canvas-landing-input.interface.mjs +2 -0
  125. package/esm2022/app/reports/interfaces/component-data-applied.interface.mjs +2 -0
  126. package/esm2022/app/reports/interfaces/component-data-drill.interface.mjs +2 -0
  127. package/esm2022/app/reports/interfaces/filter-bar-placement.type.mjs +2 -0
  128. package/esm2022/app/reports/interfaces/filter-component-toggle-state.interface.mjs +2 -0
  129. package/esm2022/app/reports/interfaces/filter-settings-option.interface.mjs +2 -0
  130. package/esm2022/app/reports/interfaces/filter-type-select-state.interface.mjs +2 -0
  131. package/esm2022/app/reports/interfaces/report-chart-hit.interface.mjs +2 -0
  132. package/esm2022/app/reports/interfaces/report-chat-viewer-cross-filter-field.interface.mjs +2 -0
  133. package/esm2022/app/reports/interfaces/report-chat-viewer-cross-filter.interface.mjs +2 -0
  134. package/esm2022/app/reports/interfaces/report-chat-viewer-detail.interface.mjs +2 -0
  135. package/esm2022/app/reports/interfaces/report-chat-viewer-drill-step.interface.mjs +2 -0
  136. package/esm2022/app/reports/interfaces/report-chat-viewer-drill.interface.mjs +2 -0
  137. package/esm2022/app/reports/interfaces/report-chat-viewer-filter.interface.mjs +1 -1
  138. package/esm2022/app/reports/interfaces/report-chat-viewer-selection.interface.mjs +2 -0
  139. package/esm2022/app/reports/interfaces/report-chat-viewer-state.interface.mjs +1 -1
  140. package/esm2022/app/reports/interfaces/report-drill-crumb.interface.mjs +2 -0
  141. package/esm2022/app/reports/interfaces/report-drill-refusal.type.mjs +2 -0
  142. package/esm2022/app/reports/interfaces/report-drill-step.interface.mjs +2 -0
  143. package/esm2022/app/reports/interfaces/report-export-line-kind.type.mjs +2 -0
  144. package/esm2022/app/reports/interfaces/report-export-line.interface.mjs +2 -0
  145. package/esm2022/app/reports/interfaces/report-export-lines-input.interface.mjs +2 -0
  146. package/esm2022/app/reports/interfaces/report-export-snapshot.interface.mjs +2 -0
  147. package/esm2022/app/reports/interfaces/report-filter-line-context.interface.mjs +2 -0
  148. package/esm2022/app/reports/interfaces/report-filter-line-form.type.mjs +2 -0
  149. package/esm2022/app/reports/interfaces/report-filter-match.type.mjs +2 -0
  150. package/esm2022/app/reports/interfaces/report-filter-option-pair.interface.mjs +2 -0
  151. package/esm2022/app/reports/interfaces/report-filter-options-ask.interface.mjs +2 -0
  152. package/esm2022/app/reports/interfaces/report-filter-options-list.interface.mjs +2 -0
  153. package/esm2022/app/reports/interfaces/report-filter-options-request.interface.mjs +2 -0
  154. package/esm2022/app/reports/interfaces/report-filter-options-stream.interface.mjs +2 -0
  155. package/esm2022/app/reports/interfaces/report-filter-options.interface.mjs +2 -0
  156. package/esm2022/app/reports/interfaces/report-filter-skip.type.mjs +2 -0
  157. package/esm2022/app/reports/interfaces/report-mark-action.type.mjs +2 -0
  158. package/esm2022/app/reports/interfaces/report-mark-click.interface.mjs +2 -0
  159. package/esm2022/app/reports/interfaces/report-mark-context.interface.mjs +2 -0
  160. package/esm2022/app/reports/interfaces/report-mark-decision.interface.mjs +2 -0
  161. package/esm2022/app/reports/interfaces/report-mark-event.interface.mjs +2 -0
  162. package/esm2022/app/reports/interfaces/report-mark-point.interface.mjs +2 -0
  163. package/esm2022/app/reports/interfaces/report-temporary-state.interface.mjs +2 -0
  164. package/esm2022/app/reports/interfaces/report-tile-state.interface.mjs +2 -0
  165. package/esm2022/app/reports/interfaces/report-url-link.interface.mjs +2 -0
  166. package/esm2022/app/reports/interfaces/report-url-value-name.type.mjs +2 -0
  167. package/esm2022/app/reports/interfaces/report-url-write.interface.mjs +2 -0
  168. package/esm2022/app/reports/interfaces/report-view-config.interface.mjs +2 -0
  169. package/esm2022/app/reports/interfaces/report-view-create.interface.mjs +2 -0
  170. package/esm2022/app/reports/interfaces/report-view-deleted.interface.mjs +2 -0
  171. package/esm2022/app/reports/interfaces/report-view-dialog-data.interface.mjs +2 -0
  172. package/esm2022/app/reports/interfaces/report-view-dropped.interface.mjs +2 -0
  173. package/esm2022/app/reports/interfaces/report-view-menu-item.interface.mjs +2 -0
  174. package/esm2022/app/reports/interfaces/report-view-summary.interface.mjs +2 -0
  175. package/esm2022/app/reports/interfaces/report-view.interface.mjs +2 -0
  176. package/esm2022/app/reports/interfaces/report-viewer-feature.type.mjs +2 -0
  177. package/esm2022/app/reports/interfaces/report-views.interface.mjs +2 -0
  178. package/esm2022/app/reports/interfaces/report.interface.mjs +1 -1
  179. package/esm2022/app/reports/interfaces/tile-load-result.interface.mjs +2 -0
  180. package/esm2022/app/reports/layout.mjs +11 -1
  181. package/esm2022/app/reports/mark-click.mjs +193 -0
  182. package/esm2022/app/reports/option-builder.mjs +159 -15
  183. package/esm2022/app/reports/report-chat-viewer-state.mjs +34 -0
  184. package/esm2022/app/reports/report-date-presets.mjs +18 -0
  185. package/esm2022/app/reports/report-filter-items.mjs +343 -72
  186. package/esm2022/app/reports/report-tile.mjs +12 -0
  187. package/esm2022/app/reports/report-url-state.mjs +596 -108
  188. package/esm2022/app/reports/report-view-config.mjs +697 -0
  189. package/esm2022/app/reports/report-view-menu.mjs +119 -0
  190. package/esm2022/app/reports/report-viewer-features.mjs +42 -0
  191. package/esm2022/app/reports/services/report-filter-options.service.mjs +238 -0
  192. package/esm2022/app/reports/services/report-filter-state.service.mjs +715 -71
  193. package/esm2022/app/reports/services/report-view.service.mjs +358 -0
  194. package/esm2022/app/reports/text.mjs +293 -85
  195. package/esm2022/app/reports/tile-data-state.mjs +127 -0
  196. package/esm2022/app/reports/tile-loads.mjs +38 -0
  197. package/esm2022/app/reports/values.mjs +183 -0
  198. package/esm2022/app/reports/views/report/fs-ai-report.component.mjs +180 -46
  199. package/esm2022/app/reports/views/report/report.component.mjs +106 -23
  200. package/esm2022/public_api.mjs +24 -1
  201. package/fesm2022/{firestitch-report-echarts-CFnbJx44.mjs → firestitch-report-echarts-UBg8Wlhd.mjs} +2 -2
  202. package/fesm2022/{firestitch-report-echarts-CFnbJx44.mjs.map → firestitch-report-echarts-UBg8Wlhd.mjs.map} +1 -1
  203. package/fesm2022/{firestitch-report-firestitch-report-CSylkyko.mjs → firestitch-report-firestitch-report-B1keNrcK.mjs} +11315 -4201
  204. package/fesm2022/firestitch-report-firestitch-report-B1keNrcK.mjs.map +1 -0
  205. package/fesm2022/firestitch-report.mjs +1 -1
  206. package/package.json +1 -1
  207. package/public_api.d.ts +23 -0
  208. package/fesm2022/firestitch-report-firestitch-report-CSylkyko.mjs.map +0 -1
@@ -0,0 +1,484 @@
1
+ import { Plugin } from '@firestitch/html-editor';
2
+ import { VALUE_TOKEN_PATTERN, valueText, valueToken } from '../../text';
3
+ // How a value chip is marked in the editor. The names follow the embeds of
4
+ // @firestitch/markdown-editor. Attributes rather than a class: the report keeps
5
+ // Froala on inline styles (useClasses: false), and a chip never reaches storage
6
+ // anyway — it turns back into its {{value.key}} token on the way out.
7
+ const TYPE_ATTRIBUTE = 'data-embed-type';
8
+ const KEY_ATTRIBUTE = 'data-embed-key';
9
+ const MISSING_ATTRIBUTE = 'data-embed-missing';
10
+ const CHIP_SELECTOR = `[${KEY_ATTRIBUTE}]`;
11
+ const VALUE_TYPE = 'value';
12
+ // The page a copy came from, on the clipboard beside its text: values belong
13
+ // to their page, so a value pasted onto another one doesn't come with it.
14
+ const SCOPE_TYPE = 'application/x-fs-report-value-scope';
15
+ // What Froala must keep on a chip when it cleans html it is handed.
16
+ export const VALUE_EMBED_ATTRIBUTES = [TYPE_ATTRIBUTE, KEY_ATTRIBUTE, MISSING_ATTRIBUTE, 'contenteditable'];
17
+ // A brief ring around the chips an edit was stopped at.
18
+ const FLASH = [{ boxShadow: '0 0 0 2px #e15759' }, { boxShadow: '0 0 0 2px transparent' }];
19
+ const FLASH_MS = 700;
20
+ // Commands that would build what the server rewrites (ReportTextHtml): a table
21
+ // is kept only between paragraphs, and a cell holds words and values only.
22
+ const TABLE_INSERT_COMMANDS = ['insertTable', 'tableInsert'];
23
+ const NO_TABLE_INSIDE = 'li, td, th';
24
+ const CELL_COMMANDS = ['formatUL', 'formatOL', 'paragraphFormat'];
25
+ const CELL = 'td, th';
26
+ // Undo and redo restore a step; they remove nothing of their own.
27
+ const HISTORY_COMMANDS = ['undo', 'redo'];
28
+ // Keys that, pressed alone, edit nothing.
29
+ const MODIFIER_KEYS = ['Shift', 'Control', 'Alt', 'AltGraph', 'Meta'];
30
+ // The cells of a table selected as cells (Froala's own marking).
31
+ const SELECTED_CELL = '.fr-selected-cell';
32
+ // Live values inside a text block's editor.
33
+ //
34
+ // Stored html carries a value as a {{value.key}} token. While editing, each
35
+ // token is a chip: one character to the cursor, labeled with the value, and
36
+ // reporting a click. Froala's html.get hands back tokens again, so the draft
37
+ // and the saved html never hold a chip.
38
+ //
39
+ // A chip can't be deleted by editing: Backspace or Delete beside it, and any
40
+ // deleting, typing over, cutting, pasting over or dragging of a selection that
41
+ // holds one, is stopped and reported. It is taken out on purpose by selecting
42
+ // it and pressing Delete, then taking the stopped selection's
43
+ // removeSelection(); a value that was deleted leaves through removeKey().
44
+ //
45
+ // A table is the exception: deleting a row, a column or the table, or
46
+ // emptying several selected cells, goes through with the chips in it, and is
47
+ // reported as removed() when it took a value's last chip, with the undo that
48
+ // brings them back.
49
+ export class ValueEmbedPlugin extends Plugin {
50
+ // The editor this plugin serves; null until it is built, and after it is gone.
51
+ _editor = null;
52
+ // Set while a deliberate removal runs, so the guards let it through.
53
+ _removing = false;
54
+ // Listeners on the editable element, captured so each runs before Froala's
55
+ // own handler for the same event.
56
+ _domListeners = [];
57
+ // The page the paste under way was copied on ('' when not from a block).
58
+ _pasteScope = '';
59
+ // How many chips each key had as the command under way started; null for
60
+ // one that removes nothing of its own (undo, redo).
61
+ _before = null;
62
+ constructor(config) {
63
+ super();
64
+ this.config = config;
65
+ }
66
+ initialize() {
67
+ if (!this.config.host().contains(this.editor.el)) {
68
+ return;
69
+ }
70
+ const editor = this.editor;
71
+ const el = editor.el;
72
+ this._editor = editor;
73
+ editor.events.on('html.set', () => this._toChips());
74
+ editor.events.on('paste.after', () => this._toChips(true));
75
+ this._watchCommands(editor);
76
+ editor.events.on('html.get', (html) => this._toTokens(html));
77
+ // First in Froala's chain, so its own Backspace handling never runs on a
78
+ // stopped key.
79
+ editor.events.on('keydown', (event) => this._onKeydown(event), true);
80
+ editor.events.on('paste.before', (event) => {
81
+ this._pasteScope = event?.clipboardData?.getData(SCOPE_TYPE) ?? '';
82
+ return this._guardSelection(event);
83
+ });
84
+ // A press on a chip opens its popover; Froala's floating toolbar, which
85
+ // pops up on any press in the text and sits above every overlay, stays
86
+ // away for it.
87
+ editor.events.on('toolbar.show', (event) => (this._onChip(event) ? false : undefined), true);
88
+ // Only while it is still this editor: reopening a block builds the next
89
+ // one before the last is torn down.
90
+ editor.events.on('destroy', () => {
91
+ if (this._editor === editor) {
92
+ this.destroy();
93
+ }
94
+ });
95
+ this._domListeners = [
96
+ ['beforeinput', (event) => this._onBeforeInput(event)],
97
+ ['cut', (event) => this._guardSelection(event)],
98
+ ['dragstart', (event) => this._guardSelection(event)],
99
+ ['copy', (event) => this._onCopy(event)],
100
+ ['click', (event) => this._onClick(event)],
101
+ ];
102
+ this._domListeners.forEach(([name, listener]) => el.addEventListener(name, listener, true));
103
+ this._toChips();
104
+ }
105
+ destroy() {
106
+ const el = this._editor?.el;
107
+ this._domListeners.forEach(([name, listener]) => el?.removeEventListener(name, listener, true));
108
+ this._domListeners = [];
109
+ this._editor = null;
110
+ }
111
+ // Relabel every chip: the values arrived or changed, or names were toggled.
112
+ refresh() {
113
+ this._chips().forEach((chip) => this._label(chip));
114
+ }
115
+ // Put Froala's floating toolbar and a table's popup away, when either is
116
+ // already up as a chip's popover opens: they sit above every overlay.
117
+ hideToolbar() {
118
+ this._editor?.toolbar.hide();
119
+ this._editor?.popups.hide('table.edit');
120
+ }
121
+ // The editor's own undo of the last step: what puts back the chips an edit
122
+ // took out.
123
+ undo() {
124
+ this._editor?.commands.undo();
125
+ }
126
+ // Take a value out of the text, wherever it appears — it was deleted.
127
+ removeKey(key) {
128
+ this._chips()
129
+ .filter((chip) => chip.getAttribute(KEY_ATTRIBUTE) === key)
130
+ .forEach((chip) => this.remove(chip));
131
+ }
132
+ // Take one chip out of the text.
133
+ remove(chip) {
134
+ if (!this._editor?.el.contains(chip)) {
135
+ return;
136
+ }
137
+ // The cursor goes back where the chip was — whatever asked for the
138
+ // removal (a dialog, a popover) took the focus, and without it an Undo
139
+ // straight after would never reach the editor.
140
+ const caret = document.createRange();
141
+ caret.setStartBefore(chip);
142
+ caret.collapse(true);
143
+ this._editor.undo.saveStep();
144
+ chip.remove();
145
+ this._editor.el.focus();
146
+ const selection = this._selection();
147
+ selection.removeAllRanges();
148
+ selection.addRange(caret);
149
+ this._changed();
150
+ }
151
+ _chips() {
152
+ return this._editor
153
+ ? Array.from(this._editor.el.querySelectorAll(CHIP_SELECTOR))
154
+ : [];
155
+ }
156
+ // How many chips each key has in the block.
157
+ _chipCounts() {
158
+ const counts = new Map();
159
+ this._chips().forEach((chip) => {
160
+ const key = chip.getAttribute(KEY_ATTRIBUTE);
161
+ counts.set(key, (counts.get(key) ?? 0) + 1);
162
+ });
163
+ return counts;
164
+ }
165
+ // Tell the host when an edit took the last chip of some key out of the
166
+ // block, given the counts from before it.
167
+ _reportRemoved(before) {
168
+ if (!before || !this._editor) {
169
+ return;
170
+ }
171
+ const after = this._chipCounts();
172
+ if ([...before.keys()].some((key) => !after.has(key))) {
173
+ this.config.removed({
174
+ before: [...before.keys()],
175
+ after: [...after.keys()],
176
+ undo: () => this.undo(),
177
+ });
178
+ }
179
+ }
180
+ // A toolbar command sees tokens, not chips: Clear formatting unwraps every
181
+ // span, a chip included, which would leave a typed number behind. Around a
182
+ // token it formats plain text, and the chip comes back inside whatever
183
+ // formatting the token was given.
184
+ _watchCommands(editor) {
185
+ editor.events.on('commands.before', (command) => this._onCommandBefore(command));
186
+ editor.events.on('commands.after', () => {
187
+ this._toChips();
188
+ this._reportRemoved(this._before);
189
+ this._before = null;
190
+ });
191
+ // Undo and redo restore a step as Froala saved it: the one before a
192
+ // command holds tokens, as the command saw them. Neither fires
193
+ // commands.after: Froala's commands.undo() — Ctrl+Z, and undo() here —
194
+ // runs the undo directly.
195
+ editor.events.on('commands.undo', () => this._toChips());
196
+ editor.events.on('commands.redo', () => this._toChips());
197
+ }
198
+ // Every command starts a new edit. One that would build what the server
199
+ // rewrites is refused (returning false cancels it); any other runs on
200
+ // tokens, its chip counts kept to see what it removed.
201
+ _onCommandBefore(command) {
202
+ this.config.changed();
203
+ if (TABLE_INSERT_COMMANDS.includes(command) && this._caretIn(NO_TABLE_INSIDE)) {
204
+ this.config.refused('A table goes between paragraphs, never inside a list or another table.');
205
+ return false;
206
+ }
207
+ if (CELL_COMMANDS.includes(command) && this._caretIn(CELL)) {
208
+ this.config.refused('A table cell holds words and values; a list or a heading goes outside the table.');
209
+ return false;
210
+ }
211
+ this._before = HISTORY_COMMANDS.includes(command) ? null : this._chipCounts();
212
+ this._toTokenText();
213
+ }
214
+ // Whether the caret sits inside an element of this editor that `selector`
215
+ // matches.
216
+ _caretIn(selector) {
217
+ const container = this._editor.selection.element()?.closest?.(selector) ?? null;
218
+ return !!container && this._editor.el.contains(container);
219
+ }
220
+ // Turn every {{value.key}} token in the editor's text into a chip. For a
221
+ // paste, a token only stays when it was copied on this page and the page has
222
+ // the value; otherwise it goes, and just the text around it is pasted.
223
+ _toChips(pasted = false) {
224
+ const el = this._editor?.el;
225
+ if (!el) {
226
+ return;
227
+ }
228
+ const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
229
+ const texts = [];
230
+ while (walker.nextNode()) {
231
+ const text = walker.currentNode;
232
+ if (text.data.includes('{{') && !text.parentElement?.closest(CHIP_SELECTOR)) {
233
+ texts.push(text);
234
+ }
235
+ }
236
+ texts.forEach((text) => this._splitText(text, pasted));
237
+ }
238
+ _keepsPasted(key) {
239
+ return this._pasteScope === this.config.scope() && !!this.config.values()[key];
240
+ }
241
+ _splitText(text, pasted) {
242
+ const matches = Array.from(text.data.matchAll(VALUE_TOKEN_PATTERN));
243
+ if (!matches.length) {
244
+ return;
245
+ }
246
+ // Only non-empty text around the chips, so a selection counted in child
247
+ // nodes keeps its place.
248
+ const fragment = document.createDocumentFragment();
249
+ const appendText = (value) => {
250
+ if (value) {
251
+ fragment.append(value);
252
+ }
253
+ };
254
+ let consumed = 0;
255
+ matches.forEach((match) => {
256
+ const key = match[1].toLowerCase();
257
+ appendText(text.data.slice(consumed, match.index));
258
+ if (!pasted || this._keepsPasted(key)) {
259
+ fragment.append(this._createChip(key));
260
+ }
261
+ consumed = match.index + match[0].length;
262
+ });
263
+ appendText(text.data.slice(consumed));
264
+ text.replaceWith(fragment);
265
+ }
266
+ // Every chip in the editor back to its token, as text.
267
+ _toTokenText() {
268
+ this._chips().forEach((chip) => chip.replaceWith(valueToken(chip.getAttribute(KEY_ATTRIBUTE))));
269
+ }
270
+ _createChip(key) {
271
+ const chip = document.createElement('span');
272
+ chip.setAttribute(TYPE_ATTRIBUTE, VALUE_TYPE);
273
+ chip.setAttribute(KEY_ATTRIBUTE, key);
274
+ chip.setAttribute('contenteditable', 'false');
275
+ this._label(chip);
276
+ return chip;
277
+ }
278
+ // A chip reads as the value does in the viewed block — its number, the
279
+ // ellipsis while that loads, else the em dash — so opening the editor moves
280
+ // no word; or as its name, when names are toggled on. A key with no value on
281
+ // the page reads as the key itself, marked missing.
282
+ _label(chip) {
283
+ const key = chip.getAttribute(KEY_ATTRIBUTE);
284
+ const value = this.config.values()[key];
285
+ chip.textContent = !value
286
+ ? key
287
+ : this.config.showNames() ? value.name : valueText(value);
288
+ chip.title = value?.name ?? key;
289
+ chip.toggleAttribute(MISSING_ATTRIBUTE, !value);
290
+ }
291
+ // The html Froala hands out, with every chip back to its token.
292
+ _toTokens(html) {
293
+ if (!html.includes(KEY_ATTRIBUTE)) {
294
+ return html;
295
+ }
296
+ const template = document.createElement('template');
297
+ template.innerHTML = html;
298
+ template.content.querySelectorAll(CHIP_SELECTOR).forEach((chip) => {
299
+ chip.replaceWith(valueToken(chip.getAttribute(KEY_ATTRIBUTE)));
300
+ });
301
+ return template.innerHTML;
302
+ }
303
+ _onKeydown(event) {
304
+ // Any key but a lone modifier starts a new edit.
305
+ if (!MODIFIER_KEYS.includes(event.key)) {
306
+ this.config.changed();
307
+ }
308
+ const deleting = event.key === 'Backspace' || event.key === 'Delete';
309
+ // Deleting across several selected cells goes through, values and all:
310
+ // Froala saves an undo step and empties the cells, and what that took is
311
+ // reported once they are empty.
312
+ if (deleting && this._editor.el.querySelectorAll(SELECTED_CELL).length > 1) {
313
+ const before = this._chipCounts();
314
+ setTimeout(() => this._reportRemoved(before));
315
+ return undefined;
316
+ }
317
+ const range = this._range();
318
+ if (!range) {
319
+ return;
320
+ }
321
+ if (range.collapsed) {
322
+ if (!deleting) {
323
+ return;
324
+ }
325
+ const chip = this._adjacentChip(event.key === 'Backspace', this._granularity(event));
326
+ return chip ? this._block(event, [chip], null) : undefined;
327
+ }
328
+ // A selection is replaced by a deleting key, Enter, a typed character or
329
+ // a cut.
330
+ const typing = event.key.length === 1 && !event.ctrlKey && !event.metaKey;
331
+ const cutting = (event.ctrlKey || event.metaKey) && event.key.toLowerCase() === 'x';
332
+ if (!deleting && !typing && !cutting && event.key !== 'Enter') {
333
+ return;
334
+ }
335
+ const chips = this._chipsIn(range);
336
+ return chips.length ? this._block(event, chips, range) : undefined;
337
+ }
338
+ // The same rule for edits that arrive without a key Froala sees: a phone
339
+ // keyboard, an input method, a spell-check replacement.
340
+ _onBeforeInput(event) {
341
+ const range = this._range();
342
+ if (this._removing || !range) {
343
+ return;
344
+ }
345
+ if (range.collapsed) {
346
+ const backward = event.inputType.endsWith('Backward');
347
+ if (event.inputType.startsWith('delete')) {
348
+ const chip = this._adjacentChip(backward, event.inputType.includes('Word') ? 'word' : 'character');
349
+ if (chip) {
350
+ this._block(event, [chip], null);
351
+ }
352
+ }
353
+ return;
354
+ }
355
+ const chips = this._chipsIn(range);
356
+ if (chips.length) {
357
+ this._block(event, chips, range);
358
+ }
359
+ }
360
+ // Cut, drag and paste-over: stopped when the selection holds a value.
361
+ _guardSelection(event) {
362
+ const range = this._range();
363
+ if (this._removing || !range || range.collapsed) {
364
+ return;
365
+ }
366
+ const chips = this._chipsIn(range);
367
+ return chips.length ? this._block(event, chips, range) : undefined;
368
+ }
369
+ // Copying a value copies its token, and the page it was copied on, so
370
+ // pasting it back on this page — in this block or another — makes it a chip
371
+ // again.
372
+ _onCopy(event) {
373
+ const range = this._range();
374
+ if (!range || range.collapsed || !this._chipsIn(range).length) {
375
+ return;
376
+ }
377
+ const holder = document.createElement('div');
378
+ holder.append(range.cloneContents());
379
+ holder.querySelectorAll(CHIP_SELECTOR).forEach((chip) => {
380
+ chip.replaceWith(valueToken(chip.getAttribute(KEY_ATTRIBUTE)));
381
+ });
382
+ event.clipboardData.setData('text/plain', this._plainText(holder));
383
+ event.clipboardData.setData('text/html', holder.innerHTML);
384
+ event.clipboardData.setData(SCOPE_TYPE, this.config.scope());
385
+ event.preventDefault();
386
+ }
387
+ // What copied html reads as in plain text: a paragraph on its own lines, a
388
+ // table's cells tab-separated and its rows on lines of their own. That is
389
+ // the browser's innerText, which only text laid out on the page has — so
390
+ // the holder is put offscreen (not hidden: hidden text has none) while it is
391
+ // read.
392
+ _plainText(holder) {
393
+ holder.style.cssText = 'position: fixed; left: -10000px; top: 0';
394
+ document.body.append(holder);
395
+ const text = holder.innerText;
396
+ holder.remove();
397
+ return text;
398
+ }
399
+ _onClick(event) {
400
+ const chip = event.target?.closest?.(CHIP_SELECTOR);
401
+ if (!chip || !this._editor?.el.contains(chip)) {
402
+ return;
403
+ }
404
+ event.preventDefault();
405
+ // A press in a table cell can open the table's popup on mouseup, just
406
+ // before this click; a chip in a cell shows only its own popover.
407
+ this._editor.popups.hide('table.edit');
408
+ this.config.click(chip.getAttribute(KEY_ATTRIBUTE), chip);
409
+ }
410
+ _onChip(event) {
411
+ return !!event?.target?.closest?.(CHIP_SELECTOR);
412
+ }
413
+ _block(event, chips, range) {
414
+ event.preventDefault();
415
+ event.stopPropagation();
416
+ chips.forEach((chip) => chip.animate(FLASH, FLASH_MS));
417
+ this.config.blocked({
418
+ count: chips.length,
419
+ ...(range ? { removeSelection: () => this._removeRange(range) } : {}),
420
+ });
421
+ return false;
422
+ }
423
+ _removeRange(range) {
424
+ if (!this._editor) {
425
+ return;
426
+ }
427
+ const selection = this._selection();
428
+ this._editor.el.focus();
429
+ selection.removeAllRanges();
430
+ selection.addRange(range);
431
+ this._editor.undo.saveStep();
432
+ this._removing = true;
433
+ // The browser's own delete, so two paragraphs a selection spans join the
434
+ // way they would for a plain Delete.
435
+ document.execCommand('delete');
436
+ this._removing = false;
437
+ this._changed();
438
+ }
439
+ // An edit made here rather than typed: record it for undo, and tell
440
+ // html-editor so the draft follows.
441
+ _changed() {
442
+ this._editor.undo.saveStep();
443
+ this._editor.events.trigger('contentChanged');
444
+ }
445
+ _selection() {
446
+ return this._editor.el.ownerDocument.getSelection();
447
+ }
448
+ // The selection, when it is inside this editor.
449
+ _range() {
450
+ const selection = this._editor ? this._selection() : null;
451
+ if (!selection?.rangeCount) {
452
+ return null;
453
+ }
454
+ const range = selection.getRangeAt(0);
455
+ return this._editor.el.contains(range.commonAncestorContainer) ? range : null;
456
+ }
457
+ _chipsIn(range) {
458
+ return this._chips().filter((chip) => range.intersectsNode(chip));
459
+ }
460
+ // The chip a collapsed cursor would delete into: stretch the selection by
461
+ // what the key deletes, see what it covers, and put it back. Letting the
462
+ // browser stretch it handles every shape the html takes — a chip inside a
463
+ // bold span, at a line's end, beside an empty text node.
464
+ _adjacentChip(backward, granularity) {
465
+ const selection = this._selection();
466
+ const range = selection.getRangeAt(0).cloneRange();
467
+ selection.modify('extend', backward ? 'backward' : 'forward', granularity);
468
+ const chip = selection.rangeCount
469
+ ? this._chipsIn(selection.getRangeAt(0))[0] ?? null
470
+ : null;
471
+ selection.removeAllRanges();
472
+ selection.addRange(range);
473
+ return chip;
474
+ }
475
+ // How far a deleting key reaches: a word with Ctrl/Alt, to the line's start
476
+ // with Cmd on a Mac, one character otherwise.
477
+ _granularity(event) {
478
+ if (event.metaKey) {
479
+ return 'lineboundary';
480
+ }
481
+ return event.ctrlKey || event.altKey ? 'word' : 'character';
482
+ }
483
+ }
484
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsdWUtZW1iZWQucGx1Z2luLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL2NvbXBvbmVudHMvY29tcG9uZW50LXRleHQvdmFsdWUtZW1iZWQucGx1Z2luLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxNQUFNLEVBQWdCLE1BQU0seUJBQXlCLENBQUM7QUFFL0QsT0FBTyxFQUFhLG1CQUFtQixFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFHbkYsMkVBQTJFO0FBQzNFLGdGQUFnRjtBQUNoRixnRkFBZ0Y7QUFDaEYsc0VBQXNFO0FBQ3RFLE1BQU0sY0FBYyxHQUFHLGlCQUFpQixDQUFDO0FBQ3pDLE1BQU0sYUFBYSxHQUFHLGdCQUFnQixDQUFDO0FBQ3ZDLE1BQU0saUJBQWlCLEdBQUcsb0JBQW9CLENBQUM7QUFDL0MsTUFBTSxhQUFhLEdBQUcsSUFBSSxhQUFhLEdBQUcsQ0FBQztBQUMzQyxNQUFNLFVBQVUsR0FBRyxPQUFPLENBQUM7QUFFM0IsNkVBQTZFO0FBQzdFLDBFQUEwRTtBQUMxRSxNQUFNLFVBQVUsR0FBRyxxQ0FBcUMsQ0FBQztBQUV6RCxvRUFBb0U7QUFDcEUsTUFBTSxDQUFDLE1BQU0sc0JBQXNCLEdBQUcsQ0FBQyxjQUFjLEVBQUUsYUFBYSxFQUFFLGlCQUFpQixFQUFFLGlCQUFpQixDQUFDLENBQUM7QUFFNUcsd0RBQXdEO0FBQ3hELE1BQU0sS0FBSyxHQUFlLENBQUMsRUFBRSxTQUFTLEVBQUUsbUJBQW1CLEVBQUUsRUFBRSxFQUFFLFNBQVMsRUFBRSx1QkFBdUIsRUFBRSxDQUFDLENBQUM7QUFDdkcsTUFBTSxRQUFRLEdBQUcsR0FBRyxDQUFDO0FBRXJCLCtFQUErRTtBQUMvRSwyRUFBMkU7QUFDM0UsTUFBTSxxQkFBcUIsR0FBRyxDQUFDLGFBQWEsRUFBRSxhQUFhLENBQUMsQ0FBQztBQUM3RCxNQUFNLGVB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USxFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxTQUFTLEVBQUUsV0FBVyxDQUFDLENBQUM7UUFDM0UsTUFBTSxJQUFJLEdBQUcsU0FBUyxDQUFDLFVBQVU7WUFDL0IsQ0FBQyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLElBQUk7WUFDbkQsQ0FBQyxDQUFDLElBQUksQ0FBQztRQUVULFNBQVMsQ0FBQyxlQUFlLEVBQUUsQ0FBQztRQUM1QixTQUFTLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBRTFCLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVELDRFQUE0RTtJQUM1RSw4Q0FBOEM7SUFDdEMsWUFBWSxDQUFDLEtBQW9CO1FBQ3ZDLElBQUksS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2xCLE9BQU8sY0FBYyxDQUFDO1FBQ3hCLENBQUM7UUFFRCxPQUFPLEtBQUssQ0FBQyxPQUFPLElBQUksS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUM7SUFDOUQsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgUGx1Z2luLCBQbHVnaW5Db25maWcgfSBmcm9tICdAZmlyZXN0aXRjaC9odG1sLWVkaXRvcic7XG5cbmltcG9ydCB7IFRleHRWYWx1ZSwgVkFMVUVfVE9LRU5fUEFUVEVSTiwgdmFsdWVUZXh0LCB2YWx1ZVRva2VuIH0gZnJvbSAnLi4vLi4vdGV4dCc7XG5cblxuLy8gSG93IGEgdmFsdWUgY2hpcCBpcyBtYXJrZWQgaW4gdGhlIGVkaXRvci4gVGhlIG5hbWVzIGZvbGxvdyB0aGUgZW1iZWRzIG9mXG4vLyBAZmlyZXN0aXRjaC9tYXJrZG93bi1lZGl0b3IuIEF0dHJpYnV0ZXMgcmF0aGVyIHRoYW4gYSBjbGFzczogdGhlIHJlcG9ydCBrZWVwc1xuLy8gRnJvYWxhIG9uIGlubGluZSBzdHlsZXMgKHVzZUNsYXNzZXM6IGZhbHNlKSwgYW5kIGEgY2hpcCBuZXZlciByZWFjaGVzIHN0b3JhZ2Vcbi8vIGFueXdheSDigJQgaXQgdHVybnMgYmFjayBpbnRvIGl0cyB7e3ZhbHVlLmtleX19IHRva2VuIG9uIHRoZSB3YXkgb3V0LlxuY29uc3QgVFlQRV9BVFRSSUJVVEUgPSAnZGF0YS1lbWJlZC10eXBlJztcbmNvbnN0IEtFWV9BVFRSSUJVVEUgPSAnZGF0YS1lbWJlZC1rZXknO1xuY29uc3QgTUlTU0lOR19BVFRSSUJVVEUgPSAnZGF0YS1lbWJlZC1taXNzaW5nJztcbmNvbnN0IENISVBfU0VMRUNUT1IgPSBgWyR7S0VZX0FUVFJJQlVURX1dYDtcbmNvbnN0IFZBTFVFX1RZUEUgPSAndmFsdWUnO1xuXG4vLyBUaGUgcGFnZSBhIGNvcHkgY2FtZSBmcm9tLCBvbiB0aGUgY2xpcGJvYXJkIGJlc2lkZSBpdHMgdGV4dDogdmFsdWVzIGJlbG9uZ1xuLy8gdG8gdGhlaXIgcGFnZSwgc28gYSB2YWx1ZSBwYXN0ZWQgb250byBhbm90aGVyIG9uZSBkb2Vzbid0IGNvbWUgd2l0aCBpdC5cbmNvbnN0IFNDT1BFX1RZUEUgPSAnYXBwbGljYXRpb24veC1mcy1yZXBvcnQtdmFsdWUtc2NvcGUnO1xuXG4vLyBXaGF0IEZyb2FsYSBtdXN0IGtlZXAgb24gYSBjaGlwIHdoZW4gaXQgY2xlYW5zIGh0bWwgaXQgaXMgaGFuZGVkLlxuZXhwb3J0IGNvbnN0IFZBTFVFX0VNQkVEX0FUVFJJQlVURVMgPSBbVFlQRV9BVFRSSUJVVEUsIEtFWV9BVFRSSUJVVEUsIE1JU1NJTkdfQVRUUklCVVRFLCAnY29udGVudGVkaXRhYmxlJ107XG5cbi8vIEEgYnJpZWYgcmluZyBhcm91bmQgdGhlIGNoaXBzIGFuIGVkaXQgd2FzIHN0b3BwZWQgYXQuXG5jb25zdCBGTEFTSDogS2V5ZnJhbWVbXSA9IFt7IGJveFNoYWRvdzogJzAgMCAwIDJweCAjZTE1NzU5JyB9LCB7IGJveFNoYWRvdzogJzAgMCAwIDJweCB0cmFuc3BhcmVudCcgfV07XG5jb25zdCBGTEFTSF9NUyA9IDcwMDtcblxuLy8gQ29tbWFuZHMgdGhhdCB3b3VsZCBidWlsZCB3aGF0IHRoZSBzZXJ2ZXIgcmV3cml0ZXMgKFJlcG9ydFRleHRIdG1sKTogYSB0YWJsZVxuLy8gaXMga2VwdCBvbmx5IGJldHdlZW4gcGFyYWdyYXBocywgYW5kIGEgY2VsbCBob2xkcyB3b3JkcyBhbmQgdmFsdWVzIG9ubHkuXG5jb25zdCBUQUJMRV9JTlNFUlRfQ09NTUFORFMgPSBbJ2luc2VydFRhYmxlJywgJ3RhYmxlSW5zZXJ0J107XG5jb25zdCBOT19UQUJMRV9JTlNJREUgPSAnbGksIHRkLCB0aCc7XG5jb25zdCBDRUxMX0NPTU1BTkRTID0gWydmb3JtYXRVTCcsICdmb3JtYXRPTCcsICdwYXJhZ3JhcGhGb3JtYXQnXTtcbmNvbnN0IENFTEwgPSAndGQsIHRoJztcblxuLy8gVW5kbyBhbmQgcmVkbyByZXN0b3JlIGEgc3RlcDsgdGhleSByZW1vdmUgbm90aGluZyBvZiB0aGVpciBvd24uXG5jb25zdCBISVNUT1JZX0NPTU1BTkRTID0gWyd1bmRvJywgJ3JlZG8nXTtcblxuLy8gS2V5cyB0aGF0LCBwcmVzc2VkIGFsb25lLCBlZGl0IG5vdGhpbmcuXG5jb25zdCBNT0RJRklFUl9LRVlTID0gWydTaGlmdCcsICdDb250cm9sJywgJ0FsdCcsICdBbHRHcmFwaCcsICdNZXRhJ107XG5cbi8vIFRoZSBjZWxscyBvZiBhIHRhYmxlIHNlbGVjdGVkIGFzIGNlbGxzIChGcm9hbGEncyBvd24gbWFya2luZykuXG5jb25zdCBTRUxFQ1RFRF9DRUxMID0gJy5mci1zZWxlY3RlZC1jZWxsJztcblxuLy8gQW4gZWRpdCB0aGF0IHdvdWxkIGhhdmUgcmVtb3ZlZCB2YWx1ZXMsIGFuZCB3YXMgc3RvcHBlZC5cbmV4cG9ydCBpbnRlcmZhY2UgVmFsdWVFbWJlZEJsb2NrIHtcbiAgY291bnQ6IG51bWJlcjtcbiAgLy8gUHJlc2VudCB3aGVuIHRoZSBlZGl0IHdhcyBvbiBhIHNlbGVjdGlvbjogcmVtb3ZlcyB0aGUgc2VsZWN0aW9uLCB2YWx1ZXNcbiAgLy8gYW5kIGFsbCDigJQgdGhlIGRlbGliZXJhdGUgd2F5IHRocm91Z2guXG4gIHJlbW92ZVNlbGVjdGlvbj86ICgpID0+IHZvaWQ7XG59XG5cbi8vIEFuIGVkaXQgdGhhdCB0b29rIHRoZSBsYXN0IGNoaXAgb2Ygc29tZSB2YWx1ZXMgb3V0IG9mIHRoZSBibG9jazogZGVsZXRpbmdcbi8vIGEgcm93LCBhIGNvbHVtbiBvciBhIHRhYmxlLCBvciBlbXB0eWluZyBjZWxscy4gQWxsb3dlZCwgdmFsdWVzIGFuZCBhbGwuXG5leHBvcnQgaW50ZXJmYWNlIFZhbHVlRW1iZWRSZW1vdmFsIHtcbiAgLy8gVGhlIGtleXMgdGhlIGJsb2NrJ3MgY2hpcHMgbmFtZWQgYmVmb3JlIHRoZSBlZGl0LCBhbmQgYWZ0ZXIgaXQuXG4gIGJlZm9yZTogc3RyaW5nW107XG4gIGFmdGVyOiBzdHJpbmdbXTtcbiAgLy8gVGhlIGVkaXRvcidzIG93biB1bmRvLCB3aGljaCBicmluZ3MgdGhlIGNoaXBzIGJhY2suXG4gIHVuZG86ICgpID0+IHZvaWQ7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVmFsdWVFbWJlZFBsdWdpbkNvbmZpZyBleHRlbmRzIFBsdWdpbkNvbmZpZyB7XG4gIC8vIFRoZSBlbGVtZW50IHRoZSBlZGl0b3Igc2l0cyBpbi4gaHRtbC1lZGl0b3IgcmVnaXN0ZXJzIGEgcGx1Z2luIHdpdGggRnJvYWxhXG4gIC8vIGdsb2JhbGx5LCBzbyBGcm9hbGEgaGFuZHMgaXQgZXZlcnkgZWRpdG9yIGJ1aWx0IGFmdGVyd2FyZHM7IGl0IHdvcmtzIG9ubHlcbiAgLy8gZm9yIHRoZSBvbmUgaW5zaWRlIHRoaXMgZWxlbWVudC5cbiAgaG9zdDogKCkgPT4gSFRNTEVsZW1lbnQ7XG4gIC8vIFRoZSBwYWdlJ3MgdmFsdWVzLCBieSBrZXkuIE9uZSB3aG9zZSBudW1iZXIgaXMgc3RpbGwgb24gaXRzIHdheSBpcyBsaXN0ZWRcbiAgLy8gd2l0aCBsb2FkaW5nOiB0cnVlOyBhIGtleSBub3QgbGlzdGVkIGlzIG5vIHZhbHVlIG9mIHRoZSBwYWdlLlxuICB2YWx1ZXM6ICgpID0+IFJlY29yZDxzdHJpbmcsIFRleHRWYWx1ZT47XG4gIC8vIFRoZSBwYWdlIHRoZSBibG9jaydzIHZhbHVlcyBiZWxvbmcgdG8uXG4gIHNjb3BlOiAoKSA9PiBzdHJpbmc7XG4gIC8vIExhYmVsIGNoaXBzIHdpdGggdGhlIHZhbHVlJ3MgbmFtZSBpbnN0ZWFkIG9mIGl0cyBudW1iZXIuXG4gIHNob3dOYW1lczogKCkgPT4gYm9vbGVhbjtcbiAgY2xpY2s6IChrZXk6IHN0cmluZywgY2hpcDogSFRNTEVsZW1lbnQpID0+IHZvaWQ7XG4gIGJsb2NrZWQ6IChibG9jazogVmFsdWVFbWJlZEJsb2NrKSA9PiB2b2lkO1xuICByZW1vdmVkOiAocmVtb3ZhbDogVmFsdWVFbWJlZFJlbW92YWwpID0+IHZvaWQ7XG4gIC8vIEEga2V5IHdhcyBwcmVzc2VkIG9yIGEgY29tbWFuZCBpcyBhYm91dCB0byBydW46IHdoYXQgd2FzIHNhaWQgYWJvdXQgdGhlXG4gIC8vIGxhc3QgZWRpdCBubyBsb25nZXIgYXBwbGllcy5cbiAgY2hhbmdlZDogKCkgPT4gdm9pZDtcbiAgLy8gQSBjb21tYW5kIHdhcyByZWZ1c2VkLCBhbmQgd2h5LlxuICByZWZ1c2VkOiAodGV4dDogc3RyaW5nKSA9PiB2b2lkO1xufVxuXG4vLyBMaXZlIHZhbHVlcyBpbnNpZGUgYSB0ZXh0IGJsb2NrJ3MgZWRpdG9yLlxuLy9cbi8vIFN0b3JlZCBodG1sIGNhcnJpZXMgYSB2YWx1ZSBhcyBhIHt7dmFsdWUua2V5fX0gdG9rZW4uIFdoaWxlIGVkaXRpbmcsIGVhY2hcbi8vIHRva2VuIGlzIGEgY2hpcDogb25lIGNoYXJhY3RlciB0byB0aGUgY3Vyc29yLCBsYWJlbGVkIHdpdGggdGhlIHZhbHVlLCBhbmRcbi8vIHJlcG9ydGluZyBhIGNsaWNrLiBGcm9hbGEncyBodG1sLmdldCBoYW5kcyBiYWNrIHRva2VucyBhZ2Fpbiwgc28gdGhlIGRyYWZ0XG4vLyBhbmQgdGhlIHNhdmVkIGh0bWwgbmV2ZXIgaG9sZCBhIGNoaXAuXG4vL1xuLy8gQSBjaGlwIGNhbid0IGJlIGRlbGV0ZWQgYnkgZWRpdGluZzogQmFja3NwYWNlIG9yIERlbGV0ZSBiZXNpZGUgaXQsIGFuZCBhbnlcbi8vIGRlbGV0aW5nLCB0eXBpbmcgb3ZlciwgY3V0dGluZywgcGFzdGluZyBvdmVyIG9yIGRyYWdnaW5nIG9mIGEgc2VsZWN0aW9uIHRoYXRcbi8vIGhvbGRzIG9uZSwgaXMgc3RvcHBlZCBhbmQgcmVwb3J0ZWQuIEl0IGlzIHRha2VuIG91dCBvbiBwdXJwb3NlIGJ5IHNlbGVjdGluZ1xuLy8gaXQgYW5kIHByZXNzaW5nIERlbGV0ZSwgdGhlbiB0YWtpbmcgdGhlIHN0b3BwZWQgc2VsZWN0aW9uJ3Ncbi8vIHJlbW92ZVNlbGVjdGlvbigpOyBhIHZhbHVlIHRoYXQgd2FzIGRlbGV0ZWQgbGVhdmVzIHRocm91Z2ggcmVtb3ZlS2V5KCkuXG4vL1xuLy8gQSB0YWJsZSBpcyB0aGUgZXhjZXB0aW9uOiBkZWxldGluZyBhIHJvdywgYSBjb2x1bW4gb3IgdGhlIHRhYmxlLCBvclxuLy8gZW1wdHlpbmcgc2V2ZXJhbCBzZWxlY3RlZCBjZWxscywgZ29lcyB0aHJvdWdoIHdpdGggdGhlIGNoaXBzIGluIGl0LCBhbmQgaXNcbi8vIHJlcG9ydGVkIGFzIHJlbW92ZWQoKSB3aGVuIGl0IHRvb2sgYSB2YWx1ZSdzIGxhc3QgY2hpcCwgd2l0aCB0aGUgdW5kbyB0aGF0XG4vLyBicmluZ3MgdGhlbSBiYWNrLlxuZXhwb3J0IGNsYXNzIFZhbHVlRW1iZWRQbHVnaW4gZXh0ZW5kcyBQbHVnaW4ge1xuXG4gIC8vIFRoZSBiYXNlIGNsYXNzJ3MgY29uZmlnLCB0eXBlZCBmb3IgdGhpcyBwbHVnaW4uXG4gIHB1YmxpYyBkZWNsYXJlIGNvbmZpZzogVmFsdWVFbWJlZFBsdWdpbkNvbmZpZztcblxuICAvLyBUaGUgZWRpdG9yIHRoaXMgcGx1Z2luIHNlcnZlczsgbnVsbCB1bnRpbCBpdCBpcyBidWlsdCwgYW5kIGFmdGVyIGl0IGlzIGdvbmUuXG4gIHByaXZhdGUgX2VkaXRvcjogYW55ID0gbnVsbDtcbiAgLy8gU2V0IHdoaWxlIGEgZGVsaWJlcmF0ZSByZW1vdmFsIHJ1bnMsIHNvIHRoZSBndWFyZHMgbGV0IGl0IHRocm91Z2guXG4gIHByaXZhdGUgX3JlbW92aW5nID0gZmFsc2U7XG4gIC8vIExpc3RlbmVycyBvbiB0aGUgZWRpdGFibGUgZWxlbWVudCwgY2FwdHVyZWQgc28gZWFjaCBydW5zIGJlZm9yZSBGcm9hbGEnc1xuICAvLyBvd24gaGFuZGxlciBmb3IgdGhlIHNhbWUgZXZlbnQuXG4gIHByaXZhdGUgX2RvbUxpc3RlbmVyczogW3N0cmluZywgRXZlbnRMaXN0ZW5lcl1bXSA9IFtdO1xuICAvLyBUaGUgcGFnZSB0aGUgcGFzdGUgdW5kZXIgd2F5IHdhcyBjb3BpZWQgb24gKCcnIHdoZW4gbm90IGZyb20gYSBibG9jaykuXG4gIHByaXZhdGUgX3Bhc3RlU2NvcGUgPSAnJztcbiAgLy8gSG93IG1hbnkgY2hpcHMgZWFjaCBrZXkgaGFkIGFzIHRoZSBjb21tYW5kIHVuZGVyIHdheSBzdGFydGVkOyBudWxsIGZvclxuICAvLyBvbmUgdGhhdCByZW1vdmVzIG5vdGhpbmcgb2YgaXRzIG93biAodW5kbywgcmVkbykuXG4gIHByaXZhdGUgX2JlZm9yZTogTWFwPHN0cmluZywgbnVtYmVyPiB8IG51bGwgPSBudWxsO1xuXG4gIGNvbnN0cnVjdG9yKGNvbmZpZzogVmFsdWVFbWJlZFBsdWdpbkNvbmZpZykge1xuICAgIHN1cGVyKCk7XG4gICAgdGhpcy5jb25maWcgPSBjb25maWc7XG4gIH1cblxuICBwdWJsaWMgaW5pdGlhbGl6ZSgpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuY29uZmlnLmhvc3QoKS5jb250YWlucyh0aGlzLmVkaXRvci5lbCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBlZGl0b3IgPSB0aGlzLmVkaXRvcjtcbiAgICBjb25zdCBlbDogSFRNTEVsZW1lbnQgPSBlZGl0b3IuZWw7XG4gICAgdGhpcy5fZWRpdG9yID0gZWRpdG9yO1xuXG4gICAgZWRpdG9yLmV2ZW50cy5vbignaHRtbC5zZXQnLCAoKSA9PiB0aGlzLl90b0NoaXBzKCkpO1xuICAgIGVkaXRvci5ldmVudHMub24oJ3Bhc3RlLmFmdGVyJywgKCkgPT4gdGhpcy5fdG9DaGlwcyh0cnVlKSk7XG4gICAgdGhpcy5fd2F0Y2hDb21tYW5kcyhlZGl0b3IpO1xuICAgIGVkaXRvci5ldmVudHMub24oJ2h0bWwuZ2V0JywgKGh0bWw6IHN0cmluZykgPT4gdGhpcy5fdG9Ub2tlbnMoaHRtbCkpO1xuICAgIC8vIEZpcnN0IGluIEZyb2FsYSdzIGNoYWluLCBzbyBpdHMgb3duIEJhY2tzcGFjZSBoYW5kbGluZyBuZXZlciBydW5zIG9uIGFcbiAgICAvLyBzdG9wcGVkIGtleS5cbiAgICBlZGl0b3IuZXZlbnRzLm9uKCdrZXlkb3duJywgKGV2ZW50OiBLZXlib2FyZEV2ZW50KSA9PiB0aGlzLl9vbktleWRvd24oZXZlbnQpLCB0cnVlKTtcbiAgICBlZGl0b3IuZXZlbnRzLm9uKCdwYXN0ZS5iZWZvcmUnLCAoZXZlbnQ6IENsaXBib2FyZEV2ZW50KSA9PiB7XG4gICAgICB0aGlzLl9wYXN0ZVNjb3BlID0gZXZlbnQ/LmNsaXBib2FyZERhdGE/LmdldERhdGEoU0NPUEVfVFlQRSkgPz8gJyc7XG5cbiAgICAgIHJldHVybiB0aGlzLl9ndWFyZFNlbGVjdGlvbihldmVudCk7XG4gICAgfSk7XG4gICAgLy8gQSBwcmVzcyBvbiBhIGNoaXAgb3BlbnMgaXRzIHBvcG92ZXI7IEZyb2FsYSdzIGZsb2F0aW5nIHRvb2xiYXIsIHdoaWNoXG4gICAgLy8gcG9wcyB1cCBvbiBhbnkgcHJlc3MgaW4gdGhlIHRleHQgYW5kIHNpdHMgYWJvdmUgZXZlcnkgb3ZlcmxheSwgc3RheXNcbiAgICAvLyBhd2F5IGZvciBpdC5cbiAgICBlZGl0b3IuZXZlbnRzLm9uKCd0b29sYmFyLnNob3cnLCAoZXZlbnQ/OiBFdmVudCkgPT4gKHRoaXMuX29uQ2hpcChldmVudCkgPyBmYWxzZSA6IHVuZGVmaW5lZCksIHRydWUpO1xuICAgIC8vIE9ubHkgd2hpbGUgaXQgaXMgc3RpbGwgdGhpcyBlZGl0b3I6IHJlb3BlbmluZyBhIGJsb2NrIGJ1aWxkcyB0aGUgbmV4dFxuICAgIC8vIG9uZSBiZWZvcmUgdGhlIGxhc3QgaXMgdG9ybiBkb3duLlxuICAgIGVkaXRvci5ldmVudHMub24oJ2Rlc3Ryb3knLCAoKSA9PiB7XG4gICAgICBpZiAodGhpcy5fZWRpdG9yID09PSBlZGl0b3IpIHtcbiAgICAgICAgdGhpcy5kZXN0cm95KCk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICB0aGlzLl9kb21MaXN0ZW5lcnMgPSBbXG4gICAgICBbJ2JlZm9yZWlucHV0JywgKGV2ZW50KSA9PiB0aGlzLl9vbkJlZm9yZUlucHV0KGV2ZW50IGFzIElucHV0RXZlbnQpXSxcbiAgICAgIFsnY3V0JywgKGV2ZW50KSA9PiB0aGlzLl9ndWFyZFNlbGVjdGlvbihldmVudCldLFxuICAgICAgWydkcmFnc3RhcnQnLCAoZXZlbnQpID0+IHRoaXMuX2d1YXJkU2VsZWN0aW9uKGV2ZW50KV0sXG4gICAgICBbJ2NvcHknLCAoZXZlbnQpID0+IHRoaXMuX29uQ29weShldmVudCBhcyBDbGlwYm9hcmRFdmVudCldLFxuICAgICAgWydjbGljaycsIChldmVudCkgPT4gdGhpcy5fb25DbGljayhldmVudCBhcyBNb3VzZUV2ZW50KV0sXG4gICAgXTtcbiAgICB0aGlzLl9kb21MaXN0ZW5lcnMuZm9yRWFjaCgoW25hbWUsIGxpc3RlbmVyXSkgPT4gZWwuYWRkRXZlbnRMaXN0ZW5lcihuYW1lLCBsaXN0ZW5lciwgdHJ1ZSkpO1xuXG4gICAgdGhpcy5fdG9DaGlwcygpO1xuICB9XG5cbiAgcHVibGljIGRlc3Ryb3koKTogdm9pZCB7XG4gICAgY29uc3QgZWw6IEhUTUxFbGVtZW50IHwgdW5kZWZpbmVkID0gdGhpcy5fZWRpdG9yPy5lbDtcbiAgICB0aGlzLl9kb21MaXN0ZW5lcnMuZm9yRWFjaCgoW25hbWUsIGxpc3RlbmVyXSkgPT4gZWw/LnJlbW92ZUV2ZW50TGlzdGVuZXIobmFtZSwgbGlzdGVuZXIsIHRydWUpKTtcbiAgICB0aGlzLl9kb21MaXN0ZW5lcnMgPSBbXTtcbiAgICB0aGlzLl9lZGl0b3IgPSBudWxsO1xuICB9XG5cbiAgLy8gUmVsYWJlbCBldmVyeSBjaGlwOiB0aGUgdmFsdWVzIGFycml2ZWQgb3IgY2hhbmdlZCwgb3IgbmFtZXMgd2VyZSB0b2dnbGVkLlxuICBwdWJsaWMgcmVmcmVzaCgpOiB2b2lkIHtcbiAgICB0aGlzLl9jaGlwcygpLmZvckVhY2goKGNoaXApID0+IHRoaXMuX2xhYmVsKGNoaXApKTtcbiAgfVxuXG4gIC8vIFB1dCBGcm9hbGEncyBmbG9hdGluZyB0b29sYmFyIGFuZCBhIHRhYmxlJ3MgcG9wdXAgYXdheSwgd2hlbiBlaXRoZXIgaXNcbiAgLy8gYWxyZWFkeSB1cCBhcyBhIGNoaXAncyBwb3BvdmVyIG9wZW5zOiB0aGV5IHNpdCBhYm92ZSBldmVyeSBvdmVybGF5LlxuICBwdWJsaWMgaGlkZVRvb2xiYXIoKTogdm9pZCB7XG4gICAgdGhpcy5fZWRpdG9yPy50b29sYmFyLmhpZGUoKTtcbiAgICB0aGlzLl9lZGl0b3I/LnBvcHVwcy5oaWRlKCd0YWJsZS5lZGl0Jyk7XG4gIH1cblxuICAvLyBUaGUgZWRpdG9yJ3Mgb3duIHVuZG8gb2YgdGhlIGxhc3Qgc3RlcDogd2hhdCBwdXRzIGJhY2sgdGhlIGNoaXBzIGFuIGVkaXRcbiAgLy8gdG9vayBvdXQuXG4gIHB1YmxpYyB1bmRvKCk6IHZvaWQge1xuICAgIHRoaXMuX2VkaXRvcj8uY29tbWFuZHMudW5kbygpO1xuICB9XG5cbiAgLy8gVGFrZSBhIHZhbHVlIG91dCBvZiB0aGUgdGV4dCwgd2hlcmV2ZXIgaXQgYXBwZWFycyDigJQgaXQgd2FzIGRlbGV0ZWQuXG4gIHB1YmxpYyByZW1vdmVLZXkoa2V5OiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLl9jaGlwcygpXG4gICAgICAuZmlsdGVyKChjaGlwKSA9PiBjaGlwLmdldEF0dHJpYnV0ZShLRVlfQVRUUklCVVRFKSA9PT0ga2V5KVxuICAgICAgLmZvckVhY2goKGNoaXApID0+IHRoaXMucmVtb3ZlKGNoaXApKTtcbiAgfVxuXG4gIC8vIFRha2Ugb25lIGNoaXAgb3V0IG9mIHRoZSB0ZXh0LlxuICBwdWJsaWMgcmVtb3ZlKGNoaXA6IEhUTUxFbGVtZW50KTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLl9lZGl0b3I/LmVsLmNvbnRhaW5zKGNoaXApKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gVGhlIGN1cnNvciBnb2VzIGJhY2sgd2hlcmUgdGhlIGNoaXAgd2FzIOKAlCB3aGF0ZXZlciBhc2tlZCBmb3IgdGhlXG4gICAgLy8gcmVtb3ZhbCAoYSBkaWFsb2csIGEgcG9wb3ZlcikgdG9vayB0aGUgZm9jdXMsIGFuZCB3aXRob3V0IGl0IGFuIFVuZG9cbiAgICAvLyBzdHJhaWdodCBhZnRlciB3b3VsZCBuZXZlciByZWFjaCB0aGUgZWRpdG9yLlxuICAgIGNvbnN0IGNhcmV0ID0gZG9jdW1lbnQuY3JlYXRlUmFuZ2UoKTtcbiAgICBjYXJldC5zZXRTdGFydEJlZm9yZShjaGlwKTtcbiAgICBjYXJldC5jb2xsYXBzZSh0cnVlKTtcblxuICAgIHRoaXMuX2VkaXRvci51bmRvLnNhdmVTdGVwKCk7XG4gICAgY2hpcC5yZW1vdmUoKTtcbiAgICB0aGlzLl9lZGl0b3IuZWwuZm9jdXMoKTtcbiAgICBjb25zdCBzZWxlY3Rpb24gPSB0aGlzLl9zZWxlY3Rpb24oKTtcbiAgICBzZWxlY3Rpb24ucmVtb3ZlQWxsUmFuZ2VzKCk7XG4gICAgc2VsZWN0aW9uLmFkZFJhbmdlKGNhcmV0KTtcbiAgICB0aGlzLl9jaGFuZ2VkKCk7XG4gIH1cblxuICBwcml2YXRlIF9jaGlwcygpOiBIVE1MRWxlbWVudFtdIHtcbiAgICByZXR1cm4gdGhpcy5fZWRpdG9yXG4gICAgICA/IEFycmF5LmZyb20odGhpcy5fZWRpdG9yLmVsLnF1ZXJ5U2VsZWN0b3JBbGwoQ0hJUF9TRUxFQ1RPUikpXG4gICAgICA6IFtdO1xuICB9XG5cbiAgLy8gSG93IG1hbnkgY2hpcHMgZWFjaCBrZXkgaGFzIGluIHRoZSBibG9jay5cbiAgcHJpdmF0ZSBfY2hpcENvdW50cygpOiBNYXA8c3RyaW5nLCBudW1iZXI+IHtcbiAgICBjb25zdCBjb3VudHMgPSBuZXcgTWFwPHN0cmluZywgbnVtYmVyPigpO1xuICAgIHRoaXMuX2NoaXBzKCkuZm9yRWFjaCgoY2hpcCkgPT4ge1xuICAgICAgY29uc3Qga2V5ID0gY2hpcC5nZXRBdHRyaWJ1dGUoS0VZX0FUVFJJQlVURSk7XG4gICAgICBjb3VudHMuc2V0KGtleSwgKGNvdW50cy5nZXQoa2V5KSA/PyAwKSArIDEpO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIGNvdW50cztcbiAgfVxuXG4gIC8vIFRlbGwgdGhlIGhvc3Qgd2hlbiBhbiBlZGl0IHRvb2sgdGhlIGxhc3QgY2hpcCBvZiBzb21lIGtleSBvdXQgb2YgdGhlXG4gIC8vIGJsb2NrLCBnaXZlbiB0aGUgY291bnRzIGZyb20gYmVmb3JlIGl0LlxuICBwcml2YXRlIF9yZXBvcnRSZW1vdmVkKGJlZm9yZTogTWFwPHN0cmluZywgbnVtYmVyPiB8IG51bGwpOiB2b2lkIHtcbiAgICBpZiAoIWJlZm9yZSB8fCAhdGhpcy5fZWRpdG9yKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgYWZ0ZXIgPSB0aGlzLl9jaGlwQ291bnRzKCk7XG4gICAgaWYgKFsuLi5iZWZvcmUua2V5cygpXS5zb21lKChrZXkpID0+ICFhZnRlci5oYXMoa2V5KSkpIHtcbiAgICAgIHRoaXMuY29uZmlnLnJlbW92ZWQoe1xuICAgICAgICBiZWZvcmU6IFsuLi5iZWZvcmUua2V5cygpXSxcbiAgICAgICAgYWZ0ZXI6IFsuLi5hZnRlci5rZXlzKCldLFxuICAgICAgICB1bmRvOiAoKSA9PiB0aGlzLnVuZG8oKSxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8vIEEgdG9vbGJhciBjb21tYW5kIHNlZXMgdG9rZW5zLCBub3QgY2hpcHM6IENsZWFyIGZvcm1hdHRpbmcgdW53cmFwcyBldmVyeVxuICAvLyBzcGFuLCBhIGNoaXAgaW5jbHVkZWQsIHdoaWNoIHdvdWxkIGxlYXZlIGEgdHlwZWQgbnVtYmVyIGJlaGluZC4gQXJvdW5kIGFcbiAgLy8gdG9rZW4gaXQgZm9ybWF0cyBwbGFpbiB0ZXh0LCBhbmQgdGhlIGNoaXAgY29tZXMgYmFjayBpbnNpZGUgd2hhdGV2ZXJcbiAgLy8gZm9ybWF0dGluZyB0aGUgdG9rZW4gd2FzIGdpdmVuLlxuICBwcml2YXRlIF93YXRjaENvbW1hbmRzKGVkaXRvcjogYW55KTogdm9pZCB7XG4gICAgZWRpdG9yLmV2ZW50cy5vbignY29tbWFuZHMuYmVmb3JlJywgKGNvbW1hbmQ6IHN0cmluZykgPT4gdGhpcy5fb25Db21tYW5kQmVmb3JlKGNvbW1hbmQpKTtcbiAgICBlZGl0b3IuZXZlbnRzLm9uKCdjb21tYW5kcy5hZnRlcicsICgpID0+IHtcbiAgICAgIHRoaXMuX3RvQ2hpcHMoKTtcbiAgICAgIHRoaXMuX3JlcG9ydFJlbW92ZWQodGhpcy5fYmVmb3JlKTtcbiAgICAgIHRoaXMuX2JlZm9yZSA9IG51bGw7XG4gICAgfSk7XG4gICAgLy8gVW5kbyBhbmQgcmVkbyByZXN0b3JlIGEgc3RlcCBhcyBGcm9hbGEgc2F2ZWQgaXQ6IHRoZSBvbmUgYmVmb3JlIGFcbiAgICAvLyBjb21tYW5kIGhvbGRzIHRva2VucywgYXMgdGhlIGNvbW1hbmQgc2F3IHRoZW0uIE5laXRoZXIgZmlyZXNcbiAgICAvLyBjb21tYW5kcy5hZnRlcjogRnJvYWxhJ3MgY29tbWFuZHMudW5kbygpIOKAlCBDdHJsK1osIGFuZCB1bmRvKCkgaGVyZSDigJRcbiAgICAvLyBydW5zIHRoZSB1bmRvIGRpcmVjdGx5LlxuICAgIGVkaXRvci5ldmVudHMub24oJ2NvbW1hbmRzLnVuZG8nLCAoKSA9PiB0aGlzLl90b0NoaXBzKCkpO1xuICAgIGVkaXRvci5ldmVudHMub24oJ2NvbW1hbmRzLnJlZG8nLCAoKSA9PiB0aGlzLl90b0NoaXBzKCkpO1xuICB9XG5cbiAgLy8gRXZlcnkgY29tbWFuZCBzdGFydHMgYSBuZXcgZWRpdC4gT25lIHRoYXQgd291bGQgYnVpbGQgd2hhdCB0aGUgc2VydmVyXG4gIC8vIHJld3JpdGVzIGlzIHJlZnVzZWQgKHJldHVybmluZyBmYWxzZSBjYW5jZWxzIGl0KTsgYW55IG90aGVyIHJ1bnMgb25cbiAgLy8gdG9rZW5zLCBpdHMgY2hpcCBjb3VudHMga2VwdCB0byBzZWUgd2hhdCBpdCByZW1vdmVkLlxuICBwcml2YXRlIF9vbkNvbW1hbmRCZWZvcmUoY29tbWFuZDogc3RyaW5nKTogZmFsc2UgfCB2b2lkIHtcbiAgICB0aGlzLmNvbmZpZy5jaGFuZ2VkKCk7XG5cbiAgICBpZiAoVEFCTEVfSU5TRVJUX0NPTU1BTkRTLmluY2x1ZGVzKGNvbW1hbmQpICYmIHRoaXMuX2NhcmV0SW4oTk9fVEFCTEVfSU5TSURFKSkge1xuICAgICAgdGhpcy5jb25maWcucmVmdXNlZCgnQSB0YWJsZSBnb2VzIGJldHdlZW4gcGFyYWdyYXBocywgbmV2ZXIgaW5zaWRlIGEgbGlzdCBvciBhbm90aGVyIHRhYmxlLicpO1xuXG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgaWYgKENFTExfQ09NTUFORFMuaW5jbHVkZXMoY29tbWFuZCkgJiYgdGhpcy5fY2FyZXRJbihDRUxMKSkge1xuICAgICAgdGhpcy5jb25maWcucmVmdXNlZCgnQSB0YWJsZSBjZWxsIGhvbGRzIHdvcmRzIGFuZCB2YWx1ZXM7IGEgbGlzdCBvciBhIGhlYWRpbmcgZ29lcyBvdXRzaWRlIHRoZSB0YWJsZS4nKTtcblxuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHRoaXMuX2JlZm9yZSA9IEhJU1RPUllfQ09NTUFORFMuaW5jbHVkZXMoY29tbWFuZCkgPyBudWxsIDogdGhpcy5fY2hpcENvdW50cygpO1xuICAgIHRoaXMuX3RvVG9rZW5UZXh0KCk7XG4gIH1cblxuICAvLyBXaGV0aGVyIHRoZSBjYXJldCBzaXRzIGluc2lkZSBhbiBlbGVtZW50IG9mIHRoaXMgZWRpdG9yIHRoYXQgYHNlbGVjdG9yYFxuICAvLyBtYXRjaGVzLlxuICBwcml2YXRlIF9jYXJldEluKHNlbGVjdG9yOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICBjb25zdCBjb250YWluZXI6IEVsZW1lbnQgfCBudWxsID0gdGhpcy5fZWRpdG9yLnNlbGVjdGlvbi5lbGVtZW50KCk/LmNsb3Nlc3Q/LihzZWxlY3RvcikgPz8gbnVsbDtcblxuICAgIHJldHVybiAhIWNvbnRhaW5lciAmJiB0aGlzLl9lZGl0b3IuZWwuY29udGFpbnMoY29udGFpbmVyKTtcbiAgfVxuXG4gIC8vIFR1cm4gZXZlcnkge3t2YWx1ZS5rZXl9fSB0b2tlbiBpbiB0aGUgZWRpdG9yJ3MgdGV4dCBpbnRvIGEgY2hpcC4gRm9yIGFcbiAgLy8gcGFzdGUsIGEgdG9rZW4gb25seSBzdGF5cyB3aGVuIGl0IHdhcyBjb3BpZWQgb24gdGhpcyBwYWdlIGFuZCB0aGUgcGFnZSBoYXNcbiAgLy8gdGhlIHZhbHVlOyBvdGhlcndpc2UgaXQgZ29lcywgYW5kIGp1c3QgdGhlIHRleHQgYXJvdW5kIGl0IGlzIHBhc3RlZC5cbiAgcHJpdmF0ZSBfdG9DaGlwcyhwYXN0ZWQgPSBmYWxzZSk6IHZvaWQge1xuICAgIGNvbnN0IGVsOiBIVE1MRWxlbWVudCB8IHVuZGVmaW5lZCA9IHRoaXMuX2VkaXRvcj8uZWw7XG4gICAgaWYgKCFlbCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHdhbGtlciA9IGRvY3VtZW50LmNyZWF0ZVRyZWVXYWxrZXIoZWwsIE5vZGVGaWx0ZXIuU0hPV19URVhUKTtcbiAgICBjb25zdCB0ZXh0czogVGV4dFtdID0gW107XG4gICAgd2hpbGUgKHdhbGtlci5uZXh0Tm9kZSgpKSB7XG4gICAgICBjb25zdCB0ZXh0ID0gd2Fsa2VyLmN1cnJlbnROb2RlIGFzIFRleHQ7XG4gICAgICBpZiAodGV4dC5kYXRhLmluY2x1ZGVzKCd7eycpICYmICF0ZXh0LnBhcmVudEVsZW1lbnQ/LmNsb3Nlc3QoQ0hJUF9TRUxFQ1RPUikpIHtcbiAgICAgICAgdGV4dHMucHVzaCh0ZXh0KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0ZXh0cy5mb3JFYWNoKCh0ZXh0KSA9PiB0aGlzLl9zcGxpdFRleHQodGV4dCwgcGFzdGVkKSk7XG4gIH1cblxuICBwcml2YXRlIF9rZWVwc1Bhc3RlZChrZXk6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLl9wYXN0ZVNjb3BlID09PSB0aGlzLmNvbmZpZy5zY29wZSgpICYmICEhdGhpcy5jb25maWcudmFsdWVzKClba2V5XTtcbiAgfVxuXG4gIHByaXZhdGUgX3NwbGl0VGV4dCh0ZXh0OiBUZXh0LCBwYXN0ZWQ6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICBjb25zdCBtYXRjaGVzID0gQXJyYXkuZnJvbSh0ZXh0LmRhdGEubWF0Y2hBbGwoVkFMVUVfVE9LRU5fUEFUVEVSTikpO1xuICAgIGlmICghbWF0Y2hlcy5sZW5ndGgpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBPbmx5IG5vbi1lbXB0eSB0ZXh0IGFyb3VuZCB0aGUgY2hpcHMsIHNvIGEgc2VsZWN0aW9uIGNvdW50ZWQgaW4gY2hpbGRcbiAgICAvLyBub2RlcyBrZWVwcyBpdHMgcGxhY2UuXG4gICAgY29uc3QgZnJhZ21lbnQgPSBkb2N1bWVudC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCk7XG4gICAgY29uc3QgYXBwZW5kVGV4dCA9ICh2YWx1ZTogc3RyaW5nKSA9PiB7XG4gICAgICBpZiAodmFsdWUpIHtcbiAgICAgICAgZnJhZ21lbnQuYXBwZW5kKHZhbHVlKTtcbiAgICAgIH1cbiAgICB9O1xuICAgIGxldCBjb25zdW1lZCA9IDA7XG4gICAgbWF0Y2hlcy5mb3JFYWNoKChtYXRjaCkgPT4ge1xuICAgICAgY29uc3Qga2V5ID0gbWF0Y2hbMV0udG9Mb3dlckNhc2UoKTtcbiAgICAgIGFwcGVuZFRleHQodGV4dC5kYXRhLnNsaWNlKGNvbnN1bWVkLCBtYXRjaC5pbmRleCkpO1xuICAgICAgaWYgKCFwYXN0ZWQgfHwgdGhpcy5fa2VlcHNQYXN0ZWQoa2V5KSkge1xuICAgICAgICBmcmFnbWVudC5hcHBlbmQodGhpcy5fY3JlYXRlQ2hpcChrZXkpKTtcbiAgICAgIH1cbiAgICAgIGNvbnN1bWVkID0gbWF0Y2guaW5kZXggKyBtYXRjaFswXS5sZW5ndGg7XG4gICAgfSk7XG4gICAgYXBwZW5kVGV4dCh0ZXh0LmRhdGEuc2xpY2UoY29uc3VtZWQpKTtcblxuICAgIHRleHQucmVwbGFjZVdpdGgoZnJhZ21lbnQpO1xuICB9XG5cbiAgLy8gRXZlcnkgY2hpcCBpbiB0aGUgZWRpdG9yIGJhY2sgdG8gaXRzIHRva2VuLCBhcyB0ZXh0LlxuICBwcml2YXRlIF90b1Rva2VuVGV4dCgpOiB2b2lkIHtcbiAgICB0aGlzLl9jaGlwcygpLmZvckVhY2goKGNoaXApID0+IGNoaXAucmVwbGFjZVdpdGgodmFsdWVUb2tlbihjaGlwLmdldEF0dHJpYnV0ZShLRVlfQVRUUklCVVRFKSkpKTtcbiAgfVxuXG4gIHByaXZhdGUgX2NyZWF0ZUNoaXAoa2V5OiBzdHJpbmcpOiBIVE1MRWxlbWVudCB7XG4gICAgY29uc3QgY2hpcCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NwYW4nKTtcbiAgICBjaGlwLnNldEF0dHJpYnV0ZShUWVBFX0FUVFJJQlVURSwgVkFMVUVfVFlQRSk7XG4gICAgY2hpcC5zZXRBdHRyaWJ1dGUoS0VZX0FUVFJJQlVURSwga2V5KTtcbiAgICBjaGlwLnNldEF0dHJpYnV0ZSgnY29udGVudGVkaXRhYmxlJywgJ2ZhbHNlJyk7XG4gICAgdGhpcy5fbGFiZWwoY2hpcCk7XG5cbiAgICByZXR1cm4gY2hpcDtcbiAgfVxuXG4gIC8vIEEgY2hpcCByZWFkcyBhcyB0aGUgdmFsdWUgZG9lcyBpbiB0aGUgdmlld2VkIGJsb2NrIOKAlCBpdHMgbnVtYmVyLCB0aGVcbiAgLy8gZWxsaXBzaXMgd2hpbGUgdGhhdCBsb2FkcywgZWxzZSB0aGUgZW0gZGFzaCDigJQgc28gb3BlbmluZyB0aGUgZWRpdG9yIG1vdmVzXG4gIC8vIG5vIHdvcmQ7IG9yIGFzIGl0cyBuYW1lLCB3aGVuIG5hbWVzIGFyZSB0b2dnbGVkIG9uLiBBIGtleSB3aXRoIG5vIHZhbHVlIG9uXG4gIC8vIHRoZSBwYWdlIHJlYWRzIGFzIHRoZSBrZXkgaXRzZWxmLCBtYXJrZWQgbWlzc2luZy5cbiAgcHJpdmF0ZSBfbGFiZWwoY2hpcDogSFRNTEVsZW1lbnQpOiB2b2lkIHtcbiAgICBjb25zdCBrZXkgPSBjaGlwLmdldEF0dHJpYnV0ZShLRVlfQVRUUklCVVRFKTtcbiAgICBjb25zdCB2YWx1ZSA9IHRoaXMuY29uZmlnLnZhbHVlcygpW2tleV07XG5cbiAgICBjaGlwLnRleHRDb250ZW50ID0gIXZhbHVlXG4gICAgICA/IGtleVxuICAgICAgOiB0aGlzLmNvbmZpZy5zaG93TmFtZXMoKSA/IHZhbHVlLm5hbWUgOiB2YWx1ZVRleHQodmFsdWUpO1xuICAgIGNoaXAudGl0bGUgPSB2YWx1ZT8ubmFtZSA/PyBrZXk7XG4gICAgY2hpcC50b2dnbGVBdHRyaWJ1dGUoTUlTU0lOR19BVFRSSUJVVEUsICF2YWx1ZSk7XG4gIH1cblxuICAvLyBUaGUgaHRtbCBGcm9hbGEgaGFuZHMgb3V0LCB3aXRoIGV2ZXJ5IGNoaXAgYmFjayB0byBpdHMgdG9rZW4uXG4gIHByaXZhdGUgX3RvVG9rZW5zKGh0bWw6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgaWYgKCFodG1sLmluY2x1ZGVzKEtFWV9BVFRSSUJVVEUpKSB7XG4gICAgICByZXR1cm4gaHRtbDtcbiAgICB9XG5cbiAgICBjb25zdCB0ZW1wbGF0ZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3RlbXBsYXRlJyk7XG4gICAgdGVtcGxhdGUuaW5uZXJIVE1MID0gaHRtbDtcbiAgICB0ZW1wbGF0ZS5jb250ZW50LnF1ZXJ5U2VsZWN0b3JBbGwoQ0hJUF9TRUxFQ1RPUikuZm9yRWFjaCgoY2hpcCkgPT4ge1xuICAgICAgY2hpcC5yZXBsYWNlV2l0aCh2YWx1ZVRva2VuKGNoaXAuZ2V0QXR0cmlidXRlKEtFWV9BVFRSSUJVVEUpKSk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gdGVtcGxhdGUuaW5uZXJIVE1MO1xuICB9XG5cbiAgcHJpdmF0ZSBfb25LZXlkb3duKGV2ZW50OiBLZXlib2FyZEV2ZW50KTogYm9vbGVhbiB8IHZvaWQge1xuICAgIC8vIEFueSBrZXkgYnV0IGEgbG9uZSBtb2RpZmllciBzdGFydHMgYSBuZXcgZWRpdC5cbiAgICBpZiAoIU1PRElGSUVSX0tFWVMuaW5jbHVkZXMoZXZlbnQua2V5KSkge1xuICAgICAgdGhpcy5jb25maWcuY2hhbmdlZCgpO1xuICAgIH1cblxuICAgIGNvbnN0IGRlbGV0aW5nID0gZXZlbnQua2V5ID09PSAnQmFja3NwYWNlJyB8fCBldmVudC5rZXkgPT09ICdEZWxldGUnO1xuXG4gICAgLy8gRGVsZXRpbmcgYWNyb3NzIHNldmVyYWwgc2VsZWN0ZWQgY2VsbHMgZ29lcyB0aHJvdWdoLCB2YWx1ZXMgYW5kIGFsbDpcbiAgICAvLyBGcm9hbGEgc2F2ZXMgYW4gdW5kbyBzdGVwIGFuZCBlbXB0aWVzIHRoZSBjZWxscywgYW5kIHdoYXQgdGhhdCB0b29rIGlzXG4gICAgLy8gcmVwb3J0ZWQgb25jZSB0aGV5IGFyZSBlbXB0eS5cbiAgICBpZiAoZGVsZXRpbmcgJiYgdGhpcy5fZWRpdG9yLmVsLnF1ZXJ5U2VsZWN0b3JBbGwoU0VMRUNURURfQ0VMTCkubGVuZ3RoID4gMSkge1xuICAgICAgY29uc3QgYmVmb3JlID0gdGhpcy5fY2hpcENvdW50cygpO1xuICAgICAgc2V0VGltZW91dCgoKSA9PiB0aGlzLl9yZXBvcnRSZW1vdmVkKGJlZm9yZSkpO1xuXG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGNvbnN0IHJhbmdlID0gdGhpcy5fcmFuZ2UoKTtcbiAgICBpZiAoIXJhbmdlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHJhbmdlLmNvbGxhcHNlZCkge1xuICAgICAgaWYgKCFkZWxldGluZykge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGNoaXAgPSB0aGlzLl9hZGphY2VudENoaXAoZXZlbnQua2V5ID09PSAnQmFja3NwYWNlJywgdGhpcy5fZ3JhbnVsYXJpdHkoZXZlbnQpKTtcblxuICAgICAgcmV0dXJuIGNoaXAgPyB0aGlzLl9ibG9jayhldmVudCwgW2NoaXBdLCBudWxsKSA6IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICAvLyBBIHNlbGVjdGlvbiBpcyByZXBsYWNlZCBieSBhIGRlbGV0aW5nIGtleSwgRW50ZXIsIGEgdHlwZWQgY2hhcmFjdGVyIG9yXG4gICAgLy8gYSBjdXQuXG4gICAgY29uc3QgdHlwaW5nID0gZXZlbnQua2V5Lmxlbmd0aCA9PT0gMSAmJiAhZXZlbnQuY3RybEtleSAmJiAhZXZlbnQubWV0YUtleTtcbiAgICBjb25zdCBjdXR0aW5nID0gKGV2ZW50LmN0cmxLZXkgfHwgZXZlbnQubWV0YUtleSkgJiYgZXZlbnQua2V5LnRvTG93ZXJDYXNlKCkgPT09ICd4JztcbiAgICBpZiAoIWRlbGV0aW5nICYmICF0eXBpbmcgJiYgIWN1dHRpbmcgJiYgZXZlbnQua2V5ICE9PSAnRW50ZXInKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgY2hpcHMgPSB0aGlzLl9jaGlwc0luKHJhbmdlKTtcblxuICAgIHJldHVybiBjaGlwcy5sZW5ndGggPyB0aGlzLl9ibG9jayhldmVudCwgY2hpcHMsIHJhbmdlKSA6IHVuZGVmaW5lZDtcbiAgfVxuXG4gIC8vIFRoZSBzYW1lIHJ1bGUgZm9yIGVkaXRzIHRoYXQgYXJyaXZlIHdpdGhvdXQgYSBrZXkgRnJvYWxhIHNlZXM6IGEgcGhvbmVcbiAgLy8ga2V5Ym9hcmQsIGFuIGlucHV0IG1ldGhvZCwgYSBzcGVsbC1jaGVjayByZXBsYWNlbWVudC5cbiAgcHJpdmF0ZSBfb25CZWZvcmVJbnB1dChldmVudDogSW5wdXRFdmVudCk6IHZvaWQge1xuICAgIGNvbnN0IHJhbmdlID0gdGhpcy5fcmFuZ2UoKTtcbiAgICBpZiAodGhpcy5fcmVtb3ZpbmcgfHwgIXJhbmdlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHJhbmdlLmNvbGxhcHNlZCkge1xuICAgICAgY29uc3QgYmFja3dhcmQgPSBldmVudC5pbnB1dFR5cGUuZW5kc1dpdGgoJ0JhY2t3YXJkJyk7XG4gICAgICBpZiAoZXZlbnQuaW5wdXRUeXBlLnN0YXJ0c1dpdGgoJ2RlbGV0ZScpKSB7XG4gICAgICAgIGNvbnN0IGNoaXAgPSB0aGlzLl9hZGphY2VudENoaXAoYmFja3dhcmQsIGV2ZW50LmlucHV0VHlwZS5pbmNsdWRlcygnV29yZCcpID8gJ3dvcmQnIDogJ2NoYXJhY3RlcicpO1xuICAgICAgICBpZiAoY2hpcCkge1xuICAgICAgICAgIHRoaXMuX2Jsb2NrKGV2ZW50LCBbY2hpcF0sIG51bGwpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBjaGlwcyA9IHRoaXMuX2NoaXBzSW4ocmFuZ2UpO1xuICAgIGlmIChjaGlwcy5sZW5ndGgpIHtcbiAgICAgIHRoaXMuX2Jsb2NrKGV2ZW50LCBjaGlwcywgcmFuZ2UpO1xuICAgIH1cbiAgfVxuXG4gIC8vIEN1dCwgZHJhZyBhbmQgcGFzdGUtb3Zlcjogc3RvcHBlZCB3aGVuIHRoZSBzZWxlY3Rpb24gaG9sZHMgYSB2YWx1ZS5cbiAgcHJpdmF0ZSBfZ3VhcmRTZWxlY3Rpb24oZXZlbnQ6IEV2ZW50KTogYm9vbGVhbiB8IHZvaWQge1xuICAgIGNvbnN0IHJhbmdlID0gdGhpcy5fcmFuZ2UoKTtcbiAgICBpZiAodGhpcy5fcmVtb3ZpbmcgfHwgIXJhbmdlIHx8IHJhbmdlLmNvbGxhcHNlZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGNoaXBzID0gdGhpcy5fY2hpcHNJbihyYW5nZSk7XG5cbiAgICByZXR1cm4gY2hpcHMubGVuZ3RoID8gdGhpcy5fYmxvY2soZXZlbnQsIGNoaXBzLCByYW5nZSkgOiB1bmRlZmluZWQ7XG4gIH1cblxuICAvLyBDb3B5aW5nIGEgdmFsdWUgY29waWVzIGl0cyB0b2tlbiwgYW5kIHRoZSBwYWdlIGl0IHdhcyBjb3BpZWQgb24sIHNvXG4gIC8vIHBhc3RpbmcgaXQgYmFjayBvbiB0aGlzIHBhZ2Ug4oCUIGluIHRoaXMgYmxvY2sgb3IgYW5vdGhlciDigJQgbWFrZXMgaXQgYSBjaGlwXG4gIC8vIGFnYWluLlxuICBwcml2YXRlIF9vbkNvcHkoZXZlbnQ6IENsaXBib2FyZEV2ZW50KTogdm9pZCB7XG4gICAgY29uc3QgcmFuZ2UgPSB0aGlzLl9yYW5nZSgpO1xuICAgIGlmICghcmFuZ2UgfHwgcmFuZ2UuY29sbGFwc2VkIHx8ICF0aGlzLl9jaGlwc0luKHJhbmdlKS5sZW5ndGgpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBob2xkZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICBob2xkZXIuYXBwZW5kKHJhbmdlLmNsb25lQ29udGVudHMoKSk7XG4gICAgaG9sZGVyLnF1ZXJ5U2VsZWN0b3JBbGwoQ0hJUF9TRUxFQ1RPUikuZm9yRWFjaCgoY2hpcCkgPT4ge1xuICAgICAgY2hpcC5yZXBsYWNlV2l0aCh2YWx1ZVRva2VuKGNoaXAuZ2V0QXR0cmlidXRlKEtFWV9BVFRSSUJVVEUpKSk7XG4gICAgfSk7XG5cbiAgICBldmVudC5jbGlwYm9hcmREYXRhLnNldERhdGEoJ3RleHQvcGxhaW4nLCB0aGlzLl9wbGFpblRleHQoaG9sZGVyKSk7XG4gICAgZXZlbnQuY2xpcGJvYXJkRGF0YS5zZXREYXRhKCd0ZXh0L2h0bWwnLCBob2xkZXIuaW5uZXJIVE1MKTtcbiAgICBldmVudC5jbGlwYm9hcmREYXRhLnNldERhdGEoU0NPUEVfVFlQRSwgdGhpcy5jb25maWcuc2NvcGUoKSk7XG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgfVxuXG4gIC8vIFdoYXQgY29waWVkIGh0bWwgcmVhZHMgYXMgaW4gcGxhaW4gdGV4dDogYSBwYXJhZ3JhcGggb24gaXRzIG93biBsaW5lcywgYVxuICAvLyB0YWJsZSdzIGNlbGxzIHRhYi1zZXBhcmF0ZWQgYW5kIGl0cyByb3dzIG9uIGxpbmVzIG9mIHRoZWlyIG93bi4gVGhhdCBpc1xuICAvLyB0aGUgYnJvd3NlcidzIGlubmVyVGV4dCwgd2hpY2ggb25seSB0ZXh0IGxhaWQgb3V0IG9uIHRoZSBwYWdlIGhhcyDigJQgc29cbiAgLy8gdGhlIGhvbGRlciBpcyBwdXQgb2Zmc2NyZWVuIChub3QgaGlkZGVuOiBoaWRkZW4gdGV4dCBoYXMgbm9uZSkgd2hpbGUgaXQgaXNcbiAgLy8gcmVhZC5cbiAgcHJpdmF0ZSBfcGxhaW5UZXh0KGhvbGRlcjogSFRNTEVsZW1lbnQpOiBzdHJpbmcge1xuICAgIGhvbGRlci5zdHlsZS5jc3NUZXh0ID0gJ3Bvc2l0aW9uOiBmaXhlZDsgbGVmdDogLTEwMDAwcHg7IHRvcDogMCc7XG4gICAgZG9jdW1lbnQuYm9keS5hcHBlbmQoaG9sZGVyKTtcbiAgICBjb25zdCB0ZXh0ID0gaG9sZGVyLmlubmVyVGV4dDtcbiAgICBob2xkZXIucmVtb3ZlKCk7XG5cbiAgICByZXR1cm4gdGV4dDtcbiAgfVxuXG4gIHByaXZhdGUgX29uQ2xpY2soZXZlbnQ6IE1vdXNlRXZlbnQpOiB2b2lkIHtcbiAgICBjb25zdCBjaGlwID0gKGV2ZW50LnRhcmdldCBhcyBFbGVtZW50KT8uY2xvc2VzdD8uKENISVBfU0VMRUNUT1IpIGFzIEhUTUxFbGVtZW50IHwgbnVsbDtcbiAgICBpZiAoIWNoaXAgfHwgIXRoaXMuX2VkaXRvcj8uZWwuY29udGFpbnMoY2hpcCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIC8vIEEgcHJlc3MgaW4gYSB0YWJsZSBjZWxsIGNhbiBvcGVuIHRoZSB0YWJsZSdzIHBvcHVwIG9uIG1vdXNldXAsIGp1c3RcbiAgICAvLyBiZWZvcmUgdGhpcyBjbGljazsgYSBjaGlwIGluIGEgY2VsbCBzaG93cyBvbmx5IGl0cyBvd24gcG9wb3Zlci5cbiAgICB0aGlzLl9lZGl0b3IucG9wdXBzLmhpZGUoJ3RhYmxlLmVkaXQnKTtcbiAgICB0aGlzLmNvbmZpZy5jbGljayhjaGlwLmdldEF0dHJpYnV0ZShLRVlfQVRUUklCVVRFKSwgY2hpcCk7XG4gIH1cblxuICBwcml2YXRlIF9vbkNoaXAoZXZlbnQ/OiBFdmVudCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAhIShldmVudD8udGFyZ2V0IGFzIEVsZW1lbnQgfCB1bmRlZmluZWQpPy5jbG9zZXN0Py4oQ0hJUF9TRUxFQ1RPUik7XG4gIH1cblxuICBwcml2YXRlIF9ibG9jayhldmVudDogRXZlbnQsIGNoaXBzOiBIVE1MRWxlbWVudFtdLCByYW5nZTogUmFuZ2UgfCBudWxsKTogZmFsc2Uge1xuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgY2hpcHMuZm9yRWFjaCgoY2hpcCkgPT4gY2hpcC5hbmltYXRlKEZMQVNILCBGTEFTSF9NUykpO1xuXG4gICAgdGhpcy5jb25maWcuYmxvY2tlZCh7XG4gICAgICBjb3VudDogY2hpcHMubGVuZ3RoLFxuICAgICAgLi4uKHJhbmdlID8geyByZW1vdmVTZWxlY3Rpb246ICgpID0+IHRoaXMuX3JlbW92ZVJhbmdlKHJhbmdlKSB9IDoge30pLFxuICAgIH0pO1xuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgcHJpdmF0ZSBfcmVtb3ZlUmFuZ2UocmFuZ2U6IFJhbmdlKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLl9lZGl0b3IpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBzZWxlY3Rpb24gPSB0aGlzLl9zZWxlY3Rpb24oKTtcbiAgICB0aGlzLl9lZGl0b3IuZWwuZm9jdXMoKTtcbiAgICBzZWxlY3Rpb24ucmVtb3ZlQWxsUmFuZ2VzKCk7XG4gICAgc2VsZWN0aW9uLmFkZFJhbmdlKHJhbmdlKTtcblxuICAgIHRoaXMuX2VkaXRvci51bmRvLnNhdmVTdGVwKCk7XG4gICAgdGhpcy5fcmVtb3ZpbmcgPSB0cnVlO1xuICAgIC8vIFRoZSBicm93c2VyJ3Mgb3duIGRlbGV0ZSwgc28gdHdvIHBhcmFncmFwaHMgYSBzZWxlY3Rpb24gc3BhbnMgam9pbiB0aGVcbiAgICAvLyB3YXkgdGhleSB3b3VsZCBmb3IgYSBwbGFpbiBEZWxldGUuXG4gICAgZG9jdW1lbnQuZXhlY0NvbW1hbmQoJ2RlbGV0ZScpO1xuICAgIHRoaXMuX3JlbW92aW5nID0gZmFsc2U7XG4gICAgdGhpcy5fY2hhbmdlZCgpO1xuICB9XG5cbiAgLy8gQW4gZWRpdCBtYWRlIGhlcmUgcmF0aGVyIHRoYW4gdHlwZWQ6IHJlY29yZCBpdCBmb3IgdW5kbywgYW5kIHRlbGxcbiAgLy8gaHRtbC1lZGl0b3Igc28gdGhlIGRyYWZ0IGZvbGxvd3MuXG4gIHByaXZhdGUgX2NoYW5nZWQoKTogdm9pZCB7XG4gICAgdGhpcy5fZWRpdG9yLnVuZG8uc2F2ZVN0ZXAoKTtcbiAgICB0aGlzLl9lZGl0b3IuZXZlbnRzLnRyaWdnZXIoJ2NvbnRlbnRDaGFuZ2VkJyk7XG4gIH1cblxuICBwcml2YXRlIF9zZWxlY3Rpb24oKTogU2VsZWN0aW9uIHtcbiAgICByZXR1cm4gdGhpcy5fZWRpdG9yLmVsLm93bmVyRG9jdW1lbnQuZ2V0U2VsZWN0aW9uKCk7XG4gIH1cblxuICAvLyBUaGUgc2VsZWN0aW9uLCB3aGVuIGl0IGlzIGluc2lkZSB0aGlzIGVkaXRvci5cbiAgcHJpdmF0ZSBfcmFuZ2UoKTogUmFuZ2UgfCBudWxsIHtcbiAgICBjb25zdCBzZWxlY3Rpb24gPSB0aGlzLl9lZGl0b3IgPyB0aGlzLl9zZWxlY3Rpb24oKSA6IG51bGw7XG4gICAgaWYgKCFzZWxlY3Rpb24/LnJhbmdlQ291bnQpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGNvbnN0IHJhbmdlID0gc2VsZWN0aW9uLmdldFJhbmdlQXQoMCk7XG5cbiAgICByZXR1cm4gdGhpcy5fZWRpdG9yLmVsLmNvbnRhaW5zKHJhbmdlLmNvbW1vbkFuY2VzdG9yQ29udGFpbmVyKSA/IHJhbmdlIDogbnVsbDtcbiAgfVxuXG4gIHByaXZhdGUgX2NoaXBzSW4ocmFuZ2U6IFJhbmdlKTogSFRNTEVsZW1lbnRbXSB7XG4gICAgcmV0dXJuIHRoaXMuX2NoaXBzKCkuZmlsdGVyKChjaGlwKSA9PiByYW5nZS5pbnRlcnNlY3RzTm9kZShjaGlwKSk7XG4gIH1cblxuICAvLyBUaGUgY2hpcCBhIGNvbGxhcHNlZCBjdXJzb3Igd291bGQgZGVsZXRlIGludG86IHN0cmV0Y2ggdGhlIHNlbGVjdGlvbiBieVxuICAvLyB3aGF0IHRoZSBrZXkgZGVsZXRlcywgc2VlIHdoYXQgaXQgY292ZXJzLCBhbmQgcHV0IGl0IGJhY2suIExldHRpbmcgdGhlXG4gIC8vIGJyb3dzZXIgc3RyZXRjaCBpdCBoYW5kbGVzIGV2ZXJ5IHNoYXBlIHRoZSBodG1sIHRha2VzIOKAlCBhIGNoaXAgaW5zaWRlIGFcbiAgLy8gYm9sZCBzcGFuLCBhdCBhIGxpbmUncyBlbmQsIGJlc2lkZSBhbiBlbXB0eSB0ZXh0IG5vZGUuXG4gIHByaXZhdGUgX2FkamFjZW50Q2hpcChiYWNrd2FyZDogYm9vbGVhbiwgZ3JhbnVsYXJpdHk6IHN0cmluZyk6IEhUTUxFbGVtZW50IHwgbnVsbCB7XG4gICAgY29uc3Qgc2VsZWN0aW9uID0gdGhpcy5fc2VsZWN0aW9uKCk7XG4gICAgY29uc3QgcmFuZ2UgPSBzZWxlY3Rpb24uZ2V0UmFuZ2VBdCgwKS5jbG9uZVJhbmdlKCk7XG5cbiAgICBzZWxlY3Rpb24ubW9kaWZ5KCdleHRlbmQnLCBiYWNrd2FyZCA/ICdiYWNrd2FyZCcgOiAnZm9yd2FyZCcsIGdyYW51bGFyaXR5KTtcbiAgICBjb25zdCBjaGlwID0gc2VsZWN0aW9uLnJhbmdlQ291bnRcbiAgICAgID8gdGhpcy5fY2hpcHNJbihzZWxlY3Rpb24uZ2V0UmFuZ2VBdCgwKSlbMF0gPz8gbnVsbFxuICAgICAgOiBudWxsO1xuXG4gICAgc2VsZWN0aW9uLnJlbW92ZUFsbFJhbmdlcygpO1xuICAgIHNlbGVjdGlvbi5hZGRSYW5nZShyYW5nZSk7XG5cbiAgICByZXR1cm4gY2hpcDtcbiAgfVxuXG4gIC8vIEhvdyBmYXIgYSBkZWxldGluZyBrZXkgcmVhY2hlczogYSB3b3JkIHdpdGggQ3RybC9BbHQsIHRvIHRoZSBsaW5lJ3Mgc3RhcnRcbiAgLy8gd2l0aCBDbWQgb24gYSBNYWMsIG9uZSBjaGFyYWN0ZXIgb3RoZXJ3aXNlLlxuICBwcml2YXRlIF9ncmFudWxhcml0eShldmVudDogS2V5Ym9hcmRFdmVudCk6IHN0cmluZyB7XG4gICAgaWYgKGV2ZW50Lm1ldGFLZXkpIHtcbiAgICAgIHJldHVybiAnbGluZWJvdW5kYXJ5JztcbiAgICB9XG5cbiAgICByZXR1cm4gZXZlbnQuY3RybEtleSB8fCBldmVudC5hbHRLZXkgPyAnd29yZCcgOiAnY2hhcmFjdGVyJztcbiAgfVxufVxuIl19