@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
@@ -1,8 +1,14 @@
1
- import { ChangeDetectionStrategy, Component, DestroyRef, ElementRef, computed, effect, inject, input, output, untracked, viewChild, } from '@angular/core';
1
+ import { ChangeDetectionStrategy, Component, DestroyRef, ElementRef, computed, effect, inject, input, output, signal, untracked, viewChild, } from '@angular/core';
2
2
  import { FormsModule } from '@angular/forms';
3
+ import { MatButton, MatIconButton } from '@angular/material/button';
4
+ import { MatIcon } from '@angular/material/icon';
5
+ import { MatTooltip } from '@angular/material/tooltip';
3
6
  import { DomSanitizer } from '@angular/platform-browser';
4
7
  import { FsHtmlEditorComponent } from '@firestitch/html-editor';
5
- import { DEFAULT_TEXT_COLOR, DEFAULT_TEXT_SIZE, HEADING_TEXT_SIZES, fillTextTokens, } from '../../text';
8
+ import { FsPopoverDirective } from '@firestitch/popover';
9
+ import { DEFAULT_TEXT_COLOR, DEFAULT_TEXT_SIZE, HEADING_TEXT_SIZES, TEXT_TABLE_BORDER_COLOR, TEXT_TABLE_BORDER_WIDTH, TEXT_TABLE_CELL_PADDING, TEXT_TABLE_MARGIN, fillTextTokens, } from '../../text';
10
+ import { NO_VALUE_KEYS, readKeys } from '../../values';
11
+ import { VALUE_EMBED_ATTRIBUTES, ValueEmbedPlugin, } from './value-embed.plugin';
6
12
  import * as i0 from "@angular/core";
7
13
  import * as i1 from "@angular/forms";
8
14
  // Point sizes — the report's type unit (1:1 with PowerPoint and PDF).
@@ -15,12 +21,44 @@ const TOKENS = {
15
21
  };
16
22
  // What the editor may produce — exactly what the server keeps
17
23
  // (ReportTextHtml) and the exports draw. Anything else would edit fine and
18
- // then vanish on save.
19
- const ALLOWED_TAGS = ['p', 'h1', 'h2', 'h3', 'br', 'strong', 'em', 'u', 's', 'span', 'a', 'ul', 'ol', 'li'];
20
- const ALLOWED_STYLES = ['color', 'background-color', 'font-size', 'font-weight', 'font-style', 'text-decoration', 'font-family', 'text-align'];
21
- // Froala's own toolbars and popups live on the body, not in the block; a press
22
- // on any of them is still part of editing the block.
23
- const EDITOR_CHROME = '.fr-toolbar, .fr-popup, .fr-dropdown-menu, .fr-modal, .fr-tooltip';
24
+ // then vanish on save. A table keeps its rows, cells and spans, and a cell its
25
+ // alignment, fill and width; its borders and padding are never stored, so
26
+ // every renderer draws the one grid in text.ts (TEXT_TABLE_*).
27
+ const ALLOWED_TAGS = [
28
+ 'p', 'h1', 'h2', 'h3', 'br', 'strong', 'em', 'u', 's', 'span', 'a', 'ul', 'ol', 'li',
29
+ 'table', 'thead', 'tbody', 'tfoot', 'tr', 'th', 'td',
30
+ ];
31
+ const ALLOWED_STYLES = [
32
+ 'color', 'background-color', 'font-size', 'font-weight', 'font-style', 'text-decoration', 'font-family', 'text-align',
33
+ 'vertical-align', 'width',
34
+ ];
35
+ // With useClasses: false, Froala's html.get copies every stylesheet declaration
36
+ // that matches an element into its inline style, then lays the element's own
37
+ // inline style back over it. So an ignored property never loses what the user
38
+ // set; it only keeps the canvas's, Froala's and the host app's css out of the
39
+ // saved html. Listed: every property the server keeps and the shorthands that
40
+ // set one (otherwise Froala's grey header fill would be saved as the user's),
41
+ // then everything else those stylesheets set on a block's elements, so a block
42
+ // opened and closed untouched saves nothing new. Names match exactly, so a
43
+ // rule's longhands are listed too: the browser spells Froala's table
44
+ // `border: none` as border-width/-style/-color/-image, and the host app's
45
+ // headings set margin-top and margin-bottom. Froala also outlines a table the
46
+ // pointer is over, with a class that is still on it when the html is read.
47
+ const IGNORED_SHEET_STYLES = [
48
+ 'color', 'background', 'background-color', 'font', 'font-family', 'font-size', 'font-style', 'font-weight',
49
+ 'text-decoration', 'text-align', 'vertical-align', 'width',
50
+ 'height', 'min-width', 'max-width', 'margin', 'margin-top', 'margin-bottom', 'padding', 'padding-left',
51
+ 'border', 'border-width', 'border-style', 'border-color', 'border-image', 'border-collapse', 'empty-cells',
52
+ 'outline', 'position', 'display', 'list-style', 'line-height', 'user-select',
53
+ ];
54
+ // Froala's own toolbars and popups live on the body, not in the block, and so
55
+ // does a value chip's popover (an overlay); a press on any of them is still part
56
+ // of editing the block.
57
+ const EDITOR_CHROME = '.fr-toolbar, .fr-popup, .fr-dropdown-menu, .fr-modal, .fr-tooltip, .cdk-overlay-container';
58
+ // The toolbar toggle between a chip's number and its name.
59
+ const VALUE_NAMES_BUTTON = 'valueNames';
60
+ // How long a notice under the open block stays up.
61
+ const VALUE_BLOCK_NOTICE_MS = 6000;
24
62
  // A text block: authored rich text on the page.
25
63
  //
26
64
  // Read mode renders the stored html with its tokens ({{page.number}}, …) filled
@@ -32,7 +70,12 @@ const EDITOR_CHROME = '.fr-toolbar, .fr-popup, .fr-dropdown-menu, .fr-modal, .fr
32
70
  // Edit mode mounts <fs-html-editor> in its floating mode in place — the words
33
71
  // stay where they sit on the slide — with Froala's inline toolbar popping up
34
72
  // over them. The editor exists only while editing; the raw html is edited, so a
35
- // token reads as {{page.number}} while editing and as the number otherwise.
73
+ // token reads as {{page.number}} while editing and as the number otherwise. The
74
+ // exception is a live value ({{value.key}}): it edits as a chip, which no stray
75
+ // keystroke removes; selecting it and pressing Delete offers to take it out
76
+ // (ValueEmbedPlugin). Deleting a table's rows, columns or cells does take the
77
+ // chips in them, and a notice under the block counts the values that leaves
78
+ // unused, with an Undo.
36
79
  //
37
80
  // The block never saves on its own: it emits the new html when editing ends
38
81
  // and the host persists it.
@@ -43,11 +86,20 @@ export class ComponentTextComponent {
43
86
  html = input('');
44
87
  tokens = input.required();
45
88
  editing = input(false);
89
+ // The value keys the other text blocks of this block's layer show. Asked
90
+ // for when an edit takes the last chip of a value out of this block, as a
91
+ // value another block still shows is not left unused; a function, as a
92
+ // saved block's html changes without any input changing.
93
+ shownElsewhere = input(() => NO_VALUE_KEYS);
46
94
  // The html after an edit, only when it changed.
47
95
  saved = output();
48
96
  // A press landed outside the block (or Escape): the host ends edit mode,
49
97
  // which saves.
50
98
  editEnded = output();
99
+ // A value's settings were asked for from its popover, by the value's key.
100
+ // The host opens the value's settings dialog, where it can also be deleted
101
+ // (then removeValue()).
102
+ valueSettings = output();
51
103
  typeScale = {
52
104
  body: `${DEFAULT_TEXT_SIZE}pt`,
53
105
  h1: `${HEADING_TEXT_SIZES[1]}pt`,
@@ -55,10 +107,38 @@ export class ComponentTextComponent {
55
107
  h3: `${HEADING_TEXT_SIZES[3]}pt`,
56
108
  color: DEFAULT_TEXT_COLOR,
57
109
  };
110
+ tableLook = {
111
+ border: `${TEXT_TABLE_BORDER_WIDTH}pt solid ${TEXT_TABLE_BORDER_COLOR}`,
112
+ padding: `${TEXT_TABLE_CELL_PADDING.vertical}pt ${TEXT_TABLE_CELL_PADDING.horizontal}pt`,
113
+ margin: `${TEXT_TABLE_MARGIN}pt`,
114
+ };
115
+ // Chips label values with their names instead of their numbers.
116
+ showValueNames = signal(false);
117
+ // The notice under the open block. A new one replaces it.
118
+ notice = signal(null);
119
+ // The chip whose popover was opened last, and what the popover says about it.
120
+ valuePopover = signal(null);
121
+ valuePopoverValue = computed(() => {
122
+ const key = this.valuePopover()?.key;
123
+ return key ? this.tokens().values?.[key] ?? null : null;
124
+ });
125
+ valueEmbeds = new ValueEmbedPlugin({
126
+ name: 'reportValueEmbeds',
127
+ host: () => this._host.nativeElement,
128
+ values: () => this.tokens().values ?? {},
129
+ scope: () => String(this.tokens().valuePageId ?? ''),
130
+ showNames: () => this.showValueNames(),
131
+ click: (key, chip) => this._openValuePopover(key, chip),
132
+ blocked: (block) => this._showNotice({ kind: 'blocked', block }),
133
+ removed: (removal) => this._onValuesRemoved(removal),
134
+ changed: () => this.dismissNotice(),
135
+ refused: (text) => this._showNotice({ kind: 'message', text }),
136
+ });
58
137
  editorConfig = {
59
138
  floating: true,
60
139
  autofocus: true,
61
140
  placeholder: 'Type here',
141
+ plugins: [this.valueEmbeds],
62
142
  buttons: [
63
143
  {
64
144
  name: 'insertField',
@@ -67,26 +147,46 @@ export class ComponentTextComponent {
67
147
  options: TOKENS,
68
148
  click: (editor, value) => editor.html.insert(value),
69
149
  },
150
+ {
151
+ name: VALUE_NAMES_BUTTON,
152
+ title: 'Show value names',
153
+ svgKey: 'textMore',
154
+ click: () => this.showValueNames.update((names) => !names),
155
+ },
70
156
  ],
71
157
  froalaConfig: {
72
158
  toolbarButtons: [
73
159
  'paragraphFormat', 'fontSize', '|',
74
160
  'bold', 'italic', 'underline', 'strikeThrough', 'textColor', '|',
75
- 'align', 'formatUL', 'formatOL', '|',
76
- 'insertLink', 'insertField', 'clearFormatting',
161
+ 'align', 'formatUL', 'formatOL', 'insertTable', '|',
162
+ 'insertLink', 'insertField', VALUE_NAMES_BUTTON, 'clearFormatting',
77
163
  ],
164
+ // A table's popup offers only what the server keeps: no table or cell
165
+ // styles (classes) and no footer row.
166
+ tableEditButtons: [
167
+ 'tableHeader', 'tableRemove', 'tableRows', 'tableColumns', '-',
168
+ 'tableCells', 'tableCellBackground', 'tableCellVerticalAlign', 'tableCellHorizontalAlign',
169
+ ],
170
+ tableDefaultWidth: '100%',
171
+ // Both are positioned in screen space inside the canvas's CSS scale, so
172
+ // they land off the table; rows and columns are added from the table's
173
+ // popup instead.
174
+ tableResizer: false,
175
+ tableInsertHelper: false,
78
176
  paragraphFormat: { N: 'Normal', H1: 'Heading 1', H2: 'Heading 2', H3: 'Heading 3' },
79
177
  paragraphFormatSelection: true,
80
178
  fontSize: FONT_SIZES,
81
179
  fontSizeUnit: 'pt',
82
180
  fontSizeSelection: true,
83
181
  htmlAllowedTags: ALLOWED_TAGS,
84
- htmlAllowedAttrs: ['style', 'href', 'target', 'rel'],
182
+ htmlAllowedAttrs: ['style', 'href', 'target', 'rel', 'colspan', 'rowspan', ...VALUE_EMBED_ATTRIBUTES],
85
183
  htmlAllowedStyleProps: ALLOWED_STYLES,
184
+ htmlIgnoreCSSProperties: IGNORED_SHEET_STYLES,
86
185
  htmlRemoveTags: ['script', 'style'],
87
186
  // Inline styles rather than Froala's fr-* classes, which neither the
88
187
  // server nor the exports know.
89
188
  useClasses: false,
189
+ // A paste is its words only: a pasted table flattens to text.
90
190
  pastePlain: true,
91
191
  // Every keystroke reaches the model straight away, so ending the edit an
92
192
  // instant after typing never loses the last word.
@@ -97,10 +197,12 @@ export class ComponentTextComponent {
97
197
  // What the editor holds right now.
98
198
  draft = '';
99
199
  _editor = viewChild(FsHtmlEditorComponent);
200
+ _valuePopoverAnchor = viewChild('valuePopoverAnchor', { read: ElementRef });
100
201
  _sanitizer = inject(DomSanitizer);
101
202
  _host = inject(ElementRef);
102
203
  _destroyRef = inject(DestroyRef);
103
204
  _isOpen = false;
205
+ _noticeTimer = null;
104
206
  constructor() {
105
207
  // Opening seeds the draft; closing — whoever closed it: a press outside,
106
208
  // Escape, the block being deselected or edit mode ending — saves it.
@@ -116,12 +218,21 @@ export class ComponentTextComponent {
116
218
  }
117
219
  });
118
220
  });
221
+ // Chips follow the page's values and the names toggle.
222
+ effect(() => {
223
+ this.tokens();
224
+ this.showValueNames();
225
+ untracked(() => this.valueEmbeds.refresh());
226
+ });
119
227
  // A press anywhere that is not the block or the editor's own chrome ends
120
228
  // the edit. Captured, so it is seen before the canvas or a sibling
121
229
  // component acts on the same press.
122
230
  const onPress = (event) => this._onDocumentPress(event);
123
231
  document.addEventListener('pointerdown', onPress, true);
124
- this._destroyRef.onDestroy(() => document.removeEventListener('pointerdown', onPress, true));
232
+ this._destroyRef.onDestroy(() => {
233
+ document.removeEventListener('pointerdown', onPress, true);
234
+ this._clearNoticeTimer();
235
+ });
125
236
  }
126
237
  onKeydown(event) {
127
238
  if (this.editing() && event.key === 'Escape') {
@@ -129,6 +240,82 @@ export class ComponentTextComponent {
129
240
  this._close();
130
241
  }
131
242
  }
243
+ // Take a value out of the text: its settings dialog deleted it.
244
+ removeValue(key) {
245
+ this.valueEmbeds.removeKey(key);
246
+ }
247
+ // Only for a value the page has: a chip naming no value there has no
248
+ // settings to open.
249
+ openValueSettings(popover) {
250
+ popover.close();
251
+ const key = this.valuePopover()?.key;
252
+ if (key && this.tokens().values?.[key]) {
253
+ this.valueSettings.emit(key);
254
+ }
255
+ }
256
+ removeBlockedSelection() {
257
+ const notice = this.notice();
258
+ if (notice?.kind === 'blocked') {
259
+ notice.block.removeSelection?.();
260
+ }
261
+ this.dismissNotice();
262
+ }
263
+ // Put back the values an edit left unused: the editor's own undo of it.
264
+ undoValuesUnused() {
265
+ const notice = this.notice();
266
+ if (notice?.kind === 'unused') {
267
+ notice.undo();
268
+ }
269
+ this.dismissNotice();
270
+ }
271
+ dismissNotice() {
272
+ this._clearNoticeTimer();
273
+ this.notice.set(null);
274
+ }
275
+ _openValuePopover(key, chip) {
276
+ const host = this._host.nativeElement;
277
+ const hostRect = host.getBoundingClientRect();
278
+ const chipRect = chip.getBoundingClientRect();
279
+ // The canvas is CSS-scaled; the anchor sits in the block's own pixels.
280
+ const scale = host.offsetWidth ? hostRect.width / host.offsetWidth : 1;
281
+ this.valueEmbeds.hideToolbar();
282
+ this.valuePopover.set({
283
+ key,
284
+ chip,
285
+ left: (chipRect.left - hostRect.left) / scale,
286
+ top: (chipRect.top - hostRect.top) / scale,
287
+ width: chipRect.width / scale,
288
+ height: chipRect.height / scale,
289
+ });
290
+ // fs-popover opens on a click on its element: once the anchor has moved
291
+ // over the chip, click it.
292
+ setTimeout(() => this._valuePopoverAnchor()?.nativeElement.click());
293
+ }
294
+ _showNotice(notice) {
295
+ this._clearNoticeTimer();
296
+ this.notice.set(notice);
297
+ this._noticeTimer = setTimeout(() => this.notice.set(null), VALUE_BLOCK_NOTICE_MS);
298
+ }
299
+ _clearNoticeTimer() {
300
+ if (this._noticeTimer) {
301
+ clearTimeout(this._noticeTimer);
302
+ this._noticeTimer = null;
303
+ }
304
+ }
305
+ // An edit took the last chip of some values out of this block. Counted are
306
+ // the values the layer no longer reads: shown by no block, this one or
307
+ // another, nor read by a formula one of them shows. They are not deleted:
308
+ // saving html never deletes a value.
309
+ _onValuesRemoved(removal) {
310
+ const elsewhere = [...this.shownElsewhere()()];
311
+ const values = this.tokens().values ?? {};
312
+ const before = readKeys([...removal.before, ...elsewhere], values);
313
+ const after = readKeys([...removal.after, ...elsewhere], values);
314
+ const count = [...before].filter((key) => !after.has(key) && !!values[key]).length;
315
+ if (count > 0) {
316
+ this._showNotice({ kind: 'unused', count, undo: removal.undo });
317
+ }
318
+ }
132
319
  _onDocumentPress(event) {
133
320
  if (!this.editing()) {
134
321
  return;
@@ -160,18 +347,24 @@ export class ComponentTextComponent {
160
347
  return;
161
348
  }
162
349
  this._isOpen = false;
350
+ this.dismissNotice();
163
351
  if (this.draft !== this.html()) {
164
352
  this.saved.emit(this.draft);
165
353
  }
166
354
  }
167
355
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ComponentTextComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
168
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ComponentTextComponent, isStandalone: true, selector: "app-report-component-text", inputs: { html: { classPropertyName: "html", publicName: "html", isSignal: true, isRequired: false, transformFunction: null }, tokens: { classPropertyName: "tokens", publicName: "tokens", isSignal: true, isRequired: true, transformFunction: null }, editing: { classPropertyName: "editing", publicName: "editing", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { saved: "saved", editEnded: "editEnded" }, host: { listeners: { "keydown": "onKeydown($event)" }, properties: { "style.--text-size": "typeScale.body", "style.--text-h1-size": "typeScale.h1", "style.--text-h2-size": "typeScale.h2", "style.--text-h3-size": "typeScale.h3", "style.--text-color": "typeScale.color" } }, viewQueries: [{ propertyName: "_editor", first: true, predicate: FsHtmlEditorComponent, descendants: true, isSignal: true }], ngImport: i0, template: "@if (editing()) {\n <!-- Floating fs-html-editor: no frame, Froala's inline toolbar pops up over\n the text. pointerdown stays here so a press in the text never starts a\n drag of the block or a pan of the canvas. -->\n <fs-html-editor\n class=\"text-content editing\"\n [config]=\"editorConfig\"\n [(ngModel)]=\"draft\"\n (pointerdown)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\">\n </fs-html-editor>\n} @else {\n <div\n class=\"text-content\"\n [innerHTML]=\"displayHtml()\">\n </div>\n}\n", styles: ["@charset \"UTF-8\";:host{display:block;position:relative;width:100%;height:100%}.text-content{display:block;width:100%;height:100%;overflow:hidden;font-family:Arial,Helvetica,sans-serif;font-size:var(--text-size);line-height:1.25;color:var(--text-color);word-wrap:break-word}.text-content ::ng-deep p,.text-content ::ng-deep h1,.text-content ::ng-deep h2,.text-content ::ng-deep h3,.text-content ::ng-deep ul,.text-content ::ng-deep ol{margin:0}.text-content ::ng-deep h1{font-size:var(--text-h1-size)}.text-content ::ng-deep h2{font-size:var(--text-h2-size)}.text-content ::ng-deep h3{font-size:var(--text-h3-size)}.text-content ::ng-deep h1,.text-content ::ng-deep h2,.text-content ::ng-deep h3{font-weight:700;line-height:1.2}.text-content ::ng-deep ul,.text-content ::ng-deep ol{padding-left:1.4em}.text-content ::ng-deep p:empty:before{content:\"\\200b\"}.text-content ::ng-deep a{color:inherit}.text-content.editing{overflow:auto;cursor:text}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: FsHtmlEditorComponent, selector: "fs-html-editor", inputs: ["config", "disabled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
356
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ComponentTextComponent, isStandalone: true, selector: "app-report-component-text", inputs: { html: { classPropertyName: "html", publicName: "html", isSignal: true, isRequired: false, transformFunction: null }, tokens: { classPropertyName: "tokens", publicName: "tokens", isSignal: true, isRequired: true, transformFunction: null }, editing: { classPropertyName: "editing", publicName: "editing", isSignal: true, isRequired: false, transformFunction: null }, shownElsewhere: { classPropertyName: "shownElsewhere", publicName: "shownElsewhere", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { saved: "saved", editEnded: "editEnded", valueSettings: "valueSettings" }, host: { listeners: { "keydown": "onKeydown($event)" }, properties: { "style.--text-size": "typeScale.body", "style.--text-h1-size": "typeScale.h1", "style.--text-h2-size": "typeScale.h2", "style.--text-h3-size": "typeScale.h3", "style.--text-color": "typeScale.color", "style.--text-table-border": "tableLook.border", "style.--text-table-padding": "tableLook.padding", "style.--text-table-margin": "tableLook.margin" } }, viewQueries: [{ propertyName: "_editor", first: true, predicate: FsHtmlEditorComponent, descendants: true, isSignal: true }, { propertyName: "_valuePopoverAnchor", first: true, predicate: ["valuePopoverAnchor"], descendants: true, read: ElementRef, isSignal: true }], ngImport: i0, template: "@if (editing()) {\n <!-- Floating fs-html-editor: no frame, Froala's inline toolbar pops up over\n the text. pointerdown stays here so a press in the text never starts a\n drag of the block or a pan of the canvas. -->\n <fs-html-editor\n class=\"text-content editing\"\n [config]=\"editorConfig\"\n [(ngModel)]=\"draft\"\n (pointerdown)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\">\n </fs-html-editor>\n\n <!-- One notice at a time: an edit stopped because it would have removed\n values, an edit that left values no text reads, or a refused command.\n mousedown keeps the editor's focus and selection, so Undo reaches it. -->\n @if (notice(); as current) {\n <div\n class=\"value-notice fs-row.gap-sm\"\n (pointerdown)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.preventDefault()\">\n @switch (current.kind) {\n @case ('blocked') {\n @if (current.block.removeSelection) {\n <span>\n This selection includes {{ current.block.count }} {{ current.block.count === 1 ? 'value' : 'values' }}.\n </span>\n <button\n mat-button\n color=\"primary\"\n type=\"button\"\n (click)=\"removeBlockedSelection()\">\n Remove text and {{ current.block.count === 1 ? 'value' : current.block.count + ' values' }}\n </button>\n } @else {\n <span>To take a value out, select it, then press Delete.</span>\n }\n }\n @case ('unused') {\n <span>{{ current.count }} {{ current.count === 1 ? 'value' : 'values' }} moved to Not used</span>\n <button\n mat-button\n color=\"primary\"\n type=\"button\"\n (click)=\"undoValuesUnused()\">\n Undo\n </button>\n }\n @case ('message') {\n <span>{{ current.text }}</span>\n }\n }\n <button\n mat-button\n type=\"button\"\n (click)=\"dismissNotice()\">\n Dismiss\n </button>\n </div>\n }\n} @else {\n <div\n class=\"text-content\"\n [innerHTML]=\"displayHtml()\">\n </div>\n}\n\n<!-- A clicked value chip's popover: an fs-popover on an invisible anchor laid\n over the chip (the chip itself belongs to the editor). Outside the editing\n block, so a popover still open when editing ends closes the usual way. -->\n<span\n #valuePopoverAnchor\n class=\"value-popover-anchor\"\n aria-hidden=\"true\"\n fsPopover\n trigger=\"click\"\n wrapperClass=\"value-popover-wrapper\"\n [template]=\"valuePopoverTemplate\"\n [indication]=\"false\"\n [maxWidth]=\"320\"\n [style.left.px]=\"valuePopover()?.left\"\n [style.top.px]=\"valuePopover()?.top\"\n [style.width.px]=\"valuePopover()?.width\"\n [style.height.px]=\"valuePopover()?.height\">\n</span>\n<ng-template\n #valuePopoverTemplate\n let-popover=\"popover\">\n <!-- What the value is, and its settings (where it can also be deleted); a\n chip naming no value on the page has no settings. -->\n <div class=\"value-popover fs-row\">\n <div class=\"fs-flex\">\n <div class=\"value-popover-name\">{{ valuePopoverValue()?.name ?? valuePopover()?.key }}</div>\n @if (!valuePopoverValue()) {\n <div class=\"small\">Not a value on this page</div>\n }\n </div>\n @if (valuePopoverValue()) {\n <button\n mat-icon-button\n type=\"button\"\n class=\"value-popover-settings\"\n matTooltip=\"Settings\"\n (click)=\"openValueSettings(popover)\">\n <mat-icon>settings</mat-icon>\n </button>\n }\n </div>\n</ng-template>\n", styles: ["@charset \"UTF-8\";:host{display:block;position:relative;width:100%;height:100%}.text-content{display:block;width:100%;height:100%;overflow:hidden;font-family:Arial,Helvetica,sans-serif;font-size:var(--text-size);line-height:1.25;color:var(--text-color);word-wrap:break-word;letter-spacing:normal;word-spacing:normal;font-weight:400;font-style:normal;text-transform:none;white-space:normal}.text-content ::ng-deep p,.text-content ::ng-deep h1,.text-content ::ng-deep h2,.text-content ::ng-deep h3,.text-content ::ng-deep ul,.text-content ::ng-deep ol{margin:0}.text-content ::ng-deep h1{font-size:var(--text-h1-size)}.text-content ::ng-deep h2{font-size:var(--text-h2-size)}.text-content ::ng-deep h3{font-size:var(--text-h3-size)}.text-content ::ng-deep h1,.text-content ::ng-deep h2,.text-content ::ng-deep h3{font-weight:700;line-height:1.2}.text-content ::ng-deep ul,.text-content ::ng-deep ol{padding-left:1.4em}.text-content ::ng-deep p:empty:before{content:\"\\200b\"}.text-content ::ng-deep a{color:inherit}.text-content ::ng-deep table{border-collapse:collapse;margin:var(--text-table-margin) 0}.text-content ::ng-deep th,.text-content ::ng-deep td{border:var(--text-table-border);padding:var(--text-table-padding);vertical-align:middle;text-align:left}.text-content ::ng-deep th{text-align:center;font-weight:700}.text-content.editing{overflow:auto;cursor:text}.text-content.editing ::ng-deep [data-embed-key]{padding:0 2px;border-radius:3px;background-color:#4e79a729;cursor:pointer;-webkit-user-select:all;user-select:all}.text-content.editing ::ng-deep [data-embed-key]:hover{background-color:#4e79a747}.text-content.editing ::ng-deep [data-embed-missing]{background-color:#e1575924;outline:1px dashed rgba(225,87,89,.7)}.text-content.editing ::ng-deep th,.text-content.editing ::ng-deep tfoot td{background-color:transparent}.text-content.editing ::ng-deep .fr-table-selector{display:none}.text-content.editing ::ng-deep .fr-table-selection-hover{outline:none}.value-popover-anchor{position:absolute;pointer-events:none}::ng-deep .value-popover-wrapper .popover-content{padding:15px!important}.value-popover{gap:15px}.value-popover-name{font-weight:600}.value-popover-settings{--mdc-icon-button-state-layer-size: 24px;width:24px;height:24px;padding:0}.value-notice{position:absolute;top:100%;left:0;z-index:2;margin-top:4px;padding:2px 4px 2px 10px;border:1px solid #d9dee3;border-radius:4px;background:#fff;white-space:nowrap;font-family:Arial,Helvetica,sans-serif}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: FsHtmlEditorComponent, selector: "fs-html-editor", inputs: ["config", "disabled"] }, { kind: "directive", type: FsPopoverDirective, selector: "[fsPopover]", inputs: ["text", "template", "data", "leaveDelay", "showDelay", "maxWidth", "maxHeight", "wrapperClass", "autoShow", "autoClose", "loadingDiameter", "loading", "indication", "position", "theme", "size", "trigger", "enabled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
169
357
  }
170
358
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ComponentTextComponent, decorators: [{
171
359
  type: Component,
172
360
  args: [{ selector: 'app-report-component-text', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
173
361
  FormsModule,
362
+ MatButton,
363
+ MatIconButton,
364
+ MatIcon,
365
+ MatTooltip,
174
366
  FsHtmlEditorComponent,
367
+ FsPopoverDirective,
175
368
  ], host: {
176
369
  '(keydown)': 'onKeydown($event)',
177
370
  // The document type scale comes from the same constants the PowerPoint and
@@ -181,6 +374,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
181
374
  '[style.--text-h2-size]': 'typeScale.h2',
182
375
  '[style.--text-h3-size]': 'typeScale.h3',
183
376
  '[style.--text-color]': 'typeScale.color',
184
- }, template: "@if (editing()) {\n <!-- Floating fs-html-editor: no frame, Froala's inline toolbar pops up over\n the text. pointerdown stays here so a press in the text never starts a\n drag of the block or a pan of the canvas. -->\n <fs-html-editor\n class=\"text-content editing\"\n [config]=\"editorConfig\"\n [(ngModel)]=\"draft\"\n (pointerdown)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\">\n </fs-html-editor>\n} @else {\n <div\n class=\"text-content\"\n [innerHTML]=\"displayHtml()\">\n </div>\n}\n", styles: ["@charset \"UTF-8\";:host{display:block;position:relative;width:100%;height:100%}.text-content{display:block;width:100%;height:100%;overflow:hidden;font-family:Arial,Helvetica,sans-serif;font-size:var(--text-size);line-height:1.25;color:var(--text-color);word-wrap:break-word}.text-content ::ng-deep p,.text-content ::ng-deep h1,.text-content ::ng-deep h2,.text-content ::ng-deep h3,.text-content ::ng-deep ul,.text-content ::ng-deep ol{margin:0}.text-content ::ng-deep h1{font-size:var(--text-h1-size)}.text-content ::ng-deep h2{font-size:var(--text-h2-size)}.text-content ::ng-deep h3{font-size:var(--text-h3-size)}.text-content ::ng-deep h1,.text-content ::ng-deep h2,.text-content ::ng-deep h3{font-weight:700;line-height:1.2}.text-content ::ng-deep ul,.text-content ::ng-deep ol{padding-left:1.4em}.text-content ::ng-deep p:empty:before{content:\"\\200b\"}.text-content ::ng-deep a{color:inherit}.text-content.editing{overflow:auto;cursor:text}\n"] }]
377
+ // A table's grid comes from them the same way.
378
+ '[style.--text-table-border]': 'tableLook.border',
379
+ '[style.--text-table-padding]': 'tableLook.padding',
380
+ '[style.--text-table-margin]': 'tableLook.margin',
381
+ }, template: "@if (editing()) {\n <!-- Floating fs-html-editor: no frame, Froala's inline toolbar pops up over\n the text. pointerdown stays here so a press in the text never starts a\n drag of the block or a pan of the canvas. -->\n <fs-html-editor\n class=\"text-content editing\"\n [config]=\"editorConfig\"\n [(ngModel)]=\"draft\"\n (pointerdown)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\">\n </fs-html-editor>\n\n <!-- One notice at a time: an edit stopped because it would have removed\n values, an edit that left values no text reads, or a refused command.\n mousedown keeps the editor's focus and selection, so Undo reaches it. -->\n @if (notice(); as current) {\n <div\n class=\"value-notice fs-row.gap-sm\"\n (pointerdown)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.preventDefault()\">\n @switch (current.kind) {\n @case ('blocked') {\n @if (current.block.removeSelection) {\n <span>\n This selection includes {{ current.block.count }} {{ current.block.count === 1 ? 'value' : 'values' }}.\n </span>\n <button\n mat-button\n color=\"primary\"\n type=\"button\"\n (click)=\"removeBlockedSelection()\">\n Remove text and {{ current.block.count === 1 ? 'value' : current.block.count + ' values' }}\n </button>\n } @else {\n <span>To take a value out, select it, then press Delete.</span>\n }\n }\n @case ('unused') {\n <span>{{ current.count }} {{ current.count === 1 ? 'value' : 'values' }} moved to Not used</span>\n <button\n mat-button\n color=\"primary\"\n type=\"button\"\n (click)=\"undoValuesUnused()\">\n Undo\n </button>\n }\n @case ('message') {\n <span>{{ current.text }}</span>\n }\n }\n <button\n mat-button\n type=\"button\"\n (click)=\"dismissNotice()\">\n Dismiss\n </button>\n </div>\n }\n} @else {\n <div\n class=\"text-content\"\n [innerHTML]=\"displayHtml()\">\n </div>\n}\n\n<!-- A clicked value chip's popover: an fs-popover on an invisible anchor laid\n over the chip (the chip itself belongs to the editor). Outside the editing\n block, so a popover still open when editing ends closes the usual way. -->\n<span\n #valuePopoverAnchor\n class=\"value-popover-anchor\"\n aria-hidden=\"true\"\n fsPopover\n trigger=\"click\"\n wrapperClass=\"value-popover-wrapper\"\n [template]=\"valuePopoverTemplate\"\n [indication]=\"false\"\n [maxWidth]=\"320\"\n [style.left.px]=\"valuePopover()?.left\"\n [style.top.px]=\"valuePopover()?.top\"\n [style.width.px]=\"valuePopover()?.width\"\n [style.height.px]=\"valuePopover()?.height\">\n</span>\n<ng-template\n #valuePopoverTemplate\n let-popover=\"popover\">\n <!-- What the value is, and its settings (where it can also be deleted); a\n chip naming no value on the page has no settings. -->\n <div class=\"value-popover fs-row\">\n <div class=\"fs-flex\">\n <div class=\"value-popover-name\">{{ valuePopoverValue()?.name ?? valuePopover()?.key }}</div>\n @if (!valuePopoverValue()) {\n <div class=\"small\">Not a value on this page</div>\n }\n </div>\n @if (valuePopoverValue()) {\n <button\n mat-icon-button\n type=\"button\"\n class=\"value-popover-settings\"\n matTooltip=\"Settings\"\n (click)=\"openValueSettings(popover)\">\n <mat-icon>settings</mat-icon>\n </button>\n }\n </div>\n</ng-template>\n", styles: ["@charset \"UTF-8\";:host{display:block;position:relative;width:100%;height:100%}.text-content{display:block;width:100%;height:100%;overflow:hidden;font-family:Arial,Helvetica,sans-serif;font-size:var(--text-size);line-height:1.25;color:var(--text-color);word-wrap:break-word;letter-spacing:normal;word-spacing:normal;font-weight:400;font-style:normal;text-transform:none;white-space:normal}.text-content ::ng-deep p,.text-content ::ng-deep h1,.text-content ::ng-deep h2,.text-content ::ng-deep h3,.text-content ::ng-deep ul,.text-content ::ng-deep ol{margin:0}.text-content ::ng-deep h1{font-size:var(--text-h1-size)}.text-content ::ng-deep h2{font-size:var(--text-h2-size)}.text-content ::ng-deep h3{font-size:var(--text-h3-size)}.text-content ::ng-deep h1,.text-content ::ng-deep h2,.text-content ::ng-deep h3{font-weight:700;line-height:1.2}.text-content ::ng-deep ul,.text-content ::ng-deep ol{padding-left:1.4em}.text-content ::ng-deep p:empty:before{content:\"\\200b\"}.text-content ::ng-deep a{color:inherit}.text-content ::ng-deep table{border-collapse:collapse;margin:var(--text-table-margin) 0}.text-content ::ng-deep th,.text-content ::ng-deep td{border:var(--text-table-border);padding:var(--text-table-padding);vertical-align:middle;text-align:left}.text-content ::ng-deep th{text-align:center;font-weight:700}.text-content.editing{overflow:auto;cursor:text}.text-content.editing ::ng-deep [data-embed-key]{padding:0 2px;border-radius:3px;background-color:#4e79a729;cursor:pointer;-webkit-user-select:all;user-select:all}.text-content.editing ::ng-deep [data-embed-key]:hover{background-color:#4e79a747}.text-content.editing ::ng-deep [data-embed-missing]{background-color:#e1575924;outline:1px dashed rgba(225,87,89,.7)}.text-content.editing ::ng-deep th,.text-content.editing ::ng-deep tfoot td{background-color:transparent}.text-content.editing ::ng-deep .fr-table-selector{display:none}.text-content.editing ::ng-deep .fr-table-selection-hover{outline:none}.value-popover-anchor{position:absolute;pointer-events:none}::ng-deep .value-popover-wrapper .popover-content{padding:15px!important}.value-popover{gap:15px}.value-popover-name{font-weight:600}.value-popover-settings{--mdc-icon-button-state-layer-size: 24px;width:24px;height:24px;padding:0}.value-notice{position:absolute;top:100%;left:0;z-index:2;margin-top:4px;padding:2px 4px 2px 10px;border:1px solid #d9dee3;border-radius:4px;background:#fff;white-space:nowrap;font-family:Arial,Helvetica,sans-serif}\n"] }]
185
382
  }], ctorParameters: () => [] });
186
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tcG9uZW50LXRleHQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL2NvbXBvbmVudHMvY29tcG9uZW50LXRleHQvY29tcG9uZW50LXRleHQuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL2NvbXBvbmVudHMvY29tcG9uZW50LXRleHQvY29tcG9uZW50LXRleHQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLHVCQUF1QixFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQ25HLFNBQVMsRUFBRSxTQUFTLEdBQ3JCLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM3QyxPQUFPLEVBQUUsWUFBWSxFQUFZLE1BQU0sMkJBQTJCLENBQUM7QUFFbkUsT0FBTyxFQUFFLHFCQUFxQixFQUFzQixNQUFNLHlCQUF5QixDQUFDO0FBRXBGLE9BQU8sRUFDTCxrQkFBa0IsRUFBRSxpQkFBaUIsRUFBRSxrQkFBa0IsRUFBb0IsY0FBYyxHQUM1RixNQUFNLFlBQVksQ0FBQzs7O0FBR3BCLHNFQUFzRTtBQUN0RSxNQUFNLFVBQVUsR0FBRyxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztBQUV4SCw4RUFBOEU7QUFDOUUsTUFBTSxNQUFNLEdBQUc7SUFDYixpQkFBaUIs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Vzt3QkFDWCxxQkFBcUI7cUJBQ3RCLFFBQ0s7d0JBQ0osV0FBVyxFQUFFLG1CQUFtQjt3QkFDaEMsMkVBQTJFO3dCQUMzRSxrRUFBa0U7d0JBQ2xFLHFCQUFxQixFQUFFLGdCQUFnQjt3QkFDdkMsd0JBQXdCLEVBQUUsY0FBYzt3QkFDeEMsd0JBQXdCLEVBQUUsY0FBYzt3QkFDeEMsd0JBQXdCLEVBQUUsY0FBYzt3QkFDeEMsc0JBQXNCLEVBQUUsaUJBQWlCO3FCQUMxQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDb21wb25lbnQsIERlc3Ryb3lSZWYsIEVsZW1lbnRSZWYsIGNvbXB1dGVkLCBlZmZlY3QsIGluamVjdCwgaW5wdXQsIG91dHB1dCxcbiAgdW50cmFja2VkLCB2aWV3Q2hpbGQsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRm9ybXNNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBEb21TYW5pdGl6ZXIsIFNhZmVIdG1sIH0gZnJvbSAnQGFuZ3VsYXIvcGxhdGZvcm0tYnJvd3Nlcic7XG5cbmltcG9ydCB7IEZzSHRtbEVkaXRvckNvbXBvbmVudCwgRnNIdG1sRWRpdG9yQ29uZmlnIH0gZnJvbSAnQGZpcmVzdGl0Y2gvaHRtbC1lZGl0b3InO1xuXG5pbXBvcnQge1xuICBERUZBVUxUX1RFWFRfQ09MT1IsIERFRkFVTFRfVEVYVF9TSVpFLCBIRUFESU5HX1RFWFRfU0laRVMsIFRleHRUb2tlbkNvbnRleHQsIGZpbGxUZXh0VG9rZW5zLFxufSBmcm9tICcuLi8uLi90ZXh0JztcblxuXG4vLyBQb2ludCBzaXplcyDigJQgdGhlIHJlcG9ydCdzIHR5cGUgdW5pdCAoMToxIHdpdGggUG93ZXJQb2ludCBhbmQgUERGKS5cbmNvbnN0IEZPTlRfU0laRVMgPSBbJzgnLCAnOScsICcxMCcsICcxMScsICcxMicsICcxNCcsICcxNicsICcxOCcsICcyMCcsICcyNCcsICcyOCcsICczMicsICczNicsICc0MCcsICc0OCcsICc2MCcsICc3MiddO1xuXG4vLyBUaGUgZmllbGRzIGEgYmxvY2sgY2FuIGNhcnJ5LCBmaWxsZWQgcGVyIHBhZ2Ugb24gdGhlIGNhbnZhcyBhbmQgaW4gZXhwb3J0cy5cbmNvbnN0IFRPS0VOUyA9IHtcbiAgJ3t7cGFnZS5udW1iZXJ9fSc6ICdQYWdlIG51bWJlcicsXG4gICd7e3BhZ2UubmFtZX19JzogJ1BhZ2UgbmFtZScsXG4gICd7e3JlcG9ydC5uYW1lfX0nOiAnUmVwb3J0IG5hbWUnLFxufTtcblxuLy8gV2hhdCB0aGUgZWRpdG9yIG1heSBwcm9kdWNlIOKAlCBleGFjdGx5IHdoYXQgdGhlIHNlcnZlciBrZWVwc1xuLy8gKFJlcG9ydFRleHRIdG1sKSBhbmQgdGhlIGV4cG9ydHMgZHJhdy4gQW55dGhpbmcgZWxzZSB3b3VsZCBlZGl0IGZpbmUgYW5kXG4vLyB0aGVuIHZhbmlzaCBvbiBzYXZlLlxuY29uc3QgQUxMT1dFRF9UQUdTID0gWydwJywgJ2gxJywgJ2gyJywgJ2gzJywgJ2JyJywgJ3N0cm9uZycsICdlbScsICd1JywgJ3MnLCAnc3BhbicsICdhJywgJ3VsJywgJ29sJywgJ2xpJ107XG5jb25zdCBBTExPV0VEX1NUWUxFUyA9IFsnY29sb3InLCAnYmFja2dyb3VuZC1jb2xvcicsICdmb250LXNpemUnLCAnZm9udC13ZWlnaHQnLCAnZm9udC1zdHlsZScsICd0ZXh0LWRlY29yYXRpb24nLCAnZm9udC1mYW1pbHknLCAndGV4dC1hbGlnbiddO1xuXG4vLyBGcm9hbGEncyBvd24gdG9vbGJhcnMgYW5kIHBvcHVwcyBsaXZlIG9uIHRoZSBib2R5LCBub3QgaW4gdGhlIGJsb2NrOyBhIHByZXNzXG4vLyBvbiBhbnkgb2YgdGhlbSBpcyBzdGlsbCBwYXJ0IG9mIGVkaXRpbmcgdGhlIGJsb2NrLlxuY29uc3QgRURJVE9SX0NIUk9NRSA9ICcuZnItdG9vbGJhciwgLmZyLXBvcHVwLCAuZnItZHJvcGRvd24tbWVudSwgLmZyLW1vZGFsLCAuZnItdG9vbHRpcCc7XG5cbi8vIEEgdGV4dCBibG9jazogYXV0aG9yZWQgcmljaCB0ZXh0IG9uIHRoZSBwYWdlLlxuLy9cbi8vIFJlYWQgbW9kZSByZW5kZXJzIHRoZSBzdG9yZWQgaHRtbCB3aXRoIGl0cyB0b2tlbnMgKHt7cGFnZS5udW1iZXJ9fSwg4oCmKSBmaWxsZWRcbi8vIGZvciB0aGUgcGFnZSBpdCBpcyBkcmF3biBvbi4gVGhlIGh0bWwgaGFzIGFscmVhZHkgYmVlbiByZWJ1aWx0IHNlcnZlci1zaWRlXG4vLyBmcm9tIGFuIGFsbG93bGlzdCAoUmVwb3J0VGV4dEh0bWwpLCB3aGljaCBpcyB3aGF0IG1ha2VzIGJpbmRpbmcgaXQgYXMgdHJ1c3RlZFxuLy8gbWFya3VwIHNhZmUg4oCUIEFuZ3VsYXIncyBvd24gc2FuaXRpemVyIHdvdWxkIHN0cmlwIHRoZSBpbmxpbmUgc3R5bGVzIHRoYXQgQVJFXG4vLyB0aGUgZm9ybWF0dGluZy5cbi8vXG4vLyBFZGl0IG1vZGUgbW91bnRzIDxmcy1odG1sLWVkaXRvcj4gaW4gaXRzIGZsb2F0aW5nIG1vZGUgaW4gcGxhY2Ug4oCUIHRoZSB3b3Jkc1xuLy8gc3RheSB3aGVyZSB0aGV5IHNpdCBvbiB0aGUgc2xpZGUg4oCUIHdpdGggRnJvYWxhJ3MgaW5saW5lIHRvb2xiYXIgcG9wcGluZyB1cFxuLy8gb3ZlciB0aGVtLiBUaGUgZWRpdG9yIGV4aXN0cyBvbmx5IHdoaWxlIGVkaXRpbmc7IHRoZSByYXcgaHRtbCBpcyBlZGl0ZWQsIHNvIGFcbi8vIHRva2VuIHJlYWRzIGFzIHt7cGFnZS5udW1iZXJ9fSB3aGlsZSBlZGl0aW5nIGFuZCBhcyB0aGUgbnVtYmVyIG90aGVyd2lzZS5cbi8vXG4vLyBUaGUgYmxvY2sgbmV2ZXIgc2F2ZXMgb24gaXRzIG93bjogaXQgZW1pdHMgdGhlIG5ldyBodG1sIHdoZW4gZWRpdGluZyBlbmRzXG4vLyBhbmQgdGhlIGhvc3QgcGVyc2lzdHMgaXQuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdhcHAtcmVwb3J0LWNvbXBvbmVudC10ZXh0JyxcbiAgdGVtcGxhdGVVcmw6ICcuL2NvbXBvbmVudC10ZXh0LmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vY29tcG9uZW50LXRleHQuY29tcG9uZW50LnNjc3MnXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtcbiAgICBGb3Jtc01vZHVsZSxcbiAgICBGc0h0bWxFZGl0b3JDb21wb25lbnQsXG4gIF0sXG4gIGhvc3Q6IHtcbiAgICAnKGtleWRvd24pJzogJ29uS2V5ZG93bigkZXZlbnQpJyxcbiAgICAvLyBUaGUgZG9jdW1lbnQgdHlwZSBzY2FsZSBjb21lcyBmcm9tIHRoZSBzYW1lIGNvbnN0YW50cyB0aGUgUG93ZXJQb2ludCBhbmRcbiAgICAvLyBQREYgZXhwb3J0cyBkcmF3IHdpdGgsIHNvIGEgcGFyYWdyYXBoIGlzIG9uZSBzaXplIGluIGFsbCB0aHJlZS5cbiAgICAnW3N0eWxlLi0tdGV4dC1zaXplXSc6ICd0eXBlU2NhbGUuYm9keScsXG4gICAgJ1tzdHlsZS4tLXRleHQtaDEtc2l6ZV0nOiAndHlwZVNjYWxlLmgxJyxcbiAgICAnW3N0eWxlLi0tdGV4dC1oMi1zaXplXSc6ICd0eXBlU2NhbGUuaDInLFxuICAgICdbc3R5bGUuLS10ZXh0LWgzLXNpemVdJzogJ3R5cGVTY2FsZS5oMycsXG4gICAgJ1tzdHlsZS4tLXRleHQtY29sb3JdJzogJ3R5cGVTY2FsZS5jb2xvcicsXG4gIH0sXG59KVxuZXhwb3J0IGNsYXNzIENvbXBvbmVudFRleHRDb21wb25lbnQge1xuXG4gIC8vIFRoZSBibG9jaydzIHN0b3JlZCBodG1sIChjb25maWcuaHRtbCkuIEl0cyBvd24gaW5wdXQgcmF0aGVyIHRoYW4gcmVhZCBvZmZcbiAgLy8gdGhlIGNvbXBvbmVudCwgc28gYSBzYXZlZCBlZGl0IOKAlCBhIG5ldyBzdHJpbmcgb24gdGhlIHNhbWUgY29tcG9uZW50IOKAlCBpc1xuICAvLyBzZWVuIGFzIGEgY2hhbmdlIGFuZCByZXBhaW50cy5cbiAgcHVibGljIHJlYWRvbmx5IGh0bWwgPSBpbnB1dCgnJyk7XG4gIHB1YmxpYyByZWFkb25seSB0b2tlbnMgPSBpbnB1dC5yZXF1aXJlZDxUZXh0VG9rZW5Db250ZXh0PigpO1xuICBwdWJsaWMgcmVhZG9ubHkgZWRpdGluZyA9IGlucHV0KGZhbHNlKTtcblxuICAvLyBUaGUgaHRtbCBhZnRlciBhbiBlZGl0LCBvbmx5IHdoZW4gaXQgY2hhbmdlZC5cbiAgcHVibGljIHJlYWRvbmx5IHNhdmVkID0gb3V0cHV0PHN0cmluZz4oKTtcblxuICAvLyBBIHByZXNzIGxhbmRlZCBvdXRzaWRlIHRoZSBibG9jayAob3IgRXNjYXBlKTogdGhlIGhvc3QgZW5kcyBlZGl0IG1vZGUsXG4gIC8vIHdoaWNoIHNhdmVzLlxuICBwdWJsaWMgcmVhZG9ubHkgZWRpdEVuZGVkID0gb3V0cHV0PHZvaWQ+KCk7XG5cbiAgcHVibGljIHJlYWRvbmx5IHR5cGVTY2FsZSA9IHtcbiAgICBib2R5OiBgJHtERUZBVUxUX1RFWFRfU0laRX1wdGAsXG4gICAgaDE6IGAke0hFQURJTkdfVEVYVF9TSVpFU1sxXX1wdGAsXG4gICAgaDI6IGAke0hFQURJTkdfVEVYVF9TSVpFU1syXX1wdGAsXG4gICAgaDM6IGAke0hFQURJTkdfVEVYVF9TSVpFU1szXX1wdGAsXG4gICAgY29sb3I6IERFRkFVTFRfVEVYVF9DT0xPUixcbiAgfTtcblxuICBwdWJsaWMgcmVhZG9ubHkgZWRpdG9yQ29uZmlnOiBGc0h0bWxFZGl0b3JDb25maWcgPSB7XG4gICAgZmxvYXRpbmc6IHRydWUsXG4gICAgYXV0b2ZvY3VzOiB0cnVlLFxuICAgIHBsYWNlaG9sZGVyOiAnVHlwZSBoZXJlJyxcbiAgICBidXR0b25zOiBbXG4gICAgICB7XG4gICAgICAgIG5hbWU6ICdpbnNlcnRGaWVsZCcsXG4gICAgICAgIHRpdGxlOiAnSW5zZXJ0IGZpZWxkJyxcbiAgICAgICAgc3ZnS2V5OiAndGFncycsXG4gICAgICAgIG9wdGlvbnM6IFRPS0VOUyxcbiAgICAgICAgY2xpY2s6IChlZGl0b3IsIHZhbHVlKSA9PiBlZGl0b3IuaHRtbC5pbnNlcnQodmFsdWUpLFxuICAgICAgfSxcbiAgICBdLFxuICAgIGZyb2FsYUNvbmZpZzoge1xuICAgICAgdG9vbGJhckJ1dHRvbnM6IFtcbiAgICAgICAgJ3BhcmFncmFwaEZvcm1hdCcsICdmb250U2l6ZScsICd8JyxcbiAgICAgICAgJ2JvbGQnLCAnaXRhbGljJywgJ3VuZGVybGluZScsICdzdHJpa2VUaHJvdWdoJywgJ3RleHRDb2xvcicsICd8JyxcbiAgICAgICAgJ2FsaWduJywgJ2Zvcm1hdFVMJywgJ2Zvcm1hdE9MJywgJ3wnLFxuICAgICAgICAnaW5zZXJ0TGluaycsICdpbnNlcnRGaWVsZCcsICdjbGVhckZvcm1hdHRpbmcnLFxuICAgICAgXSxcbiAgICAgIHBhcmFncmFwaEZvcm1hdDogeyBOOiAnTm9ybWFsJywgSDE6ICdIZWFkaW5nIDEnLCBIMjogJ0hlYWRpbmcgMicsIEgzOiAnSGVhZGluZyAzJyB9LFxuICAgICAgcGFyYWdyYXBoRm9ybWF0U2VsZWN0aW9uOiB0cnVlLFxuICAgICAgZm9udFNpemU6IEZPTlRfU0laRVMsXG4gICAgICBmb250U2l6ZVVuaXQ6ICdwdCcsXG4gICAgICBmb250U2l6ZVNlbGVjdGlvbjogdHJ1ZSxcbiAgICAgIGh0bWxBbGxvd2VkVGFnczogQUxMT1dFRF9UQUdTLFxuICAgICAgaHRtbEFsbG93ZWRBdHRyczogWydzdHlsZScsICdocmVmJywgJ3RhcmdldCcsICdyZWwnXSxcbiAgICAgIGh0bWxBbGxvd2VkU3R5bGVQcm9wczogQUxMT1dFRF9TVFlMRVMsXG4gICAgICBodG1sUmVtb3ZlVGFnczogWydzY3JpcHQnLCAnc3R5bGUnXSxcbiAgICAgIC8vIElubGluZSBzdHlsZXMgcmF0aGVyIHRoYW4gRnJvYWxhJ3MgZnItKiBjbGFzc2VzLCB3aGljaCBuZWl0aGVyIHRoZVxuICAgICAgLy8gc2VydmVyIG5vciB0aGUgZXhwb3J0cyBrbm93LlxuICAgICAgdXNlQ2xhc3NlczogZmFsc2UsXG4gICAgICBwYXN0ZVBsYWluOiB0cnVlLFxuICAgICAgLy8gRXZlcnkga2V5c3Ryb2tlIHJlYWNoZXMgdGhlIG1vZGVsIHN0cmFpZ2h0IGF3YXksIHNvIGVuZGluZyB0aGUgZWRpdCBhblxuICAgICAgLy8gaW5zdGFudCBhZnRlciB0eXBpbmcgbmV2ZXIgbG9zZXMgdGhlIGxhc3Qgd29yZC5cbiAgICAgIHR5cGluZ1RpbWVyOiAwLFxuICAgIH0sXG4gIH07XG5cbiAgcHVibGljIHJlYWRvbmx5IGRpc3BsYXlIdG1sID0gY29tcHV0ZWQ8U2FmZUh0bWw+KCgpID0+IHRoaXMuX3Nhbml0aXplci5ieXBhc3NTZWN1cml0eVRydXN0SHRtbChcbiAgICBmaWxsVGV4dFRva2Vucyh0aGlzLmh0bWwoKSwgdGhpcy50b2tlbnMoKSksXG4gICkpO1xuXG4gIC8vIFdoYXQgdGhlIGVkaXRvciBob2xkcyByaWdodCBub3cuXG4gIHB1YmxpYyBkcmFmdCA9ICcnO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgX2VkaXRvciA9IHZpZXdDaGlsZChGc0h0bWxFZGl0b3JDb21wb25lbnQpO1xuICBwcml2YXRlIHJlYWRvbmx5IF9zYW5pdGl6ZXIgPSBpbmplY3QoRG9tU2FuaXRpemVyKTtcbiAgcHJpdmF0ZSByZWFkb25seSBfaG9zdDogRWxlbWVudFJlZjxIVE1MRWxlbWVudD4gPSBpbmplY3QoRWxlbWVudFJlZik7XG4gIHByaXZhdGUgcmVhZG9ubHkgX2Rlc3Ryb3lSZWYgPSBpbmplY3QoRGVzdHJveVJlZik7XG4gIHByaXZhdGUgX2lzT3BlbiA9IGZhbHNlO1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIC8vIE9wZW5pbmcgc2VlZHMgdGhlIGRyYWZ0OyBjbG9zaW5nIOKAlCB3aG9ldmVyIGNsb3NlZCBpdDogYSBwcmVzcyBvdXRzaWRlLFxuICAgIC8vIEVzY2FwZSwgdGhlIGJsb2NrIGJlaW5nIGRlc2VsZWN0ZWQgb3IgZWRpdCBtb2RlIGVuZGluZyDigJQgc2F2ZXMgaXQuXG4gICAgZWZmZWN0KCgpID0+IHtcbiAgICAgIGNvbnN0IGVkaXRpbmcgPSB0aGlzLmVkaXRpbmcoKTtcblxuICAgICAgdW50cmFja2VkKCgpID0+IHtcbiAgICAgICAgaWYgKGVkaXRpbmcgJiYgIXRoaXMuX2lzT3Blbikge1xuICAgICAgICAgIHRoaXMuX2lzT3BlbiA9IHRydWU7XG4gICAgICAgICAgdGhpcy5kcmFmdCA9IHRoaXMuaHRtbCgpO1xuICAgICAgICB9IGVsc2UgaWYgKCFlZGl0aW5nICYmIHRoaXMuX2lzT3Blbikge1xuICAgICAgICAgIHRoaXMuX2ZpbmlzaCgpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIC8vIEEgcHJlc3MgYW55d2hlcmUgdGhhdCBpcyBub3QgdGhlIGJsb2NrIG9yIHRoZSBlZGl0b3IncyBvd24gY2hyb21lIGVuZHNcbiAgICAvLyB0aGUgZWRpdC4gQ2FwdHVyZWQsIHNvIGl0IGlzIHNlZW4gYmVmb3JlIHRoZSBjYW52YXMgb3IgYSBzaWJsaW5nXG4gICAgLy8gY29tcG9uZW50IGFjdHMgb24gdGhlIHNhbWUgcHJlc3MuXG4gICAgY29uc3Qgb25QcmVzcyA9IChldmVudDogUG9pbnRlckV2ZW50KSA9PiB0aGlzLl9vbkRvY3VtZW50UHJlc3MoZXZlbnQpO1xuICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3BvaW50ZXJkb3duJywgb25QcmVzcywgdHJ1ZSk7XG4gICAgdGhpcy5fZGVzdHJveVJlZi5vbkRlc3Ryb3koKCkgPT4gZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigncG9pbnRlcmRvd24nLCBvblByZXNzLCB0cnVlKSk7XG4gIH1cblxuICBwdWJsaWMgb25LZXlkb3duKGV2ZW50OiBLZXlib2FyZEV2ZW50KTogdm9pZCB7XG4gICAgaWYgKHRoaXMuZWRpdGluZygpICYmIGV2ZW50LmtleSA9PT0gJ0VzY2FwZScpIHtcbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICB0aGlzLl9jbG9zZSgpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX29uRG9jdW1lbnRQcmVzcyhldmVudDogUG9pbnRlckV2ZW50KTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmVkaXRpbmcoKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHRhcmdldCA9IGV2ZW50LnRhcmdldCBhcyBIVE1MRWxlbWVudCB8IG51bGw7XG4gICAgaWYgKHRhcmdldCAmJiAodGhpcy5faG9zdC5uYXRpdmVFbGVtZW50LmNvbnRhaW5zKHRhcmdldCkgfHwgdGFyZ2V0LmNsb3Nlc3QoRURJVE9SX0NIUk9NRSkpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5fY2xvc2UoKTtcbiAgfVxuXG4gIC8vIFNhdmUgTk9XLCB0aGVuIGFzayB0aGUgaG9zdCB0byBjbG9zZS4gU2F2aW5nIGhlcmUgcmF0aGVyIHRoYW4gd2FpdGluZyBmb3JcbiAgLy8gdGhlIGVkaXRpbmcgaW5wdXQgdG8gZmxpcCBtYXR0ZXJzOiB0aGUgc2FtZSBwcmVzcyBtYXkgYmUgb24gYSBwYWdlIHRhYixcbiAgLy8gYW5kIGJ5IHRoZSB0aW1lIHRoZSBpbnB1dCBjaGFuZ2VkIHRoaXMgYmxvY2sgY291bGQgYWxyZWFkeSBiZSBkZXN0cm95ZWQsXG4gIC8vIHdpdGggaXRzIGVkaXQgZ29uZS5cbiAgcHJpdmF0ZSBfY2xvc2UoKTogdm9pZCB7XG4gICAgdGhpcy5fc3luY0RyYWZ0KCk7XG4gICAgdGhpcy5fZmluaXNoKCk7XG4gICAgdGhpcy5lZGl0RW5kZWQuZW1pdCgpO1xuICB9XG5cbiAgLy8gUmVhZCB0aGUgZWRpdG9yIGRpcmVjdGx5IHJhdGhlciB0aGFuIHRydXN0aW5nIHRoZSBsYXN0IG1vZGVsIHVwZGF0ZS5cbiAgcHJpdmF0ZSBfc3luY0RyYWZ0KCk6IHZvaWQge1xuICAgIGNvbnN0IGh0bWwgPSB0aGlzLl9lZGl0b3IoKT8uZWRpdG9yPy5odG1sPy5nZXQoKTtcbiAgICBpZiAodHlwZW9mIGh0bWwgPT09ICdzdHJpbmcnKSB7XG4gICAgICB0aGlzLmRyYWZ0ID0gaHRtbDtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9maW5pc2goKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLl9pc09wZW4pIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLl9pc09wZW4gPSBmYWxzZTtcbiAgICBpZiAodGhpcy5kcmFmdCAhPT0gdGhpcy5odG1sKCkpIHtcbiAgICAgIHRoaXMuc2F2ZWQuZW1pdCh0aGlzLmRyYWZ0KTtcbiAgICB9XG4gIH1cbn1cbiIsIkBpZiAoZWRpdGluZygpKSB7XG4gIDwhLS0gRmxvYXRpbmcgZnMtaHRtbC1lZGl0b3I6IG5vIGZyYW1lLCBGcm9hbGEncyBpbmxpbmUgdG9vbGJhciBwb3BzIHVwIG92ZXJcbiAgICAgICB0aGUgdGV4dC4gcG9pbnRlcmRvd24gc3RheXMgaGVyZSBzbyBhIHByZXNzIGluIHRoZSB0ZXh0IG5ldmVyIHN0YXJ0cyBhXG4gICAgICAgZHJhZyBvZiB0aGUgYmxvY2sgb3IgYSBwYW4gb2YgdGhlIGNhbnZhcy4gLS0+XG4gIDxmcy1odG1sLWVkaXRvclxuICAgICAgY2xhc3M9XCJ0ZXh0LWNvbnRlbnQgZWRpdGluZ1wiXG4gICAgICBbY29uZmlnXT1cImVkaXRvckNvbmZpZ1wiXG4gICAgICBbKG5nTW9kZWwpXT1cImRyYWZ0XCJcbiAgICAgIChwb2ludGVyZG93bik9XCIkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKClcIlxuICAgICAgKG1vdXNlZG93bik9XCIkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKClcIj5cbiAgPC9mcy1odG1sLWVkaXRvcj5cbn0gQGVsc2Uge1xuICA8ZGl2XG4gICAgICBjbGFzcz1cInRleHQtY29udGVudFwiXG4gICAgICBbaW5uZXJIVE1MXT1cImRpc3BsYXlIdG1sKClcIj5cbiAgPC9kaXY+XG59XG4iXX0=
383
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tcG9uZW50LXRleHQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL2NvbXBvbmVudHMvY29tcG9uZW50LXRleHQvY29tcG9uZW50LXRleHQuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL2NvbXBvbmVudHMvY29tcG9uZW50LXRleHQvY29tcG9uZW50LXRleHQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLHVCQUF1QixFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUMzRyxTQUFTLEVBQUUsU0FBUyxHQUNyQixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDN0MsT0FBTyxFQUFFLFNBQVMsRUFBRSxhQUFhLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUNwRSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDakQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxZQUFZLEVBQVksTUFBTSwyQkFBMkIsQ0FBQztBQUVuRSxPQUFPLEVBQUUscUJBQXFCLEVBQXNCLE1BQU0seUJBQXlCLENBQUM7QUFDcEYsT0FBTyxFQUFFLGtCQUFrQixFQUFnQixNQUFNLHFCQUFxQixDQUFDO0FBRXZFLE9BQU8sRUFDTCxrQkFBa0IsRUFBRSxpQkFBaUIsRUFBRSxrQkFBa0IsRUFBRSx1QkFBdUIsRUFBRSx1QkFBdUIsRUFDM0csdUJBQXVCLEVBQUUsaUJBQWlCLEVBQStCLGNBQWMsR0FDeEYsTUFBTSxZQUFZLENBQUM7QUFDcEIsT0FBTyxFQUFFLGFB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aUxBQ1QsYUFBYSw2RkFDYixPQUFPLDJJQUNQLFVBQVUsaVJBQ1YscUJBQXFCLDJGQUNyQixrQkFBa0I7OzRGQWlCVCxzQkFBc0I7a0JBOUJsQyxTQUFTOytCQUNFLDJCQUEyQixtQkFHcEIsdUJBQXVCLENBQUMsTUFBTSxjQUNuQyxJQUFJLFdBQ1A7d0JBQ1AsV0FBVzt3QkFDWCxTQUFTO3dCQUNULGFBQWE7d0JBQ2IsT0FBTzt3QkFDUCxVQUFVO3dCQUNWLHFCQUFxQjt3QkFDckIsa0JBQWtCO3FCQUNuQixRQUNLO3dCQUNKLFdBQVcsRUFBRSxtQkFBbUI7d0JBQ2hDLDJFQUEyRTt3QkFDM0Usa0VBQWtFO3dCQUNsRSxxQkFBcUIsRUFBRSxnQkFBZ0I7d0JBQ3ZDLHdCQUF3QixFQUFFLGNBQWM7d0JBQ3hDLHdCQUF3QixFQUFFLGNBQWM7d0JBQ3hDLHdCQUF3QixFQUFFLGNBQWM7d0JBQ3hDLHNCQUFzQixFQUFFLGlCQUFpQjt3QkFDekMsK0NBQStDO3dCQUMvQyw2QkFBNkIsRUFBRSxrQkFBa0I7d0JBQ2pELDhCQUE4QixFQUFFLG1CQUFtQjt3QkFDbkQsNkJBQTZCLEVBQUUsa0JBQWtCO3FCQUNsRCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDb21wb25lbnQsIERlc3Ryb3lSZWYsIEVsZW1lbnRSZWYsIGNvbXB1dGVkLCBlZmZlY3QsIGluamVjdCwgaW5wdXQsIG91dHB1dCwgc2lnbmFsLFxuICB1bnRyYWNrZWQsIHZpZXdDaGlsZCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBGb3Jtc01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IE1hdEJ1dHRvbiwgTWF0SWNvbkJ1dHRvbiB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2J1dHRvbic7XG5pbXBvcnQgeyBNYXRJY29uIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvaWNvbic7XG5pbXBvcnQgeyBNYXRUb29sdGlwIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvdG9vbHRpcCc7XG5pbXBvcnQgeyBEb21TYW5pdGl6ZXIsIFNhZmVIdG1sIH0gZnJvbSAnQGFuZ3VsYXIvcGxhdGZvcm0tYnJvd3Nlcic7XG5cbmltcG9ydCB7IEZzSHRtbEVkaXRvckNvbXBvbmVudCwgRnNIdG1sRWRpdG9yQ29uZmlnIH0gZnJvbSAnQGZpcmVzdGl0Y2gvaHRtbC1lZGl0b3InO1xuaW1wb3J0IHsgRnNQb3BvdmVyRGlyZWN0aXZlLCBGc1BvcG92ZXJSZWYgfSBmcm9tICdAZmlyZXN0aXRjaC9wb3BvdmVyJztcblxuaW1wb3J0IHtcbiAgREVGQVVMVF9URVhUX0NPTE9SLCBERUZBVUxUX1RFWFRfU0laRSwgSEVBRElOR19URVhUX1NJWkVTLCBURVhUX1RBQkxFX0JPUkRFUl9DT0xPUiwgVEVYVF9UQUJMRV9CT1JERVJfV0lEVEgsXG4gIFRFWFRfVEFCTEVfQ0VMTF9QQURESU5HLCBURVhUX1RBQkxFX01BUkdJTiwgVGV4dFRva2VuQ29udGV4dCwgVGV4dFZhbHVlLCBmaWxsVGV4dFRva2Vucyxcbn0gZnJvbSAnLi4vLi4vdGV4dCc7XG5pbXBvcnQgeyBOT19WQUxVRV9LRVlTLCByZWFkS2V5cyB9IGZyb20gJy4uLy4uL3ZhbHVlcyc7XG5cbmltcG9ydCB7XG4gIFZBTFVFX0VNQkVEX0FUVFJJQlVURVMsIFZhbHVlRW1iZWRCbG9jaywgVmFsdWVFbWJlZFBsdWdpbiwgVmFsdWVFbWJlZFJlbW92YWwsXG59IGZyb20gJy4vdmFsdWUtZW1iZWQucGx1Z2luJztcblxuXG4vLyBQb2ludCBzaXplcyDigJQgdGhlIHJlcG9ydCdzIHR5cGUgdW5pdCAoMToxIHdpdGggUG93ZXJQb2ludCBhbmQgUERGKS5cbmNvbnN0IEZPTlRfU0laRVMgPSBbJzgnLCAnOScsICcxMCcsICcxMScsICcxMicsICcxNCcsICcxNicsICcxOCcsICcyMCcsICcyNCcsICcyOCcsICczMicsICczNicsICc0MCcsICc0OCcsICc2MCcsICc3MiddO1xuXG4vLyBUaGUgZmllbGRzIGEgYmxvY2sgY2FuIGNhcnJ5LCBmaWxsZWQgcGVyIHBhZ2Ugb24gdGhlIGNhbnZhcyBhbmQgaW4gZXhwb3J0cy5cbmNvbnN0IFRPS0VOUyA9IHtcbiAgJ3t7cGFnZS5udW1iZXJ9fSc6ICdQYWdlIG51bWJlcicsXG4gICd7e3BhZ2UubmFtZX19JzogJ1BhZ2UgbmFtZScsXG4gICd7e3JlcG9ydC5uYW1lfX0nOiAnUmVwb3J0IG5hbWUnLFxufTtcblxuLy8gV2hhdCB0aGUgZWRpdG9yIG1heSBwcm9kdWNlIOKAlCBleGFjdGx5IHdoYXQgdGhlIHNlcnZlciBrZWVwc1xuLy8gKFJlcG9ydFRleHRIdG1sKSBhbmQgdGhlIGV4cG9ydHMgZHJhdy4gQW55dGhpbmcgZWxzZSB3b3VsZCBlZGl0IGZpbmUgYW5kXG4vLyB0aGVuIHZhbmlzaCBvbiBzYXZlLiBBIHRhYmxlIGtlZXBzIGl0cyByb3dzLCBjZWxscyBhbmQgc3BhbnMsIGFuZCBhIGNlbGwgaXRzXG4vLyBhbGlnbm1lbnQsIGZpbGwgYW5kIHdpZHRoOyBpdHMgYm9yZGVycyBhbmQgcGFkZGluZyBhcmUgbmV2ZXIgc3RvcmVkLCBzb1xuLy8gZXZlcnkgcmVuZGVyZXIgZHJhd3MgdGhlIG9uZSBncmlkIGluIHRleHQudHMgKFRFWFRfVEFCTEVfKikuXG5jb25zdCBBTExPV0VEX1RBR1MgPSBbXG4gICdwJywgJ2gxJywgJ2gyJywgJ2gzJywgJ2JyJywgJ3N0cm9uZycsICdlbScsICd1JywgJ3MnLCAnc3BhbicsICdhJywgJ3VsJywgJ29sJywgJ2xpJyxcbiAgJ3RhYmxlJywgJ3RoZWFkJywgJ3Rib2R5JywgJ3Rmb290JywgJ3RyJywgJ3RoJywgJ3RkJyxcbl07XG5jb25zdCBBTExPV0VEX1NUWUxFUyA9IFtcbiAgJ2NvbG9yJywgJ2JhY2tncm91bmQtY29sb3InLCAnZm9udC1zaXplJywgJ2ZvbnQtd2VpZ2h0JywgJ2ZvbnQtc3R5bGUnLCAndGV4dC1kZWNvcmF0aW9uJywgJ2ZvbnQtZmFtaWx5JywgJ3RleHQtYWxpZ24nLFxuICAndmVydGljYWwtYWxpZ24nLCAnd2lkdGgnLFxuXTtcblxuLy8gV2l0aCB1c2VDbGFzc2VzOiBmYWxzZSwgRnJvYWxhJ3MgaHRtbC5nZXQgY29waWVzIGV2ZXJ5IHN0eWxlc2hlZXQgZGVjbGFyYXRpb25cbi8vIHRoYXQgbWF0Y2hlcyBhbiBlbGVtZW50IGludG8gaXRzIGlubGluZSBzdHlsZSwgdGhlbiBsYXlzIHRoZSBlbGVtZW50J3Mgb3duXG4vLyBpbmxpbmUgc3R5bGUgYmFjayBvdmVyIGl0LiBTbyBhbiBpZ25vcmVkIHByb3BlcnR5IG5ldmVyIGxvc2VzIHdoYXQgdGhlIHVzZXJcbi8vIHNldDsgaXQgb25seSBrZWVwcyB0aGUgY2FudmFzJ3MsIEZyb2FsYSdzIGFuZCB0aGUgaG9zdCBhcHAncyBjc3Mgb3V0IG9mIHRoZVxuLy8gc2F2ZWQgaHRtbC4gTGlzdGVkOiBldmVyeSBwcm9wZXJ0eSB0aGUgc2VydmVyIGtlZXBzIGFuZCB0aGUgc2hvcnRoYW5kcyB0aGF0XG4vLyBzZXQgb25lIChvdGhlcndpc2UgRnJvYWxhJ3MgZ3JleSBoZWFkZXIgZmlsbCB3b3VsZCBiZSBzYXZlZCBhcyB0aGUgdXNlcidzKSxcbi8vIHRoZW4gZXZlcnl0aGluZyBlbHNlIHRob3NlIHN0eWxlc2hlZXRzIHNldCBvbiBhIGJsb2NrJ3MgZWxlbWVudHMsIHNvIGEgYmxvY2tcbi8vIG9wZW5lZCBhbmQgY2xvc2VkIHVudG91Y2hlZCBzYXZlcyBub3RoaW5nIG5ldy4gTmFtZXMgbWF0Y2ggZXhhY3RseSwgc28gYVxuLy8gcnVsZSdzIGxvbmdoYW5kcyBhcmUgbGlzdGVkIHRvbzogdGhlIGJyb3dzZXIgc3BlbGxzIEZyb2FsYSdzIHRhYmxlXG4vLyBgYm9yZGVyOiBub25lYCBhcyBib3JkZXItd2lkdGgvLXN0eWxlLy1jb2xvci8taW1hZ2UsIGFuZCB0aGUgaG9zdCBhcHAnc1xuLy8gaGVhZGluZ3Mgc2V0IG1hcmdpbi10b3AgYW5kIG1hcmdpbi1ib3R0b20uIEZyb2FsYSBhbHNvIG91dGxpbmVzIGEgdGFibGUgdGhlXG4vLyBwb2ludGVyIGlzIG92ZXIsIHdpdGggYSBjbGFzcyB0aGF0IGlzIHN0aWxsIG9uIGl0IHdoZW4gdGhlIGh0bWwgaXMgcmVhZC5cbmNvbnN0IElHTk9SRURfU0hFRVRfU1RZTEVTID0gW1xuICAnY29sb3InLCAnYmFja2dyb3VuZCcsICdiYWNrZ3JvdW5kLWNvbG9yJywgJ2ZvbnQnLCAnZm9udC1mYW1pbHknLCAnZm9udC1zaXplJywgJ2ZvbnQtc3R5bGUnLCAnZm9udC13ZWlnaHQnLFxuICAndGV4dC1kZWNvcmF0aW9uJywgJ3RleHQtYWxpZ24nLCAndmVydGljYWwtYWxpZ24nLCAnd2lkdGgnLFxuICAnaGVpZ2h0JywgJ21pbi13aWR0aCcsICdtYXgtd2lkdGgnLCAnbWFyZ2luJywgJ21hcmdpbi10b3AnLCAnbWFyZ2luLWJvdHRvbScsICdwYWRkaW5nJywgJ3BhZGRpbmctbGVmdCcsXG4gICdib3JkZXInLCAnYm9yZGVyLXdpZHRoJywgJ2JvcmRlci1zdHlsZScsICdib3JkZXItY29sb3InLCAnYm9yZGVyLWltYWdlJywgJ2JvcmRlci1jb2xsYXBzZScsICdlbXB0eS1jZWxscycsXG4gICdvdXRsaW5lJywgJ3Bvc2l0aW9uJywgJ2Rpc3BsYXknLCAnbGlzdC1zdHlsZScsICdsaW5lLWhlaWdodCcsICd1c2VyLXNlbGVjdCcsXG5dO1xuXG4vLyBGcm9hbGEncyBvd24gdG9vbGJhcnMgYW5kIHBvcHVwcyBsaXZlIG9uIHRoZSBib2R5LCBub3QgaW4gdGhlIGJsb2NrLCBhbmQgc29cbi8vIGRvZXMgYSB2YWx1ZSBjaGlwJ3MgcG9wb3ZlciAoYW4gb3ZlcmxheSk7IGEgcHJlc3Mgb24gYW55IG9mIHRoZW0gaXMgc3RpbGwgcGFydFxuLy8gb2YgZWRpdGluZyB0aGUgYmxvY2suXG5jb25zdCBFRElUT1JfQ0hST01FID0gJy5mci10b29sYmFyLCAuZnItcG9wdXAsIC5mci1kcm9wZG93bi1tZW51LCAuZnItbW9kYWwsIC5mci10b29sdGlwLCAuY2RrLW92ZXJsYXktY29udGFpbmVyJztcblxuLy8gVGhlIHRvb2xiYXIgdG9nZ2xlIGJldHdlZW4gYSBjaGlwJ3MgbnVtYmVyIGFuZCBpdHMgbmFtZS5cbmNvbnN0IFZBTFVFX05BTUVTX0JVVFRPTiA9ICd2YWx1ZU5hbWVzJztcblxuLy8gSG93IGxvbmcgYSBub3RpY2UgdW5kZXIgdGhlIG9wZW4gYmxvY2sgc3RheXMgdXAuXG5jb25zdCBWQUxVRV9CTE9DS19OT1RJQ0VfTVMgPSA2MDAwO1xuXG4vLyBXaGF0IHRoZSBub3RpY2UgdW5kZXIgdGhlIG9wZW4gYmxvY2sgc2F5cywgb25lIGF0IGEgdGltZTogYW4gZWRpdCB3YXNcbi8vIHN0b3BwZWQgYmVjYXVzZSBpdCB3b3VsZCBoYXZlIHJlbW92ZWQgdmFsdWVzOyBhbiBlZGl0IGxlZnQgdmFsdWVzIHRoYXQgbm9cbi8vIHRleHQgcmVhZHMgYW55IG1vcmUsIHdpdGggdGhlIHVuZG8gdGhhdCBwdXRzIHRoZW0gYmFjazsgb3IgYSBjb21tYW5kIHdhc1xuLy8gcmVmdXNlZC5cbnR5cGUgVGV4dE5vdGljZSA9XG4gIHwgeyBraW5kOiAnYmxvY2tlZCc7IGJsb2NrOiBWYWx1ZUVtYmVkQmxvY2sgfVxuICB8IHsga2luZDogJ3VudXNlZCc7IGNvdW50OiBudW1iZXI7IHVuZG86ICgpID0+IHZvaWQgfVxuICB8IHsga2luZDogJ21lc3NhZ2UnOyB0ZXh0OiBzdHJpbmcgfTtcblxuLy8gQSBjbGlja2VkIHZhbHVlIGNoaXAncyBwb3BvdmVyIGlzIGFuIGZzLXBvcG92ZXIsIHdoaWNoIGF0dGFjaGVzIHRvIGFuIGVsZW1lbnRcbi8vIG9mIHRoaXMgY29tcG9uZW50J3Mgb3duIHRlbXBsYXRlIOKAlCB0aGUgY2hpcCBiZWxvbmdzIHRvIHRoZSBlZGl0b3IuIFNvIGl0XG4vLyBvcGVucyBmcm9tIGFuIGludmlzaWJsZSBhbmNob3IgbGFpZCBvdmVyIHRoZSBjaGlwLCBpbiB0aGUgYmxvY2sncyBvd25cbi8vICh1bnNjYWxlZCkgcGl4ZWxzLlxuaW50ZXJmYWNlIFZhbHVlUG9wb3ZlckFuY2hvciB7XG4gIGtleTogc3RyaW5nO1xuICBjaGlwOiBIVE1MRWxlbWVudDtcbiAgbGVmdDogbnVtYmVyO1xuICB0b3A6IG51bWJlcjtcbiAgd2lkdGg6IG51bWJlcjtcbiAgaGVpZ2h0OiBudW1iZXI7XG59XG5cbi8vIEEgdGV4dCBibG9jazogYXV0aG9yZWQgcmljaCB0ZXh0IG9uIHRoZSBwYWdlLlxuLy9cbi8vIFJlYWQgbW9kZSByZW5kZXJzIHRoZSBzdG9yZWQgaHRtbCB3aXRoIGl0cyB0b2tlbnMgKHt7cGFnZS5udW1iZXJ9fSwg4oCmKSBmaWxsZWRcbi8vIGZvciB0aGUgcGFnZSBpdCBpcyBkcmF3biBvbi4gVGhlIGh0bWwgaGFzIGFscmVhZHkgYmVlbiByZWJ1aWx0IHNlcnZlci1zaWRlXG4vLyBmcm9tIGFuIGFsbG93bGlzdCAoUmVwb3J0VGV4dEh0bWwpLCB3aGljaCBpcyB3aGF0IG1ha2VzIGJpbmRpbmcgaXQgYXMgdHJ1c3RlZFxuLy8gbWFya3VwIHNhZmUg4oCUIEFuZ3VsYXIncyBvd24gc2FuaXRpemVyIHdvdWxkIHN0cmlwIHRoZSBpbmxpbmUgc3R5bGVzIHRoYXQgQVJFXG4vLyB0aGUgZm9ybWF0dGluZy5cbi8vXG4vLyBFZGl0IG1vZGUgbW91bnRzIDxmcy1odG1sLWVkaXRvcj4gaW4gaXRzIGZsb2F0aW5nIG1vZGUgaW4gcGxhY2Ug4oCUIHRoZSB3b3Jkc1xuLy8gc3RheSB3aGVyZSB0aGV5IHNpdCBvbiB0aGUgc2xpZGUg4oCUIHdpdGggRnJvYWxhJ3MgaW5saW5lIHRvb2xiYXIgcG9wcGluZyB1cFxuLy8gb3ZlciB0aGVtLiBUaGUgZWRpdG9yIGV4aXN0cyBvbmx5IHdoaWxlIGVkaXRpbmc7IHRoZSByYXcgaHRtbCBpcyBlZGl0ZWQsIHNvIGFcbi8vIHRva2VuIHJlYWRzIGFzIHt7cGFnZS5udW1iZXJ9fSB3aGlsZSBlZGl0aW5nIGFuZCBhcyB0aGUgbnVtYmVyIG90aGVyd2lzZS4gVGhlXG4vLyBleGNlcHRpb24gaXMgYSBsaXZlIHZhbHVlICh7e3ZhbHVlLmtleX19KTogaXQgZWRpdHMgYXMgYSBjaGlwLCB3aGljaCBubyBzdHJheVxuLy8ga2V5c3Ryb2tlIHJlbW92ZXM7IHNlbGVjdGluZyBpdCBhbmQgcHJlc3NpbmcgRGVsZXRlIG9mZmVycyB0byB0YWtlIGl0IG91dFxuLy8gKFZhbHVlRW1iZWRQbHVnaW4pLiBEZWxldGluZyBhIHRhYmxlJ3Mgcm93cywgY29sdW1ucyBvciBjZWxscyBkb2VzIHRha2UgdGhlXG4vLyBjaGlwcyBpbiB0aGVtLCBhbmQgYSBub3RpY2UgdW5kZXIgdGhlIGJsb2NrIGNvdW50cyB0aGUgdmFsdWVzIHRoYXQgbGVhdmVzXG4vLyB1bnVzZWQsIHdpdGggYW4gVW5kby5cbi8vXG4vLyBUaGUgYmxvY2sgbmV2ZXIgc2F2ZXMgb24gaXRzIG93bjogaXQgZW1pdHMgdGhlIG5ldyBodG1sIHdoZW4gZWRpdGluZyBlbmRzXG4vLyBhbmQgdGhlIGhvc3QgcGVyc2lzdHMgaXQuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdhcHAtcmVwb3J0LWNvbXBvbmVudC10ZXh0JyxcbiAgdGVtcGxhdGVVcmw6ICcuL2NvbXBvbmVudC10ZXh0LmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vY29tcG9uZW50LXRleHQuY29tcG9uZW50LnNjc3MnXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtcbiAgICBGb3Jtc01vZHVsZSxcbiAgICBNYXRCdXR0b24sXG4gICAgTWF0SWNvbkJ1dHRvbixcbiAgICBNYXRJY29uLFxuICAgIE1hdFRvb2x0aXAsXG4gICAgRnNIdG1sRWRpdG9yQ29tcG9uZW50LFxuICAgIEZzUG9wb3ZlckRpcmVjdGl2ZSxcbiAgXSxcbiAgaG9zdDoge1xuICAgICcoa2V5ZG93biknOiAnb25LZXlkb3duKCRldmVudCknLFxuICAgIC8vIFRoZSBkb2N1bWVudCB0eXBlIHNjYWxlIGNvbWVzIGZyb20gdGhlIHNhbWUgY29uc3RhbnRzIHRoZSBQb3dlclBvaW50IGFuZFxuICAgIC8vIFBERiBleHBvcnRzIGRyYXcgd2l0aCwgc28gYSBwYXJhZ3JhcGggaXMgb25lIHNpemUgaW4gYWxsIHRocmVlLlxuICAgICdbc3R5bGUuLS10ZXh0LXNpemVdJzogJ3R5cGVTY2FsZS5ib2R5JyxcbiAgICAnW3N0eWxlLi0tdGV4dC1oMS1zaXplXSc6ICd0eXBlU2NhbGUuaDEnLFxuICAgICdbc3R5bGUuLS10ZXh0LWgyLXNpemVdJzogJ3R5cGVTY2FsZS5oMicsXG4gICAgJ1tzdHlsZS4tLXRleHQtaDMtc2l6ZV0nOiAndHlwZVNjYWxlLmgzJyxcbiAgICAnW3N0eWxlLi0tdGV4dC1jb2xvcl0nOiAndHlwZVNjYWxlLmNvbG9yJyxcbiAgICAvLyBBIHRhYmxlJ3MgZ3JpZCBjb21lcyBmcm9tIHRoZW0gdGhlIHNhbWUgd2F5LlxuICAgICdbc3R5bGUuLS10ZXh0LXRhYmxlLWJvcmRlcl0nOiAndGFibGVMb29rLmJvcmRlcicsXG4gICAgJ1tzdHlsZS4tLXRleHQtdGFibGUtcGFkZGluZ10nOiAndGFibGVMb29rLnBhZGRpbmcnLFxuICAgICdbc3R5bGUuLS10ZXh0LXRhYmxlLW1hcmdpbl0nOiAndGFibGVMb29rLm1hcmdpbicsXG4gIH0sXG59KVxuZXhwb3J0IGNsYXNzIENvbXBvbmVudFRleHRDb21wb25lbnQge1xuXG4gIC8vIFRoZSBibG9jaydzIHN0b3JlZCBodG1sIChjb25maWcuaHRtbCkuIEl0cyBvd24gaW5wdXQgcmF0aGVyIHRoYW4gcmVhZCBvZmZcbiAgLy8gdGhlIGNvbXBvbmVudCwgc28gYSBzYXZlZCBlZGl0IOKAlCBhIG5ldyBzdHJpbmcgb24gdGhlIHNhbWUgY29tcG9uZW50IOKAlCBpc1xuICAvLyBzZWVuIGFzIGEgY2hhbmdlIGFuZCByZXBhaW50cy5cbiAgcHVibGljIHJlYWRvbmx5IGh0bWwgPSBpbnB1dCgnJyk7XG4gIHB1YmxpYyByZWFkb25seSB0b2tlbnMgPSBpbnB1dC5yZXF1aXJlZDxUZXh0VG9rZW5Db250ZXh0PigpO1xuICBwdWJsaWMgcmVhZG9ubHkgZWRpdGluZyA9IGlucHV0KGZhbHNlKTtcblxuICAvLyBUaGUgdmFsdWUga2V5cyB0aGUgb3RoZXIgdGV4dCBibG9ja3Mgb2YgdGhpcyBibG9jaydzIGxheWVyIHNob3cuIEFza2VkXG4gIC8vIGZvciB3aGVuIGFuIGVkaXQgdGFrZXMgdGhlIGxhc3QgY2hpcCBvZiBhIHZhbHVlIG91dCBvZiB0aGlzIGJsb2NrLCBhcyBhXG4gIC8vIHZhbHVlIGFub3RoZXIgYmxvY2sgc3RpbGwgc2hvd3MgaXMgbm90IGxlZnQgdW51c2VkOyBhIGZ1bmN0aW9uLCBhcyBhXG4gIC8vIHNhdmVkIGJsb2NrJ3MgaHRtbCBjaGFuZ2VzIHdpdGhvdXQgYW55IGlucHV0IGNoYW5naW5nLlxuICBwdWJsaWMgcmVhZG9ubHkgc2hvd25FbHNld2hlcmUgPSBpbnB1dDwoKSA9PiBSZWFkb25seVNldDxzdHJpbmc+PigoKSA9PiBOT19WQUxVRV9LRVlTKTtcblxuICAvLyBUaGUgaHRtbCBhZnRlciBhbiBlZGl0LCBvbmx5IHdoZW4gaXQgY2hhbmdlZC5cbiAgcHVibGljIHJlYWRvbmx5IHNhdmVkID0gb3V0cHV0PHN0cmluZz4oKTtcblxuICAvLyBBIHByZXNzIGxhbmRlZCBvdXRzaWRlIHRoZSBibG9jayAob3IgRXNjYXBlKTogdGhlIGhvc3QgZW5kcyBlZGl0IG1vZGUsXG4gIC8vIHdoaWNoIHNhdmVzLlxuICBwdWJsaWMgcmVhZG9ubHkgZWRpdEVuZGVkID0gb3V0cHV0PHZvaWQ+KCk7XG5cbiAgLy8gQSB2YWx1ZSdzIHNldHRpbmdzIHdlcmUgYXNrZWQgZm9yIGZyb20gaXRzIHBvcG92ZXIsIGJ5IHRoZSB2YWx1ZSdzIGtleS5cbiAgLy8gVGhlIGhvc3Qgb3BlbnMgdGhlIHZhbHVlJ3Mgc2V0dGluZ3MgZGlhbG9nLCB3aGVyZSBpdCBjYW4gYWxzbyBiZSBkZWxldGVkXG4gIC8vICh0aGVuIHJlbW92ZVZhbHVlKCkpLlxuICBwdWJsaWMgcmVhZG9ubHkgdmFsdWVTZXR0aW5ncyA9IG91dHB1dDxzdHJpbmc+KCk7XG5cbiAgcHVibGljIHJlYWRvbmx5IHR5cGVTY2FsZSA9IHtcbiAgICBib2R5OiBgJHtERUZBVUxUX1RFWFRfU0laRX1wdGAsXG4gICAgaDE6IGAke0hFQURJTkdfVEVYVF9TSVpFU1sxXX1wdGAsXG4gICAgaDI6IGAke0hFQURJTkdfVEVYVF9TSVpFU1syXX1wdGAsXG4gICAgaDM6IGAke0hFQURJTkdfVEVYVF9TSVpFU1szXX1wdGAsXG4gICAgY29sb3I6IERFRkFVTFRfVEVYVF9DT0xPUixcbiAgfTtcblxuICBwdWJsaWMgcmVhZG9ubHkgdGFibGVMb29rID0ge1xuICAgIGJvcmRlcjogYCR7VEVYVF9UQUJMRV9CT1JERVJfV0lEVEh9cHQgc29saWQgJHtURVhUX1RBQkxFX0JPUkRFUl9DT0xPUn1gLFxuICAgIHBhZGRpbmc6IGAke1RFWFRfVEFCTEVfQ0VMTF9QQURESU5HLnZlcnRpY2FsfXB0ICR7VEVYVF9UQUJMRV9DRUxMX1BBRERJTkcuaG9yaXpvbnRhbH1wdGAsXG4gICAgbWFyZ2luOiBgJHtURVhUX1RBQkxFX01BUkdJTn1wdGAsXG4gIH07XG5cbiAgLy8gQ2hpcHMgbGFiZWwgdmFsdWVzIHdpdGggdGhlaXIgbmFtZXMgaW5zdGVhZCBvZiB0aGVpciBudW1iZXJzLlxuICBwdWJsaWMgcmVhZG9ubHkgc2hvd1ZhbHVlTmFtZXMgPSBzaWduYWwoZmFsc2UpO1xuXG4gIC8vIFRoZSBub3RpY2UgdW5kZXIgdGhlIG9wZW4gYmxvY2suIEEgbmV3IG9uZSByZXBsYWNlcyBpdC5cbiAgcHVibGljIHJlYWRvbmx5IG5vdGljZSA9IHNpZ25hbDxUZXh0Tm90aWNlIHwgbnVsbD4obnVsbCk7XG5cbiAgLy8gVGhlIGNoaXAgd2hvc2UgcG9wb3ZlciB3YXMgb3BlbmVkIGxhc3QsIGFuZCB3aGF0IHRoZSBwb3BvdmVyIHNheXMgYWJvdXQgaXQuXG4gIHB1YmxpYyByZWFkb25seSB2YWx1ZVBvcG92ZXIgPSBzaWduYWw8VmFsdWVQb3BvdmVyQW5jaG9yIHwgbnVsbD4obnVsbCk7XG4gIHB1YmxpYyByZWFkb25seSB2YWx1ZVBvcG92ZXJWYWx1ZSA9IGNvbXB1dGVkPFRleHRWYWx1ZSB8IG51bGw+KCgpID0+IHtcbiAgICBjb25zdCBrZXkgPSB0aGlzLnZhbHVlUG9wb3ZlcigpPy5rZXk7XG5cbiAgICByZXR1cm4ga2V5ID8gdGhpcy50b2tlbnMoKS52YWx1ZXM/LltrZXldID8/IG51bGwgOiBudWxsO1xuICB9KTtcblxuICBwdWJsaWMgcmVhZG9ubHkgdmFsdWVFbWJlZHMgPSBuZXcgVmFsdWVFbWJlZFBsdWdpbih7XG4gICAgbmFtZTogJ3JlcG9ydFZhbHVlRW1iZWRzJyxcbiAgICBob3N0OiAoKSA9PiB0aGlzLl9ob3N0Lm5hdGl2ZUVsZW1lbnQsXG4gICAgdmFsdWVzOiAoKSA9PiB0aGlzLnRva2VucygpLnZhbHVlcyA/PyB7fSxcbiAgICBzY29wZTogKCkgPT4gU3RyaW5nKHRoaXMudG9rZW5zKCkudmFsdWVQYWdlSWQgPz8gJycpLFxuICAgIHNob3dOYW1lczogKCkgPT4gdGhpcy5zaG93VmFsdWVOYW1lcygpLFxuICAgIGNsaWNrOiAoa2V5LCBjaGlwKSA9PiB0aGlzLl9vcGVuVmFsdWVQb3BvdmVyKGtleSwgY2hpcCksXG4gICAgYmxvY2tlZDogKGJsb2NrKSA9PiB0aGlzLl9zaG93Tm90aWNlKHsga2luZDogJ2Jsb2NrZWQnLCBibG9jayB9KSxcbiAgICByZW1vdmVkOiAocmVtb3ZhbCkgPT4gdGhpcy5fb25WYWx1ZXNSZW1vdmVkKHJlbW92YWwpLFxuICAgIGNoYW5nZWQ6ICgpID0+IHRoaXMuZGlzbWlzc05vdGljZSgpLFxuICAgIHJlZnVzZWQ6ICh0ZXh0KSA9PiB0aGlzLl9zaG93Tm90aWNlKHsga2luZDogJ21lc3NhZ2UnLCB0ZXh0IH0pLFxuICB9KTtcblxuICBwdWJsaWMgcmVhZG9ubHkgZWRpdG9yQ29uZmlnOiBGc0h0bWxFZGl0b3JDb25maWcgPSB7XG4gICAgZmxvYXRpbmc6IHRydWUsXG4gICAgYXV0b2ZvY3VzOiB0cnVlLFxuICAgIHBsYWNlaG9sZGVyOiAnVHlwZSBoZXJlJyxcbiAgICBwbHVnaW5zOiBbdGhpcy52YWx1ZUVtYmVkc10sXG4gICAgYnV0dG9uczogW1xuICAgICAge1xuICAgICAgICBuYW1lOiAnaW5zZXJ0RmllbGQnLFxuICAgICAgICB0aXRsZTogJ0luc2VydCBmaWVsZCcsXG4gICAgICAgIHN2Z0tleTogJ3RhZ3MnLFxuICAgICAgICBvcHRpb25zOiBUT0tFTlMsXG4gICAgICAgIGNsaWNrOiAoZWRpdG9yLCB2YWx1ZSkgPT4gZWRpdG9yLmh0bWwuaW5zZXJ0KHZhbHVlKSxcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIG5hbWU6IFZBTFVFX05BTUVTX0JVVFRPTixcbiAgICAgICAgdGl0bGU6ICdTaG93IHZhbHVlIG5hbWVzJyxcbiAgICAgICAgc3ZnS2V5OiAndGV4dE1vcmUnLFxuICAgICAgICBjbGljazogKCkgPT4gdGhpcy5zaG93VmFsdWVOYW1lcy51cGRhdGUoKG5hbWVzKSA9PiAhbmFtZXMpLFxuICAgICAgfSxcbiAgICBdLFxuICAgIGZyb2FsYUNvbmZpZzoge1xuICAgICAgdG9vbGJhckJ1dHRvbnM6IFtcbiAgICAgICAgJ3BhcmFncmFwaEZvcm1hdCcsICdmb250U2l6ZScsICd8JyxcbiAgICAgICAgJ2JvbGQnLCAnaXRhbGljJywgJ3VuZGVybGluZScsICdzdHJpa2VUaHJvdWdoJywgJ3RleHRDb2xvcicsICd8JyxcbiAgICAgICAgJ2FsaWduJywgJ2Zvcm1hdFVMJywgJ2Zvcm1hdE9MJywgJ2luc2VydFRhYmxlJywgJ3wnLFxuICAgICAgICAnaW5zZXJ0TGluaycsICdpbnNlcnRGaWVsZCcsIFZBTFVFX05BTUVTX0JVVFRPTiwgJ2NsZWFyRm9ybWF0dGluZycsXG4gICAgICBdLFxuICAgICAgLy8gQSB0YWJsZSdzIHBvcHVwIG9mZmVycyBvbmx5IHdoYXQgdGhlIHNlcnZlciBrZWVwczogbm8gdGFibGUgb3IgY2VsbFxuICAgICAgLy8gc3R5bGVzIChjbGFzc2VzKSBhbmQgbm8gZm9vdGVyIHJvdy5cbiAgICAgIHRhYmxlRWRpdEJ1dHRvbnM6IFtcbiAgICAgICAgJ3RhYmxlSGVhZGVyJywgJ3RhYmxlUmVtb3ZlJywgJ3RhYmxlUm93cycsICd0YWJsZUNvbHVtbnMnLCAnLScsXG4gICAgICAgICd0YWJsZUNlbGxzJywgJ3RhYmxlQ2VsbEJhY2tncm91bmQnLCAndGFibGVDZWxsVmVydGljYWxBbGlnbicsICd0YWJsZUNlbGxIb3Jpem9udGFsQWxpZ24nLFxuICAgICAgXSxcbiAgICAgIHRhYmxlRGVmYXVsdFdpZHRoOiAnMTAwJScsXG4gICAgICAvLyBCb3RoIGFyZSBwb3NpdGlvbmVkIGluIHNjcmVlbiBzcGFjZSBpbnNpZGUgdGhlIGNhbnZhcydzIENTUyBzY2FsZSwgc29cbiAgICAgIC8vIHRoZXkgbGFuZCBvZmYgdGhlIHRhYmxlOyByb3dzIGFuZCBjb2x1bW5zIGFyZSBhZGRlZCBmcm9tIHRoZSB0YWJsZSdzXG4gICAgICAvLyBwb3B1cCBpbnN0ZWFkLlxuICAgICAgdGFibGVSZXNpemVyOiBmYWxzZSxcbiAgICAgIHRhYmxlSW5zZXJ0SGVscGVyOiBmYWxzZSxcbiAgICAgIHBhcmFncmFwaEZvcm1hdDogeyBOOiAnTm9ybWFsJywgSDE6ICdIZWFkaW5nIDEnLCBIMjogJ0hlYWRpbmcgMicsIEgzOiAnSGVhZGluZyAzJyB9LFxuICAgICAgcGFyYWdyYXBoRm9ybWF0U2VsZWN0aW9uOiB0cnVlLFxuICAgICAgZm9udFNpemU6IEZPTlRfU0laRVMsXG4gICAgICBmb250U2l6ZVVuaXQ6ICdwdCcsXG4gICAgICBmb250U2l6ZVNlbGVjdGlvbjogdHJ1ZSxcbiAgICAgIGh0bWxBbGxvd2VkVGFnczogQUxMT1dFRF9UQUdTLFxuICAgICAgaHRtbEFsbG93ZWRBdHRyczogWydzdHlsZScsICdocmVmJywgJ3RhcmdldCcsICdyZWwnLCAnY29sc3BhbicsICdyb3dzcGFuJywgLi4uVkFMVUVfRU1CRURfQVRUUklCVVRFU10sXG4gICAgICBodG1sQWxsb3dlZFN0eWxlUHJvcHM6IEFMTE9XRURfU1RZTEVTLFxuICAgICAgaHRtbElnbm9yZUNTU1Byb3BlcnRpZXM6IElHTk9SRURfU0hFRVRfU1RZTEVTLFxuICAgICAgaHRtbFJlbW92ZVRhZ3M6IFsnc2NyaXB0JywgJ3N0eWxlJ10sXG4gICAgICAvLyBJbmxpbmUgc3R5bGVzIHJhdGhlciB0aGFuIEZyb2FsYSdzIGZyLSogY2xhc3Nlcywgd2hpY2ggbmVpdGhlciB0aGVcbiAgICAgIC8vIHNlcnZlciBub3IgdGhlIGV4cG9ydHMga25vdy5cbiAgICAgIHVzZUNsYXNzZXM6IGZhbHNlLFxuICAgICAgLy8gQSBwYXN0ZSBpcyBpdHMgd29yZHMgb25seTogYSBwYXN0ZWQgdGFibGUgZmxhdHRlbnMgdG8gdGV4dC5cbiAgICAgIHBhc3RlUGxhaW46IHRydWUsXG4gICAgICAvLyBFdmVyeSBrZXlzdHJva2UgcmVhY2hlcyB0aGUgbW9kZWwgc3RyYWlnaHQgYXdheSwgc28gZW5kaW5nIHRoZSBlZGl0IGFuXG4gICAgICAvLyBpbnN0YW50IGFmdGVyIHR5cGluZyBuZXZlciBsb3NlcyB0aGUgbGFzdCB3b3JkLlxuICAgICAgdHlwaW5nVGltZXI6IDAsXG4gICAgfSxcbiAgfTtcblxuICBwdWJsaWMgcmVhZG9ubHkgZGlzcGxheUh0bWwgPSBjb21wdXRlZDxTYWZlSHRtbD4oKCkgPT4gdGhpcy5fc2FuaXRpemVyLmJ5cGFzc1NlY3VyaXR5VHJ1c3RIdG1sKFxuICAgIGZpbGxUZXh0VG9rZW5zKHRoaXMuaHRtbCgpLCB0aGlzLnRva2VucygpKSxcbiAgKSk7XG5cbiAgLy8gV2hhdCB0aGUgZWRpdG9yIGhvbGRzIHJpZ2h0IG5vdy5cbiAgcHVibGljIGRyYWZ0ID0gJyc7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBfZWRpdG9yID0gdmlld0NoaWxkKEZzSHRtbEVkaXRvckNvbXBvbmVudCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgX3ZhbHVlUG9wb3ZlckFuY2hvciA9IHZpZXdDaGlsZCgndmFsdWVQb3BvdmVyQW5jaG9yJywgeyByZWFkOiBFbGVtZW50UmVmIH0pO1xuICBwcml2YXRlIHJlYWRvbmx5IF9zYW5pdGl6ZXIgPSBpbmplY3QoRG9tU2FuaXRpemVyKTtcbiAgcHJpdmF0ZSByZWFkb25seSBfaG9zdDogRWxlbWVudFJlZjxIVE1MRWxlbWVudD4gPSBpbmplY3QoRWxlbWVudFJlZik7XG4gIHByaXZhdGUgcmVhZG9ubHkgX2Rlc3Ryb3lSZWYgPSBpbmplY3QoRGVzdHJveVJlZik7XG4gIHByaXZhdGUgX2lzT3BlbiA9IGZhbHNlO1xuICBwcml2YXRlIF9ub3RpY2VUaW1lcjogUmV0dXJuVHlwZTx0eXBlb2Ygc2V0VGltZW91dD4gfCBudWxsID0gbnVsbDtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICAvLyBPcGVuaW5nIHNlZWRzIHRoZSBkcmFmdDsgY2xvc2luZyDigJQgd2hvZXZlciBjbG9zZWQgaXQ6IGEgcHJlc3Mgb3V0c2lkZSxcbiAgICAvLyBFc2NhcGUsIHRoZSBibG9jayBiZWluZyBkZXNlbGVjdGVkIG9yIGVkaXQgbW9kZSBlbmRpbmcg4oCUIHNhdmVzIGl0LlxuICAgIGVmZmVjdCgoKSA9PiB7XG4gICAgICBjb25zdCBlZGl0aW5nID0gdGhpcy5lZGl0aW5nKCk7XG5cbiAgICAgIHVudHJhY2tlZCgoKSA9PiB7XG4gICAgICAgIGlmIChlZGl0aW5nICYmICF0aGlzLl9pc09wZW4pIHtcbiAgICAgICAgICB0aGlzLl9pc09wZW4gPSB0cnVlO1xuICAgICAgICAgIHRoaXMuZHJhZnQgPSB0aGlzLmh0bWwoKTtcbiAgICAgICAgfSBlbHNlIGlmICghZWRpdGluZyAmJiB0aGlzLl9pc09wZW4pIHtcbiAgICAgICAgICB0aGlzLl9maW5pc2goKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICAvLyBDaGlwcyBmb2xsb3cgdGhlIHBhZ2UncyB2YWx1ZXMgYW5kIHRoZSBuYW1lcyB0b2dnbGUuXG4gICAgZWZmZWN0KCgpID0+IHtcbiAgICAgIHRoaXMudG9rZW5zKCk7XG4gICAgICB0aGlzLnNob3dWYWx1ZU5hbWVzKCk7XG4gICAgICB1bnRyYWNrZWQoKCkgPT4gdGhpcy52YWx1ZUVtYmVkcy5yZWZyZXNoKCkpO1xuICAgIH0pO1xuXG4gICAgLy8gQSBwcmVzcyBhbnl3aGVyZSB0aGF0IGlzIG5vdCB0aGUgYmxvY2sgb3IgdGhlIGVkaXRvcidzIG93biBjaHJvbWUgZW5kc1xuICAgIC8vIHRoZSBlZGl0LiBDYXB0dXJlZCwgc28gaXQgaXMgc2VlbiBiZWZvcmUgdGhlIGNhbnZhcyBvciBhIHNpYmxpbmdcbiAgICAvLyBjb21wb25lbnQgYWN0cyBvbiB0aGUgc2FtZSBwcmVzcy5cbiAgICBjb25zdCBvblByZXNzID0gKGV2ZW50OiBQb2ludGVyRXZlbnQpID0+IHRoaXMuX29uRG9jdW1lbnRQcmVzcyhldmVudCk7XG4gICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigncG9pbnRlcmRvd24nLCBvblByZXNzLCB0cnVlKTtcbiAgICB0aGlzLl9kZXN0cm95UmVmLm9uRGVzdHJveSgoKSA9PiB7XG4gICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdwb2ludGVyZG93bicsIG9uUHJlc3MsIHRydWUpO1xuICAgICAgdGhpcy5fY2xlYXJOb3RpY2VUaW1lcigpO1xuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIG9uS2V5ZG93bihldmVudDogS2V5Ym9hcmRFdmVudCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmVkaXRpbmcoKSAmJiBldmVudC5rZXkgPT09ICdFc2NhcGUnKSB7XG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgdGhpcy5fY2xvc2UoKTtcbiAgICB9XG4gIH1cblxuICAvLyBUYWtlIGEgdmFsdWUgb3V0IG9mIHRoZSB0ZXh0OiBpdHMgc2V0dGluZ3MgZGlhbG9nIGRlbGV0ZWQgaXQuXG4gIHB1YmxpYyByZW1vdmVWYWx1ZShrZXk6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMudmFsdWVFbWJlZHMucmVtb3ZlS2V5KGtleSk7XG4gIH1cblxuICAvLyBPbmx5IGZvciBhIHZhbHVlIHRoZSBwYWdlIGhhczogYSBjaGlwIG5hbWluZyBubyB2YWx1ZSB0aGVyZSBoYXMgbm9cbiAgLy8gc2V0dGluZ3MgdG8gb3Blbi5cbiAgcHVibGljIG9wZW5WYWx1ZVNldHRpbmdzKHBvcG92ZXI6IEZzUG9wb3ZlclJlZik6IHZvaWQge1xuICAgIHBvcG92ZXIuY2xvc2UoKTtcbiAgICBjb25zdCBrZXkgPSB0aGlzLnZhbHVlUG9wb3ZlcigpPy5rZXk7XG4gICAgaWYgKGtleSAmJiB0aGlzLnRva2VucygpLnZhbHVlcz8uW2tleV0pIHtcbiAgICAgIHRoaXMudmFsdWVTZXR0aW5ncy5lbWl0KGtleSk7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIHJlbW92ZUJsb2NrZWRTZWxlY3Rpb24oKTogdm9pZCB7XG4gICAgY29uc3Qgbm90aWNlID0gdGhpcy5ub3RpY2UoKTtcbiAgICBpZiAobm90aWNlPy5raW5kID09PSAnYmxvY2tlZCcpIHtcbiAgICAgIG5vdGljZS5ibG9jay5yZW1vdmVTZWxlY3Rpb24/LigpO1xuICAgIH1cbiAgICB0aGlzLmRpc21pc3NOb3RpY2UoKTtcbiAgfVxuXG4gIC8vIFB1dCBiYWNrIHRoZSB2YWx1ZXMgYW4gZWRpdCBsZWZ0IHVudXNlZDogdGhlIGVkaXRvcidzIG93biB1bmRvIG9mIGl0LlxuICBwdWJsaWMgdW5kb1ZhbHVlc1VudXNlZCgpOiB2b2lkIHtcbiAgICBjb25zdCBub3RpY2UgPSB0aGlzLm5vdGljZSgpO1xuICAgIGlmIChub3RpY2U/LmtpbmQgPT09ICd1bnVzZWQnKSB7XG4gICAgICBub3RpY2UudW5kbygpO1xuICAgIH1cbiAgICB0aGlzLmRpc21pc3NOb3RpY2UoKTtcbiAgfVxuXG4gIHB1YmxpYyBkaXNtaXNzTm90aWNlKCk6IHZvaWQge1xuICAgIHRoaXMuX2NsZWFyTm90aWNlVGltZXIoKTtcbiAgICB0aGlzLm5vdGljZS5zZXQobnVsbCk7XG4gIH1cblxuICBwcml2YXRlIF9vcGVuVmFsdWVQb3BvdmVyKGtleTogc3RyaW5nLCBjaGlwOiBIVE1MRWxlbWVudCk6IHZvaWQge1xuICAgIGNvbnN0IGhvc3QgPSB0aGlzLl9ob3N0Lm5hdGl2ZUVsZW1lbnQ7XG4gICAgY29uc3QgaG9zdFJlY3QgPSBob3N0LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIGNvbnN0IGNoaXBSZWN0ID0gY2hpcC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAvLyBUaGUgY2FudmFzIGlzIENTUy1zY2FsZWQ7IHRoZSBhbmNob3Igc2l0cyBpbiB0aGUgYmxvY2sncyBvd24gcGl4ZWxzLlxuICAgIGNvbnN0IHNjYWxlID0gaG9zdC5vZmZzZXRXaWR0aCA/IGhvc3RSZWN0LndpZHRoIC8gaG9zdC5vZmZzZXRXaWR0aCA6IDE7XG5cbiAgICB0aGlzLnZhbHVlRW1iZWRzLmhpZGVUb29sYmFyKCk7XG4gICAgdGhpcy52YWx1ZVBvcG92ZXIuc2V0KHtcbiAgICAgIGtleSxcbiAgICAgIGNoaXAsXG4gICAgICBsZWZ0OiAoY2hpcFJlY3QubGVmdCAtIGhvc3RSZWN0LmxlZnQpIC8gc2NhbGUsXG4gICAgICB0b3A6IChjaGlwUmVjdC50b3AgLSBob3N0UmVjdC50b3ApIC8gc2NhbGUsXG4gICAgICB3aWR0aDogY2hpcFJlY3Qud2lkdGggLyBzY2FsZSxcbiAgICAgIGhlaWdodDogY2hpcFJlY3QuaGVpZ2h0IC8gc2NhbGUsXG4gICAgfSk7XG5cbiAgICAvLyBmcy1wb3BvdmVyIG9wZW5zIG9uIGEgY2xpY2sgb24gaXRzIGVsZW1lbnQ6IG9uY2UgdGhlIGFuY2hvciBoYXMgbW92ZWRcbiAgICAvLyBvdmVyIHRoZSBjaGlwLCBjbGljayBpdC5cbiAgICBzZXRUaW1lb3V0KCgpID0+IHRoaXMuX3ZhbHVlUG9wb3ZlckFuY2hvcigpPy5uYXRpdmVFbGVtZW50LmNsaWNrKCkpO1xuICB9XG5cbiAgcHJpdmF0ZSBfc2hvd05vdGljZShub3RpY2U6IFRleHROb3RpY2UpOiB2b2lkIHtcbiAgICB0aGlzLl9jbGVhck5vdGljZVRpbWVyKCk7XG4gICAgdGhpcy5ub3RpY2Uuc2V0KG5vdGljZSk7XG4gICAgdGhpcy5fbm90aWNlVGltZXIgPSBzZXRUaW1lb3V0KCgpID0+IHRoaXMubm90aWNlLnNldChudWxsKSwgVkFMVUVfQkxPQ0tfTk9USUNFX01TKTtcbiAgfVxuXG4gIHByaXZhdGUgX2NsZWFyTm90aWNlVGltZXIoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuX25vdGljZVRpbWVyKSB7XG4gICAgICBjbGVhclRpbWVvdXQodGhpcy5fbm90aWNlVGltZXIpO1xuICAgICAgdGhpcy5fbm90aWNlVGltZXIgPSBudWxsO1xuICAgIH1cbiAgfVxuXG4gIC8vIEFuIGVkaXQgdG9vayB0aGUgbGFzdCBjaGlwIG9mIHNvbWUgdmFsdWVzIG91dCBvZiB0aGlzIGJsb2NrLiBDb3VudGVkIGFyZVxuICAvLyB0aGUgdmFsdWVzIHRoZSBsYXllciBubyBsb25nZXIgcmVhZHM6IHNob3duIGJ5IG5vIGJsb2NrLCB0aGlzIG9uZSBvclxuICAvLyBhbm90aGVyLCBub3IgcmVhZCBieSBhIGZvcm11bGEgb25lIG9mIHRoZW0gc2hvd3MuIFRoZXkgYXJlIG5vdCBkZWxldGVkOlxuICAvLyBzYXZpbmcgaHRtbCBuZXZlciBkZWxldGVzIGEgdmFsdWUuXG4gIHByaXZhdGUgX29uVmFsdWVzUmVtb3ZlZChyZW1vdmFsOiBWYWx1ZUVtYmVkUmVtb3ZhbCk6IHZvaWQge1xuICAgIGNvbnN0IGVsc2V3aGVyZSA9IFsuLi50aGlzLnNob3duRWxzZXdoZXJlKCkoKV07XG4gICAgY29uc3QgdmFsdWVzID0gdGhpcy50b2tlbnMoKS52YWx1ZXMgPz8ge307XG4gICAgY29uc3QgYmVmb3JlID0gcmVhZEtleXMoWy4uLnJlbW92YWwuYmVmb3JlLCAuLi5lbHNld2hlcmVdLCB2YWx1ZXMpO1xuICAgIGNvbnN0IGFmdGVyID0gcmVhZEtleXMoWy4uLnJlbW92YWwuYWZ0ZXIsIC4uLmVsc2V3aGVyZV0sIHZhbHVlcyk7XG4gICAgY29uc3QgY291bnQgPSBbLi4uYmVmb3JlXS5maWx0ZXIoKGtleSkgPT4gIWFmdGVyLmhhcyhrZXkpICYmICEhdmFsdWVzW2tleV0pLmxlbmd0aDtcblxuICAgIGlmIChjb3VudCA+IDApIHtcbiAgICAgIHRoaXMuX3Nob3dOb3RpY2UoeyBraW5kOiAndW51c2VkJywgY291bnQsIHVuZG86IHJlbW92YWwudW5kbyB9KTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9vbkRvY3VtZW50UHJlc3MoZXZlbnQ6IFBvaW50ZXJFdmVudCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5lZGl0aW5nKCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCB0YXJnZXQgPSBldmVudC50YXJnZXQgYXMgSFRNTEVsZW1lbnQgfCBudWxsO1xuICAgIGlmICh0YXJnZXQgJiYgKHRoaXMuX2hvc3QubmF0aXZlRWxlbWVudC5jb250YWlucyh0YXJnZXQpIHx8IHRhcmdldC5jbG9zZXN0KEVESVRPUl9DSFJPTUUpKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuX2Nsb3NlKCk7XG4gIH1cblxuICAvLyBTYXZlIE5PVywgdGhlbiBhc2sgdGhlIGhvc3QgdG8gY2xvc2UuIFNhdmluZyBoZXJlIHJhdGhlciB0aGFuIHdhaXRpbmcgZm9yXG4gIC8vIHRoZSBlZGl0aW5nIGlucHV0IHRvIGZsaXAgbWF0dGVyczogdGhlIHNhbWUgcHJlc3MgbWF5IGJlIG9uIGEgcGFnZSB0YWIsXG4gIC8vIGFuZCBieSB0aGUgdGltZSB0aGUgaW5wdXQgY2hhbmdlZCB0aGlzIGJsb2NrIGNvdWxkIGFscmVhZHkgYmUgZGVzdHJveWVkLFxuICAvLyB3aXRoIGl0cyBlZGl0IGdvbmUuXG4gIHByaXZhdGUgX2Nsb3NlKCk6IHZvaWQge1xuICAgIHRoaXMuX3N5bmNEcmFmdCgpO1xuICAgIHRoaXMuX2ZpbmlzaCgpO1xuICAgIHRoaXMuZWRpdEVuZGVkLmVtaXQoKTtcbiAgfVxuXG4gIC8vIFJlYWQgdGhlIGVkaXRvciBkaXJlY3RseSByYXRoZXIgdGhhbiB0cnVzdGluZyB0aGUgbGFzdCBtb2RlbCB1cGRhdGUuXG4gIHByaXZhdGUgX3N5bmNEcmFmdCgpOiB2b2lkIHtcbiAgICBjb25zdCBodG1sID0gdGhpcy5fZWRpdG9yKCk/LmVkaXRvcj8uaHRtbD8uZ2V0KCk7XG4gICAgaWYgKHR5cGVvZiBodG1sID09PSAnc3RyaW5nJykge1xuICAgICAgdGhpcy5kcmFmdCA9IGh0bWw7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfZmluaXNoKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5faXNPcGVuKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5faXNPcGVuID0gZmFsc2U7XG4gICAgdGhpcy5kaXNtaXNzTm90aWNlKCk7XG4gICAgaWYgKHRoaXMuZHJhZnQgIT09IHRoaXMuaHRtbCgpKSB7XG4gICAgICB0aGlzLnNhdmVkLmVtaXQodGhpcy5kcmFmdCk7XG4gICAgfVxuICB9XG59XG4iLCJAaWYgKGVkaXRpbmcoKSkge1xuICA8IS0tIEZsb2F0aW5nIGZzLWh0bWwtZWRpdG9yOiBubyBmcmFtZSwgRnJvYWxhJ3MgaW5saW5lIHRvb2xiYXIgcG9wcyB1cCBvdmVyXG4gICAgICAgdGhlIHRleHQuIHBvaW50ZXJkb3duIHN0YXlzIGhlcmUgc28gYSBwcmVzcyBpbiB0aGUgdGV4dCBuZXZlciBzdGFydHMgYVxuICAgICAgIGRyYWcgb2YgdGhlIGJsb2NrIG9yIGEgcGFuIG9mIHRoZSBjYW52YXMuIC0tPlxuICA8ZnMtaHRtbC1lZGl0b3JcbiAgICAgIGNsYXNzPVwidGV4dC1jb250ZW50IGVkaXRpbmdcIlxuICAgICAgW2NvbmZpZ109XCJlZGl0b3JDb25maWdcIlxuICAgICAgWyhuZ01vZGVsKV09XCJkcmFmdFwiXG4gICAgICAocG9pbnRlcmRvd24pPVwiJGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpXCJcbiAgICAgIChtb3VzZWRvd24pPVwiJGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpXCI+XG4gIDwvZnMtaHRtbC1lZGl0b3I+XG5cbiAgPCEtLSBPbmUgbm90aWNlIGF0IGEgdGltZTogYW4gZWRpdCBzdG9wcGVkIGJlY2F1c2UgaXQgd291bGQgaGF2ZSByZW1vdmVkXG4gICAgICAgdmFsdWVzLCBhbiBlZGl0IHRoYXQgbGVmdCB2YWx1ZXMgbm8gdGV4dCByZWFkcywgb3IgYSByZWZ1c2VkIGNvbW1hbmQuXG4gICAgICAgbW91c2Vkb3duIGtlZXBzIHRoZSBlZGl0b3IncyBmb2N1cyBhbmQgc2VsZWN0aW9uLCBzbyBVbmRvIHJlYWNoZXMgaXQuIC0tPlxuICBAaWYgKG5vdGljZSgpOyBhcyBjdXJyZW50KSB7XG4gICAgPGRpdlxuICAgICAgICBjbGFzcz1cInZhbHVlLW5vdGljZSBmcy1yb3cuZ2FwLXNtXCJcbiAgICAgICAgKHBvaW50ZXJkb3duKT1cIiRldmVudC5zdG9wUHJvcGFnYXRpb24oKVwiXG4gICAgICAgIChtb3VzZWRvd24pPVwiJGV2ZW50LnByZXZlbnREZWZhdWx0KClcIj5cbiAgICAgIEBzd2l0Y2ggKGN1cnJlbnQua2luZCkge1xuICAgICAgICBAY2FzZSAoJ2Jsb2NrZWQnKSB7XG4gICAgICAgICAgQGlmIChjdXJyZW50LmJsb2NrLnJlbW92ZVNlbGVjdGlvbikge1xuICAgICAgICAgICAgPHNwYW4+XG4gICAgICAgICAgICAgIFRoaXMgc2VsZWN0aW9uIGluY2x1ZGVzIHt7IGN1cnJlbnQuYmxvY2suY291bnQgfX0ge3sgY3VycmVudC5ibG9jay5jb3VudCA9PT0gMSA/ICd2YWx1ZScgOiAndmFsdWVzJyB9fS5cbiAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICBtYXQtYnV0dG9uXG4gICAgICAgICAgICAgICAgY29sb3I9XCJwcmltYXJ5XCJcbiAgICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgICAgICAoY2xpY2spPVwicmVtb3ZlQmxvY2tlZFNlbGVjdGlvbigpXCI+XG4gICAgICAgICAgICAgIFJlbW92ZSB0ZXh0IGFuZCB7eyBjdXJyZW50LmJsb2NrLmNvdW50ID09PSAxID8gJ3ZhbHVlJyA6IGN1cnJlbnQuYmxvY2suY291bnQgKyAnIHZhbHVlcycgfX1cbiAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgIH0gQGVsc2Uge1xuICAgICAgICAgICAgPHNwYW4+VG8gdGFrZSBhIHZhbHVlIG91dCwgc2VsZWN0IGl0LCB0aGVuIHByZXNzIERlbGV0ZS48L3NwYW4+XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIEBjYXNlICgndW51c2VkJykge1xuICAgICAgICAgIDxzcGFuPnt7IGN1cnJlbnQuY291bnQgfX0ge3sgY3VycmVudC5jb3VudCA9PT0gMSA/ICd2YWx1ZScgOiAndmFsdWVzJyB9fSBtb3ZlZCB0byBOb3QgdXNlZDwvc3Bhbj5cbiAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgIG1hdC1idXR0b25cbiAgICAgICAgICAgICAgY29sb3I9XCJwcmltYXJ5XCJcbiAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgIChjbGljayk9XCJ1bmRvVmFsdWVzVW51c2VkKClcIj5cbiAgICAgICAgICAgIFVuZG9cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgfVxuICAgICAgICBAY2FzZSAoJ21lc3NhZ2UnKSB7XG4gICAgICAgICAgPHNwYW4+e3sgY3VycmVudC50ZXh0IH19PC9zcGFuPlxuICAgICAgICB9XG4gICAgICB9XG4gICAgICA8YnV0dG9uXG4gICAgICAgICAgbWF0LWJ1dHRvblxuICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgIChjbGljayk9XCJkaXNtaXNzTm90aWNlKClcIj5cbiAgICAgICAgRGlzbWlzc1xuICAgICAgPC9idXR0b24+XG4gICAgPC9kaXY+XG4gIH1cbn0gQGVsc2Uge1xuICA8ZGl2XG4gICAgICBjbGFzcz1cInRleHQtY29udGVudFwiXG4gICAgICBbaW5uZXJIVE1MXT1cImRpc3BsYXlIdG1sKClcIj5cbiAgPC9kaXY+XG59XG5cbjwhLS0gQSBjbGlja2VkIHZhbHVlIGNoaXAncyBwb3BvdmVyOiBhbiBmcy1wb3BvdmVyIG9uIGFuIGludmlzaWJsZSBhbmNob3IgbGFpZFxuICAgICBvdmVyIHRoZSBjaGlwICh0aGUgY2hpcCBpdHNlbGYgYmVsb25ncyB0byB0aGUgZWRpdG9yKS4gT3V0c2lkZSB0aGUgZWRpdGluZ1xuICAgICBibG9jaywgc28gYSBwb3BvdmVyIHN0aWxsIG9wZW4gd2hlbiBlZGl0aW5nIGVuZHMgY2xvc2VzIHRoZSB1c3VhbCB3YXkuIC0tPlxuPHNwYW5cbiAgICAjdmFsdWVQb3BvdmVyQW5jaG9yXG4gICAgY2xhc3M9XCJ2YWx1ZS1wb3BvdmVyLWFuY2hvclwiXG4gICAgYXJpYS1oaWRkZW49XCJ0cnVlXCJcbiAgICBmc1BvcG92ZXJcbiAgICB0cmlnZ2VyPVwiY2xpY2tcIlxuICAgIHdyYXBwZXJDbGFzcz1cInZhbHVlLXBvcG92ZXItd3JhcHBlclwiXG4gICAgW3RlbXBsYXRlXT1cInZhbHVlUG9wb3ZlclRlbXBsYXRlXCJcbiAgICBbaW5kaWNhdGlvbl09XCJmYWxzZVwiXG4gICAgW21heFdpZHRoXT1cIjMyMFwiXG4gICAgW3N0eWxlLmxlZnQucHhdPVwidmFsdWVQb3BvdmVyKCk/LmxlZnRcIlxuICAgIFtzdHlsZS50b3AucHhdPVwidmFsdWVQb3BvdmVyKCk/LnRvcFwiXG4gICAgW3N0eWxlLndpZHRoLnB4XT1cInZhbHVlUG9wb3ZlcigpPy53aWR0aFwiXG4gICAgW3N0eWxlLmhlaWdodC5weF09XCJ2YWx1ZVBvcG92ZXIoKT8uaGVpZ2h0XCI+XG48L3NwYW4+XG48bmctdGVtcGxhdGVcbiAgICAjdmFsdWVQb3BvdmVyVGVtcGxhdGVcbiAgICBsZXQtcG9wb3Zlcj1cInBvcG92ZXJcIj5cbiAgPCEtLSBXaGF0IHRoZSB2YWx1ZSBpcywgYW5kIGl0cyBzZXR0aW5ncyAod2hlcmUgaXQgY2FuIGFsc28gYmUgZGVsZXRlZCk7IGFcbiAgICAgICBjaGlwIG5hbWluZyBubyB2YWx1ZSBvbiB0aGUgcGFnZSBoYXMgbm8gc2V0dGluZ3MuIC0tPlxuICA8ZGl2IGNsYXNzPVwidmFsdWUtcG9wb3ZlciBmcy1yb3dcIj5cbiAgICA8ZGl2IGNsYXNzPVwiZnMtZmxleFwiPlxuICAgICAgPGRpdiBjbGFzcz1cInZhbHVlLXBvcG92ZXItbmFtZVwiPnt7IHZhbHVlUG9wb3ZlclZhbHVlKCk/Lm5hbWUgPz8gdmFsdWVQb3BvdmVyKCk/LmtleSB9fTwvZGl2PlxuICAgICAgQGlmICghdmFsdWVQb3BvdmVyVmFsdWUoKSkge1xuICAgICAgICA8ZGl2IGNsYXNzPVwic21hbGxcIj5Ob3QgYSB2YWx1ZSBvbiB0aGlzIHBhZ2U8L2Rpdj5cbiAgICAgIH1cbiAgICA8L2Rpdj5cbiAgICBAaWYgKHZhbHVlUG9wb3ZlclZhbHVlKCkpIHtcbiAgICAgIDxidXR0b25cbiAgICAgICAgICBtYXQtaWNvbi1idXR0b25cbiAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICBjbGFzcz1cInZhbHVlLXBvcG92ZXItc2V0dGluZ3NcIlxuICAgICAgICAgIG1hdFRvb2x0aXA9XCJTZXR0aW5nc1wiXG4gICAgICAgICAgKGNsaWNrKT1cIm9wZW5WYWx1ZVNldHRpbmdzKHBvcG92ZXIpXCI+XG4gICAgICAgIDxtYXQtaWNvbj5zZXR0aW5nczwvbWF0LWljb24+XG4gICAgICA8L2J1dHRvbj5cbiAgICB9XG4gIDwvZGl2PlxuPC9uZy10ZW1wbGF0ZT5cbiJdfQ==