@khanacademy/perseus-core 3.7.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/es/index.js CHANGED
@@ -1,2070 +1,8 @@
1
- import { seededRNG as seededRNG$1, shuffle as shuffle$2 } from '@khanacademy/perseus-core';
2
-
3
- /**
4
- * Adds the given perseus library version information to the __perseus_debug__
5
- * object and ensures that the object is attached to `globalThis` (`window` in
6
- * browser environments).
7
- *
8
- * This allows each library to provide runtime version information to assist in
9
- * debugging in production environments.
10
- */
11
- const addLibraryVersionToPerseusDebug = (libraryName, libraryVersion) => {
12
- // If the library version is the default value, then we don't want to
13
- // prefix it with a "v" to indicate that it is a version number.
14
- let prefix = "v";
15
- if (libraryVersion === "__lib_version__") {
16
- prefix = "";
17
- }
18
- const formattedVersion = `${prefix}${libraryVersion}`;
19
- if (typeof globalThis !== "undefined") {
20
- var _globalThis$__perseus;
21
- globalThis.__perseus_debug__ = (_globalThis$__perseus = globalThis.__perseus_debug__) != null ? _globalThis$__perseus : {};
22
- const existingVersionEntry = globalThis.__perseus_debug__[libraryName];
23
- if (existingVersionEntry) {
24
- // If we already have an entry and it doesn't match the registered
25
- // version, we morph the entry into an array and log a warning.
26
- if (existingVersionEntry !== formattedVersion) {
27
- // Existing entry might be an array already (oops, at least 2
28
- // versions of the library already loaded!).
29
- const allVersions = Array.isArray(existingVersionEntry) ? existingVersionEntry : [existingVersionEntry];
30
- allVersions.push(formattedVersion);
31
- globalThis.__perseus_debug__[libraryName] = allVersions;
32
-
33
- // eslint-disable-next-line no-console
34
- console.warn(`Multiple versions of ${libraryName} loaded on this page: ${allVersions.sort().join(", ")}`);
35
- }
36
- } else {
37
- globalThis.__perseus_debug__[libraryName] = formattedVersion;
38
- }
39
- } else {
40
- // eslint-disable-next-line no-console
41
- console.warn(`globalThis not found found (${formattedVersion})`);
42
- }
43
- };
44
-
45
- // Current version.
46
- var VERSION = '1.13.3';
47
-
48
- // Establish the root object, `window` (`self`) in the browser, `global`
49
- // on the server, or `this` in some virtual machines. We use `self`
50
- // instead of `window` for `WebWorker` support.
51
- var root = (typeof self == 'object' && self.self === self && self) ||
52
- (typeof global == 'object' && global.global === global && global) ||
53
- Function('return this')() ||
54
- {};
55
-
56
- // Save bytes in the minified (but not gzipped) version:
57
- var ArrayProto = Array.prototype, ObjProto = Object.prototype;
58
- var SymbolProto = typeof Symbol !== 'undefined' ? Symbol.prototype : null;
59
-
60
- // Create quick reference variables for speed access to core prototypes.
61
- var push = ArrayProto.push,
62
- slice = ArrayProto.slice,
63
- toString = ObjProto.toString,
64
- hasOwnProperty = ObjProto.hasOwnProperty;
65
-
66
- // Modern feature detection.
67
- var supportsArrayBuffer = typeof ArrayBuffer !== 'undefined',
68
- supportsDataView = typeof DataView !== 'undefined';
69
-
70
- // All **ECMAScript 5+** native function implementations that we hope to use
71
- // are declared here.
72
- var nativeIsArray = Array.isArray,
73
- nativeKeys = Object.keys,
74
- nativeCreate = Object.create,
75
- nativeIsView = supportsArrayBuffer && ArrayBuffer.isView;
76
-
77
- // Create references to these builtin functions because we override them.
78
- var _isNaN = isNaN,
79
- _isFinite = isFinite;
80
-
81
- // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed.
82
- var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString');
83
- var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',
84
- 'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'];
85
-
86
- // The largest integer that can be represented exactly.
87
- var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
88
-
89
- // Some functions take a variable number of arguments, or a few expected
90
- // arguments at the beginning and then a variable number of values to operate
91
- // on. This helper accumulates all remaining arguments past the function’s
92
- // argument length (or an explicit `startIndex`), into an array that becomes
93
- // the last argument. Similar to ES6’s "rest parameter".
94
- function restArguments(func, startIndex) {
95
- startIndex = startIndex == null ? func.length - 1 : +startIndex;
96
- return function() {
97
- var length = Math.max(arguments.length - startIndex, 0),
98
- rest = Array(length),
99
- index = 0;
100
- for (; index < length; index++) {
101
- rest[index] = arguments[index + startIndex];
102
- }
103
- switch (startIndex) {
104
- case 0: return func.call(this, rest);
105
- case 1: return func.call(this, arguments[0], rest);
106
- case 2: return func.call(this, arguments[0], arguments[1], rest);
107
- }
108
- var args = Array(startIndex + 1);
109
- for (index = 0; index < startIndex; index++) {
110
- args[index] = arguments[index];
111
- }
112
- args[startIndex] = rest;
113
- return func.apply(this, args);
114
- };
115
- }
116
-
117
- // Is a given variable an object?
118
- function isObject$1(obj) {
119
- var type = typeof obj;
120
- return type === 'function' || (type === 'object' && !!obj);
121
- }
122
-
123
- // Is a given value equal to null?
124
- function isNull(obj) {
125
- return obj === null;
126
- }
127
-
128
- // Is a given variable undefined?
129
- function isUndefined(obj) {
130
- return obj === void 0;
131
- }
132
-
133
- // Is a given value a boolean?
134
- function isBoolean(obj) {
135
- return obj === true || obj === false || toString.call(obj) === '[object Boolean]';
136
- }
137
-
138
- // Is a given value a DOM element?
139
- function isElement(obj) {
140
- return !!(obj && obj.nodeType === 1);
141
- }
142
-
143
- // Internal function for creating a `toString`-based type tester.
144
- function tagTester(name) {
145
- var tag = '[object ' + name + ']';
146
- return function(obj) {
147
- return toString.call(obj) === tag;
148
- };
149
- }
150
-
151
- var isString = tagTester('String');
152
-
153
- var isNumber = tagTester('Number');
154
-
155
- var isDate = tagTester('Date');
156
-
157
- var isRegExp = tagTester('RegExp');
158
-
159
- var isError = tagTester('Error');
160
-
161
- var isSymbol = tagTester('Symbol');
162
-
163
- var isArrayBuffer = tagTester('ArrayBuffer');
164
-
165
- var isFunction = tagTester('Function');
166
-
167
- // Optimize `isFunction` if appropriate. Work around some `typeof` bugs in old
168
- // v8, IE 11 (#1621), Safari 8 (#1929), and PhantomJS (#2236).
169
- var nodelist = root.document && root.document.childNodes;
170
- if (typeof /./ != 'function' && typeof Int8Array != 'object' && typeof nodelist != 'function') {
171
- isFunction = function(obj) {
172
- return typeof obj == 'function' || false;
173
- };
174
- }
175
-
176
- var isFunction$1 = isFunction;
177
-
178
- var hasObjectTag = tagTester('Object');
179
-
180
- // In IE 10 - Edge 13, `DataView` has string tag `'[object Object]'`.
181
- // In IE 11, the most common among them, this problem also applies to
182
- // `Map`, `WeakMap` and `Set`.
183
- var hasStringTagBug = (
184
- supportsDataView && hasObjectTag(new DataView(new ArrayBuffer(8)))
185
- ),
186
- isIE11 = (typeof Map !== 'undefined' && hasObjectTag(new Map));
187
-
188
- var isDataView = tagTester('DataView');
189
-
190
- // In IE 10 - Edge 13, we need a different heuristic
191
- // to determine whether an object is a `DataView`.
192
- function ie10IsDataView(obj) {
193
- return obj != null && isFunction$1(obj.getInt8) && isArrayBuffer(obj.buffer);
194
- }
195
-
196
- var isDataView$1 = (hasStringTagBug ? ie10IsDataView : isDataView);
197
-
198
- // Is a given value an array?
199
- // Delegates to ECMA5's native `Array.isArray`.
200
- var isArray = nativeIsArray || tagTester('Array');
201
-
202
- // Internal function to check whether `key` is an own property name of `obj`.
203
- function has$1(obj, key) {
204
- return obj != null && hasOwnProperty.call(obj, key);
205
- }
206
-
207
- var isArguments = tagTester('Arguments');
208
-
209
- // Define a fallback version of the method in browsers (ahem, IE < 9), where
210
- // there isn't any inspectable "Arguments" type.
211
- (function() {
212
- if (!isArguments(arguments)) {
213
- isArguments = function(obj) {
214
- return has$1(obj, 'callee');
215
- };
216
- }
217
- }());
218
-
219
- var isArguments$1 = isArguments;
220
-
221
- // Is a given object a finite number?
222
- function isFinite$1(obj) {
223
- return !isSymbol(obj) && _isFinite(obj) && !isNaN(parseFloat(obj));
224
- }
225
-
226
- // Is the given value `NaN`?
227
- function isNaN$1(obj) {
228
- return isNumber(obj) && _isNaN(obj);
229
- }
230
-
231
- // Predicate-generating function. Often useful outside of Underscore.
232
- function constant$1(value) {
233
- return function() {
234
- return value;
235
- };
236
- }
237
-
238
- // Common internal logic for `isArrayLike` and `isBufferLike`.
239
- function createSizePropertyCheck(getSizeProperty) {
240
- return function(collection) {
241
- var sizeProperty = getSizeProperty(collection);
242
- return typeof sizeProperty == 'number' && sizeProperty >= 0 && sizeProperty <= MAX_ARRAY_INDEX;
243
- }
244
- }
245
-
246
- // Internal helper to generate a function to obtain property `key` from `obj`.
247
- function shallowProperty(key) {
248
- return function(obj) {
249
- return obj == null ? void 0 : obj[key];
250
- };
251
- }
252
-
253
- // Internal helper to obtain the `byteLength` property of an object.
254
- var getByteLength = shallowProperty('byteLength');
255
-
256
- // Internal helper to determine whether we should spend extensive checks against
257
- // `ArrayBuffer` et al.
258
- var isBufferLike = createSizePropertyCheck(getByteLength);
259
-
260
- // Is a given value a typed array?
261
- var typedArrayPattern = /\[object ((I|Ui)nt(8|16|32)|Float(32|64)|Uint8Clamped|Big(I|Ui)nt64)Array\]/;
262
- function isTypedArray(obj) {
263
- // `ArrayBuffer.isView` is the most future-proof, so use it when available.
264
- // Otherwise, fall back on the above regular expression.
265
- return nativeIsView ? (nativeIsView(obj) && !isDataView$1(obj)) :
266
- isBufferLike(obj) && typedArrayPattern.test(toString.call(obj));
267
- }
268
-
269
- var isTypedArray$1 = supportsArrayBuffer ? isTypedArray : constant$1(false);
270
-
271
- // Internal helper to obtain the `length` property of an object.
272
- var getLength = shallowProperty('length');
273
-
274
- // Internal helper to create a simple lookup structure.
275
- // `collectNonEnumProps` used to depend on `_.contains`, but this led to
276
- // circular imports. `emulatedSet` is a one-off solution that only works for
277
- // arrays of strings.
278
- function emulatedSet(keys) {
279
- var hash = {};
280
- for (var l = keys.length, i = 0; i < l; ++i) hash[keys[i]] = true;
281
- return {
282
- contains: function(key) { return hash[key] === true; },
283
- push: function(key) {
284
- hash[key] = true;
285
- return keys.push(key);
286
- }
287
- };
288
- }
289
-
290
- // Internal helper. Checks `keys` for the presence of keys in IE < 9 that won't
291
- // be iterated by `for key in ...` and thus missed. Extends `keys` in place if
292
- // needed.
293
- function collectNonEnumProps(obj, keys) {
294
- keys = emulatedSet(keys);
295
- var nonEnumIdx = nonEnumerableProps.length;
296
- var constructor = obj.constructor;
297
- var proto = (isFunction$1(constructor) && constructor.prototype) || ObjProto;
298
-
299
- // Constructor is a special case.
300
- var prop = 'constructor';
301
- if (has$1(obj, prop) && !keys.contains(prop)) keys.push(prop);
302
-
303
- while (nonEnumIdx--) {
304
- prop = nonEnumerableProps[nonEnumIdx];
305
- if (prop in obj && obj[prop] !== proto[prop] && !keys.contains(prop)) {
306
- keys.push(prop);
307
- }
308
- }
309
- }
310
-
311
- // Retrieve the names of an object's own properties.
312
- // Delegates to **ECMAScript 5**'s native `Object.keys`.
313
- function keys(obj) {
314
- if (!isObject$1(obj)) return [];
315
- if (nativeKeys) return nativeKeys(obj);
316
- var keys = [];
317
- for (var key in obj) if (has$1(obj, key)) keys.push(key);
318
- // Ahem, IE < 9.
319
- if (hasEnumBug) collectNonEnumProps(obj, keys);
320
- return keys;
321
- }
322
-
323
- // Is a given array, string, or object empty?
324
- // An "empty" object has no enumerable own-properties.
325
- function isEmpty(obj) {
326
- if (obj == null) return true;
327
- // Skip the more expensive `toString`-based type checks if `obj` has no
328
- // `.length`.
329
- var length = getLength(obj);
330
- if (typeof length == 'number' && (
331
- isArray(obj) || isString(obj) || isArguments$1(obj)
332
- )) return length === 0;
333
- return getLength(keys(obj)) === 0;
334
- }
335
-
336
- // Returns whether an object has a given set of `key:value` pairs.
337
- function isMatch(object, attrs) {
338
- var _keys = keys(attrs), length = _keys.length;
339
- if (object == null) return !length;
340
- var obj = Object(object);
341
- for (var i = 0; i < length; i++) {
342
- var key = _keys[i];
343
- if (attrs[key] !== obj[key] || !(key in obj)) return false;
344
- }
345
- return true;
346
- }
347
-
348
- // If Underscore is called as a function, it returns a wrapped object that can
349
- // be used OO-style. This wrapper holds altered versions of all functions added
350
- // through `_.mixin`. Wrapped objects may be chained.
351
- function _$1(obj) {
352
- if (obj instanceof _$1) return obj;
353
- if (!(this instanceof _$1)) return new _$1(obj);
354
- this._wrapped = obj;
355
- }
356
-
357
- _$1.VERSION = VERSION;
358
-
359
- // Extracts the result from a wrapped and chained object.
360
- _$1.prototype.value = function() {
361
- return this._wrapped;
362
- };
363
-
364
- // Provide unwrapping proxies for some methods used in engine operations
365
- // such as arithmetic and JSON stringification.
366
- _$1.prototype.valueOf = _$1.prototype.toJSON = _$1.prototype.value;
367
-
368
- _$1.prototype.toString = function() {
369
- return String(this._wrapped);
370
- };
371
-
372
- // Internal function to wrap or shallow-copy an ArrayBuffer,
373
- // typed array or DataView to a new view, reusing the buffer.
374
- function toBufferView(bufferSource) {
375
- return new Uint8Array(
376
- bufferSource.buffer || bufferSource,
377
- bufferSource.byteOffset || 0,
378
- getByteLength(bufferSource)
379
- );
380
- }
381
-
382
- // We use this string twice, so give it a name for minification.
383
- var tagDataView = '[object DataView]';
384
-
385
- // Internal recursive comparison function for `_.isEqual`.
386
- function eq(a, b, aStack, bStack) {
387
- // Identical objects are equal. `0 === -0`, but they aren't identical.
388
- // See the [Harmony `egal` proposal](https://wiki.ecmascript.org/doku.php?id=harmony:egal).
389
- if (a === b) return a !== 0 || 1 / a === 1 / b;
390
- // `null` or `undefined` only equal to itself (strict comparison).
391
- if (a == null || b == null) return false;
392
- // `NaN`s are equivalent, but non-reflexive.
393
- if (a !== a) return b !== b;
394
- // Exhaust primitive checks
395
- var type = typeof a;
396
- if (type !== 'function' && type !== 'object' && typeof b != 'object') return false;
397
- return deepEq(a, b, aStack, bStack);
398
- }
399
-
400
- // Internal recursive comparison function for `_.isEqual`.
401
- function deepEq(a, b, aStack, bStack) {
402
- // Unwrap any wrapped objects.
403
- if (a instanceof _$1) a = a._wrapped;
404
- if (b instanceof _$1) b = b._wrapped;
405
- // Compare `[[Class]]` names.
406
- var className = toString.call(a);
407
- if (className !== toString.call(b)) return false;
408
- // Work around a bug in IE 10 - Edge 13.
409
- if (hasStringTagBug && className == '[object Object]' && isDataView$1(a)) {
410
- if (!isDataView$1(b)) return false;
411
- className = tagDataView;
412
- }
413
- switch (className) {
414
- // These types are compared by value.
415
- case '[object RegExp]':
416
- // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
417
- case '[object String]':
418
- // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
419
- // equivalent to `new String("5")`.
420
- return '' + a === '' + b;
421
- case '[object Number]':
422
- // `NaN`s are equivalent, but non-reflexive.
423
- // Object(NaN) is equivalent to NaN.
424
- if (+a !== +a) return +b !== +b;
425
- // An `egal` comparison is performed for other numeric values.
426
- return +a === 0 ? 1 / +a === 1 / b : +a === +b;
427
- case '[object Date]':
428
- case '[object Boolean]':
429
- // Coerce dates and booleans to numeric primitive values. Dates are compared by their
430
- // millisecond representations. Note that invalid dates with millisecond representations
431
- // of `NaN` are not equivalent.
432
- return +a === +b;
433
- case '[object Symbol]':
434
- return SymbolProto.valueOf.call(a) === SymbolProto.valueOf.call(b);
435
- case '[object ArrayBuffer]':
436
- case tagDataView:
437
- // Coerce to typed array so we can fall through.
438
- return deepEq(toBufferView(a), toBufferView(b), aStack, bStack);
439
- }
440
-
441
- var areArrays = className === '[object Array]';
442
- if (!areArrays && isTypedArray$1(a)) {
443
- var byteLength = getByteLength(a);
444
- if (byteLength !== getByteLength(b)) return false;
445
- if (a.buffer === b.buffer && a.byteOffset === b.byteOffset) return true;
446
- areArrays = true;
447
- }
448
- if (!areArrays) {
449
- if (typeof a != 'object' || typeof b != 'object') return false;
450
-
451
- // Objects with different constructors are not equivalent, but `Object`s or `Array`s
452
- // from different frames are.
453
- var aCtor = a.constructor, bCtor = b.constructor;
454
- if (aCtor !== bCtor && !(isFunction$1(aCtor) && aCtor instanceof aCtor &&
455
- isFunction$1(bCtor) && bCtor instanceof bCtor)
456
- && ('constructor' in a && 'constructor' in b)) {
457
- return false;
458
- }
459
- }
460
- // Assume equality for cyclic structures. The algorithm for detecting cyclic
461
- // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
462
-
463
- // Initializing stack of traversed objects.
464
- // It's done here since we only need them for objects and arrays comparison.
465
- aStack = aStack || [];
466
- bStack = bStack || [];
467
- var length = aStack.length;
468
- while (length--) {
469
- // Linear search. Performance is inversely proportional to the number of
470
- // unique nested structures.
471
- if (aStack[length] === a) return bStack[length] === b;
472
- }
473
-
474
- // Add the first object to the stack of traversed objects.
475
- aStack.push(a);
476
- bStack.push(b);
477
-
478
- // Recursively compare objects and arrays.
479
- if (areArrays) {
480
- // Compare array lengths to determine if a deep comparison is necessary.
481
- length = a.length;
482
- if (length !== b.length) return false;
483
- // Deep compare the contents, ignoring non-numeric properties.
484
- while (length--) {
485
- if (!eq(a[length], b[length], aStack, bStack)) return false;
486
- }
487
- } else {
488
- // Deep compare objects.
489
- var _keys = keys(a), key;
490
- length = _keys.length;
491
- // Ensure that both objects contain the same number of properties before comparing deep equality.
492
- if (keys(b).length !== length) return false;
493
- while (length--) {
494
- // Deep compare each member
495
- key = _keys[length];
496
- if (!(has$1(b, key) && eq(a[key], b[key], aStack, bStack))) return false;
497
- }
498
- }
499
- // Remove the first object from the stack of traversed objects.
500
- aStack.pop();
501
- bStack.pop();
502
- return true;
503
- }
504
-
505
- // Perform a deep comparison to check if two objects are equal.
506
- function isEqual(a, b) {
507
- return eq(a, b);
508
- }
509
-
510
- // Retrieve all the enumerable property names of an object.
511
- function allKeys(obj) {
512
- if (!isObject$1(obj)) return [];
513
- var keys = [];
514
- for (var key in obj) keys.push(key);
515
- // Ahem, IE < 9.
516
- if (hasEnumBug) collectNonEnumProps(obj, keys);
517
- return keys;
518
- }
519
-
520
- // Since the regular `Object.prototype.toString` type tests don't work for
521
- // some types in IE 11, we use a fingerprinting heuristic instead, based
522
- // on the methods. It's not great, but it's the best we got.
523
- // The fingerprint method lists are defined below.
524
- function ie11fingerprint(methods) {
525
- var length = getLength(methods);
526
- return function(obj) {
527
- if (obj == null) return false;
528
- // `Map`, `WeakMap` and `Set` have no enumerable keys.
529
- var keys = allKeys(obj);
530
- if (getLength(keys)) return false;
531
- for (var i = 0; i < length; i++) {
532
- if (!isFunction$1(obj[methods[i]])) return false;
533
- }
534
- // If we are testing against `WeakMap`, we need to ensure that
535
- // `obj` doesn't have a `forEach` method in order to distinguish
536
- // it from a regular `Map`.
537
- return methods !== weakMapMethods || !isFunction$1(obj[forEachName]);
538
- };
539
- }
540
-
541
- // In the interest of compact minification, we write
542
- // each string in the fingerprints only once.
543
- var forEachName = 'forEach',
544
- hasName = 'has',
545
- commonInit = ['clear', 'delete'],
546
- mapTail = ['get', hasName, 'set'];
547
-
548
- // `Map`, `WeakMap` and `Set` each have slightly different
549
- // combinations of the above sublists.
550
- var mapMethods = commonInit.concat(forEachName, mapTail),
551
- weakMapMethods = commonInit.concat(mapTail),
552
- setMethods = ['add'].concat(commonInit, forEachName, hasName);
553
-
554
- var isMap = isIE11 ? ie11fingerprint(mapMethods) : tagTester('Map');
555
-
556
- var isWeakMap = isIE11 ? ie11fingerprint(weakMapMethods) : tagTester('WeakMap');
557
-
558
- var isSet = isIE11 ? ie11fingerprint(setMethods) : tagTester('Set');
559
-
560
- var isWeakSet = tagTester('WeakSet');
561
-
562
- // Retrieve the values of an object's properties.
563
- function values(obj) {
564
- var _keys = keys(obj);
565
- var length = _keys.length;
566
- var values = Array(length);
567
- for (var i = 0; i < length; i++) {
568
- values[i] = obj[_keys[i]];
569
- }
570
- return values;
571
- }
572
-
573
- // Convert an object into a list of `[key, value]` pairs.
574
- // The opposite of `_.object` with one argument.
575
- function pairs(obj) {
576
- var _keys = keys(obj);
577
- var length = _keys.length;
578
- var pairs = Array(length);
579
- for (var i = 0; i < length; i++) {
580
- pairs[i] = [_keys[i], obj[_keys[i]]];
581
- }
582
- return pairs;
583
- }
584
-
585
- // Invert the keys and values of an object. The values must be serializable.
586
- function invert(obj) {
587
- var result = {};
588
- var _keys = keys(obj);
589
- for (var i = 0, length = _keys.length; i < length; i++) {
590
- result[obj[_keys[i]]] = _keys[i];
591
- }
592
- return result;
593
- }
594
-
595
- // Return a sorted list of the function names available on the object.
596
- function functions(obj) {
597
- var names = [];
598
- for (var key in obj) {
599
- if (isFunction$1(obj[key])) names.push(key);
600
- }
601
- return names.sort();
602
- }
603
-
604
- // An internal function for creating assigner functions.
605
- function createAssigner(keysFunc, defaults) {
606
- return function(obj) {
607
- var length = arguments.length;
608
- if (defaults) obj = Object(obj);
609
- if (length < 2 || obj == null) return obj;
610
- for (var index = 1; index < length; index++) {
611
- var source = arguments[index],
612
- keys = keysFunc(source),
613
- l = keys.length;
614
- for (var i = 0; i < l; i++) {
615
- var key = keys[i];
616
- if (!defaults || obj[key] === void 0) obj[key] = source[key];
617
- }
618
- }
619
- return obj;
620
- };
621
- }
622
-
623
- // Extend a given object with all the properties in passed-in object(s).
624
- var extend = createAssigner(allKeys);
625
-
626
- // Assigns a given object with all the own properties in the passed-in
627
- // object(s).
628
- // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)
629
- var extendOwn = createAssigner(keys);
630
-
631
- // Fill in a given object with default properties.
632
- var defaults = createAssigner(allKeys, true);
633
-
634
- // Create a naked function reference for surrogate-prototype-swapping.
635
- function ctor() {
636
- return function(){};
637
- }
638
-
639
- // An internal function for creating a new object that inherits from another.
640
- function baseCreate(prototype) {
641
- if (!isObject$1(prototype)) return {};
642
- if (nativeCreate) return nativeCreate(prototype);
643
- var Ctor = ctor();
644
- Ctor.prototype = prototype;
645
- var result = new Ctor;
646
- Ctor.prototype = null;
647
- return result;
648
- }
649
-
650
- // Creates an object that inherits from the given prototype object.
651
- // If additional properties are provided then they will be added to the
652
- // created object.
653
- function create(prototype, props) {
654
- var result = baseCreate(prototype);
655
- if (props) extendOwn(result, props);
656
- return result;
657
- }
658
-
659
- // Create a (shallow-cloned) duplicate of an object.
660
- function clone(obj) {
661
- if (!isObject$1(obj)) return obj;
662
- return isArray(obj) ? obj.slice() : extend({}, obj);
663
- }
664
-
665
- // Invokes `interceptor` with the `obj` and then returns `obj`.
666
- // The primary purpose of this method is to "tap into" a method chain, in
667
- // order to perform operations on intermediate results within the chain.
668
- function tap(obj, interceptor) {
669
- interceptor(obj);
670
- return obj;
671
- }
672
-
673
- // Normalize a (deep) property `path` to array.
674
- // Like `_.iteratee`, this function can be customized.
675
- function toPath$1(path) {
676
- return isArray(path) ? path : [path];
677
- }
678
- _$1.toPath = toPath$1;
679
-
680
- // Internal wrapper for `_.toPath` to enable minification.
681
- // Similar to `cb` for `_.iteratee`.
682
- function toPath(path) {
683
- return _$1.toPath(path);
684
- }
685
-
686
- // Internal function to obtain a nested property in `obj` along `path`.
687
- function deepGet(obj, path) {
688
- var length = path.length;
689
- for (var i = 0; i < length; i++) {
690
- if (obj == null) return void 0;
691
- obj = obj[path[i]];
692
- }
693
- return length ? obj : void 0;
694
- }
695
-
696
- // Get the value of the (deep) property on `path` from `object`.
697
- // If any property in `path` does not exist or if the value is
698
- // `undefined`, return `defaultValue` instead.
699
- // The `path` is normalized through `_.toPath`.
700
- function get(object, path, defaultValue) {
701
- var value = deepGet(object, toPath(path));
702
- return isUndefined(value) ? defaultValue : value;
703
- }
704
-
705
- // Shortcut function for checking if an object has a given property directly on
706
- // itself (in other words, not on a prototype). Unlike the internal `has`
707
- // function, this public version can also traverse nested properties.
708
- function has(obj, path) {
709
- path = toPath(path);
710
- var length = path.length;
711
- for (var i = 0; i < length; i++) {
712
- var key = path[i];
713
- if (!has$1(obj, key)) return false;
714
- obj = obj[key];
715
- }
716
- return !!length;
717
- }
718
-
719
- // Keep the identity function around for default iteratees.
720
- function identity(value) {
721
- return value;
722
- }
723
-
724
- // Returns a predicate for checking whether an object has a given set of
725
- // `key:value` pairs.
726
- function matcher(attrs) {
727
- attrs = extendOwn({}, attrs);
728
- return function(obj) {
729
- return isMatch(obj, attrs);
730
- };
731
- }
732
-
733
- // Creates a function that, when passed an object, will traverse that object’s
734
- // properties down the given `path`, specified as an array of keys or indices.
735
- function property(path) {
736
- path = toPath(path);
737
- return function(obj) {
738
- return deepGet(obj, path);
739
- };
740
- }
741
-
742
- // Internal function that returns an efficient (for current engines) version
743
- // of the passed-in callback, to be repeatedly applied in other Underscore
744
- // functions.
745
- function optimizeCb(func, context, argCount) {
746
- if (context === void 0) return func;
747
- switch (argCount == null ? 3 : argCount) {
748
- case 1: return function(value) {
749
- return func.call(context, value);
750
- };
751
- // The 2-argument case is omitted because we’re not using it.
752
- case 3: return function(value, index, collection) {
753
- return func.call(context, value, index, collection);
754
- };
755
- case 4: return function(accumulator, value, index, collection) {
756
- return func.call(context, accumulator, value, index, collection);
757
- };
758
- }
759
- return function() {
760
- return func.apply(context, arguments);
761
- };
762
- }
763
-
764
- // An internal function to generate callbacks that can be applied to each
765
- // element in a collection, returning the desired result — either `_.identity`,
766
- // an arbitrary callback, a property matcher, or a property accessor.
767
- function baseIteratee(value, context, argCount) {
768
- if (value == null) return identity;
769
- if (isFunction$1(value)) return optimizeCb(value, context, argCount);
770
- if (isObject$1(value) && !isArray(value)) return matcher(value);
771
- return property(value);
772
- }
773
-
774
- // External wrapper for our callback generator. Users may customize
775
- // `_.iteratee` if they want additional predicate/iteratee shorthand styles.
776
- // This abstraction hides the internal-only `argCount` argument.
777
- function iteratee(value, context) {
778
- return baseIteratee(value, context, Infinity);
779
- }
780
- _$1.iteratee = iteratee;
781
-
782
- // The function we call internally to generate a callback. It invokes
783
- // `_.iteratee` if overridden, otherwise `baseIteratee`.
784
- function cb(value, context, argCount) {
785
- if (_$1.iteratee !== iteratee) return _$1.iteratee(value, context);
786
- return baseIteratee(value, context, argCount);
787
- }
788
-
789
- // Returns the results of applying the `iteratee` to each element of `obj`.
790
- // In contrast to `_.map` it returns an object.
791
- function mapObject$1(obj, iteratee, context) {
792
- iteratee = cb(iteratee, context);
793
- var _keys = keys(obj),
794
- length = _keys.length,
795
- results = {};
796
- for (var index = 0; index < length; index++) {
797
- var currentKey = _keys[index];
798
- results[currentKey] = iteratee(obj[currentKey], currentKey, obj);
799
- }
800
- return results;
801
- }
802
-
803
- // Predicate-generating function. Often useful outside of Underscore.
804
- function noop(){}
805
-
806
- // Generates a function for a given object that returns a given property.
807
- function propertyOf(obj) {
808
- if (obj == null) return noop;
809
- return function(path) {
810
- return get(obj, path);
811
- };
812
- }
813
-
814
- // Run a function **n** times.
815
- function times(n, iteratee, context) {
816
- var accum = Array(Math.max(0, n));
817
- iteratee = optimizeCb(iteratee, context, 1);
818
- for (var i = 0; i < n; i++) accum[i] = iteratee(i);
819
- return accum;
820
- }
821
-
822
- // Return a random integer between `min` and `max` (inclusive).
823
- function random$1(min, max) {
824
- if (max == null) {
825
- max = min;
826
- min = 0;
827
- }
828
- return min + Math.floor(Math.random() * (max - min + 1));
829
- }
830
-
831
- // A (possibly faster) way to get the current timestamp as an integer.
832
- var now = Date.now || function() {
833
- return new Date().getTime();
834
- };
835
-
836
- // Internal helper to generate functions for escaping and unescaping strings
837
- // to/from HTML interpolation.
838
- function createEscaper(map) {
839
- var escaper = function(match) {
840
- return map[match];
841
- };
842
- // Regexes for identifying a key that needs to be escaped.
843
- var source = '(?:' + keys(map).join('|') + ')';
844
- var testRegexp = RegExp(source);
845
- var replaceRegexp = RegExp(source, 'g');
846
- return function(string) {
847
- string = string == null ? '' : '' + string;
848
- return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
849
- };
850
- }
851
-
852
- // Internal list of HTML entities for escaping.
853
- var escapeMap = {
854
- '&': '&amp;',
855
- '<': '&lt;',
856
- '>': '&gt;',
857
- '"': '&quot;',
858
- "'": '&#x27;',
859
- '`': '&#x60;'
860
- };
861
-
862
- // Function for escaping strings to HTML interpolation.
863
- var escape = createEscaper(escapeMap);
864
-
865
- // Internal list of HTML entities for unescaping.
866
- var unescapeMap = invert(escapeMap);
867
-
868
- // Function for unescaping strings from HTML interpolation.
869
- var unescape = createEscaper(unescapeMap);
870
-
871
- // By default, Underscore uses ERB-style template delimiters. Change the
872
- // following template settings to use alternative delimiters.
873
- var templateSettings = _$1.templateSettings = {
874
- evaluate: /<%([\s\S]+?)%>/g,
875
- interpolate: /<%=([\s\S]+?)%>/g,
876
- escape: /<%-([\s\S]+?)%>/g
877
- };
878
-
879
- // When customizing `_.templateSettings`, if you don't want to define an
880
- // interpolation, evaluation or escaping regex, we need one that is
881
- // guaranteed not to match.
882
- var noMatch = /(.)^/;
883
-
884
- // Certain characters need to be escaped so that they can be put into a
885
- // string literal.
886
- var escapes = {
887
- "'": "'",
888
- '\\': '\\',
889
- '\r': 'r',
890
- '\n': 'n',
891
- '\u2028': 'u2028',
892
- '\u2029': 'u2029'
893
- };
894
-
895
- var escapeRegExp = /\\|'|\r|\n|\u2028|\u2029/g;
896
-
897
- function escapeChar(match) {
898
- return '\\' + escapes[match];
899
- }
900
-
901
- // In order to prevent third-party code injection through
902
- // `_.templateSettings.variable`, we test it against the following regular
903
- // expression. It is intentionally a bit more liberal than just matching valid
904
- // identifiers, but still prevents possible loopholes through defaults or
905
- // destructuring assignment.
906
- var bareIdentifier = /^\s*(\w|\$)+\s*$/;
907
-
908
- // JavaScript micro-templating, similar to John Resig's implementation.
909
- // Underscore templating handles arbitrary delimiters, preserves whitespace,
910
- // and correctly escapes quotes within interpolated code.
911
- // NB: `oldSettings` only exists for backwards compatibility.
912
- function template(text, settings, oldSettings) {
913
- if (!settings && oldSettings) settings = oldSettings;
914
- settings = defaults({}, settings, _$1.templateSettings);
915
-
916
- // Combine delimiters into one regular expression via alternation.
917
- var matcher = RegExp([
918
- (settings.escape || noMatch).source,
919
- (settings.interpolate || noMatch).source,
920
- (settings.evaluate || noMatch).source
921
- ].join('|') + '|$', 'g');
922
-
923
- // Compile the template source, escaping string literals appropriately.
924
- var index = 0;
925
- var source = "__p+='";
926
- text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
927
- source += text.slice(index, offset).replace(escapeRegExp, escapeChar);
928
- index = offset + match.length;
929
-
930
- if (escape) {
931
- source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
932
- } else if (interpolate) {
933
- source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
934
- } else if (evaluate) {
935
- source += "';\n" + evaluate + "\n__p+='";
936
- }
937
-
938
- // Adobe VMs need the match returned to produce the correct offset.
939
- return match;
940
- });
941
- source += "';\n";
942
-
943
- var argument = settings.variable;
944
- if (argument) {
945
- // Insure against third-party code injection. (CVE-2021-23358)
946
- if (!bareIdentifier.test(argument)) throw new Error(
947
- 'variable is not a bare identifier: ' + argument
948
- );
949
- } else {
950
- // If a variable is not specified, place data values in local scope.
951
- source = 'with(obj||{}){\n' + source + '}\n';
952
- argument = 'obj';
953
- }
954
-
955
- source = "var __t,__p='',__j=Array.prototype.join," +
956
- "print=function(){__p+=__j.call(arguments,'');};\n" +
957
- source + 'return __p;\n';
958
-
959
- var render;
960
- try {
961
- render = new Function(argument, '_', source);
962
- } catch (e) {
963
- e.source = source;
964
- throw e;
965
- }
966
-
967
- var template = function(data) {
968
- return render.call(this, data, _$1);
969
- };
970
-
971
- // Provide the compiled source as a convenience for precompilation.
972
- template.source = 'function(' + argument + '){\n' + source + '}';
973
-
974
- return template;
975
- }
976
-
977
- // Traverses the children of `obj` along `path`. If a child is a function, it
978
- // is invoked with its parent as context. Returns the value of the final
979
- // child, or `fallback` if any child is undefined.
980
- function result(obj, path, fallback) {
981
- path = toPath(path);
982
- var length = path.length;
983
- if (!length) {
984
- return isFunction$1(fallback) ? fallback.call(obj) : fallback;
985
- }
986
- for (var i = 0; i < length; i++) {
987
- var prop = obj == null ? void 0 : obj[path[i]];
988
- if (prop === void 0) {
989
- prop = fallback;
990
- i = length; // Ensure we don't continue iterating.
991
- }
992
- obj = isFunction$1(prop) ? prop.call(obj) : prop;
993
- }
994
- return obj;
995
- }
996
-
997
- // Generate a unique integer id (unique within the entire client session).
998
- // Useful for temporary DOM ids.
999
- var idCounter = 0;
1000
- function uniqueId(prefix) {
1001
- var id = ++idCounter + '';
1002
- return prefix ? prefix + id : id;
1003
- }
1004
-
1005
- // Start chaining a wrapped Underscore object.
1006
- function chain(obj) {
1007
- var instance = _$1(obj);
1008
- instance._chain = true;
1009
- return instance;
1010
- }
1011
-
1012
- // Internal function to execute `sourceFunc` bound to `context` with optional
1013
- // `args`. Determines whether to execute a function as a constructor or as a
1014
- // normal function.
1015
- function executeBound(sourceFunc, boundFunc, context, callingContext, args) {
1016
- if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args);
1017
- var self = baseCreate(sourceFunc.prototype);
1018
- var result = sourceFunc.apply(self, args);
1019
- if (isObject$1(result)) return result;
1020
- return self;
1021
- }
1022
-
1023
- // Partially apply a function by creating a version that has had some of its
1024
- // arguments pre-filled, without changing its dynamic `this` context. `_` acts
1025
- // as a placeholder by default, allowing any combination of arguments to be
1026
- // pre-filled. Set `_.partial.placeholder` for a custom placeholder argument.
1027
- var partial = restArguments(function(func, boundArgs) {
1028
- var placeholder = partial.placeholder;
1029
- var bound = function() {
1030
- var position = 0, length = boundArgs.length;
1031
- var args = Array(length);
1032
- for (var i = 0; i < length; i++) {
1033
- args[i] = boundArgs[i] === placeholder ? arguments[position++] : boundArgs[i];
1034
- }
1035
- while (position < arguments.length) args.push(arguments[position++]);
1036
- return executeBound(func, bound, this, this, args);
1037
- };
1038
- return bound;
1039
- });
1040
-
1041
- partial.placeholder = _$1;
1042
-
1043
- // Create a function bound to a given object (assigning `this`, and arguments,
1044
- // optionally).
1045
- var bind = restArguments(function(func, context, args) {
1046
- if (!isFunction$1(func)) throw new TypeError('Bind must be called on a function');
1047
- var bound = restArguments(function(callArgs) {
1048
- return executeBound(func, bound, context, this, args.concat(callArgs));
1049
- });
1050
- return bound;
1051
- });
1052
-
1053
- // Internal helper for collection methods to determine whether a collection
1054
- // should be iterated as an array or as an object.
1055
- // Related: https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength
1056
- // Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094
1057
- var isArrayLike = createSizePropertyCheck(getLength);
1058
-
1059
- // Internal implementation of a recursive `flatten` function.
1060
- function flatten$1(input, depth, strict, output) {
1061
- output = output || [];
1062
- if (!depth && depth !== 0) {
1063
- depth = Infinity;
1064
- } else if (depth <= 0) {
1065
- return output.concat(input);
1066
- }
1067
- var idx = output.length;
1068
- for (var i = 0, length = getLength(input); i < length; i++) {
1069
- var value = input[i];
1070
- if (isArrayLike(value) && (isArray(value) || isArguments$1(value))) {
1071
- // Flatten current level of array or arguments object.
1072
- if (depth > 1) {
1073
- flatten$1(value, depth - 1, strict, output);
1074
- idx = output.length;
1075
- } else {
1076
- var j = 0, len = value.length;
1077
- while (j < len) output[idx++] = value[j++];
1078
- }
1079
- } else if (!strict) {
1080
- output[idx++] = value;
1081
- }
1082
- }
1083
- return output;
1084
- }
1085
-
1086
- // Bind a number of an object's methods to that object. Remaining arguments
1087
- // are the method names to be bound. Useful for ensuring that all callbacks
1088
- // defined on an object belong to it.
1089
- var bindAll = restArguments(function(obj, keys) {
1090
- keys = flatten$1(keys, false, false);
1091
- var index = keys.length;
1092
- if (index < 1) throw new Error('bindAll must be passed function names');
1093
- while (index--) {
1094
- var key = keys[index];
1095
- obj[key] = bind(obj[key], obj);
1096
- }
1097
- return obj;
1098
- });
1099
-
1100
- // Memoize an expensive function by storing its results.
1101
- function memoize(func, hasher) {
1102
- var memoize = function(key) {
1103
- var cache = memoize.cache;
1104
- var address = '' + (hasher ? hasher.apply(this, arguments) : key);
1105
- if (!has$1(cache, address)) cache[address] = func.apply(this, arguments);
1106
- return cache[address];
1107
- };
1108
- memoize.cache = {};
1109
- return memoize;
1110
- }
1111
-
1112
- // Delays a function for the given number of milliseconds, and then calls
1113
- // it with the arguments supplied.
1114
- var delay = restArguments(function(func, wait, args) {
1115
- return setTimeout(function() {
1116
- return func.apply(null, args);
1117
- }, wait);
1118
- });
1119
-
1120
- // Defers a function, scheduling it to run after the current call stack has
1121
- // cleared.
1122
- var defer = partial(delay, _$1, 1);
1123
-
1124
- // Returns a function, that, when invoked, will only be triggered at most once
1125
- // during a given window of time. Normally, the throttled function will run
1126
- // as much as it can, without ever going more than once per `wait` duration;
1127
- // but if you'd like to disable the execution on the leading edge, pass
1128
- // `{leading: false}`. To disable execution on the trailing edge, ditto.
1129
- function throttle(func, wait, options) {
1130
- var timeout, context, args, result;
1131
- var previous = 0;
1132
- if (!options) options = {};
1133
-
1134
- var later = function() {
1135
- previous = options.leading === false ? 0 : now();
1136
- timeout = null;
1137
- result = func.apply(context, args);
1138
- if (!timeout) context = args = null;
1139
- };
1140
-
1141
- var throttled = function() {
1142
- var _now = now();
1143
- if (!previous && options.leading === false) previous = _now;
1144
- var remaining = wait - (_now - previous);
1145
- context = this;
1146
- args = arguments;
1147
- if (remaining <= 0 || remaining > wait) {
1148
- if (timeout) {
1149
- clearTimeout(timeout);
1150
- timeout = null;
1151
- }
1152
- previous = _now;
1153
- result = func.apply(context, args);
1154
- if (!timeout) context = args = null;
1155
- } else if (!timeout && options.trailing !== false) {
1156
- timeout = setTimeout(later, remaining);
1157
- }
1158
- return result;
1159
- };
1160
-
1161
- throttled.cancel = function() {
1162
- clearTimeout(timeout);
1163
- previous = 0;
1164
- timeout = context = args = null;
1165
- };
1166
-
1167
- return throttled;
1168
- }
1169
-
1170
- // When a sequence of calls of the returned function ends, the argument
1171
- // function is triggered. The end of a sequence is defined by the `wait`
1172
- // parameter. If `immediate` is passed, the argument function will be
1173
- // triggered at the beginning of the sequence instead of at the end.
1174
- function debounce(func, wait, immediate) {
1175
- var timeout, previous, args, result, context;
1176
-
1177
- var later = function() {
1178
- var passed = now() - previous;
1179
- if (wait > passed) {
1180
- timeout = setTimeout(later, wait - passed);
1181
- } else {
1182
- timeout = null;
1183
- if (!immediate) result = func.apply(context, args);
1184
- // This check is needed because `func` can recursively invoke `debounced`.
1185
- if (!timeout) args = context = null;
1186
- }
1187
- };
1188
-
1189
- var debounced = restArguments(function(_args) {
1190
- context = this;
1191
- args = _args;
1192
- previous = now();
1193
- if (!timeout) {
1194
- timeout = setTimeout(later, wait);
1195
- if (immediate) result = func.apply(context, args);
1196
- }
1197
- return result;
1198
- });
1199
-
1200
- debounced.cancel = function() {
1201
- clearTimeout(timeout);
1202
- timeout = args = context = null;
1203
- };
1204
-
1205
- return debounced;
1206
- }
1207
-
1208
- // Returns the first function passed as an argument to the second,
1209
- // allowing you to adjust arguments, run code before and after, and
1210
- // conditionally execute the original function.
1211
- function wrap(func, wrapper) {
1212
- return partial(wrapper, func);
1213
- }
1214
-
1215
- // Returns a negated version of the passed-in predicate.
1216
- function negate(predicate) {
1217
- return function() {
1218
- return !predicate.apply(this, arguments);
1219
- };
1220
- }
1221
-
1222
- // Returns a function that is the composition of a list of functions, each
1223
- // consuming the return value of the function that follows.
1224
- function compose() {
1225
- var args = arguments;
1226
- var start = args.length - 1;
1227
- return function() {
1228
- var i = start;
1229
- var result = args[start].apply(this, arguments);
1230
- while (i--) result = args[i].call(this, result);
1231
- return result;
1232
- };
1233
- }
1234
-
1235
- // Returns a function that will only be executed on and after the Nth call.
1236
- function after(times, func) {
1237
- return function() {
1238
- if (--times < 1) {
1239
- return func.apply(this, arguments);
1240
- }
1241
- };
1242
- }
1243
-
1244
- // Returns a function that will only be executed up to (but not including) the
1245
- // Nth call.
1246
- function before(times, func) {
1247
- var memo;
1248
- return function() {
1249
- if (--times > 0) {
1250
- memo = func.apply(this, arguments);
1251
- }
1252
- if (times <= 1) func = null;
1253
- return memo;
1254
- };
1255
- }
1256
-
1257
- // Returns a function that will be executed at most one time, no matter how
1258
- // often you call it. Useful for lazy initialization.
1259
- var once = partial(before, 2);
1260
-
1261
- // Returns the first key on an object that passes a truth test.
1262
- function findKey(obj, predicate, context) {
1263
- predicate = cb(predicate, context);
1264
- var _keys = keys(obj), key;
1265
- for (var i = 0, length = _keys.length; i < length; i++) {
1266
- key = _keys[i];
1267
- if (predicate(obj[key], key, obj)) return key;
1268
- }
1269
- }
1270
-
1271
- // Internal function to generate `_.findIndex` and `_.findLastIndex`.
1272
- function createPredicateIndexFinder(dir) {
1273
- return function(array, predicate, context) {
1274
- predicate = cb(predicate, context);
1275
- var length = getLength(array);
1276
- var index = dir > 0 ? 0 : length - 1;
1277
- for (; index >= 0 && index < length; index += dir) {
1278
- if (predicate(array[index], index, array)) return index;
1279
- }
1280
- return -1;
1281
- };
1282
- }
1283
-
1284
- // Returns the first index on an array-like that passes a truth test.
1285
- var findIndex = createPredicateIndexFinder(1);
1286
-
1287
- // Returns the last index on an array-like that passes a truth test.
1288
- var findLastIndex = createPredicateIndexFinder(-1);
1289
-
1290
- // Use a comparator function to figure out the smallest index at which
1291
- // an object should be inserted so as to maintain order. Uses binary search.
1292
- function sortedIndex(array, obj, iteratee, context) {
1293
- iteratee = cb(iteratee, context, 1);
1294
- var value = iteratee(obj);
1295
- var low = 0, high = getLength(array);
1296
- while (low < high) {
1297
- var mid = Math.floor((low + high) / 2);
1298
- if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
1299
- }
1300
- return low;
1301
- }
1302
-
1303
- // Internal function to generate the `_.indexOf` and `_.lastIndexOf` functions.
1304
- function createIndexFinder(dir, predicateFind, sortedIndex) {
1305
- return function(array, item, idx) {
1306
- var i = 0, length = getLength(array);
1307
- if (typeof idx == 'number') {
1308
- if (dir > 0) {
1309
- i = idx >= 0 ? idx : Math.max(idx + length, i);
1310
- } else {
1311
- length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1;
1312
- }
1313
- } else if (sortedIndex && idx && length) {
1314
- idx = sortedIndex(array, item);
1315
- return array[idx] === item ? idx : -1;
1316
- }
1317
- if (item !== item) {
1318
- idx = predicateFind(slice.call(array, i, length), isNaN$1);
1319
- return idx >= 0 ? idx + i : -1;
1320
- }
1321
- for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) {
1322
- if (array[idx] === item) return idx;
1323
- }
1324
- return -1;
1325
- };
1326
- }
1327
-
1328
- // Return the position of the first occurrence of an item in an array,
1329
- // or -1 if the item is not included in the array.
1330
- // If the array is large and already in sort order, pass `true`
1331
- // for **isSorted** to use binary search.
1332
- var indexOf = createIndexFinder(1, findIndex, sortedIndex);
1333
-
1334
- // Return the position of the last occurrence of an item in an array,
1335
- // or -1 if the item is not included in the array.
1336
- var lastIndexOf = createIndexFinder(-1, findLastIndex);
1337
-
1338
- // Return the first value which passes a truth test.
1339
- function find(obj, predicate, context) {
1340
- var keyFinder = isArrayLike(obj) ? findIndex : findKey;
1341
- var key = keyFinder(obj, predicate, context);
1342
- if (key !== void 0 && key !== -1) return obj[key];
1343
- }
1344
-
1345
- // Convenience version of a common use case of `_.find`: getting the first
1346
- // object containing specific `key:value` pairs.
1347
- function findWhere(obj, attrs) {
1348
- return find(obj, matcher(attrs));
1349
- }
1350
-
1351
- // The cornerstone for collection functions, an `each`
1352
- // implementation, aka `forEach`.
1353
- // Handles raw objects in addition to array-likes. Treats all
1354
- // sparse array-likes as if they were dense.
1355
- function each(obj, iteratee, context) {
1356
- iteratee = optimizeCb(iteratee, context);
1357
- var i, length;
1358
- if (isArrayLike(obj)) {
1359
- for (i = 0, length = obj.length; i < length; i++) {
1360
- iteratee(obj[i], i, obj);
1361
- }
1362
- } else {
1363
- var _keys = keys(obj);
1364
- for (i = 0, length = _keys.length; i < length; i++) {
1365
- iteratee(obj[_keys[i]], _keys[i], obj);
1366
- }
1367
- }
1368
- return obj;
1369
- }
1370
-
1371
- // Return the results of applying the iteratee to each element.
1372
- function map(obj, iteratee, context) {
1373
- iteratee = cb(iteratee, context);
1374
- var _keys = !isArrayLike(obj) && keys(obj),
1375
- length = (_keys || obj).length,
1376
- results = Array(length);
1377
- for (var index = 0; index < length; index++) {
1378
- var currentKey = _keys ? _keys[index] : index;
1379
- results[index] = iteratee(obj[currentKey], currentKey, obj);
1380
- }
1381
- return results;
1382
- }
1383
-
1384
- // Internal helper to create a reducing function, iterating left or right.
1385
- function createReduce(dir) {
1386
- // Wrap code that reassigns argument variables in a separate function than
1387
- // the one that accesses `arguments.length` to avoid a perf hit. (#1991)
1388
- var reducer = function(obj, iteratee, memo, initial) {
1389
- var _keys = !isArrayLike(obj) && keys(obj),
1390
- length = (_keys || obj).length,
1391
- index = dir > 0 ? 0 : length - 1;
1392
- if (!initial) {
1393
- memo = obj[_keys ? _keys[index] : index];
1394
- index += dir;
1395
- }
1396
- for (; index >= 0 && index < length; index += dir) {
1397
- var currentKey = _keys ? _keys[index] : index;
1398
- memo = iteratee(memo, obj[currentKey], currentKey, obj);
1399
- }
1400
- return memo;
1401
- };
1402
-
1403
- return function(obj, iteratee, memo, context) {
1404
- var initial = arguments.length >= 3;
1405
- return reducer(obj, optimizeCb(iteratee, context, 4), memo, initial);
1406
- };
1407
- }
1408
-
1409
- // **Reduce** builds up a single result from a list of values, aka `inject`,
1410
- // or `foldl`.
1411
- var reduce = createReduce(1);
1412
-
1413
- // The right-associative version of reduce, also known as `foldr`.
1414
- var reduceRight = createReduce(-1);
1415
-
1416
- // Return all the elements that pass a truth test.
1417
- function filter(obj, predicate, context) {
1418
- var results = [];
1419
- predicate = cb(predicate, context);
1420
- each(obj, function(value, index, list) {
1421
- if (predicate(value, index, list)) results.push(value);
1422
- });
1423
- return results;
1424
- }
1425
-
1426
- // Return all the elements for which a truth test fails.
1427
- function reject(obj, predicate, context) {
1428
- return filter(obj, negate(cb(predicate)), context);
1429
- }
1430
-
1431
- // Determine whether all of the elements pass a truth test.
1432
- function every(obj, predicate, context) {
1433
- predicate = cb(predicate, context);
1434
- var _keys = !isArrayLike(obj) && keys(obj),
1435
- length = (_keys || obj).length;
1436
- for (var index = 0; index < length; index++) {
1437
- var currentKey = _keys ? _keys[index] : index;
1438
- if (!predicate(obj[currentKey], currentKey, obj)) return false;
1439
- }
1440
- return true;
1441
- }
1442
-
1443
- // Determine if at least one element in the object passes a truth test.
1444
- function some(obj, predicate, context) {
1445
- predicate = cb(predicate, context);
1446
- var _keys = !isArrayLike(obj) && keys(obj),
1447
- length = (_keys || obj).length;
1448
- for (var index = 0; index < length; index++) {
1449
- var currentKey = _keys ? _keys[index] : index;
1450
- if (predicate(obj[currentKey], currentKey, obj)) return true;
1451
- }
1452
- return false;
1453
- }
1454
-
1455
- // Determine if the array or object contains a given item (using `===`).
1456
- function contains(obj, item, fromIndex, guard) {
1457
- if (!isArrayLike(obj)) obj = values(obj);
1458
- if (typeof fromIndex != 'number' || guard) fromIndex = 0;
1459
- return indexOf(obj, item, fromIndex) >= 0;
1460
- }
1461
-
1462
- // Invoke a method (with arguments) on every item in a collection.
1463
- var invoke = restArguments(function(obj, path, args) {
1464
- var contextPath, func;
1465
- if (isFunction$1(path)) {
1466
- func = path;
1467
- } else {
1468
- path = toPath(path);
1469
- contextPath = path.slice(0, -1);
1470
- path = path[path.length - 1];
1471
- }
1472
- return map(obj, function(context) {
1473
- var method = func;
1474
- if (!method) {
1475
- if (contextPath && contextPath.length) {
1476
- context = deepGet(context, contextPath);
1477
- }
1478
- if (context == null) return void 0;
1479
- method = context[path];
1480
- }
1481
- return method == null ? method : method.apply(context, args);
1482
- });
1483
- });
1484
-
1485
- // Convenience version of a common use case of `_.map`: fetching a property.
1486
- function pluck$1(obj, key) {
1487
- return map(obj, property(key));
1488
- }
1489
-
1490
- // Convenience version of a common use case of `_.filter`: selecting only
1491
- // objects containing specific `key:value` pairs.
1492
- function where(obj, attrs) {
1493
- return filter(obj, matcher(attrs));
1494
- }
1495
-
1496
- // Return the maximum element (or element-based computation).
1497
- function max(obj, iteratee, context) {
1498
- var result = -Infinity, lastComputed = -Infinity,
1499
- value, computed;
1500
- if (iteratee == null || (typeof iteratee == 'number' && typeof obj[0] != 'object' && obj != null)) {
1501
- obj = isArrayLike(obj) ? obj : values(obj);
1502
- for (var i = 0, length = obj.length; i < length; i++) {
1503
- value = obj[i];
1504
- if (value != null && value > result) {
1505
- result = value;
1506
- }
1507
- }
1508
- } else {
1509
- iteratee = cb(iteratee, context);
1510
- each(obj, function(v, index, list) {
1511
- computed = iteratee(v, index, list);
1512
- if (computed > lastComputed || (computed === -Infinity && result === -Infinity)) {
1513
- result = v;
1514
- lastComputed = computed;
1515
- }
1516
- });
1517
- }
1518
- return result;
1519
- }
1520
-
1521
- // Return the minimum element (or element-based computation).
1522
- function min(obj, iteratee, context) {
1523
- var result = Infinity, lastComputed = Infinity,
1524
- value, computed;
1525
- if (iteratee == null || (typeof iteratee == 'number' && typeof obj[0] != 'object' && obj != null)) {
1526
- obj = isArrayLike(obj) ? obj : values(obj);
1527
- for (var i = 0, length = obj.length; i < length; i++) {
1528
- value = obj[i];
1529
- if (value != null && value < result) {
1530
- result = value;
1531
- }
1532
- }
1533
- } else {
1534
- iteratee = cb(iteratee, context);
1535
- each(obj, function(v, index, list) {
1536
- computed = iteratee(v, index, list);
1537
- if (computed < lastComputed || (computed === Infinity && result === Infinity)) {
1538
- result = v;
1539
- lastComputed = computed;
1540
- }
1541
- });
1542
- }
1543
- return result;
1544
- }
1545
-
1546
- // Safely create a real, live array from anything iterable.
1547
- var reStrSymbol = /[^\ud800-\udfff]|[\ud800-\udbff][\udc00-\udfff]|[\ud800-\udfff]/g;
1548
- function toArray(obj) {
1549
- if (!obj) return [];
1550
- if (isArray(obj)) return slice.call(obj);
1551
- if (isString(obj)) {
1552
- // Keep surrogate pair characters together.
1553
- return obj.match(reStrSymbol);
1554
- }
1555
- if (isArrayLike(obj)) return map(obj, identity);
1556
- return values(obj);
1557
- }
1558
-
1559
- // Sample **n** random values from a collection using the modern version of the
1560
- // [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
1561
- // If **n** is not specified, returns a single random element.
1562
- // The internal `guard` argument allows it to work with `_.map`.
1563
- function sample(obj, n, guard) {
1564
- if (n == null || guard) {
1565
- if (!isArrayLike(obj)) obj = values(obj);
1566
- return obj[random$1(obj.length - 1)];
1567
- }
1568
- var sample = toArray(obj);
1569
- var length = getLength(sample);
1570
- n = Math.max(Math.min(n, length), 0);
1571
- var last = length - 1;
1572
- for (var index = 0; index < n; index++) {
1573
- var rand = random$1(index, last);
1574
- var temp = sample[index];
1575
- sample[index] = sample[rand];
1576
- sample[rand] = temp;
1577
- }
1578
- return sample.slice(0, n);
1579
- }
1580
-
1581
- // Shuffle a collection.
1582
- function shuffle$1(obj) {
1583
- return sample(obj, Infinity);
1584
- }
1585
-
1586
- // Sort the object's values by a criterion produced by an iteratee.
1587
- function sortBy(obj, iteratee, context) {
1588
- var index = 0;
1589
- iteratee = cb(iteratee, context);
1590
- return pluck$1(map(obj, function(value, key, list) {
1591
- return {
1592
- value: value,
1593
- index: index++,
1594
- criteria: iteratee(value, key, list)
1595
- };
1596
- }).sort(function(left, right) {
1597
- var a = left.criteria;
1598
- var b = right.criteria;
1599
- if (a !== b) {
1600
- if (a > b || a === void 0) return 1;
1601
- if (a < b || b === void 0) return -1;
1602
- }
1603
- return left.index - right.index;
1604
- }), 'value');
1605
- }
1606
-
1607
- // An internal function used for aggregate "group by" operations.
1608
- function group(behavior, partition) {
1609
- return function(obj, iteratee, context) {
1610
- var result = partition ? [[], []] : {};
1611
- iteratee = cb(iteratee, context);
1612
- each(obj, function(value, index) {
1613
- var key = iteratee(value, index, obj);
1614
- behavior(result, value, key);
1615
- });
1616
- return result;
1617
- };
1618
- }
1619
-
1620
- // Groups the object's values by a criterion. Pass either a string attribute
1621
- // to group by, or a function that returns the criterion.
1622
- var groupBy = group(function(result, value, key) {
1623
- if (has$1(result, key)) result[key].push(value); else result[key] = [value];
1624
- });
1625
-
1626
- // Indexes the object's values by a criterion, similar to `_.groupBy`, but for
1627
- // when you know that your index values will be unique.
1628
- var indexBy = group(function(result, value, key) {
1629
- result[key] = value;
1630
- });
1631
-
1632
- // Counts instances of an object that group by a certain criterion. Pass
1633
- // either a string attribute to count by, or a function that returns the
1634
- // criterion.
1635
- var countBy = group(function(result, value, key) {
1636
- if (has$1(result, key)) result[key]++; else result[key] = 1;
1637
- });
1638
-
1639
- // Split a collection into two arrays: one whose elements all pass the given
1640
- // truth test, and one whose elements all do not pass the truth test.
1641
- var partition = group(function(result, value, pass) {
1642
- result[pass ? 0 : 1].push(value);
1643
- }, true);
1644
-
1645
- // Return the number of elements in a collection.
1646
- function size(obj) {
1647
- if (obj == null) return 0;
1648
- return isArrayLike(obj) ? obj.length : keys(obj).length;
1649
- }
1650
-
1651
- // Internal `_.pick` helper function to determine whether `key` is an enumerable
1652
- // property name of `obj`.
1653
- function keyInObj(value, key, obj) {
1654
- return key in obj;
1655
- }
1656
-
1657
- // Return a copy of the object only containing the allowed properties.
1658
- var pick = restArguments(function(obj, keys) {
1659
- var result = {}, iteratee = keys[0];
1660
- if (obj == null) return result;
1661
- if (isFunction$1(iteratee)) {
1662
- if (keys.length > 1) iteratee = optimizeCb(iteratee, keys[1]);
1663
- keys = allKeys(obj);
1664
- } else {
1665
- iteratee = keyInObj;
1666
- keys = flatten$1(keys, false, false);
1667
- obj = Object(obj);
1668
- }
1669
- for (var i = 0, length = keys.length; i < length; i++) {
1670
- var key = keys[i];
1671
- var value = obj[key];
1672
- if (iteratee(value, key, obj)) result[key] = value;
1673
- }
1674
- return result;
1675
- });
1676
-
1677
- // Return a copy of the object without the disallowed properties.
1678
- var omit = restArguments(function(obj, keys) {
1679
- var iteratee = keys[0], context;
1680
- if (isFunction$1(iteratee)) {
1681
- iteratee = negate(iteratee);
1682
- if (keys.length > 1) context = keys[1];
1683
- } else {
1684
- keys = map(flatten$1(keys, false, false), String);
1685
- iteratee = function(value, key) {
1686
- return !contains(keys, key);
1687
- };
1688
- }
1689
- return pick(obj, iteratee, context);
1690
- });
1691
-
1692
- // Returns everything but the last entry of the array. Especially useful on
1693
- // the arguments object. Passing **n** will return all the values in
1694
- // the array, excluding the last N.
1695
- function initial(array, n, guard) {
1696
- return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));
1697
- }
1698
-
1699
- // Get the first element of an array. Passing **n** will return the first N
1700
- // values in the array. The **guard** check allows it to work with `_.map`.
1701
- function first(array, n, guard) {
1702
- if (array == null || array.length < 1) return n == null || guard ? void 0 : [];
1703
- if (n == null || guard) return array[0];
1704
- return initial(array, array.length - n);
1705
- }
1706
-
1707
- // Returns everything but the first entry of the `array`. Especially useful on
1708
- // the `arguments` object. Passing an **n** will return the rest N values in the
1709
- // `array`.
1710
- function rest(array, n, guard) {
1711
- return slice.call(array, n == null || guard ? 1 : n);
1712
- }
1713
-
1714
- // Get the last element of an array. Passing **n** will return the last N
1715
- // values in the array.
1716
- function last(array, n, guard) {
1717
- if (array == null || array.length < 1) return n == null || guard ? void 0 : [];
1718
- if (n == null || guard) return array[array.length - 1];
1719
- return rest(array, Math.max(0, array.length - n));
1720
- }
1721
-
1722
- // Trim out all falsy values from an array.
1723
- function compact(array) {
1724
- return filter(array, Boolean);
1725
- }
1726
-
1727
- // Flatten out an array, either recursively (by default), or up to `depth`.
1728
- // Passing `true` or `false` as `depth` means `1` or `Infinity`, respectively.
1729
- function flatten(array, depth) {
1730
- return flatten$1(array, depth, false);
1731
- }
1732
-
1733
- // Take the difference between one array and a number of other arrays.
1734
- // Only the elements present in just the first array will remain.
1735
- var difference = restArguments(function(array, rest) {
1736
- rest = flatten$1(rest, true, true);
1737
- return filter(array, function(value){
1738
- return !contains(rest, value);
1739
- });
1740
- });
1741
-
1742
- // Return a version of the array that does not contain the specified value(s).
1743
- var without = restArguments(function(array, otherArrays) {
1744
- return difference(array, otherArrays);
1745
- });
1746
-
1747
- // Produce a duplicate-free version of the array. If the array has already
1748
- // been sorted, you have the option of using a faster algorithm.
1749
- // The faster algorithm will not work with an iteratee if the iteratee
1750
- // is not a one-to-one function, so providing an iteratee will disable
1751
- // the faster algorithm.
1752
- function uniq(array, isSorted, iteratee, context) {
1753
- if (!isBoolean(isSorted)) {
1754
- context = iteratee;
1755
- iteratee = isSorted;
1756
- isSorted = false;
1757
- }
1758
- if (iteratee != null) iteratee = cb(iteratee, context);
1759
- var result = [];
1760
- var seen = [];
1761
- for (var i = 0, length = getLength(array); i < length; i++) {
1762
- var value = array[i],
1763
- computed = iteratee ? iteratee(value, i, array) : value;
1764
- if (isSorted && !iteratee) {
1765
- if (!i || seen !== computed) result.push(value);
1766
- seen = computed;
1767
- } else if (iteratee) {
1768
- if (!contains(seen, computed)) {
1769
- seen.push(computed);
1770
- result.push(value);
1771
- }
1772
- } else if (!contains(result, value)) {
1773
- result.push(value);
1774
- }
1775
- }
1776
- return result;
1777
- }
1778
-
1779
- // Produce an array that contains the union: each distinct element from all of
1780
- // the passed-in arrays.
1781
- var union$1 = restArguments(function(arrays) {
1782
- return uniq(flatten$1(arrays, true, true));
1783
- });
1784
-
1785
- // Produce an array that contains every item shared between all the
1786
- // passed-in arrays.
1787
- function intersection(array) {
1788
- var result = [];
1789
- var argsLength = arguments.length;
1790
- for (var i = 0, length = getLength(array); i < length; i++) {
1791
- var item = array[i];
1792
- if (contains(result, item)) continue;
1793
- var j;
1794
- for (j = 1; j < argsLength; j++) {
1795
- if (!contains(arguments[j], item)) break;
1796
- }
1797
- if (j === argsLength) result.push(item);
1798
- }
1799
- return result;
1800
- }
1801
-
1802
- // Complement of zip. Unzip accepts an array of arrays and groups
1803
- // each array's elements on shared indices.
1804
- function unzip(array) {
1805
- var length = (array && max(array, getLength).length) || 0;
1806
- var result = Array(length);
1807
-
1808
- for (var index = 0; index < length; index++) {
1809
- result[index] = pluck$1(array, index);
1810
- }
1811
- return result;
1812
- }
1813
-
1814
- // Zip together multiple lists into a single array -- elements that share
1815
- // an index go together.
1816
- var zip = restArguments(unzip);
1817
-
1818
- // Converts lists into objects. Pass either a single array of `[key, value]`
1819
- // pairs, or two parallel arrays of the same length -- one of keys, and one of
1820
- // the corresponding values. Passing by pairs is the reverse of `_.pairs`.
1821
- function object$1(list, values) {
1822
- var result = {};
1823
- for (var i = 0, length = getLength(list); i < length; i++) {
1824
- if (values) {
1825
- result[list[i]] = values[i];
1826
- } else {
1827
- result[list[i][0]] = list[i][1];
1828
- }
1829
- }
1830
- return result;
1831
- }
1832
-
1833
- // Generate an integer Array containing an arithmetic progression. A port of
1834
- // the native Python `range()` function. See
1835
- // [the Python documentation](https://docs.python.org/library/functions.html#range).
1836
- function range(start, stop, step) {
1837
- if (stop == null) {
1838
- stop = start || 0;
1839
- start = 0;
1840
- }
1841
- if (!step) {
1842
- step = stop < start ? -1 : 1;
1843
- }
1844
-
1845
- var length = Math.max(Math.ceil((stop - start) / step), 0);
1846
- var range = Array(length);
1847
-
1848
- for (var idx = 0; idx < length; idx++, start += step) {
1849
- range[idx] = start;
1850
- }
1851
-
1852
- return range;
1853
- }
1854
-
1855
- // Chunk a single array into multiple arrays, each containing `count` or fewer
1856
- // items.
1857
- function chunk(array, count) {
1858
- if (count == null || count < 1) return [];
1859
- var result = [];
1860
- var i = 0, length = array.length;
1861
- while (i < length) {
1862
- result.push(slice.call(array, i, i += count));
1863
- }
1864
- return result;
1865
- }
1866
-
1867
- // Helper function to continue chaining intermediate results.
1868
- function chainResult(instance, obj) {
1869
- return instance._chain ? _$1(obj).chain() : obj;
1870
- }
1871
-
1872
- // Add your own custom functions to the Underscore object.
1873
- function mixin(obj) {
1874
- each(functions(obj), function(name) {
1875
- var func = _$1[name] = obj[name];
1876
- _$1.prototype[name] = function() {
1877
- var args = [this._wrapped];
1878
- push.apply(args, arguments);
1879
- return chainResult(this, func.apply(_$1, args));
1880
- };
1881
- });
1882
- return _$1;
1883
- }
1884
-
1885
- // Add all mutator `Array` functions to the wrapper.
1886
- each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
1887
- var method = ArrayProto[name];
1888
- _$1.prototype[name] = function() {
1889
- var obj = this._wrapped;
1890
- if (obj != null) {
1891
- method.apply(obj, arguments);
1892
- if ((name === 'shift' || name === 'splice') && obj.length === 0) {
1893
- delete obj[0];
1894
- }
1895
- }
1896
- return chainResult(this, obj);
1897
- };
1898
- });
1899
-
1900
- // Add all accessor `Array` functions to the wrapper.
1901
- each(['concat', 'join', 'slice'], function(name) {
1902
- var method = ArrayProto[name];
1903
- _$1.prototype[name] = function() {
1904
- var obj = this._wrapped;
1905
- if (obj != null) obj = method.apply(obj, arguments);
1906
- return chainResult(this, obj);
1907
- };
1908
- });
1909
-
1910
- // Named Exports
1911
-
1912
- var allExports = /*#__PURE__*/Object.freeze({
1913
- __proto__: null,
1914
- VERSION: VERSION,
1915
- restArguments: restArguments,
1916
- isObject: isObject$1,
1917
- isNull: isNull,
1918
- isUndefined: isUndefined,
1919
- isBoolean: isBoolean,
1920
- isElement: isElement,
1921
- isString: isString,
1922
- isNumber: isNumber,
1923
- isDate: isDate,
1924
- isRegExp: isRegExp,
1925
- isError: isError,
1926
- isSymbol: isSymbol,
1927
- isArrayBuffer: isArrayBuffer,
1928
- isDataView: isDataView$1,
1929
- isArray: isArray,
1930
- isFunction: isFunction$1,
1931
- isArguments: isArguments$1,
1932
- isFinite: isFinite$1,
1933
- isNaN: isNaN$1,
1934
- isTypedArray: isTypedArray$1,
1935
- isEmpty: isEmpty,
1936
- isMatch: isMatch,
1937
- isEqual: isEqual,
1938
- isMap: isMap,
1939
- isWeakMap: isWeakMap,
1940
- isSet: isSet,
1941
- isWeakSet: isWeakSet,
1942
- keys: keys,
1943
- allKeys: allKeys,
1944
- values: values,
1945
- pairs: pairs,
1946
- invert: invert,
1947
- functions: functions,
1948
- methods: functions,
1949
- extend: extend,
1950
- extendOwn: extendOwn,
1951
- assign: extendOwn,
1952
- defaults: defaults,
1953
- create: create,
1954
- clone: clone,
1955
- tap: tap,
1956
- get: get,
1957
- has: has,
1958
- mapObject: mapObject$1,
1959
- identity: identity,
1960
- constant: constant$1,
1961
- noop: noop,
1962
- toPath: toPath$1,
1963
- property: property,
1964
- propertyOf: propertyOf,
1965
- matcher: matcher,
1966
- matches: matcher,
1967
- times: times,
1968
- random: random$1,
1969
- now: now,
1970
- escape: escape,
1971
- unescape: unescape,
1972
- templateSettings: templateSettings,
1973
- template: template,
1974
- result: result,
1975
- uniqueId: uniqueId,
1976
- chain: chain,
1977
- iteratee: iteratee,
1978
- partial: partial,
1979
- bind: bind,
1980
- bindAll: bindAll,
1981
- memoize: memoize,
1982
- delay: delay,
1983
- defer: defer,
1984
- throttle: throttle,
1985
- debounce: debounce,
1986
- wrap: wrap,
1987
- negate: negate,
1988
- compose: compose,
1989
- after: after,
1990
- before: before,
1991
- once: once,
1992
- findKey: findKey,
1993
- findIndex: findIndex,
1994
- findLastIndex: findLastIndex,
1995
- sortedIndex: sortedIndex,
1996
- indexOf: indexOf,
1997
- lastIndexOf: lastIndexOf,
1998
- find: find,
1999
- detect: find,
2000
- findWhere: findWhere,
2001
- each: each,
2002
- forEach: each,
2003
- map: map,
2004
- collect: map,
2005
- reduce: reduce,
2006
- foldl: reduce,
2007
- inject: reduce,
2008
- reduceRight: reduceRight,
2009
- foldr: reduceRight,
2010
- filter: filter,
2011
- select: filter,
2012
- reject: reject,
2013
- every: every,
2014
- all: every,
2015
- some: some,
2016
- any: some,
2017
- contains: contains,
2018
- includes: contains,
2019
- include: contains,
2020
- invoke: invoke,
2021
- pluck: pluck$1,
2022
- where: where,
2023
- max: max,
2024
- min: min,
2025
- shuffle: shuffle$1,
2026
- sample: sample,
2027
- sortBy: sortBy,
2028
- groupBy: groupBy,
2029
- indexBy: indexBy,
2030
- countBy: countBy,
2031
- partition: partition,
2032
- toArray: toArray,
2033
- size: size,
2034
- pick: pick,
2035
- omit: omit,
2036
- first: first,
2037
- head: first,
2038
- take: first,
2039
- initial: initial,
2040
- last: last,
2041
- rest: rest,
2042
- tail: rest,
2043
- drop: rest,
2044
- compact: compact,
2045
- flatten: flatten,
2046
- without: without,
2047
- uniq: uniq,
2048
- unique: uniq,
2049
- union: union$1,
2050
- intersection: intersection,
2051
- difference: difference,
2052
- unzip: unzip,
2053
- transpose: unzip,
2054
- zip: zip,
2055
- object: object$1,
2056
- range: range,
2057
- chunk: chunk,
2058
- mixin: mixin,
2059
- 'default': _$1
2060
- });
2061
-
2062
- // Default Export
2063
-
2064
- // Add all of the Underscore functions to the wrapper object.
2065
- var _ = mixin(allExports);
2066
- // Legacy Node.js API.
2067
- _._ = _;
1
+ import _ from 'underscore';
2
+ import _extends from '@babel/runtime/helpers/extends';
3
+ import * as KAS from '@khanacademy/kas';
4
+ import _objectWithoutPropertiesLoose from '@babel/runtime/helpers/objectWithoutPropertiesLoose';
5
+ import { seededRNG as seededRNG$1, shuffle as shuffle$1 } from '@khanacademy/perseus-core';
2068
6
 
2069
7
  function getMatrixSize(matrix) {
2070
8
  const matrixSize = [1, 1];
@@ -2111,7 +49,9 @@ const getDecimalSeparator = locale => {
2111
49
  const match = new Intl.NumberFormat(locale).format(numberWithDecimalSeparator)
2112
50
  // 0x661 is ARABIC-INDIC DIGIT ONE
2113
51
  // 0x6F1 is EXTENDED ARABIC-INDIC DIGIT ONE
2114
- .match(/[^\d\u0661\u06F1]/);
52
+ // 0x967 is DEVANAGARI DIGIT ONE
53
+ // 0x9e7 is BENGALI/BANGLA DIGIT ONE
54
+ .match(/[^\d\u0661\u06F1\u0967\u09e7]/);
2115
55
  return (_match$ = match == null ? void 0 : match[0]) != null ? _match$ : ".";
2116
56
  }
2117
57
  };
@@ -2892,16 +832,6 @@ const number = (rawValue, ctx) => {
2892
832
  return ctx.failure("number", rawValue);
2893
833
  };
2894
834
 
2895
- function _extends() {
2896
- return _extends = Object.assign ? Object.assign.bind() : function (n) {
2897
- for (var e = 1; e < arguments.length; e++) {
2898
- var t = arguments[e];
2899
- for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
2900
- }
2901
- return n;
2902
- }, _extends.apply(null, arguments);
2903
- }
2904
-
2905
835
  function object(schema) {
2906
836
  return (rawValue, ctx) => {
2907
837
  if (!isObject(rawValue)) {
@@ -3152,6 +1082,76 @@ const parseExplanationWidget = parseWidget(constant("explanation"), object({
3152
1082
  static: defaulted(boolean, () => false)
3153
1083
  }));
3154
1084
 
1085
+ const KeypadKeys = ["PLUS", "MINUS", "NEGATIVE", "TIMES", "DIVIDE", "DECIMAL", "PERIOD", "PERCENT", "CDOT", "EQUAL", "NEQ", "GT", "LT", "GEQ", "LEQ",
1086
+ // mobile native only
1087
+ "FRAC_INCLUSIVE",
1088
+ // mobile native only
1089
+ "FRAC_EXCLUSIVE",
1090
+ // mobile native only
1091
+ "FRAC", "EXP", "EXP_2", "EXP_3", "SQRT", "CUBE_ROOT", "RADICAL", "LEFT_PAREN", "RIGHT_PAREN", "LN", "LOG", "LOG_N", "SIN", "COS",
1092
+ // TODO(charlie): Add in additional Greek letters.,
1093
+ "TAN", "PI", "THETA", "UP", "RIGHT", "DOWN", "LEFT", "BACKSPACE", "DISMISS", "JUMP_OUT_PARENTHESES", "JUMP_OUT_EXPONENT", "JUMP_OUT_BASE", "JUMP_INTO_NUMERATOR", "JUMP_OUT_NUMERATOR", "JUMP_OUT_DENOMINATOR",
1094
+ // Multi-functional keys.
1095
+ "NUM_0", "NUM_1", "NUM_2", "NUM_3", "NUM_4", "NUM_5", "NUM_6", "NUM_7", "NUM_8", "NUM_9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"];
1096
+
1097
+ // Used by KeypadContext to pass around a renderer reference
1098
+
1099
+ /**
1100
+ * Scrape the answer forms for any variables or contants (like Pi)
1101
+ * that need to be included as keys on the keypad.
1102
+ */
1103
+ function deriveExtraKeys(widgetOptions) {
1104
+ if (widgetOptions.extraKeys) {
1105
+ return widgetOptions.extraKeys;
1106
+ }
1107
+
1108
+ // If there are no extra symbols available, we include Pi anyway, so
1109
+ // that the "extra symbols" button doesn't appear empty.
1110
+ const defaultKeys = ["PI"];
1111
+ if (widgetOptions.answerForms == null) {
1112
+ return defaultKeys;
1113
+ }
1114
+
1115
+ // Extract any and all variables and constants from the answer forms.
1116
+ const uniqueExtraVariables = {};
1117
+ const uniqueExtraConstants = {};
1118
+ for (const answerForm of widgetOptions.answerForms) {
1119
+ const maybeExpr = KAS.parse(answerForm.value, widgetOptions);
1120
+ if (maybeExpr.parsed) {
1121
+ const expr = maybeExpr.expr;
1122
+
1123
+ // The keypad expects Greek letters to be capitalized (e.g., it
1124
+ // requires `PI` instead of `pi`). Right now, it only supports Pi
1125
+ // and Theta, so we special-case.
1126
+ const isGreek = symbol => symbol === "pi" || symbol === "theta";
1127
+ const toKey = symbol => isGreek(symbol) ? symbol.toUpperCase() : symbol;
1128
+ const isKey = key => KeypadKeys.includes(key);
1129
+ for (const variable of expr.getVars()) {
1130
+ const maybeKey = toKey(variable);
1131
+ if (isKey(maybeKey)) {
1132
+ uniqueExtraVariables[maybeKey] = true;
1133
+ }
1134
+ }
1135
+ for (const constant of expr.getConsts()) {
1136
+ const maybeKey = toKey(constant);
1137
+ if (isKey(maybeKey)) {
1138
+ uniqueExtraConstants[maybeKey] = true;
1139
+ }
1140
+ }
1141
+ }
1142
+ }
1143
+
1144
+ // TODO(charlie): Alert the keypad as to which of these symbols should be
1145
+ // treated as functions.
1146
+ const extraVariables = Object.keys(uniqueExtraVariables).sort();
1147
+ const extraConstants = Object.keys(uniqueExtraConstants).sort();
1148
+ const extraKeys = [...extraVariables, ...extraConstants];
1149
+ if (!extraKeys.length) {
1150
+ return defaultKeys;
1151
+ }
1152
+ return extraKeys;
1153
+ }
1154
+
3155
1155
  // Given a function, creates a PartialParser that converts one type to another
3156
1156
  // using that function. The returned parser never fails.
3157
1157
  function convert(f) {
@@ -3253,11 +1253,25 @@ function removeInvalidAnswerForms(possiblyInvalid) {
3253
1253
  }
3254
1254
  return valid;
3255
1255
  }
3256
- const version1 = object({
1256
+ const version2$1 = object({
1257
+ major: constant(2),
1258
+ minor: number
1259
+ });
1260
+ const parseExpressionWidgetV2 = parseWidgetWithVersion(version2$1, constant("expression"), object({
1261
+ answerForms: pipeParsers(array(parsePossiblyInvalidAnswerForm)).then(convert(removeInvalidAnswerForms)).parser,
1262
+ functions: array(string),
1263
+ times: boolean,
1264
+ visibleLabel: optional(string),
1265
+ ariaLabel: optional(string),
1266
+ buttonSets: parseLegacyButtonSets,
1267
+ buttonsVisible: optional(enumeration("always", "never", "focused")),
1268
+ extraKeys: array(enumeration(...KeypadKeys))
1269
+ }));
1270
+ const version1$1 = object({
3257
1271
  major: constant(1),
3258
1272
  minor: number
3259
1273
  });
3260
- const parseExpressionWidgetV1 = parseWidgetWithVersion(version1, constant("expression"), object({
1274
+ const parseExpressionWidgetV1 = parseWidgetWithVersion(version1$1, constant("expression"), object({
3261
1275
  answerForms: pipeParsers(array(parsePossiblyInvalidAnswerForm)).then(convert(removeInvalidAnswerForms)).parser,
3262
1276
  functions: array(string),
3263
1277
  times: boolean,
@@ -3266,11 +1280,32 @@ const parseExpressionWidgetV1 = parseWidgetWithVersion(version1, constant("expre
3266
1280
  buttonSets: parseLegacyButtonSets,
3267
1281
  buttonsVisible: optional(enumeration("always", "never", "focused"))
3268
1282
  }));
3269
- const version0 = optional(object({
1283
+ function migrateV1ToV2$1(widget) {
1284
+ const {
1285
+ options
1286
+ } = widget;
1287
+ return _extends({}, widget, {
1288
+ version: {
1289
+ major: 2,
1290
+ minor: 0
1291
+ },
1292
+ options: {
1293
+ times: options.times,
1294
+ buttonSets: options.buttonSets,
1295
+ functions: options.functions,
1296
+ buttonsVisible: options.buttonsVisible,
1297
+ visibleLabel: options.visibleLabel,
1298
+ ariaLabel: options.ariaLabel,
1299
+ answerForms: options.answerForms,
1300
+ extraKeys: deriveExtraKeys(options)
1301
+ }
1302
+ });
1303
+ }
1304
+ const version0$1 = optional(object({
3270
1305
  major: constant(0),
3271
1306
  minor: number
3272
1307
  }));
3273
- const parseExpressionWidgetV0 = parseWidgetWithVersion(version0, constant("expression"), object({
1308
+ const parseExpressionWidgetV0 = parseWidgetWithVersion(version0$1, constant("expression"), object({
3274
1309
  functions: array(string),
3275
1310
  times: boolean,
3276
1311
  visibleLabel: optional(string),
@@ -3281,7 +1316,7 @@ const parseExpressionWidgetV0 = parseWidgetWithVersion(version0, constant("expre
3281
1316
  buttonSets: parseLegacyButtonSets,
3282
1317
  buttonsVisible: optional(enumeration("always", "never", "focused"))
3283
1318
  }));
3284
- function migrateV0ToV1(widget) {
1319
+ function migrateV0ToV1$1(widget) {
3285
1320
  const {
3286
1321
  options
3287
1322
  } = widget;
@@ -3306,7 +1341,7 @@ function migrateV0ToV1(widget) {
3306
1341
  }
3307
1342
  });
3308
1343
  }
3309
- const parseExpressionWidget = versionedWidgetOptions(1, parseExpressionWidgetV1).withMigrationFrom(0, parseExpressionWidgetV0, migrateV0ToV1).parser;
1344
+ const parseExpressionWidget = versionedWidgetOptions(2, parseExpressionWidgetV2).withMigrationFrom(1, parseExpressionWidgetV1, migrateV1ToV2$1).withMigrationFrom(0, parseExpressionWidgetV0, migrateV0ToV1$1).parser;
3310
1345
 
3311
1346
  const falseToNull = pipeParsers(constant(false)).then(convert(() => null)).parser;
3312
1347
  const parseGradedGroupWidgetOptions = object({
@@ -4079,13 +2114,16 @@ const parseLockedPolygonType = object({
4079
2114
  labels: optional(array(parseLockedLabelType)),
4080
2115
  ariaLabel: optional(string)
4081
2116
  });
2117
+
2118
+ // Exported for testing.
2119
+ const parseLockedFunctionDomain = defaulted(pair(defaulted(number, () => -Infinity), defaulted(number, () => Infinity)), () => [-Infinity, Infinity]);
4082
2120
  const parseLockedFunctionType = object({
4083
2121
  type: constant("function"),
4084
2122
  color: parseLockedFigureColor,
4085
2123
  strokeStyle: parseLockedLineStyle,
4086
2124
  equation: string,
4087
2125
  directionalAxis: enumeration("x", "y"),
4088
- domain: optional(pairOfNumbers),
2126
+ domain: parseLockedFunctionDomain,
4089
2127
  // TODO(benchristel): default labels to empty array?
4090
2128
  labels: optional(array(parseLockedLabelType)),
4091
2129
  ariaLabel: optional(string)
@@ -4205,6 +2243,7 @@ const parseNumberLineWidget = parseWidget(constant("number-line"), object({
4205
2243
  }));
4206
2244
 
4207
2245
  const parseMathFormat = enumeration("integer", "mixed", "improper", "proper", "decimal", "percent", "pi");
2246
+ const parseSimplify = enumeration("required", "correct", "enforced", "optional");
4208
2247
  const parseNumericInputWidget = parseWidget(constant("numeric-input"), object({
4209
2248
  answers: array(object({
4210
2249
  message: string,
@@ -4219,7 +2258,12 @@ const parseNumericInputWidget = parseWidget(constant("numeric-input"), object({
4219
2258
  // TODO(benchristel): simplify should never be a boolean, but we
4220
2259
  // have some content where it is anyway. If we ever backfill
4221
2260
  // the data, we should simplify `simplify`.
4222
- simplify: optional(nullable(union(string).or(pipeParsers(boolean).then(convert(String)).parser).parser))
2261
+ simplify: optional(nullable(union(parseSimplify).or(pipeParsers(boolean).then(convert(value => {
2262
+ if (typeof value === "boolean") {
2263
+ return value ? "required" : "optional";
2264
+ }
2265
+ return value;
2266
+ })).parser).parser))
4223
2267
  })),
4224
2268
  labelText: optional(string),
4225
2269
  size: string,
@@ -4295,13 +2339,133 @@ const parsePlotterWidget = parseWidget(constant("plotter"), object({
4295
2339
  // of why we want to duplicate the defaults here.
4296
2340
  plotDimensions: defaulted(array(number), () => [380, 300])
4297
2341
  }));
4298
-
4299
- const parsePythonProgramWidget = parseWidget(constant("python-program"), object({
4300
- programID: string,
4301
- height: number
2342
+
2343
+ const parsePythonProgramWidget = parseWidget(constant("python-program"), object({
2344
+ programID: string,
2345
+ height: number
2346
+ }));
2347
+
2348
+ const _excluded$a = ["noneOfTheAbove"];
2349
+ const currentVersion$3 = {
2350
+ major: 2,
2351
+ minor: 0
2352
+ };
2353
+ function deriveNumCorrect(options) {
2354
+ const {
2355
+ choices,
2356
+ numCorrect
2357
+ } = options;
2358
+ return numCorrect != null ? numCorrect : choices.filter(c => c.correct).length;
2359
+ }
2360
+ const widgetOptionsUpgrades$2 = {
2361
+ "2": v1props => {
2362
+ const upgraded = _extends({}, v1props, {
2363
+ numCorrect: deriveNumCorrect(v1props)
2364
+ });
2365
+ return upgraded;
2366
+ },
2367
+ "1": v0props => {
2368
+ const {
2369
+ noneOfTheAbove
2370
+ } = v0props,
2371
+ rest = _objectWithoutPropertiesLoose(v0props, _excluded$a);
2372
+ if (noneOfTheAbove) {
2373
+ throw new Error("radio widget v0 no longer supports auto noneOfTheAbove");
2374
+ }
2375
+ return _extends({}, rest, {
2376
+ hasNoneOfTheAbove: false
2377
+ });
2378
+ }
2379
+ };
2380
+ const defaultWidgetOptions$v = {
2381
+ choices: [{}, {}, {}, {}],
2382
+ displayCount: null,
2383
+ randomize: false,
2384
+ hasNoneOfTheAbove: false,
2385
+ multipleSelect: false,
2386
+ countChoices: false,
2387
+ deselectEnabled: false
2388
+ };
2389
+
2390
+ const _excluded$9 = ["noneOfTheAbove"];
2391
+ const version2 = optional(object({
2392
+ major: constant(2),
2393
+ minor: number
2394
+ }));
2395
+ const parseRadioWidgetV2 = parseWidgetWithVersion(version2, constant("radio"), object({
2396
+ numCorrect: optional(number),
2397
+ choices: array(object({
2398
+ content: defaulted(string, () => ""),
2399
+ clue: optional(string),
2400
+ correct: optional(boolean),
2401
+ isNoneOfTheAbove: optional(boolean),
2402
+ // deprecated
2403
+ // There is an import cycle between radio-widget.ts and
2404
+ // widgets-map.ts. The anonymous function below ensures that we
2405
+ // don't refer to parseWidgetsMap before it's defined.
2406
+ widgets: optional((rawVal, ctx) => parseWidgetsMap(rawVal, ctx))
2407
+ })),
2408
+ hasNoneOfTheAbove: optional(boolean),
2409
+ countChoices: optional(boolean),
2410
+ randomize: optional(boolean),
2411
+ multipleSelect: optional(boolean),
2412
+ deselectEnabled: optional(boolean),
2413
+ // deprecated
2414
+ onePerLine: optional(boolean),
2415
+ // deprecated
2416
+ displayCount: optional(any),
2417
+ // v0 props
2418
+ // `noneOfTheAbove` is still in use (but only set to `false`).
2419
+ noneOfTheAbove: optional(constant(false))
2420
+ }));
2421
+ const version1 = optional(object({
2422
+ major: constant(1),
2423
+ minor: number
2424
+ }));
2425
+ const parseRadioWidgetV1 = parseWidgetWithVersion(version1, constant("radio"), object({
2426
+ choices: array(object({
2427
+ content: defaulted(string, () => ""),
2428
+ clue: optional(string),
2429
+ correct: optional(boolean),
2430
+ isNoneOfTheAbove: optional(boolean),
2431
+ // deprecated
2432
+ // There is an import cycle between radio-widget.ts and
2433
+ // widgets-map.ts. The anonymous function below ensures that we
2434
+ // don't refer to parseWidgetsMap before it's defined.
2435
+ widgets: defaulted((rawVal, ctx) => parseWidgetsMap(rawVal, ctx), () => undefined)
2436
+ })),
2437
+ hasNoneOfTheAbove: optional(boolean),
2438
+ countChoices: optional(boolean),
2439
+ randomize: optional(boolean),
2440
+ multipleSelect: optional(boolean),
2441
+ deselectEnabled: optional(boolean),
2442
+ // deprecated
2443
+ onePerLine: optional(boolean),
2444
+ // deprecated
2445
+ displayCount: optional(any),
2446
+ // v0 props
2447
+ // `noneOfTheAbove` is still in use (but only set to `false`).
2448
+ noneOfTheAbove: optional(constant(false))
2449
+ }));
2450
+ function migrateV1ToV2(widget) {
2451
+ const {
2452
+ options
2453
+ } = widget;
2454
+ return _extends({}, widget, {
2455
+ version: {
2456
+ major: 2,
2457
+ minor: 0
2458
+ },
2459
+ options: _extends({}, options, {
2460
+ numCorrect: deriveNumCorrect(options)
2461
+ })
2462
+ });
2463
+ }
2464
+ const version0 = optional(object({
2465
+ major: constant(0),
2466
+ minor: number
4302
2467
  }));
4303
-
4304
- const parseRadioWidget = parseWidget(constant("radio"), object({
2468
+ const parseRadioWidgetV0 = parseWidgetWithVersion(version0, constant("radio"), object({
4305
2469
  choices: array(object({
4306
2470
  content: defaulted(string, () => ""),
4307
2471
  clue: optional(string),
@@ -4311,7 +2475,7 @@ const parseRadioWidget = parseWidget(constant("radio"), object({
4311
2475
  // There is an import cycle between radio-widget.ts and
4312
2476
  // widgets-map.ts. The anonymous function below ensures that we
4313
2477
  // don't refer to parseWidgetsMap before it's defined.
4314
- widgets: defaulted((rawVal, ctx) => parseWidgetsMap(rawVal, ctx), () => undefined)
2478
+ widgets: optional((rawVal, ctx) => parseWidgetsMap(rawVal, ctx))
4315
2479
  })),
4316
2480
  hasNoneOfTheAbove: optional(boolean),
4317
2481
  countChoices: optional(boolean),
@@ -4326,6 +2490,22 @@ const parseRadioWidget = parseWidget(constant("radio"), object({
4326
2490
  // `noneOfTheAbove` is still in use (but only set to `false`).
4327
2491
  noneOfTheAbove: optional(constant(false))
4328
2492
  }));
2493
+ function migrateV0ToV1(widget) {
2494
+ const {
2495
+ options
2496
+ } = widget;
2497
+ const rest = _objectWithoutPropertiesLoose(options, _excluded$9);
2498
+ return _extends({}, widget, {
2499
+ version: {
2500
+ major: 1,
2501
+ minor: 0
2502
+ },
2503
+ options: _extends({}, rest, {
2504
+ hasNoneOfTheAbove: false
2505
+ })
2506
+ });
2507
+ }
2508
+ const parseRadioWidget = versionedWidgetOptions(2, parseRadioWidgetV2).withMigrationFrom(1, parseRadioWidgetV1, migrateV1ToV2).withMigrationFrom(0, parseRadioWidgetV0, migrateV0ToV1).parser;
4329
2509
 
4330
2510
  const parseSorterWidget = parseWidget(constant("sorter"), object({
4331
2511
  correct: array(string),
@@ -4499,7 +2679,7 @@ const parsePerseusRenderer = defaulted(object({
4499
2679
  const parsePerseusArticle = union(parsePerseusRenderer).or(array(parsePerseusRenderer)).parser;
4500
2680
 
4501
2681
  const parseHint = object({
4502
- replace: optional(boolean),
2682
+ replace: defaulted(boolean, () => undefined),
4503
2683
  content: string,
4504
2684
  widgets: defaulted(parseWidgetsMap, () => ({})),
4505
2685
  images: parseImages,
@@ -4620,9 +2800,51 @@ function throwErrorIfCheatingDetected() {
4620
2800
  }
4621
2801
  }
4622
2802
 
2803
+ /**
2804
+ * Adds the given perseus library version information to the __perseus_debug__
2805
+ * object and ensures that the object is attached to `globalThis` (`window` in
2806
+ * browser environments).
2807
+ *
2808
+ * This allows each library to provide runtime version information to assist in
2809
+ * debugging in production environments.
2810
+ */
2811
+ const addLibraryVersionToPerseusDebug = (libraryName, libraryVersion) => {
2812
+ // If the library version is the default value, then we don't want to
2813
+ // prefix it with a "v" to indicate that it is a version number.
2814
+ let prefix = "v";
2815
+ if (libraryVersion === "__lib_version__") {
2816
+ prefix = "";
2817
+ }
2818
+ const formattedVersion = `${prefix}${libraryVersion}`;
2819
+ if (typeof globalThis !== "undefined") {
2820
+ var _globalThis$__perseus;
2821
+ globalThis.__perseus_debug__ = (_globalThis$__perseus = globalThis.__perseus_debug__) != null ? _globalThis$__perseus : {};
2822
+ const existingVersionEntry = globalThis.__perseus_debug__[libraryName];
2823
+ if (existingVersionEntry) {
2824
+ // If we already have an entry and it doesn't match the registered
2825
+ // version, we morph the entry into an array and log a warning.
2826
+ if (existingVersionEntry !== formattedVersion) {
2827
+ // Existing entry might be an array already (oops, at least 2
2828
+ // versions of the library already loaded!).
2829
+ const allVersions = Array.isArray(existingVersionEntry) ? existingVersionEntry : [existingVersionEntry];
2830
+ allVersions.push(formattedVersion);
2831
+ globalThis.__perseus_debug__[libraryName] = allVersions;
2832
+
2833
+ // eslint-disable-next-line no-console
2834
+ console.warn(`Multiple versions of ${libraryName} loaded on this page: ${allVersions.sort().join(", ")}`);
2835
+ }
2836
+ } else {
2837
+ globalThis.__perseus_debug__[libraryName] = formattedVersion;
2838
+ }
2839
+ } else {
2840
+ // eslint-disable-next-line no-console
2841
+ console.warn(`globalThis not found found (${formattedVersion})`);
2842
+ }
2843
+ };
2844
+
4623
2845
  // This file is processed by a Rollup plugin (replace) to inject the production
4624
2846
  const libName = "@khanacademy/perseus-core";
4625
- const libVersion = "3.7.0";
2847
+ const libVersion = "5.0.0";
4626
2848
  addLibraryVersionToPerseusDebug(libName, libVersion);
4627
2849
 
4628
2850
  /**
@@ -4739,7 +2961,7 @@ function getCategorizerPublicWidgetOptions(options) {
4739
2961
  };
4740
2962
  }
4741
2963
 
4742
- const defaultWidgetOptions$v = {
2964
+ const defaultWidgetOptions$u = {
4743
2965
  items: [],
4744
2966
  categories: [],
4745
2967
  values: [],
@@ -4747,7 +2969,7 @@ const defaultWidgetOptions$v = {
4747
2969
  };
4748
2970
  const categorizerWidgetLogic = {
4749
2971
  name: "categorizer",
4750
- defaultWidgetOptions: defaultWidgetOptions$v,
2972
+ defaultWidgetOptions: defaultWidgetOptions$u,
4751
2973
  getPublicWidgetOptions: getCategorizerPublicWidgetOptions
4752
2974
  };
4753
2975
 
@@ -4756,7 +2978,7 @@ function getCSProgramPublicWidgetOptions(options) {
4756
2978
  }
4757
2979
 
4758
2980
  const DEFAULT_HEIGHT = 400;
4759
- const defaultWidgetOptions$u = {
2981
+ const defaultWidgetOptions$t = {
4760
2982
  programID: "",
4761
2983
  programType: null,
4762
2984
  settings: [{
@@ -4769,18 +2991,18 @@ const defaultWidgetOptions$u = {
4769
2991
  };
4770
2992
  const csProgramWidgetLogic = {
4771
2993
  name: "cs-program",
4772
- defaultWidgetOptions: defaultWidgetOptions$u,
2994
+ defaultWidgetOptions: defaultWidgetOptions$t,
4773
2995
  supportedAlignments: ["block", "full-width"],
4774
2996
  getPublicWidgetOptions: getCSProgramPublicWidgetOptions
4775
2997
  };
4776
2998
 
4777
- const defaultWidgetOptions$t = {
2999
+ const defaultWidgetOptions$s = {
4778
3000
  togglePrompt: "",
4779
3001
  definition: ""
4780
3002
  };
4781
3003
  const definitionWidgetLogic = {
4782
3004
  name: "definition",
4783
- defaultWidgetOptions: defaultWidgetOptions$t,
3005
+ defaultWidgetOptions: defaultWidgetOptions$s,
4784
3006
  defaultAlignment: "inline"
4785
3007
  };
4786
3008
 
@@ -4805,7 +3027,7 @@ function getDropdownPublicWidgetOptions(options) {
4805
3027
  };
4806
3028
  }
4807
3029
 
4808
- const defaultWidgetOptions$s = {
3030
+ const defaultWidgetOptions$r = {
4809
3031
  placeholder: "",
4810
3032
  choices: [{
4811
3033
  content: "",
@@ -4814,12 +3036,12 @@ const defaultWidgetOptions$s = {
4814
3036
  };
4815
3037
  const dropdownWidgetLogic = {
4816
3038
  name: "definition",
4817
- defaultWidgetOptions: defaultWidgetOptions$s,
3039
+ defaultWidgetOptions: defaultWidgetOptions$r,
4818
3040
  defaultAlignment: "inline-block",
4819
3041
  getPublicWidgetOptions: getDropdownPublicWidgetOptions
4820
3042
  };
4821
3043
 
4822
- const defaultWidgetOptions$r = {
3044
+ const defaultWidgetOptions$q = {
4823
3045
  showPrompt: "Explain",
4824
3046
  hidePrompt: "Hide explanation",
4825
3047
  explanation: "explanation goes here\n\nmore explanation",
@@ -4827,31 +3049,46 @@ const defaultWidgetOptions$r = {
4827
3049
  };
4828
3050
  const explanationWidgetLogic = {
4829
3051
  name: "explanation",
4830
- defaultWidgetOptions: defaultWidgetOptions$r,
3052
+ defaultWidgetOptions: defaultWidgetOptions$q,
4831
3053
  defaultAlignment: "inline"
4832
3054
  };
4833
3055
 
4834
- const currentVersion$3 = {
4835
- major: 1,
3056
+ const currentVersion$2 = {
3057
+ major: 2,
4836
3058
  minor: 0
4837
3059
  };
4838
- const widgetOptionsUpgrades$2 = {
4839
- "1": v0options => ({
4840
- times: v0options.times,
4841
- buttonSets: v0options.buttonSets,
4842
- functions: v0options.functions,
4843
- buttonsVisible: v0options.buttonsVisible,
4844
- visibleLabel: v0options.visibleLabel,
4845
- ariaLabel: v0options.ariaLabel,
4846
- answerForms: [{
4847
- considered: "correct",
4848
- form: v0options.form,
4849
- simplify: v0options.simplify,
4850
- value: v0options.value
4851
- }]
4852
- })
3060
+ const widgetOptionsUpgrades$1 = {
3061
+ "2": v1options => {
3062
+ return {
3063
+ times: v1options.times,
3064
+ buttonSets: v1options.buttonSets,
3065
+ functions: v1options.functions,
3066
+ buttonsVisible: v1options.buttonsVisible,
3067
+ visibleLabel: v1options.visibleLabel,
3068
+ ariaLabel: v1options.ariaLabel,
3069
+ answerForms: v1options.answerForms,
3070
+ extraKeys: v1options.extraKeys || deriveExtraKeys(v1options)
3071
+ };
3072
+ },
3073
+ "1": v0options => {
3074
+ return {
3075
+ times: v0options.times,
3076
+ buttonSets: v0options.buttonSets,
3077
+ functions: v0options.functions,
3078
+ buttonsVisible: v0options.buttonsVisible,
3079
+ visibleLabel: v0options.visibleLabel,
3080
+ ariaLabel: v0options.ariaLabel,
3081
+ extraKeys: v0options.extraKeys,
3082
+ answerForms: [{
3083
+ considered: "correct",
3084
+ form: v0options.form,
3085
+ simplify: v0options.simplify,
3086
+ value: v0options.value
3087
+ }]
3088
+ };
3089
+ }
4853
3090
  };
4854
- const defaultWidgetOptions$q = {
3091
+ const defaultWidgetOptions$p = {
4855
3092
  answerForms: [],
4856
3093
  times: false,
4857
3094
  buttonSets: ["basic"],
@@ -4874,20 +3111,21 @@ function getExpressionPublicWidgetOptions(options) {
4874
3111
  times: options.times,
4875
3112
  visibleLabel: options.visibleLabel,
4876
3113
  ariaLabel: options.ariaLabel,
4877
- buttonsVisible: options.buttonsVisible
3114
+ buttonsVisible: options.buttonsVisible,
3115
+ extraKeys: options.extraKeys
4878
3116
  };
4879
3117
  }
4880
3118
 
4881
3119
  const expressionWidgetLogic = {
4882
3120
  name: "expression",
4883
- version: currentVersion$3,
4884
- widgetOptionsUpgrades: widgetOptionsUpgrades$2,
4885
- defaultWidgetOptions: defaultWidgetOptions$q,
3121
+ version: currentVersion$2,
3122
+ widgetOptionsUpgrades: widgetOptionsUpgrades$1,
3123
+ defaultWidgetOptions: defaultWidgetOptions$p,
4886
3124
  defaultAlignment: "inline-block",
4887
3125
  getPublicWidgetOptions: getExpressionPublicWidgetOptions
4888
3126
  };
4889
3127
 
4890
- const defaultWidgetOptions$p = {
3128
+ const defaultWidgetOptions$o = {
4891
3129
  title: "",
4892
3130
  content: "",
4893
3131
  widgets: {},
@@ -4896,34 +3134,24 @@ const defaultWidgetOptions$p = {
4896
3134
  };
4897
3135
  const gradedGroupWidgetLogic = {
4898
3136
  name: "graded-group",
4899
- defaultWidgetOptions: defaultWidgetOptions$p
3137
+ defaultWidgetOptions: defaultWidgetOptions$o
4900
3138
  };
4901
3139
 
4902
- const defaultWidgetOptions$o = {
3140
+ const defaultWidgetOptions$n = {
4903
3141
  gradedGroups: []
4904
3142
  };
4905
3143
  const gradedGroupSetWidgetLogic = {
4906
3144
  name: "graded-group-set",
4907
- defaultWidgetOptions: defaultWidgetOptions$o
3145
+ defaultWidgetOptions: defaultWidgetOptions$n
4908
3146
  };
4909
3147
 
4910
- function _objectWithoutPropertiesLoose(r, e) {
4911
- if (null == r) return {};
4912
- var t = {};
4913
- for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
4914
- if (-1 !== e.indexOf(n)) continue;
4915
- t[n] = r[n];
4916
- }
4917
- return t;
4918
- }
4919
-
4920
- const _excluded$9 = ["correct"];
3148
+ const _excluded$8 = ["correct"];
4921
3149
  function getGrapherPublicWidgetOptions(options) {
4922
- const publicOptions = _objectWithoutPropertiesLoose(options, _excluded$9);
3150
+ const publicOptions = _objectWithoutPropertiesLoose(options, _excluded$8);
4923
3151
  return publicOptions;
4924
3152
  }
4925
3153
 
4926
- const defaultWidgetOptions$n = {
3154
+ const defaultWidgetOptions$m = {
4927
3155
  graph: {
4928
3156
  labels: ["x", "y"],
4929
3157
  range: [[-10, 10], [-10, 10]],
@@ -4945,25 +3173,25 @@ const defaultWidgetOptions$n = {
4945
3173
  };
4946
3174
  const grapherWidgetLogic = {
4947
3175
  name: "grapher",
4948
- defaultWidgetOptions: defaultWidgetOptions$n,
3176
+ defaultWidgetOptions: defaultWidgetOptions$m,
4949
3177
  getPublicWidgetOptions: getGrapherPublicWidgetOptions
4950
3178
  };
4951
3179
 
4952
- const defaultWidgetOptions$m = {
3180
+ const defaultWidgetOptions$l = {
4953
3181
  content: "",
4954
3182
  widgets: {},
4955
3183
  images: {}
4956
3184
  };
4957
3185
  const groupWidgetLogic = {
4958
3186
  name: "group",
4959
- defaultWidgetOptions: defaultWidgetOptions$m
3187
+ defaultWidgetOptions: defaultWidgetOptions$l
4960
3188
  };
4961
3189
 
4962
3190
  function getIFramePublicWidgetOptions(options) {
4963
3191
  return options;
4964
3192
  }
4965
3193
 
4966
- const defaultWidgetOptions$l = {
3194
+ const defaultWidgetOptions$k = {
4967
3195
  url: "",
4968
3196
  settings: [{
4969
3197
  name: "",
@@ -4976,11 +3204,11 @@ const defaultWidgetOptions$l = {
4976
3204
  };
4977
3205
  const iframeWidgetLogic = {
4978
3206
  name: "iframe",
4979
- defaultWidgetOptions: defaultWidgetOptions$l,
3207
+ defaultWidgetOptions: defaultWidgetOptions$k,
4980
3208
  getPublicWidgetOptions: getIFramePublicWidgetOptions
4981
3209
  };
4982
3210
 
4983
- const defaultWidgetOptions$k = {
3211
+ const defaultWidgetOptions$j = {
4984
3212
  title: "",
4985
3213
  range: [[0, 10], [0, 10]],
4986
3214
  box: [400, 400],
@@ -4995,12 +3223,12 @@ const defaultWidgetOptions$k = {
4995
3223
  };
4996
3224
  const imageWidgetLogic = {
4997
3225
  name: "image",
4998
- defaultWidgetOptions: defaultWidgetOptions$k,
3226
+ defaultWidgetOptions: defaultWidgetOptions$j,
4999
3227
  supportedAlignments: ["block", "full-width"],
5000
3228
  defaultAlignment: "block"
5001
3229
  };
5002
3230
 
5003
- const defaultWidgetOptions$j = {
3231
+ const defaultWidgetOptions$i = {
5004
3232
  value: 0,
5005
3233
  simplify: "required",
5006
3234
  size: "normal",
@@ -5011,11 +3239,11 @@ const defaultWidgetOptions$j = {
5011
3239
  };
5012
3240
  const inputNumberWidgetLogic = {
5013
3241
  name: "input-number",
5014
- defaultWidgetOptions: defaultWidgetOptions$j,
3242
+ defaultWidgetOptions: defaultWidgetOptions$i,
5015
3243
  defaultAlignment: "inline-block"
5016
3244
  };
5017
3245
 
5018
- const defaultWidgetOptions$i = {
3246
+ const defaultWidgetOptions$h = {
5019
3247
  graph: {
5020
3248
  box: [400, 400],
5021
3249
  labels: ["x", "y"],
@@ -5028,16 +3256,16 @@ const defaultWidgetOptions$i = {
5028
3256
  };
5029
3257
  const interactionWidgetLogic = {
5030
3258
  name: "interaction",
5031
- defaultWidgetOptions: defaultWidgetOptions$i
3259
+ defaultWidgetOptions: defaultWidgetOptions$h
5032
3260
  };
5033
3261
 
5034
- const _excluded$8 = ["correct"];
3262
+ const _excluded$7 = ["correct"];
5035
3263
  function getInteractiveGraphPublicWidgetOptions(options) {
5036
- const publicOptions = _objectWithoutPropertiesLoose(options, _excluded$8);
3264
+ const publicOptions = _objectWithoutPropertiesLoose(options, _excluded$7);
5037
3265
  return publicOptions;
5038
3266
  }
5039
3267
 
5040
- const defaultWidgetOptions$h = {
3268
+ const defaultWidgetOptions$g = {
5041
3269
  labels: ["x", "y"],
5042
3270
  range: [[-10, 10], [-10, 10]],
5043
3271
  step: [1, 1],
@@ -5057,11 +3285,11 @@ const defaultWidgetOptions$h = {
5057
3285
  };
5058
3286
  const interactiveGraphWidgetLogic = {
5059
3287
  name: "interactive-graph",
5060
- defaultWidgetOptions: defaultWidgetOptions$h,
3288
+ defaultWidgetOptions: defaultWidgetOptions$g,
5061
3289
  getPublicWidgetOptions: getInteractiveGraphPublicWidgetOptions
5062
3290
  };
5063
3291
 
5064
- const _excluded$7 = ["answers"];
3292
+ const _excluded$6 = ["answers"];
5065
3293
  /**
5066
3294
  * For details on the individual options, see the
5067
3295
  * PerseusLabelImageWidgetOptions type
@@ -5073,11 +3301,11 @@ function getLabelImagePublicWidgetOptions(options) {
5073
3301
  });
5074
3302
  }
5075
3303
  function getLabelImageMarkerPublicData(marker) {
5076
- const publicData = _objectWithoutPropertiesLoose(marker, _excluded$7);
3304
+ const publicData = _objectWithoutPropertiesLoose(marker, _excluded$6);
5077
3305
  return publicData;
5078
3306
  }
5079
3307
 
5080
- const defaultWidgetOptions$g = {
3308
+ const defaultWidgetOptions$f = {
5081
3309
  choices: [],
5082
3310
  imageAlt: "",
5083
3311
  imageUrl: "",
@@ -5089,7 +3317,7 @@ const defaultWidgetOptions$g = {
5089
3317
  };
5090
3318
  const labelImageWidgetLogic = {
5091
3319
  name: "label-image",
5092
- defaultWidgetOptions: defaultWidgetOptions$g,
3320
+ defaultWidgetOptions: defaultWidgetOptions$f,
5093
3321
  getPublicWidgetOptions: getLabelImagePublicWidgetOptions
5094
3322
  };
5095
3323
 
@@ -5104,9 +3332,9 @@ const shuffleMatcher = props => {
5104
3332
  // If the order doesn't matter, don't shuffle the left column
5105
3333
  left = props.left;
5106
3334
  } else {
5107
- left = shuffle$2(props.left, rng, /* ensurePermuted */true);
3335
+ left = shuffle$1(props.left, rng, /* ensurePermuted */true);
5108
3336
  }
5109
- const right = shuffle$2(props.right, rng, /* ensurePermuted */true);
3337
+ const right = shuffle$1(props.right, rng, /* ensurePermuted */true);
5110
3338
  return {
5111
3339
  left,
5112
3340
  right
@@ -5121,9 +3349,9 @@ function shuffleMatcherWithRandom(data) {
5121
3349
  // If the order doesn't matter, don't shuffle the left column
5122
3350
  left = data.left;
5123
3351
  } else {
5124
- left = shuffle$2(data.left, Math.random, /* ensurePermuted */true);
3352
+ left = shuffle$1(data.left, Math.random, /* ensurePermuted */true);
5125
3353
  }
5126
- const right = shuffle$2(data.right, Math.random, /* ensurePermuted */true);
3354
+ const right = shuffle$1(data.right, Math.random, /* ensurePermuted */true);
5127
3355
  return {
5128
3356
  left,
5129
3357
  right
@@ -5150,7 +3378,7 @@ function getMatcherPublicWidgetOptions(options) {
5150
3378
  });
5151
3379
  }
5152
3380
 
5153
- const defaultWidgetOptions$f = {
3381
+ const defaultWidgetOptions$e = {
5154
3382
  left: ["$x$", "$y$", "$z$"],
5155
3383
  right: ["$1$", "$2$", "$3$"],
5156
3384
  labels: ["test", "label"],
@@ -5159,17 +3387,17 @@ const defaultWidgetOptions$f = {
5159
3387
  };
5160
3388
  const matcherWidgetLogic = {
5161
3389
  name: "matcher",
5162
- defaultWidgetOptions: defaultWidgetOptions$f,
3390
+ defaultWidgetOptions: defaultWidgetOptions$e,
5163
3391
  getPublicWidgetOptions: getMatcherPublicWidgetOptions
5164
3392
  };
5165
3393
 
5166
- const _excluded$6 = ["answers"];
3394
+ const _excluded$5 = ["answers"];
5167
3395
  function getMatrixPublicWidgetOptions(options) {
5168
- const publicOptions = _objectWithoutPropertiesLoose(options, _excluded$6);
3396
+ const publicOptions = _objectWithoutPropertiesLoose(options, _excluded$5);
5169
3397
  return publicOptions;
5170
3398
  }
5171
3399
 
5172
- const defaultWidgetOptions$e = {
3400
+ const defaultWidgetOptions$d = {
5173
3401
  matrixBoardSize: [3, 3],
5174
3402
  answers: [[]],
5175
3403
  prefix: "",
@@ -5178,23 +3406,23 @@ const defaultWidgetOptions$e = {
5178
3406
  };
5179
3407
  const matrixWidgetLogic = {
5180
3408
  name: "matrix",
5181
- defaultWidgetOptions: defaultWidgetOptions$e,
3409
+ defaultWidgetOptions: defaultWidgetOptions$d,
5182
3410
  getPublicWidgetOptions: getMatrixPublicWidgetOptions
5183
3411
  };
5184
3412
 
5185
- const _excluded$5 = ["imageUrl", "imageTop", "imageLeft"];
5186
- const currentVersion$2 = {
3413
+ const _excluded$4 = ["imageUrl", "imageTop", "imageLeft"];
3414
+ const currentVersion$1 = {
5187
3415
  major: 1,
5188
3416
  minor: 0
5189
3417
  };
5190
- const widgetOptionsUpgrades$1 = {
3418
+ const widgetOptionsUpgrades = {
5191
3419
  "1": v0options => {
5192
3420
  const {
5193
3421
  imageUrl,
5194
3422
  imageTop,
5195
3423
  imageLeft
5196
3424
  } = v0options,
5197
- rest = _objectWithoutPropertiesLoose(v0options, _excluded$5);
3425
+ rest = _objectWithoutPropertiesLoose(v0options, _excluded$4);
5198
3426
  return _extends({}, rest, {
5199
3427
  image: {
5200
3428
  url: imageUrl,
@@ -5204,7 +3432,7 @@ const widgetOptionsUpgrades$1 = {
5204
3432
  });
5205
3433
  }
5206
3434
  };
5207
- const defaultWidgetOptions$d = {
3435
+ const defaultWidgetOptions$c = {
5208
3436
  box: [480, 480],
5209
3437
  image: {},
5210
3438
  showProtractor: true,
@@ -5217,18 +3445,18 @@ const defaultWidgetOptions$d = {
5217
3445
 
5218
3446
  const measurerWidgetLogic = {
5219
3447
  name: "measurer",
5220
- version: currentVersion$2,
5221
- widgetOptionsUpgrades: widgetOptionsUpgrades$1,
5222
- defaultWidgetOptions: defaultWidgetOptions$d
3448
+ version: currentVersion$1,
3449
+ widgetOptionsUpgrades: widgetOptionsUpgrades,
3450
+ defaultWidgetOptions: defaultWidgetOptions$c
5223
3451
  };
5224
3452
 
5225
- const _excluded$4 = ["correctX", "correctRel"];
3453
+ const _excluded$3 = ["correctX", "correctRel"];
5226
3454
  function getNumberLinePublicWidgetOptions(options) {
5227
- const publicOptions = _objectWithoutPropertiesLoose(options, _excluded$4);
3455
+ const publicOptions = _objectWithoutPropertiesLoose(options, _excluded$3);
5228
3456
  return publicOptions;
5229
3457
  }
5230
3458
 
5231
- const defaultWidgetOptions$c = {
3459
+ const defaultWidgetOptions$b = {
5232
3460
  range: [0, 10],
5233
3461
  labelRange: [null, null],
5234
3462
  labelStyle: "decimal",
@@ -5244,26 +3472,48 @@ const defaultWidgetOptions$c = {
5244
3472
  };
5245
3473
  const numberLineWidgetLogic = {
5246
3474
  name: "number-line",
5247
- defaultWidgetOptions: defaultWidgetOptions$c,
3475
+ defaultWidgetOptions: defaultWidgetOptions$b,
5248
3476
  getPublicWidgetOptions: getNumberLinePublicWidgetOptions
5249
3477
  };
5250
3478
 
5251
- const _excluded$3 = ["answers"];
3479
+ const _excluded$2 = ["answers"];
5252
3480
  /**
5253
3481
  * For details on the individual options, see the
5254
3482
  * PerseusNumericInputWidgetOptions type
5255
3483
  */
5256
3484
 
3485
+ /**
3486
+ * This data from `answers` is used pre-scoring to give hints
3487
+ * to the learner regarding the format of accepted answers
3488
+ */
3489
+ function getNumericInputAnswerPublicData(answer) {
3490
+ const {
3491
+ answerForms,
3492
+ simplify,
3493
+ status
3494
+ } = answer;
3495
+ return {
3496
+ answerForms,
3497
+ simplify,
3498
+ status
3499
+ };
3500
+ }
3501
+
5257
3502
  /**
5258
3503
  * Given a PerseusNumericInputWidgetOptions object, return a new object with only
5259
3504
  * the public options that should be exposed to the client.
5260
3505
  */
5261
3506
  function getNumericInputPublicWidgetOptions(options) {
5262
- const publicWidgetOptions = _objectWithoutPropertiesLoose(options, _excluded$3);
5263
- return publicWidgetOptions;
3507
+ const {
3508
+ answers
3509
+ } = options,
3510
+ publicWidgetOptions = _objectWithoutPropertiesLoose(options, _excluded$2);
3511
+ return _extends({}, publicWidgetOptions, {
3512
+ answers: answers.map(getNumericInputAnswerPublicData)
3513
+ });
5264
3514
  }
5265
3515
 
5266
- const defaultWidgetOptions$b = {
3516
+ const defaultWidgetOptions$a = {
5267
3517
  answers: [{
5268
3518
  value: null,
5269
3519
  status: "correct",
@@ -5280,7 +3530,7 @@ const defaultWidgetOptions$b = {
5280
3530
  };
5281
3531
  const numericInputWidgetLogic = {
5282
3532
  name: "numeric-input",
5283
- defaultWidgetOptions: defaultWidgetOptions$b,
3533
+ defaultWidgetOptions: defaultWidgetOptions$a,
5284
3534
  defaultAlignment: "inline-block",
5285
3535
  getPublicWidgetOptions: getNumericInputPublicWidgetOptions
5286
3536
  };
@@ -5302,7 +3552,7 @@ function getOrdererPublicWidgetOptions(options) {
5302
3552
  };
5303
3553
  }
5304
3554
 
5305
- const defaultWidgetOptions$a = {
3555
+ const defaultWidgetOptions$9 = {
5306
3556
  correctOptions: [{
5307
3557
  content: "$x$"
5308
3558
  }],
@@ -5314,11 +3564,11 @@ const defaultWidgetOptions$a = {
5314
3564
  };
5315
3565
  const ordererWidgetLogic = {
5316
3566
  name: "orderer",
5317
- defaultWidgetOptions: defaultWidgetOptions$a,
3567
+ defaultWidgetOptions: defaultWidgetOptions$9,
5318
3568
  getPublicWidgetOptions: getOrdererPublicWidgetOptions
5319
3569
  };
5320
3570
 
5321
- const defaultWidgetOptions$9 = {
3571
+ const defaultWidgetOptions$8 = {
5322
3572
  passageTitle: "",
5323
3573
  passageText: "",
5324
3574
  footnotes: "",
@@ -5326,14 +3576,14 @@ const defaultWidgetOptions$9 = {
5326
3576
  };
5327
3577
  const passageWidgetLogic = {
5328
3578
  name: "passage",
5329
- defaultWidgetOptions: defaultWidgetOptions$9
3579
+ defaultWidgetOptions: defaultWidgetOptions$8
5330
3580
  };
5331
3581
 
5332
- const currentVersion$1 = {
3582
+ const currentVersion = {
5333
3583
  major: 0,
5334
3584
  minor: 1
5335
3585
  };
5336
- const defaultWidgetOptions$8 = {
3586
+ const defaultWidgetOptions$7 = {
5337
3587
  passageNumber: 1,
5338
3588
  referenceNumber: 1,
5339
3589
  summaryText: ""
@@ -5341,30 +3591,30 @@ const defaultWidgetOptions$8 = {
5341
3591
 
5342
3592
  const passageRefWidgetLogic = {
5343
3593
  name: "passageRef",
5344
- version: currentVersion$1,
5345
- defaultWidgetOptions: defaultWidgetOptions$8,
3594
+ version: currentVersion,
3595
+ defaultWidgetOptions: defaultWidgetOptions$7,
5346
3596
  defaultAlignment: "inline"
5347
3597
  };
5348
3598
 
5349
- const defaultWidgetOptions$7 = {
3599
+ const defaultWidgetOptions$6 = {
5350
3600
  content: ""
5351
3601
  };
5352
3602
  const passageRefTargetWidgetLogic = {
5353
3603
  name: "passageRefTarget",
5354
- defaultWidgetOptions: defaultWidgetOptions$7,
3604
+ defaultWidgetOptions: defaultWidgetOptions$6,
5355
3605
  defaultAlignment: "inline"
5356
3606
  };
5357
3607
 
5358
- const defaultWidgetOptions$6 = {
3608
+ const defaultWidgetOptions$5 = {
5359
3609
  url: "",
5360
3610
  description: ""
5361
3611
  };
5362
3612
  const phetSimulationWidgetLogic = {
5363
3613
  name: "phet-simulation",
5364
- defaultWidgetOptions: defaultWidgetOptions$6
3614
+ defaultWidgetOptions: defaultWidgetOptions$5
5365
3615
  };
5366
3616
 
5367
- const _excluded$2 = ["correct"];
3617
+ const _excluded$1 = ["correct"];
5368
3618
  /**
5369
3619
  * For details on the individual options, see the
5370
3620
  * PerseusPlotterWidgetOptions type
@@ -5375,11 +3625,11 @@ const _excluded$2 = ["correct"];
5375
3625
  * the public options that should be exposed to the client.
5376
3626
  */
5377
3627
  function getPlotterPublicWidgetOptions(options) {
5378
- const publicOptions = _objectWithoutPropertiesLoose(options, _excluded$2);
3628
+ const publicOptions = _objectWithoutPropertiesLoose(options, _excluded$1);
5379
3629
  return publicOptions;
5380
3630
  }
5381
3631
 
5382
- const defaultWidgetOptions$5 = {
3632
+ const defaultWidgetOptions$4 = {
5383
3633
  scaleY: 1,
5384
3634
  maxY: 10,
5385
3635
  snapsPerLine: 2,
@@ -5396,46 +3646,17 @@ const defaultWidgetOptions$5 = {
5396
3646
  };
5397
3647
  const plotterWidgetLogic = {
5398
3648
  name: "plotter",
5399
- defaultWidgetOptions: defaultWidgetOptions$5,
3649
+ defaultWidgetOptions: defaultWidgetOptions$4,
5400
3650
  getPublicWidgetOptions: getPlotterPublicWidgetOptions
5401
3651
  };
5402
3652
 
5403
- const defaultWidgetOptions$4 = {
3653
+ const defaultWidgetOptions$3 = {
5404
3654
  programID: "",
5405
3655
  height: 400
5406
3656
  };
5407
3657
  const pythonProgramWidgetLogic = {
5408
3658
  name: "python-program",
5409
- defaultWidgetOptions: defaultWidgetOptions$4
5410
- };
5411
-
5412
- const _excluded$1 = ["noneOfTheAbove"];
5413
- const currentVersion = {
5414
- major: 1,
5415
- minor: 0
5416
- };
5417
- const widgetOptionsUpgrades = {
5418
- "1": v0props => {
5419
- const {
5420
- noneOfTheAbove
5421
- } = v0props,
5422
- rest = _objectWithoutPropertiesLoose(v0props, _excluded$1);
5423
- if (noneOfTheAbove) {
5424
- throw new Error("radio widget v0 no longer supports auto noneOfTheAbove");
5425
- }
5426
- return _extends({}, rest, {
5427
- hasNoneOfTheAbove: false
5428
- });
5429
- }
5430
- };
5431
- const defaultWidgetOptions$3 = {
5432
- choices: [{}, {}, {}, {}],
5433
- displayCount: null,
5434
- randomize: false,
5435
- hasNoneOfTheAbove: false,
5436
- multipleSelect: false,
5437
- countChoices: false,
5438
- deselectEnabled: false
3659
+ defaultWidgetOptions: defaultWidgetOptions$3
5439
3660
  };
5440
3661
 
5441
3662
  /**
@@ -5464,21 +3685,40 @@ function getRadioChoicePublicData(choice) {
5464
3685
  };
5465
3686
  }
5466
3687
 
3688
+ /**
3689
+ * Shared functionality to determine if numCorrect is used, because:
3690
+ *
3691
+ * 1. numCorrect is conditionally used for rendering pre-scoring
3692
+ * 2. numCorrect also exposes information about answers
3693
+ *
3694
+ * So only include/use numCorrect when we know it's useful.
3695
+ */
3696
+ function usesNumCorrect(multipleSelect, countChoices, numCorrect) {
3697
+ return multipleSelect && countChoices && numCorrect;
3698
+ }
3699
+
5467
3700
  /**
5468
3701
  * Given a PerseusRadioWidgetOptions object, return a new object with only
5469
3702
  * the public options that should be exposed to the client.
5470
3703
  */
5471
3704
  function getRadioPublicWidgetOptions(options) {
3705
+ const {
3706
+ numCorrect,
3707
+ choices,
3708
+ multipleSelect,
3709
+ countChoices
3710
+ } = options;
5472
3711
  return _extends({}, options, {
5473
- choices: options.choices.map(getRadioChoicePublicData)
3712
+ numCorrect: usesNumCorrect(multipleSelect, countChoices, numCorrect) ? numCorrect : undefined,
3713
+ choices: choices.map(getRadioChoicePublicData)
5474
3714
  });
5475
3715
  }
5476
3716
 
5477
3717
  const radioWidgetLogic = {
5478
3718
  name: "radio",
5479
- version: currentVersion,
5480
- widgetOptionsUpgrades: widgetOptionsUpgrades,
5481
- defaultWidgetOptions: defaultWidgetOptions$3,
3719
+ version: currentVersion$3,
3720
+ widgetOptionsUpgrades: widgetOptionsUpgrades$2,
3721
+ defaultWidgetOptions: defaultWidgetOptions$v,
5482
3722
  getPublicWidgetOptions: getRadioPublicWidgetOptions
5483
3723
  };
5484
3724
 
@@ -5492,7 +3732,7 @@ const radioWidgetLogic = {
5492
3732
  * the public options that should be exposed to the client.
5493
3733
  */
5494
3734
  function getSorterPublicWidgetOptions(options) {
5495
- const shuffledCorrect = shuffle$2(options.correct, Math.random, /* ensurePermuted */true);
3735
+ const shuffledCorrect = shuffle$1(options.correct, Math.random, /* ensurePermuted */true);
5496
3736
  return _extends({}, options, {
5497
3737
  // Note(Tamara): This does not provide correct answer information any longer.
5498
3738
  // To maintain compatibility with the original widget options, we are
@@ -5854,5 +4094,5 @@ function shuffle(array, randomSeed, ensurePermuted = false) {
5854
4094
  }
5855
4095
  const random = seededRNG(new Date().getTime() & 0xffffffff);
5856
4096
 
5857
- export { coreWidgetRegistry as CoreWidgetRegistry, Errors, grapherUtil as GrapherUtil, ItemExtras, PerseusError, PerseusExpressionAnswerFormConsidered, addLibraryVersionToPerseusDebug, addWidget, approximateDeepEqual, approximateEqual, categorizerWidgetLogic as categorizerLogic, csProgramWidgetLogic as csProgramLogic, deepClone, definitionWidgetLogic as definitionLogic, dropdownWidgetLogic as dropdownLogic, explanationWidgetLogic as explanationLogic, expressionWidgetLogic as expressionLogic, getCSProgramPublicWidgetOptions, getCategorizerPublicWidgetOptions, getDecimalSeparator, getDropdownPublicWidgetOptions, getExpressionPublicWidgetOptions, getGrapherPublicWidgetOptions, getIFramePublicWidgetOptions, getInteractiveGraphPublicWidgetOptions, getLabelImagePublicWidgetOptions, getMatcherPublicWidgetOptions, getMatrixPublicWidgetOptions, getMatrixSize, getNumberLinePublicWidgetOptions, getNumericInputPublicWidgetOptions, getOrdererPublicWidgetOptions, getPlotterPublicWidgetOptions, getRadioPublicWidgetOptions, getSorterPublicWidgetOptions, getTablePublicWidgetOptions, getUpgradedWidgetOptions, getWidgetIdsFromContent, getWidgetIdsFromContentByType, gradedGroupWidgetLogic as gradedGroupLogic, gradedGroupSetWidgetLogic as gradedGroupSetLogic, grapherWidgetLogic as grapherLogic, groupWidgetLogic as groupLogic, iframeWidgetLogic as iframeLogic, imageWidgetLogic as imageLogic, inputNumberWidgetLogic as inputNumberLogic, interactionWidgetLogic as interactionLogic, interactiveGraphWidgetLogic as interactiveGraphLogic, isFailure, isSuccess, labelImageWidgetLogic as labelImageLogic, libVersion, lockedFigureColorNames, lockedFigureColors, lockedFigureFillStyles, mapObject, matcherWidgetLogic as matcherLogic, matrixWidgetLogic as matrixLogic, measurerWidgetLogic as measurerLogic, numberLineWidgetLogic as numberLineLogic, numericInputWidgetLogic as numericInputLogic, ordererWidgetLogic as ordererLogic, parseAndMigratePerseusArticle, parseAndMigratePerseusItem, parsePerseusItem, passageWidgetLogic as passageLogic, passageRefWidgetLogic as passageRefLogic, passageRefTargetWidgetLogic as passageRefTargetLogic, phetSimulationWidgetLogic as phetSimulationLogic, plotterWidgetLogic as plotterLogic, plotterPlotTypes, pluck, pythonProgramWidgetLogic as pythonProgramLogic, radioWidgetLogic as radioLogic, random, seededRNG, shuffle, shuffleMatcher, sorterWidgetLogic as sorterLogic, splitPerseusItem, tableWidgetLogic as tableLogic, upgradeWidgetInfoToLatestVersion, videoWidgetLogic as videoLogic };
4097
+ export { coreWidgetRegistry as CoreWidgetRegistry, Errors, grapherUtil as GrapherUtil, ItemExtras, PerseusError, PerseusExpressionAnswerFormConsidered, addWidget, approximateDeepEqual, approximateEqual, categorizerWidgetLogic as categorizerLogic, csProgramWidgetLogic as csProgramLogic, deepClone, definitionWidgetLogic as definitionLogic, deriveExtraKeys, deriveNumCorrect, dropdownWidgetLogic as dropdownLogic, explanationWidgetLogic as explanationLogic, expressionWidgetLogic as expressionLogic, getCSProgramPublicWidgetOptions, getCategorizerPublicWidgetOptions, getDecimalSeparator, getDropdownPublicWidgetOptions, getExpressionPublicWidgetOptions, getGrapherPublicWidgetOptions, getIFramePublicWidgetOptions, getInteractiveGraphPublicWidgetOptions, getLabelImagePublicWidgetOptions, getMatcherPublicWidgetOptions, getMatrixPublicWidgetOptions, getMatrixSize, getNumberLinePublicWidgetOptions, getNumericInputPublicWidgetOptions, getOrdererPublicWidgetOptions, getPlotterPublicWidgetOptions, getRadioPublicWidgetOptions, getSorterPublicWidgetOptions, getTablePublicWidgetOptions, getUpgradedWidgetOptions, getWidgetIdsFromContent, getWidgetIdsFromContentByType, gradedGroupWidgetLogic as gradedGroupLogic, gradedGroupSetWidgetLogic as gradedGroupSetLogic, grapherWidgetLogic as grapherLogic, groupWidgetLogic as groupLogic, iframeWidgetLogic as iframeLogic, imageWidgetLogic as imageLogic, inputNumberWidgetLogic as inputNumberLogic, interactionWidgetLogic as interactionLogic, interactiveGraphWidgetLogic as interactiveGraphLogic, isFailure, isSuccess, labelImageWidgetLogic as labelImageLogic, libVersion, lockedFigureColorNames, lockedFigureColors, lockedFigureFillStyles, mapObject, matcherWidgetLogic as matcherLogic, matrixWidgetLogic as matrixLogic, measurerWidgetLogic as measurerLogic, numberLineWidgetLogic as numberLineLogic, numericInputWidgetLogic as numericInputLogic, ordererWidgetLogic as ordererLogic, parseAndMigratePerseusArticle, parseAndMigratePerseusItem, parsePerseusItem, passageWidgetLogic as passageLogic, passageRefWidgetLogic as passageRefLogic, passageRefTargetWidgetLogic as passageRefTargetLogic, phetSimulationWidgetLogic as phetSimulationLogic, plotterWidgetLogic as plotterLogic, plotterPlotTypes, pluck, pythonProgramWidgetLogic as pythonProgramLogic, radioWidgetLogic as radioLogic, random, seededRNG, shuffle, shuffleMatcher, sorterWidgetLogic as sorterLogic, splitPerseusItem, tableWidgetLogic as tableLogic, upgradeWidgetInfoToLatestVersion, usesNumCorrect, videoWidgetLogic as videoLogic };
5858
4098
  //# sourceMappingURL=index.js.map