@khanacademy/perseus-core 5.4.1 → 5.4.2

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
@@ -2,7 +2,7 @@ import _ from 'underscore';
2
2
  import _extends from '@babel/runtime/helpers/extends';
3
3
  import * as KAS from '@khanacademy/kas';
4
4
  import _objectWithoutPropertiesLoose from '@babel/runtime/helpers/objectWithoutPropertiesLoose';
5
- import { seededRNG as seededRNG$1, shuffle as shuffle$1 } from '@khanacademy/perseus-core';
5
+ import { addLibraryVersionToPerseusDebug } from '@khanacademy/perseus-utils';
6
6
 
7
7
  function getMatrixSize(matrix) {
8
8
  const matrixSize = [1, 1];
@@ -2738,10 +2738,10 @@ const parsePerseusItem$1 = object({
2738
2738
  question: parsePerseusRenderer,
2739
2739
  hints: defaulted(array(parseHint), () => []),
2740
2740
  answerArea: parsePerseusAnswerArea,
2741
- itemDataVersion: optional(object({
2741
+ itemDataVersion: optional(nullable(object({
2742
2742
  major: number,
2743
2743
  minor: number
2744
- })),
2744
+ }))),
2745
2745
  // Deprecated field
2746
2746
  answer: any
2747
2747
  });
@@ -2818,51 +2818,9 @@ function throwErrorIfCheatingDetected() {
2818
2818
  }
2819
2819
  }
2820
2820
 
2821
- /**
2822
- * Adds the given perseus library version information to the __perseus_debug__
2823
- * object and ensures that the object is attached to `globalThis` (`window` in
2824
- * browser environments).
2825
- *
2826
- * This allows each library to provide runtime version information to assist in
2827
- * debugging in production environments.
2828
- */
2829
- const addLibraryVersionToPerseusDebug = (libraryName, libraryVersion) => {
2830
- // If the library version is the default value, then we don't want to
2831
- // prefix it with a "v" to indicate that it is a version number.
2832
- let prefix = "v";
2833
- if (libraryVersion === "__lib_version__") {
2834
- prefix = "";
2835
- }
2836
- const formattedVersion = `${prefix}${libraryVersion}`;
2837
- if (typeof globalThis !== "undefined") {
2838
- var _globalThis$__perseus;
2839
- globalThis.__perseus_debug__ = (_globalThis$__perseus = globalThis.__perseus_debug__) != null ? _globalThis$__perseus : {};
2840
- const existingVersionEntry = globalThis.__perseus_debug__[libraryName];
2841
- if (existingVersionEntry) {
2842
- // If we already have an entry and it doesn't match the registered
2843
- // version, we morph the entry into an array and log a warning.
2844
- if (existingVersionEntry !== formattedVersion) {
2845
- // Existing entry might be an array already (oops, at least 2
2846
- // versions of the library already loaded!).
2847
- const allVersions = Array.isArray(existingVersionEntry) ? existingVersionEntry : [existingVersionEntry];
2848
- allVersions.push(formattedVersion);
2849
- globalThis.__perseus_debug__[libraryName] = allVersions;
2850
-
2851
- // eslint-disable-next-line no-console
2852
- console.warn(`Multiple versions of ${libraryName} loaded on this page: ${allVersions.sort().join(", ")}`);
2853
- }
2854
- } else {
2855
- globalThis.__perseus_debug__[libraryName] = formattedVersion;
2856
- }
2857
- } else {
2858
- // eslint-disable-next-line no-console
2859
- console.warn(`globalThis not found found (${formattedVersion})`);
2860
- }
2861
- };
2862
-
2863
2821
  // This file is processed by a Rollup plugin (replace) to inject the production
2864
2822
  const libName = "@khanacademy/perseus-core";
2865
- const libVersion = "5.4.1";
2823
+ const libVersion = "5.4.2";
2866
2824
  addLibraryVersionToPerseusDebug(libName, libVersion);
2867
2825
 
