@khanacademy/perseus 49.2.0 → 49.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/es/index.css +2 -1
- package/dist/es/index.js +159 -219
- package/dist/es/index.js.map +1 -1
- package/dist/es/strings.js +23 -86
- package/dist/es/strings.js.map +1 -1
- package/dist/index.css +2 -1
- package/dist/index.js +140 -176
- package/dist/index.js.map +1 -1
- package/dist/perseus-types.d.ts +9 -7
- package/dist/server-item-renderer.d.ts +1 -1
- package/dist/strings.js +23 -86
- package/dist/strings.js.map +1 -1
- package/dist/types.d.ts +2 -5
- package/dist/util/parse-perseus-json/general-purpose-parsers/discriminated-union.d.ts +18 -5
- package/dist/util/parse-perseus-json/general-purpose-parsers/discriminated-union.typetest.d.ts +1 -0
- package/dist/util/parse-perseus-json/perseus-parsers/versioned-widget-options.d.ts +12 -21
- package/dist/widgets/expression/expression.d.ts +2 -2
- package/dist/widgets/interactive-graphs/graph-locked-labels-layer.d.ts +1 -3
- package/dist/widgets/interactive-graphs/graph-locked-layer.d.ts +0 -2
- package/dist/widgets/interactive-graphs/locked-figures/locked-ellipse.d.ts +1 -5
- package/dist/widgets/interactive-graphs/locked-figures/locked-function.d.ts +1 -5
- package/dist/widgets/interactive-graphs/locked-figures/locked-line.d.ts +0 -2
- package/dist/widgets/interactive-graphs/locked-figures/locked-point.d.ts +1 -5
- package/dist/widgets/interactive-graphs/locked-figures/locked-polygon.d.ts +1 -5
- package/dist/widgets/interactive-graphs/locked-figures/locked-vector.d.ts +1 -5
- package/package.json +38 -38
package/dist/es/index.js
CHANGED
|
@@ -44,21 +44,13 @@ import cornersOutIcon from '@phosphor-icons/core/regular/corners-out.svg';
|
|
|
44
44
|
import Link from '@khanacademy/wonder-blocks-link';
|
|
45
45
|
|
|
46
46
|
function _extends() {
|
|
47
|
-
_extends = Object.assign
|
|
48
|
-
for (var
|
|
49
|
-
var
|
|
50
|
-
|
|
51
|
-
for (var key in source) {
|
|
52
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
53
|
-
target[key] = source[key];
|
|
54
|
-
}
|
|
55
|
-
}
|
|
47
|
+
return _extends = Object.assign ? Object.assign.bind() : function (n) {
|
|
48
|
+
for (var e = 1; e < arguments.length; e++) {
|
|
49
|
+
var t = arguments[e];
|
|
50
|
+
for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
|
|
56
51
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
return _extends.apply(this, arguments);
|
|
52
|
+
return n;
|
|
53
|
+
}, _extends.apply(null, arguments);
|
|
62
54
|
}
|
|
63
55
|
|
|
64
56
|
/**
|
|
@@ -4508,17 +4500,14 @@ const InteractiveUtil = {
|
|
|
4508
4500
|
}
|
|
4509
4501
|
};
|
|
4510
4502
|
|
|
4511
|
-
function _classPrivateFieldBase(
|
|
4512
|
-
if (!
|
|
4513
|
-
|
|
4514
|
-
}
|
|
4515
|
-
|
|
4516
|
-
return receiver;
|
|
4503
|
+
function _classPrivateFieldBase(e, t) {
|
|
4504
|
+
if (!{}.hasOwnProperty.call(e, t)) throw new TypeError("attempted to use private field on non-instance");
|
|
4505
|
+
return e;
|
|
4517
4506
|
}
|
|
4518
4507
|
|
|
4519
4508
|
var id = 0;
|
|
4520
|
-
function _classPrivateFieldKey(
|
|
4521
|
-
return "__private_" + id++ + "_" +
|
|
4509
|
+
function _classPrivateFieldKey(e) {
|
|
4510
|
+
return "__private_" + id++ + "_" + e;
|
|
4522
4511
|
}
|
|
4523
4512
|
|
|
4524
4513
|
/*!
|
|
@@ -21145,19 +21134,14 @@ TextInput.defaultProps = {
|
|
|
21145
21134
|
disabled: false
|
|
21146
21135
|
};
|
|
21147
21136
|
|
|
21148
|
-
function _objectWithoutPropertiesLoose(
|
|
21149
|
-
if (
|
|
21150
|
-
var
|
|
21151
|
-
var
|
|
21152
|
-
|
|
21153
|
-
|
|
21154
|
-
for (i = 0; i < sourceKeys.length; i++) {
|
|
21155
|
-
key = sourceKeys[i];
|
|
21156
|
-
if (excluded.indexOf(key) >= 0) continue;
|
|
21157
|
-
target[key] = source[key];
|
|
21137
|
+
function _objectWithoutPropertiesLoose(r, e) {
|
|
21138
|
+
if (null == r) return {};
|
|
21139
|
+
var t = {};
|
|
21140
|
+
for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
|
|
21141
|
+
if (e.includes(n)) continue;
|
|
21142
|
+
t[n] = r[n];
|
|
21158
21143
|
}
|
|
21159
|
-
|
|
21160
|
-
return target;
|
|
21144
|
+
return t;
|
|
21161
21145
|
}
|
|
21162
21146
|
|
|
21163
21147
|
const _excluded$7 = ["position", "visibility", "left", "top"];
|
|
@@ -32370,7 +32354,7 @@ const LegacyGrid = ({
|
|
|
32370
32354
|
* "new-awesomeness": MyAwesomeNewWidget;
|
|
32371
32355
|
*
|
|
32372
32356
|
* // A deprecated widget
|
|
32373
|
-
* "super-old-widget":
|
|
32357
|
+
* "super-old-widget": DeprecatedStandinWidget;
|
|
32374
32358
|
* }
|
|
32375
32359
|
* }
|
|
32376
32360
|
*
|
|
@@ -32564,46 +32548,28 @@ function LockedLabel(props) {
|
|
|
32564
32548
|
|
|
32565
32549
|
function GraphLockedLabelsLayer(props) {
|
|
32566
32550
|
const {
|
|
32567
|
-
flags,
|
|
32568
32551
|
lockedFigures
|
|
32569
32552
|
} = props;
|
|
32570
32553
|
return lockedFigures.map((figure, i) => {
|
|
32571
|
-
var
|
|
32554
|
+
var _figure$labels, _figure$points$0$labe, _figure$points$1$labe;
|
|
32572
32555
|
if (figure.type === "label") {
|
|
32573
32556
|
return /*#__PURE__*/React.createElement(LockedLabel, _extends({
|
|
32574
32557
|
key: `label-${i}`
|
|
32575
32558
|
}, figure));
|
|
32576
32559
|
}
|
|
32577
|
-
|
|
32578
|
-
|
|
32579
|
-
|
|
32580
|
-
|
|
32581
|
-
|
|
32582
|
-
|
|
32583
|
-
|
|
32584
|
-
|
|
32585
|
-
|
|
32586
|
-
// Polygon flag + polygon type
|
|
32587
|
-
flags != null && (_flags$mafs5 = flags["mafs"]) != null && _flags$mafs5["locked-polygon-labels"] && figure.type === "polygon" ||
|
|
32588
|
-
// Function flag + function type
|
|
32589
|
-
flags != null && (_flags$mafs6 = flags["mafs"]) != null && _flags$mafs6["locked-function-labels"] && figure.type === "function") {
|
|
32590
|
-
var _figure$labels, _figure$points$0$labe, _figure$points$1$labe;
|
|
32591
|
-
return /*#__PURE__*/React.createElement(React.Fragment, {
|
|
32592
|
-
key: i
|
|
32593
|
-
}, (_figure$labels = figure.labels) == null ? void 0 : _figure$labels.map((label, j) => /*#__PURE__*/React.createElement(LockedLabel, _extends({
|
|
32594
|
-
key: `${i}-label-${j}`
|
|
32595
|
-
}, label))), figure.type === "line" && /*#__PURE__*/React.createElement(React.Fragment, null, (_figure$points$0$labe = figure.points[0].labels) == null ? void 0 : _figure$points$0$labe.map((label, k) => /*#__PURE__*/React.createElement(LockedLabel, _extends({
|
|
32596
|
-
key: `locked-figure-${i}-point-1-label-${k}`
|
|
32597
|
-
}, label))), (_figure$points$1$labe = figure.points[1].labels) == null ? void 0 : _figure$points$1$labe.map((label, k) => /*#__PURE__*/React.createElement(LockedLabel, _extends({
|
|
32598
|
-
key: `locked-figure-${i}-point-2-label-${k}`
|
|
32599
|
-
}, label)))));
|
|
32600
|
-
}
|
|
32601
|
-
return null;
|
|
32560
|
+
return /*#__PURE__*/React.createElement(React.Fragment, {
|
|
32561
|
+
key: i
|
|
32562
|
+
}, (_figure$labels = figure.labels) == null ? void 0 : _figure$labels.map((label, j) => /*#__PURE__*/React.createElement(LockedLabel, _extends({
|
|
32563
|
+
key: `${i}-label-${j}`
|
|
32564
|
+
}, label))), figure.type === "line" && /*#__PURE__*/React.createElement(React.Fragment, null, (_figure$points$0$labe = figure.points[0].labels) == null ? void 0 : _figure$points$0$labe.map((label, k) => /*#__PURE__*/React.createElement(LockedLabel, _extends({
|
|
32565
|
+
key: `locked-figure-${i}-point-1-label-${k}`
|
|
32566
|
+
}, label))), (_figure$points$1$labe = figure.points[1].labels) == null ? void 0 : _figure$points$1$labe.map((label, k) => /*#__PURE__*/React.createElement(LockedLabel, _extends({
|
|
32567
|
+
key: `locked-figure-${i}-point-2-label-${k}`
|
|
32568
|
+
}, label)))));
|
|
32602
32569
|
});
|
|
32603
32570
|
}
|
|
32604
32571
|
|
|
32605
32572
|
const LockedEllipse = props => {
|
|
32606
|
-
var _flags$mafs;
|
|
32607
32573
|
const {
|
|
32608
32574
|
center,
|
|
32609
32575
|
radius,
|
|
@@ -32611,10 +32577,9 @@ const LockedEllipse = props => {
|
|
|
32611
32577
|
color: color$1,
|
|
32612
32578
|
fillStyle,
|
|
32613
32579
|
strokeStyle,
|
|
32614
|
-
ariaLabel
|
|
32615
|
-
flags
|
|
32580
|
+
ariaLabel
|
|
32616
32581
|
} = props;
|
|
32617
|
-
const hasAria = ariaLabel
|
|
32582
|
+
const hasAria = !!ariaLabel;
|
|
32618
32583
|
return /*#__PURE__*/React.createElement("g", {
|
|
32619
32584
|
className: "locked-ellipse",
|
|
32620
32585
|
"aria-label": hasAria ? ariaLabel : undefined,
|
|
@@ -32639,7 +32604,6 @@ const LockedEllipse = props => {
|
|
|
32639
32604
|
};
|
|
32640
32605
|
|
|
32641
32606
|
const LockedFunction = props => {
|
|
32642
|
-
var _props$flags;
|
|
32643
32607
|
const [equation, setEquation] = useState();
|
|
32644
32608
|
const {
|
|
32645
32609
|
color,
|
|
@@ -32652,7 +32616,7 @@ const LockedFunction = props => {
|
|
|
32652
32616
|
style: strokeStyle,
|
|
32653
32617
|
domain
|
|
32654
32618
|
};
|
|
32655
|
-
const hasAria = props.ariaLabel
|
|
32619
|
+
const hasAria = !!props.ariaLabel;
|
|
32656
32620
|
useEffect(() => {
|
|
32657
32621
|
// Parsing the equation in a "useEffect" hook saves about 2ms each frame
|
|
32658
32622
|
// when the learner is interacting with the graph (i.e. moving points).
|
|
@@ -32768,7 +32732,6 @@ function getArrayWithoutDuplicates(array) {
|
|
|
32768
32732
|
}
|
|
32769
32733
|
|
|
32770
32734
|
const LockedLine = props => {
|
|
32771
|
-
var _flags$mafs;
|
|
32772
32735
|
const {
|
|
32773
32736
|
color: color$1,
|
|
32774
32737
|
lineStyle,
|
|
@@ -32777,11 +32740,10 @@ const LockedLine = props => {
|
|
|
32777
32740
|
showPoint1,
|
|
32778
32741
|
showPoint2,
|
|
32779
32742
|
ariaLabel,
|
|
32780
|
-
flags,
|
|
32781
32743
|
range
|
|
32782
32744
|
} = props;
|
|
32783
32745
|
const [point1, point2] = points;
|
|
32784
|
-
const hasAria = ariaLabel
|
|
32746
|
+
const hasAria = !!ariaLabel;
|
|
32785
32747
|
let line;
|
|
32786
32748
|
if (kind === "ray") {
|
|
32787
32749
|
// Rays extend to the end of the graph in one direction.
|
|
@@ -32848,16 +32810,14 @@ const LockedLine = props => {
|
|
|
32848
32810
|
};
|
|
32849
32811
|
|
|
32850
32812
|
const LockedPoint = props => {
|
|
32851
|
-
var _flags$mafs;
|
|
32852
32813
|
const {
|
|
32853
|
-
flags,
|
|
32854
32814
|
color: color$1,
|
|
32855
32815
|
coord,
|
|
32856
32816
|
filled,
|
|
32857
32817
|
ariaLabel
|
|
32858
32818
|
} = props;
|
|
32859
32819
|
const [x, y] = coord;
|
|
32860
|
-
const hasAria = ariaLabel
|
|
32820
|
+
const hasAria = !!ariaLabel;
|
|
32861
32821
|
return /*#__PURE__*/React.createElement("g", {
|
|
32862
32822
|
className: "locked-point",
|
|
32863
32823
|
"aria-label": hasAria ? ariaLabel : undefined,
|
|
@@ -32876,7 +32836,6 @@ const LockedPoint = props => {
|
|
|
32876
32836
|
};
|
|
32877
32837
|
|
|
32878
32838
|
const LockedPolygon = props => {
|
|
32879
|
-
var _props$flags;
|
|
32880
32839
|
const {
|
|
32881
32840
|
points,
|
|
32882
32841
|
color: color$1,
|
|
@@ -32884,7 +32843,7 @@ const LockedPolygon = props => {
|
|
|
32884
32843
|
fillStyle,
|
|
32885
32844
|
strokeStyle
|
|
32886
32845
|
} = props;
|
|
32887
|
-
const hasAria = props.ariaLabel
|
|
32846
|
+
const hasAria = !!props.ariaLabel;
|
|
32888
32847
|
return /*#__PURE__*/React.createElement("g", {
|
|
32889
32848
|
className: "locked-polygon",
|
|
32890
32849
|
"aria-label": hasAria ? props.ariaLabel : undefined,
|
|
@@ -32912,15 +32871,13 @@ const LockedPolygon = props => {
|
|
|
32912
32871
|
};
|
|
32913
32872
|
|
|
32914
32873
|
const LockedVector = props => {
|
|
32915
|
-
var _flags$mafs;
|
|
32916
32874
|
const {
|
|
32917
32875
|
color,
|
|
32918
32876
|
points,
|
|
32919
|
-
ariaLabel
|
|
32920
|
-
flags
|
|
32877
|
+
ariaLabel
|
|
32921
32878
|
} = props;
|
|
32922
32879
|
const [tail, tip] = points;
|
|
32923
|
-
const hasAria = ariaLabel
|
|
32880
|
+
const hasAria = !!ariaLabel;
|
|
32924
32881
|
return /*#__PURE__*/React.createElement("g", {
|
|
32925
32882
|
className: "locked-vector",
|
|
32926
32883
|
"aria-label": hasAria ? ariaLabel : undefined,
|
|
@@ -32934,7 +32891,6 @@ const LockedVector = props => {
|
|
|
32934
32891
|
|
|
32935
32892
|
const GraphLockedLayer = props => {
|
|
32936
32893
|
const {
|
|
32937
|
-
flags,
|
|
32938
32894
|
lockedFigures
|
|
32939
32895
|
} = props;
|
|
32940
32896
|
return /*#__PURE__*/React.createElement(React.Fragment, null, lockedFigures.map((figure, index) => {
|
|
@@ -32942,40 +32898,28 @@ const GraphLockedLayer = props => {
|
|
|
32942
32898
|
case "point":
|
|
32943
32899
|
return /*#__PURE__*/React.createElement(LockedPoint, _extends({
|
|
32944
32900
|
key: `point-${index}`
|
|
32945
|
-
}, figure
|
|
32946
|
-
flags: flags
|
|
32947
|
-
}));
|
|
32901
|
+
}, figure));
|
|
32948
32902
|
case "line":
|
|
32949
32903
|
return /*#__PURE__*/React.createElement(LockedLine, _extends({
|
|
32950
32904
|
key: `line-${index}`,
|
|
32951
32905
|
range: props.range
|
|
32952
|
-
}, figure
|
|
32953
|
-
flags: flags
|
|
32954
|
-
}));
|
|
32906
|
+
}, figure));
|
|
32955
32907
|
case "vector":
|
|
32956
32908
|
return /*#__PURE__*/React.createElement(LockedVector, _extends({
|
|
32957
32909
|
key: `vector-${index}`
|
|
32958
|
-
}, figure
|
|
32959
|
-
flags: flags
|
|
32960
|
-
}));
|
|
32910
|
+
}, figure));
|
|
32961
32911
|
case "ellipse":
|
|
32962
32912
|
return /*#__PURE__*/React.createElement(LockedEllipse, _extends({
|
|
32963
32913
|
key: `ellipse-${index}`
|
|
32964
|
-
}, figure
|
|
32965
|
-
flags: flags
|
|
32966
|
-
}));
|
|
32914
|
+
}, figure));
|
|
32967
32915
|
case "polygon":
|
|
32968
32916
|
return /*#__PURE__*/React.createElement(LockedPolygon, _extends({
|
|
32969
32917
|
key: `polygon-${index}`
|
|
32970
|
-
}, figure
|
|
32971
|
-
flags: flags
|
|
32972
|
-
}));
|
|
32918
|
+
}, figure));
|
|
32973
32919
|
case "function":
|
|
32974
32920
|
return /*#__PURE__*/React.createElement(LockedFunction, _extends({
|
|
32975
32921
|
key: `function-${index}`
|
|
32976
|
-
}, figure
|
|
32977
|
-
flags: flags
|
|
32978
|
-
}));
|
|
32922
|
+
}, figure));
|
|
32979
32923
|
case "label":
|
|
32980
32924
|
// This is rendered outside the SVG element, since
|
|
32981
32925
|
// TeX cannot be rendered inside an SVG.
|
|
@@ -35446,7 +35390,6 @@ function useDraggablePx(args) {
|
|
|
35446
35390
|
* - Interactive Graph Elements
|
|
35447
35391
|
*/
|
|
35448
35392
|
const MafsGraph = props => {
|
|
35449
|
-
var _props$flags;
|
|
35450
35393
|
const {
|
|
35451
35394
|
state,
|
|
35452
35395
|
dispatch,
|
|
@@ -35583,11 +35526,9 @@ const MafsGraph = props => {
|
|
|
35583
35526
|
})),
|
|
35584
35527
|
// Only render the axis ticks and arrows if the markings are set to a full "graph"
|
|
35585
35528
|
props.markings === "graph" && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(AxisTicks, null), /*#__PURE__*/React.createElement(AxisArrows, null)), /*#__PURE__*/React.createElement("svg", nestedSVGAttributes, props.lockedFigures && /*#__PURE__*/React.createElement(GraphLockedLayer, {
|
|
35586
|
-
flags: props.flags,
|
|
35587
35529
|
lockedFigures: props.lockedFigures,
|
|
35588
35530
|
range: state.range
|
|
35589
|
-
}))),
|
|
35590
|
-
flags: props.flags,
|
|
35531
|
+
}))), props.lockedFigures && /*#__PURE__*/React.createElement(GraphLockedLabelsLayer, {
|
|
35591
35532
|
lockedFigures: props.lockedFigures
|
|
35592
35533
|
}), /*#__PURE__*/React.createElement(View, {
|
|
35593
35534
|
style: {
|
|
@@ -45560,7 +45501,7 @@ const init = function init() {
|
|
|
45560
45501
|
|
|
45561
45502
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
45562
45503
|
const libName = "@khanacademy/perseus";
|
|
45563
|
-
const libVersion = "49.2.
|
|
45504
|
+
const libVersion = "49.2.2";
|
|
45564
45505
|
addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
45565
45506
|
|
|
45566
45507
|
const apiVersion = {
|
|
@@ -47845,10 +47786,10 @@ class UnionBuilder {
|
|
|
47845
47786
|
this.parser = parser;
|
|
47846
47787
|
}
|
|
47847
47788
|
or(newBranch) {
|
|
47848
|
-
return new UnionBuilder(either
|
|
47789
|
+
return new UnionBuilder(either(this.parser, newBranch));
|
|
47849
47790
|
}
|
|
47850
47791
|
}
|
|
47851
|
-
function either
|
|
47792
|
+
function either(parseA, parseB) {
|
|
47852
47793
|
return (rawValue, ctx) => {
|
|
47853
47794
|
const resultA = parseA(rawValue, ctx);
|
|
47854
47795
|
if (isSuccess(resultA)) {
|
|
@@ -47901,9 +47842,9 @@ function parseWidgetWithVersion(parseVersion, parseType, parseOptions) {
|
|
|
47901
47842
|
const parseCategorizerWidget = parseWidget(constant("categorizer"), object({
|
|
47902
47843
|
items: array(string),
|
|
47903
47844
|
categories: array(string),
|
|
47904
|
-
randomizeItems: boolean,
|
|
47845
|
+
randomizeItems: defaulted(boolean, () => false),
|
|
47905
47846
|
static: defaulted(boolean, () => false),
|
|
47906
|
-
values: array(number),
|
|
47847
|
+
values: array(defaulted(number, () => 0)),
|
|
47907
47848
|
highlightLint: optional(boolean),
|
|
47908
47849
|
linterContext: optional(object({
|
|
47909
47850
|
contentType: string,
|
|
@@ -47923,7 +47864,7 @@ const parseCSProgramWidget = parseWidget(constant("cs-program"), object({
|
|
|
47923
47864
|
showButtons: boolean,
|
|
47924
47865
|
width: number,
|
|
47925
47866
|
height: number,
|
|
47926
|
-
static: boolean
|
|
47867
|
+
static: defaulted(boolean, () => false)
|
|
47927
47868
|
}));
|
|
47928
47869
|
|
|
47929
47870
|
const parseDefinitionWidget = parseWidget(constant("definition"), object({
|
|
@@ -47933,7 +47874,7 @@ const parseDefinitionWidget = parseWidget(constant("definition"), object({
|
|
|
47933
47874
|
}));
|
|
47934
47875
|
|
|
47935
47876
|
const parseDropdownWidget = parseWidget(constant("dropdown"), object({
|
|
47936
|
-
placeholder: string,
|
|
47877
|
+
placeholder: defaulted(string, () => ""),
|
|
47937
47878
|
ariaLabel: optional(string),
|
|
47938
47879
|
visibleLabel: optional(string),
|
|
47939
47880
|
static: defaulted(boolean, () => false),
|
|
@@ -47966,60 +47907,63 @@ function convert(f) {
|
|
|
47966
47907
|
* data does not match any of the versions.
|
|
47967
47908
|
*
|
|
47968
47909
|
* @example
|
|
47969
|
-
* const parseOptions = versionedWidgetOptions(parseOptionsV3)
|
|
47970
|
-
* .withMigrationFrom(parseOptionsV2, migrateV2ToV3)
|
|
47971
|
-
* .withMigrationFrom(parseOptionsV1, migrateV1ToV2)
|
|
47972
|
-
* .withMigrationFrom(parseOptionsV0, migrateV0ToV1)
|
|
47910
|
+
* const parseOptions = versionedWidgetOptions(3, parseOptionsV3)
|
|
47911
|
+
* .withMigrationFrom(2, parseOptionsV2, migrateV2ToV3)
|
|
47912
|
+
* .withMigrationFrom(1, parseOptionsV1, migrateV1ToV2)
|
|
47913
|
+
* .withMigrationFrom(0, parseOptionsV0, migrateV0ToV1)
|
|
47973
47914
|
* .parser;
|
|
47974
47915
|
*
|
|
47916
|
+
* @param latestMajorVersion the latest major version of the widget options.
|
|
47975
47917
|
* @param parseLatest a {@link Parser} for the latest version of the widget
|
|
47976
|
-
* options.
|
|
47977
|
-
* version.
|
|
47918
|
+
* options.
|
|
47978
47919
|
* @returns a builder object, to which migrations from earlier versions can be
|
|
47979
47920
|
* added. Migrations must be added in "reverse chronological" order as in the
|
|
47980
47921
|
* example above.
|
|
47981
47922
|
*/
|
|
47982
|
-
function versionedWidgetOptions(parseLatest) {
|
|
47983
|
-
return new VersionedWidgetOptionsParserBuilder(parseLatest, latest => latest);
|
|
47923
|
+
function versionedWidgetOptions(latestMajorVersion, parseLatest) {
|
|
47924
|
+
return new VersionedWidgetOptionsParserBuilder(latestMajorVersion, parseLatest, latest => latest, (raw, ctx) => ctx.failure("widget options with a known version number", raw));
|
|
47984
47925
|
}
|
|
47985
47926
|
class VersionedWidgetOptionsParserBuilder {
|
|
47986
|
-
constructor(
|
|
47987
|
-
this.parser =
|
|
47988
|
-
this.
|
|
47927
|
+
constructor(majorVersion, parseThisVersion, migrateToLatest, parseOtherVersions) {
|
|
47928
|
+
this.parser = void 0;
|
|
47929
|
+
this.migrateToLatest = migrateToLatest;
|
|
47930
|
+
this.parseOtherVersions = parseOtherVersions;
|
|
47931
|
+
const parseThisVersionAndMigrateToLatest = pipeParsers(parseThisVersion).then(convert(this.migrateToLatest)).parser;
|
|
47932
|
+
this.parser = (raw, ctx) => {
|
|
47933
|
+
if (!isObject(raw)) {
|
|
47934
|
+
return ctx.failure("object", raw);
|
|
47935
|
+
}
|
|
47936
|
+
const versionParseResult = parseVersionedObject(raw, ctx);
|
|
47937
|
+
if (isFailure(versionParseResult)) {
|
|
47938
|
+
return versionParseResult;
|
|
47939
|
+
}
|
|
47940
|
+
if (versionParseResult.value.version.major !== majorVersion) {
|
|
47941
|
+
return this.parseOtherVersions(raw, ctx);
|
|
47942
|
+
}
|
|
47943
|
+
return parseThisVersionAndMigrateToLatest(raw, ctx);
|
|
47944
|
+
};
|
|
47989
47945
|
}
|
|
47990
47946
|
|
|
47991
47947
|
/**
|
|
47992
47948
|
* Add a migration from an old version of the widget options.
|
|
47993
|
-
*
|
|
47994
|
-
* @returns a VersionedWidgetOptionsParserBuilder whose `parser` function
|
|
47995
|
-
* is capable of migrating the old version to the latest version. The parser
|
|
47996
|
-
* will always return the latest version of the widget options on a
|
|
47997
|
-
* successful parse.
|
|
47998
|
-
* @param parseOldVersion should be a {@link Parser} for the old options
|
|
47999
|
-
* type. It should fail if version.major isn't correct.
|
|
48000
|
-
* @param migrateToNextVersion should migrate the `Old` data to the
|
|
48001
|
-
* `Migratable` version of the current VersionedWidgetOptionsParserBuilder.
|
|
48002
|
-
* Usually, this means migrating to the next major version.
|
|
48003
47949
|
*/
|
|
48004
|
-
withMigrationFrom(parseOldVersion, migrateToNextVersion) {
|
|
48005
|
-
const
|
|
48006
|
-
const migrateToLatest = old => this.
|
|
48007
|
-
return new VersionedWidgetOptionsParserBuilder(
|
|
48008
|
-
const resultOfParsingLatest = parseLatestVersion(raw, ctx);
|
|
48009
|
-
if (isSuccess(resultOfParsingLatest)) {
|
|
48010
|
-
return resultOfParsingLatest;
|
|
48011
|
-
}
|
|
48012
|
-
const resultOfParsingOld = parseOldVersion(raw, ctx);
|
|
48013
|
-
if (isSuccess(resultOfParsingOld)) {
|
|
48014
|
-
return success(migrateToLatest(resultOfParsingOld.value));
|
|
48015
|
-
}
|
|
48016
|
-
|
|
48017
|
-
// If we're here, neither parse succeeded. Return the failure.
|
|
48018
|
-
return resultOfParsingOld;
|
|
48019
|
-
}, migrateToLatest);
|
|
47950
|
+
withMigrationFrom(majorVersion, parseOldVersion, migrateToNextVersion) {
|
|
47951
|
+
const parseOtherVersions = this.parser;
|
|
47952
|
+
const migrateToLatest = old => this.migrateToLatest(migrateToNextVersion(old));
|
|
47953
|
+
return new VersionedWidgetOptionsParserBuilder(majorVersion, parseOldVersion, migrateToLatest, parseOtherVersions);
|
|
48020
47954
|
}
|
|
48021
47955
|
}
|
|
47956
|
+
const parseVersionedObject = object({
|
|
47957
|
+
version: defaulted(object({
|
|
47958
|
+
major: number,
|
|
47959
|
+
minor: number
|
|
47960
|
+
}), () => ({
|
|
47961
|
+
major: 0,
|
|
47962
|
+
minor: 0
|
|
47963
|
+
}))
|
|
47964
|
+
});
|
|
48022
47965
|
|
|
47966
|
+
const stringOrNumberOrNullOrUndefined = union(string).or(number).or(constant(null)).or(constant(undefined)).parser;
|
|
48023
47967
|
const parsePossiblyInvalidAnswerForm = object({
|
|
48024
47968
|
// `value` is the possibly invalid part of this. It should always be a
|
|
48025
47969
|
// string, but some answer forms don't have it. The Expression widget
|
|
@@ -48028,7 +47972,7 @@ const parsePossiblyInvalidAnswerForm = object({
|
|
|
48028
47972
|
form: defaulted(boolean, () => false),
|
|
48029
47973
|
simplify: defaulted(boolean, () => false),
|
|
48030
47974
|
considered: enumeration("correct", "wrong", "ungraded"),
|
|
48031
|
-
key: pipeParsers(
|
|
47975
|
+
key: pipeParsers(stringOrNumberOrNullOrUndefined).then(convert(String)).parser
|
|
48032
47976
|
});
|
|
48033
47977
|
function removeInvalidAnswerForms(possiblyInvalid) {
|
|
48034
47978
|
const valid = [];
|
|
@@ -48045,6 +47989,11 @@ function removeInvalidAnswerForms(possiblyInvalid) {
|
|
|
48045
47989
|
}
|
|
48046
47990
|
return valid;
|
|
48047
47991
|
}
|
|
47992
|
+
|
|
47993
|
+
// NOTE(benchristel): I copied the default buttonSets from
|
|
47994
|
+
// expression.tsx. See the parse-perseus-json/README.md for
|
|
47995
|
+
// an explanation of why we want to duplicate the default here.
|
|
47996
|
+
const parseButtonSets = defaulted(array(enumeration("basic", "basic+div", "trig", "prealgebra", "logarithms", "basic relations", "advanced relations")), () => ["basic", "trig", "prealgebra", "logarithms"]);
|
|
48048
47997
|
const version1 = object({
|
|
48049
47998
|
major: constant(1),
|
|
48050
47999
|
minor: number
|
|
@@ -48055,7 +48004,7 @@ const parseExpressionWidgetV1 = parseWidgetWithVersion(version1, constant("expre
|
|
|
48055
48004
|
times: boolean,
|
|
48056
48005
|
visibleLabel: optional(string),
|
|
48057
48006
|
ariaLabel: optional(string),
|
|
48058
|
-
buttonSets:
|
|
48007
|
+
buttonSets: parseButtonSets,
|
|
48059
48008
|
buttonsVisible: optional(enumeration("always", "never", "focused"))
|
|
48060
48009
|
}));
|
|
48061
48010
|
const version0 = optional(object({
|
|
@@ -48070,7 +48019,7 @@ const parseExpressionWidgetV0 = parseWidgetWithVersion(version0, constant("expre
|
|
|
48070
48019
|
form: boolean,
|
|
48071
48020
|
simplify: boolean,
|
|
48072
48021
|
value: string,
|
|
48073
|
-
buttonSets:
|
|
48022
|
+
buttonSets: parseButtonSets,
|
|
48074
48023
|
buttonsVisible: optional(enumeration("always", "never", "focused"))
|
|
48075
48024
|
}));
|
|
48076
48025
|
function migrateV0ToV1(widget) {
|
|
@@ -48098,7 +48047,7 @@ function migrateV0ToV1(widget) {
|
|
|
48098
48047
|
}
|
|
48099
48048
|
});
|
|
48100
48049
|
}
|
|
48101
|
-
const parseExpressionWidget = versionedWidgetOptions(parseExpressionWidgetV1).withMigrationFrom(parseExpressionWidgetV0, migrateV0ToV1).parser;
|
|
48050
|
+
const parseExpressionWidget = versionedWidgetOptions(1, parseExpressionWidgetV1).withMigrationFrom(0, parseExpressionWidgetV0, migrateV0ToV1).parser;
|
|
48102
48051
|
|
|
48103
48052
|
const parsePerseusRenderer = defaulted(object({
|
|
48104
48053
|
// TODO(benchristel): content is also defaulted to empty string in
|
|
@@ -48119,13 +48068,14 @@ const parsePerseusRenderer = defaulted(object({
|
|
|
48119
48068
|
images: {}
|
|
48120
48069
|
}));
|
|
48121
48070
|
|
|
48071
|
+
const falseToNull = pipeParsers(constant(false)).then(convert(() => null)).parser;
|
|
48122
48072
|
const parseGradedGroupWidgetOptions = object({
|
|
48123
48073
|
title: defaulted(string, () => ""),
|
|
48124
48074
|
hasHint: optional(nullable(boolean)),
|
|
48125
48075
|
// This module has an import cycle with parsePerseusRenderer.
|
|
48126
48076
|
// The anonymous function below ensures that we don't try to access
|
|
48127
48077
|
// parsePerseusRenderer before it's defined.
|
|
48128
|
-
hint:
|
|
48078
|
+
hint: union(falseToNull).or(constant(null)).or(constant(undefined)).or((rawVal, ctx) => parsePerseusRenderer(rawVal, ctx)).parser,
|
|
48129
48079
|
content: string,
|
|
48130
48080
|
// This module has an import cycle with parseWidgetsMap.
|
|
48131
48081
|
// The anonymous function below ensures that we don't try to access
|
|
@@ -48144,28 +48094,41 @@ const parseGradedGroupSetWidget = parseWidget(constant("graded-group-set"), obje
|
|
|
48144
48094
|
gradedGroups: array(parseGradedGroupWidgetOptions)
|
|
48145
48095
|
}));
|
|
48146
48096
|
|
|
48147
|
-
|
|
48148
|
-
|
|
48149
|
-
|
|
48150
|
-
|
|
48151
|
-
|
|
48152
|
-
|
|
48153
|
-
|
|
48097
|
+
/**
|
|
48098
|
+
* discriminatedUnion() should be preferred over union() when parsing a
|
|
48099
|
+
* discriminated union type, because discriminatedUnion() produces more
|
|
48100
|
+
* understandable failure messages. It takes the discriminant as the source of
|
|
48101
|
+
* truth for which variant is to be parsed, and expects the other data to match
|
|
48102
|
+
* that variant.
|
|
48103
|
+
*/
|
|
48104
|
+
function discriminatedUnionOn(discriminantKey) {
|
|
48105
|
+
const noMoreBranches = (raw, ctx) => {
|
|
48106
|
+
if (!isObject(raw)) {
|
|
48107
|
+
return ctx.failure("object", raw);
|
|
48108
|
+
}
|
|
48109
|
+
return ctx.forSubtree(discriminantKey).failure("a valid value", raw[discriminantKey]);
|
|
48110
|
+
};
|
|
48111
|
+
return new DiscriminatedUnionBuilder(discriminantKey, noMoreBranches);
|
|
48154
48112
|
}
|
|
48155
48113
|
class DiscriminatedUnionBuilder {
|
|
48156
|
-
constructor(parser) {
|
|
48114
|
+
constructor(discriminantKey, parser) {
|
|
48115
|
+
this.discriminantKey = discriminantKey;
|
|
48157
48116
|
this.parser = parser;
|
|
48158
48117
|
}
|
|
48159
|
-
|
|
48160
|
-
|
|
48118
|
+
withBranch(discriminantValue, parseNewVariant) {
|
|
48119
|
+
const parseNewBranch = discriminatedUnionBranch(this.discriminantKey, discriminantValue, parseNewVariant, this.parser);
|
|
48120
|
+
return new DiscriminatedUnionBuilder(this.discriminantKey, parseNewBranch);
|
|
48161
48121
|
}
|
|
48162
48122
|
}
|
|
48163
|
-
function
|
|
48164
|
-
return (
|
|
48165
|
-
if (
|
|
48166
|
-
return
|
|
48123
|
+
function discriminatedUnionBranch(discriminantKey, discriminantValue, parseVariant, parseOtherBranches) {
|
|
48124
|
+
return (raw, ctx) => {
|
|
48125
|
+
if (!isObject(raw)) {
|
|
48126
|
+
return ctx.failure("object", raw);
|
|
48167
48127
|
}
|
|
48168
|
-
|
|
48128
|
+
if (raw[discriminantKey] === discriminantValue) {
|
|
48129
|
+
return parseVariant(raw, ctx);
|
|
48130
|
+
}
|
|
48131
|
+
return parseOtherBranches(raw, ctx);
|
|
48169
48132
|
};
|
|
48170
48133
|
}
|
|
48171
48134
|
|
|
@@ -48173,41 +48136,27 @@ const pairOfNumbers$3 = pair(number, number);
|
|
|
48173
48136
|
const pairOfPoints = pair(pairOfNumbers$3, pairOfNumbers$3);
|
|
48174
48137
|
const parseGrapherWidget = parseWidget(constant("grapher"), object({
|
|
48175
48138
|
availableTypes: array(enumeration("absolute_value", "exponential", "linear", "logarithm", "quadratic", "sinusoid", "tangent")),
|
|
48176
|
-
correct:
|
|
48177
|
-
type: constant("absolute_value")
|
|
48178
|
-
}), object({
|
|
48139
|
+
correct: discriminatedUnionOn("type").withBranch("absolute_value", object({
|
|
48179
48140
|
type: constant("absolute_value"),
|
|
48180
48141
|
coords: pairOfPoints
|
|
48181
|
-
})).
|
|
48182
|
-
type: constant("exponential")
|
|
48183
|
-
}), object({
|
|
48142
|
+
})).withBranch("exponential", object({
|
|
48184
48143
|
type: constant("exponential"),
|
|
48185
48144
|
asymptote: pairOfPoints,
|
|
48186
48145
|
coords: pairOfPoints
|
|
48187
|
-
})).
|
|
48188
|
-
type: constant("linear")
|
|
48189
|
-
}), object({
|
|
48146
|
+
})).withBranch("linear", object({
|
|
48190
48147
|
type: constant("linear"),
|
|
48191
|
-
coords: pairOfPoints
|
|
48192
|
-
})).
|
|
48193
|
-
type: constant("logarithm")
|
|
48194
|
-
}), object({
|
|
48148
|
+
coords: defaulted(pairOfPoints, () => [[-5, 5], [5, 5]])
|
|
48149
|
+
})).withBranch("logarithm", object({
|
|
48195
48150
|
type: constant("logarithm"),
|
|
48196
48151
|
asymptote: pairOfPoints,
|
|
48197
48152
|
coords: pairOfPoints
|
|
48198
|
-
})).
|
|
48199
|
-
type: constant("quadratic")
|
|
48200
|
-
}), object({
|
|
48153
|
+
})).withBranch("quadratic", object({
|
|
48201
48154
|
type: constant("quadratic"),
|
|
48202
48155
|
coords: pairOfPoints
|
|
48203
|
-
})).
|
|
48204
|
-
type: constant("sinusoid")
|
|
48205
|
-
}), object({
|
|
48156
|
+
})).withBranch("sinusoid", object({
|
|
48206
48157
|
type: constant("sinusoid"),
|
|
48207
48158
|
coords: pairOfPoints
|
|
48208
|
-
})).
|
|
48209
|
-
type: constant("tangent")
|
|
48210
|
-
}), object({
|
|
48159
|
+
})).withBranch("tangent", object({
|
|
48211
48160
|
type: constant("tangent"),
|
|
48212
48161
|
coords: pairOfPoints
|
|
48213
48162
|
})).parser,
|
|
@@ -48455,23 +48404,7 @@ const parseInteractionWidget = parseWidget(constant("interaction"), object({
|
|
|
48455
48404
|
rulerTicks: optional(number),
|
|
48456
48405
|
tickStep: pairOfNumbers$1
|
|
48457
48406
|
}),
|
|
48458
|
-
elements: array(
|
|
48459
|
-
type: parseFunctionType
|
|
48460
|
-
}), parseFunctionElement).or(object({
|
|
48461
|
-
type: parseLabelType
|
|
48462
|
-
}), parseLabelElement).or(object({
|
|
48463
|
-
type: parseLineType
|
|
48464
|
-
}), parseLineElement).or(object({
|
|
48465
|
-
type: parseMovableLineType
|
|
48466
|
-
}), parseMovableLineElement).or(object({
|
|
48467
|
-
type: parseMovablePointType
|
|
48468
|
-
}), parseMovablePointElement).or(object({
|
|
48469
|
-
type: parseParametricType
|
|
48470
|
-
}), parseParametricElement).or(object({
|
|
48471
|
-
type: parsePointType
|
|
48472
|
-
}), parsePointElement).or(object({
|
|
48473
|
-
type: parseRectangleType
|
|
48474
|
-
}), parseRectangleElement).parser)
|
|
48407
|
+
elements: array(discriminatedUnionOn("type").withBranch("function", parseFunctionElement).withBranch("label", parseLabelElement).withBranch("line", parseLineElement).withBranch("movable-line", parseMovableLineElement).withBranch("movable-point", parseMovablePointElement).withBranch("parametric", parseParametricElement).withBranch("point", parsePointElement).withBranch("rectangle", parseRectangleElement).parser)
|
|
48475
48408
|
}));
|
|
48476
48409
|
|
|
48477
48410
|
// Used to represent 2-D points and ranges
|
|
@@ -48529,7 +48462,7 @@ const parsePerseusGraphTypePolygon = object({
|
|
|
48529
48462
|
showAngles: optional(boolean),
|
|
48530
48463
|
showSides: optional(boolean),
|
|
48531
48464
|
snapTo: optional(enumeration("grid", "angles", "sides")),
|
|
48532
|
-
match: optional(enumeration("similar", "congruent", "approx")),
|
|
48465
|
+
match: optional(enumeration("similar", "congruent", "approx", "exact")),
|
|
48533
48466
|
startCoords: optional(array(pairOfNumbers)),
|
|
48534
48467
|
// TODO: remove coord? it's legacy.
|
|
48535
48468
|
coord: optional(pairOfNumbers)
|
|
@@ -48564,7 +48497,7 @@ const parsePerseusGraphTypeSinusoid = object({
|
|
|
48564
48497
|
// TODO: remove coord? it's legacy.
|
|
48565
48498
|
coord: optional(pairOfNumbers)
|
|
48566
48499
|
});
|
|
48567
|
-
const parsePerseusGraphType =
|
|
48500
|
+
const parsePerseusGraphType = discriminatedUnionOn("type").withBranch("angle", parsePerseusGraphTypeAngle).withBranch("circle", parsePerseusGraphTypeCircle).withBranch("linear", parsePerseusGraphTypeLinear).withBranch("linear-system", parsePerseusGraphTypeLinearSystem).withBranch("none", parsePerseusGraphTypeNone).withBranch("point", parsePerseusGraphTypePoint).withBranch("polygon", parsePerseusGraphTypePolygon).withBranch("quadratic", parsePerseusGraphTypeQuadratic).withBranch("ray", parsePerseusGraphTypeRay).withBranch("segment", parsePerseusGraphTypeSegment).withBranch("sinusoid", parsePerseusGraphTypeSinusoid).parser;
|
|
48568
48501
|
const parseLockedFigureColor = enumeration(...lockedFigureColorNames);
|
|
48569
48502
|
const parseLockedFigureFillType = enumeration("none", "white", "translucent", "solid");
|
|
48570
48503
|
const parseLockedLineStyle = enumeration("solid", "dashed");
|
|
@@ -48683,7 +48616,7 @@ const parseLabelImageWidget = parseWidget(constant("label-image"), object({
|
|
|
48683
48616
|
})),
|
|
48684
48617
|
hideChoicesFromInstructions: boolean,
|
|
48685
48618
|
multipleAnswers: boolean,
|
|
48686
|
-
static: boolean
|
|
48619
|
+
static: defaulted(boolean, () => false)
|
|
48687
48620
|
}));
|
|
48688
48621
|
|
|
48689
48622
|
const parseMatcherWidget = parseWidget(constant("matcher"), object({
|
|
@@ -48694,7 +48627,8 @@ const parseMatcherWidget = parseWidget(constant("matcher"), object({
|
|
|
48694
48627
|
padding: boolean
|
|
48695
48628
|
}));
|
|
48696
48629
|
|
|
48697
|
-
const
|
|
48630
|
+
const numberOrString = union(number).or(string).parser;
|
|
48631
|
+
const numeric = pipeParsers(defaulted(numberOrString, () => NaN)).then(stringToNumber).parser;
|
|
48698
48632
|
const parseMatrixWidget = parseWidget(defaulted(constant("matrix"), () => "matrix"), object({
|
|
48699
48633
|
prefix: optional(string),
|
|
48700
48634
|
suffix: optional(string),
|
|
@@ -48713,7 +48647,8 @@ const parseMeasurerWidget = parseWidget(constant("measurer"), object({
|
|
|
48713
48647
|
rulerPixels: number,
|
|
48714
48648
|
rulerLength: number,
|
|
48715
48649
|
box: pair(number, number),
|
|
48716
|
-
|
|
48650
|
+
// TODO(benchristel): static is not used. Remove it?
|
|
48651
|
+
static: defaulted(boolean, () => false)
|
|
48717
48652
|
}));
|
|
48718
48653
|
|
|
48719
48654
|
const parseMoleculeRendererWidget = parseWidget(constant("molecule-renderer"), object({
|
|
@@ -48722,9 +48657,10 @@ const parseMoleculeRendererWidget = parseWidget(constant("molecule-renderer"), o
|
|
|
48722
48657
|
smiles: optional(string)
|
|
48723
48658
|
}));
|
|
48724
48659
|
|
|
48660
|
+
const emptyStringToNull = pipeParsers(constant("")).then(convert(() => null)).parser;
|
|
48725
48661
|
const parseNumberLineWidget = parseWidget(constant("number-line"), object({
|
|
48726
48662
|
range: array(number),
|
|
48727
|
-
labelRange: array(nullable(number)),
|
|
48663
|
+
labelRange: array(nullable(union(number).or(emptyStringToNull).parser)),
|
|
48728
48664
|
labelStyle: string,
|
|
48729
48665
|
labelTicks: boolean,
|
|
48730
48666
|
isTickCtrl: optional(nullable(boolean)),
|
|
@@ -48736,10 +48672,10 @@ const parseNumberLineWidget = parseWidget(constant("number-line"), object({
|
|
|
48736
48672
|
snapDivisions: defaulted(number, () => 2),
|
|
48737
48673
|
tickStep: optional(nullable(number)),
|
|
48738
48674
|
correctRel: optional(nullable(string)),
|
|
48739
|
-
correctX: number,
|
|
48675
|
+
correctX: nullable(number),
|
|
48740
48676
|
initialX: optional(nullable(number)),
|
|
48741
48677
|
showTooltip: optional(boolean),
|
|
48742
|
-
static: boolean
|
|
48678
|
+
static: defaulted(boolean, () => false)
|
|
48743
48679
|
}));
|
|
48744
48680
|
|
|
48745
48681
|
const parseMathFormat = enumeration("integer", "mixed", "improper", "proper", "decimal", "percent", "pi");
|
|
@@ -48754,14 +48690,14 @@ const parseNumericInputWidget = parseWidget(constant("numeric-input"), object({
|
|
|
48754
48690
|
answerForms: optional(array(parseMathFormat)),
|
|
48755
48691
|
strict: boolean,
|
|
48756
48692
|
maxError: optional(nullable(number)),
|
|
48757
|
-
// TODO(benchristel): simplify should never be
|
|
48693
|
+
// TODO(benchristel): simplify should never be a boolean, but we
|
|
48758
48694
|
// have some content where it is anyway. If we ever backfill
|
|
48759
48695
|
// the data, we should simplify `simplify`.
|
|
48760
|
-
simplify: optional(nullable(union(string).or(pipeParsers(
|
|
48696
|
+
simplify: optional(nullable(union(string).or(pipeParsers(boolean).then(convert(String)).parser).parser))
|
|
48761
48697
|
})),
|
|
48762
48698
|
labelText: optional(string),
|
|
48763
48699
|
size: string,
|
|
48764
|
-
coefficient: boolean,
|
|
48700
|
+
coefficient: defaulted(boolean, () => false),
|
|
48765
48701
|
rightAlign: optional(boolean),
|
|
48766
48702
|
static: defaulted(boolean, () => false),
|
|
48767
48703
|
answerForms: optional(array(object({
|
|
@@ -48797,9 +48733,9 @@ const parsePassageRefWidget = parseWidget(constant("passage-ref"), object({
|
|
|
48797
48733
|
}));
|
|
48798
48734
|
|
|
48799
48735
|
const parsePassageWidget = parseWidget(constant("passage"), object({
|
|
48800
|
-
footnotes: string,
|
|
48736
|
+
footnotes: defaulted(string, () => ""),
|
|
48801
48737
|
passageText: string,
|
|
48802
|
-
passageTitle: string,
|
|
48738
|
+
passageTitle: defaulted(string, () => ""),
|
|
48803
48739
|
showLineNumbers: boolean,
|
|
48804
48740
|
static: defaulted(boolean, () => false)
|
|
48805
48741
|
}));
|
|
@@ -48983,6 +48919,10 @@ const parseWidgetsMapEntry = ([key, widget], widgetMap, ctx) => {
|
|
|
48983
48919
|
return parseAndAssign(`sequence ${id}`, parseDeprecatedWidget);
|
|
48984
48920
|
case "lights-puzzle":
|
|
48985
48921
|
return parseAndAssign(`lights-puzzle ${id}`, parseDeprecatedWidget);
|
|
48922
|
+
case "simulator":
|
|
48923
|
+
return parseAndAssign(`simulator ${id}`, parseDeprecatedWidget);
|
|
48924
|
+
case "transformer":
|
|
48925
|
+
return parseAndAssign(`transformer ${id}`, parseDeprecatedWidget);
|
|
48986
48926
|
default:
|
|
48987
48927
|
if (getWidget(type)) {
|
|
48988
48928
|
// @ts-expect-error - 'type' is not a valid widget type
|