@khanacademy/perseus 41.3.0 → 41.5.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.css +3 -0
- package/dist/es/index.js +591 -97
- package/dist/es/index.js.map +1 -1
- package/dist/index.css +3 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.js +591 -97
- package/dist/index.js.map +1 -1
- package/dist/server-item-renderer.d.ts +1 -1
- package/dist/util/answer-types.d.ts +45 -2
- package/dist/util/parse-perseus-json/perseus-parsers/graded-group-set-widget.d.ts +3 -0
- package/dist/util/parse-perseus-json/perseus-parsers/graded-group-widget.d.ts +16 -0
- package/dist/util/parse-perseus-json/perseus-parsers/grapher-widget.d.ts +3 -0
- package/dist/util/parse-perseus-json/perseus-parsers/group-widget.d.ts +3 -0
- package/dist/util/parse-perseus-json/perseus-parsers/iframe-widget.d.ts +3 -0
- package/dist/util/parse-perseus-json/perseus-parsers/image-widget.d.ts +3 -0
- package/dist/util/parse-perseus-json/perseus-parsers/input-number-widget.d.ts +3 -0
- package/dist/util/parse-perseus-json/perseus-parsers/interaction-widget.d.ts +3 -0
- package/dist/util/parse-perseus-json/perseus-parsers/label-image-widget.d.ts +3 -0
- package/dist/util/parse-perseus-json/perseus-parsers/matcher-widget.d.ts +3 -0
- package/dist/util/parse-perseus-json/perseus-parsers/matrix-widget.d.ts +3 -0
- package/dist/util/parse-perseus-json/perseus-parsers/measurer-widget.d.ts +3 -0
- package/dist/util/parse-perseus-json/perseus-parsers/molecule-renderer-widget.d.ts +3 -0
- package/dist/util/parse-perseus-json/perseus-parsers/number-line-widget.d.ts +3 -0
- package/dist/util/parse-perseus-json/perseus-parsers/numeric-input-widget.d.ts +3 -0
- package/dist/util/parse-perseus-json/perseus-parsers/orderer-widget.d.ts +3 -0
- package/dist/util/parse-perseus-json/perseus-parsers/passage-ref-widget.d.ts +3 -0
- package/dist/util/parse-perseus-json/perseus-parsers/passage-widget.d.ts +3 -0
- package/dist/util/parse-perseus-json/perseus-parsers/phet-simulation-widget.d.ts +3 -0
- package/dist/util/parse-perseus-json/perseus-parsers/plotter-widget.d.ts +3 -0
- package/dist/util/parse-perseus-json/perseus-parsers/python-program-widget.d.ts +3 -0
- package/dist/util/parse-perseus-json/perseus-parsers/radio-widget.d.ts +3 -0
- package/dist/util/parse-perseus-json/perseus-parsers/sorter-widget.d.ts +3 -0
- package/dist/util/parse-perseus-json/perseus-parsers/table-widget.d.ts +3 -0
- package/dist/util/parse-perseus-json/perseus-parsers/video-widget.d.ts +3 -0
- package/dist/validation.types.d.ts +4 -2
- package/dist/widgets/numeric-input/numeric-input.d.ts +7 -0
- package/dist/widgets/table/score-table.d.ts +1 -1
- package/dist/widgets/table/utils.d.ts +7 -0
- package/dist/widgets/table/validate-table.d.ts +6 -0
- package/package.json +2 -2
package/dist/es/index.js
CHANGED
|
@@ -1464,7 +1464,7 @@ const MAXERROR_EPSILON = Math.pow(2, -42);
|
|
|
1464
1464
|
// TOOD(kevinb): Figure out how this relates to KEScore in
|
|
1465
1465
|
// perseus-all-package/types.js and see if there's a way to
|
|
1466
1466
|
// unify these types.
|
|
1467
|
-
|
|
1467
|
+
/**
|
|
1468
1468
|
* Answer types
|
|
1469
1469
|
*
|
|
1470
1470
|
* Utility for creating answerable questions displayed in exercises
|
|
@@ -1507,7 +1507,6 @@ const MAXERROR_EPSILON = Math.pow(2, -42);
|
|
|
1507
1507
|
* TODO(alpert): Think of a less-absurd name for createValidatorFunctional.
|
|
1508
1508
|
*
|
|
1509
1509
|
*/
|
|
1510
|
-
|
|
1511
1510
|
const KhanAnswerTypes = {
|
|
1512
1511
|
/*
|
|
1513
1512
|
* predicate answer type
|
|
@@ -1978,9 +1977,7 @@ const KhanAnswerTypes = {
|
|
|
1978
1977
|
})];
|
|
1979
1978
|
},
|
|
1980
1979
|
createValidatorFunctional: function (correctAnswer, options, strings) {
|
|
1981
|
-
return KhanAnswerTypes.predicate.createValidatorFunctional(
|
|
1982
|
-
// @ts-expect-error - TS2556 - A spread argument must either have a tuple type or be passed to a rest parameter.
|
|
1983
|
-
...KhanAnswerTypes.number.convertToPredicate(correctAnswer, options), strings);
|
|
1980
|
+
return KhanAnswerTypes.predicate.createValidatorFunctional(...KhanAnswerTypes.number.convertToPredicate(correctAnswer, options), strings);
|
|
1984
1981
|
}
|
|
1985
1982
|
},
|
|
1986
1983
|
/*
|
|
@@ -2594,7 +2591,7 @@ const keypadConfigurationForProps = widgetOptions => {
|
|
|
2594
2591
|
times: widgetOptions.times
|
|
2595
2592
|
};
|
|
2596
2593
|
};
|
|
2597
|
-
const propUpgrades$
|
|
2594
|
+
const propUpgrades$3 = {
|
|
2598
2595
|
/* c8 ignore next */
|
|
2599
2596
|
"1": v0props => ({
|
|
2600
2597
|
times: v0props.times,
|
|
@@ -2654,7 +2651,7 @@ var Expression$1 = {
|
|
|
2654
2651
|
major: 1,
|
|
2655
2652
|
minor: 0
|
|
2656
2653
|
},
|
|
2657
|
-
propUpgrades: propUpgrades$
|
|
2654
|
+
propUpgrades: propUpgrades$3,
|
|
2658
2655
|
// For use by the editor
|
|
2659
2656
|
isLintable: true,
|
|
2660
2657
|
scorer: scoreExpression,
|
|
@@ -18726,6 +18723,9 @@ const replaceDeprecatedWidgets = () => {
|
|
|
18726
18723
|
replaceWidget("sequence", "deprecated-standin");
|
|
18727
18724
|
replaceWidget("simulator", "deprecated-standin");
|
|
18728
18725
|
replaceWidget("unit-input", "deprecated-standin");
|
|
18726
|
+
|
|
18727
|
+
// Input-Number is a special case as it is being replaced by Numeric-Input
|
|
18728
|
+
replaceWidget("input-number", "numeric-input");
|
|
18729
18729
|
};
|
|
18730
18730
|
const registerEditors = editorsToRegister => {
|
|
18731
18731
|
editorsToRegister.forEach(editor => {
|
|
@@ -18760,6 +18760,11 @@ const replaceDeprecatedEditors = () => {
|
|
|
18760
18760
|
replaceEditor("sequence", "deprecated-standin");
|
|
18761
18761
|
replaceEditor("simulator", "deprecated-standin");
|
|
18762
18762
|
replaceEditor("unit-input", "deprecated-standin");
|
|
18763
|
+
|
|
18764
|
+
// We're replacing the input-number editor with the numeric-input editor here,
|
|
18765
|
+
// but we're also modifying the JSON content to convert input-number into the
|
|
18766
|
+
// numeric-input format over in editor-page.tsx on line 92.
|
|
18767
|
+
replaceEditor("input-number", "numeric-input");
|
|
18763
18768
|
};
|
|
18764
18769
|
const getWidget = name => {
|
|
18765
18770
|
var _widgets$name;
|
|
@@ -18810,10 +18815,8 @@ const getVersionVector = () => {
|
|
|
18810
18815
|
const getPublicWidgets = () => {
|
|
18811
18816
|
// TODO(alex): Update underscore.js so that _.pick can take a function.
|
|
18812
18817
|
// @ts-expect-error - TS2740 - Type 'Pick<{ [key: string]: Readonly<{ name: string; displayName: string; getWidget?: (() => ComponentType<any>) | undefined; accessible?: boolean | ((props: any) => boolean) | undefined; hidden?: boolean | undefined; ... 10 more ...; widget: ComponentType<...>; }>; }, string>' is missing the following properties from type 'readonly Readonly<{ name: string; displayName: string; getWidget?: (() => ComponentType<any>) | undefined; accessible?: boolean | ((props: any) => boolean) | undefined; hidden?: boolean | undefined; ... 10 more ...; widget: ComponentType<...>; }>[]': length, concat, join, slice, and 18 more.
|
|
18813
|
-
return _.pick(widgets,
|
|
18814
|
-
|
|
18815
|
-
_.reject(_.keys(widgets), function (name) {
|
|
18816
|
-
return widgets[name].hidden;
|
|
18818
|
+
return _.pick(widgets, _.reject(_.keys(widgets), function (name) {
|
|
18819
|
+
return widgets[name].hidden || name === "input-number";
|
|
18817
18820
|
}));
|
|
18818
18821
|
};
|
|
18819
18822
|
const isAccessible = widgetInfo => {
|
|
@@ -22153,7 +22156,7 @@ class NumericInput extends React.Component {
|
|
|
22153
22156
|
height: "auto"
|
|
22154
22157
|
}
|
|
22155
22158
|
});
|
|
22156
|
-
return /*#__PURE__*/React.createElement(
|
|
22159
|
+
return /*#__PURE__*/React.createElement(InputWithExamples, {
|
|
22157
22160
|
ref: ref => this.inputRef = ref,
|
|
22158
22161
|
value: this.props.currentValue,
|
|
22159
22162
|
onChange: this.handleChange,
|
|
@@ -22165,7 +22168,7 @@ class NumericInput extends React.Component {
|
|
|
22165
22168
|
id: this.props.widgetId,
|
|
22166
22169
|
disabled: this.props.apiOptions.readOnly,
|
|
22167
22170
|
style: styles.input
|
|
22168
|
-
})
|
|
22171
|
+
});
|
|
22169
22172
|
}
|
|
22170
22173
|
}
|
|
22171
22174
|
|
|
@@ -22234,13 +22237,65 @@ const propsTransform = function propsTransform(widgetOptions) {
|
|
|
22234
22237
|
});
|
|
22235
22238
|
return rendererProps;
|
|
22236
22239
|
};
|
|
22240
|
+
|
|
22241
|
+
// This function is being used to replace the input-number widget
|
|
22242
|
+
// with the numeric-input widget
|
|
22243
|
+
const propUpgrades$2 = {
|
|
22244
|
+
/* c8 ignore next */
|
|
22245
|
+
"1": initialProps => {
|
|
22246
|
+
// If the initialProps has a value, it means we're upgrading from
|
|
22247
|
+
// input-number to numeric-input. In this case, we need to upgrade
|
|
22248
|
+
// the widget options accordingly.
|
|
22249
|
+
if (initialProps.value) {
|
|
22250
|
+
const provideAnswerForm = initialProps.answerType !== "number";
|
|
22251
|
+
|
|
22252
|
+
// We need to determine the mathFormat for the numeric-input widget
|
|
22253
|
+
const mathFormat = initialProps.answerType === "rational" ? "proper" // input-number uses "rational" for proper fractions
|
|
22254
|
+
: initialProps.answerType; // Otherwise, we can use the answerType directly
|
|
22255
|
+
|
|
22256
|
+
// If adjusting this logic, also adjust the logic in the convertInputNumberWidgetOptions
|
|
22257
|
+
// function in input-number.ts in the Perseus Editor package's util folder
|
|
22258
|
+
const answers = [{
|
|
22259
|
+
value: initialProps.value,
|
|
22260
|
+
simplify: initialProps.simplify,
|
|
22261
|
+
answerForms: provideAnswerForm ? [mathFormat] : undefined,
|
|
22262
|
+
strict: initialProps.inexact,
|
|
22263
|
+
// We only want to set maxError if the inexact prop is true
|
|
22264
|
+
maxError: initialProps.inexact ? initialProps.maxError : 0,
|
|
22265
|
+
status: "correct",
|
|
22266
|
+
// Input-number only allows correct answers
|
|
22267
|
+
message: ""
|
|
22268
|
+
}];
|
|
22269
|
+
return {
|
|
22270
|
+
answers,
|
|
22271
|
+
size: initialProps.size,
|
|
22272
|
+
coefficient: false,
|
|
22273
|
+
// input-number doesn't have a coefficient prop
|
|
22274
|
+
labelText: "",
|
|
22275
|
+
// input-number doesn't have a labelText prop
|
|
22276
|
+
static: false,
|
|
22277
|
+
// static is always false for numeric-input
|
|
22278
|
+
rightAlign: initialProps.rightAlign || false
|
|
22279
|
+
};
|
|
22280
|
+
} else {
|
|
22281
|
+
// Otherwise simply return the initialProps as there's no differences
|
|
22282
|
+
// between v0 and v1 for numeric-input
|
|
22283
|
+
return initialProps;
|
|
22284
|
+
}
|
|
22285
|
+
}
|
|
22286
|
+
};
|
|
22237
22287
|
var NumericInput$1 = {
|
|
22238
22288
|
name: "numeric-input",
|
|
22239
22289
|
displayName: "Numeric input",
|
|
22240
22290
|
defaultAlignment: "inline-block",
|
|
22241
22291
|
accessible: true,
|
|
22242
22292
|
widget: NumericInput,
|
|
22293
|
+
version: {
|
|
22294
|
+
major: 1,
|
|
22295
|
+
minor: 0
|
|
22296
|
+
},
|
|
22243
22297
|
transform: propsTransform,
|
|
22298
|
+
propUpgrades: propUpgrades$2,
|
|
22244
22299
|
isLintable: true,
|
|
22245
22300
|
scorer: scoreNumericInput,
|
|
22246
22301
|
getOneCorrectAnswerFromRubric(rubric) {
|
|
@@ -31960,17 +32015,12 @@ const ItemExtras = [
|
|
|
31960
32015
|
// prettier-ignore
|
|
31961
32016
|
|
|
31962
32017
|
// prettier-ignore
|
|
31963
|
-
|
|
32018
|
+
// While this widget is deprecated, we still need the type for conversion purposes
|
|
31964
32019
|
// prettier-ignore
|
|
31965
|
-
|
|
31966
32020
|
// prettier-ignore
|
|
31967
|
-
|
|
31968
32021
|
// prettier-ignore
|
|
31969
|
-
|
|
31970
32022
|
//prettier-ignore
|
|
31971
|
-
|
|
31972
32023
|
// A background image applied to various widgets.
|
|
31973
|
-
|
|
31974
32024
|
const PerseusExpressionAnswerFormConsidered = ["correct", "wrong", "ungraded"];
|
|
31975
32025
|
|
|
31976
32026
|
// 2D range: xMin, xMax, yMin, yMax
|
|
@@ -32064,6 +32114,9 @@ function replaceOutsideTeX(mathString) {
|
|
|
32064
32114
|
// Condense adjacent text nodes into a single text node
|
|
32065
32115
|
function condenseTextNodes(nodes) {
|
|
32066
32116
|
const result = [];
|
|
32117
|
+
if (!nodes) {
|
|
32118
|
+
return result;
|
|
32119
|
+
}
|
|
32067
32120
|
let currentText = "";
|
|
32068
32121
|
for (const node of nodes) {
|
|
32069
32122
|
if (node.type === "math") {
|
|
@@ -44149,17 +44202,23 @@ var Sorter$1 = {
|
|
|
44149
44202
|
scorer: scoreSorter
|
|
44150
44203
|
};
|
|
44151
44204
|
|
|
44152
|
-
|
|
44153
|
-
|
|
44154
|
-
|
|
44155
|
-
|
|
44156
|
-
|
|
44157
|
-
|
|
44158
|
-
|
|
44159
|
-
|
|
44160
|
-
|
|
44161
|
-
|
|
44162
|
-
|
|
44205
|
+
/**
|
|
44206
|
+
* Filters the given table (modelled as a 2D array) to remove any rows that are
|
|
44207
|
+
* completely empty.
|
|
44208
|
+
*
|
|
44209
|
+
* @returns A new table with only non-empty rows.
|
|
44210
|
+
*/
|
|
44211
|
+
const filterNonEmpty = function filterNonEmpty(table) {
|
|
44212
|
+
return table.filter(function (row) {
|
|
44213
|
+
// Return only rows that are non-empty.
|
|
44214
|
+
return row.some(cell => cell);
|
|
44215
|
+
});
|
|
44216
|
+
};
|
|
44217
|
+
|
|
44218
|
+
function validateTable(userInput) {
|
|
44219
|
+
const supplied = filterNonEmpty(userInput);
|
|
44220
|
+
const hasEmptyCell = supplied.some(function (row) {
|
|
44221
|
+
return row.some(function (cell) {
|
|
44163
44222
|
return cell === "";
|
|
44164
44223
|
});
|
|
44165
44224
|
});
|
|
@@ -44169,6 +44228,16 @@ function scoreTable(state, rubric, strings) {
|
|
|
44169
44228
|
message: null
|
|
44170
44229
|
};
|
|
44171
44230
|
}
|
|
44231
|
+
return null;
|
|
44232
|
+
}
|
|
44233
|
+
|
|
44234
|
+
function scoreTable(userInput, rubric, strings) {
|
|
44235
|
+
const validationResult = validateTable(userInput);
|
|
44236
|
+
if (validationResult != null) {
|
|
44237
|
+
return validationResult;
|
|
44238
|
+
}
|
|
44239
|
+
const supplied = filterNonEmpty(userInput);
|
|
44240
|
+
const solution = filterNonEmpty(rubric.answers);
|
|
44172
44241
|
if (supplied.length !== solution.length) {
|
|
44173
44242
|
return {
|
|
44174
44243
|
type: "points",
|
|
@@ -44179,17 +44248,16 @@ function scoreTable(state, rubric, strings) {
|
|
|
44179
44248
|
}
|
|
44180
44249
|
const createValidator = KhanAnswerTypes.number.createValidatorFunctional;
|
|
44181
44250
|
let message = null;
|
|
44182
|
-
const allCorrect =
|
|
44251
|
+
const allCorrect = solution.every(function (rowSolution) {
|
|
44183
44252
|
for (let i = 0; i < supplied.length; i++) {
|
|
44184
44253
|
const rowSupplied = supplied[i];
|
|
44185
|
-
const correct =
|
|
44254
|
+
const correct = rowSupplied.every(function (cellSupplied, i) {
|
|
44186
44255
|
const cellSolution = rowSolution[i];
|
|
44187
44256
|
const validator = createValidator(cellSolution, {
|
|
44188
44257
|
simplify: true
|
|
44189
44258
|
}, strings);
|
|
44190
44259
|
const result = validator(cellSupplied);
|
|
44191
44260
|
if (result.message) {
|
|
44192
|
-
// @ts-expect-error - TS2322 - Type 'string' is not assignable to type 'null'.
|
|
44193
44261
|
message = result.message;
|
|
44194
44262
|
}
|
|
44195
44263
|
return result.correct;
|
|
@@ -44205,7 +44273,7 @@ function scoreTable(state, rubric, strings) {
|
|
|
44205
44273
|
type: "points",
|
|
44206
44274
|
earned: allCorrect ? 1 : 0,
|
|
44207
44275
|
total: 1,
|
|
44208
|
-
message
|
|
44276
|
+
message
|
|
44209
44277
|
};
|
|
44210
44278
|
}
|
|
44211
44279
|
|
|
@@ -44609,7 +44677,7 @@ const init = function init() {
|
|
|
44609
44677
|
|
|
44610
44678
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
44611
44679
|
const libName = "@khanacademy/perseus";
|
|
44612
|
-
const libVersion = "41.
|
|
44680
|
+
const libVersion = "41.5.0";
|
|
44613
44681
|
addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
44614
44682
|
|
|
44615
44683
|
const apiVersion = {
|
|
@@ -45313,7 +45381,7 @@ class ServerItemRenderer extends React.Component {
|
|
|
45313
45381
|
|
|
45314
45382
|
/**
|
|
45315
45383
|
* Accepts a question area widgetId, or an answer area widgetId of
|
|
45316
|
-
* the form "answer-input
|
|
45384
|
+
* the form "answer-numeric-input 1", or the string "answer-area"
|
|
45317
45385
|
* for the whole answer area (if the answer area is a single widget).
|
|
45318
45386
|
*/
|
|
45319
45387
|
_setWidgetProps(widgetId, newProps, callback) {
|
|
@@ -48268,6 +48336,118 @@ const parseExpressionWidget = parseWidget(constant("expression"), object({
|
|
|
48268
48336
|
buttonsVisible: optional(enumeration("always", "never", "focused"))
|
|
48269
48337
|
}));
|
|
48270
48338
|
|
|
48339
|
+
const parsePerseusRenderer = object({
|
|
48340
|
+
content: string,
|
|
48341
|
+
// This module has an import cycle with parseWidgetsMap, because the
|
|
48342
|
+
// `group` widget can contain another renderer.
|
|
48343
|
+
// The anonymous function below ensures that we don't try to access
|
|
48344
|
+
// parseWidgetsMap before it's defined.
|
|
48345
|
+
widgets: (rawVal, ctx) => parseWidgetsMap(rawVal, ctx),
|
|
48346
|
+
metadata: optional(array(string)),
|
|
48347
|
+
images: record(string, object({
|
|
48348
|
+
width: number,
|
|
48349
|
+
height: number
|
|
48350
|
+
}))
|
|
48351
|
+
});
|
|
48352
|
+
|
|
48353
|
+
const parseGradedGroupWidgetOptions = object({
|
|
48354
|
+
title: string,
|
|
48355
|
+
hasHint: optional(nullable(boolean)),
|
|
48356
|
+
// This module has an import cycle with parsePerseusRenderer.
|
|
48357
|
+
// The anonymous function below ensures that we don't try to access
|
|
48358
|
+
// parsePerseusRenderer before it's defined.
|
|
48359
|
+
hint: optional(nullable((rawVal, ctx) => parsePerseusRenderer(rawVal, ctx))),
|
|
48360
|
+
content: string,
|
|
48361
|
+
// This module has an import cycle with parseWidgetsMap.
|
|
48362
|
+
// The anonymous function below ensures that we don't try to access
|
|
48363
|
+
// parseWidgetsMap before it's defined.
|
|
48364
|
+
widgets: (rawVal, ctx) => parseWidgetsMap(rawVal, ctx),
|
|
48365
|
+
widgetEnabled: optional(nullable(boolean)),
|
|
48366
|
+
immutableWidgets: optional(nullable(boolean)),
|
|
48367
|
+
images: record(string, object({
|
|
48368
|
+
width: number,
|
|
48369
|
+
height: number
|
|
48370
|
+
}))
|
|
48371
|
+
});
|
|
48372
|
+
const parseGradedGroupWidget = parseWidget(constant("graded-group"), parseGradedGroupWidgetOptions);
|
|
48373
|
+
|
|
48374
|
+
const parseGradedGroupSetWidget = parseWidget(constant("graded-group-set"), object({
|
|
48375
|
+
gradedGroups: array(parseGradedGroupWidgetOptions)
|
|
48376
|
+
}));
|
|
48377
|
+
|
|
48378
|
+
const pairOfNumbers$3 = pair(number, number);
|
|
48379
|
+
const pairOfPoints = pair(pairOfNumbers$3, pairOfNumbers$3);
|
|
48380
|
+
const parseGrapherWidget = parseWidget(constant("grapher"), object({
|
|
48381
|
+
availableTypes: array(enumeration("absolute_value", "exponential", "linear", "logarithm", "quadratic", "sinusoid", "tangent")),
|
|
48382
|
+
correct: union(object({
|
|
48383
|
+
type: constant("absolute_value"),
|
|
48384
|
+
coords: pairOfPoints
|
|
48385
|
+
})).or(object({
|
|
48386
|
+
type: constant("exponential"),
|
|
48387
|
+
asymptote: pairOfPoints,
|
|
48388
|
+
coords: pairOfPoints
|
|
48389
|
+
})).or(object({
|
|
48390
|
+
type: constant("linear"),
|
|
48391
|
+
coords: pairOfPoints
|
|
48392
|
+
})).or(object({
|
|
48393
|
+
type: constant("logarithm"),
|
|
48394
|
+
asymptote: pairOfPoints,
|
|
48395
|
+
coords: pairOfPoints
|
|
48396
|
+
})).or(object({
|
|
48397
|
+
type: constant("quadratic"),
|
|
48398
|
+
coords: pairOfPoints
|
|
48399
|
+
})).or(object({
|
|
48400
|
+
type: constant("sinusoid"),
|
|
48401
|
+
coords: pairOfPoints
|
|
48402
|
+
})).or(object({
|
|
48403
|
+
type: constant("tangent"),
|
|
48404
|
+
coords: pairOfPoints
|
|
48405
|
+
})).parser,
|
|
48406
|
+
graph: object({
|
|
48407
|
+
backgroundImage: object({
|
|
48408
|
+
bottom: optional(number),
|
|
48409
|
+
height: optional(number),
|
|
48410
|
+
left: optional(number),
|
|
48411
|
+
scale: optional(number),
|
|
48412
|
+
url: optional(nullable(string)),
|
|
48413
|
+
width: optional(number)
|
|
48414
|
+
}),
|
|
48415
|
+
box: optional(pairOfNumbers$3),
|
|
48416
|
+
editableSettings: optional(array(enumeration("graph", "snap", "image", "measure"))),
|
|
48417
|
+
gridStep: optional(pairOfNumbers$3),
|
|
48418
|
+
labels: pair(string, string),
|
|
48419
|
+
markings: enumeration("graph", "none", "grid"),
|
|
48420
|
+
range: pair(pairOfNumbers$3, pairOfNumbers$3),
|
|
48421
|
+
rulerLabel: constant(""),
|
|
48422
|
+
rulerTicks: number,
|
|
48423
|
+
showProtractor: optional(boolean),
|
|
48424
|
+
showRuler: optional(boolean),
|
|
48425
|
+
showTooltips: optional(boolean),
|
|
48426
|
+
snapStep: optional(pairOfNumbers$3),
|
|
48427
|
+
step: pairOfNumbers$3,
|
|
48428
|
+
valid: optional(union(boolean).or(string).parser)
|
|
48429
|
+
})
|
|
48430
|
+
}));
|
|
48431
|
+
|
|
48432
|
+
const parseGroupWidget = parseWidget(constant("group"),
|
|
48433
|
+
// This module has an import cycle with parsePerseusRenderer.
|
|
48434
|
+
// The anonymous function below ensures that we don't try to access
|
|
48435
|
+
// parsePerseusRenderer before it's defined.
|
|
48436
|
+
(rawVal, ctx) => parsePerseusRenderer(rawVal, ctx));
|
|
48437
|
+
|
|
48438
|
+
const parseIframeWidget = parseWidget(constant("iframe"), object({
|
|
48439
|
+
url: string,
|
|
48440
|
+
settings: array(object({
|
|
48441
|
+
name: string,
|
|
48442
|
+
value: string
|
|
48443
|
+
})),
|
|
48444
|
+
width: union(number).or(string).parser,
|
|
48445
|
+
height: union(number).or(string).parser,
|
|
48446
|
+
allowFullScreen: boolean,
|
|
48447
|
+
allowTopNavigation: optional(boolean),
|
|
48448
|
+
static: boolean
|
|
48449
|
+
}));
|
|
48450
|
+
|
|
48271
48451
|
const parsePerseusImageBackground = object({
|
|
48272
48452
|
url: optional(nullable(string)),
|
|
48273
48453
|
width: optional(number),
|
|
@@ -48279,6 +48459,160 @@ const parsePerseusImageBackground = object({
|
|
|
48279
48459
|
scale: optional(union(number).or(string).parser)
|
|
48280
48460
|
});
|
|
48281
48461
|
|
|
48462
|
+
const pairOfNumbers$2 = pair(number, number);
|
|
48463
|
+
const parseImageWidget = parseWidget(constant("image"), object({
|
|
48464
|
+
title: optional(string),
|
|
48465
|
+
caption: optional(string),
|
|
48466
|
+
alt: optional(string),
|
|
48467
|
+
backgroundImage: parsePerseusImageBackground,
|
|
48468
|
+
static: optional(boolean),
|
|
48469
|
+
labels: optional(array(object({
|
|
48470
|
+
content: string,
|
|
48471
|
+
alignment: string,
|
|
48472
|
+
coordinates: array(number)
|
|
48473
|
+
}))),
|
|
48474
|
+
range: optional(pair(pairOfNumbers$2, pairOfNumbers$2)),
|
|
48475
|
+
box: optional(pairOfNumbers$2)
|
|
48476
|
+
}));
|
|
48477
|
+
|
|
48478
|
+
const parseInputNumberWidget = parseWidget(constant("input-number"), object({
|
|
48479
|
+
answerType: optional(enumeration("number", "decimal", "integer", "rational", "improper", "mixed", "percent", "pi")),
|
|
48480
|
+
inexact: optional(boolean),
|
|
48481
|
+
maxError: optional(union(number).or(string).parser),
|
|
48482
|
+
rightAlign: optional(boolean),
|
|
48483
|
+
simplify: enumeration("required", "optional", "enforced"),
|
|
48484
|
+
size: enumeration("normal", "small"),
|
|
48485
|
+
value: union(number).or(string).parser,
|
|
48486
|
+
customKeypad: optional(boolean)
|
|
48487
|
+
}));
|
|
48488
|
+
|
|
48489
|
+
const pairOfNumbers$1 = pair(number, number);
|
|
48490
|
+
const parseFunctionElement = object({
|
|
48491
|
+
type: constant("function"),
|
|
48492
|
+
key: string,
|
|
48493
|
+
options: object({
|
|
48494
|
+
value: string,
|
|
48495
|
+
funcName: string,
|
|
48496
|
+
rangeMin: string,
|
|
48497
|
+
rangeMax: string,
|
|
48498
|
+
color: string,
|
|
48499
|
+
strokeDasharray: string,
|
|
48500
|
+
strokeWidth: number
|
|
48501
|
+
})
|
|
48502
|
+
});
|
|
48503
|
+
const parseLabelElement = object({
|
|
48504
|
+
type: constant("label"),
|
|
48505
|
+
key: string,
|
|
48506
|
+
options: object({
|
|
48507
|
+
label: string,
|
|
48508
|
+
color: string,
|
|
48509
|
+
coordX: string,
|
|
48510
|
+
coordY: string
|
|
48511
|
+
})
|
|
48512
|
+
});
|
|
48513
|
+
const parseLineElement = object({
|
|
48514
|
+
type: constant("line"),
|
|
48515
|
+
key: string,
|
|
48516
|
+
options: object({
|
|
48517
|
+
color: string,
|
|
48518
|
+
startX: string,
|
|
48519
|
+
startY: string,
|
|
48520
|
+
endX: string,
|
|
48521
|
+
endY: string,
|
|
48522
|
+
strokeDasharray: string,
|
|
48523
|
+
strokeWidth: number,
|
|
48524
|
+
arrows: string
|
|
48525
|
+
})
|
|
48526
|
+
});
|
|
48527
|
+
const parseMovableLineElement = object({
|
|
48528
|
+
type: constant("movable-line"),
|
|
48529
|
+
key: string,
|
|
48530
|
+
options: object({
|
|
48531
|
+
startX: string,
|
|
48532
|
+
startY: string,
|
|
48533
|
+
startSubscript: number,
|
|
48534
|
+
endX: string,
|
|
48535
|
+
endY: string,
|
|
48536
|
+
endSubscript: number,
|
|
48537
|
+
constraint: string,
|
|
48538
|
+
snap: number,
|
|
48539
|
+
constraintFn: string,
|
|
48540
|
+
constraintXMin: string,
|
|
48541
|
+
constraintXMax: string,
|
|
48542
|
+
constraintYMin: string,
|
|
48543
|
+
constraintYMax: string
|
|
48544
|
+
})
|
|
48545
|
+
});
|
|
48546
|
+
const parseMovablePointElement = object({
|
|
48547
|
+
type: constant("movable-point"),
|
|
48548
|
+
key: string,
|
|
48549
|
+
options: object({
|
|
48550
|
+
startX: string,
|
|
48551
|
+
startY: string,
|
|
48552
|
+
varSubscript: number,
|
|
48553
|
+
constraint: string,
|
|
48554
|
+
snap: number,
|
|
48555
|
+
constraintFn: string,
|
|
48556
|
+
constraintXMin: string,
|
|
48557
|
+
constraintXMax: string,
|
|
48558
|
+
constraintYMin: string,
|
|
48559
|
+
constraintYMax: string
|
|
48560
|
+
})
|
|
48561
|
+
});
|
|
48562
|
+
const parseParametricElement = object({
|
|
48563
|
+
type: constant("parametric"),
|
|
48564
|
+
key: string,
|
|
48565
|
+
options: object({
|
|
48566
|
+
x: string,
|
|
48567
|
+
y: string,
|
|
48568
|
+
rangeMin: string,
|
|
48569
|
+
rangeMax: string,
|
|
48570
|
+
color: string,
|
|
48571
|
+
strokeDasharray: string,
|
|
48572
|
+
strokeWidth: number
|
|
48573
|
+
})
|
|
48574
|
+
});
|
|
48575
|
+
const parsePointElement = object({
|
|
48576
|
+
type: constant("point"),
|
|
48577
|
+
key: string,
|
|
48578
|
+
options: object({
|
|
48579
|
+
color: string,
|
|
48580
|
+
coordX: string,
|
|
48581
|
+
coordY: string
|
|
48582
|
+
})
|
|
48583
|
+
});
|
|
48584
|
+
const parseRectangleElement = object({
|
|
48585
|
+
type: constant("rectangle"),
|
|
48586
|
+
key: string,
|
|
48587
|
+
options: object({
|
|
48588
|
+
color: string,
|
|
48589
|
+
coordX: string,
|
|
48590
|
+
coordY: string,
|
|
48591
|
+
width: string,
|
|
48592
|
+
height: string
|
|
48593
|
+
})
|
|
48594
|
+
});
|
|
48595
|
+
const parseInteractionWidget = parseWidget(constant("interaction"), object({
|
|
48596
|
+
static: boolean,
|
|
48597
|
+
graph: object({
|
|
48598
|
+
editableSettings: optional(array(enumeration("canvas", "graph"))),
|
|
48599
|
+
box: pairOfNumbers$1,
|
|
48600
|
+
labels: array(string),
|
|
48601
|
+
range: pair(pairOfNumbers$1, pairOfNumbers$1),
|
|
48602
|
+
gridStep: pairOfNumbers$1,
|
|
48603
|
+
markings: enumeration("graph", "grid", "none"),
|
|
48604
|
+
snapStep: optional(pairOfNumbers$1),
|
|
48605
|
+
valid: optional(union(boolean).or(string).parser),
|
|
48606
|
+
backgroundImage: optional(parsePerseusImageBackground),
|
|
48607
|
+
showProtractor: optional(boolean),
|
|
48608
|
+
showRuler: optional(boolean),
|
|
48609
|
+
rulerLabel: optional(string),
|
|
48610
|
+
rulerTicks: optional(number),
|
|
48611
|
+
tickStep: pairOfNumbers$1
|
|
48612
|
+
}),
|
|
48613
|
+
elements: array(union(parseFunctionElement).or(parseLabelElement).or(parseLineElement).or(parseMovableLineElement).or(parseMovablePointElement).or(parseParametricElement).or(parsePointElement).or(parseRectangleElement).parser)
|
|
48614
|
+
}));
|
|
48615
|
+
|
|
48282
48616
|
// Used to represent 2-D points and ranges
|
|
48283
48617
|
const pairOfNumbers = pair(number, number);
|
|
48284
48618
|
const parsePerseusGraphTypeAngle = object({
|
|
@@ -48465,6 +48799,195 @@ const parseInteractiveGraphWidget = parseWidget(constant("interactive-graph"), o
|
|
|
48465
48799
|
fullGraphAriaDescription: optional(string)
|
|
48466
48800
|
}));
|
|
48467
48801
|
|
|
48802
|
+
const parseLabelImageWidget = parseWidget(constant("label-image"), object({
|
|
48803
|
+
choices: array(string),
|
|
48804
|
+
imageUrl: string,
|
|
48805
|
+
imageAlt: string,
|
|
48806
|
+
imageHeight: number,
|
|
48807
|
+
imageWidth: number,
|
|
48808
|
+
markers: array(object({
|
|
48809
|
+
answers: array(string),
|
|
48810
|
+
label: string,
|
|
48811
|
+
x: number,
|
|
48812
|
+
y: number
|
|
48813
|
+
})),
|
|
48814
|
+
hideChoicesFromInstructions: boolean,
|
|
48815
|
+
multipleAnswers: boolean,
|
|
48816
|
+
static: boolean
|
|
48817
|
+
}));
|
|
48818
|
+
|
|
48819
|
+
const parseMatcherWidget = parseWidget(constant("matcher"), object({
|
|
48820
|
+
labels: array(string),
|
|
48821
|
+
left: array(string),
|
|
48822
|
+
right: array(string),
|
|
48823
|
+
orderMatters: boolean,
|
|
48824
|
+
padding: boolean
|
|
48825
|
+
}));
|
|
48826
|
+
|
|
48827
|
+
const parseMatrixWidget = parseWidget(constant("matrix"), object({
|
|
48828
|
+
prefix: string,
|
|
48829
|
+
suffix: string,
|
|
48830
|
+
answers: array(array(number)),
|
|
48831
|
+
cursorPosition: array(number),
|
|
48832
|
+
matrixBoardSize: array(number),
|
|
48833
|
+
static: boolean
|
|
48834
|
+
}));
|
|
48835
|
+
|
|
48836
|
+
const parseMeasurerWidget = parseWidget(constant("measurer"), object({
|
|
48837
|
+
image: parsePerseusImageBackground,
|
|
48838
|
+
showProtractor: boolean,
|
|
48839
|
+
showRuler: boolean,
|
|
48840
|
+
rulerLabel: string,
|
|
48841
|
+
rulerTicks: number,
|
|
48842
|
+
rulerPixels: number,
|
|
48843
|
+
rulerLength: number,
|
|
48844
|
+
box: pair(number, number),
|
|
48845
|
+
static: boolean
|
|
48846
|
+
}));
|
|
48847
|
+
|
|
48848
|
+
const parseMoleculeRendererWidget = parseWidget(constant("molecule-renderer"), object({
|
|
48849
|
+
widgetId: string,
|
|
48850
|
+
rotationAngle: optional(number),
|
|
48851
|
+
smiles: optional(string)
|
|
48852
|
+
}));
|
|
48853
|
+
|
|
48854
|
+
const parseNumberLineWidget = parseWidget(constant("number-line"), object({
|
|
48855
|
+
range: array(number),
|
|
48856
|
+
labelRange: array(nullable(number)),
|
|
48857
|
+
labelStyle: string,
|
|
48858
|
+
labelTicks: boolean,
|
|
48859
|
+
isTickCtrl: optional(nullable(boolean)),
|
|
48860
|
+
divisionRange: array(number),
|
|
48861
|
+
numDivisions: optional(nullable(number)),
|
|
48862
|
+
snapDivisions: number,
|
|
48863
|
+
tickStep: optional(nullable(number)),
|
|
48864
|
+
correctRel: optional(nullable(string)),
|
|
48865
|
+
correctX: number,
|
|
48866
|
+
initialX: optional(nullable(number)),
|
|
48867
|
+
showTooltip: optional(boolean),
|
|
48868
|
+
static: boolean
|
|
48869
|
+
}));
|
|
48870
|
+
|
|
48871
|
+
const parseMathFormat = enumeration("integer", "mixed", "improper", "proper", "decimal", "percent", "pi");
|
|
48872
|
+
const parseNumericInputWidget = parseWidget(constant("numeric-input"), object({
|
|
48873
|
+
answers: array(object({
|
|
48874
|
+
message: string,
|
|
48875
|
+
value: number,
|
|
48876
|
+
status: string,
|
|
48877
|
+
answerForms: optional(array(parseMathFormat)),
|
|
48878
|
+
strict: boolean,
|
|
48879
|
+
maxError: optional(nullable(number)),
|
|
48880
|
+
simplify: optional(nullable(string))
|
|
48881
|
+
})),
|
|
48882
|
+
labelText: string,
|
|
48883
|
+
size: string,
|
|
48884
|
+
coefficient: boolean,
|
|
48885
|
+
rightAlign: optional(boolean),
|
|
48886
|
+
static: boolean,
|
|
48887
|
+
answerForms: optional(array(object({
|
|
48888
|
+
name: parseMathFormat,
|
|
48889
|
+
simplify: optional(nullable(enumeration("required", "correct", "enforced", "optional")))
|
|
48890
|
+
})))
|
|
48891
|
+
}));
|
|
48892
|
+
|
|
48893
|
+
// There is an import cycle between orderer-widget.ts and perseus-renderer.ts.
|
|
48894
|
+
// This wrapper ensures that we don't refer to parsePerseusRenderer before
|
|
48895
|
+
// it's defined.
|
|
48896
|
+
function parseRenderer(rawValue, ctx) {
|
|
48897
|
+
return parsePerseusRenderer(rawValue, ctx);
|
|
48898
|
+
}
|
|
48899
|
+
const parseOrdererWidget = parseWidget(constant("orderer"), object({
|
|
48900
|
+
options: array(parseRenderer),
|
|
48901
|
+
correctOptions: array(parseRenderer),
|
|
48902
|
+
otherOptions: array(parseRenderer),
|
|
48903
|
+
height: string,
|
|
48904
|
+
layout: string
|
|
48905
|
+
}));
|
|
48906
|
+
|
|
48907
|
+
const parsePassageRefWidget = parseWidget(constant("passage-ref"), object({
|
|
48908
|
+
passageNumber: number,
|
|
48909
|
+
referenceNumber: number,
|
|
48910
|
+
summaryText: string
|
|
48911
|
+
}));
|
|
48912
|
+
|
|
48913
|
+
const parsePassageWidget = parseWidget(constant("passage"), object({
|
|
48914
|
+
footnotes: string,
|
|
48915
|
+
passageText: string,
|
|
48916
|
+
passageTitle: string,
|
|
48917
|
+
showLineNumbers: boolean,
|
|
48918
|
+
static: boolean
|
|
48919
|
+
}));
|
|
48920
|
+
|
|
48921
|
+
const parsePhetSimulationWidget = parseWidget(constant("phet-simulation"), object({
|
|
48922
|
+
url: string,
|
|
48923
|
+
description: string
|
|
48924
|
+
}));
|
|
48925
|
+
|
|
48926
|
+
const parsePlotterWidget = parseWidget(constant("plotter"), object({
|
|
48927
|
+
labels: array(string),
|
|
48928
|
+
categories: array(string),
|
|
48929
|
+
type: enumeration(...plotterPlotTypes),
|
|
48930
|
+
maxY: number,
|
|
48931
|
+
scaleY: number,
|
|
48932
|
+
labelInterval: optional(nullable(number)),
|
|
48933
|
+
snapsPerLine: number,
|
|
48934
|
+
starting: array(number),
|
|
48935
|
+
correct: array(number),
|
|
48936
|
+
picUrl: optional(nullable(string)),
|
|
48937
|
+
picSize: optional(nullable(number)),
|
|
48938
|
+
picBoxHeight: optional(nullable(number)),
|
|
48939
|
+
plotDimensions: array(number)
|
|
48940
|
+
}));
|
|
48941
|
+
|
|
48942
|
+
const parsePythonProgramWidget = parseWidget(constant("python-program"), object({
|
|
48943
|
+
programID: string,
|
|
48944
|
+
height: number
|
|
48945
|
+
}));
|
|
48946
|
+
|
|
48947
|
+
const parseRadioWidget = parseWidget(constant("radio"), object({
|
|
48948
|
+
choices: array(object({
|
|
48949
|
+
content: string,
|
|
48950
|
+
clue: optional(string),
|
|
48951
|
+
correct: optional(boolean),
|
|
48952
|
+
isNoneOfTheAbove: optional(boolean),
|
|
48953
|
+
// deprecated
|
|
48954
|
+
// There is an import cycle between radio-widget.ts and
|
|
48955
|
+
// widgets-map.ts. The anonymous function below ensures that we
|
|
48956
|
+
// don't refer to parseWidgetsMap before it's defined.
|
|
48957
|
+
widgets: optional((rawVal, ctx) => parseWidgetsMap(rawVal, ctx))
|
|
48958
|
+
})),
|
|
48959
|
+
hasNoneOfTheAbove: optional(boolean),
|
|
48960
|
+
countChoices: optional(boolean),
|
|
48961
|
+
randomize: optional(boolean),
|
|
48962
|
+
multipleSelect: optional(boolean),
|
|
48963
|
+
deselectEnabled: optional(boolean),
|
|
48964
|
+
// deprecated
|
|
48965
|
+
onePerLine: optional(boolean),
|
|
48966
|
+
// deprecated
|
|
48967
|
+
displayCount: optional(any),
|
|
48968
|
+
// v0 props
|
|
48969
|
+
// `noneOfTheAbove` is still in use (but only set to `false`).
|
|
48970
|
+
noneOfTheAbove: constant(false)
|
|
48971
|
+
}));
|
|
48972
|
+
|
|
48973
|
+
const parseSorterWidget = parseWidget(constant("sorter"), object({
|
|
48974
|
+
correct: array(string),
|
|
48975
|
+
padding: boolean,
|
|
48976
|
+
layout: enumeration("horizontal", "vertical")
|
|
48977
|
+
}));
|
|
48978
|
+
|
|
48979
|
+
const parseTableWidget = parseWidget(constant("table"), object({
|
|
48980
|
+
headers: array(string),
|
|
48981
|
+
rows: number,
|
|
48982
|
+
columns: number,
|
|
48983
|
+
answers: array(array(string))
|
|
48984
|
+
}));
|
|
48985
|
+
|
|
48986
|
+
const parseVideoWidget = parseWidget(constant("video"), object({
|
|
48987
|
+
location: string,
|
|
48988
|
+
static: optional(boolean)
|
|
48989
|
+
}));
|
|
48990
|
+
|
|
48468
48991
|
const parseWidgetsMap = (rawValue, ctx) => {
|
|
48469
48992
|
if (!isObject(rawValue)) {
|
|
48470
48993
|
return ctx.failure("PerseusWidgetsMap", rawValue);
|
|
@@ -48509,86 +49032,67 @@ const parseWidgetsMapEntry = ([key, widget], widgetMap, ctx) => {
|
|
|
48509
49032
|
case "expression":
|
|
48510
49033
|
return parseAndAssign(`expression ${id}`, parseExpressionWidget);
|
|
48511
49034
|
case "grapher":
|
|
48512
|
-
|
|
48513
|
-
return parseAndAssign(`grapher ${id}`, any);
|
|
49035
|
+
return parseAndAssign(`grapher ${id}`, parseGrapherWidget);
|
|
48514
49036
|
case "group":
|
|
48515
|
-
|
|
48516
|
-
return parseAndAssign(`group ${id}`, any);
|
|
49037
|
+
return parseAndAssign(`group ${id}`, parseGroupWidget);
|
|
48517
49038
|
case "graded-group":
|
|
48518
|
-
|
|
48519
|
-
return parseAndAssign(`graded-group ${id}`, any);
|
|
49039
|
+
return parseAndAssign(`graded-group ${id}`, parseGradedGroupWidget);
|
|
48520
49040
|
case "graded-group-set":
|
|
48521
|
-
|
|
48522
|
-
return parseAndAssign(`graded-group-set ${id}`, any);
|
|
49041
|
+
return parseAndAssign(`graded-group-set ${id}`, parseGradedGroupSetWidget);
|
|
48523
49042
|
case "iframe":
|
|
48524
|
-
|
|
48525
|
-
return parseAndAssign(`iframe ${id}`, any);
|
|
49043
|
+
return parseAndAssign(`iframe ${id}`, parseIframeWidget);
|
|
48526
49044
|
case "image":
|
|
48527
|
-
|
|
48528
|
-
return parseAndAssign(`image ${id}`, any);
|
|
49045
|
+
return parseAndAssign(`image ${id}`, parseImageWidget);
|
|
48529
49046
|
case "input-number":
|
|
48530
|
-
|
|
48531
|
-
return parseAndAssign(`input-number ${id}`, any);
|
|
49047
|
+
return parseAndAssign(`input-number ${id}`, parseInputNumberWidget);
|
|
48532
49048
|
case "interaction":
|
|
48533
|
-
|
|
48534
|
-
return parseAndAssign(`interaction ${id}`, any);
|
|
49049
|
+
return parseAndAssign(`interaction ${id}`, parseInteractionWidget);
|
|
48535
49050
|
case "interactive-graph":
|
|
48536
49051
|
return parseAndAssign(`interactive-graph ${id}`, parseInteractiveGraphWidget);
|
|
48537
49052
|
case "label-image":
|
|
48538
|
-
|
|
48539
|
-
return parseAndAssign(`label-image ${id}`, any);
|
|
49053
|
+
return parseAndAssign(`label-image ${id}`, parseLabelImageWidget);
|
|
48540
49054
|
case "matcher":
|
|
48541
|
-
|
|
48542
|
-
return parseAndAssign(`matcher ${id}`, any);
|
|
49055
|
+
return parseAndAssign(`matcher ${id}`, parseMatcherWidget);
|
|
48543
49056
|
case "matrix":
|
|
48544
|
-
|
|
48545
|
-
return parseAndAssign(`matrix ${id}`, any);
|
|
49057
|
+
return parseAndAssign(`matrix ${id}`, parseMatrixWidget);
|
|
48546
49058
|
case "measurer":
|
|
48547
|
-
|
|
48548
|
-
return parseAndAssign(`measurer ${id}`, any);
|
|
49059
|
+
return parseAndAssign(`measurer ${id}`, parseMeasurerWidget);
|
|
48549
49060
|
case "molecule-renderer":
|
|
48550
|
-
|
|
48551
|
-
return parseAndAssign(`molecule-renderer ${id}`, any);
|
|
49061
|
+
return parseAndAssign(`molecule-renderer ${id}`, parseMoleculeRendererWidget);
|
|
48552
49062
|
case "number-line":
|
|
48553
|
-
|
|
48554
|
-
return parseAndAssign(`number-line ${id}`, any);
|
|
49063
|
+
return parseAndAssign(`number-line ${id}`, parseNumberLineWidget);
|
|
48555
49064
|
case "numeric-input":
|
|
48556
|
-
|
|
48557
|
-
return parseAndAssign(`numeric-input ${id}`, any);
|
|
49065
|
+
return parseAndAssign(`numeric-input ${id}`, parseNumericInputWidget);
|
|
48558
49066
|
case "orderer":
|
|
48559
|
-
|
|
48560
|
-
return parseAndAssign(`orderer ${id}`, any);
|
|
49067
|
+
return parseAndAssign(`orderer ${id}`, parseOrdererWidget);
|
|
48561
49068
|
case "passage":
|
|
48562
|
-
|
|
48563
|
-
return parseAndAssign(`passage ${id}`, any);
|
|
49069
|
+
return parseAndAssign(`passage ${id}`, parsePassageWidget);
|
|
48564
49070
|
case "passage-ref":
|
|
48565
|
-
|
|
48566
|
-
return parseAndAssign(`passage-ref ${id}`, any);
|
|
49071
|
+
return parseAndAssign(`passage-ref ${id}`, parsePassageRefWidget);
|
|
48567
49072
|
case "passage-ref-target":
|
|
48568
|
-
//
|
|
49073
|
+
// NOTE(benchristel): as of 2024-11-12, passage-ref-target is only
|
|
49074
|
+
// used in test content. See:
|
|
49075
|
+
// https://www.khanacademy.org/devadmin/content/search?query=widget:passage-ref-target
|
|
48569
49076
|
return parseAndAssign(`passage-ref-target ${id}`, any);
|
|
48570
49077
|
case "phet-simulation":
|
|
48571
|
-
|
|
48572
|
-
return parseAndAssign(`phet-simulation ${id}`, any);
|
|
49078
|
+
return parseAndAssign(`phet-simulation ${id}`, parsePhetSimulationWidget);
|
|
48573
49079
|
case "plotter":
|
|
48574
|
-
|
|
48575
|
-
return parseAndAssign(`plotter ${id}`, any);
|
|
49080
|
+
return parseAndAssign(`plotter ${id}`, parsePlotterWidget);
|
|
48576
49081
|
case "python-program":
|
|
48577
|
-
|
|
48578
|
-
return parseAndAssign(`python-program ${id}`, any);
|
|
49082
|
+
return parseAndAssign(`python-program ${id}`, parsePythonProgramWidget);
|
|
48579
49083
|
case "radio":
|
|
48580
|
-
|
|
48581
|
-
return parseAndAssign(`radio ${id}`, any);
|
|
49084
|
+
return parseAndAssign(`radio ${id}`, parseRadioWidget);
|
|
48582
49085
|
case "sorter":
|
|
48583
|
-
|
|
48584
|
-
return parseAndAssign(`sorter ${id}`, any);
|
|
49086
|
+
return parseAndAssign(`sorter ${id}`, parseSorterWidget);
|
|
48585
49087
|
case "table":
|
|
48586
|
-
|
|
48587
|
-
return parseAndAssign(`table ${id}`, any);
|
|
49088
|
+
return parseAndAssign(`table ${id}`, parseTableWidget);
|
|
48588
49089
|
case "video":
|
|
48589
|
-
|
|
48590
|
-
return parseAndAssign(`video ${id}`, any);
|
|
49090
|
+
return parseAndAssign(`video ${id}`, parseVideoWidget);
|
|
48591
49091
|
default:
|
|
49092
|
+
if (getWidget(type)) {
|
|
49093
|
+
// @ts-expect-error - 'type' is not a valid widget type
|
|
49094
|
+
return parseAndAssign(`${type} ${id}`, any);
|
|
49095
|
+
}
|
|
48592
49096
|
return ctx.failure("a valid widget type", type);
|
|
48593
49097
|
}
|
|
48594
49098
|
};
|
|
@@ -48611,16 +49115,6 @@ const parseHint = object({
|
|
|
48611
49115
|
}))
|
|
48612
49116
|
});
|
|
48613
49117
|
|
|
48614
|
-
const parsePerseusRenderer = object({
|
|
48615
|
-
content: string,
|
|
48616
|
-
widgets: parseWidgetsMap,
|
|
48617
|
-
metadata: optional(array(string)),
|
|
48618
|
-
images: record(string, object({
|
|
48619
|
-
width: number,
|
|
48620
|
-
height: number
|
|
48621
|
-
}))
|
|
48622
|
-
});
|
|
48623
|
-
|
|
48624
49118
|
object({
|
|
48625
49119
|
question: parsePerseusRenderer,
|
|
48626
49120
|
hints: array(parseHint),
|