@khanacademy/perseus 49.1.6 → 49.2.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/components/math-input.d.ts +2 -1
- package/dist/es/index.css +5 -0
- package/dist/es/index.js +231 -59
- package/dist/es/index.js.map +1 -1
- package/dist/es/strings.js +16 -12
- package/dist/es/strings.js.map +1 -1
- package/dist/index.css +5 -0
- package/dist/index.js +232 -59
- package/dist/index.js.map +1 -1
- package/dist/perseus-types.d.ts +4 -3
- package/dist/strings.d.ts +6 -5
- package/dist/strings.js +16 -12
- package/dist/strings.js.map +1 -1
- package/dist/util/parse-perseus-json/general-purpose-parsers/convert.d.ts +2 -0
- package/dist/util/parse-perseus-json/general-purpose-parsers/discriminated-union.d.ts +8 -0
- package/dist/util/parse-perseus-json/perseus-parsers/versioned-widget-options.d.ts +45 -0
- package/dist/widgets/expression/expression.d.ts +1 -1
- package/dist/widgets/passage-ref/passage-ref.d.ts +7 -3
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -487,12 +487,12 @@ const mockStrings = {
|
|
|
487
487
|
angleMeasure,
|
|
488
488
|
vertexX,
|
|
489
489
|
vertexY,
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
490
|
+
startingSideX,
|
|
491
|
+
startingSideY,
|
|
492
|
+
endingSideX,
|
|
493
|
+
endingSideY
|
|
494
494
|
} = _ref40;
|
|
495
|
-
return `The angle measure is ${angleMeasure} degrees with a vertex at ${vertexX} comma ${vertexY}, a point on the
|
|
495
|
+
return `The angle measure is ${angleMeasure} degrees with a vertex at ${vertexX} comma ${vertexY}, a point on the starting side at ${startingSideX} comma ${startingSideY} and a point on the ending side at ${endingSideX} comma ${endingSideY}.`;
|
|
496
496
|
}
|
|
497
497
|
// The above strings are used for interactive graph SR descriptions.
|
|
498
498
|
};
|
|
@@ -897,6 +897,9 @@ const mapButtonSets = buttonSets => {
|
|
|
897
897
|
case "trig":
|
|
898
898
|
keypadButtonSets.trigonometry = true;
|
|
899
899
|
break;
|
|
900
|
+
case "scientific":
|
|
901
|
+
keypadButtonSets.scientific = true;
|
|
902
|
+
break;
|
|
900
903
|
}
|
|
901
904
|
});
|
|
902
905
|
return keypadButtonSets;
|
|
@@ -3971,7 +3974,9 @@ ZoomServiceClass.prototype._scrollHandler = function (e) {
|
|
|
3971
3974
|
}
|
|
3972
3975
|
};
|
|
3973
3976
|
ZoomServiceClass.prototype._keyHandler = function (e) {
|
|
3974
|
-
|
|
3977
|
+
// 27: Esc, 13: Enter, 32: Space
|
|
3978
|
+
const keyCodes = [27, 13, 32];
|
|
3979
|
+
if (keyCodes.includes(e.keyCode)) {
|
|
3975
3980
|
this._activeZoomClose();
|
|
3976
3981
|
}
|
|
3977
3982
|
};
|
|
@@ -4060,6 +4065,7 @@ Zoom.prototype.zoomImage = function () {
|
|
|
4060
4065
|
}.bind(this);
|
|
4061
4066
|
img.src = this._targetImage.src;
|
|
4062
4067
|
img.alt = this._targetImage.alt;
|
|
4068
|
+
img.tabIndex = 0;
|
|
4063
4069
|
this.$zoomedImage = $zoomedImage;
|
|
4064
4070
|
};
|
|
4065
4071
|
Zoom.prototype._zoomOriginal = function () {
|
|
@@ -17242,6 +17248,7 @@ class ImageLoader extends React__namespace.Component {
|
|
|
17242
17248
|
}
|
|
17243
17249
|
const staticUrl = getDependencies().staticUrl;
|
|
17244
17250
|
return /*#__PURE__*/React__namespace.createElement("img", _extends({
|
|
17251
|
+
tabIndex: 0,
|
|
17245
17252
|
src: staticUrl(src),
|
|
17246
17253
|
onKeyUp: onKeyUp,
|
|
17247
17254
|
onKeyDown: onKeyDown
|
|
@@ -22456,7 +22463,7 @@ function scoreNumericInput(userInput, rubric, strings) {
|
|
|
22456
22463
|
// We may have received TeX; try to parse it before grading.
|
|
22457
22464
|
// If `currentValue` is not TeX, this should be a no-op.
|
|
22458
22465
|
const currentValue = ParseTex(userInput.currentValue);
|
|
22459
|
-
const normalizedAnswerExpected = rubric.answers.filter(answer => answer.status === "correct").every(answer => answer.value
|
|
22466
|
+
const normalizedAnswerExpected = rubric.answers.filter(answer => answer.status === "correct").every(answer => answer.value != null && Math.abs(answer.value) <= 1);
|
|
22460
22467
|
|
|
22461
22468
|
// The coefficient is an attribute of the widget
|
|
22462
22469
|
let localValue = currentValue;
|
|
@@ -27704,8 +27711,7 @@ class Dropdown extends React__namespace.Component {
|
|
|
27704
27711
|
disabled: true,
|
|
27705
27712
|
label: /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
27706
27713
|
content: this.props.placeholder,
|
|
27707
|
-
strings: this.context.strings
|
|
27708
|
-
inline: true
|
|
27714
|
+
strings: this.context.strings
|
|
27709
27715
|
}),
|
|
27710
27716
|
labelAsText: this.props.placeholder
|
|
27711
27717
|
}), ...this.props.choices.map((choice, i) => /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.OptionItem, {
|
|
@@ -27713,8 +27719,7 @@ class Dropdown extends React__namespace.Component {
|
|
|
27713
27719
|
value: String(i + 1),
|
|
27714
27720
|
label: /*#__PURE__*/React__namespace.createElement(Renderer, {
|
|
27715
27721
|
content: choice,
|
|
27716
|
-
strings: this.context.strings
|
|
27717
|
-
inline: true
|
|
27722
|
+
strings: this.context.strings
|
|
27718
27723
|
}),
|
|
27719
27724
|
labelAsText: choice
|
|
27720
27725
|
}))];
|
|
@@ -27734,6 +27739,7 @@ class Dropdown extends React__namespace.Component {
|
|
|
27734
27739
|
}, this.props.visibleLabel), /*#__PURE__*/React__namespace.createElement(wonderBlocksDropdown.SingleSelect, {
|
|
27735
27740
|
id: dropdownId,
|
|
27736
27741
|
placeholder: "",
|
|
27742
|
+
className: "perseus-dropdown",
|
|
27737
27743
|
onChange: value => this._handleChange(parseInt(value)),
|
|
27738
27744
|
selectedValue: String(this.props.selected),
|
|
27739
27745
|
disabled: this.props.apiOptions.readOnly,
|
|
@@ -34461,10 +34467,10 @@ function AngleGraph(props) {
|
|
|
34461
34467
|
angleMeasure,
|
|
34462
34468
|
vertexX: srFormatNumber(coords[1][X], locale),
|
|
34463
34469
|
vertexY: srFormatNumber(coords[1][Y], locale),
|
|
34464
|
-
|
|
34465
|
-
|
|
34466
|
-
|
|
34467
|
-
|
|
34470
|
+
startingSideX: srFormatNumber(coords[2][X], locale),
|
|
34471
|
+
startingSideY: srFormatNumber(coords[2][Y], locale),
|
|
34472
|
+
endingSideX: srFormatNumber(coords[0][X], locale),
|
|
34473
|
+
endingSideY: srFormatNumber(coords[0][Y], locale)
|
|
34468
34474
|
});
|
|
34469
34475
|
const formatCoordinates = (x, y) => ({
|
|
34470
34476
|
x: srFormatNumber(x, locale),
|
|
@@ -45938,7 +45944,7 @@ const init = function () {
|
|
|
45938
45944
|
|
|
45939
45945
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
45940
45946
|
const libName = "@khanacademy/perseus";
|
|
45941
|
-
const libVersion = "49.
|
|
45947
|
+
const libVersion = "49.2.0";
|
|
45942
45948
|
perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
45943
45949
|
|
|
45944
45950
|
const apiVersion = {
|
|
@@ -48238,10 +48244,10 @@ class UnionBuilder {
|
|
|
48238
48244
|
this.parser = parser;
|
|
48239
48245
|
}
|
|
48240
48246
|
or(newBranch) {
|
|
48241
|
-
return new UnionBuilder(either(this.parser, newBranch));
|
|
48247
|
+
return new UnionBuilder(either$1(this.parser, newBranch));
|
|
48242
48248
|
}
|
|
48243
48249
|
}
|
|
48244
|
-
function either(parseA, parseB) {
|
|
48250
|
+
function either$1(parseA, parseB) {
|
|
48245
48251
|
return (rawValue, ctx) => {
|
|
48246
48252
|
const resultA = parseA(rawValue, ctx);
|
|
48247
48253
|
if (isSuccess(resultA)) {
|
|
@@ -48343,22 +48349,108 @@ const parseExplanationWidget = parseWidget(constant("explanation"), object({
|
|
|
48343
48349
|
// We wrap parseWidgetsMap in a function here to make sure it is not
|
|
48344
48350
|
// referenced before it is defined. There is an import cycle between
|
|
48345
48351
|
// this file and widgets-map.ts that could cause it to be undefined.
|
|
48346
|
-
widgets: (rawVal, ctx) => parseWidgetsMap(rawVal, ctx),
|
|
48347
|
-
static: boolean
|
|
48352
|
+
widgets: defaulted((rawVal, ctx) => parseWidgetsMap(rawVal, ctx), () => ({})),
|
|
48353
|
+
static: defaulted(boolean, () => false)
|
|
48348
48354
|
}));
|
|
48349
48355
|
|
|
48350
|
-
|
|
48351
|
-
|
|
48352
|
-
|
|
48353
|
-
|
|
48356
|
+
// Given a function, creates a PartialParser that converts one type to another
|
|
48357
|
+
// using that function. The returned parser never fails.
|
|
48358
|
+
function convert(f) {
|
|
48359
|
+
return (rawValue, ctx) => ctx.success(f(rawValue));
|
|
48360
|
+
}
|
|
48361
|
+
|
|
48362
|
+
/**
|
|
48363
|
+
* Creates a parser for a widget options type with multiple major versions. Old
|
|
48364
|
+
* versions are migrated to the latest version. The parse fails if the input
|
|
48365
|
+
* data does not match any of the versions.
|
|
48366
|
+
*
|
|
48367
|
+
* @example
|
|
48368
|
+
* const parseOptions = versionedWidgetOptions(parseOptionsV3)
|
|
48369
|
+
* .withMigrationFrom(parseOptionsV2, migrateV2ToV3)
|
|
48370
|
+
* .withMigrationFrom(parseOptionsV1, migrateV1ToV2)
|
|
48371
|
+
* .withMigrationFrom(parseOptionsV0, migrateV0ToV1)
|
|
48372
|
+
* .parser;
|
|
48373
|
+
*
|
|
48374
|
+
* @param parseLatest a {@link Parser} for the latest version of the widget
|
|
48375
|
+
* options. This should check version.major and fail if it's not the latest
|
|
48376
|
+
* version.
|
|
48377
|
+
* @returns a builder object, to which migrations from earlier versions can be
|
|
48378
|
+
* added. Migrations must be added in "reverse chronological" order as in the
|
|
48379
|
+
* example above.
|
|
48380
|
+
*/
|
|
48381
|
+
function versionedWidgetOptions(parseLatest) {
|
|
48382
|
+
return new VersionedWidgetOptionsParserBuilder(parseLatest, latest => latest);
|
|
48383
|
+
}
|
|
48384
|
+
class VersionedWidgetOptionsParserBuilder {
|
|
48385
|
+
constructor(parser, migrate) {
|
|
48386
|
+
this.parser = parser;
|
|
48387
|
+
this.migrate = migrate;
|
|
48388
|
+
}
|
|
48389
|
+
|
|
48390
|
+
/**
|
|
48391
|
+
* Add a migration from an old version of the widget options.
|
|
48392
|
+
*
|
|
48393
|
+
* @returns a VersionedWidgetOptionsParserBuilder whose `parser` function
|
|
48394
|
+
* is capable of migrating the old version to the latest version. The parser
|
|
48395
|
+
* will always return the latest version of the widget options on a
|
|
48396
|
+
* successful parse.
|
|
48397
|
+
* @param parseOldVersion should be a {@link Parser} for the old options
|
|
48398
|
+
* type. It should fail if version.major isn't correct.
|
|
48399
|
+
* @param migrateToNextVersion should migrate the `Old` data to the
|
|
48400
|
+
* `Migratable` version of the current VersionedWidgetOptionsParserBuilder.
|
|
48401
|
+
* Usually, this means migrating to the next major version.
|
|
48402
|
+
*/
|
|
48403
|
+
withMigrationFrom(parseOldVersion, migrateToNextVersion) {
|
|
48404
|
+
const parseLatestVersion = this.parser;
|
|
48405
|
+
const migrateToLatest = old => this.migrate(migrateToNextVersion(old));
|
|
48406
|
+
return new VersionedWidgetOptionsParserBuilder((raw, ctx) => {
|
|
48407
|
+
const resultOfParsingLatest = parseLatestVersion(raw, ctx);
|
|
48408
|
+
if (isSuccess(resultOfParsingLatest)) {
|
|
48409
|
+
return resultOfParsingLatest;
|
|
48410
|
+
}
|
|
48411
|
+
const resultOfParsingOld = parseOldVersion(raw, ctx);
|
|
48412
|
+
if (isSuccess(resultOfParsingOld)) {
|
|
48413
|
+
return success(migrateToLatest(resultOfParsingOld.value));
|
|
48414
|
+
}
|
|
48415
|
+
|
|
48416
|
+
// If we're here, neither parse succeeded. Return the failure.
|
|
48417
|
+
return resultOfParsingOld;
|
|
48418
|
+
}, migrateToLatest);
|
|
48419
|
+
}
|
|
48420
|
+
}
|
|
48421
|
+
|
|
48422
|
+
const parsePossiblyInvalidAnswerForm = object({
|
|
48423
|
+
// `value` is the possibly invalid part of this. It should always be a
|
|
48424
|
+
// string, but some answer forms don't have it. The Expression widget
|
|
48425
|
+
// ignores invalid values, so we can safely filter them out during parsing.
|
|
48426
|
+
value: optional(string),
|
|
48427
|
+
form: defaulted(boolean, () => false),
|
|
48428
|
+
simplify: defaulted(boolean, () => false),
|
|
48354
48429
|
considered: enumeration("correct", "wrong", "ungraded"),
|
|
48355
48430
|
key: pipeParsers(optional(union(string).or(number).parser)).then((key, ctx) => ctx.success(String(key))).parser
|
|
48356
48431
|
});
|
|
48357
|
-
|
|
48432
|
+
function removeInvalidAnswerForms(possiblyInvalid) {
|
|
48433
|
+
const valid = [];
|
|
48434
|
+
for (const answerForm of possiblyInvalid) {
|
|
48435
|
+
const {
|
|
48436
|
+
value
|
|
48437
|
+
} = answerForm;
|
|
48438
|
+
if (value != null) {
|
|
48439
|
+
// Copying the object seems to be needed to make TypeScript happy
|
|
48440
|
+
valid.push({
|
|
48441
|
+
...answerForm,
|
|
48442
|
+
value
|
|
48443
|
+
});
|
|
48444
|
+
}
|
|
48445
|
+
}
|
|
48446
|
+
return valid;
|
|
48447
|
+
}
|
|
48448
|
+
const version1 = object({
|
|
48358
48449
|
major: constant(1),
|
|
48359
48450
|
minor: number
|
|
48360
|
-
})
|
|
48361
|
-
|
|
48451
|
+
});
|
|
48452
|
+
const parseExpressionWidgetV1 = parseWidgetWithVersion(version1, constant("expression"), object({
|
|
48453
|
+
answerForms: pipeParsers(array(parsePossiblyInvalidAnswerForm)).then(convert(removeInvalidAnswerForms)).parser,
|
|
48362
48454
|
functions: array(string),
|
|
48363
48455
|
times: boolean,
|
|
48364
48456
|
visibleLabel: optional(string),
|
|
@@ -48366,10 +48458,11 @@ const parseExpressionWidgetV1 = parseWidgetWithVersion(object({
|
|
|
48366
48458
|
buttonSets: array(enumeration("basic", "basic+div", "trig", "prealgebra", "logarithms", "basic relations", "advanced relations")),
|
|
48367
48459
|
buttonsVisible: optional(enumeration("always", "never", "focused"))
|
|
48368
48460
|
}));
|
|
48369
|
-
const
|
|
48461
|
+
const version0 = optional(object({
|
|
48370
48462
|
major: constant(0),
|
|
48371
48463
|
minor: number
|
|
48372
|
-
}))
|
|
48464
|
+
}));
|
|
48465
|
+
const parseExpressionWidgetV0 = parseWidgetWithVersion(version0, constant("expression"), object({
|
|
48373
48466
|
functions: array(string),
|
|
48374
48467
|
times: boolean,
|
|
48375
48468
|
visibleLabel: optional(string),
|
|
@@ -48380,11 +48473,11 @@ const parseExpressionWidgetV0 = parseWidgetWithVersion(optional(object({
|
|
|
48380
48473
|
buttonSets: array(enumeration("basic", "basic+div", "trig", "prealgebra", "logarithms", "basic relations", "advanced relations")),
|
|
48381
48474
|
buttonsVisible: optional(enumeration("always", "never", "focused"))
|
|
48382
48475
|
}));
|
|
48383
|
-
function migrateV0ToV1(widget
|
|
48476
|
+
function migrateV0ToV1(widget) {
|
|
48384
48477
|
const {
|
|
48385
48478
|
options
|
|
48386
48479
|
} = widget;
|
|
48387
|
-
return
|
|
48480
|
+
return {
|
|
48388
48481
|
...widget,
|
|
48389
48482
|
version: {
|
|
48390
48483
|
major: 1,
|
|
@@ -48404,9 +48497,9 @@ function migrateV0ToV1(widget, ctx) {
|
|
|
48404
48497
|
value: options.value
|
|
48405
48498
|
}]
|
|
48406
48499
|
}
|
|
48407
|
-
}
|
|
48500
|
+
};
|
|
48408
48501
|
}
|
|
48409
|
-
const parseExpressionWidget =
|
|
48502
|
+
const parseExpressionWidget = versionedWidgetOptions(parseExpressionWidgetV1).withMigrationFrom(parseExpressionWidgetV0, migrateV0ToV1).parser;
|
|
48410
48503
|
|
|
48411
48504
|
const parsePerseusRenderer = defaulted(object({
|
|
48412
48505
|
// TODO(benchristel): content is also defaulted to empty string in
|
|
@@ -48452,31 +48545,70 @@ const parseGradedGroupSetWidget = parseWidget(constant("graded-group-set"), obje
|
|
|
48452
48545
|
gradedGroups: array(parseGradedGroupWidgetOptions)
|
|
48453
48546
|
}));
|
|
48454
48547
|
|
|
48548
|
+
// discriminatedUnion() should be preferred over union() when parsing a
|
|
48549
|
+
// discriminated union type, because discriminatedUnion() produces more
|
|
48550
|
+
// understandable failure messages. It takes the discriminant as the source of
|
|
48551
|
+
// truth for which variant is to be parsed, and expects the other data to match
|
|
48552
|
+
// that variant.
|
|
48553
|
+
function discriminatedUnion(narrow, parseVariant) {
|
|
48554
|
+
return new DiscriminatedUnionBuilder(pipeParsers(narrow).then(parseVariant).parser);
|
|
48555
|
+
}
|
|
48556
|
+
class DiscriminatedUnionBuilder {
|
|
48557
|
+
constructor(parser) {
|
|
48558
|
+
this.parser = parser;
|
|
48559
|
+
}
|
|
48560
|
+
or(narrow, parseVariant) {
|
|
48561
|
+
return new DiscriminatedUnionBuilder(either(narrow, parseVariant, this.parser));
|
|
48562
|
+
}
|
|
48563
|
+
}
|
|
48564
|
+
function either(narrowToA, parseA, parseB) {
|
|
48565
|
+
return (rawValue, ctx) => {
|
|
48566
|
+
if (isSuccess(narrowToA(rawValue, ctx))) {
|
|
48567
|
+
return parseA(rawValue, ctx);
|
|
48568
|
+
}
|
|
48569
|
+
return parseB(rawValue, ctx);
|
|
48570
|
+
};
|
|
48571
|
+
}
|
|
48572
|
+
|
|
48455
48573
|
const pairOfNumbers$3 = pair(number, number);
|
|
48456
48574
|
const pairOfPoints = pair(pairOfNumbers$3, pairOfNumbers$3);
|
|
48457
48575
|
const parseGrapherWidget = parseWidget(constant("grapher"), object({
|
|
48458
48576
|
availableTypes: array(enumeration("absolute_value", "exponential", "linear", "logarithm", "quadratic", "sinusoid", "tangent")),
|
|
48459
|
-
correct:
|
|
48577
|
+
correct: discriminatedUnion(object({
|
|
48578
|
+
type: constant("absolute_value")
|
|
48579
|
+
}), object({
|
|
48460
48580
|
type: constant("absolute_value"),
|
|
48461
48581
|
coords: pairOfPoints
|
|
48462
48582
|
})).or(object({
|
|
48583
|
+
type: constant("exponential")
|
|
48584
|
+
}), object({
|
|
48463
48585
|
type: constant("exponential"),
|
|
48464
48586
|
asymptote: pairOfPoints,
|
|
48465
48587
|
coords: pairOfPoints
|
|
48466
48588
|
})).or(object({
|
|
48589
|
+
type: constant("linear")
|
|
48590
|
+
}), object({
|
|
48467
48591
|
type: constant("linear"),
|
|
48468
48592
|
coords: pairOfPoints
|
|
48469
48593
|
})).or(object({
|
|
48594
|
+
type: constant("logarithm")
|
|
48595
|
+
}), object({
|
|
48470
48596
|
type: constant("logarithm"),
|
|
48471
48597
|
asymptote: pairOfPoints,
|
|
48472
48598
|
coords: pairOfPoints
|
|
48473
48599
|
})).or(object({
|
|
48600
|
+
type: constant("quadratic")
|
|
48601
|
+
}), object({
|
|
48474
48602
|
type: constant("quadratic"),
|
|
48475
48603
|
coords: pairOfPoints
|
|
48476
48604
|
})).or(object({
|
|
48605
|
+
type: constant("sinusoid")
|
|
48606
|
+
}), object({
|
|
48477
48607
|
type: constant("sinusoid"),
|
|
48478
48608
|
coords: pairOfPoints
|
|
48479
48609
|
})).or(object({
|
|
48610
|
+
type: constant("tangent")
|
|
48611
|
+
}), object({
|
|
48480
48612
|
type: constant("tangent"),
|
|
48481
48613
|
coords: pairOfPoints
|
|
48482
48614
|
})).parser,
|
|
@@ -48536,15 +48668,22 @@ const stringToNumber = (rawValue, ctx) => {
|
|
|
48536
48668
|
return ctx.success(parsedNumber);
|
|
48537
48669
|
};
|
|
48538
48670
|
|
|
48539
|
-
|
|
48671
|
+
function emptyToZero(x) {
|
|
48672
|
+
return x === "" ? 0 : x;
|
|
48673
|
+
}
|
|
48674
|
+
const imageDimensionToNumber = pipeParsers(union(number).or(string).parser)
|
|
48675
|
+
// In this specific case, empty string is equivalent to zero. An empty
|
|
48676
|
+
// string parses to either NaN (using parseInt) or 0 (using unary +) and
|
|
48677
|
+
// CSS will treat NaN as invalid and default to 0 instead.
|
|
48678
|
+
.then(convert(emptyToZero)).then(stringToNumber).parser;
|
|
48540
48679
|
const parsePerseusImageBackground = object({
|
|
48541
48680
|
url: optional(nullable(string)),
|
|
48542
|
-
width: optional(
|
|
48543
|
-
height: optional(
|
|
48544
|
-
top: optional(
|
|
48545
|
-
left: optional(
|
|
48546
|
-
bottom: optional(
|
|
48547
|
-
scale: optional(
|
|
48681
|
+
width: optional(imageDimensionToNumber),
|
|
48682
|
+
height: optional(imageDimensionToNumber),
|
|
48683
|
+
top: optional(imageDimensionToNumber),
|
|
48684
|
+
left: optional(imageDimensionToNumber),
|
|
48685
|
+
bottom: optional(imageDimensionToNumber),
|
|
48686
|
+
scale: optional(imageDimensionToNumber)
|
|
48548
48687
|
});
|
|
48549
48688
|
|
|
48550
48689
|
const pairOfNumbers$2 = pair(number, number);
|
|
@@ -48585,8 +48724,10 @@ const parseInputNumberWidget = parseWidget(constant("input-number"), object({
|
|
|
48585
48724
|
}));
|
|
48586
48725
|
|
|
48587
48726
|
const pairOfNumbers$1 = pair(number, number);
|
|
48727
|
+
const stringOrEmpty = defaulted(string, () => "");
|
|
48728
|
+
const parseFunctionType = constant("function");
|
|
48588
48729
|
const parseFunctionElement = object({
|
|
48589
|
-
type:
|
|
48730
|
+
type: parseFunctionType,
|
|
48590
48731
|
key: string,
|
|
48591
48732
|
options: object({
|
|
48592
48733
|
value: string,
|
|
@@ -48598,8 +48739,9 @@ const parseFunctionElement = object({
|
|
|
48598
48739
|
strokeWidth: number
|
|
48599
48740
|
})
|
|
48600
48741
|
});
|
|
48742
|
+
const parseLabelType = constant("label");
|
|
48601
48743
|
const parseLabelElement = object({
|
|
48602
|
-
type:
|
|
48744
|
+
type: parseLabelType,
|
|
48603
48745
|
key: string,
|
|
48604
48746
|
options: object({
|
|
48605
48747
|
label: string,
|
|
@@ -48608,8 +48750,9 @@ const parseLabelElement = object({
|
|
|
48608
48750
|
coordY: string
|
|
48609
48751
|
})
|
|
48610
48752
|
});
|
|
48753
|
+
const parseLineType = constant("line");
|
|
48611
48754
|
const parseLineElement = object({
|
|
48612
|
-
type:
|
|
48755
|
+
type: parseLineType,
|
|
48613
48756
|
key: string,
|
|
48614
48757
|
options: object({
|
|
48615
48758
|
color: string,
|
|
@@ -48622,8 +48765,9 @@ const parseLineElement = object({
|
|
|
48622
48765
|
arrows: string
|
|
48623
48766
|
})
|
|
48624
48767
|
});
|
|
48768
|
+
const parseMovableLineType = constant("movable-line");
|
|
48625
48769
|
const parseMovableLineElement = object({
|
|
48626
|
-
type:
|
|
48770
|
+
type: parseMovableLineType,
|
|
48627
48771
|
key: string,
|
|
48628
48772
|
options: object({
|
|
48629
48773
|
startX: string,
|
|
@@ -48641,8 +48785,9 @@ const parseMovableLineElement = object({
|
|
|
48641
48785
|
constraintYMax: string
|
|
48642
48786
|
})
|
|
48643
48787
|
});
|
|
48788
|
+
const parseMovablePointType = constant("movable-point");
|
|
48644
48789
|
const parseMovablePointElement = object({
|
|
48645
|
-
type:
|
|
48790
|
+
type: parseMovablePointType,
|
|
48646
48791
|
key: string,
|
|
48647
48792
|
options: object({
|
|
48648
48793
|
startX: string,
|
|
@@ -48651,14 +48796,15 @@ const parseMovablePointElement = object({
|
|
|
48651
48796
|
constraint: string,
|
|
48652
48797
|
snap: number,
|
|
48653
48798
|
constraintFn: string,
|
|
48654
|
-
constraintXMin:
|
|
48655
|
-
constraintXMax:
|
|
48656
|
-
constraintYMin:
|
|
48657
|
-
constraintYMax:
|
|
48799
|
+
constraintXMin: stringOrEmpty,
|
|
48800
|
+
constraintXMax: stringOrEmpty,
|
|
48801
|
+
constraintYMin: stringOrEmpty,
|
|
48802
|
+
constraintYMax: stringOrEmpty
|
|
48658
48803
|
})
|
|
48659
48804
|
});
|
|
48805
|
+
const parseParametricType = constant("parametric");
|
|
48660
48806
|
const parseParametricElement = object({
|
|
48661
|
-
type:
|
|
48807
|
+
type: parseParametricType,
|
|
48662
48808
|
key: string,
|
|
48663
48809
|
options: object({
|
|
48664
48810
|
x: string,
|
|
@@ -48670,8 +48816,9 @@ const parseParametricElement = object({
|
|
|
48670
48816
|
strokeWidth: number
|
|
48671
48817
|
})
|
|
48672
48818
|
});
|
|
48819
|
+
const parsePointType = constant("point");
|
|
48673
48820
|
const parsePointElement = object({
|
|
48674
|
-
type:
|
|
48821
|
+
type: parsePointType,
|
|
48675
48822
|
key: string,
|
|
48676
48823
|
options: object({
|
|
48677
48824
|
color: string,
|
|
@@ -48679,8 +48826,9 @@ const parsePointElement = object({
|
|
|
48679
48826
|
coordY: string
|
|
48680
48827
|
})
|
|
48681
48828
|
});
|
|
48829
|
+
const parseRectangleType = constant("rectangle");
|
|
48682
48830
|
const parseRectangleElement = object({
|
|
48683
|
-
type:
|
|
48831
|
+
type: parseRectangleType,
|
|
48684
48832
|
key: string,
|
|
48685
48833
|
options: object({
|
|
48686
48834
|
color: string,
|
|
@@ -48691,7 +48839,7 @@ const parseRectangleElement = object({
|
|
|
48691
48839
|
})
|
|
48692
48840
|
});
|
|
48693
48841
|
const parseInteractionWidget = parseWidget(constant("interaction"), object({
|
|
48694
|
-
static: boolean,
|
|
48842
|
+
static: defaulted(boolean, () => false),
|
|
48695
48843
|
graph: object({
|
|
48696
48844
|
editableSettings: optional(array(enumeration("canvas", "graph"))),
|
|
48697
48845
|
box: pairOfNumbers$1,
|
|
@@ -48708,7 +48856,23 @@ const parseInteractionWidget = parseWidget(constant("interaction"), object({
|
|
|
48708
48856
|
rulerTicks: optional(number),
|
|
48709
48857
|
tickStep: pairOfNumbers$1
|
|
48710
48858
|
}),
|
|
48711
|
-
elements: array(
|
|
48859
|
+
elements: array(discriminatedUnion(object({
|
|
48860
|
+
type: parseFunctionType
|
|
48861
|
+
}), parseFunctionElement).or(object({
|
|
48862
|
+
type: parseLabelType
|
|
48863
|
+
}), parseLabelElement).or(object({
|
|
48864
|
+
type: parseLineType
|
|
48865
|
+
}), parseLineElement).or(object({
|
|
48866
|
+
type: parseMovableLineType
|
|
48867
|
+
}), parseMovableLineElement).or(object({
|
|
48868
|
+
type: parseMovablePointType
|
|
48869
|
+
}), parseMovablePointElement).or(object({
|
|
48870
|
+
type: parseParametricType
|
|
48871
|
+
}), parseParametricElement).or(object({
|
|
48872
|
+
type: parsePointType
|
|
48873
|
+
}), parsePointElement).or(object({
|
|
48874
|
+
type: parseRectangleType
|
|
48875
|
+
}), parseRectangleElement).parser)
|
|
48712
48876
|
}));
|
|
48713
48877
|
|
|
48714
48878
|
// Used to represent 2-D points and ranges
|
|
@@ -48931,10 +49095,11 @@ const parseMatcherWidget = parseWidget(constant("matcher"), object({
|
|
|
48931
49095
|
padding: boolean
|
|
48932
49096
|
}));
|
|
48933
49097
|
|
|
49098
|
+
const numeric = pipeParsers(union(number).or(string).parser).then(stringToNumber).parser;
|
|
48934
49099
|
const parseMatrixWidget = parseWidget(defaulted(constant("matrix"), () => "matrix"), object({
|
|
48935
49100
|
prefix: optional(string),
|
|
48936
49101
|
suffix: optional(string),
|
|
48937
|
-
answers: array(array(
|
|
49102
|
+
answers: array(array(numeric)),
|
|
48938
49103
|
cursorPosition: optional(array(number)),
|
|
48939
49104
|
matrixBoardSize: array(number),
|
|
48940
49105
|
static: optional(boolean)
|
|
@@ -48982,12 +49147,18 @@ const parseMathFormat = enumeration("integer", "mixed", "improper", "proper", "d
|
|
|
48982
49147
|
const parseNumericInputWidget = parseWidget(constant("numeric-input"), object({
|
|
48983
49148
|
answers: array(object({
|
|
48984
49149
|
message: string,
|
|
48985
|
-
|
|
49150
|
+
// TODO(benchristel): value should never be null or undefined,
|
|
49151
|
+
// but we have some content where it is anyway. If we backfill
|
|
49152
|
+
// the data, simplify this.
|
|
49153
|
+
value: optional(nullable(number)),
|
|
48986
49154
|
status: string,
|
|
48987
49155
|
answerForms: optional(array(parseMathFormat)),
|
|
48988
49156
|
strict: boolean,
|
|
48989
49157
|
maxError: optional(nullable(number)),
|
|
48990
|
-
|
|
49158
|
+
// TODO(benchristel): simplify should never be `true`, but we
|
|
49159
|
+
// have some content where it is anyway. If we ever backfill
|
|
49160
|
+
// the data, we should simplify `simplify`.
|
|
49161
|
+
simplify: optional(nullable(union(string).or(pipeParsers(constant(true)).then(convert(String)).parser).parser))
|
|
48991
49162
|
})),
|
|
48992
49163
|
labelText: optional(string),
|
|
48993
49164
|
size: string,
|
|
@@ -49023,7 +49194,7 @@ const parseOrdererWidget = parseWidget(constant("orderer"), object({
|
|
|
49023
49194
|
const parsePassageRefWidget = parseWidget(constant("passage-ref"), object({
|
|
49024
49195
|
passageNumber: number,
|
|
49025
49196
|
referenceNumber: number,
|
|
49026
|
-
summaryText: string
|
|
49197
|
+
summaryText: optional(string)
|
|
49027
49198
|
}));
|
|
49028
49199
|
|
|
49029
49200
|
const parsePassageWidget = parseWidget(constant("passage"), object({
|
|
@@ -49212,6 +49383,8 @@ const parseWidgetsMapEntry = (_ref, widgetMap, ctx) => {
|
|
|
49212
49383
|
// sequence is a deprecated widget type, and the corresponding
|
|
49213
49384
|
// widget component no longer exists.
|
|
49214
49385
|
return parseAndAssign(`sequence ${id}`, parseDeprecatedWidget);
|
|
49386
|
+
case "lights-puzzle":
|
|
49387
|
+
return parseAndAssign(`lights-puzzle ${id}`, parseDeprecatedWidget);
|
|
49215
49388
|
default:
|
|
49216
49389
|
if (getWidget(type)) {
|
|
49217
49390
|
// @ts-expect-error - 'type' is not a valid widget type
|