2868
2826
  /**
@@ -3339,20 +3297,73 @@ const labelImageWidgetLogic = {
3339
3297
  getPublicWidgetOptions: getLabelImagePublicWidgetOptions
3340
3298
  };
3341
3299
 
3300
+ /* Note(tamara): Brought over from the perseus package packages/perseus/src/util.ts file.
3301
+ May be useful to bring other perseus package utilities here. Contains utility functions
3302
+ and types used across multiple widgets for randomization and shuffling. */
3303
+ const seededRNG = function seededRNG(seed) {
3304
+ let randomSeed = seed;
3305
+ return function () {
3306
+ // Robert Jenkins' 32 bit integer hash function.
3307
+ let seed = randomSeed;
3308
+ seed = seed + 0x7ed55d16 + (seed << 12) & 0xffffffff;
3309
+ seed = (seed ^ 0xc761c23c ^ seed >>> 19) & 0xffffffff;
3310
+ seed = seed + 0x165667b1 + (seed << 5) & 0xffffffff;
3311
+ seed = (seed + 0xd3a2646c ^ seed << 9) & 0xffffffff;
3312
+ seed = seed + 0xfd7046c5 + (seed << 3) & 0xffffffff;
3313
+ seed = (seed ^ 0xb55a4f09 ^ seed >>> 16) & 0xffffffff;
3314
+ return (randomSeed = seed & 0xfffffff) / 0x10000000;
3315
+ };
3316
+ };
3317
+
3318
+ // Shuffle an array using a given random seed or function.
3319
+ // If `ensurePermuted` is true, the input and output are guaranteed to be
3320
+ // distinct permutations.
3321
+ function shuffle(array, randomSeed, ensurePermuted = false) {
3322
+ // Always return a copy of the input array
3323
+ const shuffled = _.clone(array);
3324
+
3325
+ // Handle edge cases (input array is empty or uniform)
3326
+ if (!shuffled.length || _.all(shuffled, function (value) {
3327
+ return _.isEqual(value, shuffled[0]);
3328
+ })) {
3329
+ return shuffled;
3330
+ }
3331
+ let random;
3332
+ if (typeof randomSeed === "function") {
3333
+ random = randomSeed;
3334
+ } else {
3335
+ random = seededRNG(randomSeed);
3336
+ }
3337
+ do {
3338
+ // Fischer-Yates shuffle
3339
+ for (let top = shuffled.length; top > 0; top--) {
3340
+ const newEnd = Math.floor(random() * top);
3341
+ const temp = shuffled[newEnd];
3342
+
3343
+ // @ts-expect-error - TS2542 - Index signature in type 'readonly T[]' only permits reading.
3344
+ shuffled[newEnd] = shuffled[top - 1];
3345
+ // @ts-expect-error - TS2542 - Index signature in type 'readonly T[]' only permits reading.
3346
+ shuffled[top - 1] = temp;
3347
+ }
3348
+ } while (ensurePermuted && _.isEqual(array, shuffled));
3349
+ return shuffled;
3350
+ }
3351
+ const random = seededRNG(new Date().getTime() & 0xffffffff);
3352
+
3342
3353
  // TODO(LEMS-2841): Should be able to remove once getPublicWidgetOptions is hooked up
3343
3354
 
3344
3355
  // TODO(LEMS-2841): Should be able to remove once getPublicWidgetOptions is hooked up
3345
3356
  const shuffleMatcher = props => {
3346
3357
  // Use the same random() function to shuffle both columns sequentially
3347
- const rng = seededRNG$1(props.problemNum);
3358
+ const rng = seededRNG(props.problemNum);
3348
3359
  let left;
3349
3360
  if (!props.orderMatters) {
3350
3361
  // If the order doesn't matter, don't shuffle the left column
3351
3362
  left = props.left;
3352
3363
  } else {
3353
- left = shuffle$1(props.left, rng, /* ensurePermuted */true);
3364
+ left = shuffle(props.left, rng, /* ensurePermuted */true);
3354
3365
  }
3355
- const right = shuffle$1(props.right, rng, /* ensurePermuted */true);
3366
+ const right = shuffle(props.right, rng, /* ensurePermuted */true);
3356
3367
  return {
3357
3368
  left,
3358
3369
  right
@@ -3367,9 +3378,9 @@ function shuffleMatcherWithRandom(data) {
3367
3378
  // If the order doesn't matter, don't shuffle the left column
3368
3379
  left = data.left;
3369
3380
  } else {
3370
- left = shuffle$1(data.left, Math.random, /* ensurePermuted */true);
3381
+ left = shuffle(data.left, Math.random, /* ensurePermuted */true);
3371
3382
  }
3372
- const right = shuffle$1(data.right, Math.random, /* ensurePermuted */true);
3383
+ const right = shuffle(data.right, Math.random, /* ensurePermuted */true);
3373
3384
  return {
3374
3385
  left,
3375
3386
  right
@@ -3750,7 +3761,7 @@ const radioWidgetLogic = {
3750
3761
  * the public options that should be exposed to the client.
3751
3762
  */
3752
3763
  function getSorterPublicWidgetOptions(options) {
3753
- const shuffledCorrect = shuffle$1(options.correct, Math.random, /* ensurePermuted */true);
3764
+ const shuffledCorrect = shuffle(options.correct, Math.random, /* ensurePermuted */true);
3754
3765
  return _extends({}, options, {
3755
3766
  // Note(Tamara): This does not provide correct answer information any longer.
3756
3767
  // To maintain compatibility with the original widget options, we are
@@ -4064,58 +4075,5 @@ function splitPerseusItem(originalItem) {
4064
4075
  });
4065
4076
  }
4066
4077
 
4067
- /* Note(tamara): Brought over from the perseus package packages/perseus/src/util.ts file.
4068
- May be useful to bring other perseus package utilities here. Contains utility functions
4069
- and types used across multiple widgets for randomization and shuffling. */
4070
- const seededRNG = function seededRNG(seed) {
4071
- let randomSeed = seed;
4072
- return function () {
4073
- // Robert Jenkins' 32 bit integer hash function.
4074
- let seed = randomSeed;
4075
- seed = seed + 0x7ed55d16 + (seed << 12) & 0xffffffff;
4076
- seed = (seed ^ 0xc761c23c ^ seed >>> 19) & 0xffffffff;
4077
- seed = seed + 0x165667b1 + (seed << 5) & 0xffffffff;
4078
- seed = (seed + 0xd3a2646c ^ seed << 9) & 0xffffffff;
4079
- seed = seed + 0xfd7046c5 + (seed << 3) & 0xffffffff;
4080
- seed = (seed ^ 0xb55a4f09 ^ seed >>> 16) & 0xffffffff;
4081
- return (randomSeed = seed & 0xfffffff) / 0x10000000;
4082
- };
4083
- };
4084
-
4085
- // Shuffle an array using a given random seed or function.
4086
- // If `ensurePermuted` is true, the input and output are guaranteed to be
4087
- // distinct permutations.
4088
- function shuffle(array, randomSeed, ensurePermuted = false) {
4089
- // Always return a copy of the input array
4090
- const shuffled = _.clone(array);
4091
-
4092
- // Handle edge cases (input array is empty or uniform)
4093
- if (!shuffled.length || _.all(shuffled, function (value) {
4094
- return _.isEqual(value, shuffled[0]);
4095
- })) {
4096
- return shuffled;
4097
- }
4098
- let random;
4099
- if (typeof randomSeed === "function") {
4100
- random = randomSeed;
4101
- } else {
4102
- random = seededRNG(randomSeed);
4103
- }
4104
- do {
4105
- // Fischer-Yates shuffle
4106
- for (let top = shuffled.length; top > 0; top--) {
4107
- const newEnd = Math.floor(random() * top);
4108
- const temp = shuffled[newEnd];
4109
-
4110
- // @ts-expect-error - TS2542 - Index signature in type 'readonly T[]' only permits reading.
4111
- shuffled[newEnd] = shuffled[top - 1];
4112
- // @ts-expect-error - TS2542 - Index signature in type 'readonly T[]' only permits reading.
4113
- shuffled[top - 1] = temp;
4114
- }
4115
- } while (ensurePermuted && _.isEqual(array, shuffled));
4116
- return shuffled;
4117
- }
4118
- const random = seededRNG(new Date().getTime() & 0xffffffff);
4119
-
4120
4078
  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 };
4121
4079
  //# sourceMappingURL=index.js.map