@khanacademy/perseus 41.4.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 +556 -77
- 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 +556 -77
- package/dist/index.js.map +1 -1
- package/dist/server-item-renderer.d.ts +1 -1
- 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/widgets/numeric-input/numeric-input.d.ts +7 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2712,7 +2712,7 @@ const keypadConfigurationForProps = widgetOptions => {
|
|
|
2712
2712
|
times: widgetOptions.times
|
|
2713
2713
|
};
|
|
2714
2714
|
};
|
|
2715
|
-
const propUpgrades$
|
|
2715
|
+
const propUpgrades$3 = {
|
|
2716
2716
|
/* c8 ignore next */
|
|
2717
2717
|
"1": v0props => ({
|
|
2718
2718
|
times: v0props.times,
|
|
@@ -2772,7 +2772,7 @@ var Expression$1 = {
|
|
|
2772
2772
|
major: 1,
|
|
2773
2773
|
minor: 0
|
|
2774
2774
|
},
|
|
2775
|
-
propUpgrades: propUpgrades$
|
|
2775
|
+
propUpgrades: propUpgrades$3,
|
|
2776
2776
|
// For use by the editor
|
|
2777
2777
|
isLintable: true,
|
|
2778
2778
|
scorer: scoreExpression,
|
|
@@ -18924,6 +18924,9 @@ const replaceDeprecatedWidgets = () => {
|
|
|
18924
18924
|
replaceWidget("sequence", "deprecated-standin");
|
|
18925
18925
|
replaceWidget("simulator", "deprecated-standin");
|
|
18926
18926
|
replaceWidget("unit-input", "deprecated-standin");
|
|
18927
|
+
|
|
18928
|
+
// Input-Number is a special case as it is being replaced by Numeric-Input
|
|
18929
|
+
replaceWidget("input-number", "numeric-input");
|
|
18927
18930
|
};
|
|
18928
18931
|
const registerEditors = editorsToRegister => {
|
|
18929
18932
|
editorsToRegister.forEach(editor => {
|
|
@@ -18958,6 +18961,11 @@ const replaceDeprecatedEditors = () => {
|
|
|
18958
18961
|
replaceEditor("sequence", "deprecated-standin");
|
|
18959
18962
|
replaceEditor("simulator", "deprecated-standin");
|
|
18960
18963
|
replaceEditor("unit-input", "deprecated-standin");
|
|
18964
|
+
|
|
18965
|
+
// We're replacing the input-number editor with the numeric-input editor here,
|
|
18966
|
+
// but we're also modifying the JSON content to convert input-number into the
|
|
18967
|
+
// numeric-input format over in editor-page.tsx on line 92.
|
|
18968
|
+
replaceEditor("input-number", "numeric-input");
|
|
18961
18969
|
};
|
|
18962
18970
|
const getWidget = name => {
|
|
18963
18971
|
// TODO(alex): Consider referring to these as renderers to avoid
|
|
@@ -19004,10 +19012,8 @@ const getVersionVector = () => {
|
|
|
19004
19012
|
const getPublicWidgets = () => {
|
|
19005
19013
|
// TODO(alex): Update underscore.js so that _.pick can take a function.
|
|
19006
19014
|
// @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.
|
|
19007
|
-
return ___default["default"].pick(widgets,
|
|
19008
|
-
|
|
19009
|
-
___default["default"].reject(___default["default"].keys(widgets), function (name) {
|
|
19010
|
-
return widgets[name].hidden;
|
|
19015
|
+
return ___default["default"].pick(widgets, ___default["default"].reject(___default["default"].keys(widgets), function (name) {
|
|
19016
|
+
return widgets[name].hidden || name === "input-number";
|
|
19011
19017
|
}));
|
|
19012
19018
|
};
|
|
19013
19019
|
const isAccessible = widgetInfo => {
|
|
@@ -22377,7 +22383,7 @@ class NumericInput extends React__namespace.Component {
|
|
|
22377
22383
|
height: "auto"
|
|
22378
22384
|
}
|
|
22379
22385
|
});
|
|
22380
|
-
return /*#__PURE__*/React__namespace.createElement(
|
|
22386
|
+
return /*#__PURE__*/React__namespace.createElement(InputWithExamples, {
|
|
22381
22387
|
ref: ref => this.inputRef = ref,
|
|
22382
22388
|
value: this.props.currentValue,
|
|
22383
22389
|
onChange: this.handleChange,
|
|
@@ -22389,7 +22395,7 @@ class NumericInput extends React__namespace.Component {
|
|
|
22389
22395
|
id: this.props.widgetId,
|
|
22390
22396
|
disabled: this.props.apiOptions.readOnly,
|
|
22391
22397
|
style: styles.input
|
|
22392
|
-
})
|
|
22398
|
+
});
|
|
22393
22399
|
}
|
|
22394
22400
|
}
|
|
22395
22401
|
|
|
@@ -22447,13 +22453,65 @@ const propsTransform = function (widgetOptions) {
|
|
|
22447
22453
|
});
|
|
22448
22454
|
return rendererProps;
|
|
22449
22455
|
};
|
|
22456
|
+
|
|
22457
|
+
// This function is being used to replace the input-number widget
|
|
22458
|
+
// with the numeric-input widget
|
|
22459
|
+
const propUpgrades$2 = {
|
|
22460
|
+
/* c8 ignore next */
|
|
22461
|
+
"1": initialProps => {
|
|
22462
|
+
// If the initialProps has a value, it means we're upgrading from
|
|
22463
|
+
// input-number to numeric-input. In this case, we need to upgrade
|
|
22464
|
+
// the widget options accordingly.
|
|
22465
|
+
if (initialProps.value) {
|
|
22466
|
+
const provideAnswerForm = initialProps.answerType !== "number";
|
|
22467
|
+
|
|
22468
|
+
// We need to determine the mathFormat for the numeric-input widget
|
|
22469
|
+
const mathFormat = initialProps.answerType === "rational" ? "proper" // input-number uses "rational" for proper fractions
|
|
22470
|
+
: initialProps.answerType; // Otherwise, we can use the answerType directly
|
|
22471
|
+
|
|
22472
|
+
// If adjusting this logic, also adjust the logic in the convertInputNumberWidgetOptions
|
|
22473
|
+
// function in input-number.ts in the Perseus Editor package's util folder
|
|
22474
|
+
const answers = [{
|
|
22475
|
+
value: initialProps.value,
|
|
22476
|
+
simplify: initialProps.simplify,
|
|
22477
|
+
answerForms: provideAnswerForm ? [mathFormat] : undefined,
|
|
22478
|
+
strict: initialProps.inexact,
|
|
22479
|
+
// We only want to set maxError if the inexact prop is true
|
|
22480
|
+
maxError: initialProps.inexact ? initialProps.maxError : 0,
|
|
22481
|
+
status: "correct",
|
|
22482
|
+
// Input-number only allows correct answers
|
|
22483
|
+
message: ""
|
|
22484
|
+
}];
|
|
22485
|
+
return {
|
|
22486
|
+
answers,
|
|
22487
|
+
size: initialProps.size,
|
|
22488
|
+
coefficient: false,
|
|
22489
|
+
// input-number doesn't have a coefficient prop
|
|
22490
|
+
labelText: "",
|
|
22491
|
+
// input-number doesn't have a labelText prop
|
|
22492
|
+
static: false,
|
|
22493
|
+
// static is always false for numeric-input
|
|
22494
|
+
rightAlign: initialProps.rightAlign || false
|
|
22495
|
+
};
|
|
22496
|
+
} else {
|
|
22497
|
+
// Otherwise simply return the initialProps as there's no differences
|
|
22498
|
+
// between v0 and v1 for numeric-input
|
|
22499
|
+
return initialProps;
|
|
22500
|
+
}
|
|
22501
|
+
}
|
|
22502
|
+
};
|
|
22450
22503
|
var NumericInput$1 = {
|
|
22451
22504
|
name: "numeric-input",
|
|
22452
22505
|
displayName: "Numeric input",
|
|
22453
22506
|
defaultAlignment: "inline-block",
|
|
22454
22507
|
accessible: true,
|
|
22455
22508
|
widget: NumericInput,
|
|
22509
|
+
version: {
|
|
22510
|
+
major: 1,
|
|
22511
|
+
minor: 0
|
|
22512
|
+
},
|
|
22456
22513
|
transform: propsTransform,
|
|
22514
|
+
propUpgrades: propUpgrades$2,
|
|
22457
22515
|
isLintable: true,
|
|
22458
22516
|
scorer: scoreNumericInput,
|
|
22459
22517
|
getOneCorrectAnswerFromRubric(rubric) {
|
|
@@ -32259,17 +32317,12 @@ const ItemExtras = [
|
|
|
32259
32317
|
// prettier-ignore
|
|
32260
32318
|
|
|
32261
32319
|
// prettier-ignore
|
|
32262
|
-
|
|
32320
|
+
// While this widget is deprecated, we still need the type for conversion purposes
|
|
32263
32321
|
// prettier-ignore
|
|
32264
|
-
|
|
32265
32322
|
// prettier-ignore
|
|
32266
|
-
|
|
32267
32323
|
// prettier-ignore
|
|
32268
|
-
|
|
32269
32324
|
//prettier-ignore
|
|
32270
|
-
|
|
32271
32325
|
// A background image applied to various widgets.
|
|
32272
|
-
|
|
32273
32326
|
const PerseusExpressionAnswerFormConsidered = ["correct", "wrong", "ungraded"];
|
|
32274
32327
|
|
|
32275
32328
|
// 2D range: xMin, xMax, yMin, yMax
|
|
@@ -44986,7 +45039,7 @@ const init = function () {
|
|
|
44986
45039
|
|
|
44987
45040
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
44988
45041
|
const libName = "@khanacademy/perseus";
|
|
44989
|
-
const libVersion = "41.
|
|
45042
|
+
const libVersion = "41.5.0";
|
|
44990
45043
|
perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
44991
45044
|
|
|
44992
45045
|
const apiVersion = {
|
|
@@ -45679,7 +45732,7 @@ class ServerItemRenderer extends React__namespace.Component {
|
|
|
45679
45732
|
|
|
45680
45733
|
/**
|
|
45681
45734
|
* Accepts a question area widgetId, or an answer area widgetId of
|
|
45682
|
-
* the form "answer-input
|
|
45735
|
+
* the form "answer-numeric-input 1", or the string "answer-area"
|
|
45683
45736
|
* for the whole answer area (if the answer area is a single widget).
|
|
45684
45737
|
*/
|
|
45685
45738
|
_setWidgetProps(widgetId, newProps, callback) {
|
|
@@ -48663,6 +48716,118 @@ const parseExpressionWidget = parseWidget(constant("expression"), object({
|
|
|
48663
48716
|
buttonsVisible: optional(enumeration("always", "never", "focused"))
|
|
48664
48717
|
}));
|
|
48665
48718
|
|
|
48719
|
+
const parsePerseusRenderer = object({
|
|
48720
|
+
content: string,
|
|
48721
|
+
// This module has an import cycle with parseWidgetsMap, because the
|
|
48722
|
+
// `group` widget can contain another renderer.
|
|
48723
|
+
// The anonymous function below ensures that we don't try to access
|
|
48724
|
+
// parseWidgetsMap before it's defined.
|
|
48725
|
+
widgets: (rawVal, ctx) => parseWidgetsMap(rawVal, ctx),
|
|
48726
|
+
metadata: optional(array(string)),
|
|
48727
|
+
images: record(string, object({
|
|
48728
|
+
width: number,
|
|
48729
|
+
height: number
|
|
48730
|
+
}))
|
|
48731
|
+
});
|
|
48732
|
+
|
|
48733
|
+
const parseGradedGroupWidgetOptions = object({
|
|
48734
|
+
title: string,
|
|
48735
|
+
hasHint: optional(nullable(boolean)),
|
|
48736
|
+
// This module has an import cycle with parsePerseusRenderer.
|
|
48737
|
+
// The anonymous function below ensures that we don't try to access
|
|
48738
|
+
// parsePerseusRenderer before it's defined.
|
|
48739
|
+
hint: optional(nullable((rawVal, ctx) => parsePerseusRenderer(rawVal, ctx))),
|
|
48740
|
+
content: string,
|
|
48741
|
+
// This module has an import cycle with parseWidgetsMap.
|
|
48742
|
+
// The anonymous function below ensures that we don't try to access
|
|
48743
|
+
// parseWidgetsMap before it's defined.
|
|
48744
|
+
widgets: (rawVal, ctx) => parseWidgetsMap(rawVal, ctx),
|
|
48745
|
+
widgetEnabled: optional(nullable(boolean)),
|
|
48746
|
+
immutableWidgets: optional(nullable(boolean)),
|
|
48747
|
+
images: record(string, object({
|
|
48748
|
+
width: number,
|
|
48749
|
+
height: number
|
|
48750
|
+
}))
|
|
48751
|
+
});
|
|
48752
|
+
const parseGradedGroupWidget = parseWidget(constant("graded-group"), parseGradedGroupWidgetOptions);
|
|
48753
|
+
|
|
48754
|
+
const parseGradedGroupSetWidget = parseWidget(constant("graded-group-set"), object({
|
|
48755
|
+
gradedGroups: array(parseGradedGroupWidgetOptions)
|
|
48756
|
+
}));
|
|
48757
|
+
|
|
48758
|
+
const pairOfNumbers$3 = pair(number, number);
|
|
48759
|
+
const pairOfPoints = pair(pairOfNumbers$3, pairOfNumbers$3);
|
|
48760
|
+
const parseGrapherWidget = parseWidget(constant("grapher"), object({
|
|
48761
|
+
availableTypes: array(enumeration("absolute_value", "exponential", "linear", "logarithm", "quadratic", "sinusoid", "tangent")),
|
|
48762
|
+
correct: union(object({
|
|
48763
|
+
type: constant("absolute_value"),
|
|
48764
|
+
coords: pairOfPoints
|
|
48765
|
+
})).or(object({
|
|
48766
|
+
type: constant("exponential"),
|
|
48767
|
+
asymptote: pairOfPoints,
|
|
48768
|
+
coords: pairOfPoints
|
|
48769
|
+
})).or(object({
|
|
48770
|
+
type: constant("linear"),
|
|
48771
|
+
coords: pairOfPoints
|
|
48772
|
+
})).or(object({
|
|
48773
|
+
type: constant("logarithm"),
|
|
48774
|
+
asymptote: pairOfPoints,
|
|
48775
|
+
coords: pairOfPoints
|
|
48776
|
+
})).or(object({
|
|
48777
|
+
type: constant("quadratic"),
|
|
48778
|
+
coords: pairOfPoints
|
|
48779
|
+
})).or(object({
|
|
48780
|
+
type: constant("sinusoid"),
|
|
48781
|
+
coords: pairOfPoints
|
|
48782
|
+
})).or(object({
|
|
48783
|
+
type: constant("tangent"),
|
|
48784
|
+
coords: pairOfPoints
|
|
48785
|
+
})).parser,
|
|
48786
|
+
graph: object({
|
|
48787
|
+
backgroundImage: object({
|
|
48788
|
+
bottom: optional(number),
|
|
48789
|
+
height: optional(number),
|
|
48790
|
+
left: optional(number),
|
|
48791
|
+
scale: optional(number),
|
|
48792
|
+
url: optional(nullable(string)),
|
|
48793
|
+
width: optional(number)
|
|
48794
|
+
}),
|
|
48795
|
+
box: optional(pairOfNumbers$3),
|
|
48796
|
+
editableSettings: optional(array(enumeration("graph", "snap", "image", "measure"))),
|
|
48797
|
+
gridStep: optional(pairOfNumbers$3),
|
|
48798
|
+
labels: pair(string, string),
|
|
48799
|
+
markings: enumeration("graph", "none", "grid"),
|
|
48800
|
+
range: pair(pairOfNumbers$3, pairOfNumbers$3),
|
|
48801
|
+
rulerLabel: constant(""),
|
|
48802
|
+
rulerTicks: number,
|
|
48803
|
+
showProtractor: optional(boolean),
|
|
48804
|
+
showRuler: optional(boolean),
|
|
48805
|
+
showTooltips: optional(boolean),
|
|
48806
|
+
snapStep: optional(pairOfNumbers$3),
|
|
48807
|
+
step: pairOfNumbers$3,
|
|
48808
|
+
valid: optional(union(boolean).or(string).parser)
|
|
48809
|
+
})
|
|
48810
|
+
}));
|
|
48811
|
+
|
|
48812
|
+
const parseGroupWidget = parseWidget(constant("group"),
|
|
48813
|
+
// This module has an import cycle with parsePerseusRenderer.
|
|
48814
|
+
// The anonymous function below ensures that we don't try to access
|
|
48815
|
+
// parsePerseusRenderer before it's defined.
|
|
48816
|
+
(rawVal, ctx) => parsePerseusRenderer(rawVal, ctx));
|
|
48817
|
+
|
|
48818
|
+
const parseIframeWidget = parseWidget(constant("iframe"), object({
|
|
48819
|
+
url: string,
|
|
48820
|
+
settings: array(object({
|
|
48821
|
+
name: string,
|
|
48822
|
+
value: string
|
|
48823
|
+
})),
|
|
48824
|
+
width: union(number).or(string).parser,
|
|
48825
|
+
height: union(number).or(string).parser,
|
|
48826
|
+
allowFullScreen: boolean,
|
|
48827
|
+
allowTopNavigation: optional(boolean),
|
|
48828
|
+
static: boolean
|
|
48829
|
+
}));
|
|
48830
|
+
|
|
48666
48831
|
const parsePerseusImageBackground = object({
|
|
48667
48832
|
url: optional(nullable(string)),
|
|
48668
48833
|
width: optional(number),
|
|
@@ -48674,6 +48839,160 @@ const parsePerseusImageBackground = object({
|
|
|
48674
48839
|
scale: optional(union(number).or(string).parser)
|
|
48675
48840
|
});
|
|
48676
48841
|
|
|
48842
|
+
const pairOfNumbers$2 = pair(number, number);
|
|
48843
|
+
const parseImageWidget = parseWidget(constant("image"), object({
|
|
48844
|
+
title: optional(string),
|
|
48845
|
+
caption: optional(string),
|
|
48846
|
+
alt: optional(string),
|
|
48847
|
+
backgroundImage: parsePerseusImageBackground,
|
|
48848
|
+
static: optional(boolean),
|
|
48849
|
+
labels: optional(array(object({
|
|
48850
|
+
content: string,
|
|
48851
|
+
alignment: string,
|
|
48852
|
+
coordinates: array(number)
|
|
48853
|
+
}))),
|
|
48854
|
+
range: optional(pair(pairOfNumbers$2, pairOfNumbers$2)),
|
|
48855
|
+
box: optional(pairOfNumbers$2)
|
|
48856
|
+
}));
|
|
48857
|
+
|
|
48858
|
+
const parseInputNumberWidget = parseWidget(constant("input-number"), object({
|
|
48859
|
+
answerType: optional(enumeration("number", "decimal", "integer", "rational", "improper", "mixed", "percent", "pi")),
|
|
48860
|
+
inexact: optional(boolean),
|
|
48861
|
+
maxError: optional(union(number).or(string).parser),
|
|
48862
|
+
rightAlign: optional(boolean),
|
|
48863
|
+
simplify: enumeration("required", "optional", "enforced"),
|
|
48864
|
+
size: enumeration("normal", "small"),
|
|
48865
|
+
value: union(number).or(string).parser,
|
|
48866
|
+
customKeypad: optional(boolean)
|
|
48867
|
+
}));
|
|
48868
|
+
|
|
48869
|
+
const pairOfNumbers$1 = pair(number, number);
|
|
48870
|
+
const parseFunctionElement = object({
|
|
48871
|
+
type: constant("function"),
|
|
48872
|
+
key: string,
|
|
48873
|
+
options: object({
|
|
48874
|
+
value: string,
|
|
48875
|
+
funcName: string,
|
|
48876
|
+
rangeMin: string,
|
|
48877
|
+
rangeMax: string,
|
|
48878
|
+
color: string,
|
|
48879
|
+
strokeDasharray: string,
|
|
48880
|
+
strokeWidth: number
|
|
48881
|
+
})
|
|
48882
|
+
});
|
|
48883
|
+
const parseLabelElement = object({
|
|
48884
|
+
type: constant("label"),
|
|
48885
|
+
key: string,
|
|
48886
|
+
options: object({
|
|
48887
|
+
label: string,
|
|
48888
|
+
color: string,
|
|
48889
|
+
coordX: string,
|
|
48890
|
+
coordY: string
|
|
48891
|
+
})
|
|
48892
|
+
});
|
|
48893
|
+
const parseLineElement = object({
|
|
48894
|
+
type: constant("line"),
|
|
48895
|
+
key: string,
|
|
48896
|
+
options: object({
|
|
48897
|
+
color: string,
|
|
48898
|
+
startX: string,
|
|
48899
|
+
startY: string,
|
|
48900
|
+
endX: string,
|
|
48901
|
+
endY: string,
|
|
48902
|
+
strokeDasharray: string,
|
|
48903
|
+
strokeWidth: number,
|
|
48904
|
+
arrows: string
|
|
48905
|
+
})
|
|
48906
|
+
});
|
|
48907
|
+
const parseMovableLineElement = object({
|
|
48908
|
+
type: constant("movable-line"),
|
|
48909
|
+
key: string,
|
|
48910
|
+
options: object({
|
|
48911
|
+
startX: string,
|
|
48912
|
+
startY: string,
|
|
48913
|
+
startSubscript: number,
|
|
48914
|
+
endX: string,
|
|
48915
|
+
endY: string,
|
|
48916
|
+
endSubscript: number,
|
|
48917
|
+
constraint: string,
|
|
48918
|
+
snap: number,
|
|
48919
|
+
constraintFn: string,
|
|
48920
|
+
constraintXMin: string,
|
|
48921
|
+
constraintXMax: string,
|
|
48922
|
+
constraintYMin: string,
|
|
48923
|
+
constraintYMax: string
|
|
48924
|
+
})
|
|
48925
|
+
});
|
|
48926
|
+
const parseMovablePointElement = object({
|
|
48927
|
+
type: constant("movable-point"),
|
|
48928
|
+
key: string,
|
|
48929
|
+
options: object({
|
|
48930
|
+
startX: string,
|
|
48931
|
+
startY: string,
|
|
48932
|
+
varSubscript: number,
|
|
48933
|
+
constraint: string,
|
|
48934
|
+
snap: number,
|
|
48935
|
+
constraintFn: string,
|
|
48936
|
+
constraintXMin: string,
|
|
48937
|
+
constraintXMax: string,
|
|
48938
|
+
constraintYMin: string,
|
|
48939
|
+
constraintYMax: string
|
|
48940
|
+
})
|
|
48941
|
+
});
|
|
48942
|
+
const parseParametricElement = object({
|
|
48943
|
+
type: constant("parametric"),
|
|
48944
|
+
key: string,
|
|
48945
|
+
options: object({
|
|
48946
|
+
x: string,
|
|
48947
|
+
y: string,
|
|
48948
|
+
rangeMin: string,
|
|
48949
|
+
rangeMax: string,
|
|
48950
|
+
color: string,
|
|
48951
|
+
strokeDasharray: string,
|
|
48952
|
+
strokeWidth: number
|
|
48953
|
+
})
|
|
48954
|
+
});
|
|
48955
|
+
const parsePointElement = object({
|
|
48956
|
+
type: constant("point"),
|
|
48957
|
+
key: string,
|
|
48958
|
+
options: object({
|
|
48959
|
+
color: string,
|
|
48960
|
+
coordX: string,
|
|
48961
|
+
coordY: string
|
|
48962
|
+
})
|
|
48963
|
+
});
|
|
48964
|
+
const parseRectangleElement = object({
|
|
48965
|
+
type: constant("rectangle"),
|
|
48966
|
+
key: string,
|
|
48967
|
+
options: object({
|
|
48968
|
+
color: string,
|
|
48969
|
+
coordX: string,
|
|
48970
|
+
coordY: string,
|
|
48971
|
+
width: string,
|
|
48972
|
+
height: string
|
|
48973
|
+
})
|
|
48974
|
+
});
|
|
48975
|
+
const parseInteractionWidget = parseWidget(constant("interaction"), object({
|
|
48976
|
+
static: boolean,
|
|
48977
|
+
graph: object({
|
|
48978
|
+
editableSettings: optional(array(enumeration("canvas", "graph"))),
|
|
48979
|
+
box: pairOfNumbers$1,
|
|
48980
|
+
labels: array(string),
|
|
48981
|
+
range: pair(pairOfNumbers$1, pairOfNumbers$1),
|
|
48982
|
+
gridStep: pairOfNumbers$1,
|
|
48983
|
+
markings: enumeration("graph", "grid", "none"),
|
|
48984
|
+
snapStep: optional(pairOfNumbers$1),
|
|
48985
|
+
valid: optional(union(boolean).or(string).parser),
|
|
48986
|
+
backgroundImage: optional(parsePerseusImageBackground),
|
|
48987
|
+
showProtractor: optional(boolean),
|
|
48988
|
+
showRuler: optional(boolean),
|
|
48989
|
+
rulerLabel: optional(string),
|
|
48990
|
+
rulerTicks: optional(number),
|
|
48991
|
+
tickStep: pairOfNumbers$1
|
|
48992
|
+
}),
|
|
48993
|
+
elements: array(union(parseFunctionElement).or(parseLabelElement).or(parseLineElement).or(parseMovableLineElement).or(parseMovablePointElement).or(parseParametricElement).or(parsePointElement).or(parseRectangleElement).parser)
|
|
48994
|
+
}));
|
|
48995
|
+
|
|
48677
48996
|
// Used to represent 2-D points and ranges
|
|
48678
48997
|
const pairOfNumbers = pair(number, number);
|
|
48679
48998
|
const parsePerseusGraphTypeAngle = object({
|
|
@@ -48860,6 +49179,195 @@ const parseInteractiveGraphWidget = parseWidget(constant("interactive-graph"), o
|
|
|
48860
49179
|
fullGraphAriaDescription: optional(string)
|
|
48861
49180
|
}));
|
|
48862
49181
|
|
|
49182
|
+
const parseLabelImageWidget = parseWidget(constant("label-image"), object({
|
|
49183
|
+
choices: array(string),
|
|
49184
|
+
imageUrl: string,
|
|
49185
|
+
imageAlt: string,
|
|
49186
|
+
imageHeight: number,
|
|
49187
|
+
imageWidth: number,
|
|
49188
|
+
markers: array(object({
|
|
49189
|
+
answers: array(string),
|
|
49190
|
+
label: string,
|
|
49191
|
+
x: number,
|
|
49192
|
+
y: number
|
|
49193
|
+
})),
|
|
49194
|
+
hideChoicesFromInstructions: boolean,
|
|
49195
|
+
multipleAnswers: boolean,
|
|
49196
|
+
static: boolean
|
|
49197
|
+
}));
|
|
49198
|
+
|
|
49199
|
+
const parseMatcherWidget = parseWidget(constant("matcher"), object({
|
|
49200
|
+
labels: array(string),
|
|
49201
|
+
left: array(string),
|
|
49202
|
+
right: array(string),
|
|
49203
|
+
orderMatters: boolean,
|
|
49204
|
+
padding: boolean
|
|
49205
|
+
}));
|
|
49206
|
+
|
|
49207
|
+
const parseMatrixWidget = parseWidget(constant("matrix"), object({
|
|
49208
|
+
prefix: string,
|
|
49209
|
+
suffix: string,
|
|
49210
|
+
answers: array(array(number)),
|
|
49211
|
+
cursorPosition: array(number),
|
|
49212
|
+
matrixBoardSize: array(number),
|
|
49213
|
+
static: boolean
|
|
49214
|
+
}));
|
|
49215
|
+
|
|
49216
|
+
const parseMeasurerWidget = parseWidget(constant("measurer"), object({
|
|
49217
|
+
image: parsePerseusImageBackground,
|
|
49218
|
+
showProtractor: boolean,
|
|
49219
|
+
showRuler: boolean,
|
|
49220
|
+
rulerLabel: string,
|
|
49221
|
+
rulerTicks: number,
|
|
49222
|
+
rulerPixels: number,
|
|
49223
|
+
rulerLength: number,
|
|
49224
|
+
box: pair(number, number),
|
|
49225
|
+
static: boolean
|
|
49226
|
+
}));
|
|
49227
|
+
|
|
49228
|
+
const parseMoleculeRendererWidget = parseWidget(constant("molecule-renderer"), object({
|
|
49229
|
+
widgetId: string,
|
|
49230
|
+
rotationAngle: optional(number),
|
|
49231
|
+
smiles: optional(string)
|
|
49232
|
+
}));
|
|
49233
|
+
|
|
49234
|
+
const parseNumberLineWidget = parseWidget(constant("number-line"), object({
|
|
49235
|
+
range: array(number),
|
|
49236
|
+
labelRange: array(nullable(number)),
|
|
49237
|
+
labelStyle: string,
|
|
49238
|
+
labelTicks: boolean,
|
|
49239
|
+
isTickCtrl: optional(nullable(boolean)),
|
|
49240
|
+
divisionRange: array(number),
|
|
49241
|
+
numDivisions: optional(nullable(number)),
|
|
49242
|
+
snapDivisions: number,
|
|
49243
|
+
tickStep: optional(nullable(number)),
|
|
49244
|
+
correctRel: optional(nullable(string)),
|
|
49245
|
+
correctX: number,
|
|
49246
|
+
initialX: optional(nullable(number)),
|
|
49247
|
+
showTooltip: optional(boolean),
|
|
49248
|
+
static: boolean
|
|
49249
|
+
}));
|
|
49250
|
+
|
|
49251
|
+
const parseMathFormat = enumeration("integer", "mixed", "improper", "proper", "decimal", "percent", "pi");
|
|
49252
|
+
const parseNumericInputWidget = parseWidget(constant("numeric-input"), object({
|
|
49253
|
+
answers: array(object({
|
|
49254
|
+
message: string,
|
|
49255
|
+
value: number,
|
|
49256
|
+
status: string,
|
|
49257
|
+
answerForms: optional(array(parseMathFormat)),
|
|
49258
|
+
strict: boolean,
|
|
49259
|
+
maxError: optional(nullable(number)),
|
|
49260
|
+
simplify: optional(nullable(string))
|
|
49261
|
+
})),
|
|
49262
|
+
labelText: string,
|
|
49263
|
+
size: string,
|
|
49264
|
+
coefficient: boolean,
|
|
49265
|
+
rightAlign: optional(boolean),
|
|
49266
|
+
static: boolean,
|
|
49267
|
+
answerForms: optional(array(object({
|
|
49268
|
+
name: parseMathFormat,
|
|
49269
|
+
simplify: optional(nullable(enumeration("required", "correct", "enforced", "optional")))
|
|
49270
|
+
})))
|
|
49271
|
+
}));
|
|
49272
|
+
|
|
49273
|
+
// There is an import cycle between orderer-widget.ts and perseus-renderer.ts.
|
|
49274
|
+
// This wrapper ensures that we don't refer to parsePerseusRenderer before
|
|
49275
|
+
// it's defined.
|
|
49276
|
+
function parseRenderer(rawValue, ctx) {
|
|
49277
|
+
return parsePerseusRenderer(rawValue, ctx);
|
|
49278
|
+
}
|
|
49279
|
+
const parseOrdererWidget = parseWidget(constant("orderer"), object({
|
|
49280
|
+
options: array(parseRenderer),
|
|
49281
|
+
correctOptions: array(parseRenderer),
|
|
49282
|
+
otherOptions: array(parseRenderer),
|
|
49283
|
+
height: string,
|
|
49284
|
+
layout: string
|
|
49285
|
+
}));
|
|
49286
|
+
|
|
49287
|
+
const parsePassageRefWidget = parseWidget(constant("passage-ref"), object({
|
|
49288
|
+
passageNumber: number,
|
|
49289
|
+
referenceNumber: number,
|
|
49290
|
+
summaryText: string
|
|
49291
|
+
}));
|
|
49292
|
+
|
|
49293
|
+
const parsePassageWidget = parseWidget(constant("passage"), object({
|
|
49294
|
+
footnotes: string,
|
|
49295
|
+
passageText: string,
|
|
49296
|
+
passageTitle: string,
|
|
49297
|
+
showLineNumbers: boolean,
|
|
49298
|
+
static: boolean
|
|
49299
|
+
}));
|
|
49300
|
+
|
|
49301
|
+
const parsePhetSimulationWidget = parseWidget(constant("phet-simulation"), object({
|
|
49302
|
+
url: string,
|
|
49303
|
+
description: string
|
|
49304
|
+
}));
|
|
49305
|
+
|
|
49306
|
+
const parsePlotterWidget = parseWidget(constant("plotter"), object({
|
|
49307
|
+
labels: array(string),
|
|
49308
|
+
categories: array(string),
|
|
49309
|
+
type: enumeration(...plotterPlotTypes),
|
|
49310
|
+
maxY: number,
|
|
49311
|
+
scaleY: number,
|
|
49312
|
+
labelInterval: optional(nullable(number)),
|
|
49313
|
+
snapsPerLine: number,
|
|
49314
|
+
starting: array(number),
|
|
49315
|
+
correct: array(number),
|
|
49316
|
+
picUrl: optional(nullable(string)),
|
|
49317
|
+
picSize: optional(nullable(number)),
|
|
49318
|
+
picBoxHeight: optional(nullable(number)),
|
|
49319
|
+
plotDimensions: array(number)
|
|
49320
|
+
}));
|
|
49321
|
+
|
|
49322
|
+
const parsePythonProgramWidget = parseWidget(constant("python-program"), object({
|
|
49323
|
+
programID: string,
|
|
49324
|
+
height: number
|
|
49325
|
+
}));
|
|
49326
|
+
|
|
49327
|
+
const parseRadioWidget = parseWidget(constant("radio"), object({
|
|
49328
|
+
choices: array(object({
|
|
49329
|
+
content: string,
|
|
49330
|
+
clue: optional(string),
|
|
49331
|
+
correct: optional(boolean),
|
|
49332
|
+
isNoneOfTheAbove: optional(boolean),
|
|
49333
|
+
// deprecated
|
|
49334
|
+
// There is an import cycle between radio-widget.ts and
|
|
49335
|
+
// widgets-map.ts. The anonymous function below ensures that we
|
|
49336
|
+
// don't refer to parseWidgetsMap before it's defined.
|
|
49337
|
+
widgets: optional((rawVal, ctx) => parseWidgetsMap(rawVal, ctx))
|
|
49338
|
+
})),
|
|
49339
|
+
hasNoneOfTheAbove: optional(boolean),
|
|
49340
|
+
countChoices: optional(boolean),
|
|
49341
|
+
randomize: optional(boolean),
|
|
49342
|
+
multipleSelect: optional(boolean),
|
|
49343
|
+
deselectEnabled: optional(boolean),
|
|
49344
|
+
// deprecated
|
|
49345
|
+
onePerLine: optional(boolean),
|
|
49346
|
+
// deprecated
|
|
49347
|
+
displayCount: optional(any),
|
|
49348
|
+
// v0 props
|
|
49349
|
+
// `noneOfTheAbove` is still in use (but only set to `false`).
|
|
49350
|
+
noneOfTheAbove: constant(false)
|
|
49351
|
+
}));
|
|
49352
|
+
|
|
49353
|
+
const parseSorterWidget = parseWidget(constant("sorter"), object({
|
|
49354
|
+
correct: array(string),
|
|
49355
|
+
padding: boolean,
|
|
49356
|
+
layout: enumeration("horizontal", "vertical")
|
|
49357
|
+
}));
|
|
49358
|
+
|
|
49359
|
+
const parseTableWidget = parseWidget(constant("table"), object({
|
|
49360
|
+
headers: array(string),
|
|
49361
|
+
rows: number,
|
|
49362
|
+
columns: number,
|
|
49363
|
+
answers: array(array(string))
|
|
49364
|
+
}));
|
|
49365
|
+
|
|
49366
|
+
const parseVideoWidget = parseWidget(constant("video"), object({
|
|
49367
|
+
location: string,
|
|
49368
|
+
static: optional(boolean)
|
|
49369
|
+
}));
|
|
49370
|
+
|
|
48863
49371
|
const parseWidgetsMap = (rawValue, ctx) => {
|
|
48864
49372
|
if (!isObject(rawValue)) {
|
|
48865
49373
|
return ctx.failure("PerseusWidgetsMap", rawValue);
|
|
@@ -48905,86 +49413,67 @@ const parseWidgetsMapEntry = (_ref, widgetMap, ctx) => {
|
|
|
48905
49413
|
case "expression":
|
|
48906
49414
|
return parseAndAssign(`expression ${id}`, parseExpressionWidget);
|
|
48907
49415
|
case "grapher":
|
|
48908
|
-
|
|
48909
|
-
return parseAndAssign(`grapher ${id}`, any);
|
|
49416
|
+
return parseAndAssign(`grapher ${id}`, parseGrapherWidget);
|
|
48910
49417
|
case "group":
|
|
48911
|
-
|
|
48912
|
-
return parseAndAssign(`group ${id}`, any);
|
|
49418
|
+
return parseAndAssign(`group ${id}`, parseGroupWidget);
|
|
48913
49419
|
case "graded-group":
|
|
48914
|
-
|
|
48915
|
-
return parseAndAssign(`graded-group ${id}`, any);
|
|
49420
|
+
return parseAndAssign(`graded-group ${id}`, parseGradedGroupWidget);
|
|
48916
49421
|
case "graded-group-set":
|
|
48917
|
-
|
|
48918
|
-
return parseAndAssign(`graded-group-set ${id}`, any);
|
|
49422
|
+
return parseAndAssign(`graded-group-set ${id}`, parseGradedGroupSetWidget);
|
|
48919
49423
|
case "iframe":
|
|
48920
|
-
|
|
48921
|
-
return parseAndAssign(`iframe ${id}`, any);
|
|
49424
|
+
return parseAndAssign(`iframe ${id}`, parseIframeWidget);
|
|
48922
49425
|
case "image":
|
|
48923
|
-
|
|
48924
|
-
return parseAndAssign(`image ${id}`, any);
|
|
49426
|
+
return parseAndAssign(`image ${id}`, parseImageWidget);
|
|
48925
49427
|
case "input-number":
|
|
48926
|
-
|
|
48927
|
-
return parseAndAssign(`input-number ${id}`, any);
|
|
49428
|
+
return parseAndAssign(`input-number ${id}`, parseInputNumberWidget);
|
|
48928
49429
|
case "interaction":
|
|
48929
|
-
|
|
48930
|
-
return parseAndAssign(`interaction ${id}`, any);
|
|
49430
|
+
return parseAndAssign(`interaction ${id}`, parseInteractionWidget);
|
|
48931
49431
|
case "interactive-graph":
|
|
48932
49432
|
return parseAndAssign(`interactive-graph ${id}`, parseInteractiveGraphWidget);
|
|
48933
49433
|
case "label-image":
|
|
48934
|
-
|
|
48935
|
-
return parseAndAssign(`label-image ${id}`, any);
|
|
49434
|
+
return parseAndAssign(`label-image ${id}`, parseLabelImageWidget);
|
|
48936
49435
|
case "matcher":
|
|
48937
|
-
|
|
48938
|
-
return parseAndAssign(`matcher ${id}`, any);
|
|
49436
|
+
return parseAndAssign(`matcher ${id}`, parseMatcherWidget);
|
|
48939
49437
|
case "matrix":
|
|
48940
|
-
|
|
48941
|
-
return parseAndAssign(`matrix ${id}`, any);
|
|
49438
|
+
return parseAndAssign(`matrix ${id}`, parseMatrixWidget);
|
|
48942
49439
|
case "measurer":
|
|
48943
|
-
|
|
48944
|
-
return parseAndAssign(`measurer ${id}`, any);
|
|
49440
|
+
return parseAndAssign(`measurer ${id}`, parseMeasurerWidget);
|
|
48945
49441
|
case "molecule-renderer":
|
|
48946
|
-
|
|
48947
|
-
return parseAndAssign(`molecule-renderer ${id}`, any);
|
|
49442
|
+
return parseAndAssign(`molecule-renderer ${id}`, parseMoleculeRendererWidget);
|
|
48948
49443
|
case "number-line":
|
|
48949
|
-
|
|
48950
|
-
return parseAndAssign(`number-line ${id}`, any);
|
|
49444
|
+
return parseAndAssign(`number-line ${id}`, parseNumberLineWidget);
|
|
48951
49445
|
case "numeric-input":
|
|
48952
|
-
|
|
48953
|
-
return parseAndAssign(`numeric-input ${id}`, any);
|
|
49446
|
+
return parseAndAssign(`numeric-input ${id}`, parseNumericInputWidget);
|
|
48954
49447
|
case "orderer":
|
|
48955
|
-
|
|
48956
|
-
return parseAndAssign(`orderer ${id}`, any);
|
|
49448
|
+
return parseAndAssign(`orderer ${id}`, parseOrdererWidget);
|
|
48957
49449
|
case "passage":
|
|
48958
|
-
|
|
48959
|
-
return parseAndAssign(`passage ${id}`, any);
|
|
49450
|
+
return parseAndAssign(`passage ${id}`, parsePassageWidget);
|
|
48960
49451
|
case "passage-ref":
|
|
48961
|
-
|
|
48962
|
-
return parseAndAssign(`passage-ref ${id}`, any);
|
|
49452
|
+
return parseAndAssign(`passage-ref ${id}`, parsePassageRefWidget);
|
|
48963
49453
|
case "passage-ref-target":
|
|
48964
|
-
//
|
|
49454
|
+
// NOTE(benchristel): as of 2024-11-12, passage-ref-target is only
|
|
49455
|
+
// used in test content. See:
|
|
49456
|
+
// https://www.khanacademy.org/devadmin/content/search?query=widget:passage-ref-target
|
|
48965
49457
|
return parseAndAssign(`passage-ref-target ${id}`, any);
|
|
48966
49458
|
case "phet-simulation":
|
|
48967
|
-
|
|
48968
|
-
return parseAndAssign(`phet-simulation ${id}`, any);
|
|
49459
|
+
return parseAndAssign(`phet-simulation ${id}`, parsePhetSimulationWidget);
|
|
48969
49460
|
case "plotter":
|
|
48970
|
-
|
|
48971
|
-
return parseAndAssign(`plotter ${id}`, any);
|
|
49461
|
+
return parseAndAssign(`plotter ${id}`, parsePlotterWidget);
|
|
48972
49462
|
case "python-program":
|
|
48973
|
-
|
|
48974
|
-
return parseAndAssign(`python-program ${id}`, any);
|
|
49463
|
+
return parseAndAssign(`python-program ${id}`, parsePythonProgramWidget);
|
|
48975
49464
|
case "radio":
|
|
48976
|
-
|
|
48977
|
-
return parseAndAssign(`radio ${id}`, any);
|
|
49465
|
+
return parseAndAssign(`radio ${id}`, parseRadioWidget);
|
|
48978
49466
|
case "sorter":
|
|
48979
|
-
|
|
48980
|
-
return parseAndAssign(`sorter ${id}`, any);
|
|
49467
|
+
return parseAndAssign(`sorter ${id}`, parseSorterWidget);
|
|
48981
49468
|
case "table":
|
|
48982
|
-
|
|
48983
|
-
return parseAndAssign(`table ${id}`, any);
|
|
49469
|
+
return parseAndAssign(`table ${id}`, parseTableWidget);
|
|
48984
49470
|
case "video":
|
|
48985
|
-
|
|
48986
|
-
return parseAndAssign(`video ${id}`, any);
|
|
49471
|
+
return parseAndAssign(`video ${id}`, parseVideoWidget);
|
|
48987
49472
|
default:
|
|
49473
|
+
if (getWidget(type)) {
|
|
49474
|
+
// @ts-expect-error - 'type' is not a valid widget type
|
|
49475
|
+
return parseAndAssign(`${type} ${id}`, any);
|
|
49476
|
+
}
|
|
48988
49477
|
return ctx.failure("a valid widget type", type);
|
|
48989
49478
|
}
|
|
48990
49479
|
};
|
|
@@ -49007,16 +49496,6 @@ const parseHint = object({
|
|
|
49007
49496
|
}))
|
|
49008
49497
|
});
|
|
49009
49498
|
|
|
49010
|
-
const parsePerseusRenderer = object({
|
|
49011
|
-
content: string,
|
|
49012
|
-
widgets: parseWidgetsMap,
|
|
49013
|
-
metadata: optional(array(string)),
|
|
49014
|
-
images: record(string, object({
|
|
49015
|
-
width: number,
|
|
49016
|
-
height: number
|
|
49017
|
-
}))
|
|
49018
|
-
});
|
|
49019
|
-
|
|
49020
49499
|
object({
|
|
49021
49500
|
question: parsePerseusRenderer,
|
|
49022
49501
|
hints: array(parseHint),
|