@khanacademy/perseus 36.1.2 → 37.0.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/all-widgets.d.ts +1 -0
- package/dist/basic-widgets.d.ts +1 -0
- package/dist/components/math-input.d.ts +1 -1
- package/dist/es/index.js +447 -612
- package/dist/es/index.js.map +1 -1
- package/dist/extra-widgets.d.ts +1 -0
- package/dist/index.js +412 -588
- package/dist/index.js.map +1 -1
- package/dist/renderer-util.d.ts +8 -0
- package/dist/renderer.d.ts +19 -20
- package/dist/server-item-renderer.d.ts +3 -1
- package/dist/types.d.ts +11 -3
- package/dist/util.d.ts +4 -0
- package/dist/validation.types.d.ts +14 -6
- package/dist/widgets/categorizer/categorizer.d.ts +3 -5
- package/dist/widgets/cs-program/cs-program.d.ts +2 -3
- package/dist/widgets/definition/definition.d.ts +3 -4
- package/dist/widgets/deprecated-standin/deprecated-standin.d.ts +35 -0
- package/dist/widgets/deprecated-standin/index.d.ts +1 -37
- package/dist/widgets/dropdown/dropdown.d.ts +2 -3
- package/dist/widgets/explanation/explanation.d.ts +4 -5
- package/dist/widgets/expression/expression.d.ts +4 -8
- package/dist/widgets/graded-group/graded-group.d.ts +1 -0
- package/dist/widgets/graded-group-set/graded-group-set.d.ts +1 -0
- package/dist/widgets/grapher/grapher.d.ts +2 -3
- package/dist/widgets/group/group.d.ts +8 -5
- package/dist/widgets/iframe/iframe.d.ts +2 -3
- package/dist/widgets/image/image.d.ts +3 -4
- package/dist/widgets/input-number/input-number.d.ts +2 -5
- package/dist/widgets/interaction/interaction.d.ts +3 -4
- package/dist/widgets/interactive-graph.d.ts +2 -4
- package/dist/widgets/label-image/label-image.d.ts +3 -4
- package/dist/widgets/matcher/matcher.d.ts +2 -3
- package/dist/widgets/matrix/matrix.d.ts +3 -5
- package/dist/widgets/measurer/measurer.d.ts +2 -4
- package/dist/widgets/molecule/molecule.d.ts +2 -4
- package/dist/widgets/number-line/number-line.d.ts +3 -4
- package/dist/widgets/numeric-input/numeric-input.d.ts +2 -3
- package/dist/widgets/orderer/orderer.d.ts +2 -3
- package/dist/widgets/passage/passage.d.ts +3 -9
- package/dist/widgets/passage-ref/passage-ref.d.ts +3 -4
- package/dist/widgets/passage-ref-target/passage-ref-target.d.ts +2 -4
- package/dist/widgets/phet-simulation/phet-simulation.d.ts +2 -2
- package/dist/widgets/plotter/plotter.d.ts +2 -3
- package/dist/widgets/python-program/python-program.d.ts +1 -0
- package/dist/widgets/radio/radio-component.d.ts +2 -5
- package/dist/widgets/radio/radio.d.ts +1 -0
- package/dist/widgets/sorter/sorter.d.ts +2 -3
- package/dist/widgets/table/table.d.ts +3 -5
- package/dist/widgets/video/video.d.ts +2 -8
- package/dist/widgets.d.ts +2 -1
- package/package.json +2 -2
- package/dist/widgets/expression/expression.types.d.ts +0 -2
package/dist/es/index.js
CHANGED
|
@@ -53,16 +53,6 @@ function _extends() {
|
|
|
53
53
|
}, _extends.apply(null, arguments);
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
function _objectWithoutPropertiesLoose(r, e) {
|
|
57
|
-
if (null == r) return {};
|
|
58
|
-
var t = {};
|
|
59
|
-
for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
|
|
60
|
-
if (e.includes(n)) continue;
|
|
61
|
-
t[n] = r[n];
|
|
62
|
-
}
|
|
63
|
-
return t;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
56
|
/**
|
|
67
57
|
* The translated strings that are used to render Perseus.
|
|
68
58
|
*/
|
|
@@ -2258,7 +2248,6 @@ function expressionValidator(userInput, rubric, strings, locale) {
|
|
|
2258
2248
|
};
|
|
2259
2249
|
}
|
|
2260
2250
|
|
|
2261
|
-
const _excluded$5 = ["scoring"];
|
|
2262
2251
|
// Map of international operator names to their English equivalents
|
|
2263
2252
|
const englishOperators = {
|
|
2264
2253
|
arctg: "arctan",
|
|
@@ -2281,13 +2270,6 @@ const anglicizeOperators = tex => {
|
|
|
2281
2270
|
const normalizeTex = tex => {
|
|
2282
2271
|
return anglicizeOperators(tex);
|
|
2283
2272
|
};
|
|
2284
|
-
const deriveKeypadVersion = apiOptions => {
|
|
2285
|
-
// We can derive which version of the keypad is in use. This is
|
|
2286
|
-
// a bit tricky, but this code will be relatively short-lived
|
|
2287
|
-
// as we coalesce onto the new, v2 Keypad, at which point we
|
|
2288
|
-
// can remove this `virtualKeypadVersion` field entirely.
|
|
2289
|
-
return apiOptions.nativeKeypadProxy != null ? "REACT_NATIVE_KEYPAD" : "MATH_INPUT_KEYPAD_V2";
|
|
2290
|
-
};
|
|
2291
2273
|
// The new, MathQuill input expression widget
|
|
2292
2274
|
class Expression extends React.Component {
|
|
2293
2275
|
constructor(..._args) {
|
|
@@ -2346,27 +2328,6 @@ class Expression extends React.Component {
|
|
|
2346
2328
|
});
|
|
2347
2329
|
}
|
|
2348
2330
|
};
|
|
2349
|
-
this.simpleValidate = _ref => {
|
|
2350
|
-
let {
|
|
2351
|
-
scoring
|
|
2352
|
-
} = _ref,
|
|
2353
|
-
rubric = _objectWithoutPropertiesLoose(_ref, _excluded$5);
|
|
2354
|
-
const score = expressionValidator(this.getUserInput(), rubric, this.context.strings, this.context.locale);
|
|
2355
|
-
|
|
2356
|
-
// "scoring" is a flag that indicates when we are checking answers.
|
|
2357
|
-
// otherwise, we may just be checking validity after changes.
|
|
2358
|
-
if (scoring && score.type !== "invalid") {
|
|
2359
|
-
var _this$props$analytics;
|
|
2360
|
-
(_this$props$analytics = this.props.analytics) == null || _this$props$analytics.onAnalyticsEvent({
|
|
2361
|
-
type: "perseus:expression-evaluated",
|
|
2362
|
-
payload: {
|
|
2363
|
-
result: score.earned === score.total ? "correct" : "incorrect",
|
|
2364
|
-
virtualKeypadVersion: deriveKeypadVersion(this.props.apiOptions)
|
|
2365
|
-
}
|
|
2366
|
-
});
|
|
2367
|
-
}
|
|
2368
|
-
return score;
|
|
2369
|
-
};
|
|
2370
2331
|
this.change = (...args) => {
|
|
2371
2332
|
return change.apply(this, args);
|
|
2372
2333
|
};
|
|
@@ -2384,8 +2345,8 @@ class Expression extends React.Component {
|
|
|
2384
2345
|
this.props.trackInteraction();
|
|
2385
2346
|
};
|
|
2386
2347
|
this._handleFocus = () => {
|
|
2387
|
-
var _this$props$
|
|
2388
|
-
(_this$props$
|
|
2348
|
+
var _this$props$analytics;
|
|
2349
|
+
(_this$props$analytics = this.props.analytics) == null || _this$props$analytics.onAnalyticsEvent({
|
|
2389
2350
|
type: "perseus:expression-focused",
|
|
2390
2351
|
payload: null
|
|
2391
2352
|
});
|
|
@@ -2412,10 +2373,6 @@ class Expression extends React.Component {
|
|
|
2412
2373
|
return [[]];
|
|
2413
2374
|
};
|
|
2414
2375
|
}
|
|
2415
|
-
// TODO remove this in favor of just using expressionValidator
|
|
2416
|
-
static validate(userInput, rubric, strings, locale) {
|
|
2417
|
-
return expressionValidator(userInput, rubric, strings, locale);
|
|
2418
|
-
}
|
|
2419
2376
|
static getUserInputFromProps(props) {
|
|
2420
2377
|
return normalizeTex(props.value);
|
|
2421
2378
|
}
|
|
@@ -2465,7 +2422,7 @@ class Expression extends React.Component {
|
|
|
2465
2422
|
}, cb);
|
|
2466
2423
|
}
|
|
2467
2424
|
render() {
|
|
2468
|
-
var _this$props$keypadCon, _this$props$
|
|
2425
|
+
var _this$props$keypadCon, _this$props$analytics2;
|
|
2469
2426
|
if (this.props.apiOptions.customKeypad) {
|
|
2470
2427
|
return /*#__PURE__*/React.createElement(View, {
|
|
2471
2428
|
className: css(styles$D.mobileLabelInputWrapper)
|
|
@@ -2538,7 +2495,7 @@ class Expression extends React.Component {
|
|
|
2538
2495
|
hasError: this.state.showErrorStyle,
|
|
2539
2496
|
ariaLabel: this.props.ariaLabel || this.context.strings.mathInputBox,
|
|
2540
2497
|
extraKeys: (_this$props$keypadCon = this.props.keypadConfiguration) == null ? void 0 : _this$props$keypadCon.extraKeys,
|
|
2541
|
-
analytics: (_this$props$
|
|
2498
|
+
analytics: (_this$props$analytics2 = this.props.analytics) != null ? _this$props$analytics2 : {
|
|
2542
2499
|
onAnalyticsEvent: async function () {}
|
|
2543
2500
|
}
|
|
2544
2501
|
}))));
|
|
@@ -2691,7 +2648,8 @@ var Expression$1 = {
|
|
|
2691
2648
|
},
|
|
2692
2649
|
propUpgrades: propUpgrades$2,
|
|
2693
2650
|
// For use by the editor
|
|
2694
|
-
isLintable: true
|
|
2651
|
+
isLintable: true,
|
|
2652
|
+
validator: expressionValidator
|
|
2695
2653
|
};
|
|
2696
2654
|
|
|
2697
2655
|
/**
|
|
@@ -2920,6 +2878,9 @@ function combineScores(scoreA, scoreB) {
|
|
|
2920
2878
|
}
|
|
2921
2879
|
});
|
|
2922
2880
|
}
|
|
2881
|
+
function flattenScores(widgetScoreMap) {
|
|
2882
|
+
return Object.values(widgetScoreMap).reduce(combineScores, noScore);
|
|
2883
|
+
}
|
|
2923
2884
|
function isCorrect(score) {
|
|
2924
2885
|
return score.type === "points" && score.earned >= score.total;
|
|
2925
2886
|
}
|
|
@@ -3452,6 +3413,7 @@ const Util = {
|
|
|
3452
3413
|
shuffle: shuffle$3,
|
|
3453
3414
|
split,
|
|
3454
3415
|
combineScores,
|
|
3416
|
+
flattenScores,
|
|
3455
3417
|
keScoreFromPerseusScore,
|
|
3456
3418
|
firstNumericalParse: firstNumericalParse$1,
|
|
3457
3419
|
stringArrayOfSize: stringArrayOfSize$1,
|
|
@@ -9988,6 +9950,8 @@ const setLabelMargins = function setLabelMargins(span, size) {
|
|
|
9988
9950
|
});
|
|
9989
9951
|
} else {
|
|
9990
9952
|
var _$container$css, _$container$width, _$span$css;
|
|
9953
|
+
const currentHeightMatchesProps = span.scrollHeight === height;
|
|
9954
|
+
|
|
9991
9955
|
// We are using jQuery to collect information and calculate a scale
|
|
9992
9956
|
// since we don't have a way to pass it to this function.
|
|
9993
9957
|
// We need the width of the container in order to calculate the scale to apply to the label.
|
|
@@ -10009,6 +9973,17 @@ const setLabelMargins = function setLabelMargins(span, size) {
|
|
|
10009
9973
|
// Inherited line-height values can really mess up placement.
|
|
10010
9974
|
$container.css("line-height", "normal");
|
|
10011
9975
|
|
|
9976
|
+
// TODO: Verify that this change doesn't impact other graphies
|
|
9977
|
+
// Check the full list of consuming widgets.
|
|
9978
|
+
|
|
9979
|
+
// If the change in line-height affected the height of the element,
|
|
9980
|
+
// then the height used for calculations should be updated.
|
|
9981
|
+
// This can happen when the first label in the container calls this method,
|
|
9982
|
+
// and the line-height was different when the height measurement was originally referenced.
|
|
9983
|
+
if (currentHeightMatchesProps && span.scrollHeight !== height) {
|
|
9984
|
+
height = span.scrollHeight;
|
|
9985
|
+
}
|
|
9986
|
+
|
|
10012
9987
|
// The expected width of the graphie is found in the "max-width" property on ".svg-image" containers,
|
|
10013
9988
|
// and is found in the "width" property on ".graphie" containers.
|
|
10014
9989
|
const widthValues = (_$container$css = $container.css(["max-width", "width"])) != null ? _$container$css : {
|
|
@@ -14645,7 +14620,7 @@ const mapObject$1 = function mapObject(obj, lambda) {
|
|
|
14645
14620
|
* });
|
|
14646
14621
|
* {a: 'aa', b: 'bb'}
|
|
14647
14622
|
*/
|
|
14648
|
-
const mapObjectFromArray
|
|
14623
|
+
const mapObjectFromArray = function mapObjectFromArray(arr, lambda) {
|
|
14649
14624
|
const result = {};
|
|
14650
14625
|
_.each(arr, function (elem) {
|
|
14651
14626
|
result[elem] = lambda(elem);
|
|
@@ -14655,7 +14630,7 @@ const mapObjectFromArray$1 = function mapObjectFromArray(arr, lambda) {
|
|
|
14655
14630
|
var objective_ = {
|
|
14656
14631
|
pluck: pluck,
|
|
14657
14632
|
mapObject: mapObject$1,
|
|
14658
|
-
mapObjectFromArray: mapObjectFromArray
|
|
14633
|
+
mapObjectFromArray: mapObjectFromArray
|
|
14659
14634
|
};
|
|
14660
14635
|
|
|
14661
14636
|
/**
|
|
@@ -18818,169 +18793,6 @@ class QuestionParagraph extends React.Component {
|
|
|
18818
18793
|
}
|
|
18819
18794
|
}
|
|
18820
18795
|
|
|
18821
|
-
/**
|
|
18822
|
-
* TranslationLinter asynchronously calls Khan Academy's poentry linter.
|
|
18823
|
-
*
|
|
18824
|
-
* The poentry linter checks for issues that prevent content from being
|
|
18825
|
-
* translated. This linter is KA-specific and so TranslationLinter does not do
|
|
18826
|
-
* anything in non-KA environments.
|
|
18827
|
-
*/
|
|
18828
|
-
|
|
18829
|
-
// A LintCB is called once the linter has been run.
|
|
18830
|
-
|
|
18831
|
-
// msec to wait before we actually call the linter after receiving the
|
|
18832
|
-
// last call. The timer is reset if the lint is called during the wait.
|
|
18833
|
-
const DEBOUNCE_TIMEOUT = 1000;
|
|
18834
|
-
class TranslationLinter {
|
|
18835
|
-
constructor() {
|
|
18836
|
-
// To avoid linting when nothing has changed.
|
|
18837
|
-
this.previousContent = null;
|
|
18838
|
-
/**
|
|
18839
|
-
* Runs the poentry linter on the given perseus string asynchronously.
|
|
18840
|
-
*
|
|
18841
|
-
* It doesn't do anything unless we're in a KA environment.
|
|
18842
|
-
*
|
|
18843
|
-
* onLintErrorsGenerated is called even if there are no errors. It is not
|
|
18844
|
-
* called if perseusStr is unchanged from the last call.
|
|
18845
|
-
*
|
|
18846
|
-
* Linting is relatively expensive -- so we debounce linting each instance
|
|
18847
|
-
* for some amount of time.
|
|
18848
|
-
*/
|
|
18849
|
-
this.runLinter = debounce$1((perseusStr, onLintErrorsGenerated) => {
|
|
18850
|
-
// TODO(FEI-5003): Do we still need to check for 'KA'?
|
|
18851
|
-
if (typeof KA === "undefined") {
|
|
18852
|
-
return;
|
|
18853
|
-
}
|
|
18854
|
-
if (perseusStr === this.previousContent) {
|
|
18855
|
-
return;
|
|
18856
|
-
}
|
|
18857
|
-
this.previousContent = perseusStr;
|
|
18858
|
-
if (perseusStr === "") {
|
|
18859
|
-
onLintErrorsGenerated([]);
|
|
18860
|
-
return;
|
|
18861
|
-
}
|
|
18862
|
-
fetch("/api/internal/translations/lint_poentry?preview=1&lang=en", {
|
|
18863
|
-
headers: {
|
|
18864
|
-
"Content-Type": "application/json"
|
|
18865
|
-
},
|
|
18866
|
-
body: JSON.stringify({
|
|
18867
|
-
// The poentry linter verifies that the translation from
|
|
18868
|
-
// the original text to the translated text is sane. We
|
|
18869
|
-
// want to ensure that the translation from English to
|
|
18870
|
-
// English is sane, so msgid === mstr.
|
|
18871
|
-
msgid: perseusStr,
|
|
18872
|
-
// msgid is the original text
|
|
18873
|
-
msgstr: perseusStr,
|
|
18874
|
-
// msgstr is the translated text
|
|
18875
|
-
format: "perseus_text",
|
|
18876
|
-
filename: ""
|
|
18877
|
-
}),
|
|
18878
|
-
method: "POST"
|
|
18879
|
-
}).then(response => {
|
|
18880
|
-
if (response.status >= 400) {
|
|
18881
|
-
return {
|
|
18882
|
-
status: "error",
|
|
18883
|
-
message: "Could not run i18n linter."
|
|
18884
|
-
};
|
|
18885
|
-
}
|
|
18886
|
-
return response.json();
|
|
18887
|
-
}, rejection => {
|
|
18888
|
-
return {
|
|
18889
|
-
status: "error",
|
|
18890
|
-
message: "Could not run i18n linter."
|
|
18891
|
-
};
|
|
18892
|
-
}).then(json => {
|
|
18893
|
-
if (json.status === "error") {
|
|
18894
|
-
onLintErrorsGenerated(["Some part of this text makes it untranslatable. " + "The specific message from the i18n linter was: " + json.message.replace(/\n/g, " ")]);
|
|
18895
|
-
} else {
|
|
18896
|
-
onLintErrorsGenerated([]);
|
|
18897
|
-
}
|
|
18898
|
-
});
|
|
18899
|
-
}, DEBOUNCE_TIMEOUT);
|
|
18900
|
-
}
|
|
18901
|
-
/**
|
|
18902
|
-
* Applies an array of errors generated by linters without position
|
|
18903
|
-
* information (TranslationLinter and the legacy getSaveWarnings()) to the
|
|
18904
|
-
* top of a Perseus tree.
|
|
18905
|
-
*/
|
|
18906
|
-
applyLintErrors(parsedMarkdown, translationLintErrors) {
|
|
18907
|
-
// These lint errors do not have position data associated with
|
|
18908
|
-
// them, so we just plop them at the top.
|
|
18909
|
-
if (translationLintErrors.length) {
|
|
18910
|
-
const errorText = translationLintErrors.join("\n\n");
|
|
18911
|
-
parsedMarkdown.unshift({
|
|
18912
|
-
content: {
|
|
18913
|
-
type: "text",
|
|
18914
|
-
content: ""
|
|
18915
|
-
},
|
|
18916
|
-
insideTable: false,
|
|
18917
|
-
message: errorText,
|
|
18918
|
-
ruleName: "legacy-error",
|
|
18919
|
-
severity: Rule.Severity.ERROR,
|
|
18920
|
-
type: "lint"
|
|
18921
|
-
});
|
|
18922
|
-
}
|
|
18923
|
-
}
|
|
18924
|
-
}
|
|
18925
|
-
|
|
18926
|
-
/**
|
|
18927
|
-
* Preprocess TeX code to convert things that MathJax doesn't know how to handle
|
|
18928
|
-
* to things is does.
|
|
18929
|
-
*/
|
|
18930
|
-
var preprocessTex = (texCode => texCode
|
|
18931
|
-
// Replace uses of \begin{align}...\end{align} which KaTeX doesn't
|
|
18932
|
-
// support (yet) with \begin{aligned}...\end{aligned} which renders
|
|
18933
|
-
// the same is supported by KaTeX. It does the same for align*.
|
|
18934
|
-
// TODO(kevinb) update content to use aligned instead of align.
|
|
18935
|
-
// TODO(LEMS-1608) Remove this replacement as MathJax supports the
|
|
18936
|
-
// "align" macro correctly (and, in fact, it is not synonymous with
|
|
18937
|
-
// "aligned").
|
|
18938
|
-
.replace(/\{align[*]?\}/g, "{aligned}")
|
|
18939
|
-
// Replace non-breaking spaces with regular spaces.
|
|
18940
|
-
.replace(/[\u00a0]/g, " "));
|
|
18941
|
-
|
|
18942
|
-
const {
|
|
18943
|
-
interactiveSizes
|
|
18944
|
-
} = constants$1;
|
|
18945
|
-
|
|
18946
|
-
// Note: these size cutoffs represent content-width cutoffs as specified in
|
|
18947
|
-
// http://zpl.io/1mVmvU (broken link - we no longer use Zeplin)
|
|
18948
|
-
// TODO(benkomalo): these values aren't used in JS outside of this file, but
|
|
18949
|
-
// are coupled to the values in styles/styles.less - DRY it up at some point
|
|
18950
|
-
const smMax = articleMaxWidthTableInPx;
|
|
18951
|
-
const mdMax = articleMaxWidthInPx;
|
|
18952
|
-
const containerSizeClass = {
|
|
18953
|
-
SMALL: "small",
|
|
18954
|
-
MEDIUM: "medium",
|
|
18955
|
-
LARGE: "large",
|
|
18956
|
-
XLARGE: "xlarge"
|
|
18957
|
-
};
|
|
18958
|
-
const getClassFromWidth = width => {
|
|
18959
|
-
if (!width) {
|
|
18960
|
-
return containerSizeClass.MEDIUM;
|
|
18961
|
-
}
|
|
18962
|
-
if (width <= smMax) {
|
|
18963
|
-
return containerSizeClass.SMALL;
|
|
18964
|
-
}
|
|
18965
|
-
if (width <= mdMax) {
|
|
18966
|
-
return containerSizeClass.MEDIUM;
|
|
18967
|
-
}
|
|
18968
|
-
return containerSizeClass.LARGE;
|
|
18969
|
-
};
|
|
18970
|
-
const getInteractiveBoxFromSizeClass = sizeClass => {
|
|
18971
|
-
if (sizeClass === containerSizeClass.SMALL) {
|
|
18972
|
-
return [interactiveSizes.defaultBoxSizeSmall, interactiveSizes.defaultBoxSizeSmall];
|
|
18973
|
-
}
|
|
18974
|
-
return [interactiveSizes.defaultBoxSize, interactiveSizes.defaultBoxSize];
|
|
18975
|
-
};
|
|
18976
|
-
|
|
18977
|
-
var sizingUtils = /*#__PURE__*/Object.freeze({
|
|
18978
|
-
__proto__: null,
|
|
18979
|
-
containerSizeClass: containerSizeClass,
|
|
18980
|
-
getClassFromWidth: getClassFromWidth,
|
|
18981
|
-
getInteractiveBoxFromSizeClass: getInteractiveBoxFromSizeClass
|
|
18982
|
-
});
|
|
18983
|
-
|
|
18984
18796
|
const DEFAULT_ALIGNMENT$1 = "block";
|
|
18985
18797
|
// NOTE(kevinb): "default" is not one in `validAlignments`.
|
|
18986
18798
|
const DEFAULT_SUPPORTED_ALIGNMENTS = ["default"];
|
|
@@ -19081,6 +18893,10 @@ const getWidget = name => {
|
|
|
19081
18893
|
}
|
|
19082
18894
|
return widgets[name].widget;
|
|
19083
18895
|
};
|
|
18896
|
+
const getWidgetValidator = name => {
|
|
18897
|
+
var _widgets$name$validat, _widgets$name3;
|
|
18898
|
+
return (_widgets$name$validat = (_widgets$name3 = widgets[name]) == null ? void 0 : _widgets$name3.validator) != null ? _widgets$name$validat : null;
|
|
18899
|
+
};
|
|
19084
18900
|
const getEditor = name => {
|
|
19085
18901
|
return _.has(editors, name) ? editors[name] : null;
|
|
19086
18902
|
};
|
|
@@ -19383,6 +19199,7 @@ var widgets$1 = /*#__PURE__*/Object.freeze({
|
|
|
19383
19199
|
replaceEditor: replaceEditor,
|
|
19384
19200
|
replaceDeprecatedEditors: replaceDeprecatedEditors,
|
|
19385
19201
|
getWidget: getWidget,
|
|
19202
|
+
getWidgetValidator: getWidgetValidator,
|
|
19386
19203
|
getEditor: getEditor,
|
|
19387
19204
|
getTransform: getTransform,
|
|
19388
19205
|
getVersion: getVersion,
|
|
@@ -19402,6 +19219,222 @@ var widgets$1 = /*#__PURE__*/Object.freeze({
|
|
|
19402
19219
|
isLintable: isLintable
|
|
19403
19220
|
});
|
|
19404
19221
|
|
|
19222
|
+
function emptyWidgetsFunctional(widgets,
|
|
19223
|
+
// This is a port of old code, I'm not sure why
|
|
19224
|
+
// we need widgetIds vs the keys of the widgets object
|
|
19225
|
+
widgetIds, userInputMap, strings, locale) {
|
|
19226
|
+
return widgetIds.filter(id => {
|
|
19227
|
+
const widget = widgets[id];
|
|
19228
|
+
if (!widget || widget.static) {
|
|
19229
|
+
// Static widgets shouldn't count as empty
|
|
19230
|
+
return false;
|
|
19231
|
+
}
|
|
19232
|
+
let score = null;
|
|
19233
|
+
const userInput = userInputMap[id];
|
|
19234
|
+
const validator = getWidgetValidator(widget.type);
|
|
19235
|
+
if (widget.type === "group") {
|
|
19236
|
+
const scores = scoreWidgetsFunctional(widget.options.widgets, Object.keys(widget.options.widgets), userInputMap[id], strings, locale);
|
|
19237
|
+
score = Util.flattenScores(scores);
|
|
19238
|
+
} else if (validator) {
|
|
19239
|
+
score = validator(userInput, widget.options, strings, locale);
|
|
19240
|
+
}
|
|
19241
|
+
if (score) {
|
|
19242
|
+
return Util.scoreIsEmpty(score);
|
|
19243
|
+
}
|
|
19244
|
+
});
|
|
19245
|
+
}
|
|
19246
|
+
function scoreWidgetsFunctional(widgets,
|
|
19247
|
+
// This is a port of old code, I'm not sure why
|
|
19248
|
+
// we need widgetIds vs the keys of the widgets object
|
|
19249
|
+
widgetIds, userInputMap, strings, locale) {
|
|
19250
|
+
const gradedWidgetIds = widgetIds.filter(id => {
|
|
19251
|
+
const props = widgets[id];
|
|
19252
|
+
const widgetIsGraded = (props == null ? void 0 : props.graded) == null || props.graded;
|
|
19253
|
+
const widgetIsStatic = !!(props != null && props.static);
|
|
19254
|
+
// Ungraded widgets or widgets set to static shouldn't be graded.
|
|
19255
|
+
return widgetIsGraded && !widgetIsStatic;
|
|
19256
|
+
});
|
|
19257
|
+
const widgetScores = {};
|
|
19258
|
+
gradedWidgetIds.forEach(id => {
|
|
19259
|
+
const widget = widgets[id];
|
|
19260
|
+
if (!widget) {
|
|
19261
|
+
return;
|
|
19262
|
+
}
|
|
19263
|
+
const userInput = userInputMap[id];
|
|
19264
|
+
const validator = getWidgetValidator(widget.type);
|
|
19265
|
+
if (widget.type === "group") {
|
|
19266
|
+
const scores = scoreWidgetsFunctional(widget.options.widgets, Object.keys(widget.options.widgets), userInputMap[id], strings, locale);
|
|
19267
|
+
widgetScores[id] = Util.flattenScores(scores);
|
|
19268
|
+
} else if (validator) {
|
|
19269
|
+
widgetScores[id] = validator(userInput, widget.options, strings, locale);
|
|
19270
|
+
}
|
|
19271
|
+
});
|
|
19272
|
+
return widgetScores;
|
|
19273
|
+
}
|
|
19274
|
+
|
|
19275
|
+
/**
|
|
19276
|
+
* TranslationLinter asynchronously calls Khan Academy's poentry linter.
|
|
19277
|
+
*
|
|
19278
|
+
* The poentry linter checks for issues that prevent content from being
|
|
19279
|
+
* translated. This linter is KA-specific and so TranslationLinter does not do
|
|
19280
|
+
* anything in non-KA environments.
|
|
19281
|
+
*/
|
|
19282
|
+
|
|
19283
|
+
// A LintCB is called once the linter has been run.
|
|
19284
|
+
|
|
19285
|
+
// msec to wait before we actually call the linter after receiving the
|
|
19286
|
+
// last call. The timer is reset if the lint is called during the wait.
|
|
19287
|
+
const DEBOUNCE_TIMEOUT = 1000;
|
|
19288
|
+
class TranslationLinter {
|
|
19289
|
+
constructor() {
|
|
19290
|
+
// To avoid linting when nothing has changed.
|
|
19291
|
+
this.previousContent = null;
|
|
19292
|
+
/**
|
|
19293
|
+
* Runs the poentry linter on the given perseus string asynchronously.
|
|
19294
|
+
*
|
|
19295
|
+
* It doesn't do anything unless we're in a KA environment.
|
|
19296
|
+
*
|
|
19297
|
+
* onLintErrorsGenerated is called even if there are no errors. It is not
|
|
19298
|
+
* called if perseusStr is unchanged from the last call.
|
|
19299
|
+
*
|
|
19300
|
+
* Linting is relatively expensive -- so we debounce linting each instance
|
|
19301
|
+
* for some amount of time.
|
|
19302
|
+
*/
|
|
19303
|
+
this.runLinter = debounce$1((perseusStr, onLintErrorsGenerated) => {
|
|
19304
|
+
// TODO(FEI-5003): Do we still need to check for 'KA'?
|
|
19305
|
+
if (typeof KA === "undefined") {
|
|
19306
|
+
return;
|
|
19307
|
+
}
|
|
19308
|
+
if (perseusStr === this.previousContent) {
|
|
19309
|
+
return;
|
|
19310
|
+
}
|
|
19311
|
+
this.previousContent = perseusStr;
|
|
19312
|
+
if (perseusStr === "") {
|
|
19313
|
+
onLintErrorsGenerated([]);
|
|
19314
|
+
return;
|
|
19315
|
+
}
|
|
19316
|
+
fetch("/api/internal/translations/lint_poentry?preview=1&lang=en", {
|
|
19317
|
+
headers: {
|
|
19318
|
+
"Content-Type": "application/json"
|
|
19319
|
+
},
|
|
19320
|
+
body: JSON.stringify({
|
|
19321
|
+
// The poentry linter verifies that the translation from
|
|
19322
|
+
// the original text to the translated text is sane. We
|
|
19323
|
+
// want to ensure that the translation from English to
|
|
19324
|
+
// English is sane, so msgid === mstr.
|
|
19325
|
+
msgid: perseusStr,
|
|
19326
|
+
// msgid is the original text
|
|
19327
|
+
msgstr: perseusStr,
|
|
19328
|
+
// msgstr is the translated text
|
|
19329
|
+
format: "perseus_text",
|
|
19330
|
+
filename: ""
|
|
19331
|
+
}),
|
|
19332
|
+
method: "POST"
|
|
19333
|
+
}).then(response => {
|
|
19334
|
+
if (response.status >= 400) {
|
|
19335
|
+
return {
|
|
19336
|
+
status: "error",
|
|
19337
|
+
message: "Could not run i18n linter."
|
|
19338
|
+
};
|
|
19339
|
+
}
|
|
19340
|
+
return response.json();
|
|
19341
|
+
}, rejection => {
|
|
19342
|
+
return {
|
|
19343
|
+
status: "error",
|
|
19344
|
+
message: "Could not run i18n linter."
|
|
19345
|
+
};
|
|
19346
|
+
}).then(json => {
|
|
19347
|
+
if (json.status === "error") {
|
|
19348
|
+
onLintErrorsGenerated(["Some part of this text makes it untranslatable. " + "The specific message from the i18n linter was: " + json.message.replace(/\n/g, " ")]);
|
|
19349
|
+
} else {
|
|
19350
|
+
onLintErrorsGenerated([]);
|
|
19351
|
+
}
|
|
19352
|
+
});
|
|
19353
|
+
}, DEBOUNCE_TIMEOUT);
|
|
19354
|
+
}
|
|
19355
|
+
/**
|
|
19356
|
+
* Applies an array of errors generated by linters without position
|
|
19357
|
+
* information (TranslationLinter and the legacy getSaveWarnings()) to the
|
|
19358
|
+
* top of a Perseus tree.
|
|
19359
|
+
*/
|
|
19360
|
+
applyLintErrors(parsedMarkdown, translationLintErrors) {
|
|
19361
|
+
// These lint errors do not have position data associated with
|
|
19362
|
+
// them, so we just plop them at the top.
|
|
19363
|
+
if (translationLintErrors.length) {
|
|
19364
|
+
const errorText = translationLintErrors.join("\n\n");
|
|
19365
|
+
parsedMarkdown.unshift({
|
|
19366
|
+
content: {
|
|
19367
|
+
type: "text",
|
|
19368
|
+
content: ""
|
|
19369
|
+
},
|
|
19370
|
+
insideTable: false,
|
|
19371
|
+
message: errorText,
|
|
19372
|
+
ruleName: "legacy-error",
|
|
19373
|
+
severity: Rule.Severity.ERROR,
|
|
19374
|
+
type: "lint"
|
|
19375
|
+
});
|
|
19376
|
+
}
|
|
19377
|
+
}
|
|
19378
|
+
}
|
|
19379
|
+
|
|
19380
|
+
/**
|
|
19381
|
+
* Preprocess TeX code to convert things that MathJax doesn't know how to handle
|
|
19382
|
+
* to things is does.
|
|
19383
|
+
*/
|
|
19384
|
+
var preprocessTex = (texCode => texCode
|
|
19385
|
+
// Replace uses of \begin{align}...\end{align} which KaTeX doesn't
|
|
19386
|
+
// support (yet) with \begin{aligned}...\end{aligned} which renders
|
|
19387
|
+
// the same is supported by KaTeX. It does the same for align*.
|
|
19388
|
+
// TODO(kevinb) update content to use aligned instead of align.
|
|
19389
|
+
// TODO(LEMS-1608) Remove this replacement as MathJax supports the
|
|
19390
|
+
// "align" macro correctly (and, in fact, it is not synonymous with
|
|
19391
|
+
// "aligned").
|
|
19392
|
+
.replace(/\{align[*]?\}/g, "{aligned}")
|
|
19393
|
+
// Replace non-breaking spaces with regular spaces.
|
|
19394
|
+
.replace(/[\u00a0]/g, " "));
|
|
19395
|
+
|
|
19396
|
+
const {
|
|
19397
|
+
interactiveSizes
|
|
19398
|
+
} = constants$1;
|
|
19399
|
+
|
|
19400
|
+
// Note: these size cutoffs represent content-width cutoffs as specified in
|
|
19401
|
+
// http://zpl.io/1mVmvU (broken link - we no longer use Zeplin)
|
|
19402
|
+
// TODO(benkomalo): these values aren't used in JS outside of this file, but
|
|
19403
|
+
// are coupled to the values in styles/styles.less - DRY it up at some point
|
|
19404
|
+
const smMax = articleMaxWidthTableInPx;
|
|
19405
|
+
const mdMax = articleMaxWidthInPx;
|
|
19406
|
+
const containerSizeClass = {
|
|
19407
|
+
SMALL: "small",
|
|
19408
|
+
MEDIUM: "medium",
|
|
19409
|
+
LARGE: "large",
|
|
19410
|
+
XLARGE: "xlarge"
|
|
19411
|
+
};
|
|
19412
|
+
const getClassFromWidth = width => {
|
|
19413
|
+
if (!width) {
|
|
19414
|
+
return containerSizeClass.MEDIUM;
|
|
19415
|
+
}
|
|
19416
|
+
if (width <= smMax) {
|
|
19417
|
+
return containerSizeClass.SMALL;
|
|
19418
|
+
}
|
|
19419
|
+
if (width <= mdMax) {
|
|
19420
|
+
return containerSizeClass.MEDIUM;
|
|
19421
|
+
}
|
|
19422
|
+
return containerSizeClass.LARGE;
|
|
19423
|
+
};
|
|
19424
|
+
const getInteractiveBoxFromSizeClass = sizeClass => {
|
|
19425
|
+
if (sizeClass === containerSizeClass.SMALL) {
|
|
19426
|
+
return [interactiveSizes.defaultBoxSizeSmall, interactiveSizes.defaultBoxSizeSmall];
|
|
19427
|
+
}
|
|
19428
|
+
return [interactiveSizes.defaultBoxSize, interactiveSizes.defaultBoxSize];
|
|
19429
|
+
};
|
|
19430
|
+
|
|
19431
|
+
var sizingUtils = /*#__PURE__*/Object.freeze({
|
|
19432
|
+
__proto__: null,
|
|
19433
|
+
containerSizeClass: containerSizeClass,
|
|
19434
|
+
getClassFromWidth: getClassFromWidth,
|
|
19435
|
+
getInteractiveBoxFromSizeClass: getInteractiveBoxFromSizeClass
|
|
19436
|
+
});
|
|
19437
|
+
|
|
19405
19438
|
class WidgetContainer extends React.Component {
|
|
19406
19439
|
constructor(...args) {
|
|
19407
19440
|
super(...args);
|
|
@@ -19547,8 +19580,7 @@ WidgetContainer.defaultProps = {
|
|
|
19547
19580
|
};
|
|
19548
19581
|
|
|
19549
19582
|
const {
|
|
19550
|
-
mapObject
|
|
19551
|
-
mapObjectFromArray
|
|
19583
|
+
mapObject
|
|
19552
19584
|
} = objective_;
|
|
19553
19585
|
const rContainsNonWhitespace = /\S/;
|
|
19554
19586
|
const rImageURL = /(web\+graphie|https):\/\/[^\s]*/;
|
|
@@ -19713,11 +19745,7 @@ class Renderer extends React.Component {
|
|
|
19713
19745
|
}
|
|
19714
19746
|
let interactionTracker = this._interactionTrackers[id];
|
|
19715
19747
|
if (!interactionTracker) {
|
|
19716
|
-
interactionTracker = this._interactionTrackers[id] = new InteractionTracker(apiOptions.trackInteraction,
|
|
19717
|
-
// @ts-expect-error - TS2345 - Argument of type 'string | null | undefined' is not assignable to parameter of type 'string'.
|
|
19718
|
-
widgetInfo && widgetInfo.type, id,
|
|
19719
|
-
// @ts-expect-error - TS2345 - Argument of type 'string | null | undefined' is not assignable to parameter of type 'string'.
|
|
19720
|
-
getTracking(widgetInfo && widgetInfo.type));
|
|
19748
|
+
interactionTracker = this._interactionTrackers[id] = new InteractionTracker(apiOptions.trackInteraction, widgetInfo && widgetInfo.type, id, getTracking(widgetInfo && widgetInfo.type));
|
|
19721
19749
|
}
|
|
19722
19750
|
return _extends({}, widgetProps, {
|
|
19723
19751
|
widgetId: id,
|
|
@@ -20495,23 +20523,6 @@ class Renderer extends React.Component {
|
|
|
20495
20523
|
}, this);
|
|
20496
20524
|
return state;
|
|
20497
20525
|
};
|
|
20498
|
-
this.emptyWidgets = () => {
|
|
20499
|
-
// @ts-expect-error - TS2345 - Argument of type '(id: string) => boolean | undefined' is not assignable to parameter of type 'Iteratee<string[], boolean, string>'.
|
|
20500
|
-
return _.filter(this.widgetIds, id => {
|
|
20501
|
-
const widgetInfo = this._getWidgetInfo(id);
|
|
20502
|
-
if (widgetInfo.static) {
|
|
20503
|
-
// Static widgets shouldn't count as empty
|
|
20504
|
-
return false;
|
|
20505
|
-
}
|
|
20506
|
-
const widget = this.getWidgetInstance(id);
|
|
20507
|
-
if (widget && widget.simpleValidate) {
|
|
20508
|
-
const score = widget.simpleValidate(widgetInfo.options,
|
|
20509
|
-
// @ts-expect-error - TS2345 - Argument of type 'null' is not assignable to parameter of type '((widgetId: any, value: string, message?: string | null | undefined) => unknown) | undefined'.
|
|
20510
|
-
null);
|
|
20511
|
-
return Util.scoreIsEmpty(score);
|
|
20512
|
-
}
|
|
20513
|
-
});
|
|
20514
|
-
};
|
|
20515
20526
|
this._setWidgetProps = (id, newProps, cb, silent) => {
|
|
20516
20527
|
this.setState(prevState => {
|
|
20517
20528
|
const widgetProps = _extends({}, prevState.widgetProps, {
|
|
@@ -20568,19 +20579,6 @@ class Renderer extends React.Component {
|
|
|
20568
20579
|
// Widget handles parsing of the interWidgetPath.
|
|
20569
20580
|
widget == null || widget.setInputValue == null || widget.setInputValue(interWidgetPath, newValue, focus);
|
|
20570
20581
|
};
|
|
20571
|
-
/**
|
|
20572
|
-
* Returns an array of the widget `.getUserInput()` results
|
|
20573
|
-
*/
|
|
20574
|
-
this.getUserInput = () => {
|
|
20575
|
-
return this.widgetIds.map(id => {
|
|
20576
|
-
const widget = this.getWidgetInstance(id);
|
|
20577
|
-
if (widget && widget.getUserInput) {
|
|
20578
|
-
// TODO(Jeremy): Add the widget ID in here so we can more
|
|
20579
|
-
// easily correlate it to the widget state.
|
|
20580
|
-
return widget.getUserInput();
|
|
20581
|
-
}
|
|
20582
|
-
});
|
|
20583
|
-
};
|
|
20584
20582
|
/**
|
|
20585
20583
|
* Returns an array of all widget IDs in the order they occur in
|
|
20586
20584
|
* the content.
|
|
@@ -20588,56 +20586,6 @@ class Renderer extends React.Component {
|
|
|
20588
20586
|
this.getWidgetIds = () => {
|
|
20589
20587
|
return this.widgetIds;
|
|
20590
20588
|
};
|
|
20591
|
-
/**
|
|
20592
|
-
* Returns the result of `.getUserInput()` for each widget, in
|
|
20593
|
-
* a map from widgetId to userInput.
|
|
20594
|
-
* NOTE(jeremy): This function is hauntingly similar to `getUserInput` with
|
|
20595
|
-
* the major difference being that this function returns a map of
|
|
20596
|
-
* `widgetID` => UserInput and `getUserInput` simply returns an array. It
|
|
20597
|
-
* would be trivial to map between the results of each of these functions,
|
|
20598
|
-
* so we should aim to remove one of these functions.
|
|
20599
|
-
*/
|
|
20600
|
-
this.getUserInputForWidgets = () => {
|
|
20601
|
-
return mapObjectFromArray(this.widgetIds, id => {
|
|
20602
|
-
const widget = this.getWidgetInstance(id);
|
|
20603
|
-
if (widget && widget.getUserInput) {
|
|
20604
|
-
return widget.getUserInput();
|
|
20605
|
-
}
|
|
20606
|
-
});
|
|
20607
|
-
};
|
|
20608
|
-
/**
|
|
20609
|
-
* Returns an object mapping from widget ID to perseus-style score.
|
|
20610
|
-
* The keys of this object are the values of the array returned
|
|
20611
|
-
* from `getWidgetIds`.
|
|
20612
|
-
*/
|
|
20613
|
-
this.scoreWidgets = () => {
|
|
20614
|
-
const widgetProps = this.state.widgetInfo;
|
|
20615
|
-
const gradedWidgetIds = _.filter(this.widgetIds, id => {
|
|
20616
|
-
const props = widgetProps[id];
|
|
20617
|
-
const widgetIsGraded = (props == null ? void 0 : props.graded) == null || props.graded;
|
|
20618
|
-
const widgetIsStatic = !!(props != null && props.static);
|
|
20619
|
-
// Ungraded widgets or widgets set to static shouldn't be graded.
|
|
20620
|
-
return widgetIsGraded && !widgetIsStatic;
|
|
20621
|
-
});
|
|
20622
|
-
const widgetScores = {};
|
|
20623
|
-
_.each(gradedWidgetIds, id => {
|
|
20624
|
-
const props = widgetProps[id];
|
|
20625
|
-
const widget = this.getWidgetInstance(id);
|
|
20626
|
-
// widget can be undefined if it hasn't yet been rendered
|
|
20627
|
-
if (widget && widget.simpleValidate) {
|
|
20628
|
-
widgetScores[id] = widget.simpleValidate(_extends({}, props == null ? void 0 : props.options, {
|
|
20629
|
-
scoring: true
|
|
20630
|
-
}));
|
|
20631
|
-
}
|
|
20632
|
-
});
|
|
20633
|
-
return widgetScores;
|
|
20634
|
-
};
|
|
20635
|
-
/**
|
|
20636
|
-
* Grades the content.
|
|
20637
|
-
*/
|
|
20638
|
-
this.score = () => {
|
|
20639
|
-
return _.reduce(this.scoreWidgets(), Util.combineScores, Util.noScore);
|
|
20640
|
-
};
|
|
20641
20589
|
this.guessAndScore = () => {
|
|
20642
20590
|
const totalGuess = this.getUserInput();
|
|
20643
20591
|
const totalScore = this.score();
|
|
@@ -20811,6 +20759,59 @@ class Renderer extends React.Component {
|
|
|
20811
20759
|
}
|
|
20812
20760
|
this._isMounted = false;
|
|
20813
20761
|
}
|
|
20762
|
+
emptyWidgets() {
|
|
20763
|
+
return emptyWidgetsFunctional(this.state.widgetInfo, this.widgetIds, this.getUserInputMap(), this.props.strings, this.context.locale);
|
|
20764
|
+
}
|
|
20765
|
+
/**
|
|
20766
|
+
* Returns an array of the widget `.getUserInput()` results
|
|
20767
|
+
*
|
|
20768
|
+
* TODO: can we remove this?
|
|
20769
|
+
* @deprecated use getUserInputMap
|
|
20770
|
+
*/
|
|
20771
|
+
getUserInput() {
|
|
20772
|
+
return this.widgetIds.map(id => {
|
|
20773
|
+
const widget = this.getWidgetInstance(id);
|
|
20774
|
+
if (widget && widget.getUserInput) {
|
|
20775
|
+
// TODO(Jeremy): Add the widget ID in here so we can more
|
|
20776
|
+
// easily correlate it to the widget state.
|
|
20777
|
+
return widget.getUserInput();
|
|
20778
|
+
}
|
|
20779
|
+
});
|
|
20780
|
+
}
|
|
20781
|
+
|
|
20782
|
+
/**
|
|
20783
|
+
* Returns an object of the widget `.getUserInput()` results
|
|
20784
|
+
*/
|
|
20785
|
+
getUserInputMap() {
|
|
20786
|
+
const userInputMap = {};
|
|
20787
|
+
this.widgetIds.forEach(id => {
|
|
20788
|
+
const widget = this.getWidgetInstance(id);
|
|
20789
|
+
// Handle Groups, which have their own sets of widgets
|
|
20790
|
+
if (widget != null && widget.getUserInputMap) {
|
|
20791
|
+
userInputMap[id] = widget.getUserInputMap();
|
|
20792
|
+
} else if (widget != null && widget.getUserInput) {
|
|
20793
|
+
userInputMap[id] = widget.getUserInput();
|
|
20794
|
+
}
|
|
20795
|
+
});
|
|
20796
|
+
return userInputMap;
|
|
20797
|
+
}
|
|
20798
|
+
/**
|
|
20799
|
+
* Returns an object mapping from widget ID to perseus-style score.
|
|
20800
|
+
* The keys of this object are the values of the array returned
|
|
20801
|
+
* from `getWidgetIds`.
|
|
20802
|
+
*/
|
|
20803
|
+
scoreWidgets() {
|
|
20804
|
+
return scoreWidgetsFunctional(this.state.widgetInfo, this.widgetIds, this.getUserInputMap(), this.props.strings, this.context.locale);
|
|
20805
|
+
}
|
|
20806
|
+
|
|
20807
|
+
/**
|
|
20808
|
+
* Grades the content.
|
|
20809
|
+
*/
|
|
20810
|
+
score() {
|
|
20811
|
+
const scores = this.scoreWidgets();
|
|
20812
|
+
const combinedScore = Util.flattenScores(scores);
|
|
20813
|
+
return combinedScore;
|
|
20814
|
+
}
|
|
20814
20815
|
render() {
|
|
20815
20816
|
const apiOptions = this.getApiOptions();
|
|
20816
20817
|
if (this.reuseMarkdown) {
|
|
@@ -20885,11 +20886,11 @@ class Renderer extends React.Component {
|
|
|
20885
20886
|
// If highlightLint is true and lint is detected, this call
|
|
20886
20887
|
// will modify the parse tree by adding lint nodes that will
|
|
20887
20888
|
// serve to highlight the lint when rendered
|
|
20888
|
-
const
|
|
20889
|
+
const fullLinterContext = _extends({
|
|
20889
20890
|
content: this.props.content,
|
|
20890
20891
|
widgets: this.props.widgets
|
|
20891
20892
|
}, this.props.linterContext);
|
|
20892
|
-
PerseusLinter.runLinter(parsedMarkdown,
|
|
20893
|
+
PerseusLinter.runLinter(parsedMarkdown, fullLinterContext, true);
|
|
20893
20894
|
|
|
20894
20895
|
// Apply the lint errors from the last TranslationLinter run.
|
|
20895
20896
|
// TODO(joshuan): Support overlapping dots.
|
|
@@ -20911,6 +20912,7 @@ class Renderer extends React.Component {
|
|
|
20911
20912
|
return this.lastRenderedMarkdown;
|
|
20912
20913
|
}
|
|
20913
20914
|
}
|
|
20915
|
+
Renderer.contextType = PerseusI18nContext;
|
|
20914
20916
|
Renderer.defaultProps = {
|
|
20915
20917
|
content: "",
|
|
20916
20918
|
widgets: {},
|
|
@@ -21398,6 +21400,16 @@ InputWithExamples.defaultProps = {
|
|
|
21398
21400
|
className: ""
|
|
21399
21401
|
};
|
|
21400
21402
|
|
|
21403
|
+
function _objectWithoutPropertiesLoose(r, e) {
|
|
21404
|
+
if (null == r) return {};
|
|
21405
|
+
var t = {};
|
|
21406
|
+
for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
|
|
21407
|
+
if (e.includes(n)) continue;
|
|
21408
|
+
t[n] = r[n];
|
|
21409
|
+
}
|
|
21410
|
+
return t;
|
|
21411
|
+
}
|
|
21412
|
+
|
|
21401
21413
|
const _excluded$4 = ["keypadElement", "onFocus", "value"];
|
|
21402
21414
|
class SimpleKeypadInput extends React.Component {
|
|
21403
21415
|
constructor(...args) {
|
|
@@ -21800,9 +21812,6 @@ class InputNumber extends React.Component {
|
|
|
21800
21812
|
return [strings.yourAnswer].concat(examples);
|
|
21801
21813
|
};
|
|
21802
21814
|
}
|
|
21803
|
-
static validate(state, rubric, strings) {
|
|
21804
|
-
return inputNumberValidator(state, rubric, strings);
|
|
21805
|
-
}
|
|
21806
21815
|
static getUserInputFromProps(props) {
|
|
21807
21816
|
return {
|
|
21808
21817
|
currentValue: props.currentValue
|
|
@@ -21821,9 +21830,6 @@ class InputNumber extends React.Component {
|
|
|
21821
21830
|
getUserInput() {
|
|
21822
21831
|
return InputNumber.getUserInputFromProps(this.props);
|
|
21823
21832
|
}
|
|
21824
|
-
simpleValidate(rubric) {
|
|
21825
|
-
return inputNumberValidator(this.getUserInput(), rubric, this.context.strings);
|
|
21826
|
-
}
|
|
21827
21833
|
render() {
|
|
21828
21834
|
if (this.props.apiOptions.customKeypad) {
|
|
21829
21835
|
// TODO(charlie): Support "Review Mode".
|
|
@@ -21928,7 +21934,8 @@ var InputNumber$1 = {
|
|
|
21928
21934
|
hidden: true,
|
|
21929
21935
|
widget: InputNumber,
|
|
21930
21936
|
transform: propTransform$3,
|
|
21931
|
-
isLintable: true
|
|
21937
|
+
isLintable: true,
|
|
21938
|
+
validator: inputNumberValidator
|
|
21932
21939
|
};
|
|
21933
21940
|
|
|
21934
21941
|
const ParseTex = TexWrangler.parseTex;
|
|
@@ -22202,12 +22209,6 @@ class NumericInput extends React.Component {
|
|
|
22202
22209
|
}
|
|
22203
22210
|
return answerStrings[0];
|
|
22204
22211
|
}
|
|
22205
|
-
static validate(userInput, rubric, strings) {
|
|
22206
|
-
return numericInputValidator(userInput, rubric, strings);
|
|
22207
|
-
}
|
|
22208
|
-
simpleValidate(rubric) {
|
|
22209
|
-
return numericInputValidator(this.getUserInput(), rubric, this.context.strings);
|
|
22210
|
-
}
|
|
22211
22212
|
getUserInput() {
|
|
22212
22213
|
return NumericInput.getUserInputFromProps(this.props);
|
|
22213
22214
|
}
|
|
@@ -22334,7 +22335,8 @@ var NumericInput$1 = {
|
|
|
22334
22335
|
accessible: true,
|
|
22335
22336
|
widget: NumericInput,
|
|
22336
22337
|
transform: propsTransform,
|
|
22337
|
-
isLintable: true
|
|
22338
|
+
isLintable: true,
|
|
22339
|
+
validator: numericInputValidator
|
|
22338
22340
|
};
|
|
22339
22341
|
|
|
22340
22342
|
/**
|
|
@@ -24142,6 +24144,9 @@ class Passage extends React.Component {
|
|
|
24142
24144
|
this._onResize = void 0;
|
|
24143
24145
|
// @ts-expect-error - TS2564 - Property '_stylesAppiedTimer' has no initializer and is not definitely assigned in the constructor.
|
|
24144
24146
|
this._stylesAppiedTimer = void 0;
|
|
24147
|
+
// this just helps with TS weak typing when a Widget
|
|
24148
|
+
// doesn't implement any Widget methods
|
|
24149
|
+
this.isWidget = true;
|
|
24145
24150
|
this.state = {
|
|
24146
24151
|
nLines: null,
|
|
24147
24152
|
startLineNumbersAfter: 0,
|
|
@@ -24153,10 +24158,6 @@ class Passage extends React.Component {
|
|
|
24153
24158
|
});
|
|
24154
24159
|
};
|
|
24155
24160
|
}
|
|
24156
|
-
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
24157
|
-
static validate() {
|
|
24158
|
-
return noopValidator();
|
|
24159
|
-
}
|
|
24160
24161
|
componentDidMount() {
|
|
24161
24162
|
this._updateState();
|
|
24162
24163
|
|
|
@@ -24361,21 +24362,6 @@ class Passage extends React.Component {
|
|
|
24361
24362
|
};
|
|
24362
24363
|
}
|
|
24363
24364
|
|
|
24364
|
-
/**
|
|
24365
|
-
* Misc functions
|
|
24366
|
-
*
|
|
24367
|
-
* These are misc widget functions used for the widget API
|
|
24368
|
-
*/
|
|
24369
|
-
|
|
24370
|
-
getUserInput() {
|
|
24371
|
-
return null;
|
|
24372
|
-
}
|
|
24373
|
-
|
|
24374
|
-
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
24375
|
-
simpleValidate() {
|
|
24376
|
-
return noopValidator();
|
|
24377
|
-
}
|
|
24378
|
-
|
|
24379
24365
|
/**
|
|
24380
24366
|
* Rendering
|
|
24381
24367
|
*
|
|
@@ -24528,7 +24514,8 @@ var Passage$1 = {
|
|
|
24528
24514
|
transform: editorProps => {
|
|
24529
24515
|
return _.pick(editorProps, "passageTitle", "passageText", "footnotes", "showLineNumbers");
|
|
24530
24516
|
},
|
|
24531
|
-
isLintable: true
|
|
24517
|
+
isLintable: true,
|
|
24518
|
+
validator: () => noopValidator()
|
|
24532
24519
|
};
|
|
24533
24520
|
|
|
24534
24521
|
/**
|
|
@@ -24554,6 +24541,9 @@ class PassageRef extends React.Component {
|
|
|
24554
24541
|
this._isMounted = void 0;
|
|
24555
24542
|
// @ts-expect-error - TS2564 - Property '_throttledUpdateRange' has no initializer and is not definitely assigned in the constructor.
|
|
24556
24543
|
this._throttledUpdateRange = void 0;
|
|
24544
|
+
// this just helps with TS weak typing when a Widget
|
|
24545
|
+
// doesn't implement any Widget methods
|
|
24546
|
+
this.isWidget = true;
|
|
24557
24547
|
this.state = {
|
|
24558
24548
|
lineRange: null,
|
|
24559
24549
|
content: null
|
|
@@ -24582,10 +24572,6 @@ class PassageRef extends React.Component {
|
|
|
24582
24572
|
}
|
|
24583
24573
|
};
|
|
24584
24574
|
}
|
|
24585
|
-
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
24586
|
-
static validate() {
|
|
24587
|
-
return noopValidator();
|
|
24588
|
-
}
|
|
24589
24575
|
componentDidMount() {
|
|
24590
24576
|
// TODO(scottgrant): This is a hack to remove the deprecated call to
|
|
24591
24577
|
// this.isMounted() but is still considered an anti-pattern.
|
|
@@ -24604,15 +24590,6 @@ class PassageRef extends React.Component {
|
|
|
24604
24590
|
window.removeEventListener("resize", this._throttledUpdateRange);
|
|
24605
24591
|
this._isMounted = false;
|
|
24606
24592
|
}
|
|
24607
|
-
|
|
24608
|
-
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
24609
|
-
getUserInput() {
|
|
24610
|
-
return null;
|
|
24611
|
-
}
|
|
24612
|
-
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
24613
|
-
simpleValidate() {
|
|
24614
|
-
return noopValidator();
|
|
24615
|
-
}
|
|
24616
24593
|
render() {
|
|
24617
24594
|
const {
|
|
24618
24595
|
strings
|
|
@@ -24667,7 +24644,9 @@ var PassageRef$1 = {
|
|
|
24667
24644
|
version: {
|
|
24668
24645
|
major: 0,
|
|
24669
24646
|
minor: 1
|
|
24670
|
-
}
|
|
24647
|
+
},
|
|
24648
|
+
// TODO: things that aren't interactive shouldn't need validators
|
|
24649
|
+
validator: () => noopValidator()
|
|
24671
24650
|
};
|
|
24672
24651
|
|
|
24673
24652
|
/**
|
|
@@ -26169,7 +26148,7 @@ class Radio$1 extends React.Component {
|
|
|
26169
26148
|
choiceStates
|
|
26170
26149
|
} = this.props;
|
|
26171
26150
|
if (choiceStates) {
|
|
26172
|
-
const score = this.
|
|
26151
|
+
const score = radioValidator(this.getUserInput(), rubric, this.context.strings);
|
|
26173
26152
|
const widgetCorrect = score.type === "points" && score.total === score.earned;
|
|
26174
26153
|
const newStates = choiceStates.map(state => _extends({}, state, {
|
|
26175
26154
|
highlighted: state.selected,
|
|
@@ -26217,9 +26196,6 @@ class Radio$1 extends React.Component {
|
|
|
26217
26196
|
}
|
|
26218
26197
|
};
|
|
26219
26198
|
}
|
|
26220
|
-
static validate(userInput, rubric, strings) {
|
|
26221
|
-
return radioValidator(userInput, rubric, strings);
|
|
26222
|
-
}
|
|
26223
26199
|
static getUserInputFromProps(props) {
|
|
26224
26200
|
// Return checked inputs in the form {choicesSelected: [bool]}. (Dear
|
|
26225
26201
|
// future timeline implementers: this used to be {value: i} before
|
|
@@ -26310,9 +26286,6 @@ class Radio$1 extends React.Component {
|
|
|
26310
26286
|
getUserInput() {
|
|
26311
26287
|
return Radio$1.getUserInputFromProps(this.props);
|
|
26312
26288
|
}
|
|
26313
|
-
simpleValidate(rubric) {
|
|
26314
|
-
return radioValidator(this.getUserInput(), rubric, this.context.strings);
|
|
26315
|
-
}
|
|
26316
26289
|
render() {
|
|
26317
26290
|
const {
|
|
26318
26291
|
choices
|
|
@@ -26547,7 +26520,8 @@ var Radio = {
|
|
|
26547
26520
|
minor: 0
|
|
26548
26521
|
},
|
|
26549
26522
|
propUpgrades: propUpgrades$1,
|
|
26550
|
-
isLintable: true
|
|
26523
|
+
isLintable: true,
|
|
26524
|
+
validator: radioValidator
|
|
26551
26525
|
};
|
|
26552
26526
|
|
|
26553
26527
|
/* eslint-disable import/no-named-as-default */
|
|
@@ -26590,9 +26564,6 @@ class Categorizer extends React.Component {
|
|
|
26590
26564
|
return change.apply(this, args);
|
|
26591
26565
|
};
|
|
26592
26566
|
}
|
|
26593
|
-
static validate(userInput, rubric, strings) {
|
|
26594
|
-
return categorizerValidator(userInput, rubric, strings);
|
|
26595
|
-
}
|
|
26596
26567
|
static getUserInputFromProps(props) {
|
|
26597
26568
|
return {
|
|
26598
26569
|
values: props.values
|
|
@@ -26608,9 +26579,6 @@ class Categorizer extends React.Component {
|
|
|
26608
26579
|
this.change("values", values);
|
|
26609
26580
|
this.props.trackInteraction();
|
|
26610
26581
|
}
|
|
26611
|
-
simpleValidate(rubric) {
|
|
26612
|
-
return categorizerValidator(this.getUserInput(), rubric, this.context.strings);
|
|
26613
|
-
}
|
|
26614
26582
|
render() {
|
|
26615
26583
|
const self = this;
|
|
26616
26584
|
|
|
@@ -26756,7 +26724,8 @@ var Categorizer$1 = {
|
|
|
26756
26724
|
staticTransform: editorProps => {
|
|
26757
26725
|
return _.pick(editorProps, "items", "categories", "values", "randomizeItems");
|
|
26758
26726
|
},
|
|
26759
|
-
isLintable: true
|
|
26727
|
+
isLintable: true,
|
|
26728
|
+
validator: categorizerValidator
|
|
26760
26729
|
};
|
|
26761
26730
|
|
|
26762
26731
|
/**
|
|
@@ -26880,10 +26849,6 @@ class CSProgram extends React.Component {
|
|
|
26880
26849
|
return change.apply(this, args);
|
|
26881
26850
|
};
|
|
26882
26851
|
}
|
|
26883
|
-
// The widget's grading function
|
|
26884
|
-
static validate(state) {
|
|
26885
|
-
return csProgramValidator(state);
|
|
26886
|
-
}
|
|
26887
26852
|
componentDidMount() {
|
|
26888
26853
|
$(window).on("message", this.handleMessageEvent);
|
|
26889
26854
|
}
|
|
@@ -26896,9 +26861,6 @@ class CSProgram extends React.Component {
|
|
|
26896
26861
|
message: this.props.message
|
|
26897
26862
|
};
|
|
26898
26863
|
}
|
|
26899
|
-
simpleValidate() {
|
|
26900
|
-
return csProgramValidator(this.getUserInput());
|
|
26901
|
-
}
|
|
26902
26864
|
render() {
|
|
26903
26865
|
if (!this.props.programID) {
|
|
26904
26866
|
return /*#__PURE__*/React.createElement("div", null);
|
|
@@ -26980,21 +26942,16 @@ var CSProgram$1 = {
|
|
|
26980
26942
|
displayName: "CS Program",
|
|
26981
26943
|
supportedAlignments: ["block", "full-width"],
|
|
26982
26944
|
widget: CSProgram,
|
|
26983
|
-
hidden: true
|
|
26945
|
+
hidden: true,
|
|
26946
|
+
validator: csProgramValidator
|
|
26984
26947
|
};
|
|
26985
26948
|
|
|
26986
26949
|
class Definition extends React.Component {
|
|
26987
|
-
|
|
26988
|
-
|
|
26989
|
-
|
|
26990
|
-
|
|
26991
|
-
|
|
26992
|
-
return {};
|
|
26993
|
-
}
|
|
26994
|
-
|
|
26995
|
-
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
26996
|
-
simpleValidate() {
|
|
26997
|
-
return noopValidator();
|
|
26950
|
+
constructor(...args) {
|
|
26951
|
+
super(...args);
|
|
26952
|
+
// this just helps with TS weak typing when a Widget
|
|
26953
|
+
// doesn't implement any Widget methods
|
|
26954
|
+
this.isWidget = true;
|
|
26998
26955
|
}
|
|
26999
26956
|
render() {
|
|
27000
26957
|
return /*#__PURE__*/React.createElement(DefinitionConsumer, null, ({
|
|
@@ -27050,22 +27007,19 @@ var Definition$1 = {
|
|
|
27050
27007
|
accessible: true,
|
|
27051
27008
|
defaultAlignment: "inline",
|
|
27052
27009
|
widget: Definition,
|
|
27053
|
-
transform: x => x
|
|
27010
|
+
transform: x => x,
|
|
27011
|
+
// TODO: things that aren't interactive shouldn't need validators
|
|
27012
|
+
validator: () => noopValidator()
|
|
27054
27013
|
};
|
|
27055
27014
|
|
|
27056
27015
|
// The props are type `any` on purpose so that this can receive props
|
|
27057
27016
|
// from any deprecated widget
|
|
27058
27017
|
class DeprecatedStandin extends React__default.Component {
|
|
27059
|
-
|
|
27060
|
-
|
|
27061
|
-
//
|
|
27062
|
-
|
|
27063
|
-
|
|
27064
|
-
getUserInput() {
|
|
27065
|
-
return {};
|
|
27066
|
-
}
|
|
27067
|
-
simpleValidate() {
|
|
27068
|
-
return noopValidator(1);
|
|
27018
|
+
constructor(...args) {
|
|
27019
|
+
super(...args);
|
|
27020
|
+
// this just helps with TS weak typing when a Widget
|
|
27021
|
+
// doesn't implement any Widget methods
|
|
27022
|
+
this.isWidget = true;
|
|
27069
27023
|
}
|
|
27070
27024
|
render() {
|
|
27071
27025
|
return /*#__PURE__*/React__default.createElement("div", {
|
|
@@ -27085,7 +27039,9 @@ var DeprecatedStandin$1 = {
|
|
|
27085
27039
|
name: "deprecated-standin",
|
|
27086
27040
|
displayName: "Deprecated Standin",
|
|
27087
27041
|
widget: DeprecatedStandin,
|
|
27088
|
-
hidden: true
|
|
27042
|
+
hidden: true,
|
|
27043
|
+
// TODO: things that aren't interactive shouldn't need validators
|
|
27044
|
+
validator: () => noopValidator(1)
|
|
27089
27045
|
};
|
|
27090
27046
|
|
|
27091
27047
|
function dropdownValidator(userInput, rubric) {
|
|
@@ -27126,17 +27082,11 @@ class Dropdown extends React.Component {
|
|
|
27126
27082
|
});
|
|
27127
27083
|
};
|
|
27128
27084
|
}
|
|
27129
|
-
static validate(userInput, rubric) {
|
|
27130
|
-
return dropdownValidator(userInput, rubric);
|
|
27131
|
-
}
|
|
27132
27085
|
getUserInput() {
|
|
27133
27086
|
return {
|
|
27134
27087
|
value: this.props.selected
|
|
27135
27088
|
};
|
|
27136
27089
|
}
|
|
27137
|
-
simpleValidate(rubric) {
|
|
27138
|
-
return dropdownValidator(this.getUserInput(), rubric);
|
|
27139
|
-
}
|
|
27140
27090
|
render() {
|
|
27141
27091
|
const children = [/*#__PURE__*/React.createElement(OptionItem, {
|
|
27142
27092
|
key: "placeholder",
|
|
@@ -27183,7 +27133,8 @@ var Dropdown$1 = {
|
|
|
27183
27133
|
defaultAlignment: "inline-block",
|
|
27184
27134
|
accessible: true,
|
|
27185
27135
|
widget: Dropdown,
|
|
27186
|
-
transform: optionsTransform
|
|
27136
|
+
transform: optionsTransform,
|
|
27137
|
+
validator: dropdownValidator
|
|
27187
27138
|
};
|
|
27188
27139
|
|
|
27189
27140
|
// transform = _.identity
|
|
@@ -27197,6 +27148,9 @@ function mediaQueryIsMatched(mediaQuery) {
|
|
|
27197
27148
|
class Explanation extends React.Component {
|
|
27198
27149
|
constructor(..._args) {
|
|
27199
27150
|
super(..._args);
|
|
27151
|
+
// this just helps with TS weak typing when a Widget
|
|
27152
|
+
// doesn't implement any Widget methods
|
|
27153
|
+
this.isWidget = true;
|
|
27200
27154
|
this.state = {
|
|
27201
27155
|
expanded: false
|
|
27202
27156
|
};
|
|
@@ -27211,24 +27165,12 @@ class Explanation extends React.Component {
|
|
|
27211
27165
|
this.props.trackInteraction();
|
|
27212
27166
|
};
|
|
27213
27167
|
}
|
|
27214
|
-
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
27215
|
-
static validate() {
|
|
27216
|
-
return noopValidator();
|
|
27217
|
-
}
|
|
27218
27168
|
componentDidMount() {
|
|
27219
27169
|
this._mounted = true;
|
|
27220
27170
|
}
|
|
27221
27171
|
componentWillUnmount() {
|
|
27222
27172
|
this._mounted = false;
|
|
27223
27173
|
}
|
|
27224
|
-
getUserInput() {
|
|
27225
|
-
return {};
|
|
27226
|
-
}
|
|
27227
|
-
|
|
27228
|
-
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
27229
|
-
simpleValidate() {
|
|
27230
|
-
return noopValidator();
|
|
27231
|
-
}
|
|
27232
27174
|
render() {
|
|
27233
27175
|
const promptText = this.state.expanded ? this.props.hidePrompt : this.props.showPrompt;
|
|
27234
27176
|
const caretIcon = this.state.expanded ? caretUp : caretDown;
|
|
@@ -27342,7 +27284,9 @@ var Explanation$1 = {
|
|
|
27342
27284
|
defaultAlignment: "inline",
|
|
27343
27285
|
widget: Explanation,
|
|
27344
27286
|
transform: _.identity,
|
|
27345
|
-
isLintable: true
|
|
27287
|
+
isLintable: true,
|
|
27288
|
+
// TODO: things that aren't interactive shouldn't need validators
|
|
27289
|
+
validator: () => noopValidator()
|
|
27346
27290
|
};
|
|
27347
27291
|
|
|
27348
27292
|
class GradedGroupAnswerBar extends React.Component {
|
|
@@ -28942,9 +28886,6 @@ class Grapher extends React.Component {
|
|
|
28942
28886
|
}
|
|
28943
28887
|
};
|
|
28944
28888
|
}
|
|
28945
|
-
static validate(state, rubric) {
|
|
28946
|
-
return grapherValidator(state, rubric);
|
|
28947
|
-
}
|
|
28948
28889
|
static getUserInputFromProps(props) {
|
|
28949
28890
|
return props.plot;
|
|
28950
28891
|
}
|
|
@@ -28963,9 +28904,6 @@ class Grapher extends React.Component {
|
|
|
28963
28904
|
tickStep[1] = tickStep[1] / gridStep[1];
|
|
28964
28905
|
return tickStep;
|
|
28965
28906
|
}
|
|
28966
|
-
simpleValidate(rubric) {
|
|
28967
|
-
return grapherValidator(this.getUserInput(), rubric);
|
|
28968
|
-
}
|
|
28969
28907
|
getUserInput() {
|
|
28970
28908
|
return Grapher.getUserInputFromProps(this.props);
|
|
28971
28909
|
}
|
|
@@ -29053,7 +28991,8 @@ var Grapher$1 = {
|
|
|
29053
28991
|
hidden: true,
|
|
29054
28992
|
widget: Grapher,
|
|
29055
28993
|
transform: propTransform$2,
|
|
29056
|
-
staticTransform: staticTransform$4
|
|
28994
|
+
staticTransform: staticTransform$4,
|
|
28995
|
+
validator: grapherValidator
|
|
29057
28996
|
};
|
|
29058
28997
|
|
|
29059
28998
|
// exports has no 'transform'
|
|
@@ -29099,17 +29038,18 @@ class Group extends React.Component {
|
|
|
29099
29038
|
// the group with the correct number.
|
|
29100
29039
|
this.forceUpdate();
|
|
29101
29040
|
}
|
|
29102
|
-
|
|
29041
|
+
getUserInputMap() {
|
|
29103
29042
|
var _this$rendererRef7;
|
|
29104
|
-
return (_this$rendererRef7 = this.rendererRef) == null ? void 0 : _this$rendererRef7.
|
|
29105
|
-
}
|
|
29106
|
-
simpleValidate() {
|
|
29107
|
-
var _this$rendererRef$sco, _this$rendererRef8;
|
|
29108
|
-
return (_this$rendererRef$sco = (_this$rendererRef8 = this.rendererRef) == null ? void 0 : _this$rendererRef8.score()) != null ? _this$rendererRef$sco : {
|
|
29109
|
-
type: "invalid"
|
|
29110
|
-
};
|
|
29043
|
+
return (_this$rendererRef7 = this.rendererRef) == null ? void 0 : _this$rendererRef7.getUserInputMap();
|
|
29111
29044
|
}
|
|
29112
29045
|
|
|
29046
|
+
/**
|
|
29047
|
+
* @deprecated getUserInputMap should be used for Groups
|
|
29048
|
+
*/
|
|
29049
|
+
getUserInput() {
|
|
29050
|
+
var _this$rendererRef8;
|
|
29051
|
+
return (_this$rendererRef8 = this.rendererRef) == null ? void 0 : _this$rendererRef8.getUserInput();
|
|
29052
|
+
}
|
|
29113
29053
|
// Mobile API:
|
|
29114
29054
|
getInputPaths() {
|
|
29115
29055
|
var _this$rendererRef$get, _this$rendererRef9;
|
|
@@ -29270,9 +29210,6 @@ class Iframe extends React.Component {
|
|
|
29270
29210
|
return change.apply(this, args);
|
|
29271
29211
|
};
|
|
29272
29212
|
}
|
|
29273
|
-
static validate(state) {
|
|
29274
|
-
return iframeValidator(state);
|
|
29275
|
-
}
|
|
29276
29213
|
componentDidMount() {
|
|
29277
29214
|
$(window).on("message", this.handleMessageEvent);
|
|
29278
29215
|
}
|
|
@@ -29285,9 +29222,6 @@ class Iframe extends React.Component {
|
|
|
29285
29222
|
message: this.props.message
|
|
29286
29223
|
};
|
|
29287
29224
|
}
|
|
29288
|
-
simpleValidate() {
|
|
29289
|
-
return iframeValidator(this.getUserInput());
|
|
29290
|
-
}
|
|
29291
29225
|
render() {
|
|
29292
29226
|
const style = {
|
|
29293
29227
|
width: String(this.props.width),
|
|
@@ -29361,7 +29295,8 @@ var Iframe$1 = {
|
|
|
29361
29295
|
displayName: "Iframe (deprecated)",
|
|
29362
29296
|
widget: Iframe,
|
|
29363
29297
|
// Let's not expose it to all content creators yet
|
|
29364
|
-
hidden: true
|
|
29298
|
+
hidden: true,
|
|
29299
|
+
validator: iframeValidator
|
|
29365
29300
|
};
|
|
29366
29301
|
|
|
29367
29302
|
const defaultBoxSize = 400;
|
|
@@ -29379,22 +29314,13 @@ const DEFAULT_ALIGNMENT = "block";
|
|
|
29379
29314
|
class ImageWidget extends React.Component {
|
|
29380
29315
|
constructor(..._args) {
|
|
29381
29316
|
super(..._args);
|
|
29317
|
+
// this just helps with TS weak typing when a Widget
|
|
29318
|
+
// doesn't implement any Widget methods
|
|
29319
|
+
this.isWidget = true;
|
|
29382
29320
|
this.change = (...args) => {
|
|
29383
29321
|
return change.apply(this, args);
|
|
29384
29322
|
};
|
|
29385
29323
|
}
|
|
29386
|
-
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
29387
|
-
static validate() {
|
|
29388
|
-
return noopValidator();
|
|
29389
|
-
}
|
|
29390
|
-
getUserInput() {
|
|
29391
|
-
return null;
|
|
29392
|
-
}
|
|
29393
|
-
|
|
29394
|
-
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
29395
|
-
simpleValidate() {
|
|
29396
|
-
return noopValidator();
|
|
29397
|
-
}
|
|
29398
29324
|
render() {
|
|
29399
29325
|
let image;
|
|
29400
29326
|
const alt = this.props.caption === this.props.alt ? "" : this.props.alt;
|
|
@@ -29549,7 +29475,9 @@ var Image$1 = {
|
|
|
29549
29475
|
supportedAlignments: editorAlignments,
|
|
29550
29476
|
displayName: "Image",
|
|
29551
29477
|
widget: ImageWidget,
|
|
29552
|
-
isLintable: true
|
|
29478
|
+
isLintable: true,
|
|
29479
|
+
// TODO: things that aren't interactive shouldn't need validators
|
|
29480
|
+
validator: () => noopValidator()
|
|
29553
29481
|
};
|
|
29554
29482
|
|
|
29555
29483
|
/* eslint-disable @khanacademy/ts-no-error-suppressions */
|
|
@@ -29618,6 +29546,9 @@ const KAScompile = (expr, options) => {
|
|
|
29618
29546
|
class Interaction extends React.Component {
|
|
29619
29547
|
constructor(..._args) {
|
|
29620
29548
|
super(..._args);
|
|
29549
|
+
// this just helps with TS weak typing when a Widget
|
|
29550
|
+
// doesn't implement any Widget methods
|
|
29551
|
+
this.isWidget = true;
|
|
29621
29552
|
this.state = {
|
|
29622
29553
|
variables: _getInitialVariables(this.props.elements),
|
|
29623
29554
|
functions: _getInitialFunctions(this.props.elements)
|
|
@@ -29701,10 +29632,6 @@ class Interaction extends React.Component {
|
|
|
29701
29632
|
return change.apply(this, args);
|
|
29702
29633
|
};
|
|
29703
29634
|
}
|
|
29704
|
-
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
29705
|
-
static validate() {
|
|
29706
|
-
return noopValidator();
|
|
29707
|
-
}
|
|
29708
29635
|
UNSAFE_componentWillReceiveProps(nextProps) {
|
|
29709
29636
|
// HACK(michaelpolyak): This widget is not wired to use the Perseus
|
|
29710
29637
|
// `onChange` callback to save user changes. Perseus re-rendering of the
|
|
@@ -29723,18 +29650,6 @@ class Interaction extends React.Component {
|
|
|
29723
29650
|
});
|
|
29724
29651
|
}
|
|
29725
29652
|
}
|
|
29726
|
-
getUserInput() {
|
|
29727
|
-
// TODO(eater): Perhaps we want to be able to record the state of the
|
|
29728
|
-
// user's interaction. Unfortunately sending all the props will
|
|
29729
|
-
// probably make the attempt payload too large. So for now, don't send
|
|
29730
|
-
// anything.
|
|
29731
|
-
return {};
|
|
29732
|
-
}
|
|
29733
|
-
|
|
29734
|
-
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
29735
|
-
simpleValidate() {
|
|
29736
|
-
return noopValidator();
|
|
29737
|
-
}
|
|
29738
29653
|
render() {
|
|
29739
29654
|
const range = this.props.graph.range;
|
|
29740
29655
|
let labels = this.props.graph.labels;
|
|
@@ -30153,7 +30068,9 @@ var Interactive = {
|
|
|
30153
30068
|
displayName: "Interaction",
|
|
30154
30069
|
widget: Interaction,
|
|
30155
30070
|
transform: _.identity,
|
|
30156
|
-
hidden: true
|
|
30071
|
+
hidden: true,
|
|
30072
|
+
// TODO: things that aren't interactive shouldn't need validators
|
|
30073
|
+
validator: () => noopValidator()
|
|
30157
30074
|
};
|
|
30158
30075
|
|
|
30159
30076
|
/* eslint-disable @khanacademy/ts-no-error-suppressions */
|
|
@@ -37239,9 +37156,6 @@ class LegacyInteractiveGraph extends React.Component {
|
|
|
37239
37156
|
getUserInput() {
|
|
37240
37157
|
return InteractiveGraph.getUserInputFromProps(this.props);
|
|
37241
37158
|
}
|
|
37242
|
-
simpleValidate(rubric) {
|
|
37243
|
-
return interactiveGraphValidator(this.getUserInput(), rubric);
|
|
37244
|
-
}
|
|
37245
37159
|
render() {
|
|
37246
37160
|
const box = getInteractiveBoxFromSizeClass(this.props.containerSizeClass);
|
|
37247
37161
|
const gridStep = this.props.gridStep || Util.getGridStep(this.props.range, this.props.step, box[0]);
|
|
@@ -37318,9 +37232,6 @@ class InteractiveGraph extends React.Component {
|
|
|
37318
37232
|
}
|
|
37319
37233
|
throw new PerseusError("Cannot getUserInput from a graph that has never rendered", Errors.NotAllowed);
|
|
37320
37234
|
}
|
|
37321
|
-
simpleValidate(rubric) {
|
|
37322
|
-
return interactiveGraphValidator(this.getUserInput(), rubric);
|
|
37323
|
-
}
|
|
37324
37235
|
render() {
|
|
37325
37236
|
var _this$props$apiOption;
|
|
37326
37237
|
// Mafs shim
|
|
@@ -37653,9 +37564,6 @@ class InteractiveGraph extends React.Component {
|
|
|
37653
37564
|
const angle = getClockwiseAngle(coords, allowReflexAngles);
|
|
37654
37565
|
return angle.toFixed(0) + "\u00B0 angle" + " at (" + coords[1].join(", ") + ")";
|
|
37655
37566
|
}
|
|
37656
|
-
static validate(userInput, rubric) {
|
|
37657
|
-
return interactiveGraphValidator(userInput, rubric);
|
|
37658
|
-
}
|
|
37659
37567
|
static getUserInputFromProps(props) {
|
|
37660
37568
|
return props.graph;
|
|
37661
37569
|
}
|
|
@@ -37704,7 +37612,8 @@ var InteractiveGraph$1 = {
|
|
|
37704
37612
|
name: "interactive-graph",
|
|
37705
37613
|
displayName: "Interactive graph (Assessments only)",
|
|
37706
37614
|
widget: InteractiveGraph,
|
|
37707
|
-
staticTransform: staticTransform$3
|
|
37615
|
+
staticTransform: staticTransform$3,
|
|
37616
|
+
validator: interactiveGraphValidator
|
|
37708
37617
|
};
|
|
37709
37618
|
|
|
37710
37619
|
const black = "#000000";
|
|
@@ -39069,10 +38978,6 @@ const styles$b = StyleSheet.create({
|
|
|
39069
38978
|
// TODO: should this be using WidgetProps / PerseusLabelImageWidgetOptions?
|
|
39070
38979
|
|
|
39071
38980
|
class LabelImage extends React.Component {
|
|
39072
|
-
static validate(state, rubric) {
|
|
39073
|
-
return labelImageValidator(state);
|
|
39074
|
-
}
|
|
39075
|
-
|
|
39076
38981
|
/**
|
|
39077
38982
|
* Test whether point is contained within triangle.
|
|
39078
38983
|
*
|
|
@@ -39267,9 +39172,6 @@ class LabelImage extends React.Component {
|
|
|
39267
39172
|
componentWillUnmount() {
|
|
39268
39173
|
this._mounted = false;
|
|
39269
39174
|
}
|
|
39270
|
-
simpleValidate(rubric) {
|
|
39271
|
-
return labelImageValidator(this.getUserInput());
|
|
39272
|
-
}
|
|
39273
39175
|
getUserInput() {
|
|
39274
39176
|
const {
|
|
39275
39177
|
markers
|
|
@@ -39626,19 +39528,13 @@ const LabelImageWithDependencies = /*#__PURE__*/React.forwardRef((props, ref) =>
|
|
|
39626
39528
|
analytics: deps.analytics
|
|
39627
39529
|
}, props));
|
|
39628
39530
|
});
|
|
39629
|
-
|
|
39630
|
-
// HACK: Propogate "static" methods onto our wrapper component.
|
|
39631
|
-
// In the future we should adjust client apps to not depend on these static
|
|
39632
|
-
// methods and instead adjust Peresus to provide these facilities through
|
|
39633
|
-
// instance methods on our Renderers.
|
|
39634
|
-
// @ts-expect-error - TS2339 - Property 'validate' does not exist on type
|
|
39635
|
-
LabelImageWithDependencies.validate = labelImageValidator;
|
|
39636
39531
|
var LabelImage$1 = {
|
|
39637
39532
|
name: "label-image",
|
|
39638
39533
|
displayName: "Label Image",
|
|
39639
39534
|
widget: LabelImageWithDependencies,
|
|
39640
39535
|
accessible: true,
|
|
39641
|
-
isLintable: true
|
|
39536
|
+
isLintable: true,
|
|
39537
|
+
validator: labelImageValidator
|
|
39642
39538
|
};
|
|
39643
39539
|
|
|
39644
39540
|
var ItemState = /*#__PURE__*/function (ItemState) {
|
|
@@ -40423,12 +40319,6 @@ class Matcher extends React.Component {
|
|
|
40423
40319
|
this.refs.right.moveOptionToIndex(option, index);
|
|
40424
40320
|
};
|
|
40425
40321
|
}
|
|
40426
|
-
static validate(state, rubric) {
|
|
40427
|
-
return matcherValidator(state, rubric);
|
|
40428
|
-
}
|
|
40429
|
-
simpleValidate(rubric) {
|
|
40430
|
-
return matcherValidator(this.getUserInput(), rubric);
|
|
40431
|
-
}
|
|
40432
40322
|
render() {
|
|
40433
40323
|
// To minimize layout shift, we display a spinner until our math
|
|
40434
40324
|
// renderer is ready to render the math inside the matcher. To
|
|
@@ -40566,7 +40456,8 @@ var Matcher$1 = {
|
|
|
40566
40456
|
name: "matcher",
|
|
40567
40457
|
displayName: "Matcher (two column)",
|
|
40568
40458
|
widget: Matcher,
|
|
40569
|
-
isLintable: true
|
|
40459
|
+
isLintable: true,
|
|
40460
|
+
validator: matcherValidator
|
|
40570
40461
|
};
|
|
40571
40462
|
|
|
40572
40463
|
function matrixValidator(state, rubric, strings) {
|
|
@@ -40828,9 +40719,6 @@ class Matrix extends React.Component {
|
|
|
40828
40719
|
this.props.trackInteraction();
|
|
40829
40720
|
};
|
|
40830
40721
|
}
|
|
40831
|
-
static validate(state, rubric, strings) {
|
|
40832
|
-
return matrixValidator(state, rubric, strings);
|
|
40833
|
-
}
|
|
40834
40722
|
componentDidMount() {
|
|
40835
40723
|
// Used in the `onBlur` and `onFocus` handlers
|
|
40836
40724
|
this.cursorPosition = [0, 0];
|
|
@@ -40845,9 +40733,6 @@ class Matrix extends React.Component {
|
|
|
40845
40733
|
answers: this.props.answers
|
|
40846
40734
|
};
|
|
40847
40735
|
}
|
|
40848
|
-
simpleValidate(rubric) {
|
|
40849
|
-
return matrixValidator(this.getUserInput(), rubric, this.context.strings);
|
|
40850
|
-
}
|
|
40851
40736
|
render() {
|
|
40852
40737
|
// Set the input sizes through JS so we can control the size of the
|
|
40853
40738
|
// brackets. (If we set them in CSS we won't know values until the
|
|
@@ -41040,7 +40925,8 @@ var Matrix$1 = {
|
|
|
41040
40925
|
widget: Matrix,
|
|
41041
40926
|
transform: propTransform$1,
|
|
41042
40927
|
staticTransform: staticTransform$2,
|
|
41043
|
-
isLintable: true
|
|
40928
|
+
isLintable: true,
|
|
40929
|
+
validator: matrixValidator
|
|
41044
40930
|
};
|
|
41045
40931
|
|
|
41046
40932
|
const defaultImage = {
|
|
@@ -41051,6 +40937,9 @@ const defaultImage = {
|
|
|
41051
40937
|
class Measurer extends React.Component {
|
|
41052
40938
|
constructor(...args) {
|
|
41053
40939
|
super(...args);
|
|
40940
|
+
// this just helps with TS weak typing when a Widget
|
|
40941
|
+
// doesn't implement any Widget methods
|
|
40942
|
+
this.isWidget = true;
|
|
41054
40943
|
this.state = {};
|
|
41055
40944
|
this.ruler = void 0;
|
|
41056
40945
|
this.protractor = void 0;
|
|
@@ -41104,12 +40993,6 @@ class Measurer extends React.Component {
|
|
|
41104
40993
|
});
|
|
41105
40994
|
}
|
|
41106
40995
|
}
|
|
41107
|
-
getUserInput() {
|
|
41108
|
-
return {};
|
|
41109
|
-
}
|
|
41110
|
-
simpleValidate() {
|
|
41111
|
-
return noopValidator(1);
|
|
41112
|
-
}
|
|
41113
40996
|
render() {
|
|
41114
40997
|
const image = _.extend({}, defaultImage, this.props.image);
|
|
41115
40998
|
|
|
@@ -41135,7 +41018,6 @@ class Measurer extends React.Component {
|
|
|
41135
41018
|
}));
|
|
41136
41019
|
}
|
|
41137
41020
|
}
|
|
41138
|
-
Measurer.validate = noopValidator;
|
|
41139
41021
|
Measurer.defaultProps = {
|
|
41140
41022
|
box: [480, 480],
|
|
41141
41023
|
image: {},
|
|
@@ -41169,7 +41051,9 @@ var Measurer$1 = {
|
|
|
41169
41051
|
major: 1,
|
|
41170
41052
|
minor: 0
|
|
41171
41053
|
},
|
|
41172
|
-
propUpgrades: propUpgrades
|
|
41054
|
+
propUpgrades: propUpgrades,
|
|
41055
|
+
// TODO: things that aren't interactive shouldn't need validators
|
|
41056
|
+
validator: () => noopValidator(1)
|
|
41173
41057
|
};
|
|
41174
41058
|
|
|
41175
41059
|
/**
|
|
@@ -42036,17 +41920,11 @@ class Molecule extends React.Component {
|
|
|
42036
41920
|
}
|
|
42037
41921
|
Molecule.contextType = PerseusI18nContext;
|
|
42038
41922
|
class MoleculeWidget extends React.Component {
|
|
42039
|
-
|
|
42040
|
-
|
|
42041
|
-
|
|
42042
|
-
|
|
42043
|
-
|
|
42044
|
-
return [];
|
|
42045
|
-
}
|
|
42046
|
-
|
|
42047
|
-
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
42048
|
-
validate() {
|
|
42049
|
-
return noopValidator();
|
|
41923
|
+
constructor(...args) {
|
|
41924
|
+
super(...args);
|
|
41925
|
+
// this just helps with TS weak typing when a Widget
|
|
41926
|
+
// doesn't implement any Widget methods
|
|
41927
|
+
this.isWidget = true;
|
|
42050
41928
|
}
|
|
42051
41929
|
render() {
|
|
42052
41930
|
return /*#__PURE__*/React.createElement(Molecule, {
|
|
@@ -42063,7 +41941,8 @@ var Molecule$1 = {
|
|
|
42063
41941
|
name: "molecule-renderer",
|
|
42064
41942
|
displayName: "Molecule renderer",
|
|
42065
41943
|
hidden: true,
|
|
42066
|
-
widget: MoleculeWidget
|
|
41944
|
+
widget: MoleculeWidget,
|
|
41945
|
+
validator: () => noopValidator()
|
|
42067
41946
|
};
|
|
42068
41947
|
|
|
42069
41948
|
function numberLineValidator(state, rubric) {
|
|
@@ -42208,18 +42087,16 @@ const TickMarks = Graphie.createSimpleClass((graphie, props) => {
|
|
|
42208
42087
|
results.push(graphie.line([x, -0.2], [x, 0.2]));
|
|
42209
42088
|
const labelTicks = props.labelTicks;
|
|
42210
42089
|
if (labelTicks || props.labelStyle === "decimal ticks") {
|
|
42211
|
-
|
|
42090
|
+
if (x === leftLabel || x === rightLabel) {
|
|
42091
|
+
results.push(graphie.style({
|
|
42092
|
+
color: KhanColors.BLUE
|
|
42093
|
+
}, () => _label(graphie, props.labelStyle, x, x, base)));
|
|
42094
|
+
} else {
|
|
42095
|
+
results.push(_label(graphie, props.labelStyle, x, x, base));
|
|
42096
|
+
}
|
|
42212
42097
|
}
|
|
42213
42098
|
}
|
|
42214
42099
|
|
|
42215
|
-
// Render the text labels
|
|
42216
|
-
results.push(graphie.style(props.isMobile ? {
|
|
42217
|
-
color: KhanColors.BLUE
|
|
42218
|
-
} : {}, () => _label(graphie, props.labelStyle, leftLabel, leftLabel, base)));
|
|
42219
|
-
results.push(graphie.style(props.isMobile ? {
|
|
42220
|
-
color: KhanColors.BLUE
|
|
42221
|
-
} : {}, () => _label(graphie, props.labelStyle, rightLabel, rightLabel, base)));
|
|
42222
|
-
|
|
42223
42100
|
// Render the labels' lines
|
|
42224
42101
|
graphie.style({
|
|
42225
42102
|
stroke: KhanColors.BLUE,
|
|
@@ -42494,9 +42371,6 @@ class NumberLine extends React.Component {
|
|
|
42494
42371
|
});
|
|
42495
42372
|
};
|
|
42496
42373
|
}
|
|
42497
|
-
static validate(state, rubric) {
|
|
42498
|
-
return numberLineValidator(state, rubric);
|
|
42499
|
-
}
|
|
42500
42374
|
focus() {
|
|
42501
42375
|
if (this.props.isTickCtrl) {
|
|
42502
42376
|
// eslint-disable-next-line react/no-string-refs
|
|
@@ -42526,9 +42400,6 @@ class NumberLine extends React.Component {
|
|
|
42526
42400
|
divisionRange: this.props.divisionRange
|
|
42527
42401
|
};
|
|
42528
42402
|
}
|
|
42529
|
-
simpleValidate(rubric) {
|
|
42530
|
-
return numberLineValidator(this.getUserInput(), rubric);
|
|
42531
|
-
}
|
|
42532
42403
|
render() {
|
|
42533
42404
|
const {
|
|
42534
42405
|
strings
|
|
@@ -42647,7 +42518,8 @@ var NumberLine$1 = {
|
|
|
42647
42518
|
displayName: "Number line",
|
|
42648
42519
|
widget: NumberLine,
|
|
42649
42520
|
transform: numberLineTransform,
|
|
42650
|
-
staticTransform: staticTransform$1
|
|
42521
|
+
staticTransform: staticTransform$1,
|
|
42522
|
+
validator: numberLineValidator
|
|
42651
42523
|
};
|
|
42652
42524
|
|
|
42653
42525
|
function ordererValidator(userInput, rubric) {
|
|
@@ -43080,9 +42952,6 @@ class Orderer extends React.Component {
|
|
|
43080
42952
|
});
|
|
43081
42953
|
};
|
|
43082
42954
|
}
|
|
43083
|
-
static validate(userInput, rubric) {
|
|
43084
|
-
return ordererValidator(userInput, rubric);
|
|
43085
|
-
}
|
|
43086
42955
|
UNSAFE_componentWillReceiveProps(nextProps) {
|
|
43087
42956
|
if (!_.isEqual(this.props.current, nextProps.current)) {
|
|
43088
42957
|
this.setState({
|
|
@@ -43097,9 +42966,6 @@ class Orderer extends React.Component {
|
|
|
43097
42966
|
})
|
|
43098
42967
|
};
|
|
43099
42968
|
}
|
|
43100
|
-
simpleValidate(rubric) {
|
|
43101
|
-
return ordererValidator(this.getUserInput(), rubric);
|
|
43102
|
-
}
|
|
43103
42969
|
render() {
|
|
43104
42970
|
// This is the card we are currently dragging
|
|
43105
42971
|
const dragging = this.state.dragging && /*#__PURE__*/React.createElement(Card
|
|
@@ -43217,31 +43083,22 @@ var Orderer$1 = {
|
|
|
43217
43083
|
displayName: "Orderer",
|
|
43218
43084
|
hidden: true,
|
|
43219
43085
|
widget: Orderer,
|
|
43220
|
-
isLintable: true
|
|
43086
|
+
isLintable: true,
|
|
43087
|
+
validator: ordererValidator
|
|
43221
43088
|
};
|
|
43222
43089
|
|
|
43223
43090
|
/* eslint-disable @khanacademy/ts-no-error-suppressions */
|
|
43224
43091
|
class PassageRefTarget extends React.Component {
|
|
43225
43092
|
constructor(..._args) {
|
|
43226
43093
|
super(..._args);
|
|
43094
|
+
// this just helps with TS weak typing when a Widget
|
|
43095
|
+
// doesn't implement any Widget methods
|
|
43096
|
+
this.isWidget = true;
|
|
43227
43097
|
// TODO passage-ref-target isn't interactive; remove
|
|
43228
43098
|
this.change = (...args) => {
|
|
43229
43099
|
return change.apply(this, args);
|
|
43230
43100
|
};
|
|
43231
43101
|
}
|
|
43232
|
-
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
43233
|
-
static validate() {
|
|
43234
|
-
return noopValidator();
|
|
43235
|
-
}
|
|
43236
|
-
|
|
43237
|
-
// TODO passage-ref-target isn't interactive; remove
|
|
43238
|
-
getUserInput() {
|
|
43239
|
-
return null;
|
|
43240
|
-
}
|
|
43241
|
-
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
43242
|
-
simpleValidate() {
|
|
43243
|
-
return noopValidator();
|
|
43244
|
-
}
|
|
43245
43102
|
render() {
|
|
43246
43103
|
return /*#__PURE__*/React.createElement(Renderer, {
|
|
43247
43104
|
content: this.props.content
|
|
@@ -43275,7 +43132,9 @@ var PassageRefTarget$1 = {
|
|
|
43275
43132
|
major: 0,
|
|
43276
43133
|
minor: 0
|
|
43277
43134
|
},
|
|
43278
|
-
isLintable: true
|
|
43135
|
+
isLintable: true,
|
|
43136
|
+
// TODO: things that aren't interactive shouldn't need validators
|
|
43137
|
+
validator: () => noopValidator()
|
|
43279
43138
|
};
|
|
43280
43139
|
|
|
43281
43140
|
/**
|
|
@@ -43288,6 +43147,9 @@ class PhetSimulation extends React.Component {
|
|
|
43288
43147
|
super(props);
|
|
43289
43148
|
this.iframeRef = /*#__PURE__*/React.createRef();
|
|
43290
43149
|
this.locale = void 0;
|
|
43150
|
+
// this just helps with TS weak typing when a Widget
|
|
43151
|
+
// doesn't implement any Widget methods
|
|
43152
|
+
this.isWidget = true;
|
|
43291
43153
|
this.state = {
|
|
43292
43154
|
url: null,
|
|
43293
43155
|
banner: null
|
|
@@ -43330,11 +43192,6 @@ class PhetSimulation extends React.Component {
|
|
|
43330
43192
|
await this.updateSimState(this.props.url);
|
|
43331
43193
|
}
|
|
43332
43194
|
}
|
|
43333
|
-
|
|
43334
|
-
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
43335
|
-
getUserInput() {
|
|
43336
|
-
return null;
|
|
43337
|
-
}
|
|
43338
43195
|
async updateSimState(urlString) {
|
|
43339
43196
|
const url = makeSafeUrl(urlString, this.locale);
|
|
43340
43197
|
if (url === null) {
|
|
@@ -44233,9 +44090,6 @@ class Plotter extends React.Component {
|
|
|
44233
44090
|
});
|
|
44234
44091
|
};
|
|
44235
44092
|
}
|
|
44236
|
-
static validate(userInput, rubric) {
|
|
44237
|
-
return plotterValidator(userInput, rubric);
|
|
44238
|
-
}
|
|
44239
44093
|
componentDidMount() {
|
|
44240
44094
|
this._isMounted = true;
|
|
44241
44095
|
this.setupGraphie(this.state);
|
|
@@ -44262,9 +44116,6 @@ class Plotter extends React.Component {
|
|
|
44262
44116
|
getUserInput() {
|
|
44263
44117
|
return this.state.values;
|
|
44264
44118
|
}
|
|
44265
|
-
simpleValidate(rubric) {
|
|
44266
|
-
return plotterValidator(this.getUserInput(), rubric);
|
|
44267
|
-
}
|
|
44268
44119
|
render() {
|
|
44269
44120
|
// TODO(kevinb) actually compute the size of the graphie correctly and
|
|
44270
44121
|
// make it that size so we don't have to add extra padding. The value
|
|
@@ -44304,7 +44155,8 @@ var Plotter$1 = {
|
|
|
44304
44155
|
displayName: "Plotter",
|
|
44305
44156
|
hidden: true,
|
|
44306
44157
|
widget: Plotter,
|
|
44307
|
-
staticTransform: staticTransform
|
|
44158
|
+
staticTransform: staticTransform,
|
|
44159
|
+
validator: plotterValidator
|
|
44308
44160
|
};
|
|
44309
44161
|
|
|
44310
44162
|
/**
|
|
@@ -44420,9 +44272,6 @@ class Sorter extends React.Component {
|
|
|
44420
44272
|
this.refs.sortable.moveOptionToIndex(option, index);
|
|
44421
44273
|
};
|
|
44422
44274
|
}
|
|
44423
|
-
static validate(userInput, rubric) {
|
|
44424
|
-
return sorterValidator(userInput, rubric);
|
|
44425
|
-
}
|
|
44426
44275
|
componentDidMount() {
|
|
44427
44276
|
this._isMounted = true;
|
|
44428
44277
|
}
|
|
@@ -44438,9 +44287,6 @@ class Sorter extends React.Component {
|
|
|
44438
44287
|
changed: this.state.changed
|
|
44439
44288
|
};
|
|
44440
44289
|
}
|
|
44441
|
-
simpleValidate(rubric) {
|
|
44442
|
-
return sorterValidator(this.getUserInput(), rubric);
|
|
44443
|
-
}
|
|
44444
44290
|
render() {
|
|
44445
44291
|
const options = shuffle(this.props.correct, this.props.problemNum, /* ensurePermuted */true);
|
|
44446
44292
|
const {
|
|
@@ -44474,7 +44320,8 @@ var Sorter$1 = {
|
|
|
44474
44320
|
name: "sorter",
|
|
44475
44321
|
displayName: "Sorter",
|
|
44476
44322
|
widget: Sorter,
|
|
44477
|
-
isLintable: true
|
|
44323
|
+
isLintable: true,
|
|
44324
|
+
validator: sorterValidator
|
|
44478
44325
|
};
|
|
44479
44326
|
|
|
44480
44327
|
function tableValidator(state, rubric, strings) {
|
|
@@ -44653,15 +44500,9 @@ class Table extends React.Component {
|
|
|
44653
44500
|
}, cb);
|
|
44654
44501
|
};
|
|
44655
44502
|
}
|
|
44656
|
-
static validate(state, rubric, strings) {
|
|
44657
|
-
return tableValidator(state, rubric, strings);
|
|
44658
|
-
}
|
|
44659
44503
|
getUserInput() {
|
|
44660
44504
|
return _.map(this.props.answers, _.clone);
|
|
44661
44505
|
}
|
|
44662
|
-
simpleValidate(rubric) {
|
|
44663
|
-
return tableValidator(this.getUserInput(), rubric, this.context.strings);
|
|
44664
|
-
}
|
|
44665
44506
|
getDOMNodeForPath(path) {
|
|
44666
44507
|
const inputID = getRefForPath(path);
|
|
44667
44508
|
// eslint-disable-next-line react/no-string-refs
|
|
@@ -44762,7 +44603,8 @@ var Table$1 = {
|
|
|
44762
44603
|
widget: Table,
|
|
44763
44604
|
transform: propTransform,
|
|
44764
44605
|
hidden: true,
|
|
44765
|
-
isLintable: true
|
|
44606
|
+
isLintable: true,
|
|
44607
|
+
validator: tableValidator
|
|
44766
44608
|
};
|
|
44767
44609
|
|
|
44768
44610
|
/**
|
|
@@ -44850,26 +44692,14 @@ const IS_VIMEO = /(vimeo\.com)/;
|
|
|
44850
44692
|
class Video extends React.Component {
|
|
44851
44693
|
constructor(..._args) {
|
|
44852
44694
|
super(..._args);
|
|
44853
|
-
this
|
|
44854
|
-
|
|
44855
|
-
|
|
44695
|
+
// this just helps with TS weak typing when a Widget
|
|
44696
|
+
// doesn't implement any Widget methods
|
|
44697
|
+
this.isWidget = true;
|
|
44856
44698
|
this.change = (...args) => {
|
|
44857
44699
|
// @ts-expect-error - TS2345 - Argument of type 'readonly unknown[]' is not assignable to parameter of type 'any[]'.
|
|
44858
44700
|
return change.apply(this, args);
|
|
44859
44701
|
};
|
|
44860
44702
|
}
|
|
44861
|
-
/**
|
|
44862
|
-
* This is the widget's grading function.
|
|
44863
|
-
* Points for videos are tallied by the embedded video itself, in the case
|
|
44864
|
-
* of Khan Academy videos.
|
|
44865
|
-
*/ // TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
44866
|
-
static validate() {
|
|
44867
|
-
return noopValidator();
|
|
44868
|
-
}
|
|
44869
|
-
// TODO (LEMS-2396): remove validation logic from widgets that don't validate
|
|
44870
|
-
simpleValidate() {
|
|
44871
|
-
return noopValidator();
|
|
44872
|
-
}
|
|
44873
44703
|
render() {
|
|
44874
44704
|
const {
|
|
44875
44705
|
InitialRequestUrl
|
|
@@ -44929,7 +44759,9 @@ var Video$1 = {
|
|
|
44929
44759
|
displayName: "Video",
|
|
44930
44760
|
defaultAlignment: "block",
|
|
44931
44761
|
supportedAlignments: ["block", "float-left", "float-right", "full-width"],
|
|
44932
|
-
widget: Video
|
|
44762
|
+
widget: Video,
|
|
44763
|
+
// TODO: things that aren't interactive shouldn't need validators
|
|
44764
|
+
validator: () => noopValidator()
|
|
44933
44765
|
};
|
|
44934
44766
|
|
|
44935
44767
|
/* eslint-disable import/no-named-as-default */
|
|
@@ -44973,7 +44805,7 @@ const init = function init(options) {
|
|
|
44973
44805
|
|
|
44974
44806
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
44975
44807
|
const libName = "@khanacademy/perseus";
|
|
44976
|
-
const libVersion = "
|
|
44808
|
+
const libVersion = "37.0.0";
|
|
44977
44809
|
addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
44978
44810
|
|
|
44979
44811
|
const apiVersion = {
|
|
@@ -45549,7 +45381,7 @@ class ServerItemRenderer extends React.Component {
|
|
|
45549
45381
|
});
|
|
45550
45382
|
|
|
45551
45383
|
// Call the interactionCallback, if it exists, with the current user input data
|
|
45552
|
-
(_this$props$apiOption = this.props.apiOptions) == null || _this$props$apiOption.interactionCallback == null || _this$props$apiOption.interactionCallback(this.questionRenderer.
|
|
45384
|
+
(_this$props$apiOption = this.props.apiOptions) == null || _this$props$apiOption.interactionCallback == null || _this$props$apiOption.interactionCallback(this.questionRenderer.getUserInputMap());
|
|
45553
45385
|
};
|
|
45554
45386
|
// This must be pre-bound otherwise SvgImage's shouldComponentUpdate
|
|
45555
45387
|
// won't behave correctly and we'll get an infinite loop.
|
|
@@ -48313,12 +48145,12 @@ function parsePerseusItem(json) {
|
|
|
48313
48145
|
}
|
|
48314
48146
|
throw new Error("Something went wrong.");
|
|
48315
48147
|
}
|
|
48316
|
-
function buildRandomString() {
|
|
48148
|
+
function buildRandomString(capitalize = false) {
|
|
48317
48149
|
let randomString = "";
|
|
48318
48150
|
const randomLength = Math.floor(Math.random() * 8) + 3;
|
|
48319
48151
|
for (let i = 0; i < randomLength; i++) {
|
|
48320
48152
|
const randomLetter = String.fromCharCode(97 + Math.floor(Math.random() * 26));
|
|
48321
|
-
randomString += randomLetter;
|
|
48153
|
+
randomString += capitalize && i === 0 ? randomLetter.toUpperCase() : randomLetter;
|
|
48322
48154
|
}
|
|
48323
48155
|
return randomString;
|
|
48324
48156
|
}
|
|
@@ -48326,9 +48158,12 @@ function buildRandomPhrase() {
|
|
|
48326
48158
|
const phrases = [];
|
|
48327
48159
|
const randomLength = Math.floor(Math.random() * 10) + 5;
|
|
48328
48160
|
for (let i = 0; i < randomLength; i++) {
|
|
48329
|
-
phrases.push(buildRandomString());
|
|
48161
|
+
phrases.push(buildRandomString(i === 0));
|
|
48330
48162
|
}
|
|
48331
|
-
|
|
48163
|
+
const modifierStart = ["**", "$"];
|
|
48164
|
+
const modifierEnd = ["**", "$"];
|
|
48165
|
+
const modifierIndex = Math.floor(Math.random() * modifierStart.length);
|
|
48166
|
+
return `${modifierStart[modifierIndex]}${phrases.join(" ")}${modifierEnd[modifierIndex]}`;
|
|
48332
48167
|
}
|
|
48333
48168
|
function buildTestData(testObject) {
|
|
48334
48169
|
return `{"data":{"assessmentItem":{"__typename":"AssessmentItemOrError","error":null,"item":{"__typename":"AssessmentItem","id":"x890b3c70f3e8f4a6","itemData":"${testObject}","problemType":"Type 1","sha":"c7284a3ad65214b4e62bccce236d92f7f5d35941"}}}}`;
|