@pie-lib/math-input-mathlive 1.0.12 → 1.0.13

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.
@@ -0,0 +1,415 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
5
+ describe('mathlive-instance', function () {
6
+ var instance;
7
+ beforeEach(function () {
8
+ jest.resetModules();
9
+ // eslint-disable-next-line global-require
10
+ instance = require('../mathlive-instance');
11
+ instance.__resetEmbeds();
12
+ });
13
+ describe('registerEmbed', function () {
14
+ it('registers a known embed and exposes it as a macro', function () {
15
+ instance.registerEmbed('answerBlock', function () {
16
+ return {
17
+ htmlString: '<div class="answerBlock"></div>',
18
+ latex: function latex() {
19
+ return '\\embed{answerBlock}[]';
20
+ }
21
+ };
22
+ });
23
+ expect(instance.registeredEmbeds()).toEqual(['answerBlock']);
24
+ // The macro tags output with data-embed so CSS can target it, replacing
25
+ // MathQuill's htmlString hook.
26
+ expect(instance.getMacros().answerBlock).toEqual('\\htmlData{embed=answerBlock}{\\placeholder{}}');
27
+ });
28
+ it('registers newLine as a harmless macro (it is handled by latex-bridge)', function () {
29
+ instance.registerEmbed('newLine', function () {
30
+ return {
31
+ latex: function latex() {
32
+ return '\\embed{newLine}[]';
33
+ }
34
+ };
35
+ });
36
+ expect(instance.getMacros().newLine).toEqual('\\htmlData{embed=newLine}{}');
37
+ });
38
+ it('falls back to a placeholder for an unknown embed', function () {
39
+ instance.registerEmbed('somethingCustom', function () {
40
+ return {
41
+ htmlString: '<b>x</b>'
42
+ };
43
+ });
44
+ expect(instance.getMacros().somethingCustom).toEqual('\\htmlData{embed=somethingCustom}{\\placeholder{}}');
45
+ });
46
+ it('honours an explicit mathliveLatex from the factory', function () {
47
+ instance.registerEmbed('custom', function () {
48
+ return {
49
+ mathliveLatex: '\\alpha'
50
+ };
51
+ });
52
+ expect(instance.getMacros().custom).toEqual('\\htmlData{embed=custom}{\\alpha}');
53
+ });
54
+ it('does not throw when the factory throws', function () {
55
+ expect(function () {
56
+ return instance.registerEmbed('bad', function () {
57
+ throw new Error('boom');
58
+ });
59
+ }).not.toThrow();
60
+ expect(instance.registeredEmbeds()).toEqual(['bad']);
61
+ });
62
+ it('ignores bad arguments', function () {
63
+ instance.registerEmbed(undefined, function () {
64
+ return {};
65
+ });
66
+ instance.registerEmbed('noFactory', undefined);
67
+ expect(instance.registeredEmbeds()).toEqual([]);
68
+ });
69
+ it('always includes the pie macro set', function () {
70
+ var macros = instance.getMacros();
71
+ expect(macros.parallelogram).toBeDefined();
72
+ expect(macros.longdiv).toBeDefined();
73
+ expect(macros.napprox).toEqual('\\not\\approx');
74
+ });
75
+
76
+ // Argument-taking macros exist only so previously authored latex parses.
77
+ // Editing never goes through them: MathLive serialises a macro from its
78
+ // original arguments, so typed content never comes back out.
79
+ it('argument-taking macros are plain parse-only definitions', function () {
80
+ ['longdiv', 'overarc', 'abs'].forEach(function (name) {
81
+ expect((0, _typeof2["default"])(instance.PIE_MACROS[name])).toBe('string');
82
+ expect(instance.PIE_MACROS[name]).toContain('#1');
83
+ });
84
+ });
85
+ it('argument-less symbols stay atomic', function () {
86
+ ['perpendicular', 'square', 'degree', 'napprox', 'parallelogram'].forEach(function (name) {
87
+ expect((0, _typeof2["default"])(instance.PIE_MACROS[name])).toBe('string');
88
+ });
89
+ });
90
+ it('longdiv matches the MathJax macro used by math-rendering', function () {
91
+ expect(instance.PIE_MACROS.longdiv).toEqual('\\enclose{longdiv}{#1}');
92
+ });
93
+ });
94
+ describe('applyStaticMath', function () {
95
+ it('returns undefined without an element', function () {
96
+ expect(instance.applyStaticMath(null, 'x')).toBeUndefined();
97
+ });
98
+ it('defers (returns undefined) when MathLive has not loaded', function () {
99
+ var el = document.createElement('div');
100
+ expect(instance.applyStaticMath(el, 'x')).toBeUndefined();
101
+ });
102
+ it('renders synchronously once MathLive is available', function () {
103
+ var el = document.createElement('div');
104
+ instance.__setMathLiveForTest({
105
+ convertLatexToMarkup: function convertLatexToMarkup(l) {
106
+ return "<span>".concat(l, "</span>");
107
+ }
108
+ });
109
+ expect(instance.applyStaticMath(el, '\\pi')).toBe(el);
110
+ expect(el.innerHTML).toEqual('<span>\\pi</span>');
111
+ });
112
+ it('falls back to the element textContent when no latex is passed', function () {
113
+ var el = document.createElement('div');
114
+ el.textContent = '\\theta';
115
+ instance.__setMathLiveForTest({
116
+ convertLatexToMarkup: function convertLatexToMarkup(l) {
117
+ return "<i>".concat(l, "</i>");
118
+ }
119
+ });
120
+ instance.applyStaticMath(el);
121
+ expect(el.innerHTML).toEqual('<i>\\theta</i>');
122
+ });
123
+ it('bridges stored latex (newLine embed) before rendering', function () {
124
+ var el = document.createElement('div');
125
+ instance.__setMathLiveForTest({
126
+ convertLatexToMarkup: function convertLatexToMarkup(l) {
127
+ return l;
128
+ }
129
+ });
130
+ instance.applyStaticMath(el, 'a\\embed{newLine}[]b');
131
+
132
+ // \embed{newLine}[] must become a multiline environment
133
+ expect(el.innerHTML).toContain('displaylines');
134
+ });
135
+ });
136
+ describe('configureFonts', function () {
137
+ // MathLive's default fontsDirectory is the relative './fonts/', which it
138
+ // resolves against its own (empty, when bundled) script url and throws
139
+ // "Invalid base URL" from loadFonts. Paths must become absolute.
140
+ it('is exported and callable before MathLive loads', function () {
141
+ expect((0, _typeof2["default"])(instance.configureFonts)).toBe('function');
142
+ expect(function () {
143
+ return instance.configureFonts('/mathlive-fonts');
144
+ }).not.toThrow();
145
+ });
146
+ it('accepts null to disable font loading', function () {
147
+ expect(function () {
148
+ return instance.configureFonts(null);
149
+ }).not.toThrow();
150
+ });
151
+ it('applies an absolute url to an already-loaded MathfieldElement', function () {
152
+ var MathfieldElement = {};
153
+
154
+ // simulate a loaded instance
155
+ instance.__setMathLiveForTest({
156
+ MathfieldElement: MathfieldElement
157
+ });
158
+ instance.configureFonts('/mathlive-fonts');
159
+ expect(MathfieldElement.fontsDirectory).toEqual("".concat(document.baseURI.replace(/\/$/, ''), "/mathlive-fonts"));
160
+ expect(MathfieldElement.fontsDirectory.startsWith('http')).toBe(true);
161
+ });
162
+
163
+ // \neq, \nsim and \ncong are built from Private Use Area glyphs that only
164
+ // the KaTeX fonts contain, so "no fonts" renders garbage rather than
165
+ // degrading gracefully - hence a CDN fallback by default.
166
+ it('falls back to a version-pinned CDN when nothing is configured', function () {
167
+ var MathfieldElement = {};
168
+ instance.__setMathLiveForTest({
169
+ MathfieldElement: MathfieldElement,
170
+ version: {
171
+ mathlive: '9.9.9'
172
+ }
173
+ });
174
+ instance.configureFonts(undefined);
175
+ expect(MathfieldElement.fontsDirectory).toEqual('https://unpkg.com/mathlive@9.9.9/fonts');
176
+ });
177
+ it('uses /fonts, not /dist/fonts (the latter 404s on unpkg)', function () {
178
+ var MathfieldElement = {};
179
+ instance.__setMathLiveForTest({
180
+ MathfieldElement: MathfieldElement,
181
+ version: {
182
+ mathlive: '0.110.0'
183
+ }
184
+ });
185
+ instance.configureFonts(undefined);
186
+ expect(MathfieldElement.fontsDirectory).toEqual('https://unpkg.com/mathlive@0.110.0/fonts');
187
+ expect(MathfieldElement.fontsDirectory).not.toContain('/dist/');
188
+ });
189
+ it('a configured path wins over the CDN', function () {
190
+ var MathfieldElement = {};
191
+ instance.__setMathLiveForTest({
192
+ MathfieldElement: MathfieldElement,
193
+ version: {
194
+ mathlive: '0.110.0'
195
+ }
196
+ });
197
+ instance.configureFonts('/mathlive-fonts');
198
+ expect(MathfieldElement.fontsDirectory).not.toContain('unpkg.com');
199
+ });
200
+ it('null still opts out entirely', function () {
201
+ var MathfieldElement = {};
202
+ instance.__setMathLiveForTest({
203
+ MathfieldElement: MathfieldElement,
204
+ version: {
205
+ mathlive: '0.110.0'
206
+ }
207
+ });
208
+ instance.configureFonts(null);
209
+ expect(MathfieldElement.fontsDirectory).toBeNull();
210
+ });
211
+ it('leaves a fully-qualified url untouched', function () {
212
+ var MathfieldElement = {};
213
+ instance.__setMathLiveForTest({
214
+ MathfieldElement: MathfieldElement
215
+ });
216
+ instance.configureFonts('https://cdn.example.com/fonts');
217
+ expect(MathfieldElement.fontsDirectory).toEqual('https://cdn.example.com/fonts');
218
+ });
219
+ it('passes null through rather than resolving it', function () {
220
+ var MathfieldElement = {};
221
+ instance.__setMathLiveForTest({
222
+ MathfieldElement: MathfieldElement
223
+ });
224
+ instance.configureFonts(null);
225
+ expect(MathfieldElement.fontsDirectory).toBeNull();
226
+ });
227
+ });
228
+
229
+ // A live <math-field> renders in shadow DOM, so nothing in the page's
230
+ // stylesheets reaches it - the stretchy-accent fix has to be injected there.
231
+ /**
232
+ * A keypad key like \frac inserts `\frac{#?}{#?}`; MathLive turns each `#?`
233
+ * into a `\placeholder{}` atom and *selects* the first one. Measured in
234
+ * Chromium: that atom is a leaf (its offsets are before/after, there is no
235
+ * position inside), so MathLive renders NO caret element and shows only the
236
+ * selection highlight - the box read as focused-but-dead. The caret is drawn
237
+ * by our own shadow CSS, gated on a class so it is placeholder-specific.
238
+ */
239
+ describe('trackPlaceholderCaret', function () {
240
+ var fakeField = function fakeField(selection, latex) {
241
+ var classes = new Set();
242
+ return {
243
+ listeners: {},
244
+ selection: selection,
245
+ selectionIsCollapsed: !selection,
246
+ getValue: function getValue() {
247
+ return latex;
248
+ },
249
+ classList: {
250
+ toggle: function toggle(name, on) {
251
+ return on ? classes.add(name) : classes["delete"](name);
252
+ },
253
+ contains: function contains(name) {
254
+ return classes.has(name);
255
+ }
256
+ },
257
+ addEventListener: function addEventListener(name, fn) {
258
+ this.listeners[name] = fn;
259
+ },
260
+ removeEventListener: function removeEventListener(name) {
261
+ delete this.listeners[name];
262
+ }
263
+ };
264
+ };
265
+ it('marks the host when a placeholder is selected', function () {
266
+ var mf = fakeField({
267
+ ranges: [[1, 2]]
268
+ }, '\\placeholder{}');
269
+ instance.trackPlaceholderCaret(mf);
270
+ expect(mf.classList.contains(instance.PLACEHOLDER_CARET_CLASS)).toBe(true);
271
+ });
272
+ it('does not mark an ordinary selection', function () {
273
+ var mf = fakeField({
274
+ ranges: [[0, 3]]
275
+ }, 'x+1');
276
+ instance.trackPlaceholderCaret(mf);
277
+ expect(mf.classList.contains(instance.PLACEHOLDER_CARET_CLASS)).toBe(false);
278
+ });
279
+ it('does not mark a collapsed selection, which has a real caret already', function () {
280
+ var mf = fakeField(null, '\\placeholder{}');
281
+ instance.trackPlaceholderCaret(mf);
282
+ expect(mf.classList.contains(instance.PLACEHOLDER_CARET_CLASS)).toBe(false);
283
+ });
284
+ it('leaves a named prompt alone - it takes a real caret inside', function () {
285
+ var mf = fakeField({
286
+ ranges: [[1, 2]]
287
+ }, '\\placeholder[r1]{}');
288
+ instance.trackPlaceholderCaret(mf);
289
+ expect(mf.classList.contains(instance.PLACEHOLDER_CARET_CLASS)).toBe(false);
290
+ });
291
+ it('re-evaluates whenever the selection moves', function () {
292
+ var mf = fakeField(null, '');
293
+ instance.trackPlaceholderCaret(mf);
294
+ expect(mf.classList.contains(instance.PLACEHOLDER_CARET_CLASS)).toBe(false);
295
+
296
+ // the caret lands on a placeholder
297
+ mf.selection = {
298
+ ranges: [[1, 2]]
299
+ };
300
+ mf.selectionIsCollapsed = false;
301
+ mf.getValue = function () {
302
+ return '\\placeholder{}';
303
+ };
304
+ mf.listeners['selection-change']();
305
+ expect(mf.classList.contains(instance.PLACEHOLDER_CARET_CLASS)).toBe(true);
306
+
307
+ // ...and moves off it again
308
+ mf.selectionIsCollapsed = true;
309
+ mf.listeners['selection-change']();
310
+ expect(mf.classList.contains(instance.PLACEHOLDER_CARET_CLASS)).toBe(false);
311
+ });
312
+ it('returns a teardown that detaches the listener', function () {
313
+ var mf = fakeField(null, '');
314
+ var off = instance.trackPlaceholderCaret(mf);
315
+ expect((0, _typeof2["default"])(mf.listeners['selection-change'])).toEqual('function');
316
+ off();
317
+ expect(mf.listeners['selection-change']).toBeUndefined();
318
+ });
319
+ it('survives a field that throws while reading the selection', function () {
320
+ var mf = fakeField({
321
+ ranges: [[1, 2]]
322
+ }, '');
323
+ mf.getValue = function () {
324
+ throw new Error('detached');
325
+ };
326
+ expect(function () {
327
+ return instance.trackPlaceholderCaret(mf);
328
+ }).not.toThrow();
329
+ expect(mf.classList.contains(instance.PLACEHOLDER_CARET_CLASS)).toBe(false);
330
+ });
331
+ it('is a no-op without a field', function () {
332
+ expect(instance.trackPlaceholderCaret(undefined)).toBeUndefined();
333
+ expect(instance.trackPlaceholderCaret({})).toBeUndefined();
334
+ });
335
+ });
336
+ describe('applyShadowStyles', function () {
337
+ var host = function host() {
338
+ var el = document.createElement('div');
339
+ el.attachShadow({
340
+ mode: 'open'
341
+ });
342
+ return el;
343
+ };
344
+ it('is a no-op without a shadow root', function () {
345
+ expect(function () {
346
+ return instance.applyShadowStyles(undefined);
347
+ }).not.toThrow();
348
+ expect(function () {
349
+ return instance.applyShadowStyles(document.createElement('div'));
350
+ }).not.toThrow();
351
+ });
352
+ it('injects the accent fix into the shadow root', function () {
353
+ var el = host();
354
+ instance.applyShadowStyles(el);
355
+ var viaSheet = el.shadowRoot.__pieAccentSheet;
356
+ var viaStyle = el.shadowRoot.querySelector('style[data-pie-accent]');
357
+ var css = viaSheet ? 'adopted' : viaStyle && viaStyle.textContent || '';
358
+ expect(viaSheet || viaStyle).toBeTruthy();
359
+ if (viaStyle) {
360
+ expect(css).toContain('margin-left:0 !important');
361
+ // scoped so single-glyph accents keep their centring offset
362
+ expect(css).toContain(':has(.ML__stretchy)');
363
+ }
364
+ });
365
+ it('injects the placeholder caret rules', function () {
366
+ var el = host();
367
+ instance.applyShadowStyles(el);
368
+ var viaStyle = el.shadowRoot.querySelector('style[data-pie-accent]');
369
+ if (viaStyle) {
370
+ var css = viaStyle.textContent;
371
+
372
+ // gated on the host class, so an ordinary selection gets no caret
373
+ expect(css).toContain(":host(.".concat(instance.PLACEHOLDER_CARET_CLASS, ")"));
374
+ // MathLive's own blink keyframes and caret colour, already in this root
375
+ expect(css).toContain('ML__caret-blink');
376
+ expect(css).toContain('--_caret-color');
377
+ // the innermost selected element only: MathLive marks a wrapper AND the
378
+ // glyph span, which would otherwise render two carets
379
+ expect(css).toContain('.ML__selected:not(:has(.ML__selected))');
380
+ }
381
+ });
382
+ it('injects the radical index size fix', function () {
383
+ var el = host();
384
+ instance.applyShadowStyles(el);
385
+ var viaStyle = el.shadowRoot.querySelector('style[data-pie-accent]');
386
+ if (viaStyle) {
387
+ var css = viaStyle.textContent;
388
+
389
+ // MathLive's scriptscriptstyle index (an inline 50%) reads too small in
390
+ // the authoring UI; a mathfield's shadow root needs its own copy of the
391
+ // rule, since host styles do not cross the boundary.
392
+ expect(css).toContain('.ML__sqrt-index >');
393
+ expect(css).toContain('font-size:75% !important');
394
+ }
395
+ });
396
+ it('does not inject twice', function () {
397
+ var el = host();
398
+ instance.applyShadowStyles(el);
399
+ instance.applyShadowStyles(el);
400
+ var styles = el.shadowRoot.querySelectorAll('style[data-pie-accent]');
401
+
402
+ // either one adopted sheet, or exactly one style node
403
+ expect(el.shadowRoot.__pieAccentSheet ? 1 : styles.length).toBe(1);
404
+ });
405
+ });
406
+ describe('latexToMarkup', function () {
407
+ it('returns empty string when MathLive is not loaded', function () {
408
+ expect(instance.latexToMarkup('\\pi')).toEqual('');
409
+ });
410
+ it('returns empty string for empty latex', function () {
411
+ expect(instance.latexToMarkup('')).toEqual('');
412
+ });
413
+ });
414
+ });
415
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJkZXNjcmliZSIsImluc3RhbmNlIiwiYmVmb3JlRWFjaCIsImplc3QiLCJyZXNldE1vZHVsZXMiLCJyZXF1aXJlIiwiX19yZXNldEVtYmVkcyIsIml0IiwicmVnaXN0ZXJFbWJlZCIsImh0bWxTdHJpbmciLCJsYXRleCIsImV4cGVjdCIsInJlZ2lzdGVyZWRFbWJlZHMiLCJ0b0VxdWFsIiwiZ2V0TWFjcm9zIiwiYW5zd2VyQmxvY2siLCJuZXdMaW5lIiwic29tZXRoaW5nQ3VzdG9tIiwibWF0aGxpdmVMYXRleCIsImN1c3RvbSIsIkVycm9yIiwibm90IiwidG9UaHJvdyIsInVuZGVmaW5lZCIsIm1hY3JvcyIsInBhcmFsbGVsb2dyYW0iLCJ0b0JlRGVmaW5lZCIsImxvbmdkaXYiLCJuYXBwcm94IiwiZm9yRWFjaCIsIm5hbWUiLCJfdHlwZW9mMiIsIlBJRV9NQUNST1MiLCJ0b0JlIiwidG9Db250YWluIiwiYXBwbHlTdGF0aWNNYXRoIiwidG9CZVVuZGVmaW5lZCIsImVsIiwiZG9jdW1lbnQiLCJjcmVhdGVFbGVtZW50IiwiX19zZXRNYXRoTGl2ZUZvclRlc3QiLCJjb252ZXJ0TGF0ZXhUb01hcmt1cCIsImwiLCJjb25jYXQiLCJpbm5lckhUTUwiLCJ0ZXh0Q29udGVudCIsImNvbmZpZ3VyZUZvbnRzIiwiTWF0aGZpZWxkRWxlbWVudCIsImZvbnRzRGlyZWN0b3J5IiwiYmFzZVVSSSIsInJlcGxhY2UiLCJzdGFydHNXaXRoIiwidmVyc2lvbiIsIm1hdGhsaXZlIiwidG9CZU51bGwiLCJmYWtlRmllbGQiLCJzZWxlY3Rpb24iLCJjbGFzc2VzIiwiU2V0IiwibGlzdGVuZXJzIiwic2VsZWN0aW9uSXNDb2xsYXBzZWQiLCJnZXRWYWx1ZSIsImNsYXNzTGlzdCIsInRvZ2dsZSIsIm9uIiwiYWRkIiwiY29udGFpbnMiLCJoYXMiLCJhZGRFdmVudExpc3RlbmVyIiwiZm4iLCJyZW1vdmVFdmVudExpc3RlbmVyIiwibWYiLCJyYW5nZXMiLCJ0cmFja1BsYWNlaG9sZGVyQ2FyZXQiLCJQTEFDRUhPTERFUl9DQVJFVF9DTEFTUyIsIm9mZiIsImhvc3QiLCJhdHRhY2hTaGFkb3ciLCJtb2RlIiwiYXBwbHlTaGFkb3dTdHlsZXMiLCJ2aWFTaGVldCIsInNoYWRvd1Jvb3QiLCJfX3BpZUFjY2VudFNoZWV0IiwidmlhU3R5bGUiLCJxdWVyeVNlbGVjdG9yIiwiY3NzIiwidG9CZVRydXRoeSIsInN0eWxlcyIsInF1ZXJ5U2VsZWN0b3JBbGwiLCJsZW5ndGgiLCJsYXRleFRvTWFya3VwIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL19fdGVzdHNfXy9tYXRobGl2ZS1pbnN0YW5jZS50ZXN0LmpzIl0sInNvdXJjZXNDb250ZW50IjpbImRlc2NyaWJlKCdtYXRobGl2ZS1pbnN0YW5jZScsICgpID0+IHtcbiAgbGV0IGluc3RhbmNlO1xuXG4gIGJlZm9yZUVhY2goKCkgPT4ge1xuICAgIGplc3QucmVzZXRNb2R1bGVzKCk7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGdsb2JhbC1yZXF1aXJlXG4gICAgaW5zdGFuY2UgPSByZXF1aXJlKCcuLi9tYXRobGl2ZS1pbnN0YW5jZScpO1xuICAgIGluc3RhbmNlLl9fcmVzZXRFbWJlZHMoKTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ3JlZ2lzdGVyRW1iZWQnLCAoKSA9PiB7XG4gICAgaXQoJ3JlZ2lzdGVycyBhIGtub3duIGVtYmVkIGFuZCBleHBvc2VzIGl0IGFzIGEgbWFjcm8nLCAoKSA9PiB7XG4gICAgICBpbnN0YW5jZS5yZWdpc3RlckVtYmVkKCdhbnN3ZXJCbG9jaycsICgpID0+ICh7XG4gICAgICAgIGh0bWxTdHJpbmc6ICc8ZGl2IGNsYXNzPVwiYW5zd2VyQmxvY2tcIj48L2Rpdj4nLFxuICAgICAgICBsYXRleDogKCkgPT4gJ1xcXFxlbWJlZHthbnN3ZXJCbG9ja31bXScsXG4gICAgICB9KSk7XG5cbiAgICAgIGV4cGVjdChpbnN0YW5jZS5yZWdpc3RlcmVkRW1iZWRzKCkpLnRvRXF1YWwoWydhbnN3ZXJCbG9jayddKTtcbiAgICAgIC8vIFRoZSBtYWNybyB0YWdzIG91dHB1dCB3aXRoIGRhdGEtZW1iZWQgc28gQ1NTIGNhbiB0YXJnZXQgaXQsIHJlcGxhY2luZ1xuICAgICAgLy8gTWF0aFF1aWxsJ3MgaHRtbFN0cmluZyBob29rLlxuICAgICAgZXhwZWN0KGluc3RhbmNlLmdldE1hY3JvcygpLmFuc3dlckJsb2NrKS50b0VxdWFsKCdcXFxcaHRtbERhdGF7ZW1iZWQ9YW5zd2VyQmxvY2t9e1xcXFxwbGFjZWhvbGRlcnt9fScpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3JlZ2lzdGVycyBuZXdMaW5lIGFzIGEgaGFybWxlc3MgbWFjcm8gKGl0IGlzIGhhbmRsZWQgYnkgbGF0ZXgtYnJpZGdlKScsICgpID0+IHtcbiAgICAgIGluc3RhbmNlLnJlZ2lzdGVyRW1iZWQoJ25ld0xpbmUnLCAoKSA9PiAoeyBsYXRleDogKCkgPT4gJ1xcXFxlbWJlZHtuZXdMaW5lfVtdJyB9KSk7XG5cbiAgICAgIGV4cGVjdChpbnN0YW5jZS5nZXRNYWNyb3MoKS5uZXdMaW5lKS50b0VxdWFsKCdcXFxcaHRtbERhdGF7ZW1iZWQ9bmV3TGluZX17fScpO1xuICAgIH0pO1xuXG4gICAgaXQoJ2ZhbGxzIGJhY2sgdG8gYSBwbGFjZWhvbGRlciBmb3IgYW4gdW5rbm93biBlbWJlZCcsICgpID0+IHtcbiAgICAgIGluc3RhbmNlLnJlZ2lzdGVyRW1iZWQoJ3NvbWV0aGluZ0N1c3RvbScsICgpID0+ICh7IGh0bWxTdHJpbmc6ICc8Yj54PC9iPicgfSkpO1xuXG4gICAgICBleHBlY3QoaW5zdGFuY2UuZ2V0TWFjcm9zKCkuc29tZXRoaW5nQ3VzdG9tKS50b0VxdWFsKCdcXFxcaHRtbERhdGF7ZW1iZWQ9c29tZXRoaW5nQ3VzdG9tfXtcXFxccGxhY2Vob2xkZXJ7fX0nKTtcbiAgICB9KTtcblxuICAgIGl0KCdob25vdXJzIGFuIGV4cGxpY2l0IG1hdGhsaXZlTGF0ZXggZnJvbSB0aGUgZmFjdG9yeScsICgpID0+IHtcbiAgICAgIGluc3RhbmNlLnJlZ2lzdGVyRW1iZWQoJ2N1c3RvbScsICgpID0+ICh7IG1hdGhsaXZlTGF0ZXg6ICdcXFxcYWxwaGEnIH0pKTtcblxuICAgICAgZXhwZWN0KGluc3RhbmNlLmdldE1hY3JvcygpLmN1c3RvbSkudG9FcXVhbCgnXFxcXGh0bWxEYXRhe2VtYmVkPWN1c3RvbX17XFxcXGFscGhhfScpO1xuICAgIH0pO1xuXG4gICAgaXQoJ2RvZXMgbm90IHRocm93IHdoZW4gdGhlIGZhY3RvcnkgdGhyb3dzJywgKCkgPT4ge1xuICAgICAgZXhwZWN0KCgpID0+XG4gICAgICAgIGluc3RhbmNlLnJlZ2lzdGVyRW1iZWQoJ2JhZCcsICgpID0+IHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2Jvb20nKTtcbiAgICAgICAgfSksXG4gICAgICApLm5vdC50b1Rocm93KCk7XG5cbiAgICAgIGV4cGVjdChpbnN0YW5jZS5yZWdpc3RlcmVkRW1iZWRzKCkpLnRvRXF1YWwoWydiYWQnXSk7XG4gICAgfSk7XG5cbiAgICBpdCgnaWdub3JlcyBiYWQgYXJndW1lbnRzJywgKCkgPT4ge1xuICAgICAgaW5zdGFuY2UucmVnaXN0ZXJFbWJlZCh1bmRlZmluZWQsICgpID0+ICh7fSkpO1xuICAgICAgaW5zdGFuY2UucmVnaXN0ZXJFbWJlZCgnbm9GYWN0b3J5JywgdW5kZWZpbmVkKTtcblxuICAgICAgZXhwZWN0KGluc3RhbmNlLnJlZ2lzdGVyZWRFbWJlZHMoKSkudG9FcXVhbChbXSk7XG4gICAgfSk7XG5cbiAgICBpdCgnYWx3YXlzIGluY2x1ZGVzIHRoZSBwaWUgbWFjcm8gc2V0JywgKCkgPT4ge1xuICAgICAgY29uc3QgbWFjcm9zID0gaW5zdGFuY2UuZ2V0TWFjcm9zKCk7XG5cbiAgICAgIGV4cGVjdChtYWNyb3MucGFyYWxsZWxvZ3JhbSkudG9CZURlZmluZWQoKTtcbiAgICAgIGV4cGVjdChtYWNyb3MubG9uZ2RpdikudG9CZURlZmluZWQoKTtcbiAgICAgIGV4cGVjdChtYWNyb3MubmFwcHJveCkudG9FcXVhbCgnXFxcXG5vdFxcXFxhcHByb3gnKTtcbiAgICB9KTtcblxuICAgIC8vIEFyZ3VtZW50LXRha2luZyBtYWNyb3MgZXhpc3Qgb25seSBzbyBwcmV2aW91c2x5IGF1dGhvcmVkIGxhdGV4IHBhcnNlcy5cbiAgICAvLyBFZGl0aW5nIG5ldmVyIGdvZXMgdGhyb3VnaCB0aGVtOiBNYXRoTGl2ZSBzZXJpYWxpc2VzIGEgbWFjcm8gZnJvbSBpdHNcbiAgICAvLyBvcmlnaW5hbCBhcmd1bWVudHMsIHNvIHR5cGVkIGNvbnRlbnQgbmV2ZXIgY29tZXMgYmFjayBvdXQuXG4gICAgaXQoJ2FyZ3VtZW50LXRha2luZyBtYWNyb3MgYXJlIHBsYWluIHBhcnNlLW9ubHkgZGVmaW5pdGlvbnMnLCAoKSA9PiB7XG4gICAgICBbJ2xvbmdkaXYnLCAnb3ZlcmFyYycsICdhYnMnXS5mb3JFYWNoKChuYW1lKSA9PiB7XG4gICAgICAgIGV4cGVjdCh0eXBlb2YgaW5zdGFuY2UuUElFX01BQ1JPU1tuYW1lXSkudG9CZSgnc3RyaW5nJyk7XG4gICAgICAgIGV4cGVjdChpbnN0YW5jZS5QSUVfTUFDUk9TW25hbWVdKS50b0NvbnRhaW4oJyMxJyk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGl0KCdhcmd1bWVudC1sZXNzIHN5bWJvbHMgc3RheSBhdG9taWMnLCAoKSA9PiB7XG4gICAgICBbJ3BlcnBlbmRpY3VsYXInLCAnc3F1YXJlJywgJ2RlZ3JlZScsICduYXBwcm94JywgJ3BhcmFsbGVsb2dyYW0nXS5mb3JFYWNoKChuYW1lKSA9PiB7XG4gICAgICAgIGV4cGVjdCh0eXBlb2YgaW5zdGFuY2UuUElFX01BQ1JPU1tuYW1lXSkudG9CZSgnc3RyaW5nJyk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGl0KCdsb25nZGl2IG1hdGNoZXMgdGhlIE1hdGhKYXggbWFjcm8gdXNlZCBieSBtYXRoLXJlbmRlcmluZycsICgpID0+IHtcbiAgICAgIGV4cGVjdChpbnN0YW5jZS5QSUVfTUFDUk9TLmxvbmdkaXYpLnRvRXF1YWwoJ1xcXFxlbmNsb3Nle2xvbmdkaXZ9eyMxfScpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnYXBwbHlTdGF0aWNNYXRoJywgKCkgPT4ge1xuICAgIGl0KCdyZXR1cm5zIHVuZGVmaW5lZCB3aXRob3V0IGFuIGVsZW1lbnQnLCAoKSA9PiB7XG4gICAgICBleHBlY3QoaW5zdGFuY2UuYXBwbHlTdGF0aWNNYXRoKG51bGwsICd4JykpLnRvQmVVbmRlZmluZWQoKTtcbiAgICB9KTtcblxuICAgIGl0KCdkZWZlcnMgKHJldHVybnMgdW5kZWZpbmVkKSB3aGVuIE1hdGhMaXZlIGhhcyBub3QgbG9hZGVkJywgKCkgPT4ge1xuICAgICAgY29uc3QgZWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcblxuICAgICAgZXhwZWN0KGluc3RhbmNlLmFwcGx5U3RhdGljTWF0aChlbCwgJ3gnKSkudG9CZVVuZGVmaW5lZCgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3JlbmRlcnMgc3luY2hyb25vdXNseSBvbmNlIE1hdGhMaXZlIGlzIGF2YWlsYWJsZScsICgpID0+IHtcbiAgICAgIGNvbnN0IGVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG5cbiAgICAgIGluc3RhbmNlLl9fc2V0TWF0aExpdmVGb3JUZXN0KHsgY29udmVydExhdGV4VG9NYXJrdXA6IChsKSA9PiBgPHNwYW4+JHtsfTwvc3Bhbj5gIH0pO1xuXG4gICAgICBleHBlY3QoaW5zdGFuY2UuYXBwbHlTdGF0aWNNYXRoKGVsLCAnXFxcXHBpJykpLnRvQmUoZWwpO1xuICAgICAgZXhwZWN0KGVsLmlubmVySFRNTCkudG9FcXVhbCgnPHNwYW4+XFxcXHBpPC9zcGFuPicpO1xuICAgIH0pO1xuXG4gICAgaXQoJ2ZhbGxzIGJhY2sgdG8gdGhlIGVsZW1lbnQgdGV4dENvbnRlbnQgd2hlbiBubyBsYXRleCBpcyBwYXNzZWQnLCAoKSA9PiB7XG4gICAgICBjb25zdCBlbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuXG4gICAgICBlbC50ZXh0Q29udGVudCA9ICdcXFxcdGhldGEnO1xuICAgICAgaW5zdGFuY2UuX19zZXRNYXRoTGl2ZUZvclRlc3QoeyBjb252ZXJ0TGF0ZXhUb01hcmt1cDogKGwpID0+IGA8aT4ke2x9PC9pPmAgfSk7XG4gICAgICBpbnN0YW5jZS5hcHBseVN0YXRpY01hdGgoZWwpO1xuXG4gICAgICBleHBlY3QoZWwuaW5uZXJIVE1MKS50b0VxdWFsKCc8aT5cXFxcdGhldGE8L2k+Jyk7XG4gICAgfSk7XG5cbiAgICBpdCgnYnJpZGdlcyBzdG9yZWQgbGF0ZXggKG5ld0xpbmUgZW1iZWQpIGJlZm9yZSByZW5kZXJpbmcnLCAoKSA9PiB7XG4gICAgICBjb25zdCBlbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuXG4gICAgICBpbnN0YW5jZS5fX3NldE1hdGhMaXZlRm9yVGVzdCh7IGNvbnZlcnRMYXRleFRvTWFya3VwOiAobCkgPT4gbCB9KTtcbiAgICAgIGluc3RhbmNlLmFwcGx5U3RhdGljTWF0aChlbCwgJ2FcXFxcZW1iZWR7bmV3TGluZX1bXWInKTtcblxuICAgICAgLy8gXFxlbWJlZHtuZXdMaW5lfVtdIG11c3QgYmVjb21lIGEgbXVsdGlsaW5lIGVudmlyb25tZW50XG4gICAgICBleHBlY3QoZWwuaW5uZXJIVE1MKS50b0NvbnRhaW4oJ2Rpc3BsYXlsaW5lcycpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnY29uZmlndXJlRm9udHMnLCAoKSA9PiB7XG4gICAgLy8gTWF0aExpdmUncyBkZWZhdWx0IGZvbnRzRGlyZWN0b3J5IGlzIHRoZSByZWxhdGl2ZSAnLi9mb250cy8nLCB3aGljaCBpdFxuICAgIC8vIHJlc29sdmVzIGFnYWluc3QgaXRzIG93biAoZW1wdHksIHdoZW4gYnVuZGxlZCkgc2NyaXB0IHVybCBhbmQgdGhyb3dzXG4gICAgLy8gXCJJbnZhbGlkIGJhc2UgVVJMXCIgZnJvbSBsb2FkRm9udHMuIFBhdGhzIG11c3QgYmVjb21lIGFic29sdXRlLlxuICAgIGl0KCdpcyBleHBvcnRlZCBhbmQgY2FsbGFibGUgYmVmb3JlIE1hdGhMaXZlIGxvYWRzJywgKCkgPT4ge1xuICAgICAgZXhwZWN0KHR5cGVvZiBpbnN0YW5jZS5jb25maWd1cmVGb250cykudG9CZSgnZnVuY3Rpb24nKTtcbiAgICAgIGV4cGVjdCgoKSA9PiBpbnN0YW5jZS5jb25maWd1cmVGb250cygnL21hdGhsaXZlLWZvbnRzJykpLm5vdC50b1Rocm93KCk7XG4gICAgfSk7XG5cbiAgICBpdCgnYWNjZXB0cyBudWxsIHRvIGRpc2FibGUgZm9udCBsb2FkaW5nJywgKCkgPT4ge1xuICAgICAgZXhwZWN0KCgpID0+IGluc3RhbmNlLmNvbmZpZ3VyZUZvbnRzKG51bGwpKS5ub3QudG9UaHJvdygpO1xuICAgIH0pO1xuXG4gICAgaXQoJ2FwcGxpZXMgYW4gYWJzb2x1dGUgdXJsIHRvIGFuIGFscmVhZHktbG9hZGVkIE1hdGhmaWVsZEVsZW1lbnQnLCAoKSA9PiB7XG4gICAgICBjb25zdCBNYXRoZmllbGRFbGVtZW50ID0ge307XG5cbiAgICAgIC8vIHNpbXVsYXRlIGEgbG9hZGVkIGluc3RhbmNlXG4gICAgICBpbnN0YW5jZS5fX3NldE1hdGhMaXZlRm9yVGVzdCh7IE1hdGhmaWVsZEVsZW1lbnQgfSk7XG4gICAgICBpbnN0YW5jZS5jb25maWd1cmVGb250cygnL21hdGhsaXZlLWZvbnRzJyk7XG5cbiAgICAgIGV4cGVjdChNYXRoZmllbGRFbGVtZW50LmZvbnRzRGlyZWN0b3J5KS50b0VxdWFsKGAke2RvY3VtZW50LmJhc2VVUkkucmVwbGFjZSgvXFwvJC8sICcnKX0vbWF0aGxpdmUtZm9udHNgKTtcbiAgICAgIGV4cGVjdChNYXRoZmllbGRFbGVtZW50LmZvbnRzRGlyZWN0b3J5LnN0YXJ0c1dpdGgoJ2h0dHAnKSkudG9CZSh0cnVlKTtcbiAgICB9KTtcblxuICAgIC8vIFxcbmVxLCBcXG5zaW0gYW5kIFxcbmNvbmcgYXJlIGJ1aWx0IGZyb20gUHJpdmF0ZSBVc2UgQXJlYSBnbHlwaHMgdGhhdCBvbmx5XG4gICAgLy8gdGhlIEthVGVYIGZvbnRzIGNvbnRhaW4sIHNvIFwibm8gZm9udHNcIiByZW5kZXJzIGdhcmJhZ2UgcmF0aGVyIHRoYW5cbiAgICAvLyBkZWdyYWRpbmcgZ3JhY2VmdWxseSAtIGhlbmNlIGEgQ0ROIGZhbGxiYWNrIGJ5IGRlZmF1bHQuXG4gICAgaXQoJ2ZhbGxzIGJhY2sgdG8gYSB2ZXJzaW9uLXBpbm5lZCBDRE4gd2hlbiBub3RoaW5nIGlzIGNvbmZpZ3VyZWQnLCAoKSA9PiB7XG4gICAgICBjb25zdCBNYXRoZmllbGRFbGVtZW50ID0ge307XG5cbiAgICAgIGluc3RhbmNlLl9fc2V0TWF0aExpdmVGb3JUZXN0KHsgTWF0aGZpZWxkRWxlbWVudCwgdmVyc2lvbjogeyBtYXRobGl2ZTogJzkuOS45JyB9IH0pO1xuICAgICAgaW5zdGFuY2UuY29uZmlndXJlRm9udHModW5kZWZpbmVkKTtcblxuICAgICAgZXhwZWN0KE1hdGhmaWVsZEVsZW1lbnQuZm9udHNEaXJlY3RvcnkpLnRvRXF1YWwoJ2h0dHBzOi8vdW5wa2cuY29tL21hdGhsaXZlQDkuOS45L2ZvbnRzJyk7XG4gICAgfSk7XG5cbiAgICBpdCgndXNlcyAvZm9udHMsIG5vdCAvZGlzdC9mb250cyAodGhlIGxhdHRlciA0MDRzIG9uIHVucGtnKScsICgpID0+IHtcbiAgICAgIGNvbnN0IE1hdGhmaWVsZEVsZW1lbnQgPSB7fTtcblxuICAgICAgaW5zdGFuY2UuX19zZXRNYXRoTGl2ZUZvclRlc3QoeyBNYXRoZmllbGRFbGVtZW50LCB2ZXJzaW9uOiB7IG1hdGhsaXZlOiAnMC4xMTAuMCcgfSB9KTtcbiAgICAgIGluc3RhbmNlLmNvbmZpZ3VyZUZvbnRzKHVuZGVmaW5lZCk7XG5cbiAgICAgIGV4cGVjdChNYXRoZmllbGRFbGVtZW50LmZvbnRzRGlyZWN0b3J5KS50b0VxdWFsKCdodHRwczovL3VucGtnLmNvbS9tYXRobGl2ZUAwLjExMC4wL2ZvbnRzJyk7XG4gICAgICBleHBlY3QoTWF0aGZpZWxkRWxlbWVudC5mb250c0RpcmVjdG9yeSkubm90LnRvQ29udGFpbignL2Rpc3QvJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnYSBjb25maWd1cmVkIHBhdGggd2lucyBvdmVyIHRoZSBDRE4nLCAoKSA9PiB7XG4gICAgICBjb25zdCBNYXRoZmllbGRFbGVtZW50ID0ge307XG5cbiAgICAgIGluc3RhbmNlLl9fc2V0TWF0aExpdmVGb3JUZXN0KHsgTWF0aGZpZWxkRWxlbWVudCwgdmVyc2lvbjogeyBtYXRobGl2ZTogJzAuMTEwLjAnIH0gfSk7XG4gICAgICBpbnN0YW5jZS5jb25maWd1cmVGb250cygnL21hdGhsaXZlLWZvbnRzJyk7XG5cbiAgICAgIGV4cGVjdChNYXRoZmllbGRFbGVtZW50LmZvbnRzRGlyZWN0b3J5KS5ub3QudG9Db250YWluKCd1bnBrZy5jb20nKTtcbiAgICB9KTtcblxuICAgIGl0KCdudWxsIHN0aWxsIG9wdHMgb3V0IGVudGlyZWx5JywgKCkgPT4ge1xuICAgICAgY29uc3QgTWF0aGZpZWxkRWxlbWVudCA9IHt9O1xuXG4gICAgICBpbnN0YW5jZS5fX3NldE1hdGhMaXZlRm9yVGVzdCh7IE1hdGhmaWVsZEVsZW1lbnQsIHZlcnNpb246IHsgbWF0aGxpdmU6ICcwLjExMC4wJyB9IH0pO1xuICAgICAgaW5zdGFuY2UuY29uZmlndXJlRm9udHMobnVsbCk7XG5cbiAgICAgIGV4cGVjdChNYXRoZmllbGRFbGVtZW50LmZvbnRzRGlyZWN0b3J5KS50b0JlTnVsbCgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ2xlYXZlcyBhIGZ1bGx5LXF1YWxpZmllZCB1cmwgdW50b3VjaGVkJywgKCkgPT4ge1xuICAgICAgY29uc3QgTWF0aGZpZWxkRWxlbWVudCA9IHt9O1xuXG4gICAgICBpbnN0YW5jZS5fX3NldE1hdGhMaXZlRm9yVGVzdCh7IE1hdGhmaWVsZEVsZW1lbnQgfSk7XG4gICAgICBpbnN0YW5jZS5jb25maWd1cmVGb250cygnaHR0cHM6Ly9jZG4uZXhhbXBsZS5jb20vZm9udHMnKTtcblxuICAgICAgZXhwZWN0KE1hdGhmaWVsZEVsZW1lbnQuZm9udHNEaXJlY3RvcnkpLnRvRXF1YWwoJ2h0dHBzOi8vY2RuLmV4YW1wbGUuY29tL2ZvbnRzJyk7XG4gICAgfSk7XG5cbiAgICBpdCgncGFzc2VzIG51bGwgdGhyb3VnaCByYXRoZXIgdGhhbiByZXNvbHZpbmcgaXQnLCAoKSA9PiB7XG4gICAgICBjb25zdCBNYXRoZmllbGRFbGVtZW50ID0ge307XG5cbiAgICAgIGluc3RhbmNlLl9fc2V0TWF0aExpdmVGb3JUZXN0KHsgTWF0aGZpZWxkRWxlbWVudCB9KTtcbiAgICAgIGluc3RhbmNlLmNvbmZpZ3VyZUZvbnRzKG51bGwpO1xuXG4gICAgICBleHBlY3QoTWF0aGZpZWxkRWxlbWVudC5mb250c0RpcmVjdG9yeSkudG9CZU51bGwoKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgLy8gQSBsaXZlIDxtYXRoLWZpZWxkPiByZW5kZXJzIGluIHNoYWRvdyBET00sIHNvIG5vdGhpbmcgaW4gdGhlIHBhZ2Unc1xuICAvLyBzdHlsZXNoZWV0cyByZWFjaGVzIGl0IC0gdGhlIHN0cmV0Y2h5LWFjY2VudCBmaXggaGFzIHRvIGJlIGluamVjdGVkIHRoZXJlLlxuICAvKipcbiAgICogQSBrZXlwYWQga2V5IGxpa2UgXFxmcmFjIGluc2VydHMgYFxcZnJhY3sjP317Iz99YDsgTWF0aExpdmUgdHVybnMgZWFjaCBgIz9gXG4gICAqIGludG8gYSBgXFxwbGFjZWhvbGRlcnt9YCBhdG9tIGFuZCAqc2VsZWN0cyogdGhlIGZpcnN0IG9uZS4gTWVhc3VyZWQgaW5cbiAgICogQ2hyb21pdW06IHRoYXQgYXRvbSBpcyBhIGxlYWYgKGl0cyBvZmZzZXRzIGFyZSBiZWZvcmUvYWZ0ZXIsIHRoZXJlIGlzIG5vXG4gICAqIHBvc2l0aW9uIGluc2lkZSksIHNvIE1hdGhMaXZlIHJlbmRlcnMgTk8gY2FyZXQgZWxlbWVudCBhbmQgc2hvd3Mgb25seSB0aGVcbiAgICogc2VsZWN0aW9uIGhpZ2hsaWdodCAtIHRoZSBib3ggcmVhZCBhcyBmb2N1c2VkLWJ1dC1kZWFkLiBUaGUgY2FyZXQgaXMgZHJhd25cbiAgICogYnkgb3VyIG93biBzaGFkb3cgQ1NTLCBnYXRlZCBvbiBhIGNsYXNzIHNvIGl0IGlzIHBsYWNlaG9sZGVyLXNwZWNpZmljLlxuICAgKi9cbiAgZGVzY3JpYmUoJ3RyYWNrUGxhY2Vob2xkZXJDYXJldCcsICgpID0+IHtcbiAgICBjb25zdCBmYWtlRmllbGQgPSAoc2VsZWN0aW9uLCBsYXRleCkgPT4ge1xuICAgICAgY29uc3QgY2xhc3NlcyA9IG5ldyBTZXQoKTtcblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgbGlzdGVuZXJzOiB7fSxcbiAgICAgICAgc2VsZWN0aW9uLFxuICAgICAgICBzZWxlY3Rpb25Jc0NvbGxhcHNlZDogIXNlbGVjdGlvbixcbiAgICAgICAgZ2V0VmFsdWU6ICgpID0+IGxhdGV4LFxuICAgICAgICBjbGFzc0xpc3Q6IHtcbiAgICAgICAgICB0b2dnbGU6IChuYW1lLCBvbikgPT4gKG9uID8gY2xhc3Nlcy5hZGQobmFtZSkgOiBjbGFzc2VzLmRlbGV0ZShuYW1lKSksXG4gICAgICAgICAgY29udGFpbnM6IChuYW1lKSA9PiBjbGFzc2VzLmhhcyhuYW1lKSxcbiAgICAgICAgfSxcbiAgICAgICAgYWRkRXZlbnRMaXN0ZW5lcihuYW1lLCBmbikge1xuICAgICAgICAgIHRoaXMubGlzdGVuZXJzW25hbWVdID0gZm47XG4gICAgICAgIH0sXG4gICAgICAgIHJlbW92ZUV2ZW50TGlzdGVuZXIobmFtZSkge1xuICAgICAgICAgIGRlbGV0ZSB0aGlzLmxpc3RlbmVyc1tuYW1lXTtcbiAgICAgICAgfSxcbiAgICAgIH07XG4gICAgfTtcblxuICAgIGl0KCdtYXJrcyB0aGUgaG9zdCB3aGVuIGEgcGxhY2Vob2xkZXIgaXMgc2VsZWN0ZWQnLCAoKSA9PiB7XG4gICAgICBjb25zdCBtZiA9IGZha2VGaWVsZCh7IHJhbmdlczogW1sxLCAyXV0gfSwgJ1xcXFxwbGFjZWhvbGRlcnt9Jyk7XG5cbiAgICAgIGluc3RhbmNlLnRyYWNrUGxhY2Vob2xkZXJDYXJldChtZik7XG5cbiAgICAgIGV4cGVjdChtZi5jbGFzc0xpc3QuY29udGFpbnMoaW5zdGFuY2UuUExBQ0VIT0xERVJfQ0FSRVRfQ0xBU1MpKS50b0JlKHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ2RvZXMgbm90IG1hcmsgYW4gb3JkaW5hcnkgc2VsZWN0aW9uJywgKCkgPT4ge1xuICAgICAgY29uc3QgbWYgPSBmYWtlRmllbGQoeyByYW5nZXM6IFtbMCwgM11dIH0sICd4KzEnKTtcblxuICAgICAgaW5zdGFuY2UudHJhY2tQbGFjZWhvbGRlckNhcmV0KG1mKTtcblxuICAgICAgZXhwZWN0KG1mLmNsYXNzTGlzdC5jb250YWlucyhpbnN0YW5jZS5QTEFDRUhPTERFUl9DQVJFVF9DTEFTUykpLnRvQmUoZmFsc2UpO1xuICAgIH0pO1xuXG4gICAgaXQoJ2RvZXMgbm90IG1hcmsgYSBjb2xsYXBzZWQgc2VsZWN0aW9uLCB3aGljaCBoYXMgYSByZWFsIGNhcmV0IGFscmVhZHknLCAoKSA9PiB7XG4gICAgICBjb25zdCBtZiA9IGZha2VGaWVsZChudWxsLCAnXFxcXHBsYWNlaG9sZGVye30nKTtcblxuICAgICAgaW5zdGFuY2UudHJhY2tQbGFjZWhvbGRlckNhcmV0KG1mKTtcblxuICAgICAgZXhwZWN0KG1mLmNsYXNzTGlzdC5jb250YWlucyhpbnN0YW5jZS5QTEFDRUhPTERFUl9DQVJFVF9DTEFTUykpLnRvQmUoZmFsc2UpO1xuICAgIH0pO1xuXG4gICAgaXQoJ2xlYXZlcyBhIG5hbWVkIHByb21wdCBhbG9uZSAtIGl0IHRha2VzIGEgcmVhbCBjYXJldCBpbnNpZGUnLCAoKSA9PiB7XG4gICAgICBjb25zdCBtZiA9IGZha2VGaWVsZCh7IHJhbmdlczogW1sxLCAyXV0gfSwgJ1xcXFxwbGFjZWhvbGRlcltyMV17fScpO1xuXG4gICAgICBpbnN0YW5jZS50cmFja1BsYWNlaG9sZGVyQ2FyZXQobWYpO1xuXG4gICAgICBleHBlY3QobWYuY2xhc3NMaXN0LmNvbnRhaW5zKGluc3RhbmNlLlBMQUNFSE9MREVSX0NBUkVUX0NMQVNTKSkudG9CZShmYWxzZSk7XG4gICAgfSk7XG5cbiAgICBpdCgncmUtZXZhbHVhdGVzIHdoZW5ldmVyIHRoZSBzZWxlY3Rpb24gbW92ZXMnLCAoKSA9PiB7XG4gICAgICBjb25zdCBtZiA9IGZha2VGaWVsZChudWxsLCAnJyk7XG5cbiAgICAgIGluc3RhbmNlLnRyYWNrUGxhY2Vob2xkZXJDYXJldChtZik7XG4gICAgICBleHBlY3QobWYuY2xhc3NMaXN0LmNvbnRhaW5zKGluc3RhbmNlLlBMQUNFSE9MREVSX0NBUkVUX0NMQVNTKSkudG9CZShmYWxzZSk7XG5cbiAgICAgIC8vIHRoZSBjYXJldCBsYW5kcyBvbiBhIHBsYWNlaG9sZGVyXG4gICAgICBtZi5zZWxlY3Rpb24gPSB7IHJhbmdlczogW1sxLCAyXV0gfTtcbiAgICAgIG1mLnNlbGVjdGlvbklzQ29sbGFwc2VkID0gZmFsc2U7XG4gICAgICBtZi5nZXRWYWx1ZSA9ICgpID0+ICdcXFxccGxhY2Vob2xkZXJ7fSc7XG4gICAgICBtZi5saXN0ZW5lcnNbJ3NlbGVjdGlvbi1jaGFuZ2UnXSgpO1xuICAgICAgZXhwZWN0KG1mLmNsYXNzTGlzdC5jb250YWlucyhpbnN0YW5jZS5QTEFDRUhPTERFUl9DQVJFVF9DTEFTUykpLnRvQmUodHJ1ZSk7XG5cbiAgICAgIC8vIC4uLmFuZCBtb3ZlcyBvZmYgaXQgYWdhaW5cbiAgICAgIG1mLnNlbGVjdGlvbklzQ29sbGFwc2VkID0gdHJ1ZTtcbiAgICAgIG1mLmxpc3RlbmVyc1snc2VsZWN0aW9uLWNoYW5nZSddKCk7XG4gICAgICBleHBlY3QobWYuY2xhc3NMaXN0LmNvbnRhaW5zKGluc3RhbmNlLlBMQUNFSE9MREVSX0NBUkVUX0NMQVNTKSkudG9CZShmYWxzZSk7XG4gICAgfSk7XG5cbiAgICBpdCgncmV0dXJucyBhIHRlYXJkb3duIHRoYXQgZGV0YWNoZXMgdGhlIGxpc3RlbmVyJywgKCkgPT4ge1xuICAgICAgY29uc3QgbWYgPSBmYWtlRmllbGQobnVsbCwgJycpO1xuICAgICAgY29uc3Qgb2ZmID0gaW5zdGFuY2UudHJhY2tQbGFjZWhvbGRlckNhcmV0KG1mKTtcblxuICAgICAgZXhwZWN0KHR5cGVvZiBtZi5saXN0ZW5lcnNbJ3NlbGVjdGlvbi1jaGFuZ2UnXSkudG9FcXVhbCgnZnVuY3Rpb24nKTtcbiAgICAgIG9mZigpO1xuICAgICAgZXhwZWN0KG1mLmxpc3RlbmVyc1snc2VsZWN0aW9uLWNoYW5nZSddKS50b0JlVW5kZWZpbmVkKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc3Vydml2ZXMgYSBmaWVsZCB0aGF0IHRocm93cyB3aGlsZSByZWFkaW5nIHRoZSBzZWxlY3Rpb24nLCAoKSA9PiB7XG4gICAgICBjb25zdCBtZiA9IGZha2VGaWVsZCh7IHJhbmdlczogW1sxLCAyXV0gfSwgJycpO1xuXG4gICAgICBtZi5nZXRWYWx1ZSA9ICgpID0+IHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdkZXRhY2hlZCcpO1xuICAgICAgfTtcblxuICAgICAgZXhwZWN0KCgpID0+IGluc3RhbmNlLnRyYWNrUGxhY2Vob2xkZXJDYXJldChtZikpLm5vdC50b1Rocm93KCk7XG4gICAgICBleHBlY3QobWYuY2xhc3NMaXN0LmNvbnRhaW5zKGluc3RhbmNlLlBMQUNFSE9MREVSX0NBUkVUX0NMQVNTKSkudG9CZShmYWxzZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnaXMgYSBuby1vcCB3aXRob3V0IGEgZmllbGQnLCAoKSA9PiB7XG4gICAgICBleHBlY3QoaW5zdGFuY2UudHJhY2tQbGFjZWhvbGRlckNhcmV0KHVuZGVmaW5lZCkpLnRvQmVVbmRlZmluZWQoKTtcbiAgICAgIGV4cGVjdChpbnN0YW5jZS50cmFja1BsYWNlaG9sZGVyQ2FyZXQoe30pKS50b0JlVW5kZWZpbmVkKCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdhcHBseVNoYWRvd1N0eWxlcycsICgpID0+IHtcbiAgICBjb25zdCBob3N0ID0gKCkgPT4ge1xuICAgICAgY29uc3QgZWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcblxuICAgICAgZWwuYXR0YWNoU2hhZG93KHsgbW9kZTogJ29wZW4nIH0pO1xuXG4gICAgICByZXR1cm4gZWw7XG4gICAgfTtcblxuICAgIGl0KCdpcyBhIG5vLW9wIHdpdGhvdXQgYSBzaGFkb3cgcm9vdCcsICgpID0+IHtcbiAgICAgIGV4cGVjdCgoKSA9PiBpbnN0YW5jZS5hcHBseVNoYWRvd1N0eWxlcyh1bmRlZmluZWQpKS5ub3QudG9UaHJvdygpO1xuICAgICAgZXhwZWN0KCgpID0+IGluc3RhbmNlLmFwcGx5U2hhZG93U3R5bGVzKGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpKSkubm90LnRvVGhyb3coKTtcbiAgICB9KTtcblxuICAgIGl0KCdpbmplY3RzIHRoZSBhY2NlbnQgZml4IGludG8gdGhlIHNoYWRvdyByb290JywgKCkgPT4ge1xuICAgICAgY29uc3QgZWwgPSBob3N0KCk7XG5cbiAgICAgIGluc3RhbmNlLmFwcGx5U2hhZG93U3R5bGVzKGVsKTtcblxuICAgICAgY29uc3QgdmlhU2hlZXQgPSBlbC5zaGFkb3dSb290Ll9fcGllQWNjZW50U2hlZXQ7XG4gICAgICBjb25zdCB2aWFTdHlsZSA9IGVsLnNoYWRvd1Jvb3QucXVlcnlTZWxlY3Rvcignc3R5bGVbZGF0YS1waWUtYWNjZW50XScpO1xuICAgICAgY29uc3QgY3NzID0gdmlhU2hlZXQgPyAnYWRvcHRlZCcgOiAodmlhU3R5bGUgJiYgdmlhU3R5bGUudGV4dENvbnRlbnQpIHx8ICcnO1xuXG4gICAgICBleHBlY3QodmlhU2hlZXQgfHwgdmlhU3R5bGUpLnRvQmVUcnV0aHkoKTtcblxuICAgICAgaWYgKHZpYVN0eWxlKSB7XG4gICAgICAgIGV4cGVjdChjc3MpLnRvQ29udGFpbignbWFyZ2luLWxlZnQ6MCAhaW1wb3J0YW50Jyk7XG4gICAgICAgIC8vIHNjb3BlZCBzbyBzaW5nbGUtZ2x5cGggYWNjZW50cyBrZWVwIHRoZWlyIGNlbnRyaW5nIG9mZnNldFxuICAgICAgICBleHBlY3QoY3NzKS50b0NvbnRhaW4oJzpoYXMoLk1MX19zdHJldGNoeSknKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGl0KCdpbmplY3RzIHRoZSBwbGFjZWhvbGRlciBjYXJldCBydWxlcycsICgpID0+IHtcbiAgICAgIGNvbnN0IGVsID0gaG9zdCgpO1xuXG4gICAgICBpbnN0YW5jZS5hcHBseVNoYWRvd1N0eWxlcyhlbCk7XG5cbiAgICAgIGNvbnN0IHZpYVN0eWxlID0gZWwuc2hhZG93Um9vdC5xdWVyeVNlbGVjdG9yKCdzdHlsZVtkYXRhLXBpZS1hY2NlbnRdJyk7XG5cbiAgICAgIGlmICh2aWFTdHlsZSkge1xuICAgICAgICBjb25zdCBjc3MgPSB2aWFTdHlsZS50ZXh0Q29udGVudDtcblxuICAgICAgICAvLyBnYXRlZCBvbiB0aGUgaG9zdCBjbGFzcywgc28gYW4gb3JkaW5hcnkgc2VsZWN0aW9uIGdldHMgbm8gY2FyZXRcbiAgICAgICAgZXhwZWN0KGNzcykudG9Db250YWluKGA6aG9zdCguJHtpbnN0YW5jZS5QTEFDRUhPTERFUl9DQVJFVF9DTEFTU30pYCk7XG4gICAgICAgIC8vIE1hdGhMaXZlJ3Mgb3duIGJsaW5rIGtleWZyYW1lcyBhbmQgY2FyZXQgY29sb3VyLCBhbHJlYWR5IGluIHRoaXMgcm9vdFxuICAgICAgICBleHBlY3QoY3NzKS50b0NvbnRhaW4oJ01MX19jYXJldC1ibGluaycpO1xuICAgICAgICBleHBlY3QoY3NzKS50b0NvbnRhaW4oJy0tX2NhcmV0LWNvbG9yJyk7XG4gICAgICAgIC8vIHRoZSBpbm5lcm1vc3Qgc2VsZWN0ZWQgZWxlbWVudCBvbmx5OiBNYXRoTGl2ZSBtYXJrcyBhIHdyYXBwZXIgQU5EIHRoZVxuICAgICAgICAvLyBnbHlwaCBzcGFuLCB3aGljaCB3b3VsZCBvdGhlcndpc2UgcmVuZGVyIHR3byBjYXJldHNcbiAgICAgICAgZXhwZWN0KGNzcykudG9Db250YWluKCcuTUxfX3NlbGVjdGVkOm5vdCg6aGFzKC5NTF9fc2VsZWN0ZWQpKScpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgaXQoJ2luamVjdHMgdGhlIHJhZGljYWwgaW5kZXggc2l6ZSBmaXgnLCAoKSA9PiB7XG4gICAgICBjb25zdCBlbCA9IGhvc3QoKTtcblxuICAgICAgaW5zdGFuY2UuYXBwbHlTaGFkb3dTdHlsZXMoZWwpO1xuXG4gICAgICBjb25zdCB2aWFTdHlsZSA9IGVsLnNoYWRvd1Jvb3QucXVlcnlTZWxlY3Rvcignc3R5bGVbZGF0YS1waWUtYWNjZW50XScpO1xuXG4gICAgICBpZiAodmlhU3R5bGUpIHtcbiAgICAgICAgY29uc3QgY3NzID0gdmlhU3R5bGUudGV4dENvbnRlbnQ7XG5cbiAgICAgICAgLy8gTWF0aExpdmUncyBzY3JpcHRzY3JpcHRzdHlsZSBpbmRleCAoYW4gaW5saW5lIDUwJSkgcmVhZHMgdG9vIHNtYWxsIGluXG4gICAgICAgIC8vIHRoZSBhdXRob3JpbmcgVUk7IGEgbWF0aGZpZWxkJ3Mgc2hhZG93IHJvb3QgbmVlZHMgaXRzIG93biBjb3B5IG9mIHRoZVxuICAgICAgICAvLyBydWxlLCBzaW5jZSBob3N0IHN0eWxlcyBkbyBub3QgY3Jvc3MgdGhlIGJvdW5kYXJ5LlxuICAgICAgICBleHBlY3QoY3NzKS50b0NvbnRhaW4oJy5NTF9fc3FydC1pbmRleCA+Jyk7XG4gICAgICAgIGV4cGVjdChjc3MpLnRvQ29udGFpbignZm9udC1zaXplOjc1JSAhaW1wb3J0YW50Jyk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBpdCgnZG9lcyBub3QgaW5qZWN0IHR3aWNlJywgKCkgPT4ge1xuICAgICAgY29uc3QgZWwgPSBob3N0KCk7XG5cbiAgICAgIGluc3RhbmNlLmFwcGx5U2hhZG93U3R5bGVzKGVsKTtcbiAgICAgIGluc3RhbmNlLmFwcGx5U2hhZG93U3R5bGVzKGVsKTtcblxuICAgICAgY29uc3Qgc3R5bGVzID0gZWwuc2hhZG93Um9vdC5xdWVyeVNlbGVjdG9yQWxsKCdzdHlsZVtkYXRhLXBpZS1hY2NlbnRdJyk7XG5cbiAgICAgIC8vIGVpdGhlciBvbmUgYWRvcHRlZCBzaGVldCwgb3IgZXhhY3RseSBvbmUgc3R5bGUgbm9kZVxuICAgICAgZXhwZWN0KGVsLnNoYWRvd1Jvb3QuX19waWVBY2NlbnRTaGVldCA/IDEgOiBzdHlsZXMubGVuZ3RoKS50b0JlKDEpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnbGF0ZXhUb01hcmt1cCcsICgpID0+IHtcbiAgICBpdCgncmV0dXJucyBlbXB0eSBzdHJpbmcgd2hlbiBNYXRoTGl2ZSBpcyBub3QgbG9hZGVkJywgKCkgPT4ge1xuICAgICAgZXhwZWN0KGluc3RhbmNlLmxhdGV4VG9NYXJrdXAoJ1xcXFxwaScpKS50b0VxdWFsKCcnKTtcbiAgICB9KTtcblxuICAgIGl0KCdyZXR1cm5zIGVtcHR5IHN0cmluZyBmb3IgZW1wdHkgbGF0ZXgnLCAoKSA9PiB7XG4gICAgICBleHBlY3QoaW5zdGFuY2UubGF0ZXhUb01hcmt1cCgnJykpLnRvRXF1YWwoJycpO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuIl0sIm1hcHBpbmdzIjoiOzs7O0FBQUFBLFFBQVEsQ0FBQyxtQkFBbUIsRUFBRSxZQUFNO0VBQ2xDLElBQUlDLFFBQVE7RUFFWkMsVUFBVSxDQUFDLFlBQU07SUFDZkMsSUFBSSxDQUFDQyxZQUFZLENBQUMsQ0FBQztJQUNuQjtJQUNBSCxRQUFRLEdBQUdJLE9BQU8sQ0FBQyxzQkFBc0IsQ0FBQztJQUMxQ0osUUFBUSxDQUFDSyxhQUFhLENBQUMsQ0FBQztFQUMxQixDQUFDLENBQUM7RUFFRk4sUUFBUSxDQUFDLGVBQWUsRUFBRSxZQUFNO0lBQzlCTyxFQUFFLENBQUMsbURBQW1ELEVBQUUsWUFBTTtNQUM1RE4sUUFBUSxDQUFDTyxhQUFhLENBQUMsYUFBYSxFQUFFO1FBQUEsT0FBTztVQUMzQ0MsVUFBVSxFQUFFLGlDQUFpQztVQUM3Q0MsS0FBSyxFQUFFLFNBQVBBLEtBQUtBLENBQUE7WUFBQSxPQUFRLHdCQUF3QjtVQUFBO1FBQ3ZDLENBQUM7TUFBQSxDQUFDLENBQUM7TUFFSEMsTUFBTSxDQUFDVixRQUFRLENBQUNXLGdCQUFn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