@firestitch/report 18.8.1 → 18.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (208) hide show
  1. package/app/reports/anchor-at-point.d.ts +14 -0
  2. package/app/reports/canvas-landing-page.d.ts +2 -0
  3. package/app/reports/components/component-chart/component-chart.component.d.ts +18 -2
  4. package/app/reports/components/component-kpi/component-kpi.component.d.ts +4 -1
  5. package/app/reports/components/component-text/component-text.component.d.ts +47 -2
  6. package/app/reports/components/component-text/value-embed.plugin.d.ts +67 -0
  7. package/app/reports/components/report-canvas/report-canvas.component.d.ts +37 -9
  8. package/app/reports/components/report-component/report-component.component.d.ts +45 -2
  9. package/app/reports/components/report-view-picker/report-view-picker.component.d.ts +21 -0
  10. package/app/reports/data/report.data.d.ts +18 -2
  11. package/app/reports/dialogs/component-settings/component-settings.component.d.ts +25 -2
  12. package/app/reports/dialogs/report-settings/report-settings.component.d.ts +15 -6
  13. package/app/reports/dialogs/report-view/report-view-dialog.component.d.ts +13 -0
  14. package/app/reports/drill-crumbs.d.ts +12 -0
  15. package/app/reports/enums/report-value-formula.enum.d.ts +6 -0
  16. package/app/reports/export/report-export-collector.service.d.ts +35 -4
  17. package/app/reports/export/report-export.service.d.ts +3 -1
  18. package/app/reports/export/report-filter-lines.d.ts +18 -0
  19. package/app/reports/export/report-pdf.service.d.ts +18 -2
  20. package/app/reports/export/report-pptx.service.d.ts +15 -2
  21. package/app/reports/export/report-text-layout.service.d.ts +35 -0
  22. package/app/reports/filter-settings-rules.d.ts +33 -0
  23. package/app/reports/format.d.ts +2 -1
  24. package/app/reports/interfaces/canvas-landing-input.interface.d.ts +8 -0
  25. package/app/reports/interfaces/component-data-applied.interface.d.ts +13 -0
  26. package/app/reports/interfaces/component-data-drill.interface.d.ts +22 -0
  27. package/app/reports/interfaces/filter-bar-placement.type.d.ts +1 -0
  28. package/app/reports/interfaces/filter-component-toggle-state.interface.d.ts +4 -0
  29. package/app/reports/interfaces/filter-settings-option.interface.d.ts +4 -0
  30. package/app/reports/interfaces/filter-type-select-state.interface.d.ts +5 -0
  31. package/app/reports/interfaces/report-chart-hit.interface.d.ts +5 -0
  32. package/app/reports/interfaces/report-chat-viewer-cross-filter-field.interface.d.ts +4 -0
  33. package/app/reports/interfaces/report-chat-viewer-cross-filter.interface.d.ts +7 -0
  34. package/app/reports/interfaces/report-chat-viewer-detail.interface.d.ts +4 -0
  35. package/app/reports/interfaces/report-chat-viewer-drill-step.interface.d.ts +5 -0
  36. package/app/reports/interfaces/report-chat-viewer-drill.interface.d.ts +5 -0
  37. package/app/reports/interfaces/report-chat-viewer-filter.interface.d.ts +3 -0
  38. package/app/reports/interfaces/report-chat-viewer-selection.interface.d.ts +5 -0
  39. package/app/reports/interfaces/report-chat-viewer-state.interface.d.ts +12 -0
  40. package/app/reports/interfaces/report-drill-crumb.interface.d.ts +6 -0
  41. package/app/reports/interfaces/report-drill-refusal.type.d.ts +1 -0
  42. package/app/reports/interfaces/report-drill-step.interface.d.ts +5 -0
  43. package/app/reports/interfaces/report-export-line-kind.type.d.ts +1 -0
  44. package/app/reports/interfaces/report-export-line.interface.d.ts +8 -0
  45. package/app/reports/interfaces/report-export-lines-input.interface.d.ts +9 -0
  46. package/app/reports/interfaces/report-export-snapshot.interface.d.ts +15 -0
  47. package/app/reports/interfaces/report-filter-line-context.interface.d.ts +8 -0
  48. package/app/reports/interfaces/report-filter-line-form.type.d.ts +1 -0
  49. package/app/reports/interfaces/report-filter-match.type.d.ts +1 -0
  50. package/app/reports/interfaces/report-filter-option-pair.interface.d.ts +4 -0
  51. package/app/reports/interfaces/report-filter-options-ask.interface.d.ts +6 -0
  52. package/app/reports/interfaces/report-filter-options-list.interface.d.ts +7 -0
  53. package/app/reports/interfaces/report-filter-options-request.interface.d.ts +6 -0
  54. package/app/reports/interfaces/report-filter-options-stream.interface.d.ts +11 -0
  55. package/app/reports/interfaces/report-filter-options.interface.d.ts +7 -0
  56. package/app/reports/interfaces/report-filter-skip.type.d.ts +1 -0
  57. package/app/reports/interfaces/report-mark-action.type.d.ts +1 -0
  58. package/app/reports/interfaces/report-mark-click.interface.d.ts +13 -0
  59. package/app/reports/interfaces/report-mark-context.interface.d.ts +6 -0
  60. package/app/reports/interfaces/report-mark-decision.interface.d.ts +6 -0
  61. package/app/reports/interfaces/report-mark-event.interface.d.ts +11 -0
  62. package/app/reports/interfaces/report-mark-point.interface.d.ts +8 -0
  63. package/app/reports/interfaces/report-temporary-state.interface.d.ts +4 -0
  64. package/app/reports/interfaces/report-tile-state.interface.d.ts +8 -0
  65. package/app/reports/interfaces/report-url-link.interface.d.ts +4 -0
  66. package/app/reports/interfaces/report-url-value-name.type.d.ts +1 -0
  67. package/app/reports/interfaces/report-url-write.interface.d.ts +4 -0
  68. package/app/reports/interfaces/report-view-config.interface.d.ts +11 -0
  69. package/app/reports/interfaces/report-view-create.interface.d.ts +7 -0
  70. package/app/reports/interfaces/report-view-deleted.interface.d.ts +4 -0
  71. package/app/reports/interfaces/report-view-dialog-data.interface.d.ts +7 -0
  72. package/app/reports/interfaces/report-view-dropped.interface.d.ts +5 -0
  73. package/app/reports/interfaces/report-view-menu-item.interface.d.ts +10 -0
  74. package/app/reports/interfaces/report-view-summary.interface.d.ts +11 -0
  75. package/app/reports/interfaces/report-view.interface.d.ts +7 -0
  76. package/app/reports/interfaces/report-viewer-feature.type.d.ts +1 -0
  77. package/app/reports/interfaces/report-views.interface.d.ts +7 -0
  78. package/app/reports/interfaces/report.interface.d.ts +48 -5
  79. package/app/reports/interfaces/tile-load-result.interface.d.ts +4 -0
  80. package/app/reports/layout.d.ts +2 -0
  81. package/app/reports/mark-click.d.ts +20 -0
  82. package/app/reports/option-builder.d.ts +12 -1
  83. package/app/reports/report-chat-viewer-state.d.ts +8 -0
  84. package/app/reports/report-date-presets.d.ts +2 -0
  85. package/app/reports/report-filter-items.d.ts +27 -22
  86. package/app/reports/report-tile.d.ts +2 -0
  87. package/app/reports/report-url-state.d.ts +27 -10
  88. package/app/reports/report-view-config.d.ts +36 -0
  89. package/app/reports/report-view-menu.d.ts +15 -0
  90. package/app/reports/report-viewer-features.d.ts +5 -0
  91. package/app/reports/services/report-filter-options.service.d.ts +26 -0
  92. package/app/reports/services/report-filter-state.service.d.ts +65 -2
  93. package/app/reports/services/report-view.service.d.ts +51 -0
  94. package/app/reports/text.d.ts +50 -0
  95. package/app/reports/tile-data-state.d.ts +7 -0
  96. package/app/reports/tile-loads.d.ts +4 -0
  97. package/app/reports/values.d.ts +17 -0
  98. package/app/reports/views/report/fs-ai-report.component.d.ts +9 -1
  99. package/app/reports/views/report/report.component.d.ts +6 -0
  100. package/esm2022/app/reports/anchor-at-point.mjs +49 -0
  101. package/esm2022/app/reports/canvas-landing-page.mjs +25 -0
  102. package/esm2022/app/reports/components/component-chart/component-chart.component.mjs +97 -5
  103. package/esm2022/app/reports/components/component-kpi/component-kpi.component.mjs +11 -4
  104. package/esm2022/app/reports/components/component-list/component-list.component.mjs +7 -1
  105. package/esm2022/app/reports/components/component-text/component-text.component.mjs +213 -16
  106. package/esm2022/app/reports/components/component-text/value-embed.plugin.mjs +484 -0
  107. package/esm2022/app/reports/components/report-canvas/report-canvas.component.mjs +296 -55
  108. package/esm2022/app/reports/components/report-component/report-component.component.mjs +318 -76
  109. package/esm2022/app/reports/components/report-view-picker/report-view-picker.component.mjs +115 -0
  110. package/esm2022/app/reports/data/report.data.mjs +103 -8
  111. package/esm2022/app/reports/dialogs/component-settings/component-settings.component.mjs +210 -44
  112. package/esm2022/app/reports/dialogs/report-settings/report-settings.component.mjs +86 -90
  113. package/esm2022/app/reports/dialogs/report-view/report-view-dialog.component.mjs +52 -0
  114. package/esm2022/app/reports/drill-crumbs.mjs +73 -0
  115. package/esm2022/app/reports/enums/report-value-formula.enum.mjs +14 -0
  116. package/esm2022/app/reports/export/report-export-collector.service.mjs +299 -125
  117. package/esm2022/app/reports/export/report-export.service.mjs +57 -19
  118. package/esm2022/app/reports/export/report-filter-lines.mjs +235 -0
  119. package/esm2022/app/reports/export/report-pdf.service.mjs +315 -71
  120. package/esm2022/app/reports/export/report-pptx.service.mjs +293 -71
  121. package/esm2022/app/reports/export/report-text-layout.service.mjs +241 -0
  122. package/esm2022/app/reports/filter-settings-rules.mjs +283 -0
  123. package/esm2022/app/reports/format.mjs +13 -30
  124. package/esm2022/app/reports/interfaces/canvas-landing-input.interface.mjs +2 -0
  125. package/esm2022/app/reports/interfaces/component-data-applied.interface.mjs +2 -0
  126. package/esm2022/app/reports/interfaces/component-data-drill.interface.mjs +2 -0
  127. package/esm2022/app/reports/interfaces/filter-bar-placement.type.mjs +2 -0
  128. package/esm2022/app/reports/interfaces/filter-component-toggle-state.interface.mjs +2 -0
  129. package/esm2022/app/reports/interfaces/filter-settings-option.interface.mjs +2 -0
  130. package/esm2022/app/reports/interfaces/filter-type-select-state.interface.mjs +2 -0
  131. package/esm2022/app/reports/interfaces/report-chart-hit.interface.mjs +2 -0
  132. package/esm2022/app/reports/interfaces/report-chat-viewer-cross-filter-field.interface.mjs +2 -0
  133. package/esm2022/app/reports/interfaces/report-chat-viewer-cross-filter.interface.mjs +2 -0
  134. package/esm2022/app/reports/interfaces/report-chat-viewer-detail.interface.mjs +2 -0
  135. package/esm2022/app/reports/interfaces/report-chat-viewer-drill-step.interface.mjs +2 -0
  136. package/esm2022/app/reports/interfaces/report-chat-viewer-drill.interface.mjs +2 -0
  137. package/esm2022/app/reports/interfaces/report-chat-viewer-filter.interface.mjs +1 -1
  138. package/esm2022/app/reports/interfaces/report-chat-viewer-selection.interface.mjs +2 -0
  139. package/esm2022/app/reports/interfaces/report-chat-viewer-state.interface.mjs +1 -1
  140. package/esm2022/app/reports/interfaces/report-drill-crumb.interface.mjs +2 -0
  141. package/esm2022/app/reports/interfaces/report-drill-refusal.type.mjs +2 -0
  142. package/esm2022/app/reports/interfaces/report-drill-step.interface.mjs +2 -0
  143. package/esm2022/app/reports/interfaces/report-export-line-kind.type.mjs +2 -0
  144. package/esm2022/app/reports/interfaces/report-export-line.interface.mjs +2 -0
  145. package/esm2022/app/reports/interfaces/report-export-lines-input.interface.mjs +2 -0
  146. package/esm2022/app/reports/interfaces/report-export-snapshot.interface.mjs +2 -0
  147. package/esm2022/app/reports/interfaces/report-filter-line-context.interface.mjs +2 -0
  148. package/esm2022/app/reports/interfaces/report-filter-line-form.type.mjs +2 -0
  149. package/esm2022/app/reports/interfaces/report-filter-match.type.mjs +2 -0
  150. package/esm2022/app/reports/interfaces/report-filter-option-pair.interface.mjs +2 -0
  151. package/esm2022/app/reports/interfaces/report-filter-options-ask.interface.mjs +2 -0
  152. package/esm2022/app/reports/interfaces/report-filter-options-list.interface.mjs +2 -0
  153. package/esm2022/app/reports/interfaces/report-filter-options-request.interface.mjs +2 -0
  154. package/esm2022/app/reports/interfaces/report-filter-options-stream.interface.mjs +2 -0
  155. package/esm2022/app/reports/interfaces/report-filter-options.interface.mjs +2 -0
  156. package/esm2022/app/reports/interfaces/report-filter-skip.type.mjs +2 -0
  157. package/esm2022/app/reports/interfaces/report-mark-action.type.mjs +2 -0
  158. package/esm2022/app/reports/interfaces/report-mark-click.interface.mjs +2 -0
  159. package/esm2022/app/reports/interfaces/report-mark-context.interface.mjs +2 -0
  160. package/esm2022/app/reports/interfaces/report-mark-decision.interface.mjs +2 -0
  161. package/esm2022/app/reports/interfaces/report-mark-event.interface.mjs +2 -0
  162. package/esm2022/app/reports/interfaces/report-mark-point.interface.mjs +2 -0
  163. package/esm2022/app/reports/interfaces/report-temporary-state.interface.mjs +2 -0
  164. package/esm2022/app/reports/interfaces/report-tile-state.interface.mjs +2 -0
  165. package/esm2022/app/reports/interfaces/report-url-link.interface.mjs +2 -0
  166. package/esm2022/app/reports/interfaces/report-url-value-name.type.mjs +2 -0
  167. package/esm2022/app/reports/interfaces/report-url-write.interface.mjs +2 -0
  168. package/esm2022/app/reports/interfaces/report-view-config.interface.mjs +2 -0
  169. package/esm2022/app/reports/interfaces/report-view-create.interface.mjs +2 -0
  170. package/esm2022/app/reports/interfaces/report-view-deleted.interface.mjs +2 -0
  171. package/esm2022/app/reports/interfaces/report-view-dialog-data.interface.mjs +2 -0
  172. package/esm2022/app/reports/interfaces/report-view-dropped.interface.mjs +2 -0
  173. package/esm2022/app/reports/interfaces/report-view-menu-item.interface.mjs +2 -0
  174. package/esm2022/app/reports/interfaces/report-view-summary.interface.mjs +2 -0
  175. package/esm2022/app/reports/interfaces/report-view.interface.mjs +2 -0
  176. package/esm2022/app/reports/interfaces/report-viewer-feature.type.mjs +2 -0
  177. package/esm2022/app/reports/interfaces/report-views.interface.mjs +2 -0
  178. package/esm2022/app/reports/interfaces/report.interface.mjs +1 -1
  179. package/esm2022/app/reports/interfaces/tile-load-result.interface.mjs +2 -0
  180. package/esm2022/app/reports/layout.mjs +11 -1
  181. package/esm2022/app/reports/mark-click.mjs +193 -0
  182. package/esm2022/app/reports/option-builder.mjs +159 -15
  183. package/esm2022/app/reports/report-chat-viewer-state.mjs +34 -0
  184. package/esm2022/app/reports/report-date-presets.mjs +18 -0
  185. package/esm2022/app/reports/report-filter-items.mjs +343 -72
  186. package/esm2022/app/reports/report-tile.mjs +12 -0
  187. package/esm2022/app/reports/report-url-state.mjs +596 -108
  188. package/esm2022/app/reports/report-view-config.mjs +697 -0
  189. package/esm2022/app/reports/report-view-menu.mjs +119 -0
  190. package/esm2022/app/reports/report-viewer-features.mjs +42 -0
  191. package/esm2022/app/reports/services/report-filter-options.service.mjs +238 -0
  192. package/esm2022/app/reports/services/report-filter-state.service.mjs +715 -71
  193. package/esm2022/app/reports/services/report-view.service.mjs +358 -0
  194. package/esm2022/app/reports/text.mjs +293 -85
  195. package/esm2022/app/reports/tile-data-state.mjs +127 -0
  196. package/esm2022/app/reports/tile-loads.mjs +38 -0
  197. package/esm2022/app/reports/values.mjs +183 -0
  198. package/esm2022/app/reports/views/report/fs-ai-report.component.mjs +180 -46
  199. package/esm2022/app/reports/views/report/report.component.mjs +106 -23
  200. package/esm2022/public_api.mjs +24 -1
  201. package/fesm2022/{firestitch-report-echarts-CFnbJx44.mjs → firestitch-report-echarts-UBg8Wlhd.mjs} +2 -2
  202. package/fesm2022/{firestitch-report-echarts-CFnbJx44.mjs.map → firestitch-report-echarts-UBg8Wlhd.mjs.map} +1 -1
  203. package/fesm2022/{firestitch-report-firestitch-report-CSylkyko.mjs → firestitch-report-firestitch-report-B1keNrcK.mjs} +11315 -4201
  204. package/fesm2022/firestitch-report-firestitch-report-B1keNrcK.mjs.map +1 -0
  205. package/fesm2022/firestitch-report.mjs +1 -1
  206. package/package.json +1 -1
  207. package/public_api.d.ts +23 -0
  208. package/fesm2022/firestitch-report-firestitch-report-CSylkyko.mjs.map +0 -1
@@ -0,0 +1,241 @@
1
+ import { ApplicationRef, EnvironmentInjector, Injectable, Injector, afterNextRender, createComponent, inject, } from '@angular/core';
2
+ import { ComponentTextComponent } from '../components/component-text/component-text.component';
3
+ import { PX_PER_INCH } from '../components/report-canvas/report-canvas.component';
4
+ import { componentPaddingCss } from '../layout';
5
+ import { fillTextTokens, parseTable, splitAtTables } from '../text';
6
+ import * as i0 from "@angular/core";
7
+ // How far past the bottom of its box a block may reach and still fit: two
8
+ // pixels, so the rounding of the last line's edge never counts as overflow.
9
+ // The deck keeps a table's row on the same terms.
10
+ export const OVERFLOW_SLACK = 2 / PX_PER_INCH;
11
+ // Where the canvas puts each part of a text block, for the exports. A
12
+ // browser wraps the words and sizes a table's columns by its own layout, which
13
+ // neither jsPDF nor PowerPoint reproduces. So the block is rendered offscreen
14
+ // with the canvas's own component, at the canvas's 96px per inch and unscaled,
15
+ // and the exports place what they draw where it sat: a table at its top, in
16
+ // its column widths and row heights, and the words between tables at theirs.
17
+ // It also tells whether the block runs past the bottom of its box.
18
+ //
19
+ // Provided beside the export services, so the block renders under the same
20
+ // injector the canvas's blocks do.
21
+ export class ReportTextLayoutService {
22
+ _appRef = inject(ApplicationRef);
23
+ _environmentInjector = inject(EnvironmentInjector);
24
+ _injector = inject(Injector);
25
+ _layouts = new Map();
26
+ // A block is measured once per size, padding and filled html: an export that
27
+ // draws it twice, or a second export with the same numbers, reads the same
28
+ // layout, which nothing changes.
29
+ async measure(component, tokens) {
30
+ const html = component.config?.html ?? '';
31
+ const key = [
32
+ component.id,
33
+ component.w,
34
+ component.h,
35
+ JSON.stringify(component.config?.padding ?? null),
36
+ fillTextTokens(html, tokens),
37
+ ].join('|');
38
+ let layout = this._layouts.get(key);
39
+ if (!layout) {
40
+ layout = this._render(component, html, tokens);
41
+ this._layouts.set(key, layout);
42
+ // A measure that failed is tried again next time.
43
+ layout.catch(() => this._layouts.delete(key));
44
+ }
45
+ return layout;
46
+ }
47
+ async _render(component, html, tokens) {
48
+ const text = createComponent(ComponentTextComponent, {
49
+ environmentInjector: this._environmentInjector,
50
+ elementInjector: this._injector,
51
+ });
52
+ const box = blockBox(component, text.location.nativeElement);
53
+ try {
54
+ text.setInput('html', html);
55
+ text.setInput('tokens', tokens);
56
+ text.setInput('editing', false);
57
+ document.body.append(box);
58
+ await this._rendered(text);
59
+ // Laid out first, so a font the words ask for is loading by the time
60
+ // fonts.ready is read.
61
+ box.getBoundingClientRect();
62
+ await document.fonts.ready;
63
+ return measureBlock(text.location.nativeElement.querySelector('.text-content'));
64
+ }
65
+ finally {
66
+ // Destroying the block also takes it off the application.
67
+ text.destroy();
68
+ box.remove();
69
+ }
70
+ }
71
+ // The block is rendered by the application's own change detection, as any
72
+ // view attached to it: its inputs mark it for the next render, which draws
73
+ // it before the callback runs. Not whenStable(): that also waits out
74
+ // whatever else the host app has under way (its requests and, under
75
+ // zone.js, its timers), and never resolves while a timer repeats.
76
+ _rendered(text) {
77
+ return new Promise((resolve) => {
78
+ afterNextRender(() => resolve(), { injector: this._environmentInjector });
79
+ this._appRef.attachView(text.hostView);
80
+ });
81
+ }
82
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ReportTextLayoutService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
83
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ReportTextLayoutService });
84
+ }
85
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ReportTextLayoutService, decorators: [{
86
+ type: Injectable
87
+ }] });
88
+ // The block's box as the canvas draws it (the component box): its size, a
89
+ // 1px border and the block's padding (componentPaddingCss) around a body the
90
+ // text fills. Fixed far off to the left, and hidden, so it is never seen.
91
+ function blockBox(component, text) {
92
+ const box = document.createElement('div');
93
+ const body = document.createElement('div');
94
+ Object.assign(box.style, {
95
+ position: 'fixed',
96
+ left: '-10000px',
97
+ top: '0',
98
+ visibility: 'hidden',
99
+ width: `${component.w * PX_PER_INCH}px`,
100
+ height: `${component.h * PX_PER_INCH}px`,
101
+ boxSizing: 'border-box',
102
+ border: '1px solid transparent',
103
+ padding: componentPaddingCss(component),
104
+ });
105
+ body.style.height = '100%';
106
+ body.append(text);
107
+ box.append(body);
108
+ return box;
109
+ }
110
+ // Split the rendered block at its tables, as textBlocks splits the same html,
111
+ // so the nth segment is the nth text part and the nth table the nth table
112
+ // part. How far the block reaches is the bottom of its last part that draws
113
+ // anything.
114
+ function measureBlock(content) {
115
+ const box = content.getBoundingClientRect();
116
+ const parts = splitAtTables(content);
117
+ const segments = [];
118
+ const tables = [];
119
+ let usedHeight = 0;
120
+ parts.forEach((part, index) => {
121
+ if (Array.isArray(part)) {
122
+ const segment = measureSegment(drawnNodes(part, index === parts.length - 1), box);
123
+ segments.push(segment);
124
+ usedHeight = segment?.bottom ?? usedHeight;
125
+ }
126
+ else {
127
+ const table = measureTable(part, box);
128
+ tables.push(table);
129
+ usedHeight = table.top + table.height;
130
+ }
131
+ });
132
+ const contentHeight = inches(box.height);
133
+ return {
134
+ contentWidth: inches(box.width),
135
+ contentHeight,
136
+ usedHeight,
137
+ overflow: usedHeight > contentHeight + OVERFLOW_SLACK,
138
+ segments,
139
+ tables,
140
+ };
141
+ }
142
+ // The nodes of a run between tables that the exports draw. Whitespace between
143
+ // blocks draws nothing anywhere. A blank line at the start of a block is
144
+ // drawn, on the canvas and by textBlocks alike, but textBlocks drops the blank
145
+ // lines at the very end of a block, so they are not measured either: a
146
+ // trailing empty paragraph never makes a block overflow.
147
+ function drawnNodes(nodes, blockEnd) {
148
+ const skipsLast = blockEnd ? isBlank : isVoid;
149
+ let start = 0;
150
+ let end = nodes.length;
151
+ while (start < end && isVoid(nodes[start])) {
152
+ start++;
153
+ }
154
+ while (end > start && skipsLast(nodes[end - 1])) {
155
+ end--;
156
+ }
157
+ const drawn = nodes.slice(start, end);
158
+ if (blockEnd && drawn.length) {
159
+ trimBlankLines(drawn[drawn.length - 1]);
160
+ }
161
+ return drawn;
162
+ }
163
+ // Take the blank lines off the end of the block's last node, as textBlocks
164
+ // drops them: the elements that hold no text after its last words, down its
165
+ // last children — the <br>s of <p>b<br><br></p>, a list's empty last item.
166
+ // Whitespace is passed over and left, so a paragraph never turns into an
167
+ // empty one, which the canvas draws as a line. The block is the measure's own
168
+ // copy, thrown away once measured, and nothing above what is taken off moves.
169
+ function trimBlankLines(node) {
170
+ let child = node.lastChild;
171
+ while (child && isBlank(child)) {
172
+ const previous = child.previousSibling;
173
+ if (!isVoid(child)) {
174
+ child.remove();
175
+ }
176
+ child = previous;
177
+ }
178
+ if (child) {
179
+ trimBlankLines(child);
180
+ }
181
+ }
182
+ // Whitespace between blocks, or a comment.
183
+ function isVoid(node) {
184
+ return node.nodeType === Node.TEXT_NODE
185
+ ? !/[^ \t\n\r\f]/.test(node.textContent ?? '')
186
+ : node.nodeType !== Node.ELEMENT_NODE;
187
+ }
188
+ // A node that draws no words: whitespace, or an element with no text in it,
189
+ // such as the empty line <p><br></p>.
190
+ function isBlank(node) {
191
+ return isVoid(node) || !node.textContent;
192
+ }
193
+ // From before its first node to after its last. null for a run that draws
194
+ // nothing.
195
+ function measureSegment(nodes, box) {
196
+ if (!nodes.length) {
197
+ return null;
198
+ }
199
+ const range = document.createRange();
200
+ range.setStartBefore(nodes[0]);
201
+ range.setEndAfter(nodes[nodes.length - 1]);
202
+ const rect = range.getBoundingClientRect();
203
+ return { top: inches(rect.top - box.top), bottom: inches(rect.bottom - box.top) };
204
+ }
205
+ function measureTable(table, box) {
206
+ const rect = table.getBoundingClientRect();
207
+ return {
208
+ top: inches(rect.top - box.top),
209
+ left: inches(rect.left - box.left),
210
+ width: inches(rect.width),
211
+ height: inches(rect.height),
212
+ rowHeights: Array.from(table.rows, (row) => inches(row.getBoundingClientRect().height)),
213
+ columnWidths: columnWidths(table, rect.width).map(inches),
214
+ };
215
+ }
216
+ // A grid column is as wide as a cell that spans only it. A column that only
217
+ // spanning cells cross shares what the others leave of the table's width, and
218
+ // all of them are scaled to add up to it exactly. The cells come in the same
219
+ // order as the grid's (parseTable reads the same rows), so the nth cell of a
220
+ // row is the nth cell of that grid row.
221
+ function columnWidths(table, width) {
222
+ const grid = parseTable(table);
223
+ const widths = Array.from({ length: grid.columns }, () => null);
224
+ grid.rows.forEach((row, rowIndex) => row.cells.forEach((cell, cellIndex) => {
225
+ if (cell.colSpan === 1 && widths[cell.column] === null) {
226
+ widths[cell.column] = table.rows[rowIndex].cells[cellIndex].getBoundingClientRect().width;
227
+ }
228
+ }));
229
+ const known = widths.filter((value) => value !== null);
230
+ const share = Math.max(0, width - sum(known)) / Math.max(1, widths.length - known.length);
231
+ const filled = widths.map((value) => value ?? share);
232
+ const total = sum(filled);
233
+ return filled.map((value) => total ? value * width / total : width / filled.length);
234
+ }
235
+ function sum(values) {
236
+ return values.reduce((total, value) => total + value, 0);
237
+ }
238
+ function inches(pixels) {
239
+ return pixels / PX_PER_INCH;
240
+ }
241
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVwb3J0LXRleHQtbGF5b3V0LnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvYXBwL3JlcG9ydHMvZXhwb3J0L3JlcG9ydC10ZXh0LWxheW91dC5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxjQUFjLEVBQWdCLG1CQUFtQixFQUFFLFVBQVUsRUFBRSxRQUFRLEVBQUUsZUFBZSxFQUFFLGVBQWUsRUFBRSxNQUFNLEdBQ2xILE1BQU0sZUFBZSxDQUFDO0FBRXZCLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLHVEQUF1RCxDQUFDO0FBQy9GLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxxREFBcUQsQ0FBQztBQUVsRixPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDaEQsT0FBTyxFQUFvQixjQUFjLEVBQUUsVUFBVSxFQUFFLGFBQWEsRUFBRSxNQUFNLFNBQVMsQ0FBQzs7QUF5Q3RGLDBFQUEwRTtBQUMxRSw0RUFBNEU7QUFDNUUsa0RBQWtEO0FBQ2xELE1BQU0sQ0FBQyxNQUFNLGNBQWMsR0FBRyxDQUFDLEdBQUcsV0FBVyxDQUFDO0FBRTlDLHNFQUFzRTtBQUN0RSwrRUFBK0U7QUFDL0UsOEVBQThFO0FBQzlFLCtFQUErRTtBQUMvRSw0RUFBNEU7QUFDNUUsNkVBQTZFO0FBQzdFLG1FQUFtRTtBQUNuRSxFQUFFO0FBQ0YsMkVBQTJFO0FBQzNFLG1DQUFtQztBQUVuQyxNQUFNLE9BQU8sdUJBQXVCO0lBRWpCLE9BQU8sR0FBRyxNQUFNLENBQUMsY0FBYyxDQUFDLENBQUM7SUFDakMsb0JBQW9CLEdBQUcsTUFBTSxDQUFDLG1CQUFtQixDQUFDLENBQUM7SUFDbkQsU0FBUyxHQUFHLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUM3QixRQUFRLEdBQUcsSUFBSSxHQUFHLEVBQW9DLENBQUM7SUFFeEUsNkVBQTZFO0lBQzdFLDJFQUEyRTtJQUMzRSxpQ0FBaUM7SUFDMUIsS0FBSyxDQUFDLE9BQU8sQ0FBQyxTQUEwQixFQUFFLE1BQXdCO1FBQ3ZFLE1BQU0sSUFBSSxHQUFHLFNBQVMsQ0FBQyxNQUFNLEVBQUUsSUFBSSxJQUFJLEVBQUUsQ0FBQztRQUMxQyxNQUFNLEdBQUcsR0FBRztZQUNWLFNBQVMsQ0FBQyxFQUFFO1lBQ1osU0FBUyxDQUFDLENBQUM7WUFDWCxTQUFTLENBQUMsQ0FBQztZQUNYLElBQUksQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxPQUFPLElBQUksSUFBSSxDQUFDO1lBQ2pELGNBQWMsQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDO1NBQzdCLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBRVosSUFBSSxNQUFNLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDcEMsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ1osTUFBTSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLElBQUksRUFBRSxNQUFNLENBQUMsQ0FBQztZQUMvQyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsTUFBTSxDQUFDLENBQUM7WUFDL0Isa0RBQWtEO1lBQ2xELE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUNoRCxDQUFDO1FBRUQsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQztJQUVPLEtBQUssQ0FBQyxPQUFPLENBQUMsU0FBMEIsRUFBRSxJQUFZLEVBQUUsTUFBd0I7UUFDdEYsTUFBTSxJQUFJLEdBQUcsZUFBZSxDQUFDLHNCQUFzQixFQUFFO1lBQ25ELG1CQUFtQixFQUFFLElBQUksQ0FBQyxvQkFBb0I7WUFDOUMsZUFBZSxFQUFFLElBQUksQ0FBQyxTQUFTO1NBQ2hDLENBQUMsQ0FBQztRQUNILE1BQU0sR0FBRyxHQUFHLFFBQVEsQ0FBQyxTQUFTLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUU3RCxJQUFJLENBQUM7WUFDSCxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQztZQUM1QixJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsQ0FBQztZQUNoQyxJQUFJLENBQUMsUUFBUSxDQUFDLFNBQVMsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUNoQyxRQUFRLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUMxQixNQUFNLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDM0IscUVBQXFFO1lBQ3JFLHVCQUF1QjtZQUN2QixHQUFHLENBQUMscUJBQXFCLEVBQUUsQ0FBQztZQUM1QixNQUFNLFFBQVEsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDO1lBRTNCLE9BQU8sWUFBWSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLGFBQWEsQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDO1FBQ2xGLENBQUM7Z0JBQVMsQ0FBQztZQUNULDBEQUEwRDtZQUMxRCxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDZixHQUFHLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDZixDQUFDO0lBQ0gsQ0FBQztJQUVELDBFQUEwRTtJQUMxRSwyRUFBMkU7SUFDM0UscUVBQXFFO0lBQ3JFLG9FQUFvRTtJQUNwRSxrRUFBa0U7SUFDMUQsU0FBUyxDQUFDLElBQTBDO1FBQzFELE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRTtZQUM3QixlQUFlLENBQUMsR0FBRyxFQUFFLENBQUMsT0FBTyxFQUFFLEVBQUUsRUFBRSxRQUFRLEVBQUUsSUFBSSxDQUFDLG9CQUFvQixFQUFFLENBQUMsQ0FBQztZQUMxRSxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDekMsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO3dHQW5FVSx1QkFBdUI7NEdBQXZCLHVCQUF1Qjs7NEZBQXZCLHVCQUF1QjtrQkFEbkMsVUFBVTs7QUF1RVgsMEVBQTBFO0FBQzFFLDZFQUE2RTtBQUM3RSwwRUFBMEU7QUFDMUUsU0FBUyxRQUFRLENBQUMsU0FBMEIsRUFBRSxJQUFpQjtJQUM3RCxNQUFNLEdBQUcsR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzFDLE1BQU0sSUFBSSxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLENBQUM7SUFFM0MsTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFO1FBQ3ZCLFFBQVEsRUFBRSxPQUFPO1FBQ2pCLElBQUksRUFBRSxVQUFVO1FBQ2hCLEdBQUcsRUFBRSxHQUFHO1FBQ1IsVUFBVSxFQUFFLFFBQVE7UUFDcEIsS0FBSyxFQUFFLEdBQUcsU0FBUyxDQUFDLENBQUMsR0FBRyxXQUFXLElBQUk7UUFDdkMsTUFBTSxFQUFFLEdBQUcsU0FBUyxDQUFDLENBQUMsR0FBRyxXQUFXLElBQUk7UUFDeEMsU0FBUyxFQUFFLFlBQVk7UUFDdkIsTUFBTSxFQUFFLHVCQUF1QjtRQUMvQixPQUFPLEVBQUUsbUJBQW1CLENBQUMsU0FBUyxDQUFDO0tBQ3hDLENBQUMsQ0FBQztJQUNILElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztJQUMzQixJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ2xCLEdBQUcsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7SUFFakIsT0FBTyxHQUFHLENBQUM7QUFDYixDQUFDO0FBRUQsOEVBQThFO0FBQzlFLDBFQUEwRTtBQUMxRSw0RUFBNEU7QUFDNUUsWUFBWTtBQUNaLFNBQVMsWUFBWSxDQUFDLE9BQW9CO0lBQ3hDLE1BQU0sR0FBRyxHQUFHLE9BQU8sQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO0lBQzVDLE1BQU0sS0FBSyxHQUFHLGFBQWEsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNyQyxNQUFNLFFBQVEsR0FBaUMsRUFBRSxDQUFDO0lBQ2xELE1BQU0sTUFBTSxHQUFzQixFQUFFLENBQUM7SUFDckMsSUFBSSxVQUFVLEdBQUcsQ0FBQyxDQUFDO0lBRW5CLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLEVBQUU7UUFDNUIsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7WUFDeEIsTUFBTSxPQUFPLEdBQUcsY0FBYyxDQUFDLFVBQVUsQ0FBQyxJQUFJLEVBQUUsS0FBSyxLQUFLLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7WUFDbEYsUUFBUSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUN2QixVQUFVLEdBQUcsT0FBTyxFQUFFLE1BQU0sSUFBSSxVQUFVLENBQUM7UUFDN0MsQ0FBQzthQUFNLENBQUM7WUFDTixNQUFNLEtBQUssR0FBRyxZQUFZLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFDO1lBQ3RDLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDbkIsVUFBVSxHQUFHLEtBQUssQ0FBQyxHQUFHLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQztRQUN4QyxDQUFDO0lBQ0gsQ0FBQyxDQUFDLENBQUM7SUFFSCxNQUFNLGFBQWEsR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBRXpDLE9BQU87UUFDTCxZQUFZLEVBQUUsTUFBTSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUM7UUFDL0IsYUFBYTtRQUNiLFVBQVU7UUFDVixRQUFRLEVBQUUsVUFBVSxHQUFHLGFBQWEsR0FBRyxjQUFjO1FBQ3JELFFBQVE7UUFDUixNQUFNO0tBQ1AsQ0FBQztBQUNKLENBQUM7QUFFRCw4RUFBOEU7QUFDOUUseUVBQXlFO0FBQ3pFLCtFQUErRTtBQUMvRSx1RUFBdUU7QUFDdkUseURBQXlEO0FBQ3pELFNBQVMsVUFBVSxDQUFDLEtBQWEsRUFBRSxRQUFpQjtJQUNsRCxNQUFNLFNBQVMsR0FBRyxRQUFRLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDO0lBQzlDLElBQUksS0FBSyxHQUFHLENBQUMsQ0FBQztJQUNkLElBQUksR0FBRyxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUM7SUFFdkIsT0FBTyxLQUFLLEdBQUcsR0FBRyxJQUFJLE1BQU0sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQzNDLEtBQUssRUFBRSxDQUFDO0lBQ1YsQ0FBQztJQUNELE9BQU8sR0FBRyxHQUFHLEtBQUssSUFBSSxTQUFTLENBQUMsS0FBSyxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDaEQsR0FBRyxFQUFFLENBQUM7SUFDUixDQUFDO0lBRUQsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDdEMsSUFBSSxRQUFRLElBQUksS0FBSyxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQzdCLGNBQWMsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzFDLENBQUM7SUFFRCxPQUFPLEtBQUssQ0FBQztBQUNmLENBQUM7QUFFRCwyRUFBMkU7QUFDM0UsNEVBQTRFO0FBQzVFLDJFQUEyRTtBQUMzRSx5RUFBeUU7QUFDekUsOEVBQThFO0FBQzlFLDhFQUE4RTtBQUM5RSxTQUFTLGNBQWMsQ0FBQyxJQUFVO0lBQ2hDLElBQUksS0FBSyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUM7SUFDM0IsT0FBTyxLQUFLLElBQUksT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDL0IsTUFBTSxRQUFRLEdBQUcsS0FBSyxDQUFDLGVBQWUsQ0FBQztRQUN2QyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDbkIsS0FBSyxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ2pCLENBQUM7UUFDRCxLQUFLLEdBQUcsUUFBUSxDQUFDO0lBQ25CLENBQUM7SUFFRCxJQUFJLEtBQUssRUFBRSxDQUFDO1FBQ1YsY0FBYyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3hCLENBQUM7QUFDSCxDQUFDO0FBRUQsMkNBQTJDO0FBQzNDLFNBQVMsTUFBTSxDQUFDLElBQVU7SUFDeEIsT0FBTyxJQUFJLENBQUMsUUFBUSxLQUFLLElBQUksQ0FBQyxTQUFTO1FBQ3JDLENBQUMsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsSUFBSSxFQUFFLENBQUM7UUFDOUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxRQUFRLEtBQUssSUFBSSxDQUFDLFlBQVksQ0FBQztBQUMxQyxDQUFDO0FBRUQsNEVBQTRFO0FBQzVFLHNDQUFzQztBQUN0QyxTQUFTLE9BQU8sQ0FBQyxJQUFVO0lBQ3pCLE9BQU8sTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQztBQUMzQyxDQUFDO0FBRUQsMEVBQTBFO0FBQzFFLFdBQVc7QUFDWCxTQUFTLGNBQWMsQ0FBQyxLQUFhLEVBQUUsR0FBWTtJQUNqRCxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ2xCLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVELE1BQU0sS0FBSyxHQUFHLFFBQVEsQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUNyQyxLQUFLLENBQUMsY0FBYyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQy9CLEtBQUssQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMzQyxNQUFNLElBQUksR0FBRyxLQUFLLENBQUMscUJBQXFCLEVBQUUsQ0FBQztJQUUzQyxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRSxNQUFNLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcsR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7QUFDcEYsQ0FBQztBQUVELFNBQVMsWUFBWSxDQUFDLEtBQXVCLEVBQUUsR0FBWTtJQUN6RCxNQUFNLElBQUksR0FBRyxLQUFLLENBQUMscUJBQXFCLEVBQUUsQ0FBQztJQUUzQyxPQUFPO1FBQ0wsR0FBRyxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQyxHQUFHLENBQUM7UUFDL0IsSUFBSSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUM7UUFDbEMsS0FBSyxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDO1FBQ3pCLE1BQU0sRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQztRQUMzQixVQUFVLEVBQUUsS0FBSyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLHFCQUFxQixFQUFFLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDdkYsWUFBWSxFQUFFLFlBQVksQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUM7S0FDMUQsQ0FBQztBQUNKLENBQUM7QUFFRCw0RUFBNEU7QUFDNUUsOEVBQThFO0FBQzlFLDZFQUE2RTtBQUM3RSw2RUFBNkU7QUFDN0Usd0NBQXdDO0FBQ3hDLFNBQVMsWUFBWSxDQUFDLEtBQXVCLEVBQUUsS0FBYTtJQUMxRCxNQUFNLElBQUksR0FBRyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDL0IsTUFBTSxNQUFNLEdBQXNCLEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBRSxNQUFNLEVBQUUsSUFBSSxDQUFDLE9BQU8sRUFBRSxFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBRW5GLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsR0FBRyxFQUFFLFFBQVEsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLEVBQUUsU0FBUyxFQUFFLEVBQUU7UUFDekUsSUFBSSxJQUFJLENBQUMsT0FBTyxLQUFLLENBQUMsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLElBQUksRUFBRSxDQUFDO1lBQ3ZELE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUMscUJBQXFCLEVBQUUsQ0FBQyxLQUFLLENBQUM7UUFDNUYsQ0FBQztJQUNILENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFSixNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsS0FBSyxFQUFtQixFQUFFLENBQUMsS0FBSyxLQUFLLElBQUksQ0FBQyxDQUFDO0lBQ3hFLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLEtBQUssR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxNQUFNLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUMxRixNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLElBQUksS0FBSyxDQUFDLENBQUM7SUFDckQsTUFBTSxLQUFLLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBRTFCLE9BQU8sTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLEdBQUcsS0FBSyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUN0RixDQUFDO0FBRUQsU0FBUyxHQUFHLENBQUMsTUFBZ0I7SUFDM0IsT0FBTyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsS0FBSyxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUMsS0FBSyxHQUFHLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQztBQUMzRCxDQUFDO0FBRUQsU0FBUyxNQUFNLENBQUMsTUFBYztJQUM1QixPQUFPLE1BQU0sR0FBRyxXQUFXLENBQUM7QUFDOUIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEFwcGxpY2F0aW9uUmVmLCBDb21wb25lbnRSZWYsIEVudmlyb25tZW50SW5qZWN0b3IsIEluamVjdGFibGUsIEluamVjdG9yLCBhZnRlck5leHRSZW5kZXIsIGNyZWF0ZUNvbXBvbmVudCwgaW5qZWN0LFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuaW1wb3J0IHsgQ29tcG9uZW50VGV4dENvbXBvbmVudCB9IGZyb20gJy4uL2NvbXBvbmVudHMvY29tcG9uZW50LXRleHQvY29tcG9uZW50LXRleHQuY29tcG9uZW50JztcbmltcG9ydCB7IFBYX1BFUl9JTkNIIH0gZnJvbSAnLi4vY29tcG9uZW50cy9yZXBvcnQtY2FudmFzL3JlcG9ydC1jYW52YXMuY29tcG9uZW50JztcbmltcG9ydCB7IFJlcG9ydENvbXBvbmVudCB9IGZyb20gJy4uL2ludGVyZmFjZXMvcmVwb3J0LmludGVyZmFjZSc7XG5pbXBvcnQgeyBjb21wb25lbnRQYWRkaW5nQ3NzIH0gZnJvbSAnLi4vbGF5b3V0JztcbmltcG9ydCB7IFRleHRUb2tlbkNvbnRleHQsIGZpbGxUZXh0VG9rZW5zLCBwYXJzZVRhYmxlLCBzcGxpdEF0VGFibGVzIH0gZnJvbSAnLi4vdGV4dCc7XG5cblxuLy8gV2hlcmUgYSBzdHJldGNoIG9mIGEgYmxvY2sncyB3b3JkcyBzaXRzOiB0aGUgdG9wIG9mIGl0cyBmaXJzdCBsaW5lIGFuZCB0aGVcbi8vIGJvdHRvbSBvZiBpdHMgbGFzdC5cbmV4cG9ydCBpbnRlcmZhY2UgVGV4dFNlZ21lbnRMYXlvdXQge1xuICB0b3A6IG51bWJlcjtcbiAgYm90dG9tOiBudW1iZXI7XG59XG5cbi8vIFdoZXJlIGEgdGFibGUgc2l0cyBpbiBpdHMgYmxvY2ssIGFuZCBob3cgdGFsbCBpdHMgcm93cyBhbmQgaG93IHdpZGUgaXRzXG4vLyBjb2x1bW5zIGFyZS5cbmV4cG9ydCBpbnRlcmZhY2UgVGV4dFRhYmxlTGF5b3V0IHtcbiAgdG9wOiBudW1iZXI7XG4gIGxlZnQ6IG51bWJlcjtcbiAgd2lkdGg6IG51bWJlcjtcbiAgaGVpZ2h0OiBudW1iZXI7XG4gIC8vIEEgcm93J3MgaGVpZ2h0LCBpbiB0aGUgb3JkZXIgdGV4dEJsb2NrcyBsaXN0cyB0aGUgcm93czogdGhlIGhlYWQgZmlyc3QgYW5kXG4gIC8vIHRoZSBmb290IGxhc3QuXG4gIHJvd0hlaWdodHM6IG51bWJlcltdO1xuICAvLyBBIGdyaWQgY29sdW1uJ3Mgd2lkdGggKHRhYmxlR3JpZCksIGxlZnQgdG8gcmlnaHQuIFRvZ2V0aGVyIHRoZXkgYXJlIHRoZVxuICAvLyB0YWJsZSdzIHdpZHRoLlxuICBjb2x1bW5XaWR0aHM6IG51bWJlcltdO1xufVxuXG4vLyBBIHRleHQgYmxvY2sgYXMgdGhlIGNhbnZhcyBsYXlzIGl0IG91dC4gRXZlcnl0aGluZyBpcyBpbiBpbmNoZXMsIG1lYXN1cmVkXG4vLyBmcm9tIHRoZSB0b3AgbGVmdCBvZiB0aGUgYmxvY2sncyBjb250ZW50IGJveCAoaW5zaWRlIGl0cyBwYWRkaW5nKS5cbmV4cG9ydCBpbnRlcmZhY2UgVGV4dEJsb2NrTGF5b3V0IHtcbiAgY29udGVudFdpZHRoOiBudW1iZXI7XG4gIGNvbnRlbnRIZWlnaHQ6IG51bWJlcjtcbiAgLy8gSG93IGZhciBkb3duIHRoZSBibG9jaydzIHdvcmRzIGFuZCB0YWJsZXMgcmVhY2guXG4gIHVzZWRIZWlnaHQ6IG51bWJlcjtcbiAgLy8gVGhleSByZWFjaCBwYXN0IHRoZSBib3R0b20gb2YgdGhlIGJveCwgd2hlcmUgdGhlIGNhbnZhcyBjdXRzIHRoZW0gb2ZmLlxuICBvdmVyZmxvdzogYm9vbGVhbjtcbiAgLy8gT25lIHBlciB0ZXh0IHBhcnQgb2YgdGV4dEJsb2NrcywgaW4gb3JkZXI6IG51bGwgZm9yIGEgcGFydCB0aGF0IGRyYXdzXG4gIC8vIG5vdGhpbmcuXG4gIHNlZ21lbnRzOiAoVGV4dFNlZ21lbnRMYXlvdXQgfCBudWxsKVtdO1xuICAvLyBPbmUgcGVyIHRhYmxlIHBhcnQgb2YgdGV4dEJsb2NrcywgaW4gb3JkZXIuXG4gIHRhYmxlczogVGV4dFRhYmxlTGF5b3V0W107XG59XG5cbi8vIEhvdyBmYXIgcGFzdCB0aGUgYm90dG9tIG9mIGl0cyBib3ggYSBibG9jayBtYXkgcmVhY2ggYW5kIHN0aWxsIGZpdDogdHdvXG4vLyBwaXhlbHMsIHNvIHRoZSByb3VuZGluZyBvZiB0aGUgbGFzdCBsaW5lJ3MgZWRnZSBuZXZlciBjb3VudHMgYXMgb3ZlcmZsb3cuXG4vLyBUaGUgZGVjayBrZWVwcyBhIHRhYmxlJ3Mgcm93IG9uIHRoZSBzYW1lIHRlcm1zLlxuZXhwb3J0IGNvbnN0IE9WRVJGTE9XX1NMQUNLID0gMiAvIFBYX1BFUl9JTkNIO1xuXG4vLyBXaGVyZSB0aGUgY2FudmFzIHB1dHMgZWFjaCBwYXJ0IG9mIGEgdGV4dCBibG9jaywgZm9yIHRoZSBleHBvcnRzLiBBXG4vLyBicm93c2VyIHdyYXBzIHRoZSB3b3JkcyBhbmQgc2l6ZXMgYSB0YWJsZSdzIGNvbHVtbnMgYnkgaXRzIG93biBsYXlvdXQsIHdoaWNoXG4vLyBuZWl0aGVyIGpzUERGIG5vciBQb3dlclBvaW50IHJlcHJvZHVjZXMuIFNvIHRoZSBibG9jayBpcyByZW5kZXJlZCBvZmZzY3JlZW5cbi8vIHdpdGggdGhlIGNhbnZhcydzIG93biBjb21wb25lbnQsIGF0IHRoZSBjYW52YXMncyA5NnB4IHBlciBpbmNoIGFuZCB1bnNjYWxlZCxcbi8vIGFuZCB0aGUgZXhwb3J0cyBwbGFjZSB3aGF0IHRoZXkgZHJhdyB3aGVyZSBpdCBzYXQ6IGEgdGFibGUgYXQgaXRzIHRvcCwgaW5cbi8vIGl0cyBjb2x1bW4gd2lkdGhzIGFuZCByb3cgaGVpZ2h0cywgYW5kIHRoZSB3b3JkcyBiZXR3ZWVuIHRhYmxlcyBhdCB0aGVpcnMuXG4vLyBJdCBhbHNvIHRlbGxzIHdoZXRoZXIgdGhlIGJsb2NrIHJ1bnMgcGFzdCB0aGUgYm90dG9tIG9mIGl0cyBib3guXG4vL1xuLy8gUHJvdmlkZWQgYmVzaWRlIHRoZSBleHBvcnQgc2VydmljZXMsIHNvIHRoZSBibG9jayByZW5kZXJzIHVuZGVyIHRoZSBzYW1lXG4vLyBpbmplY3RvciB0aGUgY2FudmFzJ3MgYmxvY2tzIGRvLlxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIFJlcG9ydFRleHRMYXlvdXRTZXJ2aWNlIHtcblxuICBwcml2YXRlIHJlYWRvbmx5IF9hcHBSZWYgPSBpbmplY3QoQXBwbGljYXRpb25SZWYpO1xuICBwcml2YXRlIHJlYWRvbmx5IF9lbnZpcm9ubWVudEluamVjdG9yID0gaW5qZWN0KEVudmlyb25tZW50SW5qZWN0b3IpO1xuICBwcml2YXRlIHJlYWRvbmx5IF9pbmplY3RvciA9IGluamVjdChJbmplY3Rvcik7XG4gIHByaXZhdGUgcmVhZG9ubHkgX2xheW91dHMgPSBuZXcgTWFwPHN0cmluZywgUHJvbWlzZTxUZXh0QmxvY2tMYXlvdXQ+PigpO1xuXG4gIC8vIEEgYmxvY2sgaXMgbWVhc3VyZWQgb25jZSBwZXIgc2l6ZSwgcGFkZGluZyBhbmQgZmlsbGVkIGh0bWw6IGFuIGV4cG9ydCB0aGF0XG4gIC8vIGRyYXdzIGl0IHR3aWNlLCBvciBhIHNlY29uZCBleHBvcnQgd2l0aCB0aGUgc2FtZSBudW1iZXJzLCByZWFkcyB0aGUgc2FtZVxuICAvLyBsYXlvdXQsIHdoaWNoIG5vdGhpbmcgY2hhbmdlcy5cbiAgcHVibGljIGFzeW5jIG1lYXN1cmUoY29tcG9uZW50OiBSZXBvcnRDb21wb25lbnQsIHRva2VuczogVGV4dFRva2VuQ29udGV4dCk6IFByb21pc2U8VGV4dEJsb2NrTGF5b3V0PiB7XG4gICAgY29uc3QgaHRtbCA9IGNvbXBvbmVudC5jb25maWc/Lmh0bWwgPz8gJyc7XG4gICAgY29uc3Qga2V5ID0gW1xuICAgICAgY29tcG9uZW50LmlkLFxuICAgICAgY29tcG9uZW50LncsXG4gICAgICBjb21wb25lbnQuaCxcbiAgICAgIEpTT04uc3RyaW5naWZ5KGNvbXBvbmVudC5jb25maWc/LnBhZGRpbmcgPz8gbnVsbCksXG4gICAgICBmaWxsVGV4dFRva2VucyhodG1sLCB0b2tlbnMpLFxuICAgIF0uam9pbignfCcpO1xuXG4gICAgbGV0IGxheW91dCA9IHRoaXMuX2xheW91dHMuZ2V0KGtleSk7XG4gICAgaWYgKCFsYXlvdXQpIHtcbiAgICAgIGxheW91dCA9IHRoaXMuX3JlbmRlcihjb21wb25lbnQsIGh0bWwsIHRva2Vucyk7XG4gICAgICB0aGlzLl9sYXlvdXRzLnNldChrZXksIGxheW91dCk7XG4gICAgICAvLyBBIG1lYXN1cmUgdGhhdCBmYWlsZWQgaXMgdHJpZWQgYWdhaW4gbmV4dCB0aW1lLlxuICAgICAgbGF5b3V0LmNhdGNoKCgpID0+IHRoaXMuX2xheW91dHMuZGVsZXRlKGtleSkpO1xuICAgIH1cblxuICAgIHJldHVybiBsYXlvdXQ7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIF9yZW5kZXIoY29tcG9uZW50OiBSZXBvcnRDb21wb25lbnQsIGh0bWw6IHN0cmluZywgdG9rZW5zOiBUZXh0VG9rZW5Db250ZXh0KTogUHJvbWlzZTxUZXh0QmxvY2tMYXlvdXQ+IHtcbiAgICBjb25zdCB0ZXh0ID0gY3JlYXRlQ29tcG9uZW50KENvbXBvbmVudFRleHRDb21wb25lbnQsIHtcbiAgICAgIGVudmlyb25tZW50SW5qZWN0b3I6IHRoaXMuX2Vudmlyb25tZW50SW5qZWN0b3IsXG4gICAgICBlbGVtZW50SW5qZWN0b3I6IHRoaXMuX2luamVjdG9yLFxuICAgIH0pO1xuICAgIGNvbnN0IGJveCA9IGJsb2NrQm94KGNvbXBvbmVudCwgdGV4dC5sb2NhdGlvbi5uYXRpdmVFbGVtZW50KTtcblxuICAgIHRyeSB7XG4gICAgICB0ZXh0LnNldElucHV0KCdodG1sJywgaHRtbCk7XG4gICAgICB0ZXh0LnNldElucHV0KCd0b2tlbnMnLCB0b2tlbnMpO1xuICAgICAgdGV4dC5zZXRJbnB1dCgnZWRpdGluZycsIGZhbHNlKTtcbiAgICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kKGJveCk7XG4gICAgICBhd2FpdCB0aGlzLl9yZW5kZXJlZCh0ZXh0KTtcbiAgICAgIC8vIExhaWQgb3V0IGZpcnN0LCBzbyBhIGZvbnQgdGhlIHdvcmRzIGFzayBmb3IgaXMgbG9hZGluZyBieSB0aGUgdGltZVxuICAgICAgLy8gZm9udHMucmVhZHkgaXMgcmVhZC5cbiAgICAgIGJveC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgIGF3YWl0IGRvY3VtZW50LmZvbnRzLnJlYWR5O1xuXG4gICAgICByZXR1cm4gbWVhc3VyZUJsb2NrKHRleHQubG9jYXRpb24ubmF0aXZlRWxlbWVudC5xdWVyeVNlbGVjdG9yKCcudGV4dC1jb250ZW50JykpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICAvLyBEZXN0cm95aW5nIHRoZSBibG9jayBhbHNvIHRha2VzIGl0IG9mZiB0aGUgYXBwbGljYXRpb24uXG4gICAgICB0ZXh0LmRlc3Ryb3koKTtcbiAgICAgIGJveC5yZW1vdmUoKTtcbiAgICB9XG4gIH1cblxuICAvLyBUaGUgYmxvY2sgaXMgcmVuZGVyZWQgYnkgdGhlIGFwcGxpY2F0aW9uJ3Mgb3duIGNoYW5nZSBkZXRlY3Rpb24sIGFzIGFueVxuICAvLyB2aWV3IGF0dGFjaGVkIHRvIGl0OiBpdHMgaW5wdXRzIG1hcmsgaXQgZm9yIHRoZSBuZXh0IHJlbmRlciwgd2hpY2ggZHJhd3NcbiAgLy8gaXQgYmVmb3JlIHRoZSBjYWxsYmFjayBydW5zLiBOb3Qgd2hlblN0YWJsZSgpOiB0aGF0IGFsc28gd2FpdHMgb3V0XG4gIC8vIHdoYXRldmVyIGVsc2UgdGhlIGhvc3QgYXBwIGhhcyB1bmRlciB3YXkgKGl0cyByZXF1ZXN0cyBhbmQsIHVuZGVyXG4gIC8vIHpvbmUuanMsIGl0cyB0aW1lcnMpLCBhbmQgbmV2ZXIgcmVzb2x2ZXMgd2hpbGUgYSB0aW1lciByZXBlYXRzLlxuICBwcml2YXRlIF9yZW5kZXJlZCh0ZXh0OiBDb21wb25lbnRSZWY8Q29tcG9uZW50VGV4dENvbXBvbmVudD4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICAgIGFmdGVyTmV4dFJlbmRlcigoKSA9PiByZXNvbHZlKCksIHsgaW5qZWN0b3I6IHRoaXMuX2Vudmlyb25tZW50SW5qZWN0b3IgfSk7XG4gICAgICB0aGlzLl9hcHBSZWYuYXR0YWNoVmlldyh0ZXh0Lmhvc3RWaWV3KTtcbiAgICB9KTtcbiAgfVxufVxuXG4vLyBUaGUgYmxvY2sncyBib3ggYXMgdGhlIGNhbnZhcyBkcmF3cyBpdCAodGhlIGNvbXBvbmVudCBib3gpOiBpdHMgc2l6ZSwgYVxuLy8gMXB4IGJvcmRlciBhbmQgdGhlIGJsb2NrJ3MgcGFkZGluZyAoY29tcG9uZW50UGFkZGluZ0NzcykgYXJvdW5kIGEgYm9keSB0aGVcbi8vIHRleHQgZmlsbHMuIEZpeGVkIGZhciBvZmYgdG8gdGhlIGxlZnQsIGFuZCBoaWRkZW4sIHNvIGl0IGlzIG5ldmVyIHNlZW4uXG5mdW5jdGlvbiBibG9ja0JveChjb21wb25lbnQ6IFJlcG9ydENvbXBvbmVudCwgdGV4dDogSFRNTEVsZW1lbnQpOiBIVE1MRWxlbWVudCB7XG4gIGNvbnN0IGJveCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICBjb25zdCBib2R5ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG5cbiAgT2JqZWN0LmFzc2lnbihib3guc3R5bGUsIHtcbiAgICBwb3NpdGlvbjogJ2ZpeGVkJyxcbiAgICBsZWZ0OiAnLTEwMDAwcHgnLFxuICAgIHRvcDogJzAnLFxuICAgIHZpc2liaWxpdHk6ICdoaWRkZW4nLFxuICAgIHdpZHRoOiBgJHtjb21wb25lbnQudyAqIFBYX1BFUl9JTkNIfXB4YCxcbiAgICBoZWlnaHQ6IGAke2NvbXBvbmVudC5oICogUFhfUEVSX0lOQ0h9cHhgLFxuICAgIGJveFNpemluZzogJ2JvcmRlci1ib3gnLFxuICAgIGJvcmRlcjogJzFweCBzb2xpZCB0cmFuc3BhcmVudCcsXG4gICAgcGFkZGluZzogY29tcG9uZW50UGFkZGluZ0Nzcyhjb21wb25lbnQpLFxuICB9KTtcbiAgYm9keS5zdHlsZS5oZWlnaHQgPSAnMTAwJSc7XG4gIGJvZHkuYXBwZW5kKHRleHQpO1xuICBib3guYXBwZW5kKGJvZHkpO1xuXG4gIHJldHVybiBib3g7XG59XG5cbi8vIFNwbGl0IHRoZSByZW5kZXJlZCBibG9jayBhdCBpdHMgdGFibGVzLCBhcyB0ZXh0QmxvY2tzIHNwbGl0cyB0aGUgc2FtZSBodG1sLFxuLy8gc28gdGhlIG50aCBzZWdtZW50IGlzIHRoZSBudGggdGV4dCBwYXJ0IGFuZCB0aGUgbnRoIHRhYmxlIHRoZSBudGggdGFibGVcbi8vIHBhcnQuIEhvdyBmYXIgdGhlIGJsb2NrIHJlYWNoZXMgaXMgdGhlIGJvdHRvbSBvZiBpdHMgbGFzdCBwYXJ0IHRoYXQgZHJhd3Ncbi8vIGFueXRoaW5nLlxuZnVuY3Rpb24gbWVhc3VyZUJsb2NrKGNvbnRlbnQ6IEhUTUxFbGVtZW50KTogVGV4dEJsb2NrTGF5b3V0IHtcbiAgY29uc3QgYm94ID0gY29udGVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgY29uc3QgcGFydHMgPSBzcGxpdEF0VGFibGVzKGNvbnRlbnQpO1xuICBjb25zdCBzZWdtZW50czogKFRleHRTZWdtZW50TGF5b3V0IHwgbnVsbClbXSA9IFtdO1xuICBjb25zdCB0YWJsZXM6IFRleHRUYWJsZUxheW91dFtdID0gW107XG4gIGxldCB1c2VkSGVpZ2h0ID0gMDtcblxuICBwYXJ0cy5mb3JFYWNoKChwYXJ0LCBpbmRleCkgPT4ge1xuICAgIGlmIChBcnJheS5pc0FycmF5KHBhcnQpKSB7XG4gICAgICBjb25zdCBzZWdtZW50ID0gbWVhc3VyZVNlZ21lbnQoZHJhd25Ob2RlcyhwYXJ0LCBpbmRleCA9PT0gcGFydHMubGVuZ3RoIC0gMSksIGJveCk7XG4gICAgICBzZWdtZW50cy5wdXNoKHNlZ21lbnQpO1xuICAgICAgdXNlZEhlaWdodCA9IHNlZ21lbnQ/LmJvdHRvbSA/PyB1c2VkSGVpZ2h0O1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCB0YWJsZSA9IG1lYXN1cmVUYWJsZShwYXJ0LCBib3gpO1xuICAgICAgdGFibGVzLnB1c2godGFibGUpO1xuICAgICAgdXNlZEhlaWdodCA9IHRhYmxlLnRvcCArIHRhYmxlLmhlaWdodDtcbiAgICB9XG4gIH0pO1xuXG4gIGNvbnN0IGNvbnRlbnRIZWlnaHQgPSBpbmNoZXMoYm94LmhlaWdodCk7XG5cbiAgcmV0dXJuIHtcbiAgICBjb250ZW50V2lkdGg6IGluY2hlcyhib3gud2lkdGgpLFxuICAgIGNvbnRlbnRIZWlnaHQsXG4gICAgdXNlZEhlaWdodCxcbiAgICBvdmVyZmxvdzogdXNlZEhlaWdodCA+IGNvbnRlbnRIZWlnaHQgKyBPVkVSRkxPV19TTEFDSyxcbiAgICBzZWdtZW50cyxcbiAgICB0YWJsZXMsXG4gIH07XG59XG5cbi8vIFRoZSBub2RlcyBvZiBhIHJ1biBiZXR3ZWVuIHRhYmxlcyB0aGF0IHRoZSBleHBvcnRzIGRyYXcuIFdoaXRlc3BhY2UgYmV0d2VlblxuLy8gYmxvY2tzIGRyYXdzIG5vdGhpbmcgYW55d2hlcmUuIEEgYmxhbmsgbGluZSBhdCB0aGUgc3RhcnQgb2YgYSBibG9jayBpc1xuLy8gZHJhd24sIG9uIHRoZSBjYW52YXMgYW5kIGJ5IHRleHRCbG9ja3MgYWxpa2UsIGJ1dCB0ZXh0QmxvY2tzIGRyb3BzIHRoZSBibGFua1xuLy8gbGluZXMgYXQgdGhlIHZlcnkgZW5kIG9mIGEgYmxvY2ssIHNvIHRoZXkgYXJlIG5vdCBtZWFzdXJlZCBlaXRoZXI6IGFcbi8vIHRyYWlsaW5nIGVtcHR5IHBhcmFncmFwaCBuZXZlciBtYWtlcyBhIGJsb2NrIG92ZXJmbG93LlxuZnVuY3Rpb24gZHJhd25Ob2Rlcyhub2RlczogTm9kZVtdLCBibG9ja0VuZDogYm9vbGVhbik6IE5vZGVbXSB7XG4gIGNvbnN0IHNraXBzTGFzdCA9IGJsb2NrRW5kID8gaXNCbGFuayA6IGlzVm9pZDtcbiAgbGV0IHN0YXJ0ID0gMDtcbiAgbGV0IGVuZCA9IG5vZGVzLmxlbmd0aDtcblxuICB3aGlsZSAoc3RhcnQgPCBlbmQgJiYgaXNWb2lkKG5vZGVzW3N0YXJ0XSkpIHtcbiAgICBzdGFydCsrO1xuICB9XG4gIHdoaWxlIChlbmQgPiBzdGFydCAmJiBza2lwc0xhc3Qobm9kZXNbZW5kIC0gMV0pKSB7XG4gICAgZW5kLS07XG4gIH1cblxuICBjb25zdCBkcmF3biA9IG5vZGVzLnNsaWNlKHN0YXJ0LCBlbmQpO1xuICBpZiAoYmxvY2tFbmQgJiYgZHJhd24ubGVuZ3RoKSB7XG4gICAgdHJpbUJsYW5rTGluZXMoZHJhd25bZHJhd24ubGVuZ3RoIC0gMV0pO1xuICB9XG5cbiAgcmV0dXJuIGRyYXduO1xufVxuXG4vLyBUYWtlIHRoZSBibGFuayBsaW5lcyBvZmYgdGhlIGVuZCBvZiB0aGUgYmxvY2sncyBsYXN0IG5vZGUsIGFzIHRleHRCbG9ja3Ncbi8vIGRyb3BzIHRoZW06IHRoZSBlbGVtZW50cyB0aGF0IGhvbGQgbm8gdGV4dCBhZnRlciBpdHMgbGFzdCB3b3JkcywgZG93biBpdHNcbi8vIGxhc3QgY2hpbGRyZW4g4oCUIHRoZSA8YnI+cyBvZiA8cD5iPGJyPjxicj48L3A+LCBhIGxpc3QncyBlbXB0eSBsYXN0IGl0ZW0uXG4vLyBXaGl0ZXNwYWNlIGlzIHBhc3NlZCBvdmVyIGFuZCBsZWZ0LCBzbyBhIHBhcmFncmFwaCBuZXZlciB0dXJucyBpbnRvIGFuXG4vLyBlbXB0eSBvbmUsIHdoaWNoIHRoZSBjYW52YXMgZHJhd3MgYXMgYSBsaW5lLiBUaGUgYmxvY2sgaXMgdGhlIG1lYXN1cmUncyBvd25cbi8vIGNvcHksIHRocm93biBhd2F5IG9uY2UgbWVhc3VyZWQsIGFuZCBub3RoaW5nIGFib3ZlIHdoYXQgaXMgdGFrZW4gb2ZmIG1vdmVzLlxuZnVuY3Rpb24gdHJpbUJsYW5rTGluZXMobm9kZTogTm9kZSk6IHZvaWQge1xuICBsZXQgY2hpbGQgPSBub2RlLmxhc3RDaGlsZDtcbiAgd2hpbGUgKGNoaWxkICYmIGlzQmxhbmsoY2hpbGQpKSB7XG4gICAgY29uc3QgcHJldmlvdXMgPSBjaGlsZC5wcmV2aW91c1NpYmxpbmc7XG4gICAgaWYgKCFpc1ZvaWQoY2hpbGQpKSB7XG4gICAgICBjaGlsZC5yZW1vdmUoKTtcbiAgICB9XG4gICAgY2hpbGQgPSBwcmV2aW91cztcbiAgfVxuXG4gIGlmIChjaGlsZCkge1xuICAgIHRyaW1CbGFua0xpbmVzKGNoaWxkKTtcbiAgfVxufVxuXG4vLyBXaGl0ZXNwYWNlIGJldHdlZW4gYmxvY2tzLCBvciBhIGNvbW1lbnQuXG5mdW5jdGlvbiBpc1ZvaWQobm9kZTogTm9kZSk6IGJvb2xlYW4ge1xuICByZXR1cm4gbm9kZS5ub2RlVHlwZSA9PT0gTm9kZS5URVhUX05PREVcbiAgICA/ICEvW14gXFx0XFxuXFxyXFxmXS8udGVzdChub2RlLnRleHRDb250ZW50ID8/ICcnKVxuICAgIDogbm9kZS5ub2RlVHlwZSAhPT0gTm9kZS5FTEVNRU5UX05PREU7XG59XG5cbi8vIEEgbm9kZSB0aGF0IGRyYXdzIG5vIHdvcmRzOiB3aGl0ZXNwYWNlLCBvciBhbiBlbGVtZW50IHdpdGggbm8gdGV4dCBpbiBpdCxcbi8vIHN1Y2ggYXMgdGhlIGVtcHR5IGxpbmUgPHA+PGJyPjwvcD4uXG5mdW5jdGlvbiBpc0JsYW5rKG5vZGU6IE5vZGUpOiBib29sZWFuIHtcbiAgcmV0dXJuIGlzVm9pZChub2RlKSB8fCAhbm9kZS50ZXh0Q29udGVudDtcbn1cblxuLy8gRnJvbSBiZWZvcmUgaXRzIGZpcnN0IG5vZGUgdG8gYWZ0ZXIgaXRzIGxhc3QuIG51bGwgZm9yIGEgcnVuIHRoYXQgZHJhd3Ncbi8vIG5vdGhpbmcuXG5mdW5jdGlvbiBtZWFzdXJlU2VnbWVudChub2RlczogTm9kZVtdLCBib3g6IERPTVJlY3QpOiBUZXh0U2VnbWVudExheW91dCB8IG51bGwge1xuICBpZiAoIW5vZGVzLmxlbmd0aCkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgY29uc3QgcmFuZ2UgPSBkb2N1bWVudC5jcmVhdGVSYW5nZSgpO1xuICByYW5nZS5zZXRTdGFydEJlZm9yZShub2Rlc1swXSk7XG4gIHJhbmdlLnNldEVuZEFmdGVyKG5vZGVzW25vZGVzLmxlbmd0aCAtIDFdKTtcbiAgY29uc3QgcmVjdCA9IHJhbmdlLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuXG4gIHJldHVybiB7IHRvcDogaW5jaGVzKHJlY3QudG9wIC0gYm94LnRvcCksIGJvdHRvbTogaW5jaGVzKHJlY3QuYm90dG9tIC0gYm94LnRvcCkgfTtcbn1cblxuZnVuY3Rpb24gbWVhc3VyZVRhYmxlKHRhYmxlOiBIVE1MVGFibGVFbGVtZW50LCBib3g6IERPTVJlY3QpOiBUZXh0VGFibGVMYXlvdXQge1xuICBjb25zdCByZWN0ID0gdGFibGUuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG5cbiAgcmV0dXJuIHtcbiAgICB0b3A6IGluY2hlcyhyZWN0LnRvcCAtIGJveC50b3ApLFxuICAgIGxlZnQ6IGluY2hlcyhyZWN0LmxlZnQgLSBib3gubGVmdCksXG4gICAgd2lkdGg6IGluY2hlcyhyZWN0LndpZHRoKSxcbiAgICBoZWlnaHQ6IGluY2hlcyhyZWN0LmhlaWdodCksXG4gICAgcm93SGVpZ2h0czogQXJyYXkuZnJvbSh0YWJsZS5yb3dzLCAocm93KSA9PiBpbmNoZXMocm93LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLmhlaWdodCkpLFxuICAgIGNvbHVtbldpZHRoczogY29sdW1uV2lkdGhzKHRhYmxlLCByZWN0LndpZHRoKS5tYXAoaW5jaGVzKSxcbiAgfTtcbn1cblxuLy8gQSBncmlkIGNvbHVtbiBpcyBhcyB3aWRlIGFzIGEgY2VsbCB0aGF0IHNwYW5zIG9ubHkgaXQuIEEgY29sdW1uIHRoYXQgb25seVxuLy8gc3Bhbm5pbmcgY2VsbHMgY3Jvc3Mgc2hhcmVzIHdoYXQgdGhlIG90aGVycyBsZWF2ZSBvZiB0aGUgdGFibGUncyB3aWR0aCwgYW5kXG4vLyBhbGwgb2YgdGhlbSBhcmUgc2NhbGVkIHRvIGFkZCB1cCB0byBpdCBleGFjdGx5LiBUaGUgY2VsbHMgY29tZSBpbiB0aGUgc2FtZVxuLy8gb3JkZXIgYXMgdGhlIGdyaWQncyAocGFyc2VUYWJsZSByZWFkcyB0aGUgc2FtZSByb3dzKSwgc28gdGhlIG50aCBjZWxsIG9mIGFcbi8vIHJvdyBpcyB0aGUgbnRoIGNlbGwgb2YgdGhhdCBncmlkIHJvdy5cbmZ1bmN0aW9uIGNvbHVtbldpZHRocyh0YWJsZTogSFRNTFRhYmxlRWxlbWVudCwgd2lkdGg6IG51bWJlcik6IG51bWJlcltdIHtcbiAgY29uc3QgZ3JpZCA9IHBhcnNlVGFibGUodGFibGUpO1xuICBjb25zdCB3aWR0aHM6IChudW1iZXIgfCBudWxsKVtdID0gQXJyYXkuZnJvbSh7IGxlbmd0aDogZ3JpZC5jb2x1bW5zIH0sICgpID0+IG51bGwpO1xuXG4gIGdyaWQucm93cy5mb3JFYWNoKChyb3csIHJvd0luZGV4KSA9PiByb3cuY2VsbHMuZm9yRWFjaCgoY2VsbCwgY2VsbEluZGV4KSA9PiB7XG4gICAgaWYgKGNlbGwuY29sU3BhbiA9PT0gMSAmJiB3aWR0aHNbY2VsbC5jb2x1bW5dID09PSBudWxsKSB7XG4gICAgICB3aWR0aHNbY2VsbC5jb2x1bW5dID0gdGFibGUucm93c1tyb3dJbmRleF0uY2VsbHNbY2VsbEluZGV4XS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS53aWR0aDtcbiAgICB9XG4gIH0pKTtcblxuICBjb25zdCBrbm93biA9IHdpZHRocy5maWx0ZXIoKHZhbHVlKTogdmFsdWUgaXMgbnVtYmVyID0+IHZhbHVlICE9PSBudWxsKTtcbiAgY29uc3Qgc2hhcmUgPSBNYXRoLm1heCgwLCB3aWR0aCAtIHN1bShrbm93bikpIC8gTWF0aC5tYXgoMSwgd2lkdGhzLmxlbmd0aCAtIGtub3duLmxlbmd0aCk7XG4gIGNvbnN0IGZpbGxlZCA9IHdpZHRocy5tYXAoKHZhbHVlKSA9PiB2YWx1ZSA/PyBzaGFyZSk7XG4gIGNvbnN0IHRvdGFsID0gc3VtKGZpbGxlZCk7XG5cbiAgcmV0dXJuIGZpbGxlZC5tYXAoKHZhbHVlKSA9PiB0b3RhbCA/IHZhbHVlICogd2lkdGggLyB0b3RhbCA6IHdpZHRoIC8gZmlsbGVkLmxlbmd0aCk7XG59XG5cbmZ1bmN0aW9uIHN1bSh2YWx1ZXM6IG51bWJlcltdKTogbnVtYmVyIHtcbiAgcmV0dXJuIHZhbHVlcy5yZWR1Y2UoKHRvdGFsLCB2YWx1ZSkgPT4gdG90YWwgKyB2YWx1ZSwgMCk7XG59XG5cbmZ1bmN0aW9uIGluY2hlcyhwaXhlbHM6IG51bWJlcik6IG51bWJlciB7XG4gIHJldHVybiBwaXhlbHMgLyBQWF9QRVJfSU5DSDtcbn1cbiJdfQ==
@@ -0,0 +1,283 @@
1
+ import { RELATIVE_RANGE_NAMES, isRelativeRange } from './report-view-config';
2
+ import { offersExclude } from './report-viewer-features';
3
+ // The Type select's choices. A column that can be either holds both.
4
+ export const FILTER_TYPE_OPTIONS = [
5
+ { value: 'select', name: 'Values' },
6
+ { value: 'numberRange', name: 'Number range' },
7
+ ];
8
+ export const TYPE_LOCKED_TOOLTIP = 'Remove the filter to change its type.';
9
+ export const PAGE_FILTER_TOOLTIP = 'A page filter shows in the page bar only.';
10
+ export const COMPONENT_TOGGLE_TOOLTIP = 'Show on this component';
11
+ // The Default period select's value for a range of fixed days. No relative
12
+ // range is named this.
13
+ export const FIXED_DATES_PERIOD = 'fixed';
14
+ // How many decimals a Default minimum or Default maximum takes.
15
+ export const DEFAULT_BOUND_SCALE = 6;
16
+ // Every Report bar choice, in the order the select lists them.
17
+ const BAR_PLACEMENT_OPTIONS = [
18
+ { value: 'off', name: 'Off' },
19
+ { value: 'every', name: 'Every page' },
20
+ { value: 'page', name: 'This page only' },
21
+ ];
22
+ // A number with its group commas in place ('1,250.5', '-12,000').
23
+ const GROUPED_DECIMAL = /^-?\d{1,3}(,\d{3})+(\.\d*)?$/;
24
+ // A plain decimal number ('1250.5', '-3', '0', '.5'). Hex, binary, octal,
25
+ // exponents and inner spaces do not match, though Number() reads some.
26
+ const PLAIN_DECIMAL = /^-?(\d+(\.\d*)?|\.\d+)$/;
27
+ // A default range end as typed. An empty field is no end. A number input
28
+ // with a mask hands back text with its group commas ('1,250.5'), so those go
29
+ // before Number() reads it; 0 is an end like any other. Anything that is not
30
+ // a decimal number is no end.
31
+ export function parseDefaultBound(raw) {
32
+ if (typeof raw === 'number') {
33
+ return Number.isFinite(raw) ? raw : null;
34
+ }
35
+ if (typeof raw !== 'string') {
36
+ return null;
37
+ }
38
+ const trimmed = raw.trim();
39
+ const text = GROUPED_DECIMAL.test(trimmed) ? trimmed.replace(/,/g, '') : trimmed;
40
+ if (!PLAIN_DECIMAL.test(text)) {
41
+ return null;
42
+ }
43
+ const value = Number(text);
44
+ return Number.isFinite(value) ? value : null;
45
+ }
46
+ // Why two range ends cannot be saved, in the server's words, or null. An open
47
+ // end is always fine.
48
+ export function boundsError(min, max) {
49
+ if (min === null || max === null || min <= max) {
50
+ return null;
51
+ }
52
+ return `min (${min}) is above max (${max}).`;
53
+ }
54
+ // The Type select of a column on the component settings' Filters tab. It
55
+ // shows when the column can take either type and the server serves number
56
+ // ranges (an older server lists no features). A filter's type cannot change,
57
+ // so it is locked while the column has a filter on this component.
58
+ export function typeSelectState(types, hasFilterOnThisComponent, features) {
59
+ const show = (features ?? []).includes('numberRange')
60
+ && FILTER_TYPE_OPTIONS.every((option) => (types ?? []).includes(option.value));
61
+ if (!show) {
62
+ return { show: false, disabled: false, tooltip: null };
63
+ }
64
+ return {
65
+ show: true,
66
+ disabled: hasFilterOnThisComponent,
67
+ tooltip: hasFilterOnThisComponent ? TYPE_LOCKED_TOOLTIP : null,
68
+ };
69
+ }
70
+ // The levels a new or moved filter can take on a component. This page only
71
+ // needs a server that serves page filters and a component on a page (a
72
+ // header or footer component is on no page).
73
+ export function filterLevelChoices(features, onPage) {
74
+ const levels = ['component', 'report', 'both'];
75
+ return onPage && (features ?? []).includes('pageScope')
76
+ ? [...levels, 'page']
77
+ : levels;
78
+ }
79
+ // The Report bar select's choices for the levels on offer. The choice a row
80
+ // already holds is always listed, so the select never shows blank.
81
+ export function barPlacementOptions(levelChoices, current = 'off') {
82
+ return BAR_PLACEMENT_OPTIONS.filter((option) => {
83
+ switch (option.value) {
84
+ case 'every':
85
+ return levelChoices.includes('report') || levelChoices.includes('both') || current === 'every';
86
+ case 'page':
87
+ return levelChoices.includes('page') || current === 'page';
88
+ default:
89
+ return true;
90
+ }
91
+ });
92
+ }
93
+ // A value's Report bar choices. A value has no strip of its own and its
94
+ // group may be shared, so a pick never lowers the group (the inline values
95
+ // rule): This page only is offered for a new filter, or for a group that is
96
+ // already a page group, never to move a shared group to one page.
97
+ export function valuePlacementOptions(levelChoices, current) {
98
+ const choices = !current || current === 'page'
99
+ ? levelChoices
100
+ : levelChoices.filter((level) => level !== 'page');
101
+ return barPlacementOptions(choices, barPlacement(current));
102
+ }
103
+ // The level a value's filter group ends at after a Report bar pick, or null
104
+ // when the value leaves it. Off unlinks this value alone and the group keeps
105
+ // its other members. A new filter takes the pick's level. Every page raises a
106
+ // strip-only group to both, keeping its strips, and a page group to the
107
+ // report bar. Nothing else moves the group, so a value never lowers it.
108
+ export function valueFilterLevel(placement, current) {
109
+ if (placement === 'off') {
110
+ return null;
111
+ }
112
+ if (!current) {
113
+ return placement === 'page' ? 'page' : 'report';
114
+ }
115
+ if (placement !== 'every') {
116
+ return current;
117
+ }
118
+ switch (current) {
119
+ case 'component':
120
+ return 'both';
121
+ case 'page':
122
+ return 'report';
123
+ default:
124
+ return current;
125
+ }
126
+ }
127
+ // Where a group of a level shows in the report bar. No group (no filter) is
128
+ // off.
129
+ export function barPlacement(level) {
130
+ switch (level) {
131
+ case 'report':
132
+ case 'both':
133
+ return 'every';
134
+ case 'page':
135
+ return 'page';
136
+ default:
137
+ return 'off';
138
+ }
139
+ }
140
+ // Whether a group of a level shows on its components.
141
+ export function shownOnComponent(level) {
142
+ return level === 'component' || level === 'both';
143
+ }
144
+ // The level the two controls of a row ask for, or null when they ask for no
145
+ // filter at all. A page filter shows in its page's bar only, so This page
146
+ // only ignores the This component toggle.
147
+ export function filterLevel(placement, component) {
148
+ switch (placement) {
149
+ case 'page':
150
+ return 'page';
151
+ case 'every':
152
+ return component ? 'both' : 'report';
153
+ default:
154
+ return component ? 'component' : null;
155
+ }
156
+ }
157
+ // The This component toggle of a row: locked while This page only is picked.
158
+ export function componentToggleState(placement) {
159
+ return placement === 'page'
160
+ ? { disabled: true, tooltip: PAGE_FILTER_TOOLTIP }
161
+ : { disabled: false, tooltip: COMPONENT_TOGGLE_TOOLTIP };
162
+ }
163
+ // The groups the report settings' Filters tab lists defaults for: those of
164
+ // the report bar, every page or one, in bar order.
165
+ export function defaultRowGroups(groups) {
166
+ return (groups ?? [])
167
+ .filter((group) => group.level === 'report' || group.level === 'both' || group.level === 'page')
168
+ .sort((a, b) => a.order - b.order);
169
+ }
170
+ // A default row's label: a page group names its page, 'Region (page
171
+ // "Overview")'. A page with no name reads as the canvas names it ('Page 2').
172
+ // A page this report no longer holds adds nothing.
173
+ export function defaultRowLabel(group, pages) {
174
+ const label = group.label || group.filters?.[0]?.filterColumn || 'Filter';
175
+ if (group.level !== 'page') {
176
+ return label;
177
+ }
178
+ const index = (pages ?? []).findIndex((page) => page.id === group.pageId);
179
+ if (index < 0) {
180
+ return label;
181
+ }
182
+ return `${label} (page "${pages[index].name || `Page ${index + 1}`}")`;
183
+ }
184
+ // The Default period select's choices: Fixed dates, then every relative
185
+ // range in the server enum's order, named by `labels`. A stored range this
186
+ // viewer does not know is listed last, so the select still shows it.
187
+ export function defaultPeriodOptions(labels, stored = null) {
188
+ const options = [
189
+ { value: FIXED_DATES_PERIOD, name: 'Fixed dates' },
190
+ ...RELATIVE_RANGE_NAMES.map((relative) => ({ value: relative, name: labels(relative) })),
191
+ ];
192
+ return stored && stored !== FIXED_DATES_PERIOD && !isRelativeRange(stored)
193
+ ? [...options, { value: stored, name: labels(stored) }]
194
+ : options;
195
+ }
196
+ // The Default period a stored date range default opens on: its relative
197
+ // range, else Fixed dates (the days, or none).
198
+ export function defaultPeriod(stored) {
199
+ return stored?.relative && !stored.start && !stored.end
200
+ ? stored.relative
201
+ : FIXED_DATES_PERIOD;
202
+ }
203
+ // A date range default in its stored shape: the relative range picked, else
204
+ // the fixed days, or null when there are none. Never both: the server
205
+ // refuses a relative range with days.
206
+ export function dateRangeDefault(period, start, end) {
207
+ if (period !== FIXED_DATES_PERIOD) {
208
+ return { relative: period };
209
+ }
210
+ if (!start && !end) {
211
+ return null;
212
+ }
213
+ return { ...(start ? { start } : {}), ...(end ? { end } : {}) };
214
+ }
215
+ // A select default in its stored shape: the picks kept, or left out while
216
+ // Exclude these values is on, or null when nothing is picked.
217
+ export function selectDefault(values, exclude) {
218
+ if (!values.length) {
219
+ return null;
220
+ }
221
+ return exclude ? { excludeValues: values } : { values };
222
+ }
223
+ // A number range default in its stored shape from the ends as typed: an
224
+ // open end is left out, 0 is kept, and two open ends are no default.
225
+ export function numberRangeDefault(rawMin, rawMax) {
226
+ const min = parseDefaultBound(rawMin);
227
+ const max = parseDefaultBound(rawMax);
228
+ if (min === null && max === null) {
229
+ return null;
230
+ }
231
+ return { ...(min !== null ? { min } : {}), ...(max !== null ? { max } : {}) };
232
+ }
233
+ // Whether a select group's default row offers Exclude these values: the
234
+ // report bar's rule (offersExclude), so not on a server that does not serve
235
+ // exclude (an older server lists no features) nor on a group with a member
236
+ // that binds several columns (multiColumn). A default that already leaves
237
+ // values out keeps the toggle, so it can be turned off.
238
+ export function showExcludeToggle(group, features) {
239
+ if (group.type === 'select' && group.config?.default?.excludeValues?.length) {
240
+ return true;
241
+ }
242
+ return offersExclude(group, features);
243
+ }
244
+ // A stored or draft default in a stable form for comparing: empty and
245
+ // absent keys are dropped, so a no-op edit does not read as a change. 0 is an
246
+ // end like any other. Nothing left is null.
247
+ export function normalizeDefault(value) {
248
+ if (!value) {
249
+ return null;
250
+ }
251
+ const normalized = {};
252
+ if (value.start) {
253
+ normalized.start = value.start;
254
+ }
255
+ if (value.end) {
256
+ normalized.end = value.end;
257
+ }
258
+ if (value.values?.length) {
259
+ normalized.values = value.values;
260
+ }
261
+ if (value.excludeValues?.length) {
262
+ normalized.excludeValues = value.excludeValues;
263
+ }
264
+ if (typeof value.min === 'number') {
265
+ normalized.min = value.min;
266
+ }
267
+ if (typeof value.max === 'number') {
268
+ normalized.max = value.max;
269
+ }
270
+ if (value.value) {
271
+ normalized.value = value.value;
272
+ }
273
+ if (value.relative) {
274
+ normalized.relative = value.relative;
275
+ }
276
+ return Object.keys(normalized).length ? normalized : null;
277
+ }
278
+ // Whether a row's draft default differs from the group's stored one. Only a
279
+ // changed row is saved.
280
+ export function defaultChanged(stored, draft) {
281
+ return JSON.stringify(normalizeDefault(stored)) !== JSON.stringify(normalizeDefault(draft));
282
+ }
283
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlsdGVyLXNldHRpbmdzLXJ1bGVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL2ZpbHRlci1zZXR0aW5ncy1ydWxlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFtQkEsT0FBTyxFQUFFLG9CQUFvQixFQUFFLGVBQWUsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQzdFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUd6RCxxRUFBcUU7QUFDckUsTUFBTSxDQUFDLE1BQU0sbUJBQW1CLEdBQTZDO0lBQzNFLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFO0lBQ25DLEVBQUUsS0FBSyxFQUFFLGFBQWEsRUFBRSxJQUFJLEVBQUUsY0FBYyxFQUFFO0NBQy9DLENBQUM7QUFFRixNQUFNLENBQUMsTUFBTSxtQkFBbUIsR0FBRyx1Q0FBdUMsQ0FBQztBQUMzRSxNQUFNLENBQUMsTUFBTSxtQkFBbUIsR0FBRywyQ0FBMkMsQ0FBQztBQUMvRSxNQUFNLENBQUMsTUFBTSx3QkFBd0IsR0FBRyx3QkFBd0IsQ0FBQztBQUVqRSwyRUFBMkU7QUFDM0UsdUJBQXVCO0FBQ3ZCLE1BQU0sQ0FBQyxNQUFNLGtCQUFrQixHQUFHLE9BQU8sQ0FBQztBQUUxQyxnRUFBZ0U7QUFDaEUsTUFBTSxDQUFDLE1BQU0sbUJBQW1CLEdBQUcsQ0FBQyxDQUFDO0FBRXJDLCtEQUErRDtBQUMvRCxNQUFNLHFCQUFxQixHQUErQztJQUN4RSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRTtJQUM3QixFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRTtJQUN0QyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLGdCQUFnQixFQUFFO0NBQzFDLENBQUM7QUFHRixrRUFBa0U7QUFDbEUsTUFBTSxlQUFl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TUFBTSxVQUFVLGNBQWMsQ0FDNUIsTUFBNkMsRUFDN0MsS0FBNEM7SUFFNUMsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLGdCQUFnQixDQUFDLE1BQU0sQ0FBQyxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO0FBQzlGLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBUaGUgcnVsZXMgYmVoaW5kIHRoZSB0d28gZmlsdGVyIHNldHRpbmdzIGRpYWxvZ3MsIGtlcHQgcHVyZSBzbyB0aGUgbm9kZVxuLy8gaGFybmVzcyBjaGVja3MgdGhlbSB3aXRob3V0IGEgZGlhbG9nLiBUaGUgY29tcG9uZW50IHNldHRpbmdzJyBGaWx0ZXJzIHRhYlxuLy8gcmVhZHMgdGhlIFR5cGUgc2VsZWN0LCB0aGUgUmVwb3J0IGJhciBzZWxlY3QgYW5kIHRoZSBUaGlzIGNvbXBvbmVudCB0b2dnbGVcbi8vIGZyb20gaGVyZTsgdGhlIHJlcG9ydCBzZXR0aW5ncycgRmlsdGVycyB0YWIgcmVhZHMgaXRzIGRlZmF1bHQgcm93cyAodGhlXG4vLyBwZXJpb2QsIHRoZSBleGNsdWRlIHRvZ2dsZSwgdGhlIG51bWJlciByYW5nZSBlbmRzIGFuZCB0aGVpciBjaGVjaykgZnJvbVxuLy8gaGVyZS4gVGhlIGRpYWxvZ3Mgb25seSBjYWxsIHRoZXNlLlxuaW1wb3J0IHsgRmlsdGVyQmFyUGxhY2VtZW50IH0gZnJvbSAnLi9pbnRlcmZhY2VzL2ZpbHRlci1iYXItcGxhY2VtZW50LnR5cGUnO1xuaW1wb3J0IHsgRmlsdGVyQ29tcG9uZW50VG9nZ2xlU3RhdGUgfSBmcm9tICcuL2ludGVyZmFjZXMvZmlsdGVyLWNvbXBvbmVudC10b2dnbGUtc3RhdGUuaW50ZXJmYWNlJztcbmltcG9ydCB7IEZpbHRlclNldHRpbmdzT3B0aW9uIH0gZnJvbSAnLi9pbnRlcmZhY2VzL2ZpbHRlci1zZXR0aW5ncy1vcHRpb24uaW50ZXJmYWNlJztcbmltcG9ydCB7IEZpbHRlclR5cGVTZWxlY3RTdGF0ZSB9IGZyb20gJy4vaW50ZXJmYWNlcy9maWx0ZXItdHlwZS1zZWxlY3Qtc3RhdGUuaW50ZXJmYWNlJztcbmltcG9ydCB7IFJlcG9ydFZpZXdlckZlYXR1cmUgfSBmcm9tICcuL2ludGVyZmFjZXMvcmVwb3J0LXZpZXdlci1mZWF0dXJlLnR5cGUnO1xuaW1wb3J0IHtcbiAgRmlsdGVyR3JvdXBEZWZhdWx0LFxuICBSZXBvcnRGaWx0ZXJHcm91cCxcbiAgUmVwb3J0RmlsdGVyTGV2ZWwsXG4gIFJlcG9ydEZpbHRlclR5cGUsXG4gIFJlcG9ydFBhZ2UsXG4gIFJlcG9ydFJlbGF0aXZlUmFuZ2UsXG59IGZyb20gJy4vaW50ZXJmYWNlcy9yZXBvcnQuaW50ZXJmYWNlJztcbmltcG9ydCB7IFJFTEFUSVZFX1JBTkdFX05BTUVTLCBpc1JlbGF0aXZlUmFuZ2UgfSBmcm9tICcuL3JlcG9ydC12aWV3LWNvbmZpZyc7XG5pbXBvcnQgeyBvZmZlcnNFeGNsdWRlIH0gZnJvbSAnLi9yZXBvcnQtdmlld2VyLWZlYXR1cmVzJztcblxuXG4vLyBUaGUgVHlwZSBzZWxlY3QncyBjaG9pY2VzLiBBIGNvbHVtbiB0aGF0IGNhbiBiZSBlaXRoZXIgaG9sZHMgYm90aC5cbmV4cG9ydCBjb25zdCBGSUxURVJfVFlQRV9PUFRJT05TOiBGaWx0ZXJTZXR0aW5nc09wdGlvbjxSZXBvcnRGaWx0ZXJUeXBlPltdID0gW1xuICB7IHZhbHVlOiAnc2VsZWN0JywgbmFtZTogJ1ZhbHVlcycgfSxcbiAgeyB2YWx1ZTogJ251bWJlclJhbmdlJywgbmFtZTogJ051bWJlciByYW5nZScgfSxcbl07XG5cbmV4cG9ydCBjb25zdCBUWVBFX0xPQ0tFRF9UT09MVElQID0gJ1JlbW92ZSB0aGUgZmlsdGVyIHRvIGNoYW5nZSBpdHMgdHlwZS4nO1xuZXhwb3J0IGNvbnN0IFBBR0VfRklMVEVSX1RPT0xUSVAgPSAnQSBwYWdlIGZpbHRlciBzaG93cyBpbiB0aGUgcGFnZSBiYXIgb25seS4nO1xuZXhwb3J0IGNvbnN0IENPTVBPTkVOVF9UT0dHTEVfVE9PTFRJUCA9ICdTaG93IG9uIHRoaXMgY29tcG9uZW50JztcblxuLy8gVGhlIERlZmF1bHQgcGVyaW9kIHNlbGVjdCdzIHZhbHVlIGZvciBhIHJhbmdlIG9mIGZpeGVkIGRheXMuIE5vIHJlbGF0aXZlXG4vLyByYW5nZSBpcyBuYW1lZCB0aGlzLlxuZXhwb3J0IGNvbnN0IEZJWEVEX0RBVEVTX1BFUklPRCA9ICdmaXhlZCc7XG5cbi8vIEhvdyBtYW55IGRlY2ltYWxzIGEgRGVmYXVsdCBtaW5pbXVtIG9yIERlZmF1bHQgbWF4aW11bSB0YWtlcy5cbmV4cG9ydCBjb25zdCBERUZBVUxUX0JPVU5EX1NDQUxFID0gNjtcblxuLy8gRXZlcnkgUmVwb3J0IGJhciBjaG9pY2UsIGluIHRoZSBvcmRlciB0aGUgc2VsZWN0IGxpc3RzIHRoZW0uXG5jb25zdCBCQVJfUExBQ0VNRU5UX09QVElPTlM6IEZpbHRlclNldHRpbmdzT3B0aW9uPEZpbHRlckJhclBsYWNlbWVudD5bXSA9IFtcbiAgeyB2YWx1ZTogJ29mZicsIG5hbWU6ICdPZmYnIH0sXG4gIHsgdmFsdWU6ICdldmVyeScsIG5hbWU6ICdFdmVyeSBwYWdlJyB9LFxuICB7IHZhbHVlOiAncGFnZScsIG5hbWU6ICdUaGlzIHBhZ2Ugb25seScgfSxcbl07XG5cblxuLy8gQSBudW1iZXIgd2l0aCBpdHMgZ3JvdXAgY29tbWFzIGluIHBsYWNlICgnMSwyNTAuNScsICctMTIsMDAwJykuXG5jb25zdCBHUk9VUEVEX0RFQ0lNQUwgPSAvXi0/XFxkezEsM30oLFxcZHszfSkrKFxcLlxcZCopPyQvO1xuLy8gQSBwbGFpbiBkZWNpbWFsIG51bWJlciAoJzEyNTAuNScsICctMycsICcwJywgJy41JykuIEhleCwgYmluYXJ5LCBvY3RhbCxcbi8vIGV4cG9uZW50cyBhbmQgaW5uZXIgc3BhY2VzIGRvIG5vdCBtYXRjaCwgdGhvdWdoIE51bWJlcigpIHJlYWRzIHNvbWUuXG5jb25zdCBQTEFJTl9ERUNJTUFMID0gL14tPyhcXGQrKFxcLlxcZCopP3xcXC5cXGQrKSQvO1xuXG4vLyBBIGRlZmF1bHQgcmFuZ2UgZW5kIGFzIHR5cGVkLiBBbiBlbXB0eSBmaWVsZCBpcyBubyBlbmQuIEEgbnVtYmVyIGlucHV0XG4vLyB3aXRoIGEgbWFzayBoYW5kcyBiYWNrIHRleHQgd2l0aCBpdHMgZ3JvdXAgY29tbWFzICgnMSwyNTAuNScpLCBzbyB0aG9zZSBnb1xuLy8gYmVmb3JlIE51bWJlcigpIHJlYWRzIGl0OyAwIGlzIGFuIGVuZCBsaWtlIGFueSBvdGhlci4gQW55dGhpbmcgdGhhdCBpcyBub3Rcbi8vIGEgZGVjaW1hbCBudW1iZXIgaXMgbm8gZW5kLlxuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlRGVmYXVsdEJvdW5kKHJhdzogdW5rbm93bik6IG51bWJlciB8IG51bGwge1xuICBpZiAodHlwZW9mIHJhdyA9PT0gJ251bWJlcicpIHtcbiAgICByZXR1cm4gTnVtYmVyLmlzRmluaXRlKHJhdykgPyByYXcgOiBudWxsO1xuICB9XG5cbiAgaWYgKHR5cGVvZiByYXcgIT09ICdzdHJpbmcnKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBjb25zdCB0cmltbWVkID0gcmF3LnRyaW0oKTtcbiAgY29uc3QgdGV4dCA9IEdST1VQRURfREVDSU1BTC50ZXN0KHRyaW1tZWQpID8gdHJpbW1lZC5yZXBsYWNlKC8sL2csICcnKSA6IHRyaW1tZWQ7XG4gIGlmICghUExBSU5fREVDSU1BTC50ZXN0KHRleHQpKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBjb25zdCB2YWx1ZSA9IE51bWJlcih0ZXh0KTtcblxuICByZXR1cm4gTnVtYmVyLmlzRmluaXRlKHZhbHVlKSA/IHZhbHVlIDogbnVsbDtcbn1cblxuLy8gV2h5IHR3byByYW5nZSBlbmRzIGNhbm5vdCBiZSBzYXZlZCwgaW4gdGhlIHNlcnZlcidzIHdvcmRzLCBvciBudWxsLiBBbiBvcGVuXG4vLyBlbmQgaXMgYWx3YXlzIGZpbmUuXG5leHBvcnQgZnVuY3Rpb24gYm91bmRzRXJyb3IobWluOiBudW1iZXIgfCBudWxsLCBtYXg6IG51bWJlciB8IG51bGwpOiBzdHJpbmcgfCBudWxsIHtcbiAgaWYgKG1pbiA9PT0gbnVsbCB8fCBtYXggPT09IG51bGwgfHwgbWluIDw9IG1heCkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIGBtaW4gKCR7bWlufSkgaXMgYWJvdmUgbWF4ICgke21heH0pLmA7XG59XG5cbi8vIFRoZSBUeXBlIHNlbGVjdCBvZiBhIGNvbHVtbiBvbiB0aGUgY29tcG9uZW50IHNldHRpbmdzJyBGaWx0ZXJzIHRhYi4gSXRcbi8vIHNob3dzIHdoZW4gdGhlIGNvbHVtbiBjYW4gdGFrZSBlaXRoZXIgdHlwZSBhbmQgdGhlIHNlcnZlciBzZXJ2ZXMgbnVtYmVyXG4vLyByYW5nZXMgKGFuIG9sZGVyIHNlcnZlciBsaXN0cyBubyBmZWF0dXJlcykuIEEgZmlsdGVyJ3MgdHlwZSBjYW5ub3QgY2hhbmdlLFxuLy8gc28gaXQgaXMgbG9ja2VkIHdoaWxlIHRoZSBjb2x1bW4gaGFzIGEgZmlsdGVyIG9uIHRoaXMgY29tcG9uZW50LlxuZXhwb3J0IGZ1bmN0aW9uIHR5cGVTZWxlY3RTdGF0ZShcbiAgdHlwZXM6IFJlcG9ydEZpbHRlclR5cGVbXSB8IG51bGwgfCB1bmRlZmluZWQsXG4gIGhhc0ZpbHRlck9uVGhpc0NvbXBvbmVudDogYm9vbGVhbixcbiAgZmVhdHVyZXM6IFJlcG9ydFZpZXdlckZlYXR1cmVbXSB8IG51bGwgfCB1bmRlZmluZWQsXG4pOiBGaWx0ZXJUeXBlU2VsZWN0U3RhdGUge1xuICBjb25zdCBzaG93ID0gKGZlYXR1cmVzID8/IFtdKS5pbmNsdWRlcygnbnVtYmVyUmFuZ2UnKVxuICAgICYmIEZJTFRFUl9UWVBFX09QVElPTlMuZXZlcnkoKG9wdGlvbikgPT4gKHR5cGVzID8/IFtdKS5pbmNsdWRlcyhvcHRpb24udmFsdWUpKTtcblxuICBpZiAoIXNob3cpIHtcbiAgICByZXR1cm4geyBzaG93OiBmYWxzZSwgZGlzYWJsZWQ6IGZhbHNlLCB0b29sdGlwOiBudWxsIH07XG4gIH1cblxuICByZXR1cm4ge1xuICAgIHNob3c6IHRydWUsXG4gICAgZGlzYWJsZWQ6IGhhc0ZpbHRlck9uVGhpc0NvbXBvbmVudCxcbiAgICB0b29sdGlwOiBoYXNGaWx0ZXJPblRoaXNDb21wb25lbnQgPyBUWVBFX0xPQ0tFRF9UT09MVElQIDogbnVsbCxcbiAgfTtcbn1cblxuLy8gVGhlIGxldmVscyBhIG5ldyBvciBtb3ZlZCBmaWx0ZXIgY2FuIHRha2Ugb24gYSBjb21wb25lbnQuIFRoaXMgcGFnZSBvbmx5XG4vLyBuZWVkcyBhIHNlcnZlciB0aGF0IHNlcnZlcyBwYWdlIGZpbHRlcnMgYW5kIGEgY29tcG9uZW50IG9uIGEgcGFnZSAoYVxuLy8gaGVhZGVyIG9yIGZvb3RlciBjb21wb25lbnQgaXMgb24gbm8gcGFnZSkuXG5leHBvcnQgZnVuY3Rpb24gZmlsdGVyTGV2ZWxDaG9pY2VzKFxuICBmZWF0dXJlczogUmVwb3J0Vmlld2VyRmVhdHVyZVtdIHwgbnVsbCB8IHVuZGVmaW5lZCxcbiAgb25QYWdlOiBib29sZWFuLFxuKTogUmVwb3J0RmlsdGVyTGV2ZWxbXSB7XG4gIGNvbnN0IGxldmVsczogUmVwb3J0RmlsdGVyTGV2ZWxbXSA9IFsnY29tcG9uZW50JywgJ3JlcG9ydCcsICdib3RoJ107XG5cbiAgcmV0dXJuIG9uUGFnZSAmJiAoZmVhdHVyZXMgPz8gW10pLmluY2x1ZGVzKCdwYWdlU2NvcGUnKVxuICAgID8gWy4uLmxldmVscywgJ3BhZ2UnXVxuICAgIDogbGV2ZWxzO1xufVxuXG4vLyBUaGUgUmVwb3J0IGJhciBzZWxlY3QncyBjaG9pY2VzIGZvciB0aGUgbGV2ZWxzIG9uIG9mZmVyLiBUaGUgY2hvaWNlIGEgcm93XG4vLyBhbHJlYWR5IGhvbGRzIGlzIGFsd2F5cyBsaXN0ZWQsIHNvIHRoZSBzZWxlY3QgbmV2ZXIgc2hvd3MgYmxhbmsuXG5leHBvcnQgZnVuY3Rpb24gYmFyUGxhY2VtZW50T3B0aW9ucyhcbiAgbGV2ZWxDaG9pY2VzOiBSZXBvcnRGaWx0ZXJMZXZlbFtdLFxuICBjdXJyZW50OiBGaWx0ZXJCYXJQbGFjZW1lbnQgPSAnb2ZmJyxcbik6IEZpbHRlclNldHRpbmdzT3B0aW9uPEZpbHRlckJhclBsYWNlbWVudD5bXSB7XG4gIHJldHVybiBCQVJfUExBQ0VNRU5UX09QVElPTlMuZmlsdGVyKChvcHRpb24pID0+IHtcbiAgICBzd2l0Y2ggKG9wdGlvbi52YWx1ZSkge1xuICAgICAgY2FzZSAnZXZlcnknOlxuICAgICAgICByZXR1cm4gbGV2ZWxDaG9pY2VzLmluY2x1ZGVzKCdyZXBvcnQnKSB8fCBsZXZlbENob2ljZXMuaW5jbHVkZXMoJ2JvdGgnKSB8fCBjdXJyZW50ID09PSAnZXZlcnknO1xuICAgICAgY2FzZSAncGFnZSc6XG4gICAgICAgIHJldHVybiBsZXZlbENob2ljZXMuaW5jbHVkZXMoJ3BhZ2UnKSB8fCBjdXJyZW50ID09PSAncGFnZSc7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH0pO1xufVxuXG4vLyBBIHZhbHVlJ3MgUmVwb3J0IGJhciBjaG9pY2VzLiBBIHZhbHVlIGhhcyBubyBzdHJpcCBvZiBpdHMgb3duIGFuZCBpdHNcbi8vIGdyb3VwIG1heSBiZSBzaGFyZWQsIHNvIGEgcGljayBuZXZlciBsb3dlcnMgdGhlIGdyb3VwICh0aGUgaW5saW5lIHZhbHVlc1xuLy8gcnVsZSk6IFRoaXMgcGFnZSBvbmx5IGlzIG9mZmVyZWQgZm9yIGEgbmV3IGZpbHRlciwgb3IgZm9yIGEgZ3JvdXAgdGhhdCBpc1xuLy8gYWxyZWFkeSBhIHBhZ2UgZ3JvdXAsIG5ldmVyIHRvIG1vdmUgYSBzaGFyZWQgZ3JvdXAgdG8gb25lIHBhZ2UuXG5leHBvcnQgZnVuY3Rpb24gdmFsdWVQbGFjZW1lbnRPcHRpb25zKFxuICBsZXZlbENob2ljZXM6IFJlcG9ydEZpbHRlckxldmVsW10sXG4gIGN1cnJlbnQ6IFJlcG9ydEZpbHRlckxldmVsIHwgbnVsbCB8IHVuZGVmaW5lZCxcbik6IEZpbHRlclNldHRpbmdzT3B0aW9uPEZpbHRlckJhclBsYWNlbWVudD5bXSB7XG4gIGNvbnN0IGNob2ljZXMgPSAhY3VycmVudCB8fCBjdXJyZW50ID09PSAncGFnZSdcbiAgICA/IGxldmVsQ2hvaWNlc1xuICAgIDogbGV2ZWxDaG9pY2VzLmZpbHRlcigobGV2ZWwpID0+IGxldmVsICE9PSAncGFnZScpO1xuXG4gIHJldHVybiBiYXJQbGFjZW1lbnRPcHRpb25zKGNob2ljZXMsIGJhclBsYWNlbWVudChjdXJyZW50KSk7XG59XG5cbi8vIFRoZSBsZXZlbCBhIHZhbHVlJ3MgZmlsdGVyIGdyb3VwIGVuZHMgYXQgYWZ0ZXIgYSBSZXBvcnQgYmFyIHBpY2ssIG9yIG51bGxcbi8vIHdoZW4gdGhlIHZhbHVlIGxlYXZlcyBpdC4gT2ZmIHVubGlua3MgdGhpcyB2YWx1ZSBhbG9uZSBhbmQgdGhlIGdyb3VwIGtlZXBzXG4vLyBpdHMgb3RoZXIgbWVtYmVycy4gQSBuZXcgZmlsdGVyIHRha2VzIHRoZSBwaWNrJ3MgbGV2ZWwuIEV2ZXJ5IHBhZ2UgcmFpc2VzIGFcbi8vIHN0cmlwLW9ubHkgZ3JvdXAgdG8gYm90aCwga2VlcGluZyBpdHMgc3RyaXBzLCBhbmQgYSBwYWdlIGdyb3VwIHRvIHRoZVxuLy8gcmVwb3J0IGJhci4gTm90aGluZyBlbHNlIG1vdmVzIHRoZSBncm91cCwgc28gYSB2YWx1ZSBuZXZlciBsb3dlcnMgaXQuXG5leHBvcnQgZnVuY3Rpb24gdmFsdWVGaWx0ZXJMZXZlbChcbiAgcGxhY2VtZW50OiBGaWx0ZXJCYXJQbGFjZW1lbnQsXG4gIGN1cnJlbnQ6IFJlcG9ydEZpbHRlckxldmVsIHwgbnVsbCB8IHVuZGVmaW5lZCxcbik6IFJlcG9ydEZpbHRlckxldmVsIHwgbnVsbCB7XG4gIGlmIChwbGFjZW1lbnQgPT09ICdvZmYnKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBpZiAoIWN1cnJlbnQpIHtcbiAgICByZXR1cm4gcGxhY2VtZW50ID09PSAncGFnZScgPyAncGFnZScgOiAncmVwb3J0JztcbiAgfVxuXG4gIGlmIChwbGFjZW1lbnQgIT09ICdldmVyeScpIHtcbiAgICByZXR1cm4gY3VycmVudDtcbiAgfVxuXG4gIHN3aXRjaCAoY3VycmVudCkge1xuICAgIGNhc2UgJ2NvbXBvbmVudCc6XG4gICAgICByZXR1cm4gJ2JvdGgnO1xuICAgIGNhc2UgJ3BhZ2UnOlxuICAgICAgcmV0dXJuICdyZXBvcnQnO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gY3VycmVudDtcbiAgfVxufVxuXG4vLyBXaGVyZSBhIGdyb3VwIG9mIGEgbGV2ZWwgc2hvd3MgaW4gdGhlIHJlcG9ydCBiYXIuIE5vIGdyb3VwIChubyBmaWx0ZXIpIGlzXG4vLyBvZmYuXG5leHBvcnQgZnVuY3Rpb24gYmFyUGxhY2VtZW50KGxldmVsOiBSZXBvcnRGaWx0ZXJMZXZlbCB8IG51bGwgfCB1bmRlZmluZWQpOiBGaWx0ZXJCYXJQbGFjZW1lbnQge1xuICBzd2l0Y2ggKGxldmVsKSB7XG4gICAgY2FzZSAncmVwb3J0JzpcbiAgICBjYXNlICdib3RoJzpcbiAgICAgIHJldHVybiAnZXZlcnknO1xuICAgIGNhc2UgJ3BhZ2UnOlxuICAgICAgcmV0dXJuICdwYWdlJztcbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuICdvZmYnO1xuICB9XG59XG5cbi8vIFdoZXRoZXIgYSBncm91cCBvZiBhIGxldmVsIHNob3dzIG9uIGl0cyBjb21wb25lbnRzLlxuZXhwb3J0IGZ1bmN0aW9uIHNob3duT25Db21wb25lbnQobGV2ZWw6IFJlcG9ydEZpbHRlckxldmVsIHwgbnVsbCB8IHVuZGVmaW5lZCk6IGJvb2xlYW4ge1xuICByZXR1cm4gbGV2ZWwgPT09ICdjb21wb25lbnQnIHx8IGxldmVsID09PSAnYm90aCc7XG59XG5cbi8vIFRoZSBsZXZlbCB0aGUgdHdvIGNvbnRyb2xzIG9mIGEgcm93IGFzayBmb3IsIG9yIG51bGwgd2hlbiB0aGV5IGFzayBmb3Igbm9cbi8vIGZpbHRlciBhdCBhbGwuIEEgcGFnZSBmaWx0ZXIgc2hvd3MgaW4gaXRzIHBhZ2UncyBiYXIgb25seSwgc28gVGhpcyBwYWdlXG4vLyBvbmx5IGlnbm9yZXMgdGhlIFRoaXMgY29tcG9uZW50IHRvZ2dsZS5cbmV4cG9ydCBmdW5jdGlvbiBmaWx0ZXJMZXZlbChwbGFjZW1lbnQ6IEZpbHRlckJhclBsYWNlbWVudCwgY29tcG9uZW50OiBib29sZWFuKTogUmVwb3J0RmlsdGVyTGV2ZWwgfCBudWxsIHtcbiAgc3dpdGNoIChwbGFjZW1lbnQpIHtcbiAgICBjYXNlICdwYWdlJzpcbiAgICAgIHJldHVybiAncGFnZSc7XG4gICAgY2FzZSAnZXZlcnknOlxuICAgICAgcmV0dXJuIGNvbXBvbmVudCA/ICdib3RoJyA6ICdyZXBvcnQnO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gY29tcG9uZW50ID8gJ2NvbXBvbmVudCcgOiBudWxsO1xuICB9XG59XG5cbi8vIFRoZSBUaGlzIGNvbXBvbmVudCB0b2dnbGUgb2YgYSByb3c6IGxvY2tlZCB3aGlsZSBUaGlzIHBhZ2Ugb25seSBpcyBwaWNrZWQuXG5leHBvcnQgZnVuY3Rpb24gY29tcG9uZW50VG9nZ2xlU3RhdGUocGxhY2VtZW50OiBGaWx0ZXJCYXJQbGFjZW1lbnQpOiBGaWx0ZXJDb21wb25lbnRUb2dnbGVTdGF0ZSB7XG4gIHJldHVybiBwbGFjZW1lbnQgPT09ICdwYWdlJ1xuICAgID8geyBkaXNhYmxlZDogdHJ1ZSwgdG9vbHRpcDogUEFHRV9GSUxURVJfVE9PTFRJUCB9XG4gICAgOiB7IGRpc2FibGVkOiBmYWxzZSwgdG9vbHRpcDogQ09NUE9ORU5UX1RPR0dMRV9UT09MVElQIH07XG59XG5cbi8vIFRoZSBncm91cHMgdGhlIHJlcG9ydCBzZXR0aW5ncycgRmlsdGVycyB0YWIgbGlzdHMgZGVmYXVsdHMgZm9yOiB0aG9zZSBvZlxuLy8gdGhlIHJlcG9ydCBiYXIsIGV2ZXJ5IHBhZ2Ugb3Igb25lLCBpbiBiYXIgb3JkZXIuXG5leHBvcnQgZnVuY3Rpb24gZGVmYXVsdFJvd0dyb3Vwcyhncm91cHM6IFJlcG9ydEZpbHRlckdyb3VwW10gfCBudWxsIHwgdW5kZWZpbmVkKTogUmVwb3J0RmlsdGVyR3JvdXBbXSB7XG4gIHJldHVybiAoZ3JvdXBzID8/IFtdKVxuICAgIC5maWx0ZXIoKGdyb3VwKSA9PiBncm91cC5sZXZlbCA9PT0gJ3JlcG9ydCcgfHwgZ3JvdXAubGV2ZWwgPT09ICdib3RoJyB8fCBncm91cC5sZXZlbCA9PT0gJ3BhZ2UnKVxuICAgIC5zb3J0KChhLCBiKSA9PiBhLm9yZGVyIC0gYi5vcmRlcik7XG59XG5cbi8vIEEgZGVmYXVsdCByb3cncyBsYWJlbDogYSBwYWdlIGdyb3VwIG5hbWVzIGl0cyBwYWdlLCAnUmVnaW9uIChwYWdlXG4vLyBcIk92ZXJ2aWV3XCIpJy4gQSBwYWdlIHdpdGggbm8gbmFtZSByZWFkcyBhcyB0aGUgY2FudmFzIG5hbWVzIGl0ICgnUGFnZSAyJykuXG4vLyBBIHBhZ2UgdGhpcyByZXBvcnQgbm8gbG9uZ2VyIGhvbGRzIGFkZHMgbm90aGluZy5cbmV4cG9ydCBmdW5jdGlvbiBkZWZhdWx0Um93TGFiZWwoZ3JvdXA6IFJlcG9ydEZpbHRlckdyb3VwLCBwYWdlczogUmVwb3J0UGFnZVtdIHwgbnVsbCB8IHVuZGVmaW5lZCk6IHN0cmluZyB7XG4gIGNvbnN0IGxhYmVsID0gZ3JvdXAubGFiZWwgfHwgZ3JvdXAuZmlsdGVycz8uWzBdPy5maWx0ZXJDb2x1bW4gfHwgJ0ZpbHRlcic7XG5cbiAgaWYgKGdyb3VwLmxldmVsICE9PSAncGFnZScpIHtcbiAgICByZXR1cm4gbGFiZWw7XG4gIH1cblxuICBjb25zdCBpbmRleCA9IChwYWdlcyA/PyBbXSkuZmluZEluZGV4KChwYWdlKSA9PiBwYWdlLmlkID09PSBncm91cC5wYWdlSWQpO1xuICBpZiAoaW5kZXggPCAwKSB7XG4gICAgcmV0dXJuIGxhYmVsO1xuICB9XG5cbiAgcmV0dXJuIGAke2xhYmVsfSAocGFnZSBcIiR7cGFnZXNbaW5kZXhdLm5hbWUgfHwgYFBhZ2UgJHtpbmRleCArIDF9YH1cIilgO1xufVxuXG4vLyBUaGUgRGVmYXVsdCBwZXJpb2Qgc2VsZWN0J3MgY2hvaWNlczogRml4ZWQgZGF0ZXMsIHRoZW4gZXZlcnkgcmVsYXRpdmVcbi8vIHJhbmdlIGluIHRoZSBzZXJ2ZXIgZW51bSdzIG9yZGVyLCBuYW1lZCBieSBgbGFiZWxzYC4gQSBzdG9yZWQgcmFuZ2UgdGhpc1xuLy8gdmlld2VyIGRvZXMgbm90IGtub3cgaXMgbGlzdGVkIGxhc3QsIHNvIHRoZSBzZWxlY3Qgc3RpbGwgc2hvd3MgaXQuXG5leHBvcnQgZnVuY3Rpb24gZGVmYXVsdFBlcmlvZE9wdGlvbnMoXG4gIGxhYmVsczogKHJlbGF0aXZlOiBSZXBvcnRSZWxhdGl2ZVJhbmdlKSA9PiBzdHJpbmcsXG4gIHN0b3JlZDogc3RyaW5nIHwgbnVsbCA9IG51bGwsXG4pOiBGaWx0ZXJTZXR0aW5nc09wdGlvbltdIHtcbiAgY29uc3Qgb3B0aW9uczogRmlsdGVyU2V0dGluZ3NPcHRpb25bXSA9IFtcbiAgICB7IHZhbHVlOiBGSVhFRF9EQVRFU19QRVJJT0QsIG5hbWU6ICdGaXhlZCBkYXRlcycgfSxcbiAgICAuLi5SRUxBVElWRV9SQU5HRV9OQU1FUy5tYXAoKHJlbGF0aXZlKSA9PiAoeyB2YWx1ZTogcmVsYXRpdmUsIG5hbWU6IGxhYmVscyhyZWxhdGl2ZSkgfSkpLFxuICBdO1xuXG4gIHJldHVybiBzdG9yZWQgJiYgc3RvcmVkICE9PSBGSVhFRF9EQVRFU19QRVJJT0QgJiYgIWlzUmVsYXRpdmVSYW5nZShzdG9yZWQpXG4gICAgPyBbLi4ub3B0aW9ucywgeyB2YWx1ZTogc3RvcmVkLCBuYW1lOiBsYWJlbHMoc3RvcmVkIGFzIFJlcG9ydFJlbGF0aXZlUmFuZ2UpIH1dXG4gICAgOiBvcHRpb25zO1xufVxuXG4vLyBUaGUgRGVmYXVsdCBwZXJpb2QgYSBzdG9yZWQgZGF0ZSByYW5nZSBkZWZhdWx0IG9wZW5zIG9uOiBpdHMgcmVsYXRpdmVcbi8vIHJhbmdlLCBlbHNlIEZpeGVkIGRhdGVzICh0aGUgZGF5cywgb3Igbm9uZSkuXG5leHBvcnQgZnVuY3Rpb24gZGVmYXVsdFBlcmlvZChzdG9yZWQ6IEZpbHRlckdyb3VwRGVmYXVsdCB8IG51bGwgfCB1bmRlZmluZWQpOiBzdHJpbmcge1xuICByZXR1cm4gc3RvcmVkPy5yZWxhdGl2ZSAmJiAhc3RvcmVkLnN0YXJ0ICYmICFzdG9yZWQuZW5kXG4gICAgPyBzdG9yZWQucmVsYXRpdmVcbiAgICA6IEZJWEVEX0RBVEVTX1BFUklPRDtcbn1cblxuLy8gQSBkYXRlIHJhbmdlIGRlZmF1bHQgaW4gaXRzIHN0b3JlZCBzaGFwZTogdGhlIHJlbGF0aXZlIHJhbmdlIHBpY2tlZCwgZWxzZVxuLy8gdGhlIGZpeGVkIGRheXMsIG9yIG51bGwgd2hlbiB0aGVyZSBhcmUgbm9uZS4gTmV2ZXIgYm90aDogdGhlIHNlcnZlclxuLy8gcmVmdXNlcyBhIHJlbGF0aXZlIHJhbmdlIHdpdGggZGF5cy5cbmV4cG9ydCBmdW5jdGlvbiBkYXRlUmFuZ2VEZWZhdWx0KFxuICBwZXJpb2Q6IHN0cmluZyxcbiAgc3RhcnQ6IHN0cmluZyB8IG51bGwsXG4gIGVuZDogc3RyaW5nIHwgbnVsbCxcbik6IEZpbHRlckdyb3VwRGVmYXVsdCB8IG51bGwge1xuICBpZiAocGVyaW9kICE9PSBGSVhFRF9EQVRFU19QRVJJT0QpIHtcbiAgICByZXR1cm4geyByZWxhdGl2ZTogcGVyaW9kIH07XG4gIH1cblxuICBpZiAoIXN0YXJ0ICYmICFlbmQpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiB7IC4uLihzdGFydCA/IHsgc3RhcnQgfSA6IHt9KSwgLi4uKGVuZCA/IHsgZW5kIH0gOiB7fSkgfTtcbn1cblxuLy8gQSBzZWxlY3QgZGVmYXVsdCBpbiBpdHMgc3RvcmVkIHNoYXBlOiB0aGUgcGlja3Mga2VwdCwgb3IgbGVmdCBvdXQgd2hpbGVcbi8vIEV4Y2x1ZGUgdGhlc2UgdmFsdWVzIGlzIG9uLCBvciBudWxsIHdoZW4gbm90aGluZyBpcyBwaWNrZWQuXG5leHBvcnQgZnVuY3Rpb24gc2VsZWN0RGVmYXVsdCh2YWx1ZXM6IHVua25vd25bXSwgZXhjbHVkZTogYm9vbGVhbik6IEZpbHRlckdyb3VwRGVmYXVsdCB8IG51bGwge1xuICBpZiAoIXZhbHVlcy5sZW5ndGgpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBleGNsdWRlID8geyBleGNsdWRlVmFsdWVzOiB2YWx1ZXMgfSA6IHsgdmFsdWVzIH07XG59XG5cbi8vIEEgbnVtYmVyIHJhbmdlIGRlZmF1bHQgaW4gaXRzIHN0b3JlZCBzaGFwZSBmcm9tIHRoZSBlbmRzIGFzIHR5cGVkOiBhblxuLy8gb3BlbiBlbmQgaXMgbGVmdCBvdXQsIDAgaXMga2VwdCwgYW5kIHR3byBvcGVuIGVuZHMgYXJlIG5vIGRlZmF1bHQuXG5leHBvcnQgZnVuY3Rpb24gbnVtYmVyUmFuZ2VEZWZhdWx0KHJhd01pbjogdW5rbm93biwgcmF3TWF4OiB1bmtub3duKTogRmlsdGVyR3JvdXBEZWZhdWx0IHwgbnVsbCB7XG4gIGNvbnN0IG1pbiA9IHBhcnNlRGVmYXVsdEJvdW5kKHJhd01pbik7XG4gIGNvbnN0IG1heCA9IHBhcnNlRGVmYXVsdEJvdW5kKHJhd01heCk7XG5cbiAgaWYgKG1pbiA9PT0gbnVsbCAmJiBtYXggPT09IG51bGwpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiB7IC4uLihtaW4gIT09IG51bGwgPyB7IG1pbiB9IDoge30pLCAuLi4obWF4ICE9PSBudWxsID8geyBtYXggfSA6IHt9KSB9O1xufVxuXG4vLyBXaGV0aGVyIGEgc2VsZWN0IGdyb3VwJ3MgZGVmYXVsdCByb3cgb2ZmZXJzIEV4Y2x1ZGUgdGhlc2UgdmFsdWVzOiB0aGVcbi8vIHJlcG9ydCBiYXIncyBydWxlIChvZmZlcnNFeGNsdWRlKSwgc28gbm90IG9uIGEgc2VydmVyIHRoYXQgZG9lcyBub3Qgc2VydmVcbi8vIGV4Y2x1ZGUgKGFuIG9sZGVyIHNlcnZlciBsaXN0cyBubyBmZWF0dXJlcykgbm9yIG9uIGEgZ3JvdXAgd2l0aCBhIG1lbWJlclxuLy8gdGhhdCBiaW5kcyBzZXZlcmFsIGNvbHVtbnMgKG11bHRpQ29sdW1uKS4gQSBkZWZhdWx0IHRoYXQgYWxyZWFkeSBsZWF2ZXNcbi8vIHZhbHVlcyBvdXQga2VlcHMgdGhlIHRvZ2dsZSwgc28gaXQgY2FuIGJlIHR1cm5lZCBvZmYuXG5leHBvcnQgZnVuY3Rpb24gc2hvd0V4Y2x1ZGVUb2dnbGUoXG4gIGdyb3VwOiBSZXBvcnRGaWx0ZXJHcm91cCxcbiAgZmVhdHVyZXM6IFJlcG9ydFZpZXdlckZlYXR1cmVbXSB8IG51bGwgfCB1bmRlZmluZWQsXG4pOiBib29sZWFuIHtcbiAgaWYgKGdyb3VwLnR5cGUgPT09ICdzZWxlY3QnICYmIGdyb3VwLmNvbmZpZz8uZGVmYXVsdD8uZXhjbHVkZVZhbHVlcz8ubGVuZ3RoKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICByZXR1cm4gb2ZmZXJzRXhjbHVkZShncm91cCwgZmVhdHVyZXMpO1xufVxuXG4vLyBBIHN0b3JlZCBvciBkcmFmdCBkZWZhdWx0IGluIGEgc3RhYmxlIGZvcm0gZm9yIGNvbXBhcmluZzogZW1wdHkgYW5kXG4vLyBhYnNlbnQga2V5cyBhcmUgZHJvcHBlZCwgc28gYSBuby1vcCBlZGl0IGRvZXMgbm90IHJlYWQgYXMgYSBjaGFuZ2UuIDAgaXMgYW5cbi8vIGVuZCBsaWtlIGFueSBvdGhlci4gTm90aGluZyBsZWZ0IGlzIG51bGwuXG5leHBvcnQgZnVuY3Rpb24gbm9ybWFsaXplRGVmYXVsdCh2YWx1ZTogRmlsdGVyR3JvdXBEZWZhdWx0IHwgbnVsbCB8IHVuZGVmaW5lZCk6IEZpbHRlckdyb3VwRGVmYXVsdCB8IG51bGwge1xuICBpZiAoIXZhbHVlKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBjb25zdCBub3JtYWxpemVkOiBGaWx0ZXJHcm91cERlZmF1bHQgPSB7fTtcbiAgaWYgKHZhbHVlLnN0YXJ0KSB7XG4gICAgbm9ybWFsaXplZC5zdGFydCA9IHZhbHVlLnN0YXJ0O1xuICB9XG4gIGlmICh2YWx1ZS5lbmQpIHtcbiAgICBub3JtYWxpemVkLmVuZCA9IHZhbHVlLmVuZDtcbiAgfVxuICBpZiAodmFsdWUudmFsdWVzPy5sZW5ndGgpIHtcbiAgICBub3JtYWxpemVkLnZhbHVlcyA9IHZhbHVlLnZhbHVlcztcbiAgfVxuICBpZiAodmFsdWUuZXhjbHVkZVZhbHVlcz8ubGVuZ3RoKSB7XG4gICAgbm9ybWFsaXplZC5leGNsdWRlVmFsdWVzID0gdmFsdWUuZXhjbHVkZVZhbHVlcztcbiAgfVxuICBpZiAodHlwZW9mIHZhbHVlLm1pbiA9PT0gJ251bWJlcicpIHtcbiAgICBub3JtYWxpemVkLm1pbiA9IHZhbHVlLm1pbjtcbiAgfVxuICBpZiAodHlwZW9mIHZhbHVlLm1heCA9PT0gJ251bWJlcicpIHtcbiAgICBub3JtYWxpemVkLm1heCA9IHZhbHVlLm1heDtcbiAgfVxuICBpZiAodmFsdWUudmFsdWUpIHtcbiAgICBub3JtYWxpemVkLnZhbHVlID0gdmFsdWUudmFsdWU7XG4gIH1cbiAgaWYgKHZhbHVlLnJlbGF0aXZlKSB7XG4gICAgbm9ybWFsaXplZC5yZWxhdGl2ZSA9IHZhbHVlLnJlbGF0aXZlO1xuICB9XG5cbiAgcmV0dXJuIE9iamVjdC5rZXlzKG5vcm1hbGl6ZWQpLmxlbmd0aCA/IG5vcm1hbGl6ZWQgOiBudWxsO1xufVxuXG4vLyBXaGV0aGVyIGEgcm93J3MgZHJhZnQgZGVmYXVsdCBkaWZmZXJzIGZyb20gdGhlIGdyb3VwJ3Mgc3RvcmVkIG9uZS4gT25seSBhXG4vLyBjaGFuZ2VkIHJvdyBpcyBzYXZlZC5cbmV4cG9ydCBmdW5jdGlvbiBkZWZhdWx0Q2hhbmdlZChcbiAgc3RvcmVkOiBGaWx0ZXJHcm91cERlZmF1bHQgfCBudWxsIHwgdW5kZWZpbmVkLFxuICBkcmFmdDogRmlsdGVyR3JvdXBEZWZhdWx0IHwgbnVsbCB8IHVuZGVmaW5lZCxcbik6IGJvb2xlYW4ge1xuICByZXR1cm4gSlNPTi5zdHJpbmdpZnkobm9ybWFsaXplRGVmYXVsdChzdG9yZWQpKSAhPT0gSlNPTi5zdHJpbmdpZnkobm9ybWFsaXplRGVmYXVsdChkcmFmdCkpO1xufVxuIl19