@pie-lib/math-input-mathlive 1.1.5-beta.5 → 1.1.5-beta.7
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.
- package/lib/__tests__/composites.test.js +255 -0
- package/lib/__tests__/drop-in-compat.test.js +133 -0
- package/lib/__tests__/embedded-fonts.test.js +121 -0
- package/lib/__tests__/index.test.js +118 -0
- package/lib/__tests__/input-imperative.test.js +155 -0
- package/lib/__tests__/keypad-label.test.js +229 -0
- package/lib/__tests__/keypad-render.test.js +206 -0
- package/lib/__tests__/latex-bridge.test.js +386 -0
- package/lib/__tests__/mathlive-instance.test.js +419 -0
- package/lib/__tests__/mount-race.test.js +218 -0
- package/lib/__tests__/static-prompts.test.js +405 -0
- package/lib/__tests__/tmp-markup.test.js +26 -0
- package/lib/latex-bridge.js +11 -2
- package/lib/latex-bridge.js.map +1 -1
- package/lib/mf/input.js +5 -0
- package/lib/mf/input.js.map +1 -1
- package/lib/mf/static.js +2 -0
- package/lib/mf/static.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/composites.test.jsx +220 -0
- package/src/__tests__/drop-in-compat.test.jsx +112 -0
- package/src/__tests__/index.test.jsx +109 -0
- package/src/__tests__/input-imperative.test.jsx +144 -0
- package/src/__tests__/keypad-label.test.jsx +271 -0
- package/src/__tests__/keypad-render.test.jsx +123 -0
- package/src/__tests__/latex-bridge.test.js +359 -0
- package/src/__tests__/mathlive-instance.test.js +418 -0
- package/src/__tests__/mount-race.test.jsx +142 -0
- package/src/__tests__/static-prompts.test.jsx +364 -0
- package/src/latex-bridge.js +11 -2
- package/src/mf/input.jsx +5 -0
- package/src/mf/static.jsx +2 -0
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
|
|
5
|
+
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
|
6
|
+
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
|
|
7
|
+
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
|
|
8
|
+
var _input = _interopRequireDefault(require("../mf/input"));
|
|
9
|
+
/**
|
|
10
|
+
* MathLive loads asynchronously, so `componentDidMount` resumes after an await
|
|
11
|
+
* before appending a <math-field>. Two orderings must both hold:
|
|
12
|
+
*
|
|
13
|
+
* - StrictMode dev double-mount (mount -> unmount -> mount on the SAME
|
|
14
|
+
* instance) must end up with exactly ONE field. A boolean "unmounted" flag
|
|
15
|
+
* latches here and blocks the remount entirely - which is why this uses a
|
|
16
|
+
* generation counter.
|
|
17
|
+
* - A genuine unmount while the load is in flight must append nothing.
|
|
18
|
+
*
|
|
19
|
+
* MathLive cannot load under jsdom, so it is mocked with a minimal stub in
|
|
20
|
+
* order to actually count appended fields.
|
|
21
|
+
*/
|
|
22
|
+
jest.mock('../mathlive-instance', function () {
|
|
23
|
+
// Must be a real DOM node: the component uses replaceChildren(), which
|
|
24
|
+
// rejects anything that is not a Node. Returning an element from the
|
|
25
|
+
// constructor replaces `this`, so callers get a genuine <math-field>.
|
|
26
|
+
var FakeMathfieldElement = /*#__PURE__*/(0, _createClass2["default"])(function FakeMathfieldElement() {
|
|
27
|
+
(0, _classCallCheck2["default"])(this, FakeMathfieldElement);
|
|
28
|
+
// `global` rather than `document`: jest forbids out-of-scope variables in
|
|
29
|
+
// a mock factory, and `global` is on its allow-list.
|
|
30
|
+
var el = global.document.createElement('math-field');
|
|
31
|
+
el.value = '';
|
|
32
|
+
el.getValue = function () {
|
|
33
|
+
return el.value;
|
|
34
|
+
};
|
|
35
|
+
return el;
|
|
36
|
+
});
|
|
37
|
+
return {
|
|
38
|
+
loadMathLive: function loadMathLive() {
|
|
39
|
+
return Promise.resolve({
|
|
40
|
+
MathfieldElement: FakeMathfieldElement
|
|
41
|
+
});
|
|
42
|
+
},
|
|
43
|
+
getMacros: function getMacros() {
|
|
44
|
+
return {};
|
|
45
|
+
},
|
|
46
|
+
// must mirror the real export, otherwise the component sets `undefined`
|
|
47
|
+
MATH_MODE_SPACE: '\\ ',
|
|
48
|
+
applyShadowStyles: function applyShadowStyles() {},
|
|
49
|
+
trackPlaceholderCaret: function trackPlaceholderCaret() {
|
|
50
|
+
return function () {};
|
|
51
|
+
},
|
|
52
|
+
latexToMarkup: function latexToMarkup(l) {
|
|
53
|
+
return "<span>".concat(l, "</span>");
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// eslint-disable-next-line import/first
|
|
59
|
+
|
|
60
|
+
var holderFor = function holderFor(cmp) {
|
|
61
|
+
var el = document.createElement('span');
|
|
62
|
+
cmp.holderRef = {
|
|
63
|
+
current: el
|
|
64
|
+
};
|
|
65
|
+
return el;
|
|
66
|
+
};
|
|
67
|
+
var fieldCount = function fieldCount(el) {
|
|
68
|
+
return Array.from(el.childNodes).filter(function (n) {
|
|
69
|
+
return n.tagName === 'MATH-FIELD';
|
|
70
|
+
}).length;
|
|
71
|
+
};
|
|
72
|
+
describe('async mount race', function () {
|
|
73
|
+
it('StrictMode mount -> unmount -> mount yields exactly one field', /*#__PURE__*/(0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee() {
|
|
74
|
+
var input, el, first, second;
|
|
75
|
+
return _regenerator["default"].wrap(function (_context) {
|
|
76
|
+
while (1) switch (_context.prev = _context.next) {
|
|
77
|
+
case 0:
|
|
78
|
+
input = new _input["default"]({});
|
|
79
|
+
el = holderFor(input);
|
|
80
|
+
first = input.componentDidMount();
|
|
81
|
+
input.componentWillUnmount();
|
|
82
|
+
second = input.componentDidMount();
|
|
83
|
+
_context.next = 1;
|
|
84
|
+
return Promise.all([first, second]);
|
|
85
|
+
case 1:
|
|
86
|
+
expect(fieldCount(el)).toBe(1);
|
|
87
|
+
expect(input.mathField).toBeDefined();
|
|
88
|
+
case 2:
|
|
89
|
+
case "end":
|
|
90
|
+
return _context.stop();
|
|
91
|
+
}
|
|
92
|
+
}, _callee);
|
|
93
|
+
})));
|
|
94
|
+
it('appends nothing when unmounted while the load is in flight', /*#__PURE__*/(0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee2() {
|
|
95
|
+
var input, el, pending;
|
|
96
|
+
return _regenerator["default"].wrap(function (_context2) {
|
|
97
|
+
while (1) switch (_context2.prev = _context2.next) {
|
|
98
|
+
case 0:
|
|
99
|
+
input = new _input["default"]({});
|
|
100
|
+
el = holderFor(input);
|
|
101
|
+
pending = input.componentDidMount();
|
|
102
|
+
input.componentWillUnmount();
|
|
103
|
+
_context2.next = 1;
|
|
104
|
+
return pending;
|
|
105
|
+
case 1:
|
|
106
|
+
expect(fieldCount(el)).toBe(0);
|
|
107
|
+
expect(input.mathField).toBeUndefined();
|
|
108
|
+
case 2:
|
|
109
|
+
case "end":
|
|
110
|
+
return _context2.stop();
|
|
111
|
+
}
|
|
112
|
+
}, _callee2);
|
|
113
|
+
})));
|
|
114
|
+
it('a normal single mount creates the field', /*#__PURE__*/(0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee3() {
|
|
115
|
+
var input, el;
|
|
116
|
+
return _regenerator["default"].wrap(function (_context3) {
|
|
117
|
+
while (1) switch (_context3.prev = _context3.next) {
|
|
118
|
+
case 0:
|
|
119
|
+
input = new _input["default"]({});
|
|
120
|
+
el = holderFor(input);
|
|
121
|
+
_context3.next = 1;
|
|
122
|
+
return input.componentDidMount();
|
|
123
|
+
case 1:
|
|
124
|
+
expect(fieldCount(el)).toBe(1);
|
|
125
|
+
case 2:
|
|
126
|
+
case "end":
|
|
127
|
+
return _context3.stop();
|
|
128
|
+
}
|
|
129
|
+
}, _callee3);
|
|
130
|
+
})));
|
|
131
|
+
it('repeated mounts never accumulate fields', /*#__PURE__*/(0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee4() {
|
|
132
|
+
var input, el;
|
|
133
|
+
return _regenerator["default"].wrap(function (_context4) {
|
|
134
|
+
while (1) switch (_context4.prev = _context4.next) {
|
|
135
|
+
case 0:
|
|
136
|
+
input = new _input["default"]({});
|
|
137
|
+
el = holderFor(input);
|
|
138
|
+
_context4.next = 1;
|
|
139
|
+
return input.componentDidMount();
|
|
140
|
+
case 1:
|
|
141
|
+
_context4.next = 2;
|
|
142
|
+
return input.componentDidMount();
|
|
143
|
+
case 2:
|
|
144
|
+
_context4.next = 3;
|
|
145
|
+
return input.componentDidMount();
|
|
146
|
+
case 3:
|
|
147
|
+
expect(fieldCount(el)).toBe(1);
|
|
148
|
+
case 4:
|
|
149
|
+
case "end":
|
|
150
|
+
return _context4.stop();
|
|
151
|
+
}
|
|
152
|
+
}, _callee4);
|
|
153
|
+
})));
|
|
154
|
+
|
|
155
|
+
// MathLive's mathModeSpace defaults to '', which makes the spacebar a no-op.
|
|
156
|
+
it('configures the spacebar so a space can be typed', /*#__PURE__*/(0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee5() {
|
|
157
|
+
var input;
|
|
158
|
+
return _regenerator["default"].wrap(function (_context5) {
|
|
159
|
+
while (1) switch (_context5.prev = _context5.next) {
|
|
160
|
+
case 0:
|
|
161
|
+
input = new _input["default"]({});
|
|
162
|
+
holderFor(input);
|
|
163
|
+
_context5.next = 1;
|
|
164
|
+
return input.componentDidMount();
|
|
165
|
+
case 1:
|
|
166
|
+
// a LaTeX control space - what MathQuill produced, and MathJax understands
|
|
167
|
+
expect(input.mathField.mathModeSpace).toEqual('\\ ');
|
|
168
|
+
expect(input.mathField.mathModeSpace).not.toEqual('');
|
|
169
|
+
case 2:
|
|
170
|
+
case "end":
|
|
171
|
+
return _context5.stop();
|
|
172
|
+
}
|
|
173
|
+
}, _callee5);
|
|
174
|
+
})));
|
|
175
|
+
|
|
176
|
+
// MathLive leaves a superscript after one digit by default (`smartSuperscript`),
|
|
177
|
+
// so x^23 / 10^6 cannot be typed.
|
|
178
|
+
it('stays in the exponent after a digit instead of jumping out', /*#__PURE__*/(0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee6() {
|
|
179
|
+
var input;
|
|
180
|
+
return _regenerator["default"].wrap(function (_context6) {
|
|
181
|
+
while (1) switch (_context6.prev = _context6.next) {
|
|
182
|
+
case 0:
|
|
183
|
+
input = new _input["default"]({});
|
|
184
|
+
holderFor(input);
|
|
185
|
+
_context6.next = 1;
|
|
186
|
+
return input.componentDidMount();
|
|
187
|
+
case 1:
|
|
188
|
+
expect(input.mathField.smartSuperscript).toBe(false);
|
|
189
|
+
case 2:
|
|
190
|
+
case "end":
|
|
191
|
+
return _context6.stop();
|
|
192
|
+
}
|
|
193
|
+
}, _callee6);
|
|
194
|
+
})));
|
|
195
|
+
it('reports itself through innerRef on mount and clears it on unmount', /*#__PURE__*/(0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee7() {
|
|
196
|
+
var innerRef, input;
|
|
197
|
+
return _regenerator["default"].wrap(function (_context7) {
|
|
198
|
+
while (1) switch (_context7.prev = _context7.next) {
|
|
199
|
+
case 0:
|
|
200
|
+
innerRef = jest.fn();
|
|
201
|
+
input = new _input["default"]({
|
|
202
|
+
innerRef: innerRef
|
|
203
|
+
});
|
|
204
|
+
holderFor(input);
|
|
205
|
+
_context7.next = 1;
|
|
206
|
+
return input.componentDidMount();
|
|
207
|
+
case 1:
|
|
208
|
+
expect(innerRef).toHaveBeenCalledWith(input);
|
|
209
|
+
input.componentWillUnmount();
|
|
210
|
+
expect(innerRef).toHaveBeenLastCalledWith(null);
|
|
211
|
+
case 2:
|
|
212
|
+
case "end":
|
|
213
|
+
return _context7.stop();
|
|
214
|
+
}
|
|
215
|
+
}, _callee7);
|
|
216
|
+
})));
|
|
217
|
+
});
|
|
218
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfaW5wdXQiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwicmVxdWlyZSIsImplc3QiLCJtb2NrIiwiRmFrZU1hdGhmaWVsZEVsZW1lbnQiLCJfY3JlYXRlQ2xhc3MyIiwiX2NsYXNzQ2FsbENoZWNrMiIsImVsIiwiZ2xvYmFsIiwiZG9jdW1lbnQiLCJjcmVhdGVFbGVtZW50IiwidmFsdWUiLCJnZXRWYWx1ZSIsImxvYWRNYXRoTGl2ZSIsIlByb21pc2UiLCJyZXNvbHZlIiwiTWF0aGZpZWxkRWxlbWVudCIsImdldE1hY3JvcyIsIk1BVEhfTU9ERV9TUEFDRSIsImFwcGx5U2hhZG93U3R5bGVzIiwidHJhY2tQbGFjZWhvbGRlckNhcmV0IiwibGF0ZXhUb01hcmt1cCIsImwiLCJjb25jYXQiLCJob2xkZXJGb3IiLCJjbXAiLCJob2xkZXJSZWYiLCJjdXJyZW50IiwiZmllbGRDb3VudCIsIkFycmF5IiwiZnJvbSIsImNoaWxkTm9kZXMiLCJmaWx0ZXIiLCJuIiwidGFnTmFtZSIsImxlbmd0aCIsImRlc2NyaWJlIiwiaXQiLCJfYXN5bmNUb0dlbmVyYXRvcjIiLCJfcmVnZW5lcmF0b3IiLCJtYXJrIiwiX2NhbGxlZSIsImlucHV0IiwiZmlyc3QiLCJzZWNvbmQiLCJ3cmFwIiwiX2NvbnRleHQiLCJwcmV2IiwibmV4dCIsIklucHV0IiwiY29tcG9uZW50RGlkTW91bnQiLCJjb21wb25lbnRXaWxsVW5tb3VudCIsImFsbCIsImV4cGVjdCIsInRvQmUiLCJtYXRoRmllbGQiLCJ0b0JlRGVmaW5lZCIsInN0b3AiLCJfY2FsbGVlMiIsInBlbmRpbmciLCJfY29udGV4dDIiLCJ0b0JlVW5kZWZpbmVkIiwiX2NhbGxlZTMiLCJfY29udGV4dDMiLCJfY2FsbGVlNCIsIl9jb250ZXh0NCIsIl9jYWxsZWU1IiwiX2NvbnRleHQ1IiwibWF0aE1vZGVTcGFjZSIsInRvRXF1YWwiLCJub3QiLCJfY2FsbGVlNiIsIl9jb250ZXh0NiIsInNtYXJ0U3VwZXJzY3JpcHQiLCJfY2FsbGVlNyIsImlubmVyUmVmIiwiX2NvbnRleHQ3IiwiZm4iLCJ0b0hhdmVCZWVuQ2FsbGVkV2l0aCIsInRvSGF2ZUJlZW5MYXN0Q2FsbGVkV2l0aCJdLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9fX3Rlc3RzX18vbW91bnQtcmFjZS50ZXN0LmpzeCJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIE1hdGhMaXZlIGxvYWRzIGFzeW5jaHJvbm91c2x5LCBzbyBgY29tcG9uZW50RGlkTW91bnRgIHJlc3VtZXMgYWZ0ZXIgYW4gYXdhaXRcbiAqIGJlZm9yZSBhcHBlbmRpbmcgYSA8bWF0aC1maWVsZD4uIFR3byBvcmRlcmluZ3MgbXVzdCBib3RoIGhvbGQ6XG4gKlxuICogIC0gU3RyaWN0TW9kZSBkZXYgZG91YmxlLW1vdW50IChtb3VudCAtPiB1bm1vdW50IC0+IG1vdW50IG9uIHRoZSBTQU1FXG4gKiAgICBpbnN0YW5jZSkgbXVzdCBlbmQgdXAgd2l0aCBleGFjdGx5IE9ORSBmaWVsZC4gQSBib29sZWFuIFwidW5tb3VudGVkXCIgZmxhZ1xuICogICAgbGF0Y2hlcyBoZXJlIGFuZCBibG9ja3MgdGhlIHJlbW91bnQgZW50aXJlbHkgLSB3aGljaCBpcyB3aHkgdGhpcyB1c2VzIGFcbiAqICAgIGdlbmVyYXRpb24gY291bnRlci5cbiAqICAtIEEgZ2VudWluZSB1bm1vdW50IHdoaWxlIHRoZSBsb2FkIGlzIGluIGZsaWdodCBtdXN0IGFwcGVuZCBub3RoaW5nLlxuICpcbiAqIE1hdGhMaXZlIGNhbm5vdCBsb2FkIHVuZGVyIGpzZG9tLCBzbyBpdCBpcyBtb2NrZWQgd2l0aCBhIG1pbmltYWwgc3R1YiBpblxuICogb3JkZXIgdG8gYWN0dWFsbHkgY291bnQgYXBwZW5kZWQgZmllbGRzLlxuICovXG5qZXN0Lm1vY2soJy4uL21hdGhsaXZlLWluc3RhbmNlJywgKCkgPT4ge1xuICAvLyBNdXN0IGJlIGEgcmVhbCBET00gbm9kZTogdGhlIGNvbXBvbmVudCB1c2VzIHJlcGxhY2VDaGlsZHJlbigpLCB3aGljaFxuICAvLyByZWplY3RzIGFueXRoaW5nIHRoYXQgaXMgbm90IGEgTm9kZS4gUmV0dXJuaW5nIGFuIGVsZW1lbnQgZnJvbSB0aGVcbiAgLy8gY29uc3RydWN0b3IgcmVwbGFjZXMgYHRoaXNgLCBzbyBjYWxsZXJzIGdldCBhIGdlbnVpbmUgPG1hdGgtZmllbGQ+LlxuICBjbGFzcyBGYWtlTWF0aGZpZWxkRWxlbWVudCB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAvLyBgZ2xvYmFsYCByYXRoZXIgdGhhbiBgZG9jdW1lbnRgOiBqZXN0IGZvcmJpZHMgb3V0LW9mLXNjb3BlIHZhcmlhYmxlcyBpblxuICAgICAgLy8gYSBtb2NrIGZhY3RvcnksIGFuZCBgZ2xvYmFsYCBpcyBvbiBpdHMgYWxsb3ctbGlzdC5cbiAgICAgIGNvbnN0IGVsID0gZ2xvYmFsLmRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ21hdGgtZmllbGQnKTtcblxuICAgICAgZWwudmFsdWUgPSAnJztcbiAgICAgIGVsLmdldFZhbHVlID0gKCkgPT4gZWwudmFsdWU7XG5cbiAgICAgIHJldHVybiBlbDtcbiAgICB9XG4gIH1cblxuICByZXR1cm4ge1xuICAgIGxvYWRNYXRoTGl2ZTogKCkgPT4gUHJvbWlzZS5yZXNvbHZlKHsgTWF0aGZpZWxkRWxlbWVudDogRmFrZU1hdGhmaWVsZEVsZW1lbnQgfSksXG4gICAgZ2V0TWFjcm9zOiAoKSA9PiAoe30pLFxuICAgIC8vIG11c3QgbWlycm9yIHRoZSByZWFsIGV4cG9ydCwgb3RoZXJ3aXNlIHRoZSBjb21wb25lbnQgc2V0cyBgdW5kZWZpbmVkYFxuICAgIE1BVEhfTU9ERV9TUEFDRTogJ1xcXFwgJyxcbiAgICBhcHBseVNoYWRvd1N0eWxlczogKCkgPT4ge30sXG4gICAgdHJhY2tQbGFjZWhvbGRlckNhcmV0OiAoKSA9PiAoKSA9PiB7fSxcbiAgICBsYXRleFRvTWFya3VwOiAobCkgPT4gYDxzcGFuPiR7bH08L3NwYW4+YCxcbiAgfTtcbn0pO1xuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L2ZpcnN0XG5pbXBvcnQgSW5wdXQgZnJvbSAnLi4vbWYvaW5wdXQnO1xuXG5jb25zdCBob2xkZXJGb3IgPSAoY21wKSA9PiB7XG4gIGNvbnN0IGVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3BhbicpO1xuXG4gIGNtcC5ob2xkZXJSZWYgPSB7IGN1cnJlbnQ6IGVsIH07XG5cbiAgcmV0dXJuIGVsO1xufTtcblxuY29uc3QgZmllbGRDb3VudCA9IChlbCkgPT4gQXJyYXkuZnJvbShlbC5jaGlsZE5vZGVzKS5maWx0ZXIoKG4pID0+IG4udGFnTmFtZSA9PT0gJ01BVEgtRklFTEQnKS5sZW5ndGg7XG5cbmRlc2NyaWJlKCdhc3luYyBtb3VudCByYWNlJywgKCkgPT4ge1xuICBpdCgnU3RyaWN0TW9kZSBtb3VudCAtPiB1bm1vdW50IC0+IG1vdW50IHlpZWxkcyBleGFjdGx5IG9uZSBmaWVsZCcsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBpbnB1dCA9IG5ldyBJbnB1dCh7fSk7XG4gICAgY29uc3QgZWwgPSBob2xkZXJGb3IoaW5wdXQpO1xuXG4gICAgY29uc3QgZmlyc3QgPSBpbnB1dC5jb21wb25lbnREaWRNb3VudCgpO1xuXG4gICAgaW5wdXQuY29tcG9uZW50V2lsbFVubW91bnQoKTtcblxuICAgIGNvbnN0IHNlY29uZCA9IGlucHV0LmNvbXBvbmVudERpZE1vdW50KCk7XG5cbiAgICBhd2FpdCBQcm9taXNlLmFsbChbZmlyc3QsIHNlY29uZF0pO1xuXG4gICAgZXhwZWN0KGZpZWxkQ291bnQoZWwpKS50b0JlKDEpO1xuICAgIGV4cGVjdChpbnB1dC5tYXRoRmllbGQpLnRvQmVEZWZpbmVkKCk7XG4gIH0pO1xuXG4gIGl0KCdhcHBlbmRzIG5vdGhpbmcgd2hlbiB1bm1vdW50ZWQgd2hpbGUgdGhlIGxvYWQgaXMgaW4gZmxpZ2h0JywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGlucHV0ID0gbmV3IElucHV0KHt9KTtcbiAgICBjb25zdCBlbCA9IGhvbGRlckZvcihpbnB1dCk7XG5cbiAgICBjb25zdCBwZW5kaW5nID0gaW5wdXQuY29tcG9uZW50RGlkTW91bnQoKTtcblxuICAgIGlucHV0LmNvbXBvbmVudFdpbGxVbm1vdW50KCk7XG5cbiAgICBhd2FpdCBwZW5kaW5nO1xuXG4gICAgZXhwZWN0KGZpZWxkQ291bnQoZWwpKS50b0JlKDApO1xuICAgIGV4cGVjdChpbnB1dC5tYXRoRmllbGQpLnRvQmVVbmRlZmluZWQoKTtcbiAgfSk7XG5cbiAgaXQoJ2Egbm9ybWFsIHNpbmdsZSBtb3VudCBjcmVhdGVzIHRoZSBmaWVsZCcsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBpbnB1dCA9IG5ldyBJbnB1dCh7fSk7XG4gICAgY29uc3QgZWwgPSBob2xkZXJGb3IoaW5wdXQpO1xuXG4gICAgYXdhaXQgaW5wdXQuY29tcG9uZW50RGlkTW91bnQoKTtcblxuICAgIGV4cGVjdChmaWVsZENvdW50KGVsKSkudG9CZSgxKTtcbiAgfSk7XG5cbiAgaXQoJ3JlcGVhdGVkIG1vdW50cyBuZXZlciBhY2N1bXVsYXRlIGZpZWxkcycsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBpbnB1dCA9IG5ldyBJbnB1dCh7fSk7XG4gICAgY29uc3QgZWwgPSBob2xkZXJGb3IoaW5wdXQpO1xuXG4gICAgYXdhaXQgaW5wdXQuY29tcG9uZW50RGlkTW91bnQoKTtcbiAgICBhd2FpdCBpbnB1dC5jb21wb25lbnREaWRNb3VudCgpO1xuICAgIGF3YWl0IGlucHV0LmNvbXBvbmVudERpZE1vdW50KCk7XG5cbiAgICBleHBlY3QoZmllbGRDb3VudChlbCkpLnRvQmUoMSk7XG4gIH0pO1xuXG4gIC8vIE1hdGhMaXZlJ3MgbWF0aE1vZGVTcGFjZSBkZWZhdWx0cyB0byAnJywgd2hpY2ggbWFrZXMgdGhlIHNwYWNlYmFyIGEgbm8tb3AuXG4gIGl0KCdjb25maWd1cmVzIHRoZSBzcGFjZWJhciBzbyBhIHNwYWNlIGNhbiBiZSB0eXBlZCcsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBpbnB1dCA9IG5ldyBJbnB1dCh7fSk7XG5cbiAgICBob2xkZXJGb3IoaW5wdXQpO1xuICAgIGF3YWl0IGlucHV0LmNvbXBvbmVudERpZE1vdW50KCk7XG5cbiAgICAvLyBhIExhVGVYIGNvbnRyb2wgc3BhY2UgLSB3aGF0IE1hdGhRdWlsbCBwcm9kdWNlZCwgYW5kIE1hdGhKYXggdW5kZXJzdGFuZHNcbiAgICBleHBlY3QoaW5wdXQubWF0aEZpZWxkLm1hdGhNb2RlU3BhY2UpLnRvRXF1YWwoJ1xcXFwgJyk7XG4gICAgZXhwZWN0KGlucHV0Lm1hdGhGaWVsZC5tYXRoTW9kZVNwYWNlKS5ub3QudG9FcXVhbCgnJyk7XG4gIH0pO1xuXG4gIC8vIE1hdGhMaXZlIGxlYXZlcyBhIHN1cGVyc2NyaXB0IGFmdGVyIG9uZSBkaWdpdCBieSBkZWZhdWx0IChgc21hcnRTdXBlcnNjcmlwdGApLFxuICAvLyBzbyB4XjIzIC8gMTBeNiBjYW5ub3QgYmUgdHlwZWQuXG4gIGl0KCdzdGF5cyBpbiB0aGUgZXhwb25lbnQgYWZ0ZXIgYSBkaWdpdCBpbnN0ZWFkIG9mIGp1bXBpbmcgb3V0JywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGlucHV0ID0gbmV3IElucHV0KHt9KTtcblxuICAgIGhvbGRlckZvcihpbnB1dCk7XG4gICAgYXdhaXQgaW5wdXQuY29tcG9uZW50RGlkTW91bnQoKTtcblxuICAgIGV4cGVjdChpbnB1dC5tYXRoRmllbGQuc21hcnRTdXBlcnNjcmlwdCkudG9CZShmYWxzZSk7XG4gIH0pO1xuXG4gIGl0KCdyZXBvcnRzIGl0c2VsZiB0aHJvdWdoIGlubmVyUmVmIG9uIG1vdW50IGFuZCBjbGVhcnMgaXQgb24gdW5tb3VudCcsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBpbm5lclJlZiA9IGplc3QuZm4oKTtcbiAgICBjb25zdCBpbnB1dCA9IG5ldyBJbnB1dCh7IGlubmVyUmVmIH0pO1xuXG4gICAgaG9sZGVyRm9yKGlucHV0KTtcbiAgICBhd2FpdCBpbnB1dC5jb21wb25lbnREaWRNb3VudCgpO1xuXG4gICAgZXhwZWN0KGlubmVyUmVmKS50b0hhdmVCZWVuQ2FsbGVkV2l0aChpbnB1dCk7XG5cbiAgICBpbnB1dC5jb21wb25lbnRXaWxsVW5tb3VudCgpO1xuXG4gICAgZXhwZWN0KGlubmVyUmVmKS50b0hhdmVCZWVuTGFzdENhbGxlZFdpdGgobnVsbCk7XG4gIH0pO1xufSk7XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUEwQ0EsSUFBQUEsTUFBQSxHQUFBQyxzQkFBQSxDQUFBQyxPQUFBO0FBMUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0FDLElBQUksQ0FBQ0MsSUFBSSxDQUFDLHNCQUFzQixFQUFFLFlBQU07RUFDdEM7RUFDQTtFQUNBO0VBQUEsSUFDTUMsb0JBQW9CLG9CQUFBQyxhQUFBLGFBQ3hCLFNBQUFELHFCQUFBLEVBQWM7SUFBQSxJQUFBRSxnQkFBQSxtQkFBQUYsb0JBQUE7SUFDWjtJQUNBO0lBQ0EsSUFBTUcsRUFBRSxHQUFHQyxNQUFNLENBQUNDLFFBQVEsQ0FBQ0MsYUFBYSxDQUFDLFlBQVksQ0FBQztJQUV0REgsRUFBRSxDQUFDSSxLQUFLLEdBQUcsRUFBRTtJQUNiSixFQUFFLENBQUNLLFFBQVEsR0FBRztNQUFBLE9BQU1MLEVBQUUsQ0FBQ0ksS0FBSztJQUFBO0lBRTVCLE9BQU9KLEVBQUU7RUFDWCxDQUFDO0VBR0gsT0FBTztJQUNMTSxZQUFZLEVBQUUsU0FBZEEsWUFBWUEsQ0FBQTtNQUFBLE9BQVFDLE9BQU8sQ0FBQ0MsT0FBTyxDQUFDO1FBQUVDLGdCQUFnQixFQUFFWjtNQUFxQixDQUFDLENBQUM7SUFBQTtJQUMvRWEsU0FBUyxFQUFFLFNBQVhBLFNBQVNBLENBQUE7TUFBQSxPQUFTLENBQUMsQ0FBQztJQUFBLENBQUM7SUFDckI7SUFDQUMsZUFBZSxFQUFFLEtBQUs7SUFDdEJDLGlCQUFpQixFQUFFLFNBQW5CQSxpQkFBaUJBLENBQUEsRUFBUSxDQUFDLENBQUM7SUFDM0JDLHFCQUFxQixFQUFFLFNBQXZCQSxxQkFBcUJBLENB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
|