@sbb-esta/lyne-elements-dev 5.0.0-next.3-dev.1779268556 → 5.0.0-next.3-dev.1779280398

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 (142) hide show
  1. package/autocomplete/autocomplete-base-element.js +1 -1
  2. package/autocomplete/autocomplete.component.js +1 -1
  3. package/{autocomplete-base-element-jaXVQcA7.js → autocomplete-base-element-DjfmUS0W.js} +0 -1
  4. package/autocomplete.js +1 -1
  5. package/autocomplete.pure.js +1 -1
  6. package/calendar/calendar/calendar.component.js +1 -1
  7. package/{calendar.component-DKgkIocz.js → calendar.component-BhUyyFtR.js} +66 -66
  8. package/calendar.js +1 -1
  9. package/calendar.pure.js +1 -1
  10. package/core/base-elements/button-base-element.js +47 -68
  11. package/core/datetime/date-adapter.js +2 -2
  12. package/core/i18n/i18n.js +69 -74
  13. package/core/mixins/form-associated-checkbox-mixin.js +17 -26
  14. package/core.js +40 -42
  15. package/custom-elements.json +98 -446
  16. package/datepicker/common/datepicker-button.js +1 -1
  17. package/{datepicker-button-aYDFZ_3v.js → datepicker-button-CuoZoC6e.js} +0 -3
  18. package/datepicker.js +1 -1
  19. package/datepicker.pure.js +1 -1
  20. package/development/autocomplete/autocomplete-base-element.d.ts +0 -2
  21. package/development/autocomplete/autocomplete-base-element.d.ts.map +1 -1
  22. package/development/autocomplete/autocomplete-base-element.js +1 -1
  23. package/development/autocomplete/autocomplete.component.js +1 -1
  24. package/development/{autocomplete-base-element-JxM7QbC4.js → autocomplete-base-element-CTZEg--s.js} +1 -3
  25. package/development/autocomplete.js +1 -1
  26. package/development/autocomplete.pure.js +1 -1
  27. package/development/calendar/calendar/calendar.component.d.ts +0 -6
  28. package/development/calendar/calendar/calendar.component.d.ts.map +1 -1
  29. package/development/calendar/calendar/calendar.component.js +1 -1
  30. package/development/calendar.component-DnC8Zkdk.js +1478 -0
  31. package/development/calendar.js +1 -1
  32. package/development/calendar.pure.js +1 -1
  33. package/development/core/base-elements/button-base-element.d.ts +1 -0
  34. package/development/core/base-elements/button-base-element.d.ts.map +1 -1
  35. package/development/core/base-elements/button-base-element.js +66 -92
  36. package/development/core/base-elements/element.d.ts.map +1 -1
  37. package/development/core/datetime/date-adapter.d.ts +0 -5
  38. package/development/core/datetime/date-adapter.d.ts.map +1 -1
  39. package/development/core/datetime/date-adapter.js +2 -7
  40. package/development/core/i18n/i18n.d.ts +0 -1
  41. package/development/core/i18n/i18n.d.ts.map +1 -1
  42. package/development/core/i18n/i18n.js +2 -8
  43. package/development/core/mixins/form-associated-checkbox-mixin.d.ts.map +1 -1
  44. package/development/core/mixins/form-associated-checkbox-mixin.js +7 -21
  45. package/development/core/mixins/form-associated-mixin.d.ts +1 -1
  46. package/development/core/mixins/form-associated-mixin.d.ts.map +1 -1
  47. package/development/core/mixins/form-associated-mixin.js +1 -1
  48. package/development/core.d.ts +0 -2
  49. package/development/core.d.ts.map +1 -1
  50. package/development/core.js +3 -5
  51. package/development/datepicker/common/datepicker-button.d.ts +0 -2
  52. package/development/datepicker/common/datepicker-button.d.ts.map +1 -1
  53. package/development/datepicker/common/datepicker-button.js +1 -1
  54. package/development/{datepicker-button-BAT1ebzJ.js → datepicker-button-Bb76EBYH.js} +1 -5
  55. package/development/datepicker.js +1 -1
  56. package/development/datepicker.pure.js +1 -1
  57. package/development/dialog/dialog/dialog.component.js +1 -1
  58. package/development/{dialog.component-D8B2dVck.js → dialog.component-cZ3SAujq.js} +5 -5
  59. package/development/dialog.js +1 -1
  60. package/development/dialog.pure.js +1 -1
  61. package/development/element-BAsBayf5.js +1 -1
  62. package/development/expansion-panel/expansion-panel-header/expansion-panel-header.component.d.ts.map +1 -1
  63. package/development/expansion-panel-header.component-gg5A_7Pz.js +1 -1
  64. package/development/form-field/form-field/form-field.component.d.ts +0 -6
  65. package/development/form-field/form-field/form-field.component.d.ts.map +1 -1
  66. package/development/form-field/form-field/form-field.component.js +1 -1
  67. package/development/form-field.component-w4nlNsj2.js +670 -0
  68. package/development/form-field.js +1 -1
  69. package/development/form-field.pure.js +1 -1
  70. package/development/icon/icon.component.d.ts +1 -1
  71. package/development/icon/icon.component.d.ts.map +1 -1
  72. package/development/icon/icon.component.js +5 -7
  73. package/development/optgroup-base-element-BzfcJgxG.js +140 -0
  74. package/development/option/optgroup/optgroup-base-element.d.ts +1 -2
  75. package/development/option/optgroup/optgroup-base-element.d.ts.map +1 -1
  76. package/development/option/optgroup/optgroup-base-element.js +1 -1
  77. package/development/option/optgroup/optgroup.component.js +1 -1
  78. package/development/option.js +1 -1
  79. package/development/option.pure.js +1 -1
  80. package/development/overlay/overlay-base-element.d.ts +2 -4
  81. package/development/overlay/overlay-base-element.d.ts.map +1 -1
  82. package/development/overlay/overlay-base-element.js +6 -5
  83. package/development/overlay/overlay.component.js +1 -1
  84. package/development/{overlay.component-BH-aue7w.js → overlay.component-DywhKxO1.js} +5 -5
  85. package/development/overlay.js +1 -1
  86. package/development/overlay.pure.js +1 -1
  87. package/development/panel-mixin-DPybe45K.js +1 -1
  88. package/development/slider/slider.component.d.ts +1 -0
  89. package/development/slider/slider.component.d.ts.map +1 -1
  90. package/development/slider/slider.component.js +1 -1
  91. package/development/{slider.component-BLptxiZ4.js → slider.component-Dz4Nl2ZL.js} +8 -21
  92. package/development/slider.js +1 -1
  93. package/development/slider.pure.js +1 -1
  94. package/development/{step.component-DpSJEkrK.js → step.component-CfA-kmt1.js} +1 -11
  95. package/development/stepper/step/step.component.d.ts +4 -14
  96. package/development/stepper/step/step.component.d.ts.map +1 -1
  97. package/development/stepper/step/step.component.js +1 -1
  98. package/development/stepper/stepper/stepper.component.js +1 -1
  99. package/development/{stepper.component-Bv6LCFU0.js → stepper.component-2yRFnnju.js} +5 -5
  100. package/development/stepper.js +2 -2
  101. package/development/stepper.pure.js +2 -2
  102. package/dialog/dialog/dialog.component.js +1 -1
  103. package/{dialog.component-CsBryhM-.js → dialog.component-D3G0AX4Y.js} +4 -4
  104. package/dialog.js +1 -1
  105. package/dialog.pure.js +1 -1
  106. package/form-field/form-field/form-field.component.js +1 -1
  107. package/{form-field.component-BdfK6r2v.js → form-field.component-DkqZz7aZ.js} +62 -83
  108. package/form-field.js +1 -1
  109. package/form-field.pure.js +1 -1
  110. package/icon/icon.component.js +2 -5
  111. package/lean-off-brand-theme.css +1 -0
  112. package/lean-safety-theme.css +1 -0
  113. package/lean-theme.css +1 -0
  114. package/off-brand-theme.css +1 -0
  115. package/{optgroup-base-element-Cxe8SIQh.js → optgroup-base-element-CBxsRPUF.js} +10 -17
  116. package/option/optgroup/optgroup-base-element.js +1 -1
  117. package/option/optgroup/optgroup.component.js +1 -1
  118. package/option.js +1 -1
  119. package/option.pure.js +1 -1
  120. package/overlay/overlay-base-element.js +3 -3
  121. package/overlay/overlay.component.js +1 -1
  122. package/{overlay.component-D7Z_vx1A.js → overlay.component-OSLtja0_.js} +4 -4
  123. package/overlay.js +1 -1
  124. package/overlay.pure.js +1 -1
  125. package/package.json +2 -2
  126. package/safety-theme.css +1 -0
  127. package/slider/slider.component.js +1 -1
  128. package/{slider.component-C8LKcM11.js → slider.component-BMkoF1l1.js} +23 -31
  129. package/slider.js +1 -1
  130. package/slider.pure.js +1 -1
  131. package/standard-theme.css +1 -0
  132. package/core/decorators/host-attributes.js +0 -17
  133. package/core/eventing/throttle.js +0 -11
  134. package/development/calendar.component-CgEXjBeQ.js +0 -1473
  135. package/development/core/decorators/host-attributes.d.ts +0 -22
  136. package/development/core/decorators/host-attributes.d.ts.map +0 -1
  137. package/development/core/decorators/host-attributes.js +0 -41
  138. package/development/core/eventing/throttle.d.ts +0 -3
  139. package/development/core/eventing/throttle.d.ts.map +0 -1
  140. package/development/core/eventing/throttle.js +0 -18
  141. package/development/form-field.component-CPWBCHer.js +0 -702
  142. package/development/optgroup-base-element-CLfE6pmz.js +0 -147
@@ -0,0 +1,1478 @@
1
+ import { __esDecorate, __runInitializers } from "tslib";
2
+ import { html, isServer, nothing, unsafeCSS } from "lit";
3
+ import { property, state } from "lit/decorators.js";
4
+ import { MONDAY, SbbElement, SbbLanguageController, SbbMediaMatcherController, SbbMediaQueryBreakpointLargeAndAbove, THURSDAY, TUESDAY, WEDNESDAY, buttonResetStyles, defaultDateAdapter, forceType, handleDistinctChange, i18nCalendarDateSelection, i18nCalendarWeekNumber, i18nNextMonth, i18nNextYear, i18nNextYearRange, i18nPreviousMonth, i18nPreviousYear, i18nPreviousYearRange, i18nYearMonthSelection, isArrowKeyOrPageKeysPressed, plainDate, readConfig, screenReaderOnlyStyles } from "./core.js";
5
+ import { SbbSecondaryButtonElement } from "./button.pure.js";
6
+ import { SbbIconElement } from "./icon.pure.js";
7
+ import { SbbCalendarDayElement } from "./calendar/calendar-day/calendar-day.component.js";
8
+ import { SbbCalendarMonthElement } from "./calendar/calendar-month/calendar-month.component.js";
9
+ import { SbbCalendarWeekdayElement } from "./calendar/calendar-weekday/calendar-weekday.component.js";
10
+ import { SbbCalendarWeeknumberElement } from "./calendar/calendar-weeknumber/calendar-weeknumber.component.js";
11
+ import { SbbCalendarYearElement } from "./calendar/calendar-year/calendar-year.component.js";
12
+ //#region src/elements/calendar/calendar/calendar.scss?inline
13
+ var calendar_default = ":host {\n display: block;\n width: max-content;\n line-height: var(--sbb-typo-line-height-text);\n --sbb-calendar-cell-size: 2.75rem;\n --sbb-calendar-cell-border-radius: calc(\n var(--sbb-border-radius-4x) + var(--sbb-calendar-cell-border-width)\n );\n --sbb-calendar-cell-transition-duration: var(\n --sbb-disable-animation-duration,\n var(--sbb-animation-duration-2x)\n );\n}\n@media (min-width: calc(37.5rem)) {\n :host {\n --sbb-calendar-control-view-change-height: 3rem;\n }\n}\n\n:host(:is(:state(enhanced),[state--enhanced])) {\n --sbb-calendar-cell-padding-block-end: var(--sbb-spacing-fixed-3x);\n}\n\n.sbb-calendar__wrapper {\n width: 100%;\n display: block;\n transition-duration: var(--sbb-calendar-cell-transition-duration);\n}\n\n.sbb-calendar__controls {\n width: 100%;\n display: inline-flex;\n align-items: center;\n gap: var(--sbb-calendar-control-gap);\n margin-block-end: var(--sbb-calendar-control-margin-block-end);\n}\n\n.sbb-calendar__controls-month {\n width: 100%;\n display: flex;\n gap: var(--sbb-calendar-tables-gap);\n}\n\n#sbb-calendar__controls-previous,\n#sbb-calendar__controls-next {\n -webkit-tap-highlight-color: transparent;\n}\n\n.sbb-calendar__controls-change-date {\n display: flex;\n align-items: center;\n margin: auto;\n height: var(--sbb-calendar-control-view-change-height);\n font-size: var(--sbb-text-font-size-s);\n letter-spacing: var(--sbb-typo-letter-spacing-text);\n line-height: var(--sbb-typo-letter-spacing-text);\n text-transform: capitalize;\n cursor: var(--sbb-cursor-pointer);\n padding-inline: var(--sbb-calendar-control-view-change-padding-inline);\n border-radius: var(--sbb-border-radius-infinity);\n background-color: var(--sbb-calendar-control-view-change-background);\n color: var(--sbb-calendar-control-view-change-color);\n transition-duration: var(--sbb-calendar-cell-transition-duration);\n transition-timing-function: var(--sbb-calendar-cell-transition-easing-function);\n transition-property: background-color, padding-block-end;\n}\n.sbb-calendar__controls-change-date:disabled {\n --sbb-calendar-control-view-change-background: var(--sbb-color-milk);\n --sbb-calendar-control-view-change-background: light-dark(\n var(--sbb-color-milk),\n var(--sbb-color-anthracite)\n );\n --sbb-calendar-control-view-change-color: var(--sbb-color-granite);\n --sbb-calendar-control-view-change-color: light-dark(\n var(--sbb-color-granite),\n var(--sbb-color-aluminium)\n );\n cursor: unset;\n}\n.sbb-calendar__controls-change-date:focus-visible {\n outline-offset: var(--sbb-focus-outline-offset);\n outline: var(--sbb-focus-outline-color) var(--sbb-focus-outline-style, solid) var(--sbb-focus-outline-width);\n outline-offset: var(--sbb-spacing-fixed-1x);\n}\n@media (any-hover: hover) {\n .sbb-calendar__controls-change-date:not(:active, :disabled):hover {\n padding-block-end: var(--sbb-calendar-cell-hover-shift);\n }\n}\n.sbb-calendar__controls-change-date:not(:disabled):active {\n --sbb-calendar-control-view-change-background: var(--sbb-background-color-3);\n}\n\n.sbb-calendar__table-month-view,\n.sbb-calendar__table-year-view {\n --sbb-calendar-table-column-spaces: 6;\n}\n\n.sbb-calendar__table-overflow-break {\n contain: layout;\n}\n\n.sbb-calendar__table-container {\n display: flex;\n gap: var(--sbb-calendar-tables-gap);\n margin-inline: var(--sbb-calendar-margin);\n --sbb-calendar-min-width: calc(7 * var(--sbb-calendar-cell-size));\n --sbb-calendar-overflow: calc(100% - var(--sbb-calendar-min-width));\n --sbb-calendar-start-offset: min(\n 0px,\n -1 * (var(--sbb-calendar-overflow) / var(--sbb-calendar-table-column-spaces))\n );\n --sbb-calendar-margin: var(--sbb-calendar-start-offset);\n}\n:host(:is(:state(wide),[state--wide])) .sbb-calendar__table-container {\n --sbb-calendar-min-width: calc(\n 2 * 7 * var(--sbb-calendar-cell-size) + var(--sbb-calendar-tables-gap)\n );\n --sbb-calendar-margin: calc(0.5 * var(--sbb-calendar-start-offset));\n}\n:host([orientation=horizontal][week-numbers]) .sbb-calendar__table-container {\n --sbb-calendar-min-width: calc(8 * var(--sbb-calendar-cell-size));\n}\n:host([orientation=horizontal][week-numbers]:is(:state(wide),[state--wide])) .sbb-calendar__table-container {\n --sbb-calendar-min-width: calc(\n 2 * 8 * var(--sbb-calendar-cell-size) + var(--sbb-calendar-tables-gap)\n );\n}\n:host([orientation=vertical]) .sbb-calendar__table-container {\n min-width: var(--sbb-calendar-min-width);\n --sbb-calendar-start-offset: 0;\n}\n:host([orientation=vertical]:is(:state(wide),[state--wide])) .sbb-calendar__table-container {\n --sbb-calendar-min-width: calc(\n 13 * var(--sbb-calendar-cell-size) + var(--sbb-calendar-tables-gap)\n );\n}\n\n.sbb-calendar__table {\n width: 100%;\n border-collapse: collapse;\n height: max-content;\n animation-name: show;\n animation-duration: var(--sbb-calendar-table-animation-duration);\n}\n.sbb-calendar__table.sbb-calendar__table-hide {\n --sbb-calendar-cell-transition-duration: 0ms;\n animation-name: hide;\n animation-duration: var(--sbb-calendar-table-animation-duration);\n}\n:host(:not(:is(:state(wide),[state--wide]))) .sbb-calendar__table {\n min-width: 100%;\n}\n\n.sbb-calendar__table-header {\n text-align: center;\n}\n\n.sbb-calendar__table-body {\n text-align: center;\n}\n\n.sbb-calendar__table-header-cell,\n.sbb-calendar__table-header-cell-vertical {\n width: var(--sbb-calendar-cell-size);\n color: var(--sbb-calendar-header-color);\n padding: 0;\n font-size: var(--sbb-text-font-size-xs);\n font-weight: normal;\n letter-spacing: var(--sbb-typo-letter-spacing-text);\n}\n:host(:not([multiple])) .sbb-calendar__table-header-cell,\n:host(:not([multiple])) .sbb-calendar__table-header-cell-vertical {\n height: var(--sbb-calendar-cell-size);\n}\n\n.sbb-calendar__table-header-cell-vertical {\n padding-block-end: var(--sbb-calendar-cell-padding-block-end);\n}\n\n.sbb-calendar__table-data {\n position: relative;\n padding: 0;\n text-align: center;\n}\n\n.sbb-calendar__day-cell {\n padding-block-end: var(--sbb-calendar-cell-padding-block-end);\n}\n\n:host(:not(:is(:state(enhanced),[state--enhanced]))) sbb-calendar-day {\n --sbb-calendar-cell-justify-content: center;\n --sbb-calendar-day-height: 2.75rem;\n --sbb-calendar-day-extra-display: none;\n --sbb-calendar-day-value-height: unset;\n --sbb-calendar-day-crossed-out-top: 50%;\n --sbb-calendar-day-crossed-out-translate: translate(-50%, -50%) rotate(-45deg);\n}\n\n@keyframes show {\n from {\n opacity: 0;\n transform: translateY(var(--sbb-calendar-table-animation-shift));\n }\n to {\n opacity: 1;\n transform: translateY(0%);\n }\n}\n@keyframes hide {\n from {\n opacity: 1;\n transform: translateY(0%);\n }\n to {\n opacity: 0;\n transform: translateY(var(--sbb-calendar-table-animation-shift));\n }\n}";
14
+ //#endregion
15
+ //#region src/elements/calendar/calendar/calendar.component.ts
16
+ var DAYS_PER_ROW = 7;
17
+ var MONTHS_PER_ROW = 4;
18
+ var YEARS_PER_ROW = 4;
19
+ var MONTHS_PER_PAGE = 12;
20
+ var YEARS_PER_PAGE = 24;
21
+ var SbbMonthChangeEvent = class extends Event {
22
+ get range() {
23
+ return this._range;
24
+ }
25
+ constructor(range) {
26
+ super("monthchange", {
27
+ bubbles: true,
28
+ composed: true
29
+ });
30
+ this._range = Object.freeze(range || []);
31
+ }
32
+ };
33
+ var SbbDateSelectedEvent = class extends Event {
34
+ get dateSelected() {
35
+ return this._dateSelected;
36
+ }
37
+ constructor(dates) {
38
+ super("dateselected", {
39
+ bubbles: true,
40
+ composed: true
41
+ });
42
+ this._dateSelected = Object.freeze(dates);
43
+ }
44
+ };
45
+ /**
46
+ * It displays a calendar which allows choosing a date.
47
+ *
48
+ * @slot - Use the unnamed slot to add customized `sbb-calendar-day` elements.
49
+ */
50
+ var SbbCalendarElement = (() => {
51
+ let _classSuper = SbbElement;
52
+ let _instanceExtraInitializers = [];
53
+ let _wide_decorators;
54
+ let _wide_initializers = [];
55
+ let _wide_extraInitializers = [];
56
+ let _view_decorators;
57
+ let _view_initializers = [];
58
+ let _view_extraInitializers = [];
59
+ let _min_decorators;
60
+ let _min_initializers = [];
61
+ let _min_extraInitializers = [];
62
+ let _max_decorators;
63
+ let _max_initializers = [];
64
+ let _max_extraInitializers = [];
65
+ let _multiple_decorators;
66
+ let _multiple_initializers = [];
67
+ let _multiple_extraInitializers = [];
68
+ let _set_selected_decorators;
69
+ let __selected_decorators;
70
+ let __selected_initializers = [];
71
+ let __selected_extraInitializers = [];
72
+ let _dateFilter_decorators;
73
+ let _dateFilter_initializers = [];
74
+ let _dateFilter_extraInitializers = [];
75
+ let _orientation_decorators;
76
+ let _orientation_initializers = [];
77
+ let _orientation_extraInitializers = [];
78
+ let _weekNumbers_decorators;
79
+ let _weekNumbers_initializers = [];
80
+ let _weekNumbers_extraInitializers = [];
81
+ let __activeDate_decorators;
82
+ let __activeDate_initializers = [];
83
+ let __activeDate_extraInitializers = [];
84
+ let _set__wide_decorators;
85
+ let __calendarView_decorators;
86
+ let __calendarView_initializers = [];
87
+ let __calendarView_extraInitializers = [];
88
+ let __initialized_decorators;
89
+ let __initialized_initializers = [];
90
+ let __initialized_extraInitializers = [];
91
+ return class SbbCalendarElement extends _classSuper {
92
+ static {
93
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
94
+ _wide_decorators = [forceType(), property({ type: Boolean })];
95
+ _view_decorators = [property()];
96
+ _min_decorators = [plainDate(), property()];
97
+ _max_decorators = [plainDate(), property()];
98
+ _multiple_decorators = [
99
+ forceType(),
100
+ handleDistinctChange((e, newValue) => e._onMultipleChanged(newValue)),
101
+ property({ type: Boolean })
102
+ ];
103
+ _set_selected_decorators = [property()];
104
+ __selected_decorators = [state()];
105
+ _dateFilter_decorators = [property({ attribute: "date-filter" })];
106
+ _orientation_decorators = [property({ reflect: true })];
107
+ _weekNumbers_decorators = [forceType(), property({
108
+ attribute: "week-numbers",
109
+ type: Boolean
110
+ })];
111
+ __activeDate_decorators = [state()];
112
+ _set__wide_decorators = [state()];
113
+ __calendarView_decorators = [state()];
114
+ __initialized_decorators = [state()];
115
+ __esDecorate(this, null, _wide_decorators, {
116
+ kind: "accessor",
117
+ name: "wide",
118
+ static: false,
119
+ private: false,
120
+ access: {
121
+ has: (obj) => "wide" in obj,
122
+ get: (obj) => obj.wide,
123
+ set: (obj, value) => {
124
+ obj.wide = value;
125
+ }
126
+ },
127
+ metadata: _metadata
128
+ }, _wide_initializers, _wide_extraInitializers);
129
+ __esDecorate(this, null, _view_decorators, {
130
+ kind: "accessor",
131
+ name: "view",
132
+ static: false,
133
+ private: false,
134
+ access: {
135
+ has: (obj) => "view" in obj,
136
+ get: (obj) => obj.view,
137
+ set: (obj, value) => {
138
+ obj.view = value;
139
+ }
140
+ },
141
+ metadata: _metadata
142
+ }, _view_initializers, _view_extraInitializers);
143
+ __esDecorate(this, null, _min_decorators, {
144
+ kind: "accessor",
145
+ name: "min",
146
+ static: false,
147
+ private: false,
148
+ access: {
149
+ has: (obj) => "min" in obj,
150
+ get: (obj) => obj.min,
151
+ set: (obj, value) => {
152
+ obj.min = value;
153
+ }
154
+ },
155
+ metadata: _metadata
156
+ }, _min_initializers, _min_extraInitializers);
157
+ __esDecorate(this, null, _max_decorators, {
158
+ kind: "accessor",
159
+ name: "max",
160
+ static: false,
161
+ private: false,
162
+ access: {
163
+ has: (obj) => "max" in obj,
164
+ get: (obj) => obj.max,
165
+ set: (obj, value) => {
166
+ obj.max = value;
167
+ }
168
+ },
169
+ metadata: _metadata
170
+ }, _max_initializers, _max_extraInitializers);
171
+ __esDecorate(this, null, _multiple_decorators, {
172
+ kind: "accessor",
173
+ name: "multiple",
174
+ static: false,
175
+ private: false,
176
+ access: {
177
+ has: (obj) => "multiple" in obj,
178
+ get: (obj) => obj.multiple,
179
+ set: (obj, value) => {
180
+ obj.multiple = value;
181
+ }
182
+ },
183
+ metadata: _metadata
184
+ }, _multiple_initializers, _multiple_extraInitializers);
185
+ __esDecorate(this, null, _set_selected_decorators, {
186
+ kind: "setter",
187
+ name: "selected",
188
+ static: false,
189
+ private: false,
190
+ access: {
191
+ has: (obj) => "selected" in obj,
192
+ set: (obj, value) => {
193
+ obj.selected = value;
194
+ }
195
+ },
196
+ metadata: _metadata
197
+ }, null, _instanceExtraInitializers);
198
+ __esDecorate(this, null, __selected_decorators, {
199
+ kind: "accessor",
200
+ name: "_selected",
201
+ static: false,
202
+ private: false,
203
+ access: {
204
+ has: (obj) => "_selected" in obj,
205
+ get: (obj) => obj._selected,
206
+ set: (obj, value) => {
207
+ obj._selected = value;
208
+ }
209
+ },
210
+ metadata: _metadata
211
+ }, __selected_initializers, __selected_extraInitializers);
212
+ __esDecorate(this, null, _dateFilter_decorators, {
213
+ kind: "accessor",
214
+ name: "dateFilter",
215
+ static: false,
216
+ private: false,
217
+ access: {
218
+ has: (obj) => "dateFilter" in obj,
219
+ get: (obj) => obj.dateFilter,
220
+ set: (obj, value) => {
221
+ obj.dateFilter = value;
222
+ }
223
+ },
224
+ metadata: _metadata
225
+ }, _dateFilter_initializers, _dateFilter_extraInitializers);
226
+ __esDecorate(this, null, _orientation_decorators, {
227
+ kind: "accessor",
228
+ name: "orientation",
229
+ static: false,
230
+ private: false,
231
+ access: {
232
+ has: (obj) => "orientation" in obj,
233
+ get: (obj) => obj.orientation,
234
+ set: (obj, value) => {
235
+ obj.orientation = value;
236
+ }
237
+ },
238
+ metadata: _metadata
239
+ }, _orientation_initializers, _orientation_extraInitializers);
240
+ __esDecorate(this, null, _weekNumbers_decorators, {
241
+ kind: "accessor",
242
+ name: "weekNumbers",
243
+ static: false,
244
+ private: false,
245
+ access: {
246
+ has: (obj) => "weekNumbers" in obj,
247
+ get: (obj) => obj.weekNumbers,
248
+ set: (obj, value) => {
249
+ obj.weekNumbers = value;
250
+ }
251
+ },
252
+ metadata: _metadata
253
+ }, _weekNumbers_initializers, _weekNumbers_extraInitializers);
254
+ __esDecorate(this, null, __activeDate_decorators, {
255
+ kind: "accessor",
256
+ name: "_activeDate",
257
+ static: false,
258
+ private: false,
259
+ access: {
260
+ has: (obj) => "_activeDate" in obj,
261
+ get: (obj) => obj._activeDate,
262
+ set: (obj, value) => {
263
+ obj._activeDate = value;
264
+ }
265
+ },
266
+ metadata: _metadata
267
+ }, __activeDate_initializers, __activeDate_extraInitializers);
268
+ __esDecorate(this, null, _set__wide_decorators, {
269
+ kind: "setter",
270
+ name: "_wide",
271
+ static: false,
272
+ private: false,
273
+ access: {
274
+ has: (obj) => "_wide" in obj,
275
+ set: (obj, value) => {
276
+ obj._wide = value;
277
+ }
278
+ },
279
+ metadata: _metadata
280
+ }, null, _instanceExtraInitializers);
281
+ __esDecorate(this, null, __calendarView_decorators, {
282
+ kind: "accessor",
283
+ name: "_calendarView",
284
+ static: false,
285
+ private: false,
286
+ access: {
287
+ has: (obj) => "_calendarView" in obj,
288
+ get: (obj) => obj._calendarView,
289
+ set: (obj, value) => {
290
+ obj._calendarView = value;
291
+ }
292
+ },
293
+ metadata: _metadata
294
+ }, __calendarView_initializers, __calendarView_extraInitializers);
295
+ __esDecorate(this, null, __initialized_decorators, {
296
+ kind: "accessor",
297
+ name: "_initialized",
298
+ static: false,
299
+ private: false,
300
+ access: {
301
+ has: (obj) => "_initialized" in obj,
302
+ get: (obj) => obj._initialized,
303
+ set: (obj, value) => {
304
+ obj._initialized = value;
305
+ }
306
+ },
307
+ metadata: _metadata
308
+ }, __initialized_initializers, __initialized_extraInitializers);
309
+ if (_metadata) Object.defineProperty(this, Symbol.metadata, {
310
+ enumerable: true,
311
+ configurable: true,
312
+ writable: true,
313
+ value: _metadata
314
+ });
315
+ }
316
+ static {
317
+ this.elementName = "sbb-calendar";
318
+ }
319
+ static {
320
+ this.elementDependencies = [
321
+ SbbCalendarDayElement,
322
+ SbbCalendarMonthElement,
323
+ SbbCalendarWeekdayElement,
324
+ SbbCalendarWeeknumberElement,
325
+ SbbCalendarYearElement,
326
+ SbbIconElement,
327
+ SbbSecondaryButtonElement
328
+ ];
329
+ }
330
+ static {
331
+ this.styles = [
332
+ buttonResetStyles,
333
+ screenReaderOnlyStyles,
334
+ unsafeCSS(calendar_default)
335
+ ];
336
+ }
337
+ static {
338
+ this.events = {
339
+ dateselected: "dateselected",
340
+ monthchange: "monthchange"
341
+ };
342
+ }
343
+ #wide_accessor_storage;
344
+ /** If set to true, two months are displayed */
345
+ get wide() {
346
+ return this.#wide_accessor_storage;
347
+ }
348
+ set wide(value) {
349
+ this.#wide_accessor_storage = value;
350
+ }
351
+ #view_accessor_storage;
352
+ /** The initial view of the calendar which should be displayed on opening. */
353
+ get view() {
354
+ return this.#view_accessor_storage;
355
+ }
356
+ set view(value) {
357
+ this.#view_accessor_storage = value;
358
+ }
359
+ #min_accessor_storage;
360
+ /**
361
+ * The minimum valid date. Accepts a date object or null.
362
+ * Accepts an ISO8601 formatted string (e.g. 2024-12-24) as attribute.
363
+ */
364
+ get min() {
365
+ return this.#min_accessor_storage;
366
+ }
367
+ set min(value) {
368
+ this.#min_accessor_storage = value;
369
+ }
370
+ #max_accessor_storage;
371
+ /**
372
+ * The maximum valid date. Accepts a date object or null.
373
+ * Accepts an ISO8601 formatted string (e.g. 2024-12-24) as attribute.
374
+ */
375
+ get max() {
376
+ return this.#max_accessor_storage;
377
+ }
378
+ set max(value) {
379
+ this.#max_accessor_storage = value;
380
+ }
381
+ #multiple_accessor_storage;
382
+ /** Whether the calendar allows for multiple date selection. */
383
+ get multiple() {
384
+ return this.#multiple_accessor_storage;
385
+ }
386
+ set multiple(value) {
387
+ this.#multiple_accessor_storage = value;
388
+ }
389
+ /**
390
+ * The selected date: accepts a date object, or, if `multiple`, an array of dates.
391
+ */
392
+ set selected(value) {
393
+ if (Array.isArray(value)) this._selected = value.map((dateLike) => this._dateAdapter.getValidDateOrNull(this._dateAdapter.deserialize(dateLike))).filter((date) => date !== null).filter((date) => !this._isDayInRange(this._dateAdapter.toIso8601(date)) || this._dateFilter(date)).sort(this._sortDate);
394
+ else {
395
+ const selectedDate = this._dateAdapter.getValidDateOrNull(this._dateAdapter.deserialize(value));
396
+ if (!!selectedDate && (!this._isDayInRange(this._dateAdapter.toIso8601(selectedDate)) || this._dateFilter(selectedDate))) this._selected = selectedDate;
397
+ else this._selected = null;
398
+ }
399
+ }
400
+ get selected() {
401
+ return this._selected;
402
+ }
403
+ #_selected_accessor_storage;
404
+ get _selected() {
405
+ return this.#_selected_accessor_storage;
406
+ }
407
+ set _selected(value) {
408
+ this.#_selected_accessor_storage = value;
409
+ }
410
+ #dateFilter_accessor_storage;
411
+ /** A function used to filter out dates. */
412
+ get dateFilter() {
413
+ return this.#dateFilter_accessor_storage;
414
+ }
415
+ set dateFilter(value) {
416
+ this.#dateFilter_accessor_storage = value;
417
+ }
418
+ #orientation_accessor_storage;
419
+ /** The orientation of days in the calendar. */
420
+ get orientation() {
421
+ return this.#orientation_accessor_storage;
422
+ }
423
+ set orientation(value) {
424
+ this.#orientation_accessor_storage = value;
425
+ }
426
+ #weekNumbers_accessor_storage;
427
+ /** Whether it has to display the week numbers in addition to week days. */
428
+ get weekNumbers() {
429
+ return this.#weekNumbers_accessor_storage;
430
+ }
431
+ set weekNumbers(value) {
432
+ this.#weekNumbers_accessor_storage = value;
433
+ }
434
+ #_activeDate_accessor_storage;
435
+ /** The currently active date. */
436
+ get _activeDate() {
437
+ return this.#_activeDate_accessor_storage;
438
+ }
439
+ set _activeDate(value) {
440
+ this.#_activeDate_accessor_storage = value;
441
+ }
442
+ /** The current wide property considering property value and breakpoints. From zero to small `wide` has always to be false. */
443
+ set _wide(wide) {
444
+ this.toggleState("wide", wide);
445
+ this._wideInternal = wide;
446
+ }
447
+ get _wide() {
448
+ return this._wideInternal;
449
+ }
450
+ #_calendarView_accessor_storage;
451
+ get _calendarView() {
452
+ return this.#_calendarView_accessor_storage;
453
+ }
454
+ set _calendarView(value) {
455
+ this.#_calendarView_accessor_storage = value;
456
+ }
457
+ /** A list of calendar's cells corresponding to days, months or years depending on the view. */
458
+ get _cells() {
459
+ return Array.from((this._calendarView === "day" ? Array.from(this.shadowRoot.querySelectorAll("slot")).flatMap((e) => e.assignedElements({ flatten: true })) : this.shadowRoot?.querySelectorAll(`sbb-calendar-${this._calendarView}`)) ?? []);
460
+ }
461
+ #_initialized_accessor_storage;
462
+ get _initialized() {
463
+ return this.#_initialized_accessor_storage;
464
+ }
465
+ set _initialized(value) {
466
+ this.#_initialized_accessor_storage = value;
467
+ }
468
+ constructor() {
469
+ super();
470
+ this.#wide_accessor_storage = (__runInitializers(this, _instanceExtraInitializers), __runInitializers(this, _wide_initializers, false));
471
+ this.#view_accessor_storage = (__runInitializers(this, _wide_extraInitializers), __runInitializers(this, _view_initializers, "day"));
472
+ this.#min_accessor_storage = (__runInitializers(this, _view_extraInitializers), __runInitializers(this, _min_initializers, null));
473
+ this.#max_accessor_storage = (__runInitializers(this, _min_extraInitializers), __runInitializers(this, _max_initializers, null));
474
+ this.#multiple_accessor_storage = (__runInitializers(this, _max_extraInitializers), __runInitializers(this, _multiple_initializers, false));
475
+ this.#_selected_accessor_storage = (__runInitializers(this, _multiple_extraInitializers), __runInitializers(this, __selected_initializers, null));
476
+ this.#dateFilter_accessor_storage = (__runInitializers(this, __selected_extraInitializers), __runInitializers(this, _dateFilter_initializers, null));
477
+ this.#orientation_accessor_storage = (__runInitializers(this, _dateFilter_extraInitializers), __runInitializers(this, _orientation_initializers, "horizontal"));
478
+ this.#weekNumbers_accessor_storage = (__runInitializers(this, _orientation_extraInitializers), __runInitializers(this, _weekNumbers_initializers, false));
479
+ this._dateAdapter = (__runInitializers(this, _weekNumbers_extraInitializers), readConfig().datetime?.dateAdapter ?? defaultDateAdapter);
480
+ this.#_activeDate_accessor_storage = __runInitializers(this, __activeDate_initializers, this._dateAdapter.today());
481
+ this._wideInternal = (__runInitializers(this, __activeDate_extraInitializers), false);
482
+ this.#_calendarView_accessor_storage = __runInitializers(this, __calendarView_initializers, "day");
483
+ this._nextCalendarView = (__runInitializers(this, __calendarView_extraInitializers), "day");
484
+ /** Information about the rendered day view; used in keyboard navigation. */
485
+ this._keyboardNavigationDayViewParameters = {
486
+ firstDayInView: null,
487
+ lastDayInView: null,
488
+ firstMonthOffset: 0,
489
+ firstMonthLength: 0,
490
+ secondMonthOffset: 0
491
+ };
492
+ /** Grid of calendar cells representing the dates of the month. */
493
+ this._weeks = [];
494
+ /** An array containing all the month names in the current language. */
495
+ this._monthNames = this._dateAdapter.getMonthNames("long");
496
+ this._enhancedVariant = false;
497
+ /** Whether the focus should be reset on focusCell. */
498
+ this._resetFocus = false;
499
+ /** Whether an element inside the calendar is currently focused. */
500
+ this._containingFocus = false;
501
+ this._lastSelection = null;
502
+ this.#_initialized_accessor_storage = __runInitializers(this, __initialized_initializers, false);
503
+ this._language = (__runInitializers(this, __initialized_extraInitializers), new SbbLanguageController(this).withHandler(() => {
504
+ this._monthNames = this._dateAdapter.getMonthNames("long");
505
+ this._createMonthRows();
506
+ }));
507
+ this._mediaMatcher = new SbbMediaMatcherController(this, { [SbbMediaQueryBreakpointLargeAndAbove]: () => this._init() });
508
+ this._sortDate = (a, b) => this._dateAdapter.compareDate(a, b);
509
+ this._onSlotChange = () => {
510
+ this._enhancedVariant = Array.from(this.children).some((c) => c.localName === "sbb-calendar-day");
511
+ this.toggleState("enhanced", this._enhancedVariant);
512
+ this._setTabIndex();
513
+ };
514
+ this._createMonthRows();
515
+ this._setWeekdays();
516
+ this.addEventListener("focusin", () => this._containingFocus = true);
517
+ this.addEventListener("focusout", () => this._containingFocus = false);
518
+ const resolveDay = (event) => event.target.closest("sbb-calendar-day") ?? event.composedPath().find((e) => e.localName === "sbb-calendar-day") ?? null;
519
+ this.addEventListener("click", (event) => {
520
+ const day = resolveDay(event);
521
+ if (day) this._selectDate(day.value, event);
522
+ });
523
+ this.addEventListener("keydown", (event) => {
524
+ const day = resolveDay(event);
525
+ if (day) this._handleKeyboardEvent(event, day);
526
+ });
527
+ this.addEventListener("blur", () => this._lastSelection = null);
528
+ }
529
+ _dateFilter(date) {
530
+ return this.dateFilter?.(date) ?? true;
531
+ }
532
+ /** Resets the active month according to the new state of the calendar. */
533
+ resetPosition() {
534
+ this._resetCalendarView();
535
+ this._init();
536
+ }
537
+ connectedCallback() {
538
+ super.connectedCallback();
539
+ this.resetPosition();
540
+ this.shadowRoot?.addEventListener("slotchange", this._onSlotChange, { capture: true });
541
+ }
542
+ disconnectedCallback() {
543
+ super.disconnectedCallback();
544
+ this.shadowRoot?.removeEventListener("slotchange", this._onSlotChange, { capture: true });
545
+ }
546
+ /** @internal */
547
+ focus() {
548
+ this._resetFocus = true;
549
+ this._focusCell();
550
+ }
551
+ willUpdate(changedProperties) {
552
+ super.willUpdate(changedProperties);
553
+ if (!this._initialized) return;
554
+ if (changedProperties.has("wide") || changedProperties.has("orientation")) this.resetPosition();
555
+ if (changedProperties.has("view")) {
556
+ this._setChosenYear();
557
+ this._chosenMonth = void 0;
558
+ this._nextCalendarView = this._calendarView = this.view;
559
+ }
560
+ }
561
+ updated(changedProperties) {
562
+ super.updated(changedProperties);
563
+ this._setTabIndex();
564
+ this._focusCell();
565
+ }
566
+ /**
567
+ * The `_selected` state should be adapted when the `multiple` property changes:
568
+ * - if it changes to true, the '_selected' is set to an array;
569
+ * - if it changes to false, the first available option is set as 'value' otherwise it's set to null.
570
+ */
571
+ _onMultipleChanged(isMultiple) {
572
+ if (isMultiple && !Array.isArray(this._selected)) this._selected = this._selected ? [this._selected] : [];
573
+ if (!isMultiple && Array.isArray(this._selected)) this._selected = this._selected.length ? this._selected[0] : null;
574
+ }
575
+ /** Initializes the component. */
576
+ _init(activeDate) {
577
+ if (isServer) return;
578
+ else if (this.hydrationRequired) {
579
+ this.hydrationComplete.then(() => this._init());
580
+ return;
581
+ }
582
+ if (activeDate) this._assignActiveDate(activeDate);
583
+ this._wide = (this._mediaMatcher.matches(SbbMediaQueryBreakpointLargeAndAbove) ?? false) && this.wide;
584
+ this._weeks = this._createWeekRows(this._activeDate);
585
+ this._years = this._createYearRows();
586
+ this._weekNumbers = this._weeks.flat().sort((a, b) => a.value.localeCompare(b.value)).map((day) => day.weekValue).filter((v, i, a) => a.indexOf(v) === i);
587
+ this._nextMonthWeeks = [[]];
588
+ this._nextMonthYears = [[]];
589
+ if (this._wide) {
590
+ const nextMonthDate = this._dateAdapter.addCalendarMonths(this._activeDate, 1);
591
+ this._nextMonthWeeks = this._createWeekRows(nextMonthDate, true);
592
+ this._nextMonthYears = this._createYearRows(YEARS_PER_PAGE);
593
+ this._nextMonthWeekNumbers = this._nextMonthWeeks.flat().sort((a, b) => a.value.localeCompare(b.value)).map((day) => day.weekValue).filter((v, i, a) => a.indexOf(v) === i);
594
+ }
595
+ this._initialized = true;
596
+ }
597
+ /** Focuses on a day cell prioritizing the selected day, the current day, and lastly, the first selectable day. */
598
+ _focusCell() {
599
+ if (this._resetFocus) {
600
+ this._getFirstFocusable()?.focus();
601
+ this._resetFocus = false;
602
+ }
603
+ }
604
+ /** Creates the array of weekdays. */
605
+ _setWeekdays() {
606
+ const narrowWeekdays = this._dateAdapter.getDayOfWeekNames("narrow");
607
+ const weekdays = this._dateAdapter.getDayOfWeekNames("long").map((long, i) => ({
608
+ long,
609
+ narrow: narrowWeekdays[i]
610
+ }));
611
+ const firstDayOfWeek = this._dateAdapter.getFirstDayOfWeek();
612
+ this._weekdays = weekdays.slice(firstDayOfWeek).concat(weekdays.slice(0, firstDayOfWeek));
613
+ }
614
+ /** Creates the rows along the horizontal direction and sets the parameters used in keyboard navigation. */
615
+ _createWeekRows(value, isSecondMonthInView = false) {
616
+ const daysInMonth = this._dateAdapter.getNumDaysInMonth(value);
617
+ const weekOffset = this._dateAdapter.getFirstWeekOffset(value);
618
+ if (!isSecondMonthInView) {
619
+ this._keyboardNavigationDayViewParameters.firstMonthLength = daysInMonth;
620
+ this._keyboardNavigationDayViewParameters.firstMonthOffset = weekOffset;
621
+ this._keyboardNavigationDayViewParameters.firstDayInView = this._dateAdapter.toIso8601(this._dateAdapter.createDate(this._dateAdapter.getYear(value), this._dateAdapter.getMonth(value), 1));
622
+ this._keyboardNavigationDayViewParameters.lastDayInView = this._dateAdapter.toIso8601(this._dateAdapter.createDate(this._dateAdapter.getYear(value), this._dateAdapter.getMonth(value), daysInMonth));
623
+ } else {
624
+ this._keyboardNavigationDayViewParameters.secondMonthOffset = weekOffset;
625
+ this._keyboardNavigationDayViewParameters.lastDayInView = this._dateAdapter.toIso8601(this._dateAdapter.createDate(this._dateAdapter.getYear(value), this._dateAdapter.getMonth(value), daysInMonth));
626
+ }
627
+ return this.orientation === "horizontal" ? this._createWeekRowsHorizontal(value, daysInMonth, weekOffset) : this._createWeekRowsVertical(value, daysInMonth, weekOffset);
628
+ }
629
+ /**
630
+ * Creates the rows for each week in orientation='horizontal'.
631
+ *
632
+ * Iterates through the days of the months, creates a Day object for each and pushes it into and array.
633
+ * Each seven days (considering the offset at the beginning of the month) restarts from an empty array.
634
+ *
635
+ * The result is a matrix in which every row is a week (or part of it, considering offset).
636
+ */
637
+ _createWeekRowsHorizontal(value, daysInMonth, weekOffset) {
638
+ const weeks = [[]];
639
+ for (let i = 0, cell = weekOffset; i < daysInMonth; i++, cell++) {
640
+ if (cell === DAYS_PER_ROW) {
641
+ weeks.push([]);
642
+ cell = 0;
643
+ }
644
+ const date = this._dateAdapter.createDate(this._dateAdapter.getYear(value), this._dateAdapter.getMonth(value), i + 1);
645
+ weeks[weeks.length - 1].push(this._mapDateToDay(date));
646
+ }
647
+ return weeks;
648
+ }
649
+ /**
650
+ * Creates the rows for each week in orientation='vertical'.
651
+ *
652
+ * Creates a matrix with seven empty rows.
653
+ * Iterates through the days of the months, creates a Day object for each
654
+ * and pushes it into the correct array considering the offset at the beginning of the month.
655
+ * Each seven days (including offset) restarts from the first.
656
+ *
657
+ * The result is a matrix in which every row is a set of weekdays, so:
658
+ * - row 0: all the Mondays;
659
+ * - row 1: all the Tuesdays;
660
+ * - ...
661
+ * - row 7: all the Sundays.
662
+ */
663
+ _createWeekRowsVertical(value, daysInMonth, weekOffset) {
664
+ const weeks = Array.from({ length: DAYS_PER_ROW }, () => []);
665
+ for (let i = 0, cell = weekOffset; i < daysInMonth; i++, cell++) {
666
+ if (cell === DAYS_PER_ROW) cell = 0;
667
+ const date = this._dateAdapter.createDate(this._dateAdapter.getYear(value), this._dateAdapter.getMonth(value), i + 1);
668
+ weeks[cell].push(this._mapDateToDay(date));
669
+ }
670
+ return weeks;
671
+ }
672
+ _mapDateToDay(date) {
673
+ return {
674
+ value: this._dateAdapter.toIso8601(date),
675
+ dateValue: date,
676
+ dayValue: String(this._dateAdapter.getDate(date)),
677
+ monthValue: String(this._dateAdapter.getMonth(date)),
678
+ yearValue: String(this._dateAdapter.getYear(date)),
679
+ weekValue: this._getWeek(date),
680
+ weekDayValue: this._dateAdapter.getDayOfWeek(date)
681
+ };
682
+ }
683
+ _getWeek(date) {
684
+ const firstDayOfYear = this._dateAdapter.createDate(this._dateAdapter.getYear(date), 1, 1);
685
+ const weekday = this._dateAdapter.getDayOfWeek(firstDayOfYear);
686
+ let weekIndex = [
687
+ MONDAY,
688
+ TUESDAY,
689
+ WEDNESDAY,
690
+ THURSDAY
691
+ ].includes(weekday) ? 1 : 0;
692
+ let weekStart = this._dateAdapter.addCalendarDays(firstDayOfYear, this._dateAdapter.getFirstWeekOffset(firstDayOfYear) * -1);
693
+ while (this._dateAdapter.compareDate(weekStart, date) <= 0) {
694
+ const weekEnd = this._dateAdapter.addCalendarDays(weekStart, 6);
695
+ if (this._dateAdapter.compareDate(date, weekEnd) <= 0) return weekIndex > 0 ? weekIndex : this._getWeek(this._dateAdapter.addCalendarDays(firstDayOfYear, -1));
696
+ weekStart = this._dateAdapter.addCalendarDays(weekStart, DAYS_PER_ROW);
697
+ weekIndex++;
698
+ }
699
+ throw new Error("The provided date is invalid");
700
+ }
701
+ /** Force the conversion to ISO8601 formatted string. */
702
+ _mapValueToISODate(value) {
703
+ return typeof value === "string" ? value : this._dateAdapter.toIso8601(value);
704
+ }
705
+ /** Creates the rows for the month selection view. */
706
+ _createMonthRows() {
707
+ const months = new Array(12).fill(null).map((_, i) => ({
708
+ value: String(i + 1).padStart(2, "0"),
709
+ monthValue: i + 1
710
+ }));
711
+ const rows = 12 / MONTHS_PER_ROW;
712
+ const monthArray = [];
713
+ for (let i = 0; i < rows; i++) monthArray.push(months.slice(MONTHS_PER_ROW * i, MONTHS_PER_ROW * (i + 1)));
714
+ this._months = monthArray;
715
+ }
716
+ /** Creates the rows for the year selection view. */
717
+ _createYearRows(offset = 0) {
718
+ const startValueYearView = this._getStartValueYearView();
719
+ const allYears = new Array(YEARS_PER_PAGE).fill(0).map((_, i) => startValueYearView + offset + i);
720
+ const rows = YEARS_PER_PAGE / YEARS_PER_ROW;
721
+ const yearArray = [];
722
+ for (let i = 0; i < rows; i++) yearArray.push(allYears.slice(YEARS_PER_ROW * i, YEARS_PER_ROW * (i + 1)));
723
+ return yearArray;
724
+ }
725
+ /**
726
+ * Calculates the first year that will be shown in the year selection panel.
727
+ * If `minDate` and `maxDate` are both null, the starting year is calculated as
728
+ * the multiple of YEARS_PER_PAGE closest to and less than activeDate,
729
+ * e.g., with `YEARS_PER_PAGE` = 24 and `activeDate` = 2020, the function will return 2016 (24 * 83),
730
+ * while with `activeDate` = 2000, the function will return 1992 (24 * 82).
731
+ * If `minDate` is not null, it returns the corresponding year; if `maxDate` is not null,
732
+ * it returns the corresponding year minus `YEARS_PER_PAGE`, so that the `maxDate` is the last rendered year.
733
+ * If both are not null, `maxDate` has priority over `minDate`.
734
+ */
735
+ _getStartValueYearView() {
736
+ let startingYear = 0;
737
+ if (this.max) startingYear = this._dateAdapter.getYear(this.max) - YEARS_PER_PAGE + 1;
738
+ else if (this.min) startingYear = this._dateAdapter.getYear(this.min);
739
+ const activeYear = this._dateAdapter.getYear(this._activeDate);
740
+ return activeYear - ((activeYear - startingYear) % YEARS_PER_PAGE + YEARS_PER_PAGE) % YEARS_PER_PAGE;
741
+ }
742
+ /** Checks if date is within the min-max range. */
743
+ _isDayInRange(dateString) {
744
+ if (!this.min && !this.max) return true;
745
+ const date = this._dateAdapter.deserialize(dateString);
746
+ return this._dateAdapter.sameDate(date, this._dateAdapter.clampDate(date, this.min, this.max));
747
+ }
748
+ /** Emits the selected date and sets it internally. */
749
+ _selectDate(day, event) {
750
+ this._chosenMonth = void 0;
751
+ this._setChosenYear();
752
+ if (this.multiple) {
753
+ window.getSelection()?.removeAllRanges();
754
+ let selected = !this._selected ? [] : Array.isArray(this._selected) ? this._selected : [this._selected];
755
+ const serializedSelected = selected.map((s) => this._dateAdapter.toIso8601(s));
756
+ if (event.shiftKey && this._lastSelection && serializedSelected.includes(this._dateAdapter.toIso8601(this._lastSelection)) && !serializedSelected.includes(this._dateAdapter.toIso8601(day))) {
757
+ const offset = this._dateAdapter.compareDate(this._lastSelection, day) < 0 ? 1 : -1;
758
+ const range = [];
759
+ let current = this._lastSelection;
760
+ while (!this._dateAdapter.sameDate(current, day)) {
761
+ current = this._dateAdapter.addCalendarDays(current, offset);
762
+ const serializedCurrent = this._dateAdapter.toIso8601(current);
763
+ if (!serializedSelected.includes(serializedCurrent)) range.push(serializedCurrent);
764
+ }
765
+ selected = this._mergeDates(range, serializedSelected);
766
+ } else if (selected.some((sel) => this._dateAdapter.sameDate(sel, day))) selected = selected.filter((sel) => !this._dateAdapter.sameDate(sel, day));
767
+ else selected = [...selected, day].sort(this._sortDate);
768
+ this._lastSelection = day;
769
+ this._selected = selected;
770
+ this._emitDateSelectedEvent(this._selected.map((e) => this._dateAdapter.deserialize(e)));
771
+ } else if (!this._selected || this._dateAdapter.compareDate(this._selected, day) !== 0) {
772
+ this._selected = day;
773
+ this._emitDateSelectedEvent(this._dateAdapter.deserialize(day));
774
+ }
775
+ }
776
+ /**
777
+ * Handle multiple dates selection via weekNumber / weekDay buttons:
778
+ * - if Cmd or Ctrl are pressed, add the new date to the current ones;
779
+ * - if not,
780
+ * - if the new dates are the same of the current ones, it means that the same button has been clicked twice, so do nothing;
781
+ * - if not, the selected dates are the new ones.
782
+ */
783
+ _selectMultipleDates(days) {
784
+ this._selected = this._mergeDates(days.map((e) => e.value));
785
+ this._emitDateSelectedEvent(this._selected.map((e) => this._dateAdapter.deserialize(e)));
786
+ }
787
+ _mergeDates(dates, selected) {
788
+ selected ??= this._selected.map((s) => this._dateAdapter.toIso8601(s));
789
+ const enabledDays = this._cells.filter((e) => !e.disabled).map((e) => this._mapValueToISODate(e.value));
790
+ const daysToAdd = dates.filter((isoDate) => enabledDays.includes(isoDate));
791
+ if (daysToAdd.every((day) => selected.includes(day))) selected = selected.filter((day) => !daysToAdd.includes(day));
792
+ else selected = [...selected, ...daysToAdd].filter((v, i, a) => a.indexOf(v) === i);
793
+ return selected.map((s) => this._dateAdapter.deserialize(s)).sort(this._sortDate);
794
+ }
795
+ /**
796
+ * Emits the dateselected event given the detail (as T or T[] based on the value of the multiple flag).
797
+ * FIXME: the name of the variable appears as event name in the readme
798
+ * due to a bug in the custom-elements-manifest library.
799
+ * https://github.com/open-wc/custom-elements-manifest/issues/149
800
+ */
801
+ _emitDateSelectedEvent(dateselected) {
802
+ /** @type {SbbDateSelectedEvent<T>} Event emitted on date selection. */
803
+ this.dispatchEvent(new SbbDateSelectedEvent(dateselected));
804
+ }
805
+ _emitMonthChange() {
806
+ const monthchange = (this.wide ? [...this._weeks, ...this._nextMonthWeeks] : this._weeks).flat().sort((a, b) => a.value.localeCompare(b.value));
807
+ /**
808
+ * @type {SbbMonthChangeEvent}
809
+ * Emits when the month changes.
810
+ * The `range` property contains the days array of the chosen month.
811
+ */
812
+ this.dispatchEvent(new SbbMonthChangeEvent(monthchange));
813
+ }
814
+ _setChosenYear() {
815
+ if (this.view === "month") {
816
+ let selectedDate;
817
+ if (this.multiple) selectedDate = this.selected.at(-1);
818
+ else selectedDate = this.selected;
819
+ this._chosenYear = this._dateAdapter.getYear(selectedDate ?? this._dateAdapter.today());
820
+ } else this._chosenYear = void 0;
821
+ }
822
+ _assignActiveDate(date) {
823
+ if (this.min && this._dateAdapter.compareDate(this.min, date) > 0) {
824
+ this._activeDate = this.min;
825
+ return;
826
+ }
827
+ if (this.max && this._dateAdapter.compareDate(this.max, date) < 0) {
828
+ this._activeDate = this.max;
829
+ return;
830
+ }
831
+ this._activeDate = date;
832
+ }
833
+ /** Goes to the month identified by the shift. */
834
+ _goToDifferentMonth(months) {
835
+ this._init(this._dateAdapter.addCalendarMonths(this._activeDate, months));
836
+ this._emitMonthChange();
837
+ }
838
+ _goToDifferentYear(years) {
839
+ this._chosenYear += years;
840
+ this._activeDate = this._dateAdapter.createDate(this._chosenYear, this._dateAdapter.getMonth(this._activeDate), this._dateAdapter.getDate(this._activeDate));
841
+ this._init();
842
+ }
843
+ _goToDifferentYearRange(years) {
844
+ this._init(this._dateAdapter.addCalendarYears(this._activeDate, years));
845
+ }
846
+ _prevDisabled(prevDate) {
847
+ if (!this.min) return false;
848
+ return this._dateAdapter.compareDate(prevDate, this.min) < 0;
849
+ }
850
+ _nextDisabled(nextDate) {
851
+ if (!this.max) return false;
852
+ return this._dateAdapter.compareDate(nextDate, this.max) > 0;
853
+ }
854
+ /** Checks if the "previous month" button should be disabled. */
855
+ _previousMonthDisabled() {
856
+ const prevMonth = this._dateAdapter.addCalendarDays(this._activeDate, this._dateAdapter.getDate(this._activeDate) * -1);
857
+ return this._prevDisabled(prevMonth);
858
+ }
859
+ /** Checks if the "next month" button should be disabled. */
860
+ _nextMonthDisabled() {
861
+ let nextMonth = this._dateAdapter.addCalendarMonths(this._activeDate, this._wide ? 2 : 1);
862
+ nextMonth = this._dateAdapter.createDate(this._dateAdapter.getYear(nextMonth), this._dateAdapter.getMonth(nextMonth), 1);
863
+ return this._nextDisabled(nextMonth);
864
+ }
865
+ /** Checks if the "previous year" button should be disabled. */
866
+ _previousYearDisabled() {
867
+ const prevYear = this._dateAdapter.createDate(this._dateAdapter.getYear(this._activeDate) - 1, 12, 31);
868
+ return this._prevDisabled(prevYear);
869
+ }
870
+ /** Checks if the "next year" button should be disabled. */
871
+ _nextYearDisabled() {
872
+ const nextYear = this._dateAdapter.createDate(this._dateAdapter.getYear(this._activeDate) + (this._wide ? 2 : 1), 1, 1);
873
+ return this._nextDisabled(nextYear);
874
+ }
875
+ /** Checks if the "previous year" button should be disabled in year view. */
876
+ _previousYearRangeDisabled() {
877
+ const prevYear = this._dateAdapter.createDate(this._years[0][0] - 1, 12, 31);
878
+ return this._prevDisabled(prevYear);
879
+ }
880
+ /** Checks if the "next year" button should be disabled in year view. */
881
+ _nextYearRangeDisabled() {
882
+ const years = this._wide ? this._nextMonthYears : this._years;
883
+ const lastYearRange = years[years.length - 1];
884
+ const lastYear = lastYearRange[lastYearRange.length - 1];
885
+ const nextYear = this._dateAdapter.createDate(lastYear + 1, 1, 1);
886
+ return this._nextDisabled(nextYear);
887
+ }
888
+ _handleTableBlur(eventTarget) {
889
+ if (eventTarget?.localName !== "sbb-calendar-day") this._setTabIndex();
890
+ }
891
+ _setTabIndex() {
892
+ Array.from(this._cells.filter((e) => e.tabIndex === 0) ?? []).forEach((day) => day.tabIndex = -1);
893
+ const firstFocusable = this._getFirstFocusable();
894
+ if (firstFocusable) firstFocusable.tabIndex = 0;
895
+ }
896
+ /** Get the element in the calendar to assign focus. */
897
+ _getFirstFocusable() {
898
+ if (this._calendarView === "day") {
899
+ const selectedOrCurrent = this._cells.find((e) => e.matches(":is(:state(selected),[state--selected])")) ?? this._cells.find((e) => e.matches(":is(:state(current),[state--current])"));
900
+ return selectedOrCurrent && !selectedOrCurrent.disabled ? selectedOrCurrent : this._getFirstFocusableDay();
901
+ } else {
902
+ const selectedOrCurrent = this.shadowRoot?.querySelector(":is(:state(selected),[state--selected])") ?? this.shadowRoot?.querySelector(":is(:state(current),[state--current])");
903
+ return selectedOrCurrent && !selectedOrCurrent.disabled ? selectedOrCurrent : this.shadowRoot.querySelector(`sbb-calendar-${this._calendarView}:not([disabled])`);
904
+ }
905
+ }
906
+ /**
907
+ * In `day` view in `vertical` orientation,
908
+ * if the first of the month is not a Monday, it is not the first rendered element in the table,
909
+ * so `this.shadowRoot!.querySelector('sbb-calendar-day:not([disabled])')` will return a wrong value.
910
+ *
911
+ * To solve this, the element with the lowest `value` is taken (ISO String are ordered).
912
+ */
913
+ _getFirstFocusableDay() {
914
+ const cells = this._cells;
915
+ const daysInView = cells.filter((e) => !e.disabled);
916
+ if (!daysInView || daysInView.length === 0) return null;
917
+ else {
918
+ const firstElement = daysInView.map((e) => this._dateAdapter.toIso8601(e.value)).sort()[0];
919
+ return cells.find((e) => e.matches(`[slot="${firstElement}"]`)) ?? null;
920
+ }
921
+ }
922
+ _handleKeyboardEvent(event, day) {
923
+ if (isArrowKeyOrPageKeysPressed(event)) event.preventDefault();
924
+ const origin = day ?? event.target;
925
+ const cells = this._cells;
926
+ const index = cells.indexOf(origin);
927
+ let nextEl;
928
+ if (day) nextEl = this._navigateByKeyboardDayView(event, index, cells, this._mapDateToDay(day.value));
929
+ else nextEl = this._navigateByKeyboard(event, index, cells);
930
+ const activeEl = (this._enhancedVariant ? document : this.shadowRoot).activeElement;
931
+ if (nextEl !== activeEl) {
932
+ nextEl.tabIndex = 0;
933
+ nextEl?.focus();
934
+ activeEl.tabIndex = -1;
935
+ }
936
+ }
937
+ _navigateByKeyboardDayView(evt, index, cells, day) {
938
+ const arrowsOffset = this.orientation === "horizontal" ? {
939
+ leftRight: 1,
940
+ upDown: DAYS_PER_ROW
941
+ } : {
942
+ leftRight: DAYS_PER_ROW,
943
+ upDown: 1
944
+ };
945
+ const offsetForVertical = index < this._keyboardNavigationDayViewParameters.firstMonthLength ? this._keyboardNavigationDayViewParameters.firstMonthOffset : this._keyboardNavigationDayViewParameters.secondMonthOffset;
946
+ switch (evt.key) {
947
+ case "ArrowUp": return this._findDayArrows(cells, index, day.dateValue, -arrowsOffset.upDown);
948
+ case "ArrowDown": return this._findDayArrows(cells, index, day.dateValue, arrowsOffset.upDown);
949
+ case "ArrowLeft": return this._findDayArrows(cells, index, day.dateValue, -arrowsOffset.leftRight);
950
+ case "ArrowRight": return this._findDayArrows(cells, index, day.dateValue, arrowsOffset.leftRight);
951
+ case "PageUp": if (this.orientation === "horizontal") {
952
+ const delta = (+day.dayValue % DAYS_PER_ROW || DAYS_PER_ROW) - +day.dayValue;
953
+ return this._findDayPageUpDown(cells, index, day, delta, arrowsOffset.upDown);
954
+ } else {
955
+ const delta = (Math.ceil((+day.dayValue + offsetForVertical) / DAYS_PER_ROW) - 1) * DAYS_PER_ROW - offsetForVertical + 1 - +day.dayValue;
956
+ return this._findDayPageUpDown(cells, index, day, delta, arrowsOffset.upDown);
957
+ }
958
+ case "PageDown": if (this.orientation === "horizontal") {
959
+ const monthInBounds = +day.monthValue + 1 > 12 ? 1 : +day.monthValue + 1;
960
+ const yearInBounds = +day.monthValue + 1 > 12 ? +day.yearValue + 1 : +day.yearValue;
961
+ const firstNextMonth = this._dateAdapter.createDate(yearInBounds, monthInBounds, 1);
962
+ const lastOfMonth = this._dateAdapter.getDate(this._dateAdapter.addCalendarDays(firstNextMonth, -1));
963
+ const delta = Math.trunc((lastOfMonth - +day.dayValue) / DAYS_PER_ROW) * DAYS_PER_ROW;
964
+ return this._findDayPageUpDown(cells, index, day, delta, -arrowsOffset.upDown);
965
+ } else {
966
+ const delta = Math.ceil((+day.dayValue + offsetForVertical) / DAYS_PER_ROW) * DAYS_PER_ROW - offsetForVertical - +day.dayValue;
967
+ return this._findDayPageUpDown(cells, index, day, delta, -arrowsOffset.upDown);
968
+ }
969
+ case "Home": return this._findDayFirst(cells, index, day, 1);
970
+ case "End": {
971
+ const monthInBounds = +day.monthValue + 1 > 12 ? 1 : +day.monthValue + 1;
972
+ const yearInBounds = +day.monthValue + 1 > 12 ? +day.yearValue + 1 : +day.yearValue;
973
+ const firstNextMonth = this._dateAdapter.createDate(yearInBounds, monthInBounds, 1);
974
+ return this._findDayLast(cells, index, firstNextMonth);
975
+ }
976
+ default: return cells[index];
977
+ }
978
+ }
979
+ _isDayOutOfView(date) {
980
+ return date < this._keyboardNavigationDayViewParameters.firstDayInView || date > this._keyboardNavigationDayViewParameters.lastDayInView;
981
+ }
982
+ _findDayArrows(cells, index, date, delta) {
983
+ const newDateValue = this._dateAdapter.toIso8601(this._dateAdapter.addCalendarDays(date, delta));
984
+ if (this._isDayOutOfView(newDateValue)) return cells[index];
985
+ const nextCell = cells.find((e) => this._mapValueToISODate(e.value) === newDateValue);
986
+ if (!nextCell || nextCell.disabled) return this._findDayArrows(cells, index, this._dateAdapter.deserialize(newDateValue), delta);
987
+ return nextCell;
988
+ }
989
+ _findDayPageUpDown(cells, index, day, delta, deltaIfDisabled) {
990
+ const newDateValue = this._dateAdapter.toIso8601(this._dateAdapter.addCalendarDays(day.dateValue, delta));
991
+ if (this._isDayOutOfView(newDateValue)) return cells[index];
992
+ const nextCell = cells.find((e) => this._mapValueToISODate(e.value) === newDateValue);
993
+ if (!nextCell || nextCell.disabled) return this._findDayPageUpDown(cells, index, day, delta + deltaIfDisabled, deltaIfDisabled);
994
+ return nextCell;
995
+ }
996
+ _findDayFirst(cells, index, day, date) {
997
+ const newDateValue = this._dateAdapter.toIso8601(this._dateAdapter.createDate(+day.yearValue, +day.monthValue, date));
998
+ if (this._isDayOutOfView(newDateValue)) return cells[index];
999
+ const nextCell = cells.find((e) => this._mapValueToISODate(e.value) === newDateValue);
1000
+ if (!nextCell || nextCell.disabled) return this._findDayFirst(cells, index, day, date + 1);
1001
+ return nextCell;
1002
+ }
1003
+ _findDayLast(cells, index, firstNextMonth) {
1004
+ const newDateValue = this._dateAdapter.toIso8601(this._dateAdapter.addCalendarDays(firstNextMonth, -1));
1005
+ if (this._isDayOutOfView(newDateValue)) return cells[index];
1006
+ const nextCell = cells.find((e) => this._mapValueToISODate(e.value) === newDateValue);
1007
+ if (!nextCell || nextCell.disabled) return this._findDayLast(cells, index, this._dateAdapter.deserialize(newDateValue));
1008
+ return nextCell;
1009
+ }
1010
+ /**
1011
+ * Gets the index of the element to move to, based on a list of elements (which can be potentially disabled),
1012
+ * the keyboard input and the position of the current element in the list.
1013
+ * In the day view, the `day?: Day` parameter is mandatory for calculation,
1014
+ * while in month and year view it's not due to the fixed amount of rendered cells.
1015
+ */
1016
+ _navigateByKeyboard(evt, index, cells) {
1017
+ const { elementIndexForWideMode, offsetForWideMode, lastElementIndexForWideMode, verticalOffset } = this._calculateParametersForKeyboardNavigation(index, this._calendarView === "year");
1018
+ switch (evt.key) {
1019
+ case "ArrowUp": return this._findNext(cells, index, -verticalOffset);
1020
+ case "ArrowDown": return this._findNext(cells, index, verticalOffset);
1021
+ case "ArrowLeft": return this._findNext(cells, index, -1);
1022
+ case "ArrowRight": return this._findNext(cells, index, 1);
1023
+ case "Home": return this._findFirst(cells, offsetForWideMode);
1024
+ case "PageUp": return this._findFirstOnColumn(cells, elementIndexForWideMode, offsetForWideMode, verticalOffset);
1025
+ case "PageDown": return this._findLastOnColumn(cells, index, lastElementIndexForWideMode, verticalOffset);
1026
+ case "End": return this._findLast(cells, lastElementIndexForWideMode - 1);
1027
+ default: return cells[index];
1028
+ }
1029
+ }
1030
+ /**
1031
+ * Calculates the parameters needed in keyboard navigation in year and month view.
1032
+ * @param index The starting element's index in the cell array.
1033
+ * @param isYearView Whether the displayed `view` is the year one.
1034
+ */
1035
+ _calculateParametersForKeyboardNavigation(index, isYearView) {
1036
+ const elementsPerPage = isYearView ? YEARS_PER_PAGE : MONTHS_PER_PAGE;
1037
+ const offset = Math.trunc(index / elementsPerPage) * elementsPerPage;
1038
+ const indexInView = offset === 0 ? index : index - elementsPerPage;
1039
+ return {
1040
+ verticalOffset: isYearView ? YEARS_PER_ROW : MONTHS_PER_ROW,
1041
+ elementIndexForWideMode: indexInView,
1042
+ offsetForWideMode: index - indexInView,
1043
+ lastElementIndexForWideMode: offset === 0 ? elementsPerPage : elementsPerPage * 2
1044
+ };
1045
+ }
1046
+ /**
1047
+ * Gets the next element of the provided array starting from `index` by adding `delta`.
1048
+ * If the found element is disabled, it continues adding `delta` until it finds an enabled one in the array bounds.
1049
+ */
1050
+ _findNext(days, index, delta) {
1051
+ let nextIndex = index + delta;
1052
+ while (nextIndex < days.length && days[nextIndex]?.disabled) nextIndex += delta;
1053
+ return days[nextIndex] ?? days[index];
1054
+ }
1055
+ /** Find the first enabled element in the provided array. */
1056
+ _findFirst(days, firstOfCurrentMonth) {
1057
+ return !days[firstOfCurrentMonth].disabled ? days[firstOfCurrentMonth] : this._findNext(days, firstOfCurrentMonth, 1);
1058
+ }
1059
+ /** Find the last enabled element in the provided array. */
1060
+ _findLast(days, lastOfCurrentMonth) {
1061
+ return !days[lastOfCurrentMonth].disabled ? days[lastOfCurrentMonth] : this._findNext(days, lastOfCurrentMonth, -1);
1062
+ }
1063
+ /** Find the first enabled element in the same column of the provided array. */
1064
+ _findFirstOnColumn(days, index, offset, verticalOffset) {
1065
+ const nextIndex = index % verticalOffset + offset;
1066
+ return !days[nextIndex].disabled ? days[nextIndex] : this._findNext(days, nextIndex, verticalOffset);
1067
+ }
1068
+ /** Find the last enabled element in the same column of the provided array. */
1069
+ _findLastOnColumn(days, index, offset, verticalOffset) {
1070
+ const nextIndex = index + Math.trunc((offset - index - 1) / verticalOffset) * verticalOffset;
1071
+ return !days[nextIndex].disabled ? days[nextIndex] : this._findNext(days, nextIndex, -verticalOffset);
1072
+ }
1073
+ _resetCalendarViewAndEmitMonthChange(initTransition = false) {
1074
+ this._resetCalendarView(initTransition);
1075
+ this._emitMonthChange();
1076
+ }
1077
+ _resetCalendarView(initTransition = false) {
1078
+ if (this._containingFocus) this._resetFocus = true;
1079
+ this._activeDate = (this.multiple ? this._selected.at(-1) : this._selected) ?? this._dateAdapter.today();
1080
+ this._setChosenYear();
1081
+ this._chosenMonth = void 0;
1082
+ this._init();
1083
+ this._nextCalendarView = this._calendarView = this.view;
1084
+ if (initTransition) this._startTableTransition();
1085
+ }
1086
+ /** Render the view for the day selection. */
1087
+ _renderDayView() {
1088
+ const nextMonthActiveDate = this._wide ? this._dateAdapter.addCalendarMonths(this._activeDate, 1) : void 0;
1089
+ return html`
1090
+ <div class="sbb-calendar__controls">
1091
+ ${this._getArrow("left", () => this._goToDifferentMonth(-1), i18nPreviousMonth[this._language.current], this._previousMonthDisabled())}
1092
+ <div class="sbb-calendar__controls-month">
1093
+ ${this._createLabelForDayView(this._activeDate)}
1094
+ ${this._wide ? this._createLabelForDayView(nextMonthActiveDate) : nothing}
1095
+ <span class="sbb-screen-reader-only" role="status">
1096
+ ${this._createAriaLabelForDayView(this._activeDate, nextMonthActiveDate)}
1097
+ </span>
1098
+ </div>
1099
+ ${this._getArrow("right", () => this._goToDifferentMonth(1), i18nNextMonth[this._language.current], this._nextMonthDisabled())}
1100
+ </div>
1101
+ <div class="sbb-calendar__table-overflow-break">
1102
+ <div class="sbb-calendar__table-container sbb-calendar__table-day-view">
1103
+ ${this.orientation === "horizontal" ? html`
1104
+ ${this._createDayTable(this._weeks, this._weekNumbers)}
1105
+ ${this._wide ? this._createDayTable(this._nextMonthWeeks, this._nextMonthWeekNumbers, true) : nothing}
1106
+ ` : html`
1107
+ ${this._createDayTableVertical(this._weeks, this._weekNumbers)}
1108
+ ${this._wide ? this._createDayTableVertical(this._nextMonthWeeks, this._nextMonthWeekNumbers, nextMonthActiveDate) : nothing}
1109
+ `}
1110
+ </div>
1111
+ </div>
1112
+ `;
1113
+ }
1114
+ /** Creates the label with the month for the daily view. */
1115
+ _createLabelForDayView(d) {
1116
+ const monthLabel = `${this._monthNames[this._dateAdapter.getMonth(d) - 1]} ${this._dateAdapter.getYear(d)}`;
1117
+ return html`
1118
+ <button
1119
+ type="button"
1120
+ class="sbb-calendar__date-selection sbb-calendar__controls-change-date"
1121
+ aria-label="${i18nYearMonthSelection[this._language.current]} ${monthLabel}"
1122
+ @click=${() => {
1123
+ this._resetFocus = true;
1124
+ this._nextCalendarView = "year";
1125
+ this._startTableTransition();
1126
+ }}
1127
+ >
1128
+ ${monthLabel}
1129
+ <sbb-icon name="chevron-small-down-small"></sbb-icon>
1130
+ </button>
1131
+ `;
1132
+ }
1133
+ /** Creates the aria-label for the daily view. */
1134
+ _createAriaLabelForDayView(...dates) {
1135
+ let monthLabel = "";
1136
+ for (const d of dates) if (d) monthLabel += `${this._monthNames[this._dateAdapter.getMonth(d) - 1]} ${this._dateAdapter.getYear(d)} `;
1137
+ return monthLabel;
1138
+ }
1139
+ /** Creates the calendar table for the daily view. */
1140
+ _createDayTable(weeks, weekNumbers, isWideNextMonth = false) {
1141
+ const weeksForSelectMultipleWeekNumbers = (this._wide ? [...this._weeks, ...this._nextMonthWeeks] : isWideNextMonth ? this._nextMonthWeeks : this._weeks).flat();
1142
+ const weeksForSelectMultipleWeekDays = (isWideNextMonth ? this._nextMonthWeeks : this._weeks).flat();
1143
+ return html`
1144
+ <table
1145
+ class="sbb-calendar__table"
1146
+ @focusout=${(event) => this._handleTableBlur(event.relatedTarget)}
1147
+ @animationend=${(e) => this._tableAnimationEnd(e)}
1148
+ >
1149
+ <thead class="sbb-calendar__table-header">
1150
+ <tr>
1151
+ ${this.weekNumbers ? html`<th class="sbb-calendar__table-header-cell"></th>` : nothing}
1152
+ ${this._weekdays.map((weekDay, index) => html`
1153
+ <th class="sbb-calendar__table-header-cell">
1154
+ ${this.multiple ? html`
1155
+ <sbb-calendar-weekday
1156
+ .value=${weekDay}
1157
+ @click=${() => {
1158
+ const days = weeksForSelectMultipleWeekDays.filter((day) => day.weekDayValue === (index + 1) % 7);
1159
+ this._selectMultipleDates(days);
1160
+ }}
1161
+ ></sbb-calendar-weekday>
1162
+ ` : html`
1163
+ <span class="sbb-screen-reader-only">${weekDay.long}</span>
1164
+ <span aria-hidden="true">${weekDay.narrow}</span>
1165
+ `}
1166
+ </th>
1167
+ `)}
1168
+ </tr>
1169
+ </thead>
1170
+ <tbody class="sbb-calendar__table-body">
1171
+ ${weeks.map((week, rowIndex) => {
1172
+ const firstRowOffset = DAYS_PER_ROW - week.length;
1173
+ if (rowIndex === 0 && firstRowOffset) return html`
1174
+ <tr>
1175
+ ${this.weekNumbers ? html`
1176
+ <td class="sbb-calendar__table-header-cell-vertical">
1177
+ ${this.multiple ? html`
1178
+ <sbb-calendar-weeknumber
1179
+ .value=${weekNumbers[0]}
1180
+ @click=${() => {
1181
+ const days = weeksForSelectMultipleWeekNumbers.filter((day) => day.weekValue === weekNumbers[0]);
1182
+ this._selectMultipleDates(days);
1183
+ }}
1184
+ ></sbb-calendar-weeknumber>
1185
+ ` : html`
1186
+ <span class="sbb-screen-reader-only"
1187
+ >${`${i18nCalendarWeekNumber[this._language.current]} ${weekNumbers[0]}`}</span
1188
+ >
1189
+ <span aria-hidden="true">${weekNumbers[0]}</span>
1190
+ `}
1191
+ </td>
1192
+ ` : nothing}
1193
+ ${[...Array(firstRowOffset).keys()].map(() => html`<td class="sbb-calendar__table-data"></td>`)}
1194
+ ${this._createDayCells(week)}
1195
+ </tr>
1196
+ `;
1197
+ return html`
1198
+ <tr>
1199
+ ${this.weekNumbers ? html`
1200
+ <td class="sbb-calendar__table-header-cell-vertical">
1201
+ ${this.multiple ? html`
1202
+ <sbb-calendar-weeknumber
1203
+ .value=${weekNumbers[rowIndex]}
1204
+ @click=${() => {
1205
+ const days = weeksForSelectMultipleWeekNumbers.filter((day) => day.weekValue === weekNumbers[rowIndex]);
1206
+ this._selectMultipleDates(days);
1207
+ }}
1208
+ ></sbb-calendar-weeknumber>
1209
+ ` : html`
1210
+ <span class="sbb-screen-reader-only"
1211
+ >${`${i18nCalendarWeekNumber[this._language.current]} ${weekNumbers[rowIndex]}`}</span
1212
+ >
1213
+ <span aria-hidden="true">${weekNumbers[rowIndex]}</span>
1214
+ `}
1215
+ </td>
1216
+ ` : nothing}
1217
+ ${this._createDayCells(week)}
1218
+ </tr>
1219
+ `;
1220
+ })}
1221
+ </tbody>
1222
+ </table>
1223
+ `;
1224
+ }
1225
+ /** Creates the table in orientation='vertical'. */
1226
+ _createDayTableVertical(weeks, weekNumbers, nextMonthActiveDate) {
1227
+ const weekOffset = this._dateAdapter.getFirstWeekOffset(nextMonthActiveDate ?? this._activeDate);
1228
+ const weeksForSelectMultipleWeekNumbers = (this._wide ? [...this._weeks, ...this._nextMonthWeeks] : nextMonthActiveDate ? this._nextMonthWeeks : this._weeks).flat();
1229
+ return html`
1230
+ <table
1231
+ class="sbb-calendar__table"
1232
+ @focusout=${(event) => this._handleTableBlur(event.relatedTarget)}
1233
+ @animationend=${(e) => this._tableAnimationEnd(e)}
1234
+ >
1235
+ ${this.weekNumbers ? html`
1236
+ <thead class="sbb-calendar__table-header">
1237
+ <tr>
1238
+ ${nextMonthActiveDate ? nothing : html`<th class="sbb-calendar__table-data"></th>`}
1239
+ ${weekNumbers.map((weekNumber) => html`
1240
+ <th class="sbb-calendar__table-header-cell">
1241
+ ${this.multiple ? html`
1242
+ <sbb-calendar-weeknumber
1243
+ .value=${weekNumber}
1244
+ @click=${() => {
1245
+ const days = weeksForSelectMultipleWeekNumbers.filter((day) => day.weekValue === weekNumber);
1246
+ this._selectMultipleDates(days);
1247
+ }}
1248
+ ></sbb-calendar-weeknumber>
1249
+ ` : html`
1250
+ <span class="sbb-screen-reader-only"
1251
+ >${`${i18nCalendarWeekNumber[this._language.current]} ${weekNumber}`}</span
1252
+ >
1253
+ <span aria-hidden="true">${weekNumber}</span>
1254
+ `}
1255
+ </th>
1256
+ `)}
1257
+ </tr>
1258
+ </thead>
1259
+ ` : nothing}
1260
+ <tbody class="sbb-calendar__table-body">
1261
+ ${weeks.map((week, rowIndex) => {
1262
+ const weekday = this._weekdays[rowIndex];
1263
+ const selectableDays = this._wide ? [...week, ...this._nextMonthWeeks[rowIndex]] : week;
1264
+ return html`
1265
+ <tr>
1266
+ ${nextMonthActiveDate ? nothing : html`
1267
+ <td class="sbb-calendar__table-header-cell-vertical">
1268
+ ${this.multiple ? html`
1269
+ <sbb-calendar-weekday
1270
+ .value=${weekday}
1271
+ @click=${() => this._selectMultipleDates(selectableDays)}
1272
+ >
1273
+ ${weekday.narrow}
1274
+ </sbb-calendar-weekday>
1275
+ ` : html`
1276
+ <span class="sbb-screen-reader-only">${weekday.long}</span>
1277
+ <span aria-hidden="true">${weekday.narrow}</span>
1278
+ `}
1279
+ </td>
1280
+ `}
1281
+ ${rowIndex < weekOffset ? html`<td class="sbb-calendar__table-data"></td>` : nothing}
1282
+ ${this._createDayCells(week)}
1283
+ </tr>
1284
+ `;
1285
+ })}
1286
+ </tbody>
1287
+ </table>
1288
+ `;
1289
+ }
1290
+ /** Creates the cells for the daily view. */
1291
+ _createDayCells(week) {
1292
+ return week.map((day) => {
1293
+ return html`
1294
+ <td class="sbb-calendar__table-data sbb-calendar__day-cell">
1295
+ <slot name=${day.value}>
1296
+ <sbb-calendar-day slot=${day.value}></sbb-calendar-day>
1297
+ </slot>
1298
+ </td>
1299
+ `;
1300
+ });
1301
+ }
1302
+ /** Render the view for the month selection. */
1303
+ _renderMonthView() {
1304
+ return html`
1305
+ <div class="sbb-calendar__controls">
1306
+ ${this._getArrow("left", () => this._goToDifferentYear(-1), i18nPreviousYear[this._language.current], this._previousYearDisabled())}
1307
+ <div class="sbb-calendar__controls-month">${this._createLabelForMonthView()}</div>
1308
+ ${this._getArrow("right", () => this._goToDifferentYear(1), i18nNextYear[this._language.current], this._nextYearDisabled())}
1309
+ </div>
1310
+ <div class="sbb-calendar__table-overflow-break">
1311
+ <div class="sbb-calendar__table-container sbb-calendar__table-month-view">
1312
+ ${this._createMonthTable(this._months, this._chosenYear)}
1313
+ ${this._wide ? this._createMonthTable(this._months, this._chosenYear + 1) : nothing}
1314
+ </div>
1315
+ </div>
1316
+ `;
1317
+ }
1318
+ /** Creates the label with the year for the monthly view. */
1319
+ _createLabelForMonthView() {
1320
+ return html`<button
1321
+ type="button"
1322
+ id="sbb-calendar__month-selection"
1323
+ class="sbb-calendar__controls-change-date"
1324
+ aria-label=${`${i18nCalendarDateSelection[this._language.current]} ${this._chosenYear}`}
1325
+ @click=${() => this._resetCalendarViewAndEmitMonthChange(true)}
1326
+ >
1327
+ ${this._chosenYear} ${this._wide ? ` - ${this._chosenYear + 1}` : nothing}
1328
+ <sbb-icon name="chevron-small-up-small"></sbb-icon>
1329
+ </button>
1330
+ <span class="sbb-screen-reader-only" role="status"> ${this._chosenYear} </span>`;
1331
+ }
1332
+ /** Creates the table for the month selection view. */
1333
+ _createMonthTable(months, year) {
1334
+ return html`
1335
+ <table
1336
+ class="sbb-calendar__table"
1337
+ @animationend=${(e) => this._tableAnimationEnd(e)}
1338
+ >
1339
+ ${this._wide ? html`<thead class="sbb-calendar__table-header" aria-hidden="true">
1340
+ <tr>
1341
+ <th class="sbb-calendar__table-header-cell" colspan=${MONTHS_PER_ROW}>${year}</th>
1342
+ </tr>
1343
+ </thead>` : nothing}
1344
+ <tbody class="sbb-calendar__table-body">
1345
+ ${months.map((row) => html`
1346
+ <tr>
1347
+ ${row.map((month) => {
1348
+ return html`
1349
+ <td class="sbb-calendar__table-data">
1350
+ <sbb-calendar-month
1351
+ .value="${year}-${month.value}"
1352
+ @click=${() => this._onMonthSelection(month.monthValue, year)}
1353
+ @keydown=${(evt) => this._handleKeyboardEvent(evt)}
1354
+ >
1355
+ </sbb-calendar-month>
1356
+ </td>
1357
+ `;
1358
+ })}
1359
+ </tr>
1360
+ `)}
1361
+ </tbody>
1362
+ </table>
1363
+ `;
1364
+ }
1365
+ /** Select the month and change the view to day selection. */
1366
+ _onMonthSelection(month, year) {
1367
+ this._chosenMonth = month;
1368
+ this._nextCalendarView = "day";
1369
+ this._init(this._dateAdapter.createDate(year, this._chosenMonth, this._dateAdapter.getDate(this._activeDate)));
1370
+ this._startTableTransition();
1371
+ this._emitMonthChange();
1372
+ }
1373
+ /** Render the view for the year selection. */
1374
+ _renderYearView() {
1375
+ return html`
1376
+ <div class="sbb-calendar__controls">
1377
+ ${this._getArrow("left", () => this._goToDifferentYearRange(-YEARS_PER_PAGE), i18nPreviousYearRange(YEARS_PER_PAGE)[this._language.current], this._previousYearRangeDisabled())}
1378
+ <div class="sbb-calendar__controls-month">${this._createLabelForYearView()}</div>
1379
+ ${this._getArrow("right", () => this._goToDifferentYearRange(YEARS_PER_PAGE), i18nNextYearRange(YEARS_PER_PAGE)[this._language.current], this._nextYearRangeDisabled())}
1380
+ </div>
1381
+ <div class="sbb-calendar__table-overflow-break">
1382
+ <div class="sbb-calendar__table-container sbb-calendar__table-year-view">
1383
+ ${this._createYearTable(this._years)}
1384
+ ${this._wide ? this._createYearTable(this._nextMonthYears, true) : nothing}
1385
+ </div>
1386
+ </div>
1387
+ `;
1388
+ }
1389
+ /** Creates the button arrow for all the views. */
1390
+ _getArrow(direction, click, ariaLabel, disabled) {
1391
+ return html`<sbb-secondary-button
1392
+ size="m"
1393
+ icon-name="chevron-small-${direction}-small"
1394
+ aria-label=${ariaLabel}
1395
+ @click=${click}
1396
+ ?disabled=${disabled}
1397
+ id="sbb-calendar__controls-${direction === "left" ? "previous" : "next"}"
1398
+ ></sbb-secondary-button>`;
1399
+ }
1400
+ /** Creates the label with the year range for the yearly view. */
1401
+ _createLabelForYearView() {
1402
+ const firstYear = this._years.flat()[0];
1403
+ const lastYearArray = (this._wide ? this._nextMonthYears : this._years).flat();
1404
+ const yearLabel = `${firstYear} - ${lastYearArray[lastYearArray.length - 1]}`;
1405
+ return html`
1406
+ <button
1407
+ type="button"
1408
+ id="sbb-calendar__year-selection"
1409
+ class="sbb-calendar__controls-change-date"
1410
+ aria-label="${i18nCalendarDateSelection[this._language.current]} ${yearLabel}"
1411
+ @click=${() => this._resetCalendarViewAndEmitMonthChange(true)}
1412
+ >
1413
+ ${yearLabel}
1414
+ <sbb-icon name="chevron-small-up-small"></sbb-icon>
1415
+ </button>
1416
+ <span class="sbb-screen-reader-only" role="status"> ${yearLabel} </span>
1417
+ `;
1418
+ }
1419
+ /** Creates the table for the year selection view. */
1420
+ _createYearTable(years, shiftRight = false) {
1421
+ return html` <table
1422
+ class="sbb-calendar__table"
1423
+ @animationend=${(e) => this._tableAnimationEnd(e)}
1424
+ >
1425
+ <tbody class="sbb-calendar__table-body">
1426
+ ${years.map((row) => html` <tr>
1427
+ ${row.map((year) => {
1428
+ return html`
1429
+ <td class="sbb-calendar__table-data">
1430
+ <sbb-calendar-year
1431
+ .value=${String(year)}
1432
+ @keydown=${(evt) => this._handleKeyboardEvent(evt)}
1433
+ @click=${() => this._onYearSelection(year, shiftRight)}
1434
+ >
1435
+ </sbb-calendar-year>
1436
+ </td>
1437
+ `;
1438
+ })}
1439
+ </tr>`)}
1440
+ </tbody>
1441
+ </table>`;
1442
+ }
1443
+ /** Select the year and change the view to month selection. */
1444
+ _onYearSelection(year, rightSide) {
1445
+ this._chosenYear = rightSide ? year - 1 : year;
1446
+ this._nextCalendarView = "month";
1447
+ this._assignActiveDate(this._dateAdapter.createDate(this._chosenYear, this._dateAdapter.getMonth(this._activeDate), this._dateAdapter.getDate(this._activeDate)));
1448
+ this._startTableTransition();
1449
+ }
1450
+ _getView() {
1451
+ if (isServer || this.hydrationRequired) return html`${nothing}`;
1452
+ switch (this._calendarView) {
1453
+ case "year": return this._renderYearView();
1454
+ case "month": return this._renderMonthView();
1455
+ default: return this._renderDayView();
1456
+ }
1457
+ }
1458
+ _tableAnimationEnd(event) {
1459
+ const table = event.target;
1460
+ if (event.animationName === "hide") {
1461
+ table.classList.remove("sbb-calendar__table-hide");
1462
+ if (this._containingFocus) this._resetFocus = true;
1463
+ this._calendarView = this._nextCalendarView;
1464
+ } else if (event.animationName === "show") this.internals.states.delete("transition");
1465
+ }
1466
+ _startTableTransition() {
1467
+ this.internals.states.add("transition");
1468
+ this.shadowRoot?.querySelectorAll("table")?.forEach((e) => e.classList.toggle("sbb-calendar__table-hide"));
1469
+ }
1470
+ render() {
1471
+ return html`<div class="sbb-calendar__wrapper">${this._getView()}</div>`;
1472
+ }
1473
+ };
1474
+ })();
1475
+ //#endregion
1476
+ export { SbbDateSelectedEvent as n, SbbMonthChangeEvent as r, SbbCalendarElement as t };
1477
+
1478
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FsZW5kYXIuY29tcG9uZW50LURuQzhaa2RrLmpzIiwibmFtZXMiOltdLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9lbGVtZW50cy9jYWxlbmRhci9jYWxlbmRhci9jYWxlbmRhci5zY3NzP2lubGluZSIsIi4uLy4uLy4uL3NyYy9lbGVtZW50cy9jYWxlbmRhci9jYWxlbmRhci9jYWxlbmRhci5jb21wb25lbnQudHMiXSwic291cmNlc0NvbnRlbnQiOlsiQHVzZSAnLi4vLi4vY29yZS9zdHlsZXMnIGFzIHNiYjtcblxuOmhvc3Qge1xuICBkaXNwbGF5OiBibG9jaztcblxuICAvLyBXZSBhZGQgd2lkdGggZGVmaW5pdGlvbiB0byBob3N0LCB0byBtYWtlIG92ZXJ3cml0aW5nIGVhc3kgZm9yIGNvbnN1bWVycy5cbiAgd2lkdGg6IG1heC1jb250ZW50O1xuXG4gIC8vIFNldCB0aGUgbGluZS1oZWlnaHQgZm9yIGFkamFjZW50IGVsZW1lbnRzIGluIG9yZGVyIHRvIHByZXZlbnQgZnJvbSBpbmZsdWVuY2Ugb2YgYSBjb25zdW1lci1zZXQgbGluZS1oZWlnaHQuXG4gIGxpbmUtaGVpZ2h0OiB2YXIoLS1zYmItdHlwby1saW5lLWhlaWdodC10ZXh0KTtcblxuICAtLXNiYi1jYWxlbmRhci1jZWxsLXNpemU6ICN7c2JiLnB4LXRvLXJlbS1idWlsZCg0NCl9O1xuXG4gIC8vIE1hdGNoIEZpZ21hIGRlc2lnblxuICAtLXNiYi1jYWxlbmRhci1jZWxsLWJvcmRlci1yYWRpdXM6IGNhbGMoXG4gICAgdmFyKC0tc2JiLWJvcmRlci1yYWRpdXMtNHgpICsgdmFyKC0tc2JiLWNhbGVuZGFyLWNlbGwtYm9yZGVyLXdpZHRoKVxuICApO1xuICAtLXNiYi1jYWxlbmRhci1jZWxsLXRyYW5zaXRpb24tZHVyYXRpb246IHZhcihcbiAgICAtLXNiYi1kaXNhYmxlLWFuaW1hdGlvbi1kdXJhdGlvbixcbiAgICB2YXIoLS1zYmItYW5pbWF0aW9uLWR1cmF0aW9uLTJ4KVxuICApO1xuXG4gIEBpbmNsdWRlIHNiYi5tcSgkZnJvbTogc21hbGwpIHtcbiAgICAtLXNiYi1jYWxlbmRhci1jb250cm9sLXZpZXctY2hhbmdlLWhlaWdodDogI3tzYmIucHgtdG8tcmVtLWJ1aWxkKDQ4KX07XG4gIH1cbn1cblxuOmhvc3QoOnN0YXRlKGVuaGFuY2VkKSkge1xuICAtLXNiYi1jYWxlbmRhci1jZWxsLXBhZGRpbmctYmxvY2stZW5kOiB2YXIoLS1zYmItc3BhY2luZy1maXhlZC0zeCk7XG59XG5cbi5zYmItY2FsZW5kYXJfX3dyYXBwZXIge1xuICB3aWR0aDogMTAwJTtcbiAgZGlzcGxheTogYmxvY2s7XG4gIHRyYW5zaXRpb24tZHVyYXRpb246IHZhcigtLXNiYi1jYWxlbmRhci1jZWxsLXRyYW5zaXRpb24tZHVyYXRpb24pO1xufVxuXG4uc2JiLWNhbGVuZGFyX19jb250cm9scyB7XG4gIHdpZHRoOiAxMDAlO1xuICBkaXNwbGF5OiBpbmxpbmUtZmxleDtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgZ2FwOiB2YXIoLS1zYmItY2FsZW5kYXItY29udHJvbC1nYXApO1xuICBtYXJnaW4tYmxvY2stZW5kOiB2YXIoLS1zYmItY2FsZW5kYXItY29udHJvbC1tYXJnaW4tYmxvY2stZW5kKTtcbn1cblxuLnNiYi1jYWxlbmRhcl9fY29udHJvbHMtbW9udGgge1xuICB3aWR0aDogMTAwJTtcbiAgZGlzcGxheTogZmxleDtcbiAgZ2FwOiB2YXIoLS1zYmItY2FsZW5kYXItdGFibGVzLWdhcCk7XG59XG5cbiNzYmItY2FsZW5kYXJfX2NvbnRyb2xzLXByZXZpb3VzLFxuI3NiYi1jYWxlbmRhcl9fY29udHJvbHMtbmV4dCB7XG4gIC13ZWJraXQtdGFwLWhpZ2hsaWdodC1jb2xvcjogdHJhbnNwYXJlbnQ7XG59XG5cbi5zYmItY2FsZW5kYXJfX2NvbnRyb2xzLWNoYW5nZS1kYXRlIHtcbiAgZGlzcGxheTogZmxleDtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgbWFyZ2luOiBhdXRvO1xuICBoZWlnaHQ6IHZhcigtLXNiYi1jYWxlbmRhci1jb250cm9sLXZpZXctY2hhbmdlLWhlaWdodCk7XG4gIGZvbnQtc2l6ZTogdmFyKC0tc2JiLXRleHQtZm9udC1zaXplLXMpO1xuICBsZXR0ZXItc3BhY2luZzogdmFyKC0tc2JiLXR5cG8tbGV0dGVyLXNwYWNpbmctdGV4dCk7XG4gIGxpbmUtaGVpZ2h0OiB2YXIoLS1zYmItdHlwby1sZXR0ZXItc3BhY2luZy10ZXh0KTtcbiAgdGV4dC10cmFuc2Zvcm06IGNhcGl0YWxpemU7XG4gIGN1cnNvcjogdmFyKC0tc2JiLWN1cnNvci1wb2ludGVyKTtcbiAgcGFkZGluZy1pbmxpbmU6IHZhcigtLXNiYi1jYWxlbmRhci1jb250cm9sLXZpZXctY2hhbmdlLXBhZGRpbmctaW5saW5lKTtcbiAgYm9yZGVyLXJhZGl1czogdmFyKC0tc2JiLWJvcmRlci1yYWRpdXMtaW5maW5pdHkpO1xuICBiYWNrZ3JvdW5kLWNvbG9yOiB2YXIoLS1zYmItY2FsZW5kYXItY29udHJvbC12aWV3LWNoYW5nZS1iYWNrZ3JvdW5kKTtcbiAgY29sb3I6IHZhcigtLXNiYi1jYWxlbmRhci1jb250cm9sLXZpZXctY2hhbmdlLWNvbG9yKTtcbiAgdHJhbnNpdGlvbi1kdXJhdGlvbjogdmFyKC0tc2JiLWNhbGVuZGFyLWNlbGwtdHJhbnNpdGlvbi1kdXJhdGlvbik7XG4gIHRyYW5zaXRpb24tdGltaW5nLWZ1bmN0aW9uOiB2YXIoLS1zYmItY2FsZW5kYXItY2VsbC10cmFuc2l0aW9uLWVhc2luZy1mdW5jdGlvbik7XG4gIHRyYW5zaXRpb24tcHJvcGVydHk6IGJhY2tncm91bmQtY29sb3IsIHBhZGRpbmctYmxvY2stZW5kO1xuXG4gICY6ZGlzYWJsZWQge1xuICAgIC0tc2JiLWNhbGVuZGFyLWNvbnRyb2wtdmlldy1jaGFuZ2UtYmFja2dyb3VuZDogbGlnaHQtZGFyayhcbiAgICAgIHZhcigtLXNiYi1jb2xvci1taWxrKSxcbiAgICAgIHZhcigtLXNiYi1jb2xvci1hbnRocmFjaXRlKVxuICAgICk7XG4gICAgLS1zYmItY2FsZW5kYXItY29udHJvbC12aWV3LWNoYW5nZS1jb2xvcjogbGlnaHQtZGFyayhcbiAgICAgIHZhcigtLXNiYi1jb2xvci1ncmFuaXRlKSxcbiAgICAgIHZhcigtLXNiYi1jb2xvci1hbHVtaW5pdW0pXG4gICAgKTtcblxuICAgIGN1cnNvcjogdW5zZXQ7XG4gIH1cblxuICAmOmZvY3VzLXZpc2libGUge1xuICAgIEBpbmNsdWRlIHNiYi5mb2N1cy1vdXRsaW5lO1xuXG4gICAgb3V0bGluZS1vZmZzZXQ6IHZhcigtLXNiYi1zcGFjaW5nLWZpeGVkLTF4KTtcbiAgfVxuXG4gIEBpbmNsdWRlIHNiYi5ob3Zlci1tcSB7XG4gICAgJjpub3QoOmFjdGl2ZSwgOmRpc2FibGVkKTpob3ZlciB7XG4gICAgICBwYWRkaW5nLWJsb2NrLWVuZDogdmFyKC0tc2JiLWNhbGVuZGFyLWNlbGwtaG92ZXItc2hpZnQpO1xuICAgIH1cbiAgfVxuXG4gICY6bm90KDpkaXNhYmxlZCk6YWN0aXZlIHtcbiAgICAtLXNiYi1jYWxlbmRhci1jb250cm9sLXZpZXctY2hhbmdlLWJhY2tncm91bmQ6IHZhcigtLXNiYi1iYWNrZ3JvdW5kLWNvbG9yLTMpO1xuICB9XG59XG5cbi5zYmItY2FsZW5kYXJfX3RhYmxlLW1vbnRoLXZpZXcsXG4uc2JiLWNhbGVuZGFyX190YWJsZS15ZWFyLXZpZXcge1xuICAtLXNiYi1jYWxlbmRhci10YWJsZS1jb2x1bW4tc3BhY2VzOiA2O1xufVxuXG4uc2JiLWNhbGVuZGFyX190YWJsZS1vdmVyZmxvdy1icmVhayB7XG4gIC8vIFdlIGhhdmUgdG8gY3V0IHRoZSBuZWdhdGl2ZSBtYXJnaW4gd2hpY2ggaXMgYnVpbHQgYnkgdGhlIGNvbnRhaW5pbmcgc2JiLWNhbGVuZGFyX190YWJsZS1jb250YWluZXIuXG4gIC8vIE92ZXJmbG93OiBoaWRkZW4gd291bGQgY3V0IHRoZSBmb2N1cyBvdXRsaW5lLiBUaGVyZWZvcmUgd2UgdGFrZSBgY29udGFpbmAgaGVyZS5cbiAgY29udGFpbjogbGF5b3V0O1xufVxuXG4uc2JiLWNhbGVuZGFyX190YWJsZS1jb250YWluZXIge1xuICBkaXNwbGF5OiBmbGV4O1xuICBnYXA6IHZhcigtLXNiYi1jYWxlbmRhci10YWJsZXMtZ2FwKTtcbiAgbWFyZ2luLWlubGluZTogdmFyKC0tc2JiLWNhbGVuZGFyLW1hcmdpbik7XG5cbiAgLy8gVGhlIHBhZGRpbmcgb2YgdGhlIGZpcnN0IGFuZCBsYXN0IGNvbHVtbiBzaG91bGQgbm90IGJlIHZpc2libGUgaWYgY2FsZW5kYXIgaXMgc3RyZXRjaGVkLlxuICAvLyBUaGVyZWZvcmUgd2UgbmVlZCBhIG5lZ2F0aXZlIGlubGluZSBtYXJnaW4uXG4gIC8vIEFzIHdlIGRvbid0IHdhbnQgdG8gc3F1ZWV6ZSwgdGhlIG1hcmdpbiBzaG91bGQgbmV2ZXIgYmUgZ3JlYXRlciB0aGFuIHplcm8uXG5cbiAgLy8gTWluIHdpZHRoIGlzIGVxdWFscyB0byB0aGUgbm9ybWFsIHdpZHRoIG9mIHRoZSBjYWxlbmRhclxuICAtLXNiYi1jYWxlbmRhci1taW4td2lkdGg6IGNhbGMoNyAqIHZhcigtLXNiYi1jYWxlbmRhci1jZWxsLXNpemUpKTtcblxuICAvLyBUaGUgb3ZlcmZsb3cgdmFyaWFibGUgaXMgZXF1YWxzIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIGFjdHVhbCB3aWR0aCBhbmQgdGhlIG1pbiB3aWR0aC5cbiAgLS1zYmItY2FsZW5kYXItb3ZlcmZsb3c6IGNhbGMoMTAwJSAtIHZhcigtLXNiYi1jYWxlbmRhci1taW4td2lkdGgpKTtcblxuICAvLyBUaGUgc3RhcnQgb2Zmc2V0IGlzIG5lZ2F0aXZlIG1hcmdpbiB3aGljaCBzaG91bGQgb3ZlcmxhcCB0aGUgcGFyZW50IGNvbnRhaW5lci4gU2hvdWxkIG5ldmVyIGJlIGEgcG9zaXRpdmUgdmFsdWUuXG4gIC0tc2JiLWNhbGVuZGFyLXN0YXJ0LW9mZnNldDogbWluKFxuICAgIDBweCxcbiAgICAtMSAqICh2YXIoLS1zYmItY2FsZW5kYXItb3ZlcmZsb3cpIC8gdmFyKC0tc2JiLWNhbGVuZGFyLXRhYmxlLWNvbHVtbi1zcGFjZXMpKVxuICApO1xuICAtLXNiYi1jYWxlbmRhci1tYXJnaW46IHZhcigtLXNiYi1jYWxlbmRhci1zdGFydC1vZmZzZXQpO1xuXG4gIDpob3N0KDpzdGF0ZSh3aWRlKSkgJiB7XG4gICAgLS1zYmItY2FsZW5kYXItbWluLXdpZHRoOiBjYWxjKFxuICAgICAgMiAqIDcgKiB2YXIoLS1zYmItY2FsZW5kYXItY2VsbC1zaXplKSArIHZhcigtLXNiYi1jYWxlbmRhci10YWJsZXMtZ2FwKVxuICAgICk7XG4gICAgLS1zYmItY2FsZW5kYXItbWFyZ2luOiBjYWxjKDAuNSAqIHZhcigtLXNiYi1jYWxlbmRhci1zdGFydC1vZmZzZXQpKTtcbiAgfVxuXG4gIDpob3N0KFtvcmllbnRhdGlvbj0naG9yaXpvbnRhbCddW3dlZWstbnVtYmVyc10pICYge1xuICAgIC0tc2JiLWNhbGVuZGFyLW1pbi13aWR0aDogY2FsYyg4ICogdmFyKC0tc2JiLWNhbGVuZGFyLWNlbGwtc2l6ZSkpO1xuICB9XG5cbiAgOmhvc3QoW29yaWVudGF0aW9uPSdob3Jpem9udGFsJ11bd2Vlay1udW1iZXJzXTpzdGF0ZSh3aWRlKSkgJiB7XG4gICAgLS1zYmItY2FsZW5kYXItbWluLXdpZHRoOiBjYWxjKFxuICAgICAgMiAqIDggKiB2YXIoLS1zYmItY2FsZW5kYXItY2VsbC1zaXplKSArIHZhcigtLXNiYi1jYWxlbmRhci10YWJsZXMtZ2FwKVxuICAgICk7XG4gIH1cblxuICAvLyBUaGUgY29udGFpbmVyJ3MgbWluLXdpZHRoIGlzIHNldCBpbiB2ZXJ0aWNhbCBtb2RlO1xuICAvLyB0aGUgdmFsdWUgYGNhbGMoNyAqIHZhcigtLXNiYi1jYWxlbmRhci1jZWxsLXNpemUpKWAgaXMgZmluZVxuICAvLyBjb25zaWRlcmluZyB0aGF0IHRoZSBtYXhpbXVtIG51bWJlciBvZiB3ZWVrcyBpbiBhIG1vbnRoIGlzIDYsIHBsdXMgMSBmb3IgdGhlIGhlYWRlciBhdCB0aGUgdGFibGUncyBsZWZ0IHNpZGUuXG4gIDpob3N0KFtvcmllbnRhdGlvbj0ndmVydGljYWwnXSkgJiB7XG4gICAgbWluLXdpZHRoOiB2YXIoLS1zYmItY2FsZW5kYXItbWluLXdpZHRoKTtcblxuICAgIC8vIFRoZSB2YXJpYWJsZSB0aGF0IGRlZmluZXMgdGhlIG1hcmdpbiBpcyBzZXQgdG8gMCB0byBjb3JyZWN0bHkgZGlzcGxheSB0aGUgdGFibGUgaWYgY29uc3VtZXJzIHNldCBhIGN1c3RvbSB3aWR0aC5cbiAgICAtLXNiYi1jYWxlbmRhci1zdGFydC1vZmZzZXQ6IDA7XG4gIH1cblxuICAvLyBUaGUgbWluLXdpZHRoIGluIHdpZGUgaXMgY2FsY3VsYXRlZCBhcyAobWF4IG51bWJlciBvZiB3ZWVrcyBpbiBhIG1vbnRoKSAqIChkaXNwbGF5ZWQgbW9udGhzKSArIChoZWFkZXIgY29sdW1uKSA9IDYgKiAyICsgMSA9IDEzLlxuICA6aG9zdChbb3JpZW50YXRpb249J3ZlcnRpY2FsJ106c3RhdGUod2lkZSkpICYge1xuICAgIC0tc2JiLWNhbGVuZGFyLW1pbi13aWR0aDogY2FsYyhcbiAgICAgIDEzICogdmFyKC0tc2JiLWNhbGVuZGFyLWNlbGwtc2l6ZSkgKyB2YXIoLS1zYmItY2FsZW5kYXItdGFibGVzLWdhcClcbiAgICApO1xuICB9XG59XG5cbi5zYmItY2FsZW5kYXJfX3RhYmxlIHtcbiAgd2lkdGg6IDEwMCU7XG4gIGJvcmRlci1jb2xsYXBzZTogY29sbGFwc2U7XG4gIGhlaWdodDogbWF4LWNvbnRlbnQ7XG5cbiAgYW5pbWF0aW9uOiB7XG4gICAgbmFtZTogc2hvdztcbiAgICBkdXJhdGlvbjogdmFyKC0tc2JiLWNhbGVuZGFyLXRhYmxlLWFuaW1hdGlvbi1kdXJhdGlvbik7XG4gIH1cblxuICAmLnNiYi1jYWxlbmRhcl9fdGFibGUtaGlkZSB7XG4gICAgLS1zYmItY2FsZW5kYXItY2VsbC10cmFuc2l0aW9uLWR1cmF0aW9uOiAwbXM7XG5cbiAgICBhbmltYXRpb246IHtcbiAgICAgIG5hbWU6IGhpZGU7XG4gICAgICBkdXJhdGlvbjogdmFyKC0tc2JiLWNhbGVuZGFyLXRhYmxlLWFuaW1hdGlvbi1kdXJhdGlvbik7XG4gICAgfVxuICB9XG5cbiAgOmhvc3QoOm5vdCg6c3RhdGUod2lkZSkpKSAmIHtcbiAgICAvLyBEdWUgdG8gYSBTYWZhcmkgaU9TIHJlbmRlcmluZyBidWcgd2UgbmVlZCB0byBkZWZpbmUgbWluLXdpZHRoIGFzIHdlbGwuXG4gICAgLy8gT3RoZXJ3aXNlLCBhZnRlciBvcmllbnRhdGlvbiBjaGFuZ2UsIHRoZXJlIGlzIGEgd3Jvbmcgd2lkdGggaWYgcGxhY2VkIGluIGFuIHNiYi1kaWFsb2cuXG4gICAgbWluLXdpZHRoOiAxMDAlO1xuICB9XG59XG5cbi5zYmItY2FsZW5kYXJfX3RhYmxlLWhlYWRlciB7XG4gIC8vIERlcGVuZGluZyB3aGVyZSBpbiB0aGUgRE9NIGl0J3MgdXNlZCwgaXQncyBwb3NzaWJsZSB0aGF0IGJyb3dzZXIgZGVmYXVsdHMgc2V0IHRleHQtYWxpZ24gdG8gbGVmdC5cbiAgdGV4dC1hbGlnbjogY2VudGVyO1xufVxuXG4uc2JiLWNhbGVuZGFyX190YWJsZS1ib2R5IHtcbiAgLy8gRGVwZW5kaW5nIHdoZXJlIGluIHRoZSBET00gaXQncyB1c2VkLCBpdCdzIHBvc3NpYmxlIHRoYXQgYnJvd3NlciBkZWZhdWx0cyBzZXQgdGV4dC1hbGlnbiB0byBsZWZ0LlxuICB0ZXh0LWFsaWduOiBjZW50ZXI7XG59XG5cbi5zYmItY2FsZW5kYXJfX3RhYmxlLWhlYWRlci1jZWxsLFxuLnNiYi1jYWxlbmRhcl9fdGFibGUtaGVhZGVyLWNlbGwtdmVydGljYWwge1xuICB3aWR0aDogdmFyKC0tc2JiLWNhbGVuZGFyLWNlbGwtc2l6ZSk7XG4gIGNvbG9yOiB2YXIoLS1zYmItY2FsZW5kYXItaGVhZGVyLWNvbG9yKTtcbiAgcGFkZGluZzogMDtcbiAgZm9udC1zaXplOiB2YXIoLS1zYmItdGV4dC1mb250LXNpemUteHMpO1xuICBmb250LXdlaWdodDogbm9ybWFsO1xuICBsZXR0ZXItc3BhY2luZzogdmFyKC0tc2JiLXR5cG8tbGV0dGVyLXNwYWNpbmctdGV4dCk7XG5cbiAgOmhvc3QoOm5vdChbbXVsdGlwbGVdKSkgJiB7XG4gICAgaGVpZ2h0OiB2YXIoLS1zYmItY2FsZW5kYXItY2VsbC1zaXplKTtcbiAgfVxufVxuXG4uc2JiLWNhbGVuZGFyX190YWJsZS1oZWFkZXItY2VsbC12ZXJ0aWNhbCB7XG4gIHBhZGRpbmctYmxvY2stZW5kOiB2YXIoLS1zYmItY2FsZW5kYXItY2VsbC1wYWRkaW5nLWJsb2NrLWVuZCk7XG59XG5cbi5zYmItY2FsZW5kYXJfX3RhYmxlLWRhdGEge1xuICBwb3NpdGlvbjogcmVsYXRpdmU7XG4gIHBhZGRpbmc6IDA7XG4gIHRleHQtYWxpZ246IGNlbnRlcjtcbn1cblxuLnNiYi1jYWxlbmRhcl9fZGF5LWNlbGwge1xuICBwYWRkaW5nLWJsb2NrLWVuZDogdmFyKC0tc2JiLWNhbGVuZGFyLWNlbGwtcGFkZGluZy1ibG9jay1lbmQpO1xufVxuXG5zYmItY2FsZW5kYXItZGF5IHtcbiAgOmhvc3QoOm5vdCg6c3RhdGUoZW5oYW5jZWQpKSkgJiB7XG4gICAgLS1zYmItY2FsZW5kYXItY2VsbC1qdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcbiAgICAtLXNiYi1jYWxlbmRhci1kYXktaGVpZ2h0OiAje3NiYi5weC10by1yZW0tYnVpbGQoNDQpfTtcbiAgICAtLXNiYi1jYWxlbmRhci1kYXktZXh0cmEtZGlzcGxheTogbm9uZTtcbiAgICAtLXNiYi1jYWxlbmRhci1kYXktdmFsdWUtaGVpZ2h0OiB1bnNldDtcbiAgICAtLXNiYi1jYWxlbmRhci1kYXktY3Jvc3NlZC1vdXQtdG9wOiA1MCU7XG4gICAgLS1zYmItY2FsZW5kYXItZGF5LWNyb3NzZWQtb3V0LXRyYW5zbGF0ZTogdHJhbnNsYXRlKC01MCUsIC01MCUpIHJvdGF0ZSgtNDVkZWcpO1xuICB9XG59XG5cbkBrZXlmcmFtZXMgc2hvdyB7XG4gIGZyb20ge1xuICAgIG9wYWNpdHk6IDA7XG4gICAgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKHZhcigtLXNiYi1jYWxlbmRhci10YWJsZS1hbmltYXRpb24tc2hpZnQpKTtcbiAgfVxuXG4gIHRvIHtcbiAgICBvcGFjaXR5OiAxO1xuICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlWSgwJSk7XG4gIH1cbn1cblxuQGtleWZyYW1lcyBoaWRlIHtcbiAgZnJvbSB7XG4gICAgb3BhY2l0eTogMTtcbiAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZVkoMCUpO1xuICB9XG5cbiAgdG8ge1xuICAgIG9wYWNpdHk6IDA7XG4gICAgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKHZhcigtLXNiYi1jYWxlbmRhci10YWJsZS1hbmltYXRpb24tc2hpZnQpKTtcbiAgfVxufVxuIiwiaW1wb3J0IHtcbiAgdHlwZSBDU1NSZXN1bHRHcm91cCxcbiAgaHRtbCxcbiAgaXNTZXJ2ZXIsXG4gIG5vdGhpbmcsXG4gIHR5cGUgUHJvcGVydHlWYWx1ZXMsXG4gIHR5cGUgVGVtcGxhdGVSZXN1bHQsXG4gIHVuc2FmZUNTUyxcbn0gZnJvbSAnbGl0JztcbmltcG9ydCB7IHByb3BlcnR5LCBzdGF0ZSB9IGZyb20gJ2xpdC9kZWNvcmF0b3JzLmpzJztcblxuaW1wb3J0IHsgU2JiU2Vjb25kYXJ5QnV0dG9uRWxlbWVudCB9IGZyb20gJy4uLy4uL2J1dHRvbi5wdXJlLnRzJztcbmltcG9ydCB7XG4gIGJ1dHRvblJlc2V0U3R5bGVzLFxuICB0eXBlIERhdGVBZGFwdGVyLFxuICBkZWZhdWx0RGF0ZUFkYXB0ZXIsXG4gIGZvcmNlVHlwZSxcbiAgaGFuZGxlRGlzdGluY3RDaGFuZ2UsXG4gIGkxOG5DYWxlbmRhckRhdGVTZWxlY3Rpb24sXG4gIGkxOG5DYWxlbmRhcldlZWtOdW1iZXIsXG4gIGkxOG5OZXh0TW9udGgsXG4gIGkxOG5OZXh0WWVhcixcbiAgaTE4bk5leHRZZWFyUmFuZ2UsXG4gIGkxOG5QcmV2aW91c01vbnRoLFxuICBpMThuUHJldmlvdXNZZWFyLFxuICBpMThuUHJldmlvdXNZZWFyUmFuZ2UsXG4gIGkxOG5ZZWFyTW9udGhTZWxlY3Rpb24sXG4gIGlzQXJyb3dLZXlPclBhZ2VLZXlzUHJlc3NlZCxcbiAgTU9OREFZLFxuICBwbGFpbkRhdGUsXG4gIHJlYWRDb25maWcsXG4gIFNiYkVsZW1lbnQsXG4gIHR5cGUgU2JiRWxlbWVudFR5cGUsXG4gIFNiYkxhbmd1YWdlQ29udHJvbGxlcixcbiAgU2JiTWVkaWFNYXRjaGVyQ29udHJvbGxlcixcbiAgU2JiTWVkaWFRdWVyeUJyZWFrcG9pbnRMYXJnZUFuZEFib3ZlLFxuICBzY3JlZW5SZWFkZXJPbmx5U3R5bGVzLFxuICBUSFVSU0RBWSxcbiAgVFVFU0RBWSxcbiAgV0VETkVTREFZLFxufSBmcm9tICcuLi8uLi9jb3JlLnRzJztcbmltcG9ydCB7IFNiYkljb25FbGVtZW50IH0gZnJvbSAnLi4vLi4vaWNvbi5wdXJlLnRzJztcbmltcG9ydCB7IFNiYkNhbGVuZGFyRGF5RWxlbWVudCB9IGZyb20gJy4uL2NhbGVuZGFyLWRheS9jYWxlbmRhci1kYXkuY29tcG9uZW50LnRzJztcbmltcG9ydCB7IFNiYkNhbGVuZGFyTW9udGhFbGVtZW50IH0gZnJvbSAnLi4vY2FsZW5kYXItbW9udGgvY2FsZW5kYXItbW9udGguY29tcG9uZW50LnRzJztcbmltcG9ydCB7IFNiYkNhbGVuZGFyV2Vla2RheUVsZW1lbnQgfSBmcm9tICcuLi9jYWxlbmRhci13ZWVrZGF5L2NhbGVuZGFyLXdlZWtkYXkuY29tcG9uZW50LnRzJztcbmltcG9ydCB7IFNiYkNhbGVuZGFyV2Vla251bWJlckVsZW1lbnQgfSBmcm9tICcuLi9jYWxlbmRhci13ZWVrbnVtYmVyL2NhbGVuZGFyLXdlZWtudW1iZXIuY29tcG9uZW50LnRzJztcbmltcG9ydCB7IFNiYkNhbGVuZGFyWWVhckVsZW1lbnQgfSBmcm9tICcuLi9jYWxlbmRhci15ZWFyL2NhbGVuZGFyLXllYXIuY29tcG9uZW50LnRzJztcbmltcG9ydCB0eXBlIHsgU2JiQ2FsZW5kYXJDZWxsQmFzZUVsZW1lbnQgfSBmcm9tICcuLi9jb21tb24vY2FsZW5kYXItY2VsbC1iYXNlLWVsZW1lbnQudHMnO1xuXG5pbXBvcnQgc3R5bGUgZnJvbSAnLi9jYWxlbmRhci5zY3NzP2lubGluZSc7XG5cbmNvbnN0IERBWVNfUEVSX1JPVzogbnVtYmVyID0gNztcbmNvbnN0IE1PTlRIU19QRVJfUk9XOiBudW1iZXIgPSA0O1xuY29uc3QgWUVBUlNfUEVSX1JPVzogbnVtYmVyID0gNDtcbmNvbnN0IE1PTlRIU19QRVJfUEFHRTogbnVtYmVyID0gMTI7XG5jb25zdCBZRUFSU19QRVJfUEFHRTogbnVtYmVyID0gMjQ7XG5cbmV4cG9ydCBjbGFzcyBTYmJNb250aENoYW5nZUV2ZW50IGV4dGVuZHMgRXZlbnQge1xuICBwcml2YXRlIHJlYWRvbmx5IF9yYW5nZTogcmVhZG9ubHkgRGF5W107XG5cbiAgcHVibGljIGdldCByYW5nZSgpOiByZWFkb25seSBEYXlbXSB7XG4gICAgcmV0dXJuIHRoaXMuX3JhbmdlO1xuICB9XG5cbiAgcHVibGljIGNvbnN0cnVjdG9yKHJhbmdlOiByZWFkb25seSBEYXlbXSkge1xuICAgIHN1cGVyKCdtb250aGNoYW5nZScsIHsgYnViYmxlczogdHJ1ZSwgY29tcG9zZWQ6IHRydWUgfSk7XG4gICAgdGhpcy5fcmFuZ2UgPSBPYmplY3QuZnJlZXplKHJhbmdlIHx8IFtdKTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgU2JiRGF0ZVNlbGVjdGVkRXZlbnQ8VD4gZXh0ZW5kcyBFdmVudCB7XG4gIHByaXZhdGUgcmVhZG9ubHkgX2RhdGVTZWxlY3RlZDogUmVhZG9ubHk8VCB8IFRbXT47XG5cbiAgcHVibGljIGdldCBkYXRlU2VsZWN0ZWQoKTogUmVhZG9ubHk8VCB8IFRbXT4ge1xuICAgIHJldHVybiB0aGlzLl9kYXRlU2VsZWN0ZWQ7XG4gIH1cblxuICBwdWJsaWMgY29uc3RydWN0b3IoZGF0ZXM6IFQgfCBUW10pIHtcbiAgICBzdXBlcignZGF0ZXNlbGVjdGVkJywgeyBidWJibGVzOiB0cnVlLCBjb21wb3NlZDogdHJ1ZSB9KTtcbiAgICB0aGlzLl9kYXRlU2VsZWN0ZWQgPSBPYmplY3QuZnJlZXplKGRhdGVzKTtcbiAgfVxufVxuXG4vKipcbiAqIFBhcmFtZXRlcnMgbmVlZGVkIGluIHllYXIgYW5kIG1vbnRoIHZpZXdzIHRvIGNvcnJlY3RseSBjYWxjdWxhdGUgdGhlIG5leHQgZWxlbWVudCBpbiBrZXlib2FyZCBuYXZpZ2F0aW9uLlxuICpcbiAqIFRoZSBjZWxsJ3MgaW5kZXggYW5kIHRoZSBlbGVtZW50J3MgaW5kZXggaW4gaXRzIG1vbnRoIC8geWVhciBiYXRjaCBtdXN0IGJlIGRpc3Rpbmd1aXNoZWQ6XG4gKiB0aGUgZmlyc3QgaXMgdGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IGluIHRoZSBhcnJheSBvZiBhbGwgdGhlIHJlbmRlcmVkIGNlbGxzLCB3aGlsZSB0aGUgc2Vjb25kIGlzIHRoZSBpbmRleCBvZiB0aGUgZWxlbWVudCByZWxhdGl2ZSB0byBpdHMgdGFibGUuXG4gKiBJbiBub24td2lkZSBtb2RlLCB0aGUgd3RvIGFyZSB0aGUgc2FtZSwgd2hpbGUgaW4gd2lkZSBtb2RlIHRoZSBjZWxsJ3MgaW5kZXggY2FuIGdvIGZyb20gMCB0byA0NyBmb3IgeWVhcnMgYW5kIGZyb20gMCB0byAyMyBmb3IgbW9udGhzLFxuICogd2hpbGUgdGhlIGVsZW1lbnQgaW5kZXggZ29lcyBmcm9tIDAgdG8sIHJlc3BlY3RpdmVseSwgMjMgYW5kIDExLlxuICovXG5pbnRlcmZhY2UgQ2FsZW5kYXJLZXlib2FyZE5hdmlnYXRpb25Nb250aFllYXJWaWV3c1BhcmFtZXRlcnMge1xuICAvKiogVGhlIGVsZW1lbnQgaW5kZXggd2l0aGluIGl0cyB5ZWFyIG9yIG1vbnRoIHJhbmdlLiAqL1xuICBlbGVtZW50SW5kZXhGb3JXaWRlTW9kZTogbnVtYmVyO1xuICAvKiogSW4gd2lkZSBtb2RlLCB0aGUgaW5kZXggb2YgdGhlIGZpcnN0IGVsZW1lbnQgaW4gdGhlIHNlY29uZCBwYW5lbCwgb3IsIGFsdGVybmF0aXZlbHksIHRoZSBudW1iZXIgb2YgZWxlbWVudHMgaW4gdGhlIGZpcnN0IHBhbmVsLiAqL1xuICBvZmZzZXRGb3JXaWRlTW9kZTogbnVtYmVyO1xuICAvKiogVGhlIGluZGV4IG9mIHRoZSBsYXN0IGVsZW1lbnQgd2l0aGluIHRoZSBlbGVtZW50J3MgbW9udGggKG9yIHllYXIgcmFuZ2UpLiAqL1xuICBsYXN0RWxlbWVudEluZGV4Rm9yV2lkZU1vZGU6IG51bWJlcjtcbiAgLyoqIFRoZSBudW1iZXIgb2YgY2VsbHMgZGlzcGxheWVkIGluIGEgc2luZ2xlIHJvdywgZGVwZW5kaW5nIG9uIHRoZSByZW5kZXJlZCB2aWV3LiAqL1xuICB2ZXJ0aWNhbE9mZnNldDogbnVtYmVyO1xufVxuXG4vKipcbiAqIFBhcmFtZXRlcnMgbmVlZGVkIGluIGRheSB2aWV3IHRvIGNvcnJlY3RseSBjYWxjdWxhdGUgdGhlIG5leHQgZWxlbWVudCBpbiBrZXlib2FyZCBuYXZpZ2F0aW9uLlxuICpcbiAqIEluIG9yaWVudGF0aW9uPSd2ZXJ0aWNhbCcsIGl0J3Mgbm90IHBvc3NpYmxlIHRvIHJlbHkgb24gYW55IGFycmF5L2luZGV4IHRvIGNhbGN1bGF0ZSB0aGUgZWxlbWVudCB0byBuYXZpZ2F0ZSB0byxcbiAqIHNvIGNhbGN1bGF0aW9ucyBvbiBkYXRlcyBtdXN0IGJlIGRvbmUsIHdoaWNoIHNob3VsZCBjb25zaWRlciB2aWV3IGJvdW5kYXJpZXMsIG9mZnNldHMgYW5kIG1vbnRoJ3MgbGVuZ3RoLlxuICovXG5pbnRlcmZhY2UgQ2FsZW5kYXJLZXlib2FyZE5hdmlnYXRpb25EYXlWaWV3UGFyYW1ldGVycyB7XG4gIC8qKiBUaGUgZmlyc3QgZGF5IHJlbmRlcmVkLiAqL1xuICBmaXJzdERheUluVmlldzogc3RyaW5nIHwgbnVsbDtcbiAgLyoqIFRoZSBsYXN0IGRheSByZW5kZXJlZC4gSXQgZGVwZW5kcyBvbiB0aGUgJ3dpZGUnIHZhbHVlLiAqL1xuICBsYXN0RGF5SW5WaWV3OiBzdHJpbmcgfCBudWxsO1xuICAvKiogVGhlIG9mZnNldCBmcm9tIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsgKE1vbmRheSkgb2YgdGhlIGZpcnN0IHJlbmRlcmVkIG1vbnRoLiAqL1xuICBmaXJzdE1vbnRoT2Zmc2V0OiBudW1iZXI7XG4gIC8qKiBUaGUgbnVtYmVyIG9mIGRheXMgaW4gdGhlIGZpcnN0IHJlbmRlcmVkIG1vbnRoLiAqL1xuICBmaXJzdE1vbnRoTGVuZ3RoOiBudW1iZXI7XG4gIC8qKiBUaGUgb2Zmc2V0IGZyb20gdGhlIGZpcnN0IGRheSBvZiB0aGUgd2VlayAoTW9uZGF5KSBvZiB0aGUgc2Vjb25kIHJlbmRlcmVkIG1vbnRoLiBJZiB3aWRlIGlzIGZhbHNlLCBpdCdzIGVxdWFsIHRvIHplcm8uICovXG4gIHNlY29uZE1vbnRoT2Zmc2V0OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRGF5PFQgPSBEYXRlPiB7XG4gIC8qKiBEYXRlIGFzIElTTyBzdHJpbmcuICovXG4gIHZhbHVlOiBzdHJpbmc7XG4gIGRheVZhbHVlOiBzdHJpbmc7XG4gIG1vbnRoVmFsdWU6IHN0cmluZztcbiAgeWVhclZhbHVlOiBzdHJpbmc7XG4gIGRhdGVWYWx1ZTogVDtcbiAgd2Vla1ZhbHVlOiBudW1iZXI7XG4gIHdlZWtEYXlWYWx1ZTogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIE1vbnRoQ2VsbCB7XG4gIHZhbHVlOiBzdHJpbmc7XG4gIG1vbnRoVmFsdWU6IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBXZWVrZGF5IHtcbiAgbG9uZzogc3RyaW5nO1xuICBuYXJyb3c6IHN0cmluZztcbn1cblxuLyoqXG4gKiBJdCBkaXNwbGF5cyBhIGNhbGVuZGFyIHdoaWNoIGFsbG93cyBjaG9vc2luZyBhIGRhdGUuXG4gKlxuICogQHNsb3QgLSBVc2UgdGhlIHVubmFtZWQgc2xvdCB0byBhZGQgY3VzdG9taXplZCBgc2JiLWNhbGVuZGFyLWRheWAgZWxlbWVudHMuXG4gKi9cbmV4cG9ydCBjbGFzcyBTYmJDYWxlbmRhckVsZW1lbnQ8VCA9IERhdGU+IGV4dGVuZHMgU2JiRWxlbWVudCB7XG4gIHB1YmxpYyBzdGF0aWMgb3ZlcnJpZGUgcmVhZG9ubHkgZWxlbWVudE5hbWU6IHN0cmluZyA9ICdzYmItY2FsZW5kYXInO1xuICBwdWJsaWMgc3RhdGljIG92ZXJyaWRlIGVsZW1lbnREZXBlbmRlbmNpZXM6IFNiYkVsZW1lbnRUeXBlW10gPSBbXG4gICAgU2JiQ2FsZW5kYXJEYXlFbGVtZW50LFxuICAgIFNiYkNhbGVuZGFyTW9udGhFbGVtZW50LFxuICAgIFNiYkNhbGVuZGFyV2Vla2RheUVsZW1lbnQsXG4gICAgU2JiQ2FsZW5kYXJXZWVrbnVtYmVyRWxlbWVudCxcbiAgICBTYmJDYWxlbmRhclllYXJFbGVtZW50LFxuICAgIFNiYkljb25FbGVtZW50LFxuICAgIFNiYlNlY29uZGFyeUJ1dHRvbkVsZW1lbnQsXG4gIF07XG4gIHB1YmxpYyBzdGF0aWMgb3ZlcnJpZGUgc3R5bGVzOiBDU1NSZXN1bHRHcm91cCA9IFtcbiAgICBidXR0b25SZXNldFN0eWxlcyxcbiAgICBzY3JlZW5SZWFkZXJPbmx5U3R5bGVzLFxuICAgIHVuc2FmZUNTUyhzdHlsZSksXG4gIF07XG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgZXZlbnRzID0ge1xuICAgIGRhdGVzZWxlY3RlZDogJ2RhdGVzZWxlY3RlZCcsXG4gICAgbW9udGhjaGFuZ2U6ICdtb250aGNoYW5nZScsXG4gIH0gYXMgY29uc3Q7XG5cbiAgLyoqIElmIHNldCB0byB0cnVlLCB0d28gbW9udGhzIGFyZSBkaXNwbGF5ZWQgKi9cbiAgQGZvcmNlVHlwZSgpXG4gIEBwcm9wZXJ0eSh7IHR5cGU6IEJvb2xlYW4gfSlcbiAgcHVibGljIGFjY2Vzc29yIHdpZGU6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAvKiogVGhlIGluaXRpYWwgdmlldyBvZiB0aGUgY2FsZW5kYXIgd2hpY2ggc2hvdWxkIGJlIGRpc3BsYXllZCBvbiBvcGVuaW5nLiAqL1xuICBAcHJvcGVydHkoKSBwdWJsaWMgYWNjZXNzb3IgdmlldzogJ2RheScgfCAnbW9udGgnIHwgJ3llYXInID0gJ2RheSc7XG5cbiAgLyoqXG4gICAqIFRoZSBtaW5pbXVtIHZhbGlkIGRhdGUuIEFjY2VwdHMgYSBkYXRlIG9iamVjdCBvciBudWxsLlxuICAgKiBBY2NlcHRzIGFuIElTTzg2MDEgZm9ybWF0dGVkIHN0cmluZyAoZS5nLiAyMDI0LTEyLTI0KSBhcyBhdHRyaWJ1dGUuXG4gICAqL1xuICBAcGxhaW5EYXRlKClcbiAgQHByb3BlcnR5KClcbiAgcHVibGljIGFjY2Vzc29yIG1pbjogVCB8IG51bGwgPSBudWxsO1xuXG4gIC8qKlxuICAgKiBUaGUgbWF4aW11bSB2YWxpZCBkYXRlLiBBY2NlcHRzIGEgZGF0ZSBvYmplY3Qgb3IgbnVsbC5cbiAgICogQWNjZXB0cyBhbiBJU084NjAxIGZvcm1hdHRlZCBzdHJpbmcgKGUuZy4gMjAyNC0xMi0yNCkgYXMgYXR0cmlidXRlLlxuICAgKi9cbiAgQHBsYWluRGF0ZSgpXG4gIEBwcm9wZXJ0eSgpXG4gIHB1YmxpYyBhY2Nlc3NvciBtYXg6IFQgfCBudWxsID0gbnVsbDtcblxuICAvKiogV2hldGhlciB0aGUgY2FsZW5kYXIgYWxsb3dzIGZvciBtdWx0aXBsZSBkYXRlIHNlbGVjdGlvbi4gKi9cbiAgQGZvcmNlVHlwZSgpXG4gIEBoYW5kbGVEaXN0aW5jdENoYW5nZSgoZTogU2JiQ2FsZW5kYXJFbGVtZW50PFQ+LCBuZXdWYWx1ZTogYm9vbGVhbikgPT5cbiAgICBlLl9vbk11bHRpcGxlQ2hhbmdlZChuZXdWYWx1ZSksXG4gIClcbiAgQHByb3BlcnR5KHsgdHlwZTogQm9vbGVhbiB9KVxuICBwdWJsaWMgYWNjZXNzb3IgbXVsdGlwbGU6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAvKipcbiAgICogVGhlIHNlbGVjdGVkIGRhdGU6IGFjY2VwdHMgYSBkYXRlIG9iamVjdCwgb3IsIGlmIGBtdWx0aXBsZWAsIGFuIGFycmF5IG9mIGRhdGVzLlxuICAgKi9cbiAgQHByb3BlcnR5KClcbiAgcHVibGljIHNldCBzZWxlY3RlZCh2YWx1ZTogVCB8IFRbXSB8IG51bGwpIHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgIHRoaXMuX3NlbGVjdGVkID0gdmFsdWVcbiAgICAgICAgLm1hcCgoZGF0ZUxpa2U6IFQpID0+XG4gICAgICAgICAgdGhpcy5fZGF0ZUFkYXB0ZXIuZ2V0VmFsaWREYXRlT3JOdWxsKHRoaXMuX2RhdGVBZGFwdGVyLmRlc2VyaWFsaXplKGRhdGVMaWtlKSksXG4gICAgICAgIClcbiAgICAgICAgLmZpbHRlcigoZGF0ZTogVCB8IG51bGwpOiBkYXRlIGlzIFQgPT4gZGF0ZSAhPT0gbnVsbClcbiAgICAgICAgLmZpbHRlcihcbiAgICAgICAgICAoZGF0ZTogVCkgPT5cbiAgICAgICAgICAgICF0aGlzLl9pc0RheUluUmFuZ2UodGhpcy5fZGF0ZUFkYXB0ZXIudG9Jc284NjAxKGRhdGUpKSB8fCB0aGlzLl9kYXRlRmlsdGVyKGRhdGUpLFxuICAgICAgICApXG4gICAgICAgIC5zb3J0KHRoaXMuX3NvcnREYXRlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3Qgc2VsZWN0ZWREYXRlID0gdGhpcy5fZGF0ZUFkYXB0ZXIuZ2V0VmFsaWREYXRlT3JOdWxsKFxuICAgICAgICB0aGlzLl9kYXRlQWRhcHRlci5kZXNlcmlhbGl6ZSh2YWx1ZSksXG4gICAgICApO1xuICAgICAgaWYgKFxuICAgICAgICAhIXNlbGVjdGVkRGF0ZSAmJlxuICAgICAgICAoIXRoaXMuX2lzRGF5SW5SYW5nZSh0aGlzLl9kYXRlQWRhcHRlci50b0lzbzg2MDEoc2VsZWN0ZWREYXRlKSkgfHxcbiAgICAgICAgICB0aGlzLl9kYXRlRmlsdGVyKHNlbGVjdGVkRGF0ZSkpXG4gICAgICApIHtcbiAgICAgICAgdGhpcy5fc2VsZWN0ZWQgPSBzZWxlY3RlZERhdGU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLl9zZWxlY3RlZCA9IG51bGw7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIHB1YmxpYyBnZXQgc2VsZWN0ZWQoKTogVCB8IFRbXSB8IG51bGwge1xuICAgIHJldHVybiB0aGlzLl9zZWxlY3RlZDtcbiAgfVxuICBAc3RhdGUoKSBwcml2YXRlIGFjY2Vzc29yIF9zZWxlY3RlZDogVCB8IFRbXSB8IG51bGwgPSBudWxsO1xuXG4gIC8qKiBBIGZ1bmN0aW9uIHVzZWQgdG8gZmlsdGVyIG91dCBkYXRlcy4gKi9cbiAgQHByb3BlcnR5KHsgYXR0cmlidXRlOiAnZGF0ZS1maWx0ZXInIH0pXG4gIHB1YmxpYyBhY2Nlc3NvciBkYXRlRmlsdGVyOiAoKGRhdGU6IFQgfCBudWxsKSA9PiBib29sZWFuKSB8IG51bGwgPSBudWxsO1xuXG4gIC8qKiBUaGUgb3JpZW50YXRpb24gb2YgZGF5cyBpbiB0aGUgY2FsZW5kYXIuICovXG4gIEBwcm9wZXJ0eSh7IHJlZmxlY3Q6IHRydWUgfSkgcHVibGljIGFjY2Vzc29yIG9yaWVudGF0aW9uOiAnaG9yaXpvbnRhbCcgfCAndmVydGljYWwnID1cbiAgICAnaG9yaXpvbnRhbCc7XG5cbiAgLyoqIFdoZXRoZXIgaXQgaGFzIHRvIGRpc3BsYXkgdGhlIHdlZWsgbnVtYmVycyBpbiBhZGRpdGlvbiB0byB3ZWVrIGRheXMuICovXG4gIEBmb3JjZVR5cGUoKVxuICBAcHJvcGVydHkoeyBhdHRyaWJ1dGU6ICd3ZWVrLW51bWJlcnMnLCB0eXBlOiBCb29sZWFuIH0pXG4gIHB1YmxpYyBhY2Nlc3NvciB3ZWVrTnVtYmVyczogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIHByaXZhdGUgX2RhdGVBZGFwdGVyOiBEYXRlQWRhcHRlcjxUPiA9IHJlYWRDb25maWcoKS5kYXRldGltZT8uZGF0ZUFkYXB0ZXIgPz8gZGVmYXVsdERhdGVBZGFwdGVyO1xuXG4gIC8qKiBUaGUgY3VycmVudGx5IGFjdGl2ZSBkYXRlLiAqL1xuICBAc3RhdGUoKSBwcml2YXRlIGFjY2Vzc29yIF9hY3RpdmVEYXRlOiBUID0gdGhpcy5fZGF0ZUFkYXB0ZXIudG9kYXkoKTtcblxuICAvKiogVGhlIGN1cnJlbnQgd2lkZSBwcm9wZXJ0eSBjb25zaWRlcmluZyBwcm9wZXJ0eSB2YWx1ZSBhbmQgYnJlYWtwb2ludHMuIEZyb20gemVybyB0byBzbWFsbCBgd2lkZWAgaGFzIGFsd2F5cyB0byBiZSBmYWxzZS4gKi9cbiAgQHN0YXRlKClcbiAgcHJpdmF0ZSBzZXQgX3dpZGUod2lkZTogYm9vbGVhbikge1xuICAgIHRoaXMudG9nZ2xlU3RhdGUoJ3dpZGUnLCB3aWRlKTtcbiAgICB0aGlzLl93aWRlSW50ZXJuYWwgPSB3aWRlO1xuICB9XG4gIHByaXZhdGUgZ2V0IF93aWRlKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLl93aWRlSW50ZXJuYWw7XG4gIH1cbiAgLy8gV2Uga2VlcCB0aGUgc3RhdGUgaW4gYSBmaWVsZCBiZWNhdXNlIG9mIHRoZSBXZWJLaXQgYnVnIGh0dHBzOi8vYnVncy53ZWJraXQub3JnL3Nob3dfYnVnLmNnaT9pZD0zMDM0NjcuXG4gIC8vIFRPRE86IHJlLWNoZWNrIHdoZXRoZXIgZmllbGQgaXMgbmVlZGVkXG4gIHByaXZhdGUgX3dpZGVJbnRlcm5hbDogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIEBzdGF0ZSgpIHByaXZhdGUgYWNjZXNzb3IgX2NhbGVuZGFyVmlldzogU2JiQ2FsZW5kYXJFbGVtZW50Wyd2aWV3J10gPSAnZGF5JztcblxuICBwcml2YXRlIF9uZXh0Q2FsZW5kYXJWaWV3OiBTYmJDYWxlbmRhckVsZW1lbnRbJ3ZpZXcnXSA9ICdkYXknO1xuXG4gIC8qKiBJbmZvcm1hdGlvbiBhYm91dCB0aGUgcmVuZGVyZWQgZGF5IHZpZXc7IHVzZWQgaW4ga2V5Ym9hcmQgbmF2aWdhdGlvbi4gKi9cbiAgcHJpdmF0ZSBfa2V5Ym9hcmROYXZpZ2F0aW9uRGF5Vmlld1BhcmFtZXRlcnM6IENhbGVuZGFyS2V5Ym9hcmROYXZpZ2F0aW9uRGF5Vmlld1BhcmFtZXRlcnMgPSB7XG4gICAgZmlyc3REYXlJblZpZXc6IG51bGwsXG4gICAgbGFzdERheUluVmlldzogbnVsbCxcbiAgICBmaXJzdE1vbnRoT2Zmc2V0OiAwLFxuICAgIGZpcnN0TW9udGhMZW5ndGg6IDAsXG4gICAgc2Vjb25kTW9udGhPZmZzZXQ6IDAsXG4gIH07XG5cbiAgLyoqIEEgbGlzdCBvZiBkYXlzLCBpbiB0d28gZm9ybWF0cyAobG9uZyBhbmQgc2luZ2xlIGNoYXIpLiAqL1xuICBwcml2YXRlIF93ZWVrZGF5cyE6IFdlZWtkYXlbXTtcblxuICAvKiogR3JpZCBvZiBjYWxlbmRhciBjZWxscyByZXByZXNlbnRpbmcgdGhlIGRhdGVzIG9mIHRoZSBtb250aC4gKi9cbiAgcHJpdmF0ZSBfd2Vla3M6IERheTxUPltdW10gPSBbXTtcblxuICAvKiogR3JpZCBvZiBjYWxlbmRhciBjZWxscyByZXByZXNlbnRpbmcgbW9udGhzLiAqL1xuICBwcml2YXRlIF9tb250aHMhOiBNb250aENlbGxbXVtdO1xuXG4gIC8qKiBHcmlkIG9mIGNhbGVuZGFyIGNlbGxzIHJlcHJlc2VudGluZyB5ZWFycy4gKi9cbiAgcHJpdmF0ZSBfeWVhcnMhOiBudW1iZXJbXVtdO1xuXG4gIC8qKiBHcmlkIG9mIGNhbGVuZGFyIGNlbGxzIHJlcHJlc2VudGluZyB5ZWFycyBmb3IgdGhlIHdpZGUgdmlldy4gKi9cbiAgcHJpdmF0ZSBfbmV4dE1vbnRoWWVhcnMhOiBudW1iZXJbXVtdO1xuXG4gIC8qKiBHcmlkIG9mIGNhbGVuZGFyIGNlbGxzIHJlcHJlc2VudGluZyB0aGUgZGF0ZXMgb2YgdGhlIG5leHQgbW9udGguICovXG4gIHByaXZhdGUgX25leHRNb250aFdlZWtzITogRGF5PFQ+W11bXTtcblxuICAvKiogQW4gYXJyYXkgY29udGFpbmluZyBhbGwgdGhlIG1vbnRoIG5hbWVzIGluIHRoZSBjdXJyZW50IGxhbmd1YWdlLiAqL1xuICBwcml2YXRlIF9tb250aE5hbWVzOiBzdHJpbmdbXSA9IHRoaXMuX2RhdGVBZGFwdGVyLmdldE1vbnRoTmFtZXMoJ2xvbmcnKTtcblxuICAvKiogQW4gYXJyYXkgY29udGFpbmluZyB0aGUgd2Vla3MnIG51bWJlcnMgZm9yIHRoZSBjdXJyZW50IG1vbnRoLiAqL1xuICBwcml2YXRlIF93ZWVrTnVtYmVycyE6IG51bWJlcltdO1xuXG4gIC8qKiBBbiBhcnJheSBjb250YWluaW5nIHRoZSB3ZWVrcycgbnVtYmVycyBmb3IgdGhlIG5leHQgbW9udGggaW4gd2lkZSBtb2RlLiAqL1xuICBwcml2YXRlIF9uZXh0TW9udGhXZWVrTnVtYmVycyE6IG51bWJlcltdO1xuXG4gIHByaXZhdGUgX2VuaGFuY2VkVmFyaWFudDogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIC8qKiBBIGxpc3Qgb2YgY2FsZW5kYXIncyBjZWxscyBjb3JyZXNwb25kaW5nIHRvIGRheXMsIG1vbnRocyBvciB5ZWFycyBkZXBlbmRpbmcgb24gdGhlIHZpZXcuICovXG4gIHByaXZhdGUgZ2V0IF9jZWxscygpOiBTYmJDYWxlbmRhckNlbGxCYXNlRWxlbWVudDxUPltdIHtcbiAgICByZXR1cm4gQXJyYXkuZnJvbTxTYmJDYWxlbmRhckNlbGxCYXNlRWxlbWVudDxUPj4oXG4gICAgICAodGhpcy5fY2FsZW5kYXJWaWV3ID09PSAnZGF5J1xuICAgICAgICA/IChBcnJheS5mcm9tKHRoaXMuc2hhZG93Um9vdCEucXVlcnlTZWxlY3RvckFsbCgnc2xvdCcpKS5mbGF0TWFwKChlOiBIVE1MU2xvdEVsZW1lbnQpID0+XG4gICAgICAgICAgICBlLmFzc2lnbmVkRWxlbWVudHMoeyBmbGF0dGVuOiB0cnVlIH0pLFxuICAgICAgICAgICkgYXMgU2JiQ2FsZW5kYXJEYXlFbGVtZW50PFQ+W10pXG4gICAgICAgIDogdGhpcy5zaGFkb3dSb290Py5xdWVyeVNlbGVjdG9yQWxsPFNiYkNhbGVuZGFyQ2VsbEJhc2VFbGVtZW50PFQ+PihcbiAgICAgICAgICAgIGBzYmItY2FsZW5kYXItJHt0aGlzLl9jYWxlbmRhclZpZXd9YCxcbiAgICAgICAgICApKSA/PyBbXSxcbiAgICApO1xuICB9XG5cbiAgLyoqIFRoZSBjaG9zZW4geWVhciBpbiB0aGUgeWVhciBzZWxlY3Rpb24gdmlldy4gKi9cbiAgcHJpdmF0ZSBfY2hvc2VuWWVhcj86IG51bWJlcjtcblxuICAvKiogVGhlIGNob3NlbiBtb250aCBpbiB0aGUgeWVhciBzZWxlY3Rpb24gdmlldy4gKi9cbiAgcHJpdmF0ZSBfY2hvc2VuTW9udGg/OiBudW1iZXI7XG5cbiAgLyoqIFdoZXRoZXIgdGhlIGZvY3VzIHNob3VsZCBiZSByZXNldCBvbiBmb2N1c0NlbGwuICovXG4gIHByaXZhdGUgX3Jlc2V0Rm9jdXMgPSBmYWxzZTtcblxuICAvKiogV2hldGhlciBhbiBlbGVtZW50IGluc2lkZSB0aGUgY2FsZW5kYXIgaXMgY3VycmVudGx5IGZvY3VzZWQuICovXG4gIHByaXZhdGUgX2NvbnRhaW5pbmdGb2N1cyA9IGZhbHNlO1xuXG4gIHByaXZhdGUgX2xhc3RTZWxlY3Rpb246IFQgfCBudWxsID0gbnVsbDtcblxuICBAc3RhdGUoKVxuICBwcml2YXRlIGFjY2Vzc29yIF9pbml0aWFsaXplZCA9IGZhbHNlO1xuXG4gIHByaXZhdGUgX2xhbmd1YWdlID0gbmV3IFNiYkxhbmd1YWdlQ29udHJvbGxlcih0aGlzKS53aXRoSGFuZGxlcigoKSA9PiB7XG4gICAgdGhpcy5fbW9udGhOYW1lcyA9IHRoaXMuX2RhdGVBZGFwdGVyLmdldE1vbnRoTmFtZXMoJ2xvbmcnKTtcbiAgICB0aGlzLl9jcmVhdGVNb250aFJvd3MoKTtcbiAgfSk7XG4gIHByaXZhdGUgX21lZGlhTWF0Y2hlciA9IG5ldyBTYmJNZWRpYU1hdGNoZXJDb250cm9sbGVyKHRoaXMsIHtcbiAgICBbU2JiTWVkaWFRdWVyeUJyZWFrcG9pbnRMYXJnZUFuZEFib3ZlXTogKCkgPT4gdGhpcy5faW5pdCgpLFxuICB9KTtcblxuICBwdWJsaWMgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcbiAgICB0aGlzLl9jcmVhdGVNb250aFJvd3MoKTtcbiAgICB0aGlzLl9zZXRXZWVrZGF5cygpO1xuXG4gICAgLy8gV2UgbmVlZCB0byB0cmFjayB0aGUgZm9jdXMgYXMgd2Ugc2hvdWxkIG9ubHkgdGFrZSBmb2N1cyBpbnRvIHRoZSBjYWxlbmRhciwgd2hlbiB0aGVcbiAgICAvLyBmb2N1cyB3YXMgb25jZSBzZXQgaW50byB0aGUgY2FsZW5kYXIuXG4gICAgLy8gRm9yIHNoYWRvdyBET00gY29tcGF0aWJpbGl0eSB3ZSBuZWVkIHRvIHRyYWNrIHRoaXMgcHJvZ3JhbW1hdGljYWxseS5cbiAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIoJ2ZvY3VzaW4nLCAoKSA9PiAodGhpcy5fY29udGFpbmluZ0ZvY3VzID0gdHJ1ZSkpO1xuICAgIHRoaXMuYWRkRXZlbnRMaXN0ZW5lcignZm9jdXNvdXQnLCAoKSA9PiAodGhpcy5fY29udGFpbmluZ0ZvY3VzID0gZmFsc2UpKTtcbiAgICBjb25zdCByZXNvbHZlRGF5ID0gKGV2ZW50OiBQb2ludGVyRXZlbnQgfCBLZXlib2FyZEV2ZW50KTogU2JiQ2FsZW5kYXJEYXlFbGVtZW50PFQ+IHwgbnVsbCA9PlxuICAgICAgKGV2ZW50LnRhcmdldCBhcyBIVE1MRWxlbWVudCkuY2xvc2VzdDxTYmJDYWxlbmRhckRheUVsZW1lbnQ8VD4+KCdzYmItY2FsZW5kYXItZGF5JykgPz9cbiAgICAgIGV2ZW50XG4gICAgICAgIC5jb21wb3NlZFBhdGgoKVxuICAgICAgICAuZmluZChcbiAgICAgICAgICAoZSk6IGUgaXMgU2JiQ2FsZW5kYXJEYXlFbGVtZW50PFQ+ID0+IChlIGFzIEhUTUxFbGVtZW50KS5sb2NhbE5hbWUgPT09ICdzYmItY2FsZW5kYXItZGF5JyxcbiAgICAgICAgKSA/P1xuICAgICAgbnVsbDtcbiAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgKGV2ZW50KSA9PiB7XG4gICAgICBjb25zdCBkYXkgPSByZXNvbHZlRGF5KGV2ZW50KTtcbiAgICAgIGlmIChkYXkpIHtcbiAgICAgICAgdGhpcy5fc2VsZWN0RGF0ZShkYXkudmFsdWUhLCBldmVudCk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKCdrZXlkb3duJywgKGV2ZW50KSA9PiB7XG4gICAgICBjb25zdCBkYXkgPSByZXNvbHZlRGF5KGV2ZW50KTtcbiAgICAgIGlmIChkYXkpIHtcbiAgICAgICAgdGhpcy5faGFuZGxlS2V5Ym9hcmRFdmVudChldmVudCwgZGF5KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIoJ2JsdXInLCAoKSA9PiAodGhpcy5fbGFzdFNlbGVjdGlvbiA9IG51bGwpKTtcbiAgfVxuXG4gIHByaXZhdGUgcmVhZG9ubHkgX3NvcnREYXRlID0gKGE6IFQsIGI6IFQpOiBudW1iZXIgPT4gdGhpcy5fZGF0ZUFkYXB0ZXIuY29tcGFyZURhdGUoYSwgYik7XG5cbiAgcHJpdmF0ZSBfZGF0ZUZpbHRlcihkYXRlOiBUKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuZGF0ZUZpbHRlcj8uKGRhdGUpID8/IHRydWU7XG4gIH1cblxuICAvKiogUmVzZXRzIHRoZSBhY3RpdmUgbW9udGggYWNjb3JkaW5nIHRvIHRoZSBuZXcgc3RhdGUgb2YgdGhlIGNhbGVuZGFyLiAqL1xuICBwdWJsaWMgcmVzZXRQb3NpdGlvbigpOiB2b2lkIHtcbiAgICB0aGlzLl9yZXNldENhbGVuZGFyVmlldygpO1xuICAgIHRoaXMuX2luaXQoKTtcbiAgfVxuXG4gIHB1YmxpYyBvdmVycmlkZSBjb25uZWN0ZWRDYWxsYmFjaygpOiB2b2lkIHtcbiAgICBzdXBlci5jb25uZWN0ZWRDYWxsYmFjaygpO1xuICAgIHRoaXMucmVzZXRQb3NpdGlvbigpO1xuICAgIHRoaXMuc2hhZG93Um9vdD8uYWRkRXZlbnRMaXN0ZW5lcignc2xvdGNoYW5nZScsIHRoaXMuX29uU2xvdENoYW5nZSwgeyBjYXB0dXJlOiB0cnVlIH0pO1xuICB9XG5cbiAgcHVibGljIG92ZXJyaWRlIGRpc2Nvbm5lY3RlZENhbGxiYWNrKCk6IHZvaWQge1xuICAgIHN1cGVyLmRpc2Nvbm5lY3RlZENhbGxiYWNrKCk7XG4gICAgdGhpcy5zaGFkb3dSb290Py5yZW1vdmVFdmVudExpc3RlbmVyKCdzbG90Y2hhbmdlJywgdGhpcy5fb25TbG90Q2hhbmdlLCB7IGNhcHR1cmU6IHRydWUgfSk7XG4gIH1cblxuICAvKiogQGludGVybmFsICovXG4gIHB1YmxpYyBvdmVycmlkZSBmb2N1cygpOiB2b2lkIHtcbiAgICB0aGlzLl9yZXNldEZvY3VzID0gdHJ1ZTtcbiAgICB0aGlzLl9mb2N1c0NlbGwoKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvdmVycmlkZSB3aWxsVXBkYXRlKGNoYW5nZWRQcm9wZXJ0aWVzOiBQcm9wZXJ0eVZhbHVlczx0aGlzPik6IHZvaWQge1xuICAgIHN1cGVyLndpbGxVcGRhdGUoY2hhbmdlZFByb3BlcnRpZXMpO1xuXG4gICAgaWYgKCF0aGlzLl9pbml0aWFsaXplZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChjaGFuZ2VkUHJvcGVydGllcy5oYXMoJ3dpZGUnKSB8fCBjaGFuZ2VkUHJvcGVydGllcy5oYXMoJ29yaWVudGF0aW9uJykpIHtcbiAgICAgIHRoaXMucmVzZXRQb3NpdGlvbigpO1xuICAgIH1cblxuICAgIGlmIChjaGFuZ2VkUHJvcGVydGllcy5oYXMoJ3ZpZXcnKSkge1xuICAgICAgdGhpcy5fc2V0Q2hvc2VuWWVhcigpO1xuICAgICAgdGhpcy5fY2hvc2VuTW9udGggPSB1bmRlZmluZWQ7XG4gICAgICB0aGlzLl9uZXh0Q2FsZW5kYXJWaWV3ID0gdGhpcy5fY2FsZW5kYXJWaWV3ID0gdGhpcy52aWV3O1xuICAgIH1cbiAgfVxuXG4gIHByb3RlY3RlZCBvdmVycmlkZSB1cGRhdGVkKGNoYW5nZWRQcm9wZXJ0aWVzOiBQcm9wZXJ0eVZhbHVlczx0aGlzPik6IHZvaWQge1xuICAgIHN1cGVyLnVwZGF0ZWQoY2hhbmdlZFByb3BlcnRpZXMpO1xuICAgIC8vIFRoZSBjYWxlbmRhciBuZWVkcyB0byBjYWxjdWxhdGUgdGFiLWluZGV4ZXMgb24gZmlyc3QgcmVuZGVyLFxuICAgIC8vIGFuZCBldmVyeSB0aW1lIGEgZGF0ZSBpcyBzZWxlY3RlZCBvciB0aGUgbW9udGggdmlldyBjaGFuZ2VzLlxuICAgIHRoaXMuX3NldFRhYkluZGV4KCk7XG5cbiAgICAvLyBXaGVuIGNoYW5naW5nIHZpZXcgdG8geWVhci9tb250aCwgdGhlIHRhYmluZGV4IGlzIGNoYW5nZWQsIGJ1dCB0aGUgZm9jdXNlZCBlbGVtZW50IGlzIGdldHRpbmcgbG9zdC5cbiAgICAvLyBXZSBuZWVkIHRvIGNhbGwgYF9mb2N1c0NlbGwoKWAgbWV0aG9kIGV4cGxpY2l0bHkgdG8gY29ycmVjdGx5IHNldCB0aGUgZm9jdXMuXG4gICAgdGhpcy5fZm9jdXNDZWxsKCk7XG4gIH1cblxuICBwcml2YXRlIF9vblNsb3RDaGFuZ2UgPSAoKTogdm9pZCA9PiB7XG4gICAgdGhpcy5fZW5oYW5jZWRWYXJpYW50ID0gQXJyYXkuZnJvbSh0aGlzLmNoaWxkcmVuKS5zb21lKFxuICAgICAgKGMpID0+IGMubG9jYWxOYW1lID09PSAnc2JiLWNhbGVuZGFyLWRheScsXG4gICAgKTtcbiAgICB0aGlzLnRvZ2dsZVN0YXRlKCdlbmhhbmNlZCcsIHRoaXMuX2VuaGFuY2VkVmFyaWFudCk7XG4gICAgdGhpcy5fc2V0VGFiSW5kZXgoKTtcbiAgfTtcblxuICAvKipcbiAgICogVGhlIGBfc2VsZWN0ZWRgIHN0YXRlIHNob3VsZCBiZSBhZGFwdGVkIHdoZW4gdGhlIGBtdWx0aXBsZWAgcHJvcGVydHkgY2hhbmdlczpcbiAgICogICAtIGlmIGl0IGNoYW5nZXMgdG8gdHJ1ZSwgdGhlICdfc2VsZWN0ZWQnIGlzIHNldCB0byBhbiBhcnJheTtcbiAgICogICAtIGlmIGl0IGNoYW5nZXMgdG8gZmFsc2UsIHRoZSBmaXJzdCBhdmFpbGFibGUgb3B0aW9uIGlzIHNldCBhcyAndmFsdWUnIG90aGVyd2lzZSBpdCdzIHNldCB0byBudWxsLlxuICAgKi9cbiAgcHJpdmF0ZSBfb25NdWx0aXBsZUNoYW5nZWQoaXNNdWx0aXBsZTogYm9vbGVhbik6IHZvaWQge1xuICAgIGlmIChpc011bHRpcGxlICYmICFBcnJheS5pc0FycmF5KHRoaXMuX3NlbGVjdGVkKSkge1xuICAgICAgdGhpcy5fc2VsZWN0ZWQgPSB0aGlzLl9zZWxlY3RlZCA/IFt0aGlzLl9zZWxlY3RlZCBhcyBUXSA6IFtdO1xuICAgIH1cbiAgICBpZiAoIWlzTXVsdGlwbGUgJiYgQXJyYXkuaXNBcnJheSh0aGlzLl9zZWxlY3RlZCkpIHtcbiAgICAgIHRoaXMuX3NlbGVjdGVkID0gKHRoaXMuX3NlbGVjdGVkIGFzIFRbXSkubGVuZ3RoID8gKHRoaXMuX3NlbGVjdGVkIGFzIFRbXSlbMF0gOiBudWxsO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBJbml0aWFsaXplcyB0aGUgY29tcG9uZW50LiAqL1xuICBwcml2YXRlIF9pbml0KGFjdGl2ZURhdGU/OiBUKTogdm9pZCB7XG4gICAgLy8gRHVlIHRvIGl0cyBjb21wbGV4aXR5LCB0aGUgY2FsZW5kYXIgaXMgb25seSBpbml0aWFsaXplZCBvbiBjbGllbnQgc2lkZVxuICAgIGlmIChpc1NlcnZlcikge1xuICAgICAgcmV0dXJuO1xuICAgIH0gZWxzZSBpZiAodGhpcy5oeWRyYXRpb25SZXF1aXJlZCkge1xuICAgICAgdGhpcy5oeWRyYXRpb25Db21wbGV0ZS50aGVuKCgpID0+IHRoaXMuX2luaXQoKSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKGFjdGl2ZURhdGUpIHtcbiAgICAgIHRoaXMuX2Fzc2lnbkFjdGl2ZURhdGUoYWN0aXZlRGF0ZSk7XG4gICAgfVxuICAgIHRoaXMuX3dpZGUgPVxuICAgICAgKHRoaXMuX21lZGlhTWF0Y2hlci5tYXRjaGVzKFNiYk1lZGlhUXVlcnlCcmVha3BvaW50TGFyZ2VBbmRBYm92ZSkgPz8gZmFsc2UpICYmIHRoaXMud2lkZTtcbiAgICB0aGlzLl93ZWVrcyA9IHRoaXMuX2NyZWF0ZVdlZWtSb3dzKHRoaXMuX2FjdGl2ZURhdGUpO1xuICAgIHRoaXMuX3llYXJzID0gdGhpcy5fY3JlYXRlWWVhclJvd3MoKTtcbiAgICB0aGlzLl93ZWVrTnVtYmVycyA9IHRoaXMuX3dlZWtzXG4gICAgICAuZmxhdCgpXG4gICAgICAuc29ydCgoYSwgYikgPT4gYS52YWx1ZS5sb2NhbGVDb21wYXJlKGIudmFsdWUpKVxuICAgICAgLm1hcCgoZGF5OiBEYXk8VD4pID0+IGRheS53ZWVrVmFsdWUpXG4gICAgICAuZmlsdGVyKCh2LCBpLCBhKSA9PiBhLmluZGV4T2YodikgPT09IGkpO1xuICAgIHRoaXMuX25leHRNb250aFdlZWtzID0gW1tdXTtcbiAgICB0aGlzLl9uZXh0TW9udGhZZWFycyA9IFtbXV07XG4gICAgaWYgKHRoaXMuX3dpZGUpIHtcbiAgICAgIGNvbnN0IG5leHRNb250aERhdGUgPSB0aGlzLl9kYXRlQWRhcHRlci5hZGRDYWxlbmRhck1vbnRocyh0aGlzLl9hY3RpdmVEYXRlLCAxKTtcbiAgICAgIHRoaXMuX25leHRNb250aFdlZWtzID0gdGhpcy5fY3JlYXRlV2Vla1Jvd3MobmV4dE1vbnRoRGF0ZSwgdHJ1ZSk7XG4gICAgICB0aGlzLl9uZXh0TW9udGhZZWFycyA9IHRoaXMuX2NyZWF0ZVllYXJSb3dzKFlFQVJTX1BFUl9QQUdFKTtcbiAgICAgIHRoaXMuX25leHRNb250aFdlZWtOdW1iZXJzID0gdGhpcy5fbmV4dE1vbnRoV2Vla3NcbiAgICAgICAgLmZsYXQoKVxuICAgICAgICAuc29ydCgoYSwgYikgPT4gYS52YWx1ZS5sb2NhbGVDb21wYXJlKGIudmFsdWUpKVxuICAgICAgICAubWFwKChkYXk6IERheTxUPikgPT4gZGF5LndlZWtWYWx1ZSlcbiAgICAgICAgLmZpbHRlcigodiwgaSwgYSkgPT4gYS5pbmRleE9mKHYpID09PSBpKTtcbiAgICB9XG4gICAgdGhpcy5faW5pdGlhbGl6ZWQgPSB0cnVlO1xuICB9XG5cbiAgLyoqIEZvY3VzZXMgb24gYSBkYXkgY2VsbCBwcmlvcml0aXppbmcgdGhlIHNlbGVjdGVkIGRheSwgdGhlIGN1cnJlbnQgZGF5LCBhbmQgbGFzdGx5LCB0aGUgZmlyc3Qgc2VsZWN0YWJsZSBkYXkuICovXG4gIHByaXZhdGUgX2ZvY3VzQ2VsbCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5fcmVzZXRGb2N1cykge1xuICAgICAgdGhpcy5fZ2V0Rmlyc3RGb2N1c2FibGUoKT8uZm9jdXMoKTtcbiAgICAgIHRoaXMuX3Jlc2V0Rm9jdXMgPSBmYWxzZTtcbiAgICB9XG4gIH1cblxuICAvKiogQ3JlYXRlcyB0aGUgYXJyYXkgb2Ygd2Vla2RheXMuICovXG4gIHByaXZhdGUgX3NldFdlZWtkYXlzKCk6IHZvaWQge1xuICAgIGNvbnN0IG5hcnJvd1dlZWtkYXlzOiBzdHJpbmdbXSA9IHRoaXMuX2RhdGVBZGFwdGVyLmdldERheU9mV2Vla05hbWVzKCduYXJyb3cnKTtcbiAgICBjb25zdCBsb25nV2Vla2RheXM6IHN0cmluZ1tdID0gdGhpcy5fZGF0ZUFkYXB0ZXIuZ2V0RGF5T2ZXZWVrTmFtZXMoJ2xvbmcnKTtcbiAgICBjb25zdCB3ZWVrZGF5czogV2Vla2RheVtdID0gbG9uZ1dlZWtkYXlzLm1hcCgobG9uZzogc3RyaW5nLCBpOiBudW1iZXIpID0+ICh7XG4gICAgICBsb25nLFxuICAgICAgbmFycm93OiBuYXJyb3dXZWVrZGF5c1tpXSxcbiAgICB9KSk7XG5cbiAgICAvLyBSb3RhdGVzIHRoZSBsYWJlbHMgZm9yIGRheXMgb2YgdGhlIHdlZWsgYmFzZWQgb24gdGhlIGNvbmZpZ3VyZWQgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgIGNvbnN0IGZpcnN0RGF5T2ZXZWVrOiBudW1iZXIgPSB0aGlzLl9kYXRlQWRhcHRlci5nZXRGaXJzdERheU9mV2VlaygpO1xuICAgIHRoaXMuX3dlZWtkYXlzID0gd2Vla2RheXMuc2xpY2UoZmlyc3REYXlPZldlZWspLmNvbmNhdCh3ZWVrZGF5cy5zbGljZSgwLCBmaXJzdERheU9mV2VlaykpO1xuICB9XG5cbiAgLyoqIENyZWF0ZXMgdGhlIHJvd3MgYWxvbmcgdGhlIGhvcml6b250YWwgZGlyZWN0aW9uIGFuZCBzZXRzIHRoZSBwYXJhbWV0ZXJzIHVzZWQgaW4ga2V5Ym9hcmQgbmF2aWdhdGlvbi4gKi9cbiAgcHJpdmF0ZSBfY3JlYXRlV2Vla1Jvd3ModmFsdWU6IFQsIGlzU2Vjb25kTW9udGhJblZpZXcgPSBmYWxzZSk6IERheTxUPltdW10ge1xuICAgIGNvbnN0IGRheXNJbk1vbnRoOiBudW1iZXIgPSB0aGlzLl9kYXRlQWRhcHRlci5nZXROdW1EYXlzSW5Nb250aCh2YWx1ZSk7XG4gICAgY29uc3Qgd2Vla09mZnNldDogbnVtYmVyID0gdGhpcy5fZGF0ZUFkYXB0ZXIuZ2V0Rmlyc3RXZWVrT2Zmc2V0KHZhbHVlKTtcbiAgICBpZiAoIWlzU2Vjb25kTW9udGhJblZpZXcpIHtcbiAgICAgIHRoaXMuX2tleWJvYXJkTmF2aWdhdGlvbkRheVZpZXdQYXJhbWV0ZXJzLmZpcnN0TW9udGhMZW5ndGggPSBkYXlzSW5Nb250aDtcbiAgICAgIHRoaXMuX2tleWJvYXJkTmF2aWdhdGlvbkRheVZpZXdQYXJhbWV0ZXJzLmZpcnN0TW9udGhPZmZzZXQgPSB3ZWVrT2Zmc2V0O1xuICAgICAgdGhpcy5fa2V5Ym9hcmROYXZpZ2F0aW9uRGF5Vmlld1BhcmFtZXRlcnMuZmlyc3REYXlJblZpZXcgPSB0aGlzLl9kYXRlQWRhcHRlci50b0lzbzg2MDEoXG4gICAgICAgIHRoaXMuX2RhdGVBZGFwdGVyLmNyZWF0ZURhdGUoXG4gICAgICAgICAgdGhpcy5fZGF0ZUFkYXB0ZXIuZ2V0WWVhcih2YWx1ZSksXG4gICAgICAgICAgdGhpcy5fZGF0ZUFkYXB0ZXIuZ2V0TW9udGgodmFsdWUpLFxuICAgICAgICAgIDEsXG4gICAgICAgICksXG4gICAgICApO1xuICAgICAgdGhpcy5fa2V5Ym9hcmROYXZpZ2F0aW9uRGF5Vmlld1BhcmFtZXRlcnMubGFzdERheUluVmlldyA9IHRoaXMuX2RhdGVBZGFwdGVyLnRvSXNvODYwMShcbiAgICAgICAgdGhpcy5fZGF0ZUFkYXB0ZXIuY3JlYXRlRGF0ZShcbiAgICAgICAgICB0aGlzLl9kYXRlQWRhcHRlci5nZXRZZWFyKHZhbHVlKSxcbiAgICAgICAgICB0aGlzLl9kYXRlQWRhcHRlci5nZXRNb250aCh2YWx1ZSksXG4gICAgICAgICAgZGF5c0luTW9udGgsXG4gICAgICAgICksXG4gICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl9rZXlib2FyZE5hdmlnYXRpb25EYXlWaWV3UGFyYW1ldGVycy5zZWNvbmRNb250aE9mZnNldCA9IHdlZWtPZmZzZXQ7XG4gICAgICB0aGlzLl9rZXlib2FyZE5hdmlnYXRpb25EYXlWaWV3UGFyYW1ldGVycy5sYXN0RGF5SW5WaWV3ID0gdGhpcy5fZGF0ZUFkYXB0ZXIudG9Jc284NjAxKFxuICAgICAgICB0aGlzLl9kYXRlQWRhcHRlci5jcmVhdGVEYXRlKFxuICAgICAgICAgIHRoaXMuX2RhdGVBZGFwdGVyLmdldFllYXIodmFsdWUpLFxuICAgICAgICAgIHRoaXMuX2RhdGVBZGFwdGVyLmdldE1vbnRoKHZhbHVlKSxcbiAgICAgICAgICBkYXlzSW5Nb250aCxcbiAgICAgICAgKSxcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLm9yaWVudGF0aW9uID09PSAnaG9yaXpvbnRhbCdcbiAgICAgID8gdGhpcy5fY3JlYXRlV2Vla1Jvd3NIb3Jpem9udGFsKHZhbHVlLCBkYXlzSW5Nb250aCwgd2Vla09mZnNldClcbiAgICAgIDogdGhpcy5fY3JlYXRlV2Vla1Jvd3NWZXJ0aWNhbCh2YWx1ZSwgZGF5c0luTW9udGgsIHdlZWtPZmZzZXQpO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgdGhlIHJvd3MgZm9yIGVhY2ggd2VlayBpbiBvcmllbnRhdGlvbj0naG9yaXpvbnRhbCcuXG4gICAqXG4gICAqIEl0ZXJhdGVzIHRocm91Z2ggdGhlIGRheXMgb2YgdGhlIG1vbnRocywgY3JlYXRlcyBhIERheSBvYmplY3QgZm9yIGVhY2ggYW5kIHB1c2hlcyBpdCBpbnRvIGFuZCBhcnJheS5cbiAgICogRWFjaCBzZXZlbiBkYXlzIChjb25zaWRlcmluZyB0aGUgb2Zmc2V0IGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIG1vbnRoKSByZXN0YXJ0cyBmcm9tIGFuIGVtcHR5IGFycmF5LlxuICAgKlxuICAgKiBUaGUgcmVzdWx0IGlzIGEgbWF0cml4IGluIHdoaWNoIGV2ZXJ5IHJvdyBpcyBhIHdlZWsgKG9yIHBhcnQgb2YgaXQsIGNvbnNpZGVyaW5nIG9mZnNldCkuXG4gICAqL1xuICBwcml2YXRlIF9jcmVhdGVXZWVrUm93c0hvcml6b250YWwodmFsdWU6IFQsIGRheXNJbk1vbnRoOiBudW1iZXIsIHdlZWtPZmZzZXQ6IG51bWJlcik6IERheTxUPltdW10ge1xuICAgIGNvbnN0IHdlZWtzOiBEYXk8VD5bXVtdID0gW1tdXTtcbiAgICBmb3IgKGxldCBpID0gMCwgY2VsbCA9IHdlZWtPZmZzZXQ7IGkgPCBkYXlzSW5Nb250aDsgaSsrLCBjZWxsKyspIHtcbiAgICAgIGlmIChjZWxsID09PSBEQVlTX1BFUl9ST1cpIHtcbiAgICAgICAgd2Vla3MucHVzaChbXSk7XG4gICAgICAgIGNlbGwgPSAwO1xuICAgICAgfVxuICAgICAgY29uc3QgZGF0ZSA9IHRoaXMuX2RhdGVBZGFwdGVyLmNyZWF0ZURhdGUoXG4gICAgICAgIHRoaXMuX2RhdGVBZGFwdGVyLmdldFllYXIodmFsdWUpLFxuICAgICAgICB0aGlzLl9kYXRlQWRhcHRlci5nZXRNb250aCh2YWx1ZSksXG4gICAgICAgIGkgKyAxLFxuICAgICAgKSE7XG4gICAgICB3ZWVrc1t3ZWVrcy5sZW5ndGggLSAxXS5wdXNoKHRoaXMuX21hcERhdGVUb0RheShkYXRlKSk7XG4gICAgfVxuICAgIHJldHVybiB3ZWVrcztcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIHRoZSByb3dzIGZvciBlYWNoIHdlZWsgaW4gb3JpZW50YXRpb249J3ZlcnRpY2FsJy5cbiAgICpcbiAgICogQ3JlYXRlcyBhIG1hdHJpeCB3aXRoIHNldmVuIGVtcHR5IHJvd3MuXG4gICAqIEl0ZXJhdGVzIHRocm91Z2ggdGhlIGRheXMgb2YgdGhlIG1vbnRocywgY3JlYXRlcyBhIERheSBvYmplY3QgZm9yIGVhY2hcbiAgICogYW5kIHB1c2hlcyBpdCBpbnRvIHRoZSBjb3JyZWN0IGFycmF5IGNvbnNpZGVyaW5nIHRoZSBvZmZzZXQgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgbW9udGguXG4gICAqIEVhY2ggc2V2ZW4gZGF5cyAoaW5jbHVkaW5nIG9mZnNldCkgcmVzdGFydHMgZnJvbSB0aGUgZmlyc3QuXG4gICAqXG4gICAqIFRoZSByZXN1bHQgaXMgYSBtYXRyaXggaW4gd2hpY2ggZXZlcnkgcm93IGlzIGEgc2V0IG9mIHdlZWtkYXlzLCBzbzpcbiAgICogLSByb3cgMDogYWxsIHRoZSBNb25kYXlzO1xuICAgKiAtIHJvdyAxOiBhbGwgdGhlIFR1ZXNkYXlzO1xuICAgKiAtIC4uLlxuICAgKiAtIHJvdyA3OiBhbGwgdGhlIFN1bmRheXMuXG4gICAqL1xuICBwcml2YXRlIF9jcmVhdGVXZWVrUm93c1ZlcnRpY2FsKHZhbHVlOiBULCBkYXlzSW5Nb250aDogbnVtYmVyLCB3ZWVrT2Zmc2V0OiBudW1iZXIpOiBEYXk8VD5bXVtdIHtcbiAgICBjb25zdCB3ZWVrczogRGF5PFQ+W11bXSA9IEFycmF5LmZyb20oeyBsZW5ndGg6IERBWVNfUEVSX1JPVyB9LCAoKSA9PiBbXSk7XG4gICAgZm9yIChsZXQgaSA9IDAsIGNlbGwgPSB3ZWVrT2Zmc2V0OyBpIDwgZGF5c0luTW9udGg7IGkrKywgY2VsbCsrKSB7XG4gICAgICBpZiAoY2VsbCA9PT0gREFZU19QRVJfUk9XKSB7XG4gICAgICAgIGNlbGwgPSAwO1xuICAgICAgfVxuICAgICAgY29uc3QgZGF0ZSA9IHRoaXMuX2RhdGVBZGFwdGVyLmNyZWF0ZURhdGUoXG4gICAgICAgIHRoaXMuX2RhdGVBZGFwdGVyLmdldFllYXIodmFsdWUpLFxuICAgICAgICB0aGlzLl9kYXRlQWRhcHRlci5nZXRNb250aCh2YWx1ZSksXG4gICAgICAgIGkgKyAxLFxuICAgICAgKSE7XG4gICAgICB3ZWVrc1tjZWxsXS5wdXNoKHRoaXMuX21hcERhdGVUb0RheShkYXRlKSk7XG4gICAgfVxuICAgIHJldHVybiB3ZWVrcztcbiAgfVxuXG4gIHByaXZhdGUgX21hcERhdGVUb0RheShkYXRlOiBUKTogRGF5PFQ+IHtcbiAgICBjb25zdCBpc29EYXRlID0gdGhpcy5fZGF0ZUFkYXB0ZXIudG9Jc284NjAxKGRhdGUpO1xuICAgIHJldHVybiB7XG4gICAgICB2YWx1ZTogaXNvRGF0ZSxcbiAgICAgIGRhdGVWYWx1ZTogZGF0ZSxcbiAgICAgIGRheVZhbHVlOiBTdHJpbmcodGhpcy5fZGF0ZUFkYXB0ZXIuZ2V0RGF0ZShkYXRlKSksXG4gICAgICBtb250aFZhbHVlOiBTdHJpbmcodGhpcy5fZGF0ZUFkYXB0ZXIuZ2V0TW9udGgoZGF0ZSkpLFxuICAgICAgeWVhclZhbHVlOiBTdHJpbmcodGhpcy5fZGF0ZUFkYXB0ZXIuZ2V0WWVhcihkYXRlKSksXG4gICAgICAvLyBUT0RPOiBJbXByb3ZlIHBlcmZvcm1hbmNlIG9mIHRoaXMsIGJ5IGtlZXBpbmcgdHJhY2sgb2YgdGhlXG4gICAgICAvLyB3ZWVrIG51bWJlciB3aGlsZSBpdGVyYXRpbmcgdGhyb3VnaCB0aGUgZGF5cy5cbiAgICAgIHdlZWtWYWx1ZTogdGhpcy5fZ2V0V2VlayhkYXRlKSxcbiAgICAgIHdlZWtEYXlWYWx1ZTogdGhpcy5fZGF0ZUFkYXB0ZXIuZ2V0RGF5T2ZXZWVrKGRhdGUpLFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIF9nZXRXZWVrKGRhdGU6IFQpOiBudW1iZXIge1xuICAgIGNvbnN0IGZpcnN0RGF5T2ZZZWFyID0gdGhpcy5fZGF0ZUFkYXB0ZXIuY3JlYXRlRGF0ZSh0aGlzLl9kYXRlQWRhcHRlci5nZXRZZWFyKGRhdGUpLCAxLCAxKTtcbiAgICBjb25zdCB3ZWVrZGF5ID0gdGhpcy5fZGF0ZUFkYXB0ZXIuZ2V0RGF5T2ZXZWVrKGZpcnN0RGF5T2ZZZWFyKTtcblxuICAgIGxldCB3ZWVrSW5kZXggPSBbTU9OREFZLCBUVUVTREFZLCBXRURORVNEQVksIFRIVVJTREFZXS5pbmNsdWRlcyh3ZWVrZGF5KSA/IDEgOiAwO1xuICAgIGxldCB3ZWVrU3RhcnQgPSB0aGlzLl9kYXRlQWRhcHRlci5hZGRDYWxlbmRhckRheXMoXG4gICAgICBmaXJzdERheU9mWWVhcixcbiAgICAgIHRoaXMuX2RhdGVBZGFwdGVyLmdldEZpcnN0V2Vla09mZnNldChmaXJzdERheU9mWWVhcikgKiAtMSxcbiAgICApO1xuICAgIHdoaWxlICh0aGlzLl9kYXRlQWRhcHRlci5jb21wYXJlRGF0ZSh3ZWVrU3RhcnQsIGRhdGUpIDw9IDApIHtcbiAgICAgIGNvbnN0IHdlZWtFbmQgPSB0aGlzLl9kYXRlQWRhcHRlci5hZGRDYWxlbmRhckRheXMod2Vla1N0YXJ0LCA2KTtcbiAgICAgIGlmICh0aGlzLl9kYXRlQWRhcHRlci5jb21wYXJlRGF0ZShkYXRlLCB3ZWVrRW5kKSA8PSAwKSB7XG4gICAgICAgIHJldHVybiB3ZWVrSW5kZXggPiAwXG4gICAgICAgICAgPyB3ZWVrSW5kZXhcbiAgICAgICAgICA6IHRoaXMuX2dldFdlZWsodGhpcy5fZGF0ZUFkYXB0ZXIuYWRkQ2FsZW5kYXJEYXlzKGZpcnN0RGF5T2ZZZWFyLCAtMSkpO1xuICAgICAgfVxuICAgICAgd2Vla1N0YXJ0ID0gdGhpcy5fZGF0ZUFkYXB0ZXIuYWRkQ2FsZW5kYXJEYXlzKHdlZWtTdGFydCwgREFZU19QRVJfUk9XKTtcbiAgICAgIHdlZWtJbmRleCsrO1xuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcignVGhlIHByb3ZpZGVkIGRhdGUgaXMgaW52YWxpZCcpO1xuICB9XG5cbiAgLyoqIEZvcmNlIHRoZSBjb252ZXJzaW9uIHRvIElTTzg2MDEgZm9ybWF0dGVkIHN0cmluZy4gKi9cbiAgcHJpdmF0ZSBfbWFwVmFsdWVUb0lTT0RhdGUodmFsdWU6IHN0cmluZyB8IFQpOiBzdHJpbmcge1xuICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnID8gdmFsdWUgOiB0aGlzLl9kYXRlQWRhcHRlci50b0lzbzg2MDEodmFsdWUgYXMgVCk7XG4gIH1cblxuICAvKiogQ3JlYXRlcyB0aGUgcm93cyBmb3IgdGhlIG1vbnRoIHNlbGVjdGlvbiB2aWV3LiAqL1xuICBwcml2YXRlIF9jcmVhdGVNb250aFJvd3MoKTogdm9pZCB7XG4gICAgY29uc3QgbW9udGhzOiBNb250aENlbGxbXSA9IG5ldyBBcnJheSgxMikuZmlsbChudWxsKS5tYXAoXG4gICAgICAoXywgaTogbnVtYmVyKTogTW9udGhDZWxsID0+ICh7XG4gICAgICAgIHZhbHVlOiBTdHJpbmcoaSArIDEpLnBhZFN0YXJ0KDIsICcwJyksXG4gICAgICAgIG1vbnRoVmFsdWU6IGkgKyAxLFxuICAgICAgfSksXG4gICAgKTtcbiAgICBjb25zdCByb3dzOiBudW1iZXIgPSAxMiAvIE1PTlRIU19QRVJfUk9XO1xuICAgIGNvbnN0IG1vbnRoQXJyYXk6IE1vbnRoQ2VsbFtdW10gPSBbXTtcbiAgICBmb3IgKGxldCBpOiBudW1iZXIgPSAwOyBpIDwgcm93czsgaSsrKSB7XG4gICAgICBtb250aEFycmF5LnB1c2gobW9udGhzLnNsaWNlKE1PTlRIU19QRVJfUk9XICogaSwgTU9OVEhTX1BFUl9ST1cgKiAoaSArIDEpKSk7XG4gICAgfVxuICAgIHRoaXMuX21vbnRocyA9IG1vbnRoQXJyYXk7XG4gIH1cblxuICAvKiogQ3JlYXRlcyB0aGUgcm93cyBmb3IgdGhlIHllYXIgc2VsZWN0aW9uIHZpZXcuICovXG4gIHByaXZhdGUgX2NyZWF0ZVllYXJSb3dzKG9mZnNldDogbnVtYmVyID0gMCk6IG51bWJlcltdW10ge1xuICAgIGNvbnN0IHN0YXJ0VmFsdWVZZWFyVmlldzogbnVtYmVyID0gdGhpcy5fZ2V0U3RhcnRWYWx1ZVllYXJWaWV3KCk7XG4gICAgY29uc3QgYWxsWWVhcnM6IG51bWJlcltdID0gbmV3IEFycmF5KFlFQVJTX1BFUl9QQUdFKVxuICAgICAgLmZpbGwoMClcbiAgICAgIC5tYXAoKF8sIGk6IG51bWJlcikgPT4gc3RhcnRWYWx1ZVllYXJWaWV3ICsgb2Zmc2V0ICsgaSk7XG4gICAgY29uc3Qgcm93czogbnVtYmVyID0gWUVBUlNfUEVSX1BBR0UgLyBZRUFSU19QRVJfUk9XO1xuICAgIGNvbnN0IHllYXJBcnJheTogbnVtYmVyW11bXSA9IFtdO1xuICAgIGZvciAobGV0IGk6IG51bWJlciA9IDA7IGkgPCByb3dzOyBpKyspIHtcbiAgICAgIHllYXJBcnJheS5wdXNoKGFsbFllYXJzLnNsaWNlKFlFQVJTX1BFUl9ST1cgKiBpLCBZRUFSU19QRVJfUk9XICogKGkgKyAxKSkpO1xuICAgIH1cbiAgICByZXR1cm4geWVhckFycmF5O1xuICB9XG5cbiAgLyoqXG4gICAqIENhbGN1bGF0ZXMgdGhlIGZpcnN0IHllYXIgdGhhdCB3aWxsIGJlIHNob3duIGluIHRoZSB5ZWFyIHNlbGVjdGlvbiBwYW5lbC5cbiAgICogSWYgYG1pbkRhdGVgIGFuZCBgbWF4RGF0ZWAgYXJlIGJvdGggbnVsbCwgdGhlIHN0YXJ0aW5nIHllYXIgaXMgY2FsY3VsYXRlZCBhc1xuICAgKiB0aGUgbXVsdGlwbGUgb2YgWUVBUlNfUEVSX1BBR0UgY2xvc2VzdCB0byBhbmQgbGVzcyB0aGFuIGFjdGl2ZURhdGUsXG4gICAqIGUuZy4sIHdpdGggYFlFQVJTX1BFUl9QQUdFYCA9IDI0IGFuZCBgYWN0aXZlRGF0ZWAgPSAyMDIwLCB0aGUgZnVuY3Rpb24gd2lsbCByZXR1cm4gMjAxNiAoMjQgKiA4MyksXG4gICAqIHdoaWxlIHdpdGggYGFjdGl2ZURhdGVgID0gMjAwMCwgdGhlIGZ1bmN0aW9uIHdpbGwgcmV0dXJuIDE5OTIgKDI0ICogODIpLlxuICAgKiBJZiBgbWluRGF0ZWAgaXMgbm90IG51bGwsIGl0IHJldHVybnMgdGhlIGNvcnJlc3BvbmRpbmcgeWVhcjsgaWYgYG1heERhdGVgIGlzIG5vdCBudWxsLFxuICAgKiBpdCByZXR1cm5zIHRoZSBjb3JyZXNwb25kaW5nIHllYXIgbWludXMgYFlFQVJTX1BFUl9QQUdFYCwgc28gdGhhdCB0aGUgYG1heERhdGVgIGlzIHRoZSBsYXN0IHJlbmRlcmVkIHllYXIuXG4gICAqIElmIGJvdGggYXJlIG5vdCBudWxsLCBgbWF4RGF0ZWAgaGFzIHByaW9yaXR5IG92ZXIgYG1pbkRhdGVgLlxuICAgKi9cbiAgcHJpdmF0ZSBfZ2V0U3RhcnRWYWx1ZVllYXJWaWV3KCk6IG51bWJlciB7XG4gICAgbGV0IHN0YXJ0aW5nWWVhciA9IDA7XG4gICAgaWYgKHRoaXMubWF4KSB7XG4gICAgICBzdGFydGluZ1llYXIgPSB0aGlzLl9kYXRlQWRhcHRlci5nZXRZZWFyKHRoaXMubWF4KSAtIFlFQVJTX1BFUl9QQUdFICsgMTtcbiAgICB9IGVsc2UgaWYgKHRoaXMubWluKSB7XG4gICAgICBzdGFydGluZ1llYXIgPSB0aGlzLl9kYXRlQWRhcHRlci5nZXRZZWFyKHRoaXMubWluKTtcbiAgICB9XG4gICAgY29uc3QgYWN0aXZlWWVhciA9IHRoaXMuX2RhdGVBZGFwdGVyLmdldFllYXIodGhpcy5fYWN0aXZlRGF0ZSk7XG4gICAgcmV0dXJuIChcbiAgICAgIGFjdGl2ZVllYXIgLVxuICAgICAgKCgoKGFjdGl2ZVllYXIgLSBzdGFydGluZ1llYXIpICUgWUVBUlNfUEVSX1BBR0UpICsgWUVBUlNfUEVSX1BBR0UpICUgWUVBUlNfUEVSX1BBR0UpXG4gICAgKTtcbiAgfVxuXG4gIC8qKiBDaGVja3MgaWYgZGF0ZSBpcyB3aXRoaW4gdGhlIG1pbi1tYXggcmFuZ2UuICovXG4gIHByaXZhdGUgX2lzRGF5SW5SYW5nZShkYXRlU3RyaW5nOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICBpZiAoIXRoaXMubWluICYmICF0aGlzLm1heCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGNvbnN0IGRhdGUgPSB0aGlzLl9kYXRlQWRhcHRlci5kZXNlcmlhbGl6ZShkYXRlU3RyaW5nKSE7XG4gICAgcmV0dXJuIHRoaXMuX2RhdGVBZGFwdGVyLnNhbWVEYXRlKGRhdGUsIHRoaXMuX2RhdGVBZGFwdGVyLmNsYW1wRGF0ZShkYXRlLCB0aGlzLm1pbiwgdGhpcy5tYXgpKTtcbiAgfVxuXG4gIC8qKiBFbWl0cyB0aGUgc2VsZWN0ZWQgZGF0ZSBhbmQgc2V0cyBpdCBpbnRlcm5hbGx5LiAqL1xuICBwcml2YXRlIF9zZWxlY3REYXRlKGRheTogVCwgZXZlbnQ6IFBvaW50ZXJFdmVudCk6IHZvaWQge1xuICAgIHRoaXMuX2Nob3Nlbk1vbnRoID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuX3NldENob3NlblllYXIoKTtcbiAgICBpZiAodGhpcy5tdWx0aXBsZSkge1xuICAgICAgLy8gSWYgYSByYW5nZSBpcyBzZWxlY3RlZCB2aWEgU2hpZnQsIGEgdGV4dCBzZWxlY3Rpb24gcmFuZ2Ugd2lsbCBiZSBhY3RpdmUuXG4gICAgICAvLyBXZSBuZWVkIHRvIHJlbW92ZSBpdCB0byBhdm9pZCBoYXZpbmcgYSB0ZXh0IHNlbGVjdGlvbiBvbiB0b3Agb2YgdGhlIGNhbGVuZGFyIGNlbGxzLFxuICAgICAgLy8gd2hpY2ggd291bGQgY3JlYXRlIGEgY29uZnVzaW5nIFVYLlxuICAgICAgLy8gVGhpcyBhbHNvIG11c3QgYmUgdmVyeSBlYXJseSBpbiB0aGUgZXZlbnQgaGFuZGxlciwgb3RoZXJ3aXNlIHRoZXJlIHdpbGwgYmUgYSBmbGFzaFxuICAgICAgLy8gb2Ygc2VsZWN0aW9uLlxuICAgICAgd2luZG93LmdldFNlbGVjdGlvbigpPy5yZW1vdmVBbGxSYW5nZXMoKTtcbiAgICAgIGxldCBzZWxlY3RlZCA9ICF0aGlzLl9zZWxlY3RlZFxuICAgICAgICA/IFtdXG4gICAgICAgIDogQXJyYXkuaXNBcnJheSh0aGlzLl9zZWxlY3RlZClcbiAgICAgICAgICA/IHRoaXMuX3NlbGVjdGVkXG4gICAgICAgICAgOiBbdGhpcy5fc2VsZWN0ZWRdO1xuICAgICAgY29uc3Qgc2VyaWFsaXplZFNlbGVjdGVkID0gc2VsZWN0ZWQubWFwKChzKSA9PiB0aGlzLl9kYXRlQWRhcHRlci50b0lzbzg2MDEocykpO1xuICAgICAgaWYgKFxuICAgICAgICBldmVudC5zaGlmdEtleSAmJlxuICAgICAgICB0aGlzLl9sYXN0U2VsZWN0aW9uICYmXG4gICAgICAgIHNlcmlhbGl6ZWRTZWxlY3RlZC5pbmNsdWRlcyh0aGlzLl9kYXRlQWRhcHRlci50b0lzbzg2MDEodGhpcy5fbGFzdFNlbGVjdGlvbikpICYmXG4gICAgICAgICFzZXJpYWxpemVkU2VsZWN0ZWQuaW5jbHVkZXModGhpcy5fZGF0ZUFkYXB0ZXIudG9Jc284NjAxKGRheSkpXG4gICAgICApIHtcbiAgICAgICAgY29uc3Qgb2Zmc2V0ID0gdGhpcy5fZGF0ZUFkYXB0ZXIuY29tcGFyZURhdGUodGhpcy5fbGFzdFNlbGVjdGlvbiwgZGF5KSA8IDAgPyAxIDogLTE7XG4gICAgICAgIGNvbnN0IHJhbmdlOiBzdHJpbmdbXSA9IFtdO1xuICAgICAgICBsZXQgY3VycmVudCA9IHRoaXMuX2xhc3RTZWxlY3Rpb247XG4gICAgICAgIHdoaWxlICghdGhpcy5fZGF0ZUFkYXB0ZXIuc2FtZURhdGUoY3VycmVudCwgZGF5KSkge1xuICAgICAgICAgIGN1cnJlbnQgPSB0aGlzLl9kYXRlQWRhcHRlci5hZGRDYWxlbmRhckRheXMoY3VycmVudCwgb2Zmc2V0KSE7XG4gICAgICAgICAgY29uc3Qgc2VyaWFsaXplZEN1cnJlbnQgPSB0aGlzLl9kYXRlQWRhcHRlci50b0lzbzg2MDEoY3VycmVudCk7XG4gICAgICAgICAgaWYgKCFzZXJpYWxpemVkU2VsZWN0ZWQuaW5jbHVkZXMoc2VyaWFsaXplZEN1cnJlbnQpKSB7XG4gICAgICAgICAgICByYW5nZS5wdXNoKHNlcmlhbGl6ZWRDdXJyZW50KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgc2VsZWN0ZWQgPSB0aGlzLl9tZXJnZURhdGVzKHJhbmdlLCBzZXJpYWxpemVkU2VsZWN0ZWQpO1xuICAgICAgfSBlbHNlIGlmIChzZWxlY3RlZC5zb21lKChzZWwpID0+IHRoaXMuX2RhdGVBZGFwdGVyLnNhbWVEYXRlKHNlbCwgZGF5KSkpIHtcbiAgICAgICAgc2VsZWN0ZWQgPSBzZWxlY3RlZC5maWx0ZXIoKHNlbCkgPT4gIXRoaXMuX2RhdGVBZGFwdGVyLnNhbWVEYXRlKHNlbCwgZGF5KSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzZWxlY3RlZCA9IFsuLi5zZWxlY3RlZCwgZGF5XS5zb3J0KHRoaXMuX3NvcnREYXRlKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fbGFzdFNlbGVjdGlvbiA9IGRheTtcbiAgICAgIHRoaXMuX3NlbGVjdGVkID0gc2VsZWN0ZWQ7XG4gICAgICB0aGlzLl9lbWl0RGF0ZVNlbGVjdGVkRXZlbnQodGhpcy5fc2VsZWN0ZWQubWFwKChlKSA9PiB0aGlzLl9kYXRlQWRhcHRlci5kZXNlcmlhbGl6ZShlKSEpKTtcbiAgICB9IGVsc2UgaWYgKCF0aGlzLl9zZWxlY3RlZCB8fCB0aGlzLl9kYXRlQWRhcHRlci5jb21wYXJlRGF0ZSh0aGlzLl9zZWxlY3RlZCBhcyBULCBkYXkpICE9PSAwKSB7XG4gICAgICAvLyBJbiBzaW5nbGUgc2VsZWN0aW9uLCBjaGVjayBpZiB0aGUgZGF5IGlzIGFscmVhZHkgc2VsZWN0ZWRcbiAgICAgIHRoaXMuX3NlbGVjdGVkID0gZGF5O1xuICAgICAgdGhpcy5fZW1pdERhdGVTZWxlY3RlZEV2ZW50KHRoaXMuX2RhdGVBZGFwdGVyLmRlc2VyaWFsaXplKGRheSkhKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogSGFuZGxlIG11bHRpcGxlIGRhdGVzIHNlbGVjdGlvbiB2aWEgd2Vla051bWJlciAvIHdlZWtEYXkgYnV0dG9uczpcbiAgICogLSBpZiBDbWQgb3IgQ3RybCBhcmUgcHJlc3NlZCwgYWRkIHRoZSBuZXcgZGF0ZSB0byB0aGUgY3VycmVudCBvbmVzO1xuICAgKiAtIGlmIG5vdCxcbiAgICogICAgIC0gaWYgdGhlIG5ldyBkYXRlcyBhcmUgdGhlIHNhbWUgb2YgdGhlIGN1cnJlbnQgb25lcywgaXQgbWVhbnMgdGhhdCB0aGUgc2FtZSBidXR0b24gaGFzIGJlZW4gY2xpY2tlZCB0d2ljZSwgc28gZG8gbm90aGluZztcbiAgICogICAgIC0gaWYgbm90LCB0aGUgc2VsZWN0ZWQgZGF0ZXMgYXJlIHRoZSBuZXcgb25lcy5cbiAgICovXG4gIHByaXZhdGUgX3NlbGVjdE11bHRpcGxlRGF0ZXMoZGF5czogRGF5PFQ+W10pOiB2b2lkIHtcbiAgICB0aGlzLl9zZWxlY3RlZCA9IHRoaXMuX21lcmdlRGF0ZXMoZGF5cy5tYXAoKGUpID0+IGUudmFsdWUpKTtcbiAgICB0aGlzLl9lbWl0RGF0ZVNlbGVjdGVkRXZlbnQodGhpcy5fc2VsZWN0ZWQubWFwKChlKSA9PiB0aGlzLl9kYXRlQWRhcHRlci5kZXNlcmlhbGl6ZShlKSEpKTtcbiAgfVxuXG4gIHByaXZhdGUgX21lcmdlRGF0ZXMoZGF0ZXM6IHN0cmluZ1tdLCBzZWxlY3RlZD86IHN0cmluZ1tdKTogVFtdIHtcbiAgICBzZWxlY3RlZCA/Pz0gKHRoaXMuX3NlbGVjdGVkIGFzIFRbXSkubWFwKChzKSA9PiB0aGlzLl9kYXRlQWRhcHRlci50b0lzbzg2MDEocykpO1xuICAgIC8vIEZpbHRlciBkaXNhYmxlZCBkYXlzIGJ5IG1hdGNoaW5nIHRoZSBwcm92aWRlZCBgZGF0ZXNgIHBhcmFtZXRlciBhZ2FpbnN0IHRoZSBlbmFibGVkIGNlbGxzLlxuICAgIC8vIFNpbmNlIHRoZSBidXR0b25zJyB2YWx1ZSBpcyBzZXQgdG8gdGhlIERheSdzIGludGVyZmFjZSB2YWx1ZSAoSVNPIHN0cmluZyksIHRoZXJlJ3Mgbm8gbmVlZCB0byBkZXNlcmlhbGl6ZSBpdC5cbiAgICBjb25zdCBlbmFibGVkRGF5czogc3RyaW5nW10gPSAodGhpcy5fY2VsbHMgYXMgU2JiQ2FsZW5kYXJEYXlFbGVtZW50PFQ+W10pXG4gICAgICAuZmlsdGVyKChlKSA9PiAhZS5kaXNhYmxlZClcbiAgICAgIC5tYXAoKGUpID0+IHRoaXMuX21hcFZhbHVlVG9JU09EYXRlKGUudmFsdWUhKSk7XG4gICAgY29uc3QgZGF5c1RvQWRkOiBzdHJpbmdbXSA9IGRhdGVzLmZpbHRlcigoaXNvRGF0ZSkgPT4gZW5hYmxlZERheXMuaW5jbHVkZXMoaXNvRGF0ZSkpO1xuXG4gICAgLy8gSW4gY2FzZSBvZiBtdWx0aXBsZSBzZWxlY3Rpb24sIG5ld2x5IGFkZGVkIGRheXMgbXVzdCBiZSBhZGRlZCB0byB0aGVcbiAgICAvLyBleGlzdGluZyBvbmVzLCB3aXRob3V0IGR1cGxpY2F0aW9uLlxuICAgIC8vIElmIHRoZSBkYXlzIHRvIGFkZCBhcmUgZXhhY3RseSB0aGUgc2FtZSBhcyB0aGUgc2VsZWN0ZWQgb25lcywgdGhlIHNldFxuICAgIC8vIG11c3QgYmUgZW1wdGllZC5cbiAgICBpZiAoZGF5c1RvQWRkLmV2ZXJ5KChkYXk6IHN0cmluZykgPT4gc2VsZWN0ZWQhLmluY2x1ZGVzKGRheSkpKSB7XG4gICAgICBzZWxlY3RlZCA9IHNlbGVjdGVkLmZpbHRlcigoZGF5OiBzdHJpbmcpID0+ICFkYXlzVG9BZGQuaW5jbHVkZXMoZGF5KSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHNlbGVjdGVkID0gWy4uLnNlbGVjdGVkLCAuLi5kYXlzVG9BZGRdLmZpbHRlcigodiwgaSwgYSkgPT4gYS5pbmRleE9mKHYpID09PSBpKTtcbiAgICB9XG4gICAgcmV0dXJuIHNlbGVjdGVkLm1hcCgocykgPT4gdGhpcy5fZGF0ZUFkYXB0ZXIuZGVzZXJpYWxpemUocykhKS5zb3J0KHRoaXMuX3NvcnREYXRlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFbWl0cyB0aGUgZGF0ZXNlbGVjdGVkIGV2ZW50IGdpdmVuIHRoZSBkZXRhaWwgKGFzIFQgb3IgVFtdIGJhc2VkIG9uIHRoZSB2YWx1ZSBvZiB0aGUgbXVsdGlwbGUgZmxhZykuXG4gICAqIEZJWE1FOiB0aGUgbmFtZSBvZiB0aGUgdmFyaWFibGUgYXBwZWFycyBhcyBldmVudCBuYW1lIGluIHRoZSByZWFkbWVcbiAgICogIGR1ZSB0byBhIGJ1ZyBpbiB0aGUgY3VzdG9tLWVsZW1lbnRzLW1hbmlmZXN0IGxpYnJhcnkuXG4gICAqICBodHRwczovL2dpdGh1Yi5jb20vb3Blbi13Yy9jdXN0b20tZWxlbWVudHMtbWFuaWZlc3QvaXNzdWVzLzE0OVxuICAgKi9cbiAgcHJpdmF0ZSBfZW1pdERhdGVTZWxlY3RlZEV2ZW50KGRhdGVzZWxlY3RlZDogVCB8IFRbXSk6IHZvaWQge1xuICAgIC8qKiBAdHlwZSB7U2JiRGF0ZVNlbGVjdGVkRXZlbnQ8VD59IEV2ZW50IGVtaXR0ZWQgb24gZGF0ZSBzZWxlY3Rpb24uICovXG4gICAgdGhpcy5kaXNwYXRjaEV2ZW50KG5ldyBTYmJEYXRlU2VsZWN0ZWRFdmVudDxUPihkYXRlc2VsZWN0ZWQpKTtcbiAgfVxuXG4gIHByaXZhdGUgX2VtaXRNb250aENoYW5nZSgpOiB2b2lkIHtcbiAgICAvLyBGSVhNRTogdGhlIG5hbWUgb2YgdGhpcyB2YXJpYWJsZSBhcHBlYXJzIGFzIGV2ZW50IG5hbWUgaW4gdGhlIHJlYWRtZVxuICAgIC8vICBkdWUgdG8gYSBidWcgaW4gdGhlIGN1c3RvbS1lbGVtZW50cy1tYW5pZmVzdCBsaWJyYXJ5LlxuICAgIC8vICBodHRwczovL2dpdGh1Yi5jb20vb3Blbi13Yy9jdXN0b20tZWxlbWVudHMtbWFuaWZlc3QvaXNzdWVzLzE0OVxuICAgIGNvbnN0IG1vbnRoY2hhbmdlID0gKHRoaXMud2lkZSA/IFsuLi50aGlzLl93ZWVrcywgLi4udGhpcy5fbmV4dE1vbnRoV2Vla3NdIDogdGhpcy5fd2Vla3MpXG4gICAgICAuZmxhdCgpXG4gICAgICAuc29ydCgoYSwgYikgPT4gYS52YWx1ZS5sb2NhbGVDb21wYXJlKGIudmFsdWUpKSBhcyBEYXlbXTtcbiAgICAvKipcbiAgICAgKiBAdHlwZSB7U2JiTW9udGhDaGFuZ2VFdmVudH1cbiAgICAgKiBFbWl0cyB3aGVuIHRoZSBtb250aCBjaGFuZ2VzLlxuICAgICAqIFRoZSBgcmFuZ2VgIHByb3BlcnR5IGNvbnRhaW5zIHRoZSBkYXlzIGFycmF5IG9mIHRoZSBjaG9zZW4gbW9udGguXG4gICAgICovXG4gICAgdGhpcy5kaXNwYXRjaEV2ZW50KG5ldyBTYmJNb250aENoYW5nZUV2ZW50KG1vbnRoY2hhbmdlKSk7XG4gIH1cblxuICBwcml2YXRlIF9zZXRDaG9zZW5ZZWFyKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLnZpZXcgPT09ICdtb250aCcpIHtcbiAgICAgIGxldCBzZWxlY3RlZERhdGU6IFQgfCB1bmRlZmluZWQ7XG4gICAgICBpZiAodGhpcy5tdWx0aXBsZSkge1xuICAgICAgICBzZWxlY3RlZERhdGUgPSAodGhpcy5zZWxlY3RlZCBhcyBUW10pLmF0KC0xKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHNlbGVjdGVkRGF0ZSA9IHRoaXMuc2VsZWN0ZWQgYXMgVDtcbiAgICAgIH1cbiAgICAgIHRoaXMuX2Nob3NlblllYXIgPSB0aGlzLl9kYXRlQWRhcHRlci5nZXRZZWFyKHNlbGVjdGVkRGF0ZSA/PyB0aGlzLl9kYXRlQWRhcHRlci50b2RheSgpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fY2hvc2VuWWVhciA9IHVuZGVmaW5lZDtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9hc3NpZ25BY3RpdmVEYXRlKGRhdGU6IFQpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5taW4gJiYgdGhpcy5fZGF0ZUFkYXB0ZXIuY29tcGFyZURhdGUodGhpcy5taW4sIGRhdGUpID4gMCkge1xuICAgICAgdGhpcy5fYWN0aXZlRGF0ZSA9IHRoaXMubWluO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAodGhpcy5tYXggJiYgdGhpcy5fZGF0ZUFkYXB0ZXIuY29tcGFyZURhdGUodGhpcy5tYXgsIGRhdGUpIDwgMCkge1xuICAgICAgdGhpcy5fYWN0aXZlRGF0ZSA9IHRoaXMubWF4O1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLl9hY3RpdmVEYXRlID0gZGF0ZTtcbiAgfVxuXG4gIC8qKiBHb2VzIHRvIHRoZSBtb250aCBpZGVudGlmaWVkIGJ5IHRoZSBzaGlmdC4gKi9cbiAgcHJpdmF0ZSBfZ29Ub0RpZmZlcmVudE1vbnRoKG1vbnRoczogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy5faW5pdCh0aGlzLl9kYXRlQWRhcHRlci5hZGRDYWxlbmRhck1vbnRocyh0aGlzLl9hY3RpdmVEYXRlLCBtb250aHMpKTtcbiAgICB0aGlzLl9lbWl0TW9udGhDaGFuZ2UoKTtcbiAgfVxuXG4gIHByaXZhdGUgX2dvVG9EaWZmZXJlbnRZZWFyKHllYXJzOiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLl9jaG9zZW5ZZWFyISArPSB5ZWFycztcbiAgICAvLyBDYW4ndCB1c2UgYF9hc3NpZ25BY3RpdmVEYXRlKC4uLilgIGhlcmUsIGJlY2F1c2UgaXQgd2lsbCBzZXQgaXQgdG8gbWluL21heCB2YWx1ZSBpZiBhcmd1bWVudCBpcyBvdXQgb2YgcmFuZ2VcbiAgICB0aGlzLl9hY3RpdmVEYXRlID0gdGhpcy5fZGF0ZUFkYXB0ZXIuY3JlYXRlRGF0ZShcbiAgICAgIHRoaXMuX2Nob3NlblllYXIhLFxuICAgICAgdGhpcy5fZGF0ZUFkYXB0ZXIuZ2V0TW9udGgodGhpcy5fYWN0aXZlRGF0ZSksXG4gICAgICB0aGlzLl9kYXRlQWRhcHRlci5nZXREYXRlKHRoaXMuX2FjdGl2ZURhdGUpLFxuICAgICk7XG4gICAgdGhpcy5faW5pdCgpO1xuICB9XG5cbiAgcHJpdmF0ZSBfZ29Ub0RpZmZlcmVudFllYXJSYW5nZSh5ZWFyczogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy5faW5pdCh0aGlzLl9kYXRlQWRhcHRlci5hZGRDYWxlbmRhclllYXJzKHRoaXMuX2FjdGl2ZURhdGUsIHllYXJzKSk7XG4gIH1cblxuICBwcml2YXRlIF9wcmV2RGlzYWJsZWQocHJldkRhdGU6IFQpOiBib29sZWFuIHtcbiAgICBpZiAoIXRoaXMubWluKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9kYXRlQWRhcHRlci5jb21wYXJlRGF0ZShwcmV2RGF0ZSwgdGhpcy5taW4pIDwgMDtcbiAgfVxuXG4gIHByaXZhdGUgX25leHREaXNhYmxlZChuZXh0RGF0ZTogVCk6IGJvb2xlYW4ge1xuICAgIGlmICghdGhpcy5tYXgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX2RhdGVBZGFwdGVyLmNvbXBhcmVEYXRlKG5leHREYXRlLCB0aGlzLm1heCkgPiAwO1xuICB9XG5cbiAgLyoqIENoZWNrcyBpZiB0aGUgXCJwcmV2aW91cyBtb250aFwiIGJ1dHRvbiBzaG91bGQgYmUgZGlzYWJsZWQuICovXG4gIHByaXZhdGUgX3ByZXZpb3VzTW9udGhEaXNhYmxlZCgpOiBib29sZWFuIHtcbiAgICBjb25zdCBwcmV2TW9udGggPSB0aGlzLl9kYXRlQWRhcHRlci5hZGRDYWxlbmRhckRheXMoXG4gICAgICB0aGlzLl9hY3RpdmVEYXRlLFxuICAgICAgdGhpcy5fZGF0ZUFkYXB0ZXIuZ2V0RGF0ZSh0aGlzLl9hY3RpdmVEYXRlKSAqIC0xLFxuICAgICk7XG4gICAgcmV0dXJuIHRoaXMuX3ByZXZEaXNhYmxlZChwcmV2TW9udGgpO1xuICB9XG5cbiAgLyoqIENoZWNrcyBpZiB0aGUgXCJuZXh0IG1vbnRoXCIgYnV0dG9uIHNob3VsZCBiZSBkaXNhYmxlZC4gKi9cbiAgcHJpdmF0ZSBfbmV4dE1vbnRoRGlzYWJsZWQoKTogYm9vbGVhbiB7XG4gICAgbGV0IG5leHRNb250aCA9IHRoaXMuX2RhdGVBZGFwdGVyLmFkZENhbGVuZGFyTW9udGhzKHRoaXMuX2FjdGl2ZURhdGUsIHRoaXMuX3dpZGUgPyAyIDogMSk7XG4gICAgbmV4dE1vbnRoID0gdGhpcy5fZGF0ZUFkYXB0ZXIuY3JlYXRlRGF0ZShcbiAgICAgIHRoaXMuX2RhdGVBZGFwdGVyLmdldFllYXIobmV4dE1vbnRoKSxcbiAgICAgIHRoaXMuX2RhdGVBZGFwdGVyLmdldE1vbnRoKG5leHRNb250aCksXG4gICAgICAxLFxuICAgICk7XG4gICAgcmV0dXJuIHRoaXMuX25leHREaXNhYmxlZChuZXh0TW9udGgpO1xuICB9XG5cbiAgLyoqIENoZWNrcyBpZiB0aGUgXCJwcmV2aW91cyB5ZWFyXCIgYnV0dG9uIHNob3VsZCBiZSBkaXNhYmxlZC4gKi9cbiAgcHJpdmF0ZSBfcHJldmlvdXNZZWFyRGlzYWJsZWQoKTogYm9vbGVhbiB7XG4gICAgY29uc3QgcHJldlllYXIgPSB0aGlzLl9kYXRlQWRhcHRlci5jcmVhdGVEYXRlKFxuICAgICAgdGhpcy5fZGF0ZUFkYXB0ZXIuZ2V0WWVhcih0aGlzLl9hY3RpdmVEYXRlKSAtIDEsXG4gICAgICAxMixcbiAgICAgIDMxLFxuICAgICk7XG4gICAgcmV0dXJuIHRoaXMuX3ByZXZEaXNhYmxlZChwcmV2WWVhcik7XG4gIH1cblxuICAvKiogQ2hlY2tzIGlmIHRoZSBcIm5leHQgeWVhclwiIGJ1dHRvbiBzaG91bGQgYmUgZGlzYWJsZWQuICovXG4gIHByaXZhdGUgX25leHRZZWFyRGlzYWJsZWQoKTogYm9vbGVhbiB7XG4gICAgY29uc3QgbmV4dFllYXIgPSB0aGlzLl9kYXRlQWRhcHRlci5jcmVhdGVEYXRlKFxuICAgICAgdGhpcy5fZGF0ZUFkYXB0ZXIuZ2V0WWVhcih0aGlzLl9hY3RpdmVEYXRlKSArICh0aGlzLl93aWRlID8gMiA6IDEpLFxuICAgICAgMSxcbiAgICAgIDEsXG4gICAgKTtcbiAgICByZXR1cm4gdGhpcy5fbmV4dERpc2FibGVkKG5leHRZZWFyKTtcbiAgfVxuXG4gIC8qKiBDaGVja3MgaWYgdGhlIFwicHJldmlvdXMgeWVhclwiIGJ1dHRvbiBzaG91bGQgYmUgZGlzYWJsZWQgaW4geWVhciB2aWV3LiAqL1xuICBwcml2YXRlIF9wcmV2aW91c1llYXJSYW5nZURpc2FibGVkKCk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IHByZXZZZWFyID0gdGhpcy5fZGF0ZUFkYXB0ZXIuY3JlYXRlRGF0ZSh0aGlzLl95ZWFyc1swXVswXSAtIDEsIDEyLCAzMSk7XG4gICAgcmV0dXJuIHRoaXMuX3ByZXZEaXNhYmxlZChwcmV2WWVhcik7XG4gIH1cblxuICAvKiogQ2hlY2tzIGlmIHRoZSBcIm5leHQgeWVhclwiIGJ1dHRvbiBzaG91bGQgYmUgZGlzYWJsZWQgaW4geWVhciB2aWV3LiAqL1xuICBwcml2YXRlIF9uZXh0WWVhclJhbmdlRGlzYWJsZWQoKTogYm9vbGVhbiB7XG4gICAgY29uc3QgeWVhcnMgPSB0aGlzLl93aWRlID8gdGhpcy5fbmV4dE1vbnRoWWVhcnMgOiB0aGlzLl95ZWFycztcbiAgICBjb25zdCBsYXN0WWVhclJhbmdlID0geWVhcnNbeWVhcnMubGVuZ3RoIC0gMV07XG4gICAgY29uc3QgbGFzdFllYXIgPSBsYXN0WWVhclJhbmdlW2xhc3RZZWFyUmFuZ2UubGVuZ3RoIC0gMV07XG4gICAgY29uc3QgbmV4dFllYXIgPSB0aGlzLl9kYXRlQWRhcHRlci5jcmVhdGVEYXRlKGxhc3RZZWFyICsgMSwgMSwgMSk7XG4gICAgcmV0dXJuIHRoaXMuX25leHREaXNhYmxlZChuZXh0WWVhcik7XG4gIH1cblxuICBwcml2YXRlIF9oYW5kbGVUYWJsZUJsdXIoZXZlbnRUYXJnZXQ6IEhUTUxFbGVtZW50KTogdm9pZCB7XG4gICAgaWYgKGV2ZW50VGFyZ2V0Py5sb2NhbE5hbWUgIT09ICdzYmItY2FsZW5kYXItZGF5Jykge1xuICAgICAgdGhpcy5fc2V0VGFiSW5kZXgoKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9zZXRUYWJJbmRleCgpOiB2b2lkIHtcbiAgICBBcnJheS5mcm9tKHRoaXMuX2NlbGxzLmZpbHRlcigoZSkgPT4gZS50YWJJbmRleCA9PT0gMCkgPz8gW10pLmZvckVhY2goXG4gICAgICAoZGF5KSA9PiAoZGF5LnRhYkluZGV4ID0gLTEpLFxuICAgICk7XG4gICAgY29uc3QgZmlyc3RGb2N1c2FibGUgPSB0aGlzLl9nZXRGaXJzdEZvY3VzYWJsZSgpO1xuICAgIGlmIChmaXJzdEZvY3VzYWJsZSkge1xuICAgICAgZmlyc3RGb2N1c2FibGUudGFiSW5kZXggPSAwO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBHZXQgdGhlIGVsZW1lbnQgaW4gdGhlIGNhbGVuZGFyIHRvIGFzc2lnbiBmb2N1cy4gKi9cbiAgcHJpdmF0ZSBfZ2V0Rmlyc3RGb2N1c2FibGUoKTogU2JiQ2FsZW5kYXJDZWxsQmFzZUVsZW1lbnQ8VD4gfCBudWxsIHtcbiAgICBpZiAodGhpcy5fY2FsZW5kYXJWaWV3ID09PSAnZGF5Jykge1xuICAgICAgY29uc3Qgc2VsZWN0ZWRPckN1cnJlbnQgPVxuICAgICAgICB0aGlzLl9jZWxscy5maW5kKChlKSA9PiBlLm1hdGNoZXMoJzpzdGF0ZShzZWxlY3RlZCknKSkgPz9cbiAgICAgICAgdGhpcy5fY2VsbHMuZmluZCgoZSkgPT4gZS5tYXRjaGVzKCc6c3RhdGUoY3VycmVudCknKSk7XG4gICAgICByZXR1cm4gc2VsZWN0ZWRPckN1cnJlbnQgJiYgIXNlbGVjdGVkT3JDdXJyZW50LmRpc2FibGVkXG4gICAgICAgID8gc2VsZWN0ZWRPckN1cnJlbnRcbiAgICAgICAgOiB0aGlzLl9nZXRGaXJzdEZvY3VzYWJsZURheSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBzZWxlY3RlZE9yQ3VycmVudCA9XG4gICAgICAgIHRoaXMuc2hhZG93Um9vdD8ucXVlcnlTZWxlY3RvcjxTYmJDYWxlbmRhckNlbGxCYXNlRWxlbWVudDxUPj4oJzpzdGF0ZShzZWxlY3RlZCknKSA/P1xuICAgICAgICB0aGlzLnNoYWRvd1Jvb3Q/LnF1ZXJ5U2VsZWN0b3I8U2JiQ2FsZW5kYXJDZWxsQmFzZUVsZW1lbnQ8VD4+KCc6c3RhdGUoY3VycmVudCknKTtcbiAgICAgIHJldHVybiBzZWxlY3RlZE9yQ3VycmVudCAmJiAhc2VsZWN0ZWRPckN1cnJlbnQuZGlzYWJsZWRcbiAgICAgICAgPyBzZWxlY3RlZE9yQ3VycmVudFxuICAgICAgICA6IHRoaXMuc2hhZG93Um9vdCEucXVlcnlTZWxlY3RvcjxTYmJDYWxlbmRhckNlbGxCYXNlRWxlbWVudDxUPj4oXG4gICAgICAgICAgICBgc2JiLWNhbGVuZGFyLSR7dGhpcy5fY2FsZW5kYXJWaWV3fTpub3QoW2Rpc2FibGVkXSlgLFxuICAgICAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEluIGBkYXlgIHZpZXcgaW4gYHZlcnRpY2FsYCBvcmllbnRhdGlvbixcbiAgICogaWYgdGhlIGZpcnN0IG9mIHRoZSBtb250aCBpcyBub3QgYSBNb25kYXksIGl0IGlzIG5vdCB0aGUgZmlyc3QgcmVuZGVyZWQgZWxlbWVudCBpbiB0aGUgdGFibGUsXG4gICAqIHNvIGB0aGlzLnNoYWRvd1Jvb3QhLnF1ZXJ5U2VsZWN0b3IoJ3NiYi1jYWxlbmRhci1kYXk6bm90KFtkaXNhYmxlZF0pJylgIHdpbGwgcmV0dXJuIGEgd3JvbmcgdmFsdWUuXG4gICAqXG4gICAqIFRvIHNvbHZlIHRoaXMsIHRoZSBlbGVtZW50IHdpdGggdGhlIGxvd2VzdCBgdmFsdWVgIGlzIHRha2VuIChJU08gU3RyaW5nIGFyZSBvcmRlcmVkKS5cbiAgICovXG4gIHByaXZhdGUgX2dldEZpcnN0Rm9jdXNhYmxlRGF5KCk6IFNiYkNhbGVuZGFyRGF5RWxlbWVudDxUPiB8IG51bGwge1xuICAgIGNvbnN0IGNlbGxzID0gdGhpcy5fY2VsbHMgYXMgU2JiQ2FsZW5kYXJEYXlFbGVtZW50PFQ+W107XG4gICAgY29uc3QgZGF5c0luVmlldyA9IGNlbGxzLmZpbHRlcigoZSkgPT4gIWUuZGlzYWJsZWQpO1xuICAgIGlmICghZGF5c0luVmlldyB8fCBkYXlzSW5WaWV3Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGZpcnN0RWxlbWVudCA9IGRheXNJblZpZXdcbiAgICAgICAgLm1hcCgoZSk6IHN0cmluZyA9PiB0aGlzLl9kYXRlQWRhcHRlci50b0lzbzg2MDEoZS52YWx1ZSEgYXMgVCkpXG4gICAgICAgIC5zb3J0KClbMF07XG4gICAgICByZXR1cm4gY2VsbHMuZmluZCgoZSkgPT4gZS5tYXRjaGVzKGBbc2xvdD1cIiR7Zmlyc3RFbGVtZW50fVwiXWApKSEgPz8gbnVsbDtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9oYW5kbGVLZXlib2FyZEV2ZW50KGV2ZW50OiBLZXlib2FyZEV2ZW50LCBkYXk/OiBTYmJDYWxlbmRhckRheUVsZW1lbnQ8VD4pOiB2b2lkIHtcbiAgICBpZiAoaXNBcnJvd0tleU9yUGFnZUtleXNQcmVzc2VkKGV2ZW50KSkge1xuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICB9XG4gICAgLy8gR2V0cyB0aGUgY3VycmVudGx5IHJlbmRlcmVkIHRhYmxlJ3MgY2VsbDtcbiAgICAvLyB0aGV5IGNvdWxkIGJlIGRheXMsIG1vbnRocyBvciB5ZWFycyBiYXNlZCBvbiB0aGUgY3VycmVudCBzZWxlY3Rpb24gdmlldy5cbiAgICBjb25zdCBvcmlnaW4gPSBkYXkgPz8gKGV2ZW50LnRhcmdldCBhcyBTYmJDYWxlbmRhckRheUVsZW1lbnQ8VD4pO1xuICAgIGNvbnN0IGNlbGxzID0gdGhpcy5fY2VsbHM7XG4gICAgY29uc3QgaW5kZXg6IG51bWJlciA9IGNlbGxzLmluZGV4T2Yob3JpZ2luKTtcbiAgICBsZXQgbmV4dEVsOiBTYmJDYWxlbmRhckNlbGxCYXNlRWxlbWVudDxUPjtcbiAgICBpZiAoZGF5KSB7XG4gICAgICBuZXh0RWwgPSB0aGlzLl9uYXZpZ2F0ZUJ5S2V5Ym9hcmREYXlWaWV3KFxuICAgICAgICBldmVudCxcbiAgICAgICAgaW5kZXgsXG4gICAgICAgIGNlbGxzIGFzIFNiYkNhbGVuZGFyRGF5RWxlbWVudDxUPltdLFxuICAgICAgICB0aGlzLl9tYXBEYXRlVG9EYXkoZGF5LnZhbHVlISBhcyBUKSxcbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5leHRFbCA9IHRoaXMuX25hdmlnYXRlQnlLZXlib2FyZChldmVudCwgaW5kZXgsIGNlbGxzKTtcbiAgICB9XG4gICAgY29uc3QgYWN0aXZlRWwgPSAodGhpcy5fZW5oYW5jZWRWYXJpYW50ID8gZG9jdW1lbnQgOiB0aGlzLnNoYWRvd1Jvb3QhKVxuICAgICAgLmFjdGl2ZUVsZW1lbnQgYXMgU2JiQ2FsZW5kYXJDZWxsQmFzZUVsZW1lbnQ8VD47XG4gICAgaWYgKG5leHRFbCAhPT0gYWN0aXZlRWwpIHtcbiAgICAgIG5leHRFbC50YWJJbmRleCA9IDA7XG4gICAgICBuZXh0RWw/LmZvY3VzKCk7XG4gICAgICBhY3RpdmVFbC50YWJJbmRleCA9IC0xO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX25hdmlnYXRlQnlLZXlib2FyZERheVZpZXcoXG4gICAgZXZ0OiBLZXlib2FyZEV2ZW50LFxuICAgIGluZGV4OiBudW1iZXIsXG4gICAgY2VsbHM6IFNiYkNhbGVuZGFyRGF5RWxlbWVudDxUPltdLFxuICAgIGRheTogRGF5PFQ+LFxuICApOiBTYmJDYWxlbmRhckRheUVsZW1lbnQ8VD4ge1xuICAgIGNvbnN0IGFycm93c09mZnNldCA9XG4gICAgICB0aGlzLm9yaWVudGF0aW9uID09PSAnaG9yaXpvbnRhbCdcbiAgICAgICAgPyB7IGxlZnRSaWdodDogMSwgdXBEb3duOiBEQVlTX1BFUl9ST1cgfVxuICAgICAgICA6IHsgbGVmdFJpZ2h0OiBEQVlTX1BFUl9ST1csIHVwRG93bjogMSB9O1xuICAgIGNvbnN0IG9mZnNldEZvclZlcnRpY2FsOiBudW1iZXIgPVxuICAgICAgaW5kZXggPCB0aGlzLl9rZXlib2FyZE5hdmlnYXRpb25EYXlWaWV3UGFyYW1ldGVycy5maXJzdE1vbnRoTGVuZ3RoXG4gICAgICAgID8gdGhpcy5fa2V5Ym9hcmROYXZpZ2F0aW9uRGF5Vmlld1BhcmFtZXRlcnMuZmlyc3RNb250aE9mZnNldFxuICAgICAgICA6IHRoaXMuX2tleWJvYXJkTmF2aWdhdGlvbkRheVZpZXdQYXJhbWV0ZXJzLnNlY29uZE1vbnRoT2Zmc2V0O1xuXG4gICAgc3dpdGNoIChldnQua2V5KSB7XG4gICAgICBjYXNlICdBcnJvd1VwJzpcbiAgICAgICAgcmV0dXJuIHRoaXMuX2ZpbmREYXlBcnJvd3MoY2VsbHMsIGluZGV4LCBkYXkuZGF0ZVZhbHVlLCAtYXJyb3dzT2Zmc2V0LnVwRG93bik7XG4gICAgICBjYXNlICdBcnJvd0Rvd24nOlxuICAgICAgICByZXR1cm4gdGhpcy5fZmluZERheUFycm93cyhjZWxscywgaW5kZXgsIGRheS5kYXRlVmFsdWUsIGFycm93c09mZnNldC51cERvd24pO1xuICAgICAgY2FzZSAnQXJyb3dMZWZ0JzpcbiAgICAgICAgcmV0dXJuIHRoaXMuX2ZpbmREYXlBcnJvd3MoY2VsbHMsIGluZGV4LCBkYXkuZGF0ZVZhbHVlLCAtYXJyb3dzT2Zmc2V0LmxlZnRSaWdodCk7XG4gICAgICBjYXNlICdBcnJvd1JpZ2h0JzpcbiAgICAgICAgcmV0dXJuIHRoaXMuX2ZpbmREYXlBcnJvd3MoY2VsbHMsIGluZGV4LCBkYXkuZGF0ZVZhbHVlLCBhcnJvd3NPZmZzZXQubGVmdFJpZ2h0KTtcbiAgICAgIGNhc2UgJ1BhZ2VVcCc6IHtcbiAgICAgICAgaWYgKHRoaXMub3JpZW50YXRpb24gPT09ICdob3Jpem9udGFsJykge1xuICAgICAgICAgIGNvbnN0IGZpcnN0T2ZXZWVrOiBudW1iZXIgPSArZGF5LmRheVZhbHVlICUgREFZU19QRVJfUk9XIHx8IERBWVNfUEVSX1JPVztcbiAgICAgICAgICBjb25zdCBkZWx0YTogbnVtYmVyID0gZmlyc3RPZldlZWsgLSArZGF5LmRheVZhbHVlO1xuICAgICAgICAgIHJldHVybiB0aGlzLl9maW5kRGF5UGFnZVVwRG93bihjZWxscywgaW5kZXgsIGRheSwgZGVsdGEsIGFycm93c09mZnNldC51cERvd24pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvbnN0IHdlZWtOdW1iZXI6IG51bWJlciA9IE1hdGguY2VpbCgoK2RheS5kYXlWYWx1ZSArIG9mZnNldEZvclZlcnRpY2FsKSAvIERBWVNfUEVSX1JPVyk7XG4gICAgICAgICAgY29uc3QgZmlyc3RPZldlZWs6IG51bWJlciA9ICh3ZWVrTnVtYmVyIC0gMSkgKiBEQVlTX1BFUl9ST1cgLSBvZmZzZXRGb3JWZXJ0aWNhbCArIDE7XG4gICAgICAgICAgY29uc3QgZGVsdGE6IG51bWJlciA9IGZpcnN0T2ZXZWVrIC0gK2RheS5kYXlWYWx1ZTtcbiAgICAgICAgICByZXR1cm4gdGhpcy5fZmluZERheVBhZ2VVcERvd24oY2VsbHMsIGluZGV4LCBkYXksIGRlbHRhLCBhcnJvd3NPZmZzZXQudXBEb3duKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgY2FzZSAnUGFnZURvd24nOiB7XG4gICAgICAgIGlmICh0aGlzLm9yaWVudGF0aW9uID09PSAnaG9yaXpvbnRhbCcpIHtcbiAgICAgICAgICBjb25zdCBtb250aEluQm91bmRzID0gK2RheS5tb250aFZhbHVlICsgMSA+IDEyID8gMSA6ICtkYXkubW9udGhWYWx1ZSArIDE7XG4gICAgICAgICAgY29uc3QgeWVhckluQm91bmRzID0gK2RheS5tb250aFZhbHVlICsgMSA+IDEyID8gK2RheS55ZWFyVmFsdWUgKyAxIDogK2RheS55ZWFyVmFsdWU7XG4gICAgICAgICAgY29uc3QgZmlyc3ROZXh0TW9udGg6IFQgPSB0aGlzLl9kYXRlQWRhcHRlci5jcmVhdGVEYXRlKHllYXJJbkJvdW5kcywgbW9udGhJbkJvdW5kcywgMSk7XG4gICAgICAgICAgY29uc3QgbGFzdE9mTW9udGg6IG51bWJlciA9IHRoaXMuX2RhdGVBZGFwdGVyLmdldERhdGUoXG4gICAgICAgICAgICB0aGlzLl9kYXRlQWRhcHRlci5hZGRDYWxlbmRhckRheXMoZmlyc3ROZXh0TW9udGgsIC0xKSxcbiAgICAgICAgICApO1xuICAgICAgICAgIGNvbnN0IGRlbHRhOiBudW1iZXIgPVxuICAgICAgICAgICAgTWF0aC50cnVuYygobGFzdE9mTW9udGggLSArZGF5LmRheVZhbHVlISkgLyBEQVlTX1BFUl9ST1cpICogREFZU19QRVJfUk9XO1xuICAgICAgICAgIHJldHVybiB0aGlzLl9maW5kRGF5UGFnZVVwRG93bihjZWxscywgaW5kZXgsIGRheSwgZGVsdGEsIC1hcnJvd3NPZmZzZXQudXBEb3duKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb25zdCB3ZWVrTnVtYmVyOiBudW1iZXIgPSBNYXRoLmNlaWwoKCtkYXkuZGF5VmFsdWUgKyBvZmZzZXRGb3JWZXJ0aWNhbCkgLyBEQVlTX1BFUl9ST1cpO1xuICAgICAgICAgIGNvbnN0IGxhc3RPZldlZWs6IG51bWJlciA9IHdlZWtOdW1iZXIgKiBEQVlTX1BFUl9ST1cgLSBvZmZzZXRGb3JWZXJ0aWNhbDtcbiAgICAgICAgICBjb25zdCBkZWx0YTogbnVtYmVyID0gbGFzdE9mV2VlayAtICtkYXkuZGF5VmFsdWU7XG4gICAgICAgICAgcmV0dXJuIHRoaXMuX2ZpbmREYXlQYWdlVXBEb3duKGNlbGxzLCBpbmRleCwgZGF5LCBkZWx0YSwgLWFycm93c09mZnNldC51cERvd24pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBjYXNlICdIb21lJzoge1xuICAgICAgICByZXR1cm4gdGhpcy5fZmluZERheUZpcnN0KGNlbGxzLCBpbmRleCwgZGF5LCAxKTtcbiAgICAgIH1cbiAgICAgIGNhc2UgJ0VuZCc6IHtcbiAgICAgICAgY29uc3QgbW9udGhJbkJvdW5kcyA9ICtkYXkubW9udGhWYWx1ZSArIDEgPiAxMiA/IDEgOiArZGF5Lm1vbnRoVmFsdWUgKyAxO1xuICAgICAgICBjb25zdCB5ZWFySW5Cb3VuZHMgPSArZGF5Lm1vbnRoVmFsdWUgKyAxID4gMTIgPyArZGF5LnllYXJWYWx1ZSArIDEgOiArZGF5LnllYXJWYWx1ZTtcbiAgICAgICAgY29uc3QgZmlyc3ROZXh0TW9udGg6IFQgPSB0aGlzLl9kYXRlQWRhcHRlci5jcmVhdGVEYXRlKHllYXJJbkJvdW5kcywgbW9udGhJbkJvdW5kcywgMSk7XG4gICAgICAgIHJldHVybiB0aGlzLl9maW5kRGF5TGFzdChjZWxscywgaW5kZXgsIGZpcnN0TmV4dE1vbnRoKTtcbiAgICAgIH1cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHJldHVybiBjZWxsc1tpbmRleF07XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfaXNEYXlPdXRPZlZpZXcoZGF0ZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIChcbiAgICAgIGRhdGUgPCB0aGlzLl9rZXlib2FyZE5hdmlnYXRpb25EYXlWaWV3UGFyYW1ldGVycy5maXJzdERheUluVmlldyEgfHxcbiAgICAgIGRhdGUgPiB0aGlzLl9rZXlib2FyZE5hdmlnYXRpb25EYXlWaWV3UGFyYW1ldGVycy5sYXN0RGF5SW5WaWV3IVxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIF9maW5kRGF5QXJyb3dzKFxuICAgIGNlbGxzOiBTYmJDYWxlbmRhckRheUVsZW1lbnQ8VD5bXSxcbiAgICBpbmRleDogbnVtYmVyLFxuICAgIGRhdGU6IFQsXG4gICAgZGVsdGE6IG51bWJlcixcbiAgKTogU2JiQ2FsZW5kYXJEYXlFbGVtZW50PFQ+IHtcbiAgICBjb25zdCBuZXdEYXRlVmFsdWUgPSB0aGlzLl9kYXRlQWRhcHRlci50b0lzbzg2MDEoXG4gICAgICB0aGlzLl9kYXRlQWRhcHRlci5hZGRDYWxlbmRhckRheXMoZGF0ZSwgZGVsdGEpLFxuICAgICk7XG4gICAgaWYgKHRoaXMuX2lzRGF5T3V0T2ZWaWV3KG5ld0RhdGVWYWx1ZSkpIHtcbiAgICAgIHJldHVybiBjZWxsc1tpbmRleF07XG4gICAgfVxuICAgIGNvbnN0IG5leHRDZWxsID0gY2VsbHMuZmluZCgoZSkgPT4gdGhpcy5fbWFwVmFsdWVUb0lTT0RhdGUoZS52YWx1ZSEpID09PSBuZXdEYXRlVmFsdWUpO1xuICAgIGlmICghbmV4dENlbGwgfHwgbmV4dENlbGwuZGlzYWJsZWQpIHtcbiAgICAgIHJldHVybiB0aGlzLl9maW5kRGF5QXJyb3dzKGNlbGxzLCBpbmRleCwgdGhpcy5fZGF0ZUFkYXB0ZXIuZGVzZXJpYWxpemUobmV3RGF0ZVZhbHVlKSEsIGRlbHRhKTtcbiAgICB9XG4gICAgcmV0dXJuIG5leHRDZWxsO1xuICB9XG5cbiAgcHJpdmF0ZSBfZmluZERheVBhZ2VVcERvd24oXG4gICAgY2VsbHM6IFNiYkNhbGVuZGFyRGF5RWxlbWVudDxUPltdLFxuICAgIGluZGV4OiBudW1iZXIsXG4gICAgZGF5OiBEYXk8VD4sXG4gICAgZGVsdGE6IG51bWJlcixcbiAgICBkZWx0YUlmRGlzYWJsZWQ6IG51bWJlcixcbiAgKTogU2JiQ2FsZW5kYXJEYXlFbGVtZW50PFQ+IHtcbiAgICBjb25zdCBuZXdEYXRlVmFsdWUgPSB0aGlzLl9kYXRlQWRhcHRlci50b0lzbzg2MDEoXG4gICAgICB0aGlzLl9kYXRlQWRhcHRlci5hZGRDYWxlbmRhckRheXMoZGF5LmRhdGVWYWx1ZSwgZGVsdGEpLFxuICAgICk7XG4gICAgaWYgKHRoaXMuX2lzRGF5T3V0T2ZWaWV3KG5ld0RhdGVWYWx1ZSkpIHtcbiAgICAgIHJldHVybiBjZWxsc1tpbmRleF07XG4gICAgfVxuICAgIGNvbnN0IG5leHRDZWxsID0gY2VsbHMuZmluZCgoZSkgPT4gdGhpcy5fbWFwVmFsdWVUb0lTT0RhdGUoZS52YWx1ZSEpID09PSBuZXdEYXRlVmFsdWUpO1xuICAgIGlmICghbmV4dENlbGwgfHwgbmV4dENlbGwuZGlzYWJsZWQpIHtcbiAgICAgIHJldHVybiB0aGlzLl9maW5kRGF5UGFnZVVwRG93bihjZWxscywgaW5kZXgsIGRheSwgZGVsdGEgKyBkZWx0YUlmRGlzYWJsZWQsIGRlbHRhSWZEaXNhYmxlZCk7XG4gICAgfVxuICAgIHJldHVybiBuZXh0Q2VsbDtcbiAgfVxuXG4gIHByaXZhdGUgX2ZpbmREYXlGaXJzdChcbiAgICBjZWxsczogU2JiQ2FsZW5kYXJEYXlFbGVtZW50PFQ+W10sXG4gICAgaW5kZXg6IG51bWJlcixcbiAgICBkYXk6IERheTxUPixcbiAgICBkYXRlOiBudW1iZXIsXG4gICk6IFNiYkNhbGVuZGFyRGF5RWxlbWVudDxUPiB7XG4gICAgY29uc3QgbmV3RGF0ZVZhbHVlID0gdGhpcy5fZGF0ZUFkYXB0ZXIudG9Jc284NjAxKFxuICAgICAgdGhpcy5fZGF0ZUFkYXB0ZXIuY3JlYXRlRGF0ZSgrZGF5LnllYXJWYWx1ZSwgK2RheS5tb250aFZhbHVlLCBkYXRlKSxcbiAgICApO1xuICAgIGlmICh0aGlzLl9pc0RheU91dE9mVmlldyhuZXdEYXRlVmFsdWUpKSB7XG4gICAgICByZXR1cm4gY2VsbHNbaW5kZXhdO1xuICAgIH1cbiAgICBjb25zdCBuZXh0Q2VsbCA9IGNlbGxzLmZpbmQoKGUpID0+IHRoaXMuX21hcFZhbHVlVG9JU09EYXRlKGUudmFsdWUhKSA9PT0gbmV3RGF0ZVZhbHVlKTtcbiAgICBpZiAoIW5leHRDZWxsIHx8IG5leHRDZWxsLmRpc2FibGVkKSB7XG4gICAgICByZXR1cm4gdGhpcy5fZmluZERheUZpcnN0KGNlbGxzLCBpbmRleCwgZGF5LCBkYXRlICsgMSk7XG4gICAgfVxuICAgIHJldHVybiBuZXh0Q2VsbDtcbiAgfVxuXG4gIHByaXZhdGUgX2ZpbmREYXlMYXN0KFxuICAgIGNlbGxzOiBTYmJDYWxlbmRhckRheUVsZW1lbnQ8VD5bXSxcbiAgICBpbmRleDogbnVtYmVyLFxuICAgIGZpcnN0TmV4dE1vbnRoOiBULFxuICApOiBTYmJDYWxlbmRhckRheUVsZW1lbnQ8VD4ge1xuICAgIGNvbnN0IG5ld0RhdGVWYWx1ZSA9IHRoaXMuX2RhdGVBZGFwdGVyLnRvSXNvODYwMShcbiAgICAgIHRoaXMuX2RhdGVBZGFwdGVyLmFkZENhbGVuZGFyRGF5cyhmaXJzdE5leHRNb250aCwgLTEpLFxuICAgICk7XG4gICAgaWYgKHRoaXMuX2lzRGF5T3V0T2ZWaWV3KG5ld0RhdGVWYWx1ZSkpIHtcbiAgICAgIHJldHVybiBjZWxsc1tpbmRleF07XG4gICAgfVxuICAgIGNvbnN0IG5leHRDZWxsID0gY2VsbHMuZmluZCgoZSkgPT4gdGhpcy5fbWFwVmFsdWVUb0lTT0RhdGUoZS52YWx1ZSEpID09PSBuZXdEYXRlVmFsdWUpO1xuICAgIGlmICghbmV4dENlbGwgfHwgbmV4dENlbGwuZGlzYWJsZWQpIHtcbiAgICAgIHJldHVybiB0aGlzLl9maW5kRGF5TGFzdChjZWxscywgaW5kZXgsIHRoaXMuX2RhdGVBZGFwdGVyLmRlc2VyaWFsaXplKG5ld0RhdGVWYWx1ZSkhKTtcbiAgICB9XG4gICAgcmV0dXJuIG5leHRDZWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIG1vdmUgdG8sIGJhc2VkIG9uIGEgbGlzdCBvZiBlbGVtZW50cyAod2hpY2ggY2FuIGJlIHBvdGVudGlhbGx5IGRpc2FibGVkKSxcbiAgICogdGhlIGtleWJvYXJkIGlucHV0IGFuZCB0aGUgcG9zaXRpb24gb2YgdGhlIGN1cnJlbnQgZWxlbWVudCBpbiB0aGUgbGlzdC5cbiAgICogSW4gdGhlIGRheSB2aWV3LCB0aGUgYGRheT86IERheWAgcGFyYW1ldGVyIGlzIG1hbmRhdG9yeSBmb3IgY2FsY3VsYXRpb24sXG4gICAqIHdoaWxlIGluIG1vbnRoIGFuZCB5ZWFyIHZpZXcgaXQncyBub3QgZHVlIHRvIHRoZSBmaXhlZCBhbW91bnQgb2YgcmVuZGVyZWQgY2VsbHMuXG4gICAqL1xuICBwcml2YXRlIF9uYXZpZ2F0ZUJ5S2V5Ym9hcmQoXG4gICAgZXZ0OiBLZXlib2FyZEV2ZW50LFxuICAgIGluZGV4OiBudW1iZXIsXG4gICAgY2VsbHM6IFNiYkNhbGVuZGFyQ2VsbEJhc2VFbGVtZW50PFQ+W10sXG4gICk6IFNiYkNhbGVuZGFyQ2VsbEJhc2VFbGVtZW50PFQ+IHtcbiAgICBjb25zdCB7XG4gICAgICBlbGVtZW50SW5kZXhGb3JXaWRlTW9kZSxcbiAgICAgIG9mZnNldEZvcldpZGVNb2RlLFxuICAgICAgbGFzdEVsZW1lbnRJbmRleEZvcldpZGVNb2RlLFxuICAgICAgdmVydGljYWxPZmZzZXQsXG4gICAgfTogQ2FsZW5kYXJLZXlib2FyZE5hdmlnYXRpb25Nb250aFllYXJWaWV3c1BhcmFtZXRlcnMgPVxuICAgICAgdGhpcy5fY2FsY3VsYXRlUGFyYW1ldGVyc0ZvcktleWJvYXJkTmF2aWdhdGlvbihpbmRleCwgdGhpcy5fY2FsZW5kYXJWaWV3ID09PSAneWVhcicpO1xuXG4gICAgc3dpdGNoIChldnQua2V5KSB7XG4gICAgICBjYXNlICdBcnJvd1VwJzpcbiAgICAgICAgcmV0dXJuIHRoaXMuX2ZpbmROZXh0KGNlbGxzLCBpbmRleCwgLXZlcnRpY2FsT2Zmc2V0KTtcbiAgICAgIGNhc2UgJ0Fycm93RG93bic6XG4gICAgICAgIHJldHVybiB0aGlzLl9maW5kTmV4dChjZWxscywgaW5kZXgsIHZlcnRpY2FsT2Zmc2V0KTtcbiAgICAgIGNhc2UgJ0Fycm93TGVmdCc6XG4gICAgICAgIHJldHVybiB0aGlzLl9maW5kTmV4dChjZWxscywgaW5kZXgsIC0xKTtcbiAgICAgIGNhc2UgJ0Fycm93UmlnaHQnOlxuICAgICAgICByZXR1cm4gdGhpcy5fZmluZE5leHQoY2VsbHMsIGluZGV4LCAxKTtcbiAgICAgIGNhc2UgJ0hvbWUnOlxuICAgICAgICByZXR1cm4gdGhpcy5fZmluZEZpcnN0KGNlbGxzLCBvZmZzZXRGb3JXaWRlTW9kZSk7XG4gICAgICBjYXNlICdQYWdlVXAnOlxuICAgICAgICByZXR1cm4gdGhpcy5fZmluZEZpcnN0T25Db2x1bW4oXG4gICAgICAgICAgY2VsbHMsXG4gICAgICAgICAgZWxlbWVudEluZGV4Rm9yV2lkZU1vZGUsXG4gICAgICAgICAgb2Zmc2V0Rm9yV2lkZU1vZGUsXG4gICAgICAgICAgdmVydGljYWxPZmZzZXQsXG4gICAgICAgICk7XG4gICAgICBjYXNlICdQYWdlRG93bic6XG4gICAgICAgIHJldHVybiB0aGlzLl9maW5kTGFzdE9uQ29sdW1uKGNlbGxzLCBpbmRleCwgbGFzdEVsZW1lbnRJbmRleEZvcldpZGVNb2RlLCB2ZXJ0aWNhbE9mZnNldCk7XG4gICAgICBjYXNlICdFbmQnOlxuICAgICAgICByZXR1cm4gdGhpcy5fZmluZExhc3QoY2VsbHMsIGxhc3RFbGVtZW50SW5kZXhGb3JXaWRlTW9kZSAtIDEpO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcmV0dXJuIGNlbGxzW2luZGV4XTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ2FsY3VsYXRlcyB0aGUgcGFyYW1ldGVycyBuZWVkZWQgaW4ga2V5Ym9hcmQgbmF2aWdhdGlvbiBpbiB5ZWFyIGFuZCBtb250aCB2aWV3LlxuICAgKiBAcGFyYW0gaW5kZXggVGhlIHN0YXJ0aW5nIGVsZW1lbnQncyBpbmRleCBpbiB0aGUgY2VsbCBhcnJheS5cbiAgICogQHBhcmFtIGlzWWVhclZpZXcgV2hldGhlciB0aGUgZGlzcGxheWVkIGB2aWV3YCBpcyB0aGUgeWVhciBvbmUuXG4gICAqL1xuICBwcml2YXRlIF9jYWxjdWxhdGVQYXJhbWV0ZXJzRm9yS2V5Ym9hcmROYXZpZ2F0aW9uKFxuICAgIGluZGV4OiBudW1iZXIsXG4gICAgaXNZZWFyVmlldzogYm9vbGVhbixcbiAgKTogQ2FsZW5kYXJLZXlib2FyZE5hdmlnYXRpb25Nb250aFllYXJWaWV3c1BhcmFtZXRlcnMge1xuICAgIGNvbnN0IGVsZW1lbnRzUGVyUGFnZSA9IGlzWWVhclZpZXcgPyBZRUFSU19QRVJfUEFHRSA6IE1PTlRIU19QRVJfUEFHRTtcbiAgICBjb25zdCBvZmZzZXQ6IG51bWJlciA9IE1hdGgudHJ1bmMoaW5kZXggLyBlbGVtZW50c1BlclBhZ2UpICogZWxlbWVudHNQZXJQYWdlO1xuICAgIGNvbnN0IGluZGV4SW5WaWV3OiBudW1iZXIgPSBvZmZzZXQgPT09IDAgPyBpbmRleCA6IGluZGV4IC0gZWxlbWVudHNQZXJQYWdlO1xuICAgIHJldHVybiB7XG4gICAgICB2ZXJ0aWNhbE9mZnNldDogaXNZZWFyVmlldyA/IFlFQVJTX1BFUl9ST1cgOiBNT05USFNfUEVSX1JPVyxcbiAgICAgIGVsZW1lbnRJbmRleEZvcldpZGVNb2RlOiBpbmRleEluVmlldyxcbiAgICAgIG9mZnNldEZvcldpZGVNb2RlOiBpbmRleCAtIGluZGV4SW5WaWV3LFxuICAgICAgbGFzdEVsZW1lbnRJbmRleEZvcldpZGVNb2RlOiBvZmZzZXQgPT09IDAgPyBlbGVtZW50c1BlclBhZ2UgOiBlbGVtZW50c1BlclBhZ2UgKiAyLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgbmV4dCBlbGVtZW50IG9mIHRoZSBwcm92aWRlZCBhcnJheSBzdGFydGluZyBmcm9tIGBpbmRleGAgYnkgYWRkaW5nIGBkZWx0YWAuXG4gICAqIElmIHRoZSBmb3VuZCBlbGVtZW50IGlzIGRpc2FibGVkLCBpdCBjb250aW51ZXMgYWRkaW5nIGBkZWx0YWAgdW50aWwgaXQgZmluZHMgYW4gZW5hYmxlZCBvbmUgaW4gdGhlIGFycmF5IGJvdW5kcy5cbiAgICovXG4gIHByaXZhdGUgX2ZpbmROZXh0KFxuICAgIGRheXM6IFNiYkNhbGVuZGFyQ2VsbEJhc2VFbGVtZW50PFQ+W10sXG4gICAgaW5kZXg6IG51bWJlcixcbiAgICBkZWx0YTogbnVtYmVyLFxuICApOiBTYmJDYWxlbmRhckNlbGxCYXNlRWxlbWVudDxUPiB7XG4gICAgbGV0IG5leHRJbmRleCA9IGluZGV4ICsgZGVsdGE7XG4gICAgd2hpbGUgKG5leHRJbmRleCA8IGRheXMubGVuZ3RoICYmIGRheXNbbmV4dEluZGV4XT8uZGlzYWJsZWQpIHtcbiAgICAgIG5leHRJbmRleCArPSBkZWx0YTtcbiAgICB9XG4gICAgcmV0dXJuIGRheXNbbmV4dEluZGV4XSA/PyBkYXlzW2luZGV4XTtcbiAgfVxuXG4gIC8qKiBGaW5kIHRoZSBmaXJzdCBlbmFibGVkIGVsZW1lbnQgaW4gdGhlIHByb3ZpZGVkIGFycmF5LiAqL1xuICBwcml2YXRlIF9maW5kRmlyc3QoXG4gICAgZGF5czogU2JiQ2FsZW5kYXJDZWxsQmFzZUVsZW1lbnQ8VD5bXSxcbiAgICBmaXJzdE9mQ3VycmVudE1vbnRoOiBudW1iZXIsXG4gICk6IFNiYkNhbGVuZGFyQ2VsbEJhc2VFbGVtZW50PFQ+IHtcbiAgICByZXR1cm4gIWRheXNbZmlyc3RPZkN1cnJlbnRNb250aF0uZGlzYWJsZWRcbiAgICAgID8gZGF5c1tmaXJzdE9mQ3VycmVudE1vbnRoXVxuICAgICAgOiB0aGlzLl9maW5kTmV4dChkYXlzLCBmaXJzdE9mQ3VycmVudE1vbnRoLCAxKTtcbiAgfVxuXG4gIC8qKiBGaW5kIHRoZSBsYXN0IGVuYWJsZWQgZWxlbWVudCBpbiB0aGUgcHJvdmlkZWQgYXJyYXkuICovXG4gIHByaXZhdGUgX2ZpbmRMYXN0KFxuICAgIGRheXM6IFNiYkNhbGVuZGFyQ2VsbEJhc2VFbGVtZW50PFQ+W10sXG4gICAgbGFzdE9mQ3VycmVudE1vbnRoOiBudW1iZXIsXG4gICk6IFNiYkNhbGVuZGFyQ2VsbEJhc2VFbGVtZW50PFQ+IHtcbiAgICByZXR1cm4gIWRheXNbbGFzdE9mQ3VycmVudE1vbnRoXS5kaXNhYmxlZFxuICAgICAgPyBkYXlzW2xhc3RPZkN1cnJlbnRNb250aF1cbiAgICAgIDogdGhpcy5fZmluZE5leHQoZGF5cywgbGFzdE9mQ3VycmVudE1vbnRoLCAtMSk7XG4gIH1cblxuICAvKiogRmluZCB0aGUgZmlyc3QgZW5hYmxlZCBlbGVtZW50IGluIHRoZSBzYW1lIGNvbHVtbiBvZiB0aGUgcHJvdmlkZWQgYXJyYXkuICovXG4gIHByaXZhdGUgX2ZpbmRGaXJzdE9uQ29sdW1uKFxuICAgIGRheXM6IFNiYkNhbGVuZGFyQ2VsbEJhc2VFbGVtZW50PFQ+W10sXG4gICAgaW5kZXg6IG51bWJlcixcbiAgICBvZmZzZXQ6IG51bWJlcixcbiAgICB2ZXJ0aWNhbE9mZnNldDogbnVtYmVyLFxuICApOiBTYmJDYWxlbmRhckNlbGxCYXNlRWxlbWVudDxUPiB7XG4gICAgY29uc3QgbmV4dEluZGV4ID0gKGluZGV4ICUgdmVydGljYWxPZmZzZXQpICsgb2Zmc2V0O1xuICAgIHJldHVybiAhZGF5c1tuZXh0SW5kZXhdLmRpc2FibGVkXG4gICAgICA/IGRheXNbbmV4dEluZGV4XVxuICAgICAgOiB0aGlzLl9maW5kTmV4dChkYXlzLCBuZXh0SW5kZXgsIHZlcnRpY2FsT2Zmc2V0KTtcbiAgfVxuXG4gIC8qKiBGaW5kIHRoZSBsYXN0IGVuYWJsZWQgZWxlbWVudCBpbiB0aGUgc2FtZSBjb2x1bW4gb2YgdGhlIHByb3ZpZGVkIGFycmF5LiAqL1xuICBwcml2YXRlIF9maW5kTGFzdE9uQ29sdW1uKFxuICAgIGRheXM6IFNiYkNhbGVuZGFyQ2VsbEJhc2VFbGVtZW50PFQ+W10sXG4gICAgaW5kZXg6IG51bWJlcixcbiAgICBvZmZzZXQ6IG51bWJlcixcbiAgICB2ZXJ0aWNhbE9mZnNldDogbnVtYmVyLFxuICApOiBTYmJDYWxlbmRhckNlbGxCYXNlRWxlbWVudDxUPiB7XG4gICAgY29uc3QgbmV4dEluZGV4ID0gaW5kZXggKyBNYXRoLnRydW5jKChvZmZzZXQgLSBpbmRleCAtIDEpIC8gdmVydGljYWxPZmZzZXQpICogdmVydGljYWxPZmZzZXQ7XG4gICAgcmV0dXJuICFkYXlzW25leHRJbmRleF0uZGlzYWJsZWRcbiAgICAgID8gZGF5c1tuZXh0SW5kZXhdXG4gICAgICA6IHRoaXMuX2ZpbmROZXh0KGRheXMsIG5leHRJbmRleCwgLXZlcnRpY2FsT2Zmc2V0KTtcbiAgfVxuXG4gIHByaXZhdGUgX3Jlc2V0Q2FsZW5kYXJWaWV3QW5kRW1pdE1vbnRoQ2hhbmdlKGluaXRUcmFuc2l0aW9uID0gZmFsc2UpOiB2b2lkIHtcbiAgICB0aGlzLl9yZXNldENhbGVuZGFyVmlldyhpbml0VHJhbnNpdGlvbik7XG4gICAgdGhpcy5fZW1pdE1vbnRoQ2hhbmdlKCk7XG4gIH1cblxuICBwcml2YXRlIF9yZXNldENhbGVuZGFyVmlldyhpbml0VHJhbnNpdGlvbiA9IGZhbHNlKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuX2NvbnRhaW5pbmdGb2N1cykge1xuICAgICAgdGhpcy5fcmVzZXRGb2N1cyA9IHRydWU7XG4gICAgfVxuICAgIHRoaXMuX2FjdGl2ZURhdGUgPVxuICAgICAgKHRoaXMubXVsdGlwbGUgPyAodGhpcy5fc2VsZWN0ZWQgYXMgVFtdKS5hdCgtMSkgOiAodGhpcy5fc2VsZWN0ZWQgYXMgVCkpID8/XG4gICAgICB0aGlzLl9kYXRlQWRhcHRlci50b2RheSgpO1xuICAgIHRoaXMuX3NldENob3NlblllYXIoKTtcbiAgICB0aGlzLl9jaG9zZW5Nb250aCA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLl9pbml0KCk7XG4gICAgdGhpcy5fbmV4dENhbGVuZGFyVmlldyA9IHRoaXMuX2NhbGVuZGFyVmlldyA9IHRoaXMudmlldztcblxuICAgIGlmIChpbml0VHJhbnNpdGlvbikge1xuICAgICAgdGhpcy5fc3RhcnRUYWJsZVRyYW5zaXRpb24oKTtcbiAgICB9XG4gIH1cblxuICAvKiogUmVuZGVyIHRoZSB2aWV3IGZvciB0aGUgZGF5IHNlbGVjdGlvbi4gKi9cbiAgcHJpdmF0ZSBfcmVuZGVyRGF5VmlldygpOiBUZW1wbGF0ZVJlc3VsdCB7XG4gICAgY29uc3QgbmV4dE1vbnRoQWN0aXZlRGF0ZSA9IHRoaXMuX3dpZGVcbiAgICAgID8gdGhpcy5fZGF0ZUFkYXB0ZXIuYWRkQ2FsZW5kYXJNb250aHModGhpcy5fYWN0aXZlRGF0ZSwgMSlcbiAgICAgIDogdW5kZWZpbmVkO1xuICAgIHJldHVybiBodG1sYFxuICAgICAgPGRpdiBjbGFzcz1cInNiYi1jYWxlbmRhcl9fY29udHJvbHNcIj5cbiAgICAgICAgJHt0aGlzLl9nZXRBcnJvdyhcbiAgICAgICAgICAnbGVmdCcsXG4gICAgICAgICAgKCkgPT4gdGhpcy5fZ29Ub0RpZmZlcmVudE1vbnRoKC0xKSxcbiAgICAgICAgICBpMThuUHJldmlvdXNNb250aFt0aGlzLl9sYW5ndWFnZS5jdXJyZW50XSxcbiAgICAgICAgICB0aGlzLl9wcmV2aW91c01vbnRoRGlzYWJsZWQoKSxcbiAgICAgICAgKX1cbiAgICAgICAgPGRpdiBjbGFzcz1cInNiYi1jYWxlbmRhcl9fY29udHJvbHMtbW9udGhcIj5cbiAgICAgICAgICAke3RoaXMuX2NyZWF0ZUxhYmVsRm9yRGF5Vmlldyh0aGlzLl9hY3RpdmVEYXRlKX1cbiAgICAgICAgICAke3RoaXMuX3dpZGUgPyB0aGlzLl9jcmVhdGVMYWJlbEZvckRheVZpZXcobmV4dE1vbnRoQWN0aXZlRGF0ZSEpIDogbm90aGluZ31cbiAgICAgICAgICA8c3BhbiBjbGFzcz1cInNiYi1zY3JlZW4tcmVhZGVyLW9ubHlcIiByb2xlPVwic3RhdHVzXCI+XG4gICAgICAgICAgICAke3RoaXMuX2NyZWF0ZUFyaWFMYWJlbEZvckRheVZpZXcodGhpcy5fYWN0aXZlRGF0ZSwgbmV4dE1vbnRoQWN0aXZlRGF0ZSEpfVxuICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgICR7dGhpcy5fZ2V0QXJyb3coXG4gICAgICAgICAgJ3JpZ2h0JyxcbiAgICAgICAgICAoKSA9PiB0aGlzLl9nb1RvRGlmZmVyZW50TW9udGgoMSksXG4gICAgICAgICAgaTE4bk5leHRNb250aFt0aGlzLl9sYW5ndWFnZS5jdXJyZW50XSxcbiAgICAgICAgICB0aGlzLl9uZXh0TW9udGhEaXNhYmxlZCgpLFxuICAgICAgICApfVxuICAgICAgPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwic2JiLWNhbGVuZGFyX190YWJsZS1vdmVyZmxvdy1icmVha1wiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwic2JiLWNhbGVuZGFyX190YWJsZS1jb250YWluZXIgc2JiLWNhbGVuZGFyX190YWJsZS1kYXktdmlld1wiPlxuICAgICAgICAgICR7dGhpcy5vcmllbnRhdGlvbiA9PT0gJ2hvcml6b250YWwnXG4gICAgICAgICAgICA/IGh0bWxgXG4gICAgICAgICAgICAgICAgJHt0aGlzLl9jcmVhdGVEYXlUYWJsZSh0aGlzLl93ZWVrcywgdGhpcy5fd2Vla051bWJlcnMpfVxuICAgICAgICAgICAgICAgICR7dGhpcy5fd2lkZVxuICAgICAgICAgICAgICAgICAgPyB0aGlzLl9jcmVhdGVEYXlUYWJsZSh0aGlzLl9uZXh0TW9udGhXZWVrcywgdGhpcy5fbmV4dE1vbnRoV2Vla051bWJlcnMsIHRydWUpXG4gICAgICAgICAgICAgICAgICA6IG5vdGhpbmd9XG4gICAgICAgICAgICAgIGBcbiAgICAgICAgICAgIDogaHRtbGBcbiAgICAgICAgICAgICAgICAke3RoaXMuX2NyZWF0ZURheVRhYmxlVmVydGljYWwodGhpcy5fd2Vla3MsIHRoaXMuX3dlZWtOdW1iZXJzKX1cbiAgICAgICAgICAgICAgICAke3RoaXMuX3dpZGVcbiAgICAgICAgICAgICAgICAgID8gdGhpcy5fY3JlYXRlRGF5VGFibGVWZXJ0aWNhbChcbiAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9uZXh0TW9udGhXZWVrcyxcbiAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9uZXh0TW9udGhXZWVrTnVtYmVycyxcbiAgICAgICAgICAgICAgICAgICAgICBuZXh0TW9udGhBY3RpdmVEYXRlLFxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICA6IG5vdGhpbmd9XG4gICAgICAgICAgICAgIGB9XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgYDtcbiAgfVxuXG4gIC8qKiBDcmVhdGVzIHRoZSBsYWJlbCB3aXRoIHRoZSBtb250aCBmb3IgdGhlIGRhaWx5IHZpZXcuICovXG4gIHByaXZhdGUgX2NyZWF0ZUxhYmVsRm9yRGF5VmlldyhkOiBUKTogVGVtcGxhdGVSZXN1bHQge1xuICAgIGNvbnN0IG1vbnRoTGFiZWwgPSBgJHtcbiAgICAgIHRoaXMuX21vbnRoTmFtZXNbdGhpcy5fZGF0ZUFkYXB0ZXIuZ2V0TW9udGgoZCkgLSAxXVxuICAgIH0gJHt0aGlzLl9kYXRlQWRhcHRlci5nZXRZZWFyKGQpfWA7XG4gICAgcmV0dXJuIGh0bWxgXG4gICAgICA8YnV0dG9uXG4gICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICBjbGFzcz1cInNiYi1jYWxlbmRhcl9fZGF0ZS1zZWxlY3Rpb24gc2JiLWNhbGVuZGFyX19jb250cm9scy1jaGFuZ2UtZGF0ZVwiXG4gICAgICAgIGFyaWEtbGFiZWw9XCIke2kxOG5ZZWFyTW9udGhTZWxlY3Rpb25bdGhpcy5fbGFuZ3VhZ2UuY3VycmVudF19ICR7bW9udGhMYWJlbH1cIlxuICAgICAgICBAY2xpY2s9JHsoKSA9PiB7XG4gICAgICAgICAgdGhpcy5fcmVzZXRGb2N1cyA9IHRydWU7XG4gICAgICAgICAgdGhpcy5fbmV4dENhbGVuZGFyVmlldyA9ICd5ZWFyJztcbiAgICAgICAgICB0aGlzLl9zdGFydFRhYmxlVHJhbnNpdGlvbigpO1xuICAgICAgICB9fVxuICAgICAgPlxuICAgICAgICAke21vbnRoTGFiZWx9XG4gICAgICAgIDxzYmItaWNvbiBuYW1lPVwiY2hldnJvbi1zbWFsbC1kb3duLXNtYWxsXCI+PC9zYmItaWNvbj5cbiAgICAgIDwvYnV0dG9uPlxuICAgIGA7XG4gIH1cblxuICAvKiogQ3JlYXRlcyB0aGUgYXJpYS1sYWJlbCBmb3IgdGhlIGRhaWx5IHZpZXcuICovXG4gIHByaXZhdGUgX2NyZWF0ZUFyaWFMYWJlbEZvckRheVZpZXcoLi4uZGF0ZXM6IFRbXSk6IHN0cmluZyB7XG4gICAgbGV0IG1vbnRoTGFiZWwgPSAnJztcbiAgICBmb3IgKGNvbnN0IGQgb2YgZGF0ZXMpIHtcbiAgICAgIGlmIChkKSB7XG4gICAgICAgIG1vbnRoTGFiZWwgKz0gYCR7XG4gICAgICAgICAgdGhpcy5fbW9udGhOYW1lc1t0aGlzLl9kYXRlQWRhcHRlci5nZXRNb250aChkKSAtIDFdXG4gICAgICAgIH0gJHt0aGlzLl9kYXRlQWRhcHRlci5nZXRZZWFyKGQpfSBgO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbW9udGhMYWJlbDtcbiAgfVxuXG4gIC8qKiBDcmVhdGVzIHRoZSBjYWxlbmRhciB0YWJsZSBmb3IgdGhlIGRhaWx5IHZpZXcuICovXG4gIHByaXZhdGUgX2NyZWF0ZURheVRhYmxlKFxuICAgIHdlZWtzOiBEYXk8VD5bXVtdLFxuICAgIHdlZWtOdW1iZXJzOiBudW1iZXJbXSxcbiAgICBpc1dpZGVOZXh0TW9udGg6IGJvb2xlYW4gPSBmYWxzZSxcbiAgKTogVGVtcGxhdGVSZXN1bHQge1xuICAgIGNvbnN0IHdlZWtzRm9yU2VsZWN0TXVsdGlwbGVXZWVrTnVtYmVyczogRGF5PFQ+W10gPSAoXG4gICAgICB0aGlzLl93aWRlXG4gICAgICAgID8gWy4uLnRoaXMuX3dlZWtzLCAuLi50aGlzLl9uZXh0TW9udGhXZWVrc11cbiAgICAgICAgOiBpc1dpZGVOZXh0TW9udGhcbiAgICAgICAgICA/IHRoaXMuX25leHRNb250aFdlZWtzXG4gICAgICAgICAgOiB0aGlzLl93ZWVrc1xuICAgICkuZmxhdCgpO1xuICAgIGNvbnN0IHdlZWtzRm9yU2VsZWN0TXVsdGlwbGVXZWVrRGF5czogRGF5PFQ+W10gPSAoXG4gICAgICBpc1dpZGVOZXh0TW9udGggPyB0aGlzLl9uZXh0TW9udGhXZWVrcyA6IHRoaXMuX3dlZWtzXG4gICAgKS5mbGF0KCk7XG4gICAgcmV0dXJuIGh0bWxgXG4gICAgICA8dGFibGVcbiAgICAgICAgY2xhc3M9XCJzYmItY2FsZW5kYXJfX3RhYmxlXCJcbiAgICAgICAgQGZvY3Vzb3V0PSR7KGV2ZW50OiBGb2N1c0V2ZW50KSA9PlxuICAgICAgICAgIHRoaXMuX2hhbmRsZVRhYmxlQmx1cihldmVudC5yZWxhdGVkVGFyZ2V0IGFzIEhUTUxFbGVtZW50KX1cbiAgICAgICAgQGFuaW1hdGlvbmVuZD0keyhlOiBBbmltYXRpb25FdmVudCkgPT4gdGhpcy5fdGFibGVBbmltYXRpb25FbmQoZSl9XG4gICAgICA+XG4gICAgICAgIDx0aGVhZCBjbGFzcz1cInNiYi1jYWxlbmRhcl9fdGFibGUtaGVhZGVyXCI+XG4gICAgICAgICAgPHRyPlxuICAgICAgICAgICAgJHt0aGlzLndlZWtOdW1iZXJzID8gaHRtbGA8dGggY2xhc3M9XCJzYmItY2FsZW5kYXJfX3RhYmxlLWhlYWRlci1jZWxsXCI+PC90aD5gIDogbm90aGluZ31cbiAgICAgICAgICAgICR7dGhpcy5fd2Vla2RheXMubWFwKFxuICAgICAgICAgICAgICAod2Vla0RheTogV2Vla2RheSwgaW5kZXg6IG51bWJlcikgPT4gaHRtbGBcbiAgICAgICAgICAgICAgICA8dGggY2xhc3M9XCJzYmItY2FsZW5kYXJfX3RhYmxlLWhlYWRlci1jZWxsXCI+XG4gICAgICAgICAgICAgICAgICAke3RoaXMubXVsdGlwbGVcbiAgICAgICAgICAgICAgICAgICAgPyBodG1sYFxuICAgICAgICAgICAgICAgICAgICAgICAgPHNiYi1jYWxlbmRhci13ZWVrZGF5XG4gICAgICAgICAgICAgICAgICAgICAgICAgIC52YWx1ZT0ke3dlZWtEYXl9XG4gICAgICAgICAgICAgICAgICAgICAgICAgIEBjbGljaz0keygpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBOT1RFOiBTdW5kYXlzIGhhdmUgaW5kZXggNywgd2hpbGUgdGhlaXIgd2Vla0RheVZhbHVlIGlzIDBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkYXlzOiBEYXk8VD5bXSA9IHdlZWtzRm9yU2VsZWN0TXVsdGlwbGVXZWVrRGF5cy5maWx0ZXIoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoZGF5OiBEYXk8VD4pID0+IGRheS53ZWVrRGF5VmFsdWUgPT09IChpbmRleCArIDEpICUgNyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApITtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZWxlY3RNdWx0aXBsZURhdGVzKGRheXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICB9fVxuICAgICAgICAgICAgICAgICAgICAgICAgPjwvc2JiLWNhbGVuZGFyLXdlZWtkYXk+XG4gICAgICAgICAgICAgICAgICAgICAgYFxuICAgICAgICAgICAgICAgICAgICA6IGh0bWxgXG4gICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInNiYi1zY3JlZW4tcmVhZGVyLW9ubHlcIj4ke3dlZWtEYXkubG9uZ308L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBhcmlhLWhpZGRlbj1cInRydWVcIj4ke3dlZWtEYXkubmFycm93fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICBgfVxuICAgICAgICAgICAgICAgIDwvdGg+XG4gICAgICAgICAgICAgIGAsXG4gICAgICAgICAgICApfVxuICAgICAgICAgIDwvdHI+XG4gICAgICAgIDwvdGhlYWQ+XG4gICAgICAgIDx0Ym9keSBjbGFzcz1cInNiYi1jYWxlbmRhcl9fdGFibGUtYm9keVwiPlxuICAgICAgICAgICR7d2Vla3MubWFwKCh3ZWVrOiBEYXk8VD5bXSwgcm93SW5kZXg6IG51bWJlcikgPT4ge1xuICAgICAgICAgICAgY29uc3QgZmlyc3RSb3dPZmZzZXQ6IG51bWJlciA9IERBWVNfUEVSX1JPVyAtIHdlZWsubGVuZ3RoO1xuICAgICAgICAgICAgaWYgKHJvd0luZGV4ID09PSAwICYmIGZpcnN0Um93T2Zmc2V0KSB7XG4gICAgICAgICAgICAgIHJldHVybiBodG1sYFxuICAgICAgICAgICAgICAgIDx0cj5cbiAgICAgICAgICAgICAgICAgICR7dGhpcy53ZWVrTnVtYmVyc1xuICAgICAgICAgICAgICAgICAgICA/IGh0bWxgXG4gICAgICAgICAgICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJzYmItY2FsZW5kYXJfX3RhYmxlLWhlYWRlci1jZWxsLXZlcnRpY2FsXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICR7dGhpcy5tdWx0aXBsZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgID8gaHRtbGBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNiYi1jYWxlbmRhci13ZWVrbnVtYmVyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLnZhbHVlPSR7d2Vla051bWJlcnNbMF19XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQGNsaWNrPSR7KCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZGF5czogRGF5PFQ+W10gPSB3ZWVrc0ZvclNlbGVjdE11bHRpcGxlV2Vla051bWJlcnMuZmlsdGVyKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoZGF5OiBEYXk8VD4pID0+IGRheS53ZWVrVmFsdWUgPT09IHdlZWtOdW1iZXJzWzBdLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZWxlY3RNdWx0aXBsZURhdGVzKGRheXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH19XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID48L3NiYi1jYWxlbmRhci13ZWVrbnVtYmVyPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogaHRtbGBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJzYmItc2NyZWVuLXJlYWRlci1vbmx5XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA+JHtgJHtpMThuQ2FsZW5kYXJXZWVrTnVtYmVyW3RoaXMuX2xhbmd1YWdlLmN1cnJlbnRdfSAke3dlZWtOdW1iZXJzWzBdfWB9PC9zcGFuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gYXJpYS1oaWRkZW49XCJ0cnVlXCI+JHt3ZWVrTnVtYmVyc1swXX08L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgfVxuICAgICAgICAgICAgICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgICAgICAgICAgICBgXG4gICAgICAgICAgICAgICAgICAgIDogbm90aGluZ31cbiAgICAgICAgICAgICAgICAgICR7Wy4uLkFycmF5KGZpcnN0Um93T2Zmc2V0KS5rZXlzKCldLm1hcChcbiAgICAgICAgICAgICAgICAgICAgKCkgPT4gaHRtbGA8dGQgY2xhc3M9XCJzYmItY2FsZW5kYXJfX3RhYmxlLWRhdGFcIj48L3RkPmAsXG4gICAgICAgICAgICAgICAgICApfVxuICAgICAgICAgICAgICAgICAgJHt0aGlzLl9jcmVhdGVEYXlDZWxscyh3ZWVrKX1cbiAgICAgICAgICAgICAgICA8L3RyPlxuICAgICAgICAgICAgICBgO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGh0bWxgXG4gICAgICAgICAgICAgIDx0cj5cbiAgICAgICAgICAgICAgICAke3RoaXMud2Vla051bWJlcnNcbiAgICAgICAgICAgICAgICAgID8gaHRtbGBcbiAgICAgICAgICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJzYmItY2FsZW5kYXJfX3RhYmxlLWhlYWRlci1jZWxsLXZlcnRpY2FsXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAke3RoaXMubXVsdGlwbGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgPyBodG1sYFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNiYi1jYWxlbmRhci13ZWVrbnVtYmVyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC52YWx1ZT0ke3dlZWtOdW1iZXJzW3Jvd0luZGV4XX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQGNsaWNrPSR7KCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRheXM6IERheTxUPltdID0gd2Vla3NGb3JTZWxlY3RNdWx0aXBsZVdlZWtOdW1iZXJzLmZpbHRlcihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChkYXk6IERheTxUPikgPT4gZGF5LndlZWtWYWx1ZSA9PT0gd2Vla051bWJlcnNbcm93SW5kZXhdLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkhO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3NlbGVjdE11bHRpcGxlRGF0ZXMoZGF5cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH19XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICA+PC9zYmItY2FsZW5kYXItd2Vla251bWJlcj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBgXG4gICAgICAgICAgICAgICAgICAgICAgICAgIDogaHRtbGBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwic2JiLXNjcmVlbi1yZWFkZXItb25seVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID4ke2Ake2kxOG5DYWxlbmRhcldlZWtOdW1iZXJbdGhpcy5fbGFuZ3VhZ2UuY3VycmVudF19ICR7d2Vla051bWJlcnNbcm93SW5kZXhdfWB9PC9zcGFuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBhcmlhLWhpZGRlbj1cInRydWVcIj4ke3dlZWtOdW1iZXJzW3Jvd0luZGV4XX08L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYH1cbiAgICAgICAgICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgICAgICAgICBgXG4gICAgICAgICAgICAgICAgICA6IG5vdGhpbmd9XG4gICAgICAgICAgICAgICAgJHt0aGlzLl9jcmVhdGVEYXlDZWxscyh3ZWVrKX1cbiAgICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICAgIGA7XG4gICAgICAgICAgfSl9XG4gICAgICAgIDwvdGJvZHk+XG4gICAgICA8L3RhYmxlPlxuICAgIGA7XG4gIH1cblxuICAvKiogQ3JlYXRlcyB0aGUgdGFibGUgaW4gb3JpZW50YXRpb249J3ZlcnRpY2FsJy4gKi9cbiAgcHJpdmF0ZSBfY3JlYXRlRGF5VGFibGVWZXJ0aWNhbChcbiAgICB3ZWVrczogRGF5PFQ+W11bXSxcbiAgICB3ZWVrTnVtYmVyczogbnVtYmVyW10sXG4gICAgbmV4dE1vbnRoQWN0aXZlRGF0ZT86IFQsXG4gICk6IFRlbXBsYXRlUmVzdWx0IHtcbiAgICBjb25zdCB3ZWVrT2Zmc2V0ID0gdGhpcy5fZGF0ZUFkYXB0ZXIuZ2V0Rmlyc3RXZWVrT2Zmc2V0KFxuICAgICAgbmV4dE1vbnRoQWN0aXZlRGF0ZSA/PyB0aGlzLl9hY3RpdmVEYXRlLFxuICAgICk7XG4gICAgY29uc3Qgd2Vla3NGb3JTZWxlY3RNdWx0aXBsZVdlZWtOdW1iZXJzOiBEYXk8VD5bXSA9IChcbiAgICAgIHRoaXMuX3dpZGVcbiAgICAgICAgPyBbLi4udGhpcy5fd2Vla3MsIC4uLnRoaXMuX25leHRNb250aFdlZWtzXVxuICAgICAgICA6IG5leHRNb250aEFjdGl2ZURhdGVcbiAgICAgICAgICA/IHRoaXMuX25leHRNb250aFdlZWtzXG4gICAgICAgICAgOiB0aGlzLl93ZWVrc1xuICAgICkuZmxhdCgpO1xuICAgIHJldHVybiBodG1sYFxuICAgICAgPHRhYmxlXG4gICAgICAgIGNsYXNzPVwic2JiLWNhbGVuZGFyX190YWJsZVwiXG4gICAgICAgIEBmb2N1c291dD0keyhldmVudDogRm9jdXNFdmVudCkgPT5cbiAgICAgICAgICB0aGlzLl9oYW5kbGVUYWJsZUJsdXIoZXZlbnQucmVsYXRlZFRhcmdldCBhcyBIVE1MRWxlbWVudCl9XG4gICAgICAgIEBhbmltYXRpb25lbmQ9JHsoZTogQW5pbWF0aW9uRXZlbnQpID0+IHRoaXMuX3RhYmxlQW5pbWF0aW9uRW5kKGUpfVxuICAgICAgPlxuICAgICAgICAke3RoaXMud2Vla051bWJlcnNcbiAgICAgICAgICA/IGh0bWxgXG4gICAgICAgICAgICAgIDx0aGVhZCBjbGFzcz1cInNiYi1jYWxlbmRhcl9fdGFibGUtaGVhZGVyXCI+XG4gICAgICAgICAgICAgICAgPHRyPlxuICAgICAgICAgICAgICAgICAgJHtuZXh0TW9udGhBY3RpdmVEYXRlXG4gICAgICAgICAgICAgICAgICAgID8gbm90aGluZ1xuICAgICAgICAgICAgICAgICAgICA6IGh0bWxgPHRoIGNsYXNzPVwic2JiLWNhbGVuZGFyX190YWJsZS1kYXRhXCI+PC90aD5gfVxuICAgICAgICAgICAgICAgICAgJHt3ZWVrTnVtYmVycy5tYXAoXG4gICAgICAgICAgICAgICAgICAgICh3ZWVrTnVtYmVyOiBudW1iZXIpID0+IGh0bWxgXG4gICAgICAgICAgICAgICAgICAgICAgPHRoIGNsYXNzPVwic2JiLWNhbGVuZGFyX190YWJsZS1oZWFkZXItY2VsbFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgJHt0aGlzLm11bHRpcGxlXG4gICAgICAgICAgICAgICAgICAgICAgICAgID8gaHRtbGBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzYmItY2FsZW5kYXItd2Vla251bWJlclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAudmFsdWU9JHt3ZWVrTnVtYmVyfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBAY2xpY2s9JHsoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZGF5czogRGF5PFQ+W10gPSB3ZWVrc0ZvclNlbGVjdE11bHRpcGxlV2Vla051bWJlcnMuZmlsdGVyKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGRheTogRGF5PFQ+KSA9PiBkYXkud2Vla1ZhbHVlID09PSB3ZWVrTnVtYmVyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkhO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3NlbGVjdE11bHRpcGxlRGF0ZXMoZGF5cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH19XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICA+PC9zYmItY2FsZW5kYXItd2Vla251bWJlcj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBgXG4gICAgICAgICAgICAgICAgICAgICAgICAgIDogaHRtbGBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwic2JiLXNjcmVlbi1yZWFkZXItb25seVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID4ke2Ake2kxOG5DYWxlbmRhcldlZWtOdW1iZXJbdGhpcy5fbGFuZ3VhZ2UuY3VycmVudF19ICR7d2Vla051bWJlcn1gfTwvc3BhblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gYXJpYS1oaWRkZW49XCJ0cnVlXCI+JHt3ZWVrTnVtYmVyfTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBgfVxuICAgICAgICAgICAgICAgICAgICAgIDwvdGg+XG4gICAgICAgICAgICAgICAgICAgIGAsXG4gICAgICAgICAgICAgICAgICApfVxuICAgICAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgICAgIDwvdGhlYWQ+XG4gICAgICAgICAgICBgXG4gICAgICAgICAgOiBub3RoaW5nfVxuICAgICAgICA8dGJvZHkgY2xhc3M9XCJzYmItY2FsZW5kYXJfX3RhYmxlLWJvZHlcIj5cbiAgICAgICAgICAke3dlZWtzLm1hcCgod2VlazogRGF5PFQ+W10sIHJvd0luZGV4OiBudW1iZXIpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHdlZWtkYXkgPSB0aGlzLl93ZWVrZGF5c1tyb3dJbmRleF07XG4gICAgICAgICAgICBjb25zdCBzZWxlY3RhYmxlRGF5cyA9IHRoaXMuX3dpZGUgPyBbLi4ud2VlaywgLi4udGhpcy5fbmV4dE1vbnRoV2Vla3Nbcm93SW5kZXhdXSA6IHdlZWs7XG4gICAgICAgICAgICByZXR1cm4gaHRtbGBcbiAgICAgICAgICAgICAgPHRyPlxuICAgICAgICAgICAgICAgICR7bmV4dE1vbnRoQWN0aXZlRGF0ZVxuICAgICAgICAgICAgICAgICAgPyBub3RoaW5nXG4gICAgICAgICAgICAgICAgICA6IGh0bWxgXG4gICAgICAgICAgICAgICAgICAgICAgPHRkIGNsYXNzPVwic2JiLWNhbGVuZGFyX190YWJsZS1oZWFkZXItY2VsbC12ZXJ0aWNhbFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgJHt0aGlzLm11bHRpcGxlXG4gICAgICAgICAgICAgICAgICAgICAgICAgID8gaHRtbGBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzYmItY2FsZW5kYXItd2Vla2RheVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAudmFsdWU9JHt3ZWVrZGF5fVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBAY2xpY2s9JHsoKSA9PiB0aGlzLl9zZWxlY3RNdWx0aXBsZURhdGVzKHNlbGVjdGFibGVEYXlzKX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHt3ZWVrZGF5Lm5hcnJvd31cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvc2JiLWNhbGVuZGFyLXdlZWtkYXk+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYFxuICAgICAgICAgICAgICAgICAgICAgICAgICA6IGh0bWxgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInNiYi1zY3JlZW4tcmVhZGVyLW9ubHlcIj4ke3dlZWtkYXkubG9uZ308L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBhcmlhLWhpZGRlbj1cInRydWVcIj4ke3dlZWtkYXkubmFycm93fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBgfVxuICAgICAgICAgICAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgICAgICAgICAgIGB9XG4gICAgICAgICAgICAgICAgJHtyb3dJbmRleCA8IHdlZWtPZmZzZXRcbiAgICAgICAgICAgICAgICAgID8gaHRtbGA8dGQgY2xhc3M9XCJzYmItY2FsZW5kYXJfX3RhYmxlLWRhdGFcIj48L3RkPmBcbiAgICAgICAgICAgICAgICAgIDogbm90aGluZ31cbiAgICAgICAgICAgICAgICAke3RoaXMuX2NyZWF0ZURheUNlbGxzKHdlZWspfVxuICAgICAgICAgICAgICA8L3RyPlxuICAgICAgICAgICAgYDtcbiAgICAgICAgICB9KX1cbiAgICAgICAgPC90Ym9keT5cbiAgICAgIDwvdGFibGU+XG4gICAgYDtcbiAgfVxuXG4gIC8qKiBDcmVhdGVzIHRoZSBjZWxscyBmb3IgdGhlIGRhaWx5IHZpZXcuICovXG4gIHByaXZhdGUgX2NyZWF0ZURheUNlbGxzKHdlZWs6IERheTxUPltdKTogVGVtcGxhdGVSZXN1bHRbXSB7XG4gICAgcmV0dXJuIHdlZWsubWFwKChkYXk6IERheTxUPikgPT4ge1xuICAgICAgcmV0dXJuIGh0bWxgXG4gICAgICAgIDx0ZCBjbGFzcz1cInNiYi1jYWxlbmRhcl9fdGFibGUtZGF0YSBzYmItY2FsZW5kYXJfX2RheS1jZWxsXCI+XG4gICAgICAgICAgPHNsb3QgbmFtZT0ke2RheS52YWx1ZX0+XG4gICAgICAgICAgICA8c2JiLWNhbGVuZGFyLWRheSBzbG90PSR7ZGF5LnZhbHVlfT48L3NiYi1jYWxlbmRhci1kYXk+XG4gICAgICAgICAgPC9zbG90PlxuICAgICAgICA8L3RkPlxuICAgICAgYDtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKiBSZW5kZXIgdGhlIHZpZXcgZm9yIHRoZSBtb250aCBzZWxlY3Rpb24uICovXG4gIHByaXZhdGUgX3JlbmRlck1vbnRoVmlldygpOiBUZW1wbGF0ZVJlc3VsdCB7XG4gICAgcmV0dXJuIGh0bWxgXG4gICAgICA8ZGl2IGNsYXNzPVwic2JiLWNhbGVuZGFyX19jb250cm9sc1wiPlxuICAgICAgICAke3RoaXMuX2dldEFycm93KFxuICAgICAgICAgICdsZWZ0JyxcbiAgICAgICAgICAoKSA9PiB0aGlzLl9nb1RvRGlmZmVyZW50WWVhcigtMSksXG4gICAgICAgICAgaTE4blByZXZpb3VzWWVhclt0aGlzLl9sYW5ndWFnZS5jdXJyZW50XSxcbiAgICAgICAgICB0aGlzLl9wcmV2aW91c1llYXJEaXNhYmxlZCgpLFxuICAgICAgICApfVxuICAgICAgICA8ZGl2IGNsYXNzPVwic2JiLWNhbGVuZGFyX19jb250cm9scy1tb250aFwiPiR7dGhpcy5fY3JlYXRlTGFiZWxGb3JNb250aFZpZXcoKX08L2Rpdj5cbiAgICAgICAgJHt0aGlzLl9nZXRBcnJvdyhcbiAgICAgICAgICAncmlnaHQnLFxuICAgICAgICAgICgpID0+IHRoaXMuX2dvVG9EaWZmZXJlbnRZZWFyKDEpLFxuICAgICAgICAgIGkxOG5OZXh0WWVhclt0aGlzLl9sYW5ndWFnZS5jdXJyZW50XSxcbiAgICAgICAgICB0aGlzLl9uZXh0WWVhckRpc2FibGVkKCksXG4gICAgICAgICl9XG4gICAgICA8L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3M9XCJzYmItY2FsZW5kYXJfX3RhYmxlLW92ZXJmbG93LWJyZWFrXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJzYmItY2FsZW5kYXJfX3RhYmxlLWNvbnRhaW5lciBzYmItY2FsZW5kYXJfX3RhYmxlLW1vbnRoLXZpZXdcIj5cbiAgICAgICAgICAke3RoaXMuX2NyZWF0ZU1vbnRoVGFibGUodGhpcy5fbW9udGhzLCB0aGlzLl9jaG9zZW5ZZWFyISl9XG4gICAgICAgICAgJHt0aGlzLl93aWRlID8gdGhpcy5fY3JlYXRlTW9udGhUYWJsZSh0aGlzLl9tb250aHMsIHRoaXMuX2Nob3NlblllYXIhICsgMSkgOiBub3RoaW5nfVxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgIGA7XG4gIH1cblxuICAvKiogQ3JlYXRlcyB0aGUgbGFiZWwgd2l0aCB0aGUgeWVhciBmb3IgdGhlIG1vbnRobHkgdmlldy4gKi9cbiAgcHJpdmF0ZSBfY3JlYXRlTGFiZWxGb3JNb250aFZpZXcoKTogVGVtcGxhdGVSZXN1bHQge1xuICAgIHJldHVybiBodG1sYDxidXR0b25cbiAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgIGlkPVwic2JiLWNhbGVuZGFyX19tb250aC1zZWxlY3Rpb25cIlxuICAgICAgICBjbGFzcz1cInNiYi1jYWxlbmRhcl9fY29udHJvbHMtY2hhbmdlLWRhdGVcIlxuICAgICAgICBhcmlhLWxhYmVsPSR7YCR7aTE4bkNhbGVuZGFyRGF0ZVNlbGVjdGlvblt0aGlzLl9sYW5ndWFnZS5jdXJyZW50XX0gJHt0aGlzLl9jaG9zZW5ZZWFyfWB9XG4gICAgICAgIEBjbGljaz0keygpID0+IHRoaXMuX3Jlc2V0Q2FsZW5kYXJWaWV3QW5kRW1pdE1vbnRoQ2hhbmdlKHRydWUpfVxuICAgICAgPlxuICAgICAgICAke3RoaXMuX2Nob3NlblllYXJ9ICR7dGhpcy5fd2lkZSA/IGAgLSAke3RoaXMuX2Nob3NlblllYXIhICsgMX1gIDogbm90aGluZ31cbiAgICAgICAgPHNiYi1pY29uIG5hbWU9XCJjaGV2cm9uLXNtYWxsLXVwLXNtYWxsXCI+PC9zYmItaWNvbj5cbiAgICAgIDwvYnV0dG9uPlxuICAgICAgPHNwYW4gY2xhc3M9XCJzYmItc2NyZWVuLXJlYWRlci1vbmx5XCIgcm9sZT1cInN0YXR1c1wiPiAke3RoaXMuX2Nob3NlblllYXJ9IDwvc3Bhbj5gO1xuICB9XG5cbiAgLyoqIENyZWF0ZXMgdGhlIHRhYmxlIGZvciB0aGUgbW9udGggc2VsZWN0aW9uIHZpZXcuICovXG4gIHByaXZhdGUgX2NyZWF0ZU1vbnRoVGFibGUobW9udGhzOiBNb250aENlbGxbXVtdLCB5ZWFyOiBudW1iZXIpOiBUZW1wbGF0ZVJlc3VsdCB7XG4gICAgcmV0dXJuIGh0bWxgXG4gICAgICA8dGFibGVcbiAgICAgICAgY2xhc3M9XCJzYmItY2FsZW5kYXJfX3RhYmxlXCJcbiAgICAgICAgQGFuaW1hdGlvbmVuZD0keyhlOiBBbmltYXRpb25FdmVudCkgPT4gdGhpcy5fdGFibGVBbmltYXRpb25FbmQoZSl9XG4gICAgICA+XG4gICAgICAgICR7dGhpcy5fd2lkZVxuICAgICAgICAgID8gaHRtbGA8dGhlYWQgY2xhc3M9XCJzYmItY2FsZW5kYXJfX3RhYmxlLWhlYWRlclwiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPlxuICAgICAgICAgICAgICA8dHI+XG4gICAgICAgICAgICAgICAgPHRoIGNsYXNzPVwic2JiLWNhbGVuZGFyX190YWJsZS1oZWFkZXItY2VsbFwiIGNvbHNwYW49JHtNT05USFNfUEVSX1JPV30+JHt5ZWFyfTwvdGg+XG4gICAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgICA8L3RoZWFkPmBcbiAgICAgICAgICA6IG5vdGhpbmd9XG4gICAgICAgIDx0Ym9keSBjbGFzcz1cInNiYi1jYWxlbmRhcl9fdGFibGUtYm9keVwiPlxuICAgICAgICAgICR7bW9udGhzLm1hcChcbiAgICAgICAgICAgIChyb3c6IE1vbnRoQ2VsbFtdKSA9PiBodG1sYFxuICAgICAgICAgICAgICA8dHI+XG4gICAgICAgICAgICAgICAgJHtyb3cubWFwKChtb250aDogTW9udGhDZWxsKSA9PiB7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gaHRtbGBcbiAgICAgICAgICAgICAgICAgICAgPHRkIGNsYXNzPVwic2JiLWNhbGVuZGFyX190YWJsZS1kYXRhXCI+XG4gICAgICAgICAgICAgICAgICAgICAgPHNiYi1jYWxlbmRhci1tb250aFxuICAgICAgICAgICAgICAgICAgICAgICAgLnZhbHVlPVwiJHt5ZWFyfS0ke21vbnRoLnZhbHVlfVwiXG4gICAgICAgICAgICAgICAgICAgICAgICBAY2xpY2s9JHsoKSA9PiB0aGlzLl9vbk1vbnRoU2VsZWN0aW9uKG1vbnRoLm1vbnRoVmFsdWUsIHllYXIpfVxuICAgICAgICAgICAgICAgICAgICAgICAgQGtleWRvd249JHsoZXZ0OiBLZXlib2FyZEV2ZW50KSA9PiB0aGlzLl9oYW5kbGVLZXlib2FyZEV2ZW50KGV2dCl9XG4gICAgICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICAgIDwvc2JiLWNhbGVuZGFyLW1vbnRoPlxuICAgICAgICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgICAgICAgYDtcbiAgICAgICAgICAgICAgICB9KX1cbiAgICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICAgIGAsXG4gICAgICAgICAgKX1cbiAgICAgICAgPC90Ym9keT5cbiAgICAgIDwvdGFibGU+XG4gICAgYDtcbiAgfVxuXG4gIC8qKiBTZWxlY3QgdGhlIG1vbnRoIGFuZCBjaGFuZ2UgdGhlIHZpZXcgdG8gZGF5IHNlbGVjdGlvbi4gKi9cbiAgcHJpdmF0ZSBfb25Nb250aFNlbGVjdGlvbihtb250aDogbnVtYmVyLCB5ZWFyOiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLl9jaG9zZW5Nb250aCA9IG1vbnRoO1xuICAgIHRoaXMuX25leHRDYWxlbmRhclZpZXcgPSAnZGF5JztcbiAgICB0aGlzLl9pbml0KFxuICAgICAgdGhpcy5fZGF0ZUFkYXB0ZXIuY3JlYXRlRGF0ZShcbiAgICAgICAgeWVhcixcbiAgICAgICAgdGhpcy5fY2hvc2VuTW9udGgsXG4gICAgICAgIHRoaXMuX2RhdGVBZGFwdGVyLmdldERhdGUodGhpcy5fYWN0aXZlRGF0ZSksXG4gICAgICApLFxuICAgICk7XG4gICAgdGhpcy5fc3RhcnRUYWJsZVRyYW5zaXRpb24oKTtcbiAgICB0aGlzLl9lbWl0TW9udGhDaGFuZ2UoKTtcbiAgfVxuXG4gIC8qKiBSZW5kZXIgdGhlIHZpZXcgZm9yIHRoZSB5ZWFyIHNlbGVjdGlvbi4gKi9cbiAgcHJpdmF0ZSBfcmVuZGVyWWVhclZpZXcoKTogVGVtcGxhdGVSZXN1bHQge1xuICAgIHJldHVybiBodG1sYFxuICAgICAgPGRpdiBjbGFzcz1cInNiYi1jYWxlbmRhcl9fY29udHJvbHNcIj5cbiAgICAgICAgJHt0aGlzLl9nZXRBcnJvdyhcbiAgICAgICAgICAnbGVmdCcsXG4gICAgICAgICAgKCkgPT4gdGhpcy5fZ29Ub0RpZmZlcmVudFllYXJSYW5nZSgtWUVBUlNfUEVSX1BBR0UpLFxuICAgICAgICAgIGkxOG5QcmV2aW91c1llYXJSYW5nZShZRUFSU19QRVJfUEFHRSlbdGhpcy5fbGFuZ3VhZ2UuY3VycmVudF0sXG4gICAgICAgICAgdGhpcy5fcHJldmlvdXNZZWFyUmFuZ2VEaXNhYmxlZCgpLFxuICAgICAgICApfVxuICAgICAgICA8ZGl2IGNsYXNzPVwic2JiLWNhbGVuZGFyX19jb250cm9scy1tb250aFwiPiR7dGhpcy5fY3JlYXRlTGFiZWxGb3JZZWFyVmlldygpfTwvZGl2PlxuICAgICAgICAke3RoaXMuX2dldEFycm93KFxuICAgICAgICAgICdyaWdodCcsXG4gICAgICAgICAgKCkgPT4gdGhpcy5fZ29Ub0RpZmZlcmVudFllYXJSYW5nZShZRUFSU19QRVJfUEFHRSksXG4gICAgICAgICAgaTE4bk5leHRZZWFyUmFuZ2UoWUVBUlNfUEVSX1BBR0UpW3RoaXMuX2xhbmd1YWdlLmN1cnJlbnRdLFxuICAgICAgICAgIHRoaXMuX25leHRZZWFyUmFuZ2VEaXNhYmxlZCgpLFxuICAgICAgICApfVxuICAgICAgPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwic2JiLWNhbGVuZGFyX190YWJsZS1vdmVyZmxvdy1icmVha1wiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwic2JiLWNhbGVuZGFyX190YWJsZS1jb250YWluZXIgc2JiLWNhbGVuZGFyX190YWJsZS15ZWFyLXZpZXdcIj5cbiAgICAgICAgICAke3RoaXMuX2NyZWF0ZVllYXJUYWJsZSh0aGlzLl95ZWFycyl9XG4gICAgICAgICAgJHt0aGlzLl93aWRlID8gdGhpcy5fY3JlYXRlWWVhclRhYmxlKHRoaXMuX25leHRNb250aFllYXJzLCB0cnVlKSA6IG5vdGhpbmd9XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgYDtcbiAgfVxuXG4gIC8qKiBDcmVhdGVzIHRoZSBidXR0b24gYXJyb3cgZm9yIGFsbCB0aGUgdmlld3MuICovXG4gIHByaXZhdGUgX2dldEFycm93KFxuICAgIGRpcmVjdGlvbjogJ2xlZnQnIHwgJ3JpZ2h0JyxcbiAgICBjbGljazogKCkgPT4gdm9pZCxcbiAgICBhcmlhTGFiZWw6IHN0cmluZyxcbiAgICBkaXNhYmxlZDogYm9vbGVhbixcbiAgKTogVGVtcGxhdGVSZXN1bHQge1xuICAgIHJldHVybiBodG1sYDxzYmItc2Vjb25kYXJ5LWJ1dHRvblxuICAgICAgc2l6ZT1cIm1cIlxuICAgICAgaWNvbi1uYW1lPVwiY2hldnJvbi1zbWFsbC0ke2RpcmVjdGlvbn0tc21hbGxcIlxuICAgICAgYXJpYS1sYWJlbD0ke2FyaWFMYWJlbH1cbiAgICAgIEBjbGljaz0ke2NsaWNrfVxuICAgICAgP2Rpc2FibGVkPSR7ZGlzYWJsZWR9XG4gICAgICBpZD1cInNiYi1jYWxlbmRhcl9fY29udHJvbHMtJHtkaXJlY3Rpb24gPT09ICdsZWZ0JyA/ICdwcmV2aW91cycgOiAnbmV4dCd9XCJcbiAgICA+PC9zYmItc2Vjb25kYXJ5LWJ1dHRvbj5gO1xuICB9XG5cbiAgLyoqIENyZWF0ZXMgdGhlIGxhYmVsIHdpdGggdGhlIHllYXIgcmFuZ2UgZm9yIHRoZSB5ZWFybHkgdmlldy4gKi9cbiAgcHJpdmF0ZSBfY3JlYXRlTGFiZWxGb3JZZWFyVmlldygpOiBUZW1wbGF0ZVJlc3VsdCB7XG4gICAgY29uc3QgZmlyc3RZZWFyOiBudW1iZXIgPSB0aGlzLl95ZWFycy5mbGF0KClbMF07XG4gICAgY29uc3QgbGFzdFllYXJBcnJheTogbnVtYmVyW10gPSAodGhpcy5fd2lkZSA/IHRoaXMuX25leHRNb250aFllYXJzIDogdGhpcy5feWVhcnMpLmZsYXQoKTtcbiAgICBjb25zdCBsYXN0WWVhcjogbnVtYmVyID0gbGFzdFllYXJBcnJheVtsYXN0WWVhckFycmF5Lmxlbmd0aCAtIDFdO1xuICAgIGNvbnN0IHllYXJMYWJlbCA9IGAke2ZpcnN0WWVhcn0gLSAke2xhc3RZZWFyfWA7XG4gICAgcmV0dXJuIGh0bWxgXG4gICAgICA8YnV0dG9uXG4gICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICBpZD1cInNiYi1jYWxlbmRhcl9feWVhci1zZWxlY3Rpb25cIlxuICAgICAgICBjbGFzcz1cInNiYi1jYWxlbmRhcl9fY29udHJvbHMtY2hhbmdlLWRhdGVcIlxuICAgICAgICBhcmlhLWxhYmVsPVwiJHtpMThuQ2FsZW5kYXJEYXRlU2VsZWN0aW9uW3RoaXMuX2xhbmd1YWdlLmN1cnJlbnRdfSAke3llYXJMYWJlbH1cIlxuICAgICAgICBAY2xpY2s9JHsoKSA9PiB0aGlzLl9yZXNldENhbGVuZGFyVmlld0FuZEVtaXRNb250aENoYW5nZSh0cnVlKX1cbiAgICAgID5cbiAgICAgICAgJHt5ZWFyTGFiZWx9XG4gICAgICAgIDxzYmItaWNvbiBuYW1lPVwiY2hldnJvbi1zbWFsbC11cC1zbWFsbFwiPjwvc2JiLWljb24+XG4gICAgICA8L2J1dHRvbj5cbiAgICAgIDxzcGFuIGNsYXNzPVwic2JiLXNjcmVlbi1yZWFkZXItb25seVwiIHJvbGU9XCJzdGF0dXNcIj4gJHt5ZWFyTGFiZWx9IDwvc3Bhbj5cbiAgICBgO1xuICB9XG5cbiAgLyoqIENyZWF0ZXMgdGhlIHRhYmxlIGZvciB0aGUgeWVhciBzZWxlY3Rpb24gdmlldy4gKi9cbiAgcHJpdmF0ZSBfY3JlYXRlWWVhclRhYmxlKHllYXJzOiBudW1iZXJbXVtdLCBzaGlmdFJpZ2h0ID0gZmFsc2UpOiBUZW1wbGF0ZVJlc3VsdCB7XG4gICAgcmV0dXJuIGh0bWxgIDx0YWJsZVxuICAgICAgY2xhc3M9XCJzYmItY2FsZW5kYXJfX3RhYmxlXCJcbiAgICAgIEBhbmltYXRpb25lbmQ9JHsoZTogQW5pbWF0aW9uRXZlbnQpID0+IHRoaXMuX3RhYmxlQW5pbWF0aW9uRW5kKGUpfVxuICAgID5cbiAgICAgIDx0Ym9keSBjbGFzcz1cInNiYi1jYWxlbmRhcl9fdGFibGUtYm9keVwiPlxuICAgICAgICAke3llYXJzLm1hcChcbiAgICAgICAgICAocm93OiBudW1iZXJbXSkgPT5cbiAgICAgICAgICAgIGh0bWxgIDx0cj5cbiAgICAgICAgICAgICAgJHtyb3cubWFwKCh5ZWFyOiBudW1iZXIpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaHRtbGBcbiAgICAgICAgICAgICAgICAgIDx0ZCBjbGFzcz1cInNiYi1jYWxlbmRhcl9fdGFibGUtZGF0YVwiPlxuICAgICAgICAgICAgICAgICAgICA8c2JiLWNhbGVuZGFyLXllYXJcbiAgICAgICAgICAgICAgICAgICAgICAudmFsdWU9JHtTdHJpbmcoeWVhcil9XG4gICAgICAgICAgICAgICAgICAgICAgQGtleWRvd249JHsoZXZ0OiBLZXlib2FyZEV2ZW50KSA9PiB0aGlzLl9oYW5kbGVLZXlib2FyZEV2ZW50KGV2dCl9XG4gICAgICAgICAgICAgICAgICAgICAgQGNsaWNrPSR7KCkgPT4gdGhpcy5fb25ZZWFyU2VsZWN0aW9uKHllYXIsIHNoaWZ0UmlnaHQpfVxuICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgIDwvc2JiLWNhbGVuZGFyLXllYXI+XG4gICAgICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgICAgIGA7XG4gICAgICAgICAgICAgIH0pfVxuICAgICAgICAgICAgPC90cj5gLFxuICAgICAgICApfVxuICAgICAgPC90Ym9keT5cbiAgICA8L3RhYmxlPmA7XG4gIH1cblxuICAvKiogU2VsZWN0IHRoZSB5ZWFyIGFuZCBjaGFuZ2UgdGhlIHZpZXcgdG8gbW9udGggc2VsZWN0aW9uLiAqL1xuICBwcml2YXRlIF9vblllYXJTZWxlY3Rpb24oeWVhcjogbnVtYmVyLCByaWdodFNpZGU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICB0aGlzLl9jaG9zZW5ZZWFyID0gcmlnaHRTaWRlID8geWVhciAtIDEgOiB5ZWFyO1xuICAgIHRoaXMuX25leHRDYWxlbmRhclZpZXcgPSAnbW9udGgnO1xuICAgIHRoaXMuX2Fzc2lnbkFjdGl2ZURhdGUoXG4gICAgICB0aGlzLl9kYXRlQWRhcHRlci5jcmVhdGVEYXRlKFxuICAgICAgICB0aGlzLl9jaG9zZW5ZZWFyLFxuICAgICAgICB0aGlzLl9kYXRlQWRhcHRlci5nZXRNb250aCh0aGlzLl9hY3RpdmVEYXRlKSxcbiAgICAgICAgdGhpcy5fZGF0ZUFkYXB0ZXIuZ2V0RGF0ZSh0aGlzLl9hY3RpdmVEYXRlKSxcbiAgICAgICksXG4gICAgKTtcbiAgICB0aGlzLl9zdGFydFRhYmxlVHJhbnNpdGlvbigpO1xuICB9XG5cbiAgcHJpdmF0ZSBfZ2V0VmlldygpOiBUZW1wbGF0ZVJlc3VsdCB7XG4gICAgaWYgKGlzU2VydmVyIHx8IHRoaXMuaHlkcmF0aW9uUmVxdWlyZWQpIHtcbiAgICAgIC8vIFRPRE86IFdlIGRpc2FibGUgU1NSIGZvciBjYWxlbmRhciBmb3Igbm93LiBGaWd1cmUgb3V0LCBpZiB0aGVyZSBpcyBhIHdheVxuICAgICAgLy8gdG8gZW5hYmxlIGl0LCB3aGlsZSBjb25zaWRlcmluZyBpMThuIGFuZCBkYXRlIGluZm9ybWF0aW9uLlxuICAgICAgcmV0dXJuIGh0bWxgJHtub3RoaW5nfWA7XG4gICAgfVxuICAgIHN3aXRjaCAodGhpcy5fY2FsZW5kYXJWaWV3KSB7XG4gICAgICBjYXNlICd5ZWFyJzpcbiAgICAgICAgcmV0dXJuIHRoaXMuX3JlbmRlclllYXJWaWV3KCk7XG4gICAgICBjYXNlICdtb250aCc6XG4gICAgICAgIHJldHVybiB0aGlzLl9yZW5kZXJNb250aFZpZXcoKTtcbiAgICAgIGNhc2UgJ2RheSc6XG4gICAgICBkZWZhdWx0OlxuICAgICAgICByZXR1cm4gdGhpcy5fcmVuZGVyRGF5VmlldygpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX3RhYmxlQW5pbWF0aW9uRW5kKGV2ZW50OiBBbmltYXRpb25FdmVudCk6IHZvaWQge1xuICAgIGNvbnN0IHRhYmxlID0gZXZlbnQudGFyZ2V0IGFzIEhUTUxFbGVtZW50O1xuICAgIGlmIChldmVudC5hbmltYXRpb25OYW1lID09PSAnaGlkZScpIHtcbiAgICAgIHRhYmxlLmNsYXNzTGlzdC5yZW1vdmUoJ3NiYi1jYWxlbmRhcl9fdGFibGUtaGlkZScpO1xuICAgICAgaWYgKHRoaXMuX2NvbnRhaW5pbmdGb2N1cykge1xuICAgICAgICB0aGlzLl9yZXNldEZvY3VzID0gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIHRoaXMuX2NhbGVuZGFyVmlldyA9IHRoaXMuX25leHRDYWxlbmRhclZpZXc7XG4gICAgfSBlbHNlIGlmIChldmVudC5hbmltYXRpb25OYW1lID09PSAnc2hvdycpIHtcbiAgICAgIHRoaXMuaW50ZXJuYWxzLnN0YXRlcy5kZWxldGUoJ3RyYW5zaXRpb24nKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9zdGFydFRhYmxlVHJhbnNpdGlvbigpOiB2b2lkIHtcbiAgICB0aGlzLmludGVybmFscy5zdGF0ZXMuYWRkKCd0cmFuc2l0aW9uJyk7XG4gICAgdGhpcy5zaGFkb3dSb290XG4gICAgICA/LnF1ZXJ5U2VsZWN0b3JBbGwoJ3RhYmxlJylcbiAgICAgID8uZm9yRWFjaCgoZSkgPT4gZS5jbGFzc0xpc3QudG9nZ2xlKCdzYmItY2FsZW5kYXJfX3RhYmxlLWhpZGUnKSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgcmVuZGVyKCk6IFRlbXBsYXRlUmVzdWx0IHtcbiAgICByZXR1cm4gaHRtbGA8ZGl2IGNsYXNzPVwic2JiLWNhbGVuZGFyX193cmFwcGVyXCI+JHt0aGlzLl9nZXRWaWV3KCl9PC9kaXY+YDtcbiAgfVxufVxuXG5kZWNsYXJlIGdsb2JhbCB7XG4gIGludGVyZmFjZSBIVE1MRWxlbWVudFRhZ05hbWVNYXAge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbmFtaW5nLWNvbnZlbnRpb25cbiAgICAnc2JiLWNhbGVuZGFyJzogU2JiQ2FsZW5kYXJFbGVtZW50O1xuICB9XG4gIGludGVyZmFjZSBIVE1MRWxlbWVudEV2ZW50TWFwIHtcbiAgICBtb250aGNoYW5nZTogU2JiTW9udGhDaGFuZ2VFdmVudDtcbiAgfVxufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7QUNtREEsSUFBTSxlQUF1QjtBQUM3QixJQUFNLGlCQUF5QjtBQUMvQixJQUFNLGdCQUF3QjtBQUM5QixJQUFNLGtCQUEwQjtBQUNoQyxJQUFNLGlCQUF5QjtBQUUvQixJQUFhLHNCQUFiLGNBQXlDLE1BQUs7Q0FHNUMsSUFBVyxRQUFLO0VBQ2QsT0FBTyxLQUFLO0NBQ2Q7Q0FFQSxZQUFtQixPQUFxQjtFQUN0QyxNQUFNLGVBQWU7R0FBRSxTQUFTO0dBQU0sVUFBVTtFQUFJLENBQUU7RUFDdEQsS0FBSyxTQUFTLE9BQU8sT0FBTyxTQUFTLENBQUEsQ0FBRTtDQUN6Qzs7QUFHRixJQUFhLHVCQUFiLGNBQTZDLE1BQUs7Q0FHaEQsSUFBVyxlQUFZO0VBQ3JCLE9BQU8sS0FBSztDQUNkO0NBRUEsWUFBbUIsT0FBYztFQUMvQixNQUFNLGdCQUFnQjtHQUFFLFNBQVM7R0FBTSxVQUFVO0VBQUksQ0FBRTtFQUN2RCxLQUFLLGdCQUFnQixPQUFPLE9BQU8sS0FBSztDQUMxQzs7Ozs7OztJQW1FVyw0QkFBa0I7bUJBQW1COzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O2NBQXJDLDJCQUFxQyxZQUFVOzs7dUJBc0J6RCxV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