@khanacademy/perseus 17.7.0 → 18.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.
Files changed (55) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/dist/es/index.css +0 -4
  3. package/dist/es/index.js +1416 -1020
  4. package/dist/es/index.js.map +1 -1
  5. package/dist/index.css +0 -4
  6. package/dist/index.d.ts +4 -2
  7. package/dist/index.js +1315 -953
  8. package/dist/index.js.map +1 -1
  9. package/dist/perseus-types.d.ts +4 -3
  10. package/dist/renderer.d.ts +6 -6
  11. package/dist/server-item-renderer.d.ts +2 -4
  12. package/dist/strings.js +1 -1
  13. package/dist/types.d.ts +19 -2
  14. package/dist/util/drawing-transform.d.ts +21 -0
  15. package/dist/util/extract-perseus-data.d.ts +26 -0
  16. package/dist/util/graph-bounds.d.ts +9 -0
  17. package/dist/util/graphie.d.ts +2 -0
  18. package/dist/util/interval.d.ts +1 -0
  19. package/dist/util/parse-perseus-json.d.ts +10 -0
  20. package/dist/util/tex.d.ts +1 -3
  21. package/dist/widgets/deprecated-standin/index.d.ts +4 -4
  22. package/dist/widgets/passage.d.ts +3 -3
  23. package/dist/widgets.d.ts +16 -6
  24. package/package.json +2 -1
  25. package/src/__tests__/extract-perseus-data.test.ts +1027 -0
  26. package/src/index.ts +6 -1
  27. package/src/init.ts +1 -1
  28. package/src/perseus-types.ts +4 -3
  29. package/src/renderer.tsx +12 -9
  30. package/src/server-item-renderer.tsx +2 -4
  31. package/src/styles/widgets/image.less +0 -3
  32. package/src/types.ts +19 -16
  33. package/src/util/drawing-transform.test.ts +67 -0
  34. package/src/util/drawing-transform.ts +102 -0
  35. package/src/util/extract-perseus-data.ts +539 -0
  36. package/src/util/graph-bounds.ts +23 -0
  37. package/src/util/graphie.ts +1167 -1258
  38. package/src/util/interactive.ts +2 -2
  39. package/src/util/interval.ts +4 -0
  40. package/src/util/parse-perseus-json.test.ts +10 -0
  41. package/src/util/parse-perseus-json.ts +13 -0
  42. package/src/util/tex.ts +11 -84
  43. package/src/widgets/__stories__/image.stories.tsx +12 -26
  44. package/src/widgets/__tests__/__snapshots__/grapher.test.ts.snap +72 -288
  45. package/src/widgets/__tests__/__snapshots__/interaction.test.ts.snap +5 -20
  46. package/src/widgets/__tests__/__snapshots__/interactive-graph.test.ts.snap +32 -128
  47. package/src/widgets/__tests__/__snapshots__/number-line.test.ts.snap +22 -88
  48. package/src/widgets/__tests__/__snapshots__/plotter.test.tsx.snap +12 -48
  49. package/src/widgets/deprecated-standin/__stories__/deprecated-standin.stories.tsx +8 -12
  50. package/src/widgets/deprecated-standin/__tests__/__snapshots__/deprecated-standin.test.ts.snap +6 -7
  51. package/src/widgets/deprecated-standin/index.tsx +8 -7
  52. package/src/widgets/interactive-graph.tsx +3 -2
  53. package/src/widgets/passage.tsx +5 -7
  54. package/src/widgets.ts +34 -10
  55. package/tsconfig-build.tsbuildinfo +1 -1
@@ -306,10 +306,7 @@ exports[`number-line widget should snapshot on mobile: first mobile render 1`] =
306
306
  style="position: absolute; padding: 7px; color: black; left: 29.999999999999993px; top: 61.2px; fill: none;"
307
307
  >
308
308
  <span
309
- class="katex-holder"
310
- />
311
- <span
312
- class="mathjax-holder"
309
+ class="tex-holder"
313
310
  />
314
311
  </span>
315
312
  <span
@@ -318,10 +315,7 @@ exports[`number-line widget should snapshot on mobile: first mobile render 1`] =
318
315
  style="position: absolute; padding: 7px; color: black; left: 58.49999999999999px; top: 61.2px; fill: none;"
319
316
  >
320
317
  <span
321
- class="katex-holder"
322
- />
323
- <span
324
- class="mathjax-holder"
318
+ class="tex-holder"
325
319
  />
326
320
  </span>
327
321
  <span
@@ -330,10 +324,7 @@ exports[`number-line widget should snapshot on mobile: first mobile render 1`] =
330
324
  style="position: absolute; padding: 7px; color: black; left: 86.99999999999999px; top: 61.2px; fill: none;"
331
325
  >
332
326
  <span
333
- class="katex-holder"
334
- />
335
- <span
336
- class="mathjax-holder"
327
+ class="tex-holder"
337
328
  />
338
329
  </span>
339
330
  <span
@@ -342,10 +333,7 @@ exports[`number-line widget should snapshot on mobile: first mobile render 1`] =
342
333
  style="position: absolute; padding: 7px; color: black; left: 115.49999999999999px; top: 61.2px; fill: none;"
343
334
  >
344
335
  <span
345
- class="katex-holder"
346
- />
347
- <span
348
- class="mathjax-holder"
336
+ class="tex-holder"
349
337
  />
350
338
  </span>
351
339
  <span
@@ -354,10 +342,7 @@ exports[`number-line widget should snapshot on mobile: first mobile render 1`] =
354
342
  style="position: absolute; padding: 7px; color: black; left: 144px; top: 61.2px; fill: none;"
355
343
  >
356
344
  <span
357
- class="katex-holder"
358
- />
359
- <span
360
- class="mathjax-holder"
345
+ class="tex-holder"
361
346
  />
362
347
  </span>
363
348
  <span
@@ -366,10 +351,7 @@ exports[`number-line widget should snapshot on mobile: first mobile render 1`] =
366
351
  style="position: absolute; padding: 7px; color: black; left: 172.5px; top: 61.2px; fill: none;"
367
352
  >
368
353
  <span
369
- class="katex-holder"
370
- />
371
- <span
372
- class="mathjax-holder"
354
+ class="tex-holder"
373
355
  />
374
356
  </span>
375
357
  <span
@@ -378,10 +360,7 @@ exports[`number-line widget should snapshot on mobile: first mobile render 1`] =
378
360
  style="position: absolute; padding: 7px; color: black; left: 201px; top: 61.2px; fill: none;"
379
361
  >
380
362
  <span
381
- class="katex-holder"
382
- />
383
- <span
384
- class="mathjax-holder"
363
+ class="tex-holder"
385
364
  />
386
365
  </span>
387
366
  <span
@@ -390,10 +369,7 @@ exports[`number-line widget should snapshot on mobile: first mobile render 1`] =
390
369
  style="position: absolute; padding: 7px; color: black; left: 229.5px; top: 61.2px; fill: none;"
391
370
  >
392
371
  <span
393
- class="katex-holder"
394
- />
395
- <span
396
- class="mathjax-holder"
372
+ class="tex-holder"
397
373
  />
398
374
  </span>
399
375
  <span
@@ -402,10 +378,7 @@ exports[`number-line widget should snapshot on mobile: first mobile render 1`] =
402
378
  style="position: absolute; padding: 7px; color: black; left: 258px; top: 61.2px; fill: none;"
403
379
  >
404
380
  <span
405
- class="katex-holder"
406
- />
407
- <span
408
- class="mathjax-holder"
381
+ class="tex-holder"
409
382
  />
410
383
  </span>
411
384
  <span
@@ -414,10 +387,7 @@ exports[`number-line widget should snapshot on mobile: first mobile render 1`] =
414
387
  style="position: absolute; padding: 7px; color: rgb(17, 172, 205); left: 29.999999999999993px; top: 61.2px; fill: none;"
415
388
  >
416
389
  <span
417
- class="katex-holder"
418
- />
419
- <span
420
- class="mathjax-holder"
390
+ class="tex-holder"
421
391
  />
422
392
  </span>
423
393
  <span
@@ -426,10 +396,7 @@ exports[`number-line widget should snapshot on mobile: first mobile render 1`] =
426
396
  style="position: absolute; padding: 7px; color: rgb(17, 172, 205); left: 258px; top: 61.2px; fill: none;"
427
397
  >
428
398
  <span
429
- class="katex-holder"
430
- />
431
- <span
432
- class="mathjax-holder"
399
+ class="tex-holder"
433
400
  />
434
401
  </span>
435
402
  </div>
@@ -743,10 +710,7 @@ exports[`number-line widget should snapshot: first render 1`] = `
743
710
  style="position: absolute; padding: 7px; color: black; left: 29.999999999999982px; top: 61.2px; fill: none;"
744
711
  >
745
712
  <span
746
- class="katex-holder"
747
- />
748
- <span
749
- class="mathjax-holder"
713
+ class="tex-holder"
750
714
  />
751
715
  </span>
752
716
  <span
@@ -755,10 +719,7 @@ exports[`number-line widget should snapshot: first render 1`] = `
755
719
  style="position: absolute; padding: 7px; color: black; left: 79.99999999999999px; top: 61.2px; fill: none;"
756
720
  >
757
721
  <span
758
- class="katex-holder"
759
- />
760
- <span
761
- class="mathjax-holder"
722
+ class="tex-holder"
762
723
  />
763
724
  </span>
764
725
  <span
@@ -767,10 +728,7 @@ exports[`number-line widget should snapshot: first render 1`] = `
767
728
  style="position: absolute; padding: 7px; color: black; left: 129.99999999999997px; top: 61.2px; fill: none;"
768
729
  >
769
730
  <span
770
- class="katex-holder"
771
- />
772
- <span
773
- class="mathjax-holder"
731
+ class="tex-holder"
774
732
  />
775
733
  </span>
776
734
  <span
@@ -779,10 +737,7 @@ exports[`number-line widget should snapshot: first render 1`] = `
779
737
  style="position: absolute; padding: 7px; color: black; left: 179.99999999999997px; top: 61.2px; fill: none;"
780
738
  >
781
739
  <span
782
- class="katex-holder"
783
- />
784
- <span
785
- class="mathjax-holder"
740
+ class="tex-holder"
786
741
  />
787
742
  </span>
788
743
  <span
@@ -791,10 +746,7 @@ exports[`number-line widget should snapshot: first render 1`] = `
791
746
  style="position: absolute; padding: 7px; color: black; left: 229.99999999999997px; top: 61.2px; fill: none;"
792
747
  >
793
748
  <span
794
- class="katex-holder"
795
- />
796
- <span
797
- class="mathjax-holder"
749
+ class="tex-holder"
798
750
  />
799
751
  </span>
800
752
  <span
@@ -803,10 +755,7 @@ exports[`number-line widget should snapshot: first render 1`] = `
803
755
  style="position: absolute; padding: 7px; color: black; left: 280px; top: 61.2px; fill: none;"
804
756
  >
805
757
  <span
806
- class="katex-holder"
807
- />
808
- <span
809
- class="mathjax-holder"
758
+ class="tex-holder"
810
759
  />
811
760
  </span>
812
761
  <span
@@ -815,10 +764,7 @@ exports[`number-line widget should snapshot: first render 1`] = `
815
764
  style="position: absolute; padding: 7px; color: black; left: 330px; top: 61.2px; fill: none;"
816
765
  >
817
766
  <span
818
- class="katex-holder"
819
- />
820
- <span
821
- class="mathjax-holder"
767
+ class="tex-holder"
822
768
  />
823
769
  </span>
824
770
  <span
@@ -827,10 +773,7 @@ exports[`number-line widget should snapshot: first render 1`] = `
827
773
  style="position: absolute; padding: 7px; color: black; left: 380px; top: 61.2px; fill: none;"
828
774
  >
829
775
  <span
830
- class="katex-holder"
831
- />
832
- <span
833
- class="mathjax-holder"
776
+ class="tex-holder"
834
777
  />
835
778
  </span>
836
779
  <span
@@ -839,10 +782,7 @@ exports[`number-line widget should snapshot: first render 1`] = `
839
782
  style="position: absolute; padding: 7px; color: black; left: 430px; top: 61.2px; fill: none;"
840
783
  >
841
784
  <span
842
- class="katex-holder"
843
- />
844
- <span
845
- class="mathjax-holder"
785
+ class="tex-holder"
846
786
  />
847
787
  </span>
848
788
  <span
@@ -851,10 +791,7 @@ exports[`number-line widget should snapshot: first render 1`] = `
851
791
  style="position: absolute; padding: 7px; color: black; left: 29.999999999999982px; top: 61.2px; fill: none;"
852
792
  >
853
793
  <span
854
- class="katex-holder"
855
- />
856
- <span
857
- class="mathjax-holder"
794
+ class="tex-holder"
858
795
  />
859
796
  </span>
860
797
  <span
@@ -863,10 +800,7 @@ exports[`number-line widget should snapshot: first render 1`] = `
863
800
  style="position: absolute; padding: 7px; color: black; left: 430px; top: 61.2px; fill: none;"
864
801
  >
865
802
  <span
866
- class="katex-holder"
867
- />
868
- <span
869
- class="mathjax-holder"
803
+ class="tex-holder"
870
804
  />
871
805
  </span>
872
806
  </div>
@@ -704,10 +704,7 @@ exports[`plotter widget should snapshot basic question: initial render 1`] = `
704
704
  style="position: absolute; padding: 7px; color: black; left: 75px; top: 325px; fill: none;"
705
705
  >
706
706
  <span
707
- class="katex-holder"
708
- />
709
- <span
710
- class="mathjax-holder"
707
+ class="tex-holder"
711
708
  />
712
709
  </span>
713
710
  <span
@@ -716,10 +713,7 @@ exports[`plotter widget should snapshot basic question: initial render 1`] = `
716
713
  style="position: absolute; padding: 7px; color: black; left: 75px; top: 275px; fill: none;"
717
714
  >
718
715
  <span
719
- class="katex-holder"
720
- />
721
- <span
722
- class="mathjax-holder"
716
+ class="tex-holder"
723
717
  />
724
718
  </span>
725
719
  <span
@@ -728,10 +722,7 @@ exports[`plotter widget should snapshot basic question: initial render 1`] = `
728
722
  style="position: absolute; padding: 7px; color: black; left: 75px; top: 225px; fill: none;"
729
723
  >
730
724
  <span
731
- class="katex-holder"
732
- />
733
- <span
734
- class="mathjax-holder"
725
+ class="tex-holder"
735
726
  />
736
727
  </span>
737
728
  <span
@@ -740,10 +731,7 @@ exports[`plotter widget should snapshot basic question: initial render 1`] = `
740
731
  style="position: absolute; padding: 7px; color: black; left: 75px; top: 175px; fill: none;"
741
732
  >
742
733
  <span
743
- class="katex-holder"
744
- />
745
- <span
746
- class="mathjax-holder"
734
+ class="tex-holder"
747
735
  />
748
736
  </span>
749
737
  <span
@@ -752,10 +740,7 @@ exports[`plotter widget should snapshot basic question: initial render 1`] = `
752
740
  style="position: absolute; padding: 7px; color: black; left: 75px; top: 125px; fill: none;"
753
741
  >
754
742
  <span
755
- class="katex-holder"
756
- />
757
- <span
758
- class="mathjax-holder"
743
+ class="tex-holder"
759
744
  />
760
745
  </span>
761
746
  <span
@@ -764,10 +749,7 @@ exports[`plotter widget should snapshot basic question: initial render 1`] = `
764
749
  style="position: absolute; padding: 7px; color: black; left: 75px; top: 75px; fill: none;"
765
750
  >
766
751
  <span
767
- class="katex-holder"
768
- />
769
- <span
770
- class="mathjax-holder"
752
+ class="tex-holder"
771
753
  />
772
754
  </span>
773
755
  <span
@@ -776,10 +758,7 @@ exports[`plotter widget should snapshot basic question: initial render 1`] = `
776
758
  style="position: absolute; padding: 7px; color: black; left: 75px; top: 25px; fill: none;"
777
759
  >
778
760
  <span
779
- class="katex-holder"
780
- />
781
- <span
782
- class="mathjax-holder"
761
+ class="tex-holder"
783
762
  />
784
763
  </span>
785
764
  <span
@@ -788,10 +767,7 @@ exports[`plotter widget should snapshot basic question: initial render 1`] = `
788
767
  style="position: absolute; padding: 7px; color: black; left: 121.60377358490565px; top: 325px; fill: none; stroke: #71B307; transform: none; transform-origin: 100%;"
789
768
  >
790
769
  <span
791
- class="katex-holder"
792
- />
793
- <span
794
- class="mathjax-holder"
770
+ class="tex-holder"
795
771
  />
796
772
  </span>
797
773
  <span
@@ -800,10 +776,7 @@ exports[`plotter widget should snapshot basic question: initial render 1`] = `
800
776
  style="position: absolute; padding: 7px; color: black; left: 193.30188679245282px; top: 325px; fill: none; stroke: #71B307; transform: none; transform-origin: 100%;"
801
777
  >
802
778
  <span
803
- class="katex-holder"
804
- />
805
- <span
806
- class="mathjax-holder"
779
+ class="tex-holder"
807
780
  />
808
781
  </span>
809
782
  <span
@@ -812,10 +785,7 @@ exports[`plotter widget should snapshot basic question: initial render 1`] = `
812
785
  style="position: absolute; padding: 7px; color: black; left: 265px; top: 325px; fill: none; stroke: #71B307; transform: none; transform-origin: 100%;"
813
786
  >
814
787
  <span
815
- class="katex-holder"
816
- />
817
- <span
818
- class="mathjax-holder"
788
+ class="tex-holder"
819
789
  />
820
790
  </span>
821
791
  <span
@@ -824,10 +794,7 @@ exports[`plotter widget should snapshot basic question: initial render 1`] = `
824
794
  style="position: absolute; padding: 7px; color: black; left: 336.6981132075471px; top: 325px; fill: none; stroke: #71B307; transform: none; transform-origin: 100%;"
825
795
  >
826
796
  <span
827
- class="katex-holder"
828
- />
829
- <span
830
- class="mathjax-holder"
797
+ class="tex-holder"
831
798
  />
832
799
  </span>
833
800
  <span
@@ -836,10 +803,7 @@ exports[`plotter widget should snapshot basic question: initial render 1`] = `
836
803
  style="position: absolute; padding: 7px; color: black; left: 408.3962264150943px; top: 325px; fill: none; stroke: #71B307; transform: none; transform-origin: 100%;"
837
804
  >
838
805
  <span
839
- class="katex-holder"
840
- />
841
- <span
842
- class="mathjax-holder"
806
+ class="tex-holder"
843
807
  />
844
808
  </span>
845
809
  <span
@@ -8,21 +8,17 @@ export default {
8
8
 
9
9
  const question1 = {
10
10
  content:
11
- "Read the excerpt and answer the question below. \n\nThe Governor and Council of the Massachusetts had much conference many days; and at last . . . . concluded a peace and friendship with [[\u2603 definition 1]], upon these conditions.",
12
- images: {},
11
+ "$\\overleftrightarrow{MN}$ is the perpendicular bisector of segment $\\overline{JL}$. \n\n**Perform a reflection that proves $M$ must be equidistant from $J$ and $L$ and select the option which explains the proof.** \nThe statement must be true for any point $M$ which lies on the perpendicular bisector. \n\n[[☃ standin 1]] \n\n",
12
+ images: {
13
+ "https://ka-perseus-images.s3.amazonaws.com/6cf0d9f007084e9d06e3ce0e241416dde920ec9c.png":
14
+ {height: 503, width: 504},
15
+ },
13
16
  widgets: {
14
- "definition 1": {
17
+ "standin 1": {
15
18
  graded: true,
16
- version: {
17
- major: 0,
18
- minor: 0,
19
- },
20
- static: false,
19
+ options: {},
21
20
  type: "deprecated-standin",
22
- options: {
23
- static: false,
24
- },
25
- alignment: "default",
21
+ version: {major: 0, minor: 0},
26
22
  },
27
23
  },
28
24
  } as const;
@@ -30,19 +30,18 @@ exports[`Deprecated Standin widget should have a default snapshot: first render
30
30
  style="padding-top: 8px; padding-bottom: 8px;"
31
31
  >
32
32
  <div
33
- aria-live="polite"
34
- class="default_xu2jcg-o_O-containerOuter_xu9ezy-o_O-inlineStyles_1ozd0sx"
35
- role="alert"
33
+ class="default_xu2jcg-o_O-containerOuter_xu9ezy-o_O-inlineStyles_1ipey8s"
34
+ role="status"
36
35
  >
37
36
  <div
38
- class="default_xu2jcg-o_O-backgroundColor_10s9e9d-o_O-inlineStyles_tkl0uy"
37
+ class="default_xu2jcg-o_O-backgroundColor_10s9e9d-o_O-inlineStyles_14jsc6v"
39
38
  />
40
39
  <div
41
40
  class="default_xu2jcg-o_O-containerInner_mm2xcu"
42
41
  >
43
42
  <span
44
- aria-label="warning"
45
- class="svg_1q6jc65-o_O-icon_1521uiv-o_O-icon_16tp01m-o_O-inlineStyles_g0hdza"
43
+ aria-label="info"
44
+ class="svg_1q6jc65-o_O-icon_1521uiv-o_O-icon_16tp01m-o_O-inlineStyles_94g682"
46
45
  data-test-id="banner-kind-icon"
47
46
  role="img"
48
47
  />
@@ -55,7 +54,7 @@ exports[`Deprecated Standin widget should have a default snapshot: first render
55
54
  <span
56
55
  class="text_f1191h-o_O-LabelSmall_hl4zs1"
57
56
  >
58
- This part of the question is no-longer available. You will not be graded on this part.
57
+ Sorry, this part of the question is no longer available. 😅 Don't worry, you won't be graded on this part. Keep going!
59
58
  </span>
60
59
  </div>
61
60
  </div>
@@ -6,11 +6,11 @@ import type {PerseusScore, WidgetExports} from "../../types";
6
6
 
7
7
  // The props are type `any` on purpose so that this can receive props
8
8
  // from any deprecated widget
9
- type AutoCorrectProps = any;
9
+ type Props = any;
10
10
  type Rubric = any;
11
11
  type UserInput = Empty;
12
12
 
13
- class AutoCorrect extends React.Component<AutoCorrectProps> {
13
+ class DeprecatedStandin extends React.Component<Props> {
14
14
  static validate(userInput: UserInput, rubric: Rubric): PerseusScore {
15
15
  // Since this mean to replace an existing widget the learner
16
16
  // WILL earn points for this widget
@@ -27,7 +27,7 @@ class AutoCorrect extends React.Component<AutoCorrectProps> {
27
27
  };
28
28
 
29
29
  simpleValidate: (arg1: Rubric) => PerseusScore = (rubric) => {
30
- return AutoCorrect.validate(this.getUserInput(), rubric);
30
+ return DeprecatedStandin.validate(this.getUserInput(), rubric);
31
31
  };
32
32
 
33
33
  render() {
@@ -40,9 +40,9 @@ class AutoCorrect extends React.Component<AutoCorrectProps> {
40
40
  >
41
41
  <Banner
42
42
  text={i18n._(
43
- "This part of the question is no-longer available. You will not be graded on this part.",
43
+ "Sorry, this part of the question is no longer available. 😅 Don't worry, you won't be graded on this part. Keep going!",
44
44
  )}
45
- kind="warning"
45
+ kind="info"
46
46
  layout="full-width"
47
47
  />
48
48
  </div>
@@ -53,5 +53,6 @@ class AutoCorrect extends React.Component<AutoCorrectProps> {
53
53
  export default {
54
54
  name: "deprecated-standin",
55
55
  displayName: "Deprecated Standin",
56
- widget: AutoCorrect,
57
- } as WidgetExports<typeof AutoCorrect>;
56
+ widget: DeprecatedStandin,
57
+ hidden: true,
58
+ } as WidgetExports<typeof DeprecatedStandin>;
@@ -29,6 +29,7 @@ import {
29
29
  similar,
30
30
  } from "../util/geometry";
31
31
  import GraphUtils from "../util/graph-utils";
32
+ import {polar} from "../util/graphie";
32
33
  import {getInteractiveBoxFromSizeClass} from "../util/sizing-utils";
33
34
 
34
35
  import type {Coord} from "../interactive2/types";
@@ -1216,7 +1217,7 @@ class InteractiveGraph extends React.Component<Props, State> {
1216
1217
  coords[rel(-1)],
1217
1218
  );
1218
1219
 
1219
- const offset = this.graphie?.polar(
1220
+ const offset = polar(
1220
1221
  side,
1221
1222
  outerAngle + (onLeft ? 1 : -1) * innerAngles[0],
1222
1223
  );
@@ -1263,7 +1264,7 @@ class InteractiveGraph extends React.Component<Props, State> {
1263
1264
  const onLeft =
1264
1265
  sign(ccw(coords[rel(-1)], coords[rel(1)], coords[i])) === 1;
1265
1266
 
1266
- const offset = this.graphie?.polar(
1267
+ const offset = polar(
1267
1268
  sides[0],
1268
1269
  outerAngle + (onLeft ? 1 : -1) * innerAngle,
1269
1270
  );
@@ -15,13 +15,11 @@ import PassageMarkdown from "./passage/passage-markdown";
15
15
  import type {ParseState} from "./passage/passage-markdown";
16
16
  import type {SerializedHighlightSet} from "../components/highlighting/types";
17
17
  import type {ChangeableProps} from "../mixins/changeable";
18
- import type {PerseusPassageWidgetOptions} from "../perseus-types";
19
18
  import type {
20
- PerseusScore,
21
- WidgetExports,
22
- WidgetInfo,
23
- WidgetProps,
24
- } from "../types";
19
+ PerseusPassageWidgetOptions,
20
+ PerseusWidget,
21
+ } from "../perseus-types";
22
+ import type {PerseusScore, WidgetExports, WidgetProps} from "../types";
25
23
  import type {SingleASTNode} from "@khanacademy/simple-markdown";
26
24
 
27
25
  // A fake paragraph to measure the line height of the passage,
@@ -71,7 +69,7 @@ type RenderProps = {
71
69
  showLineNumbers: PerseusPassageWidgetOptions["showLineNumbers"];
72
70
  };
73
71
 
74
- type FindWidgetsCallback = (id: string, widgetInfo: WidgetInfo) => boolean;
72
+ type FindWidgetsCallback = (id: string, widgetInfo: PerseusWidget) => boolean;
75
73
 
76
74
  type PassageProps = ChangeableProps &
77
75
  WidgetProps<RenderProps, Rubric> & {
package/src/widgets.ts CHANGED
@@ -3,12 +3,12 @@ import _ from "underscore";
3
3
  import {Errors, Log} from "./logging/log";
4
4
  import {PerseusError} from "./perseus-error";
5
5
 
6
+ import type {PerseusWidget} from "./perseus-types";
6
7
  import type {
7
8
  Alignment,
8
9
  Tracking,
9
10
  Version,
10
11
  WidgetExports,
11
- WidgetInfo,
12
12
  WidgetTransform,
13
13
  } from "./types";
14
14
  import type * as React from "react";
@@ -79,6 +79,30 @@ export const registerEditors = (editorsToRegister: ReadonlyArray<Editor>) => {
79
79
  });
80
80
  };
81
81
 
82
+ /**
83
+ *
84
+ * @param name - the widget that you are trying to replace
85
+ * @param replacementName - the name of the widget that takes its place
86
+ *
87
+ * e.g. replaceEditor("transformer", "always-correct") will make it so the
88
+ * transformer widget is replaced by the always correct widget
89
+ */
90
+ export const replaceEditor = (name: string, replacementName: string) => {
91
+ const substituteEditor = editors[replacementName];
92
+
93
+ if (!substituteEditor && Log) {
94
+ const errorMsg = `Failed to replace editor ${name} with ${replacementName}`;
95
+ Log.error(errorMsg, Errors.Internal);
96
+ return;
97
+ }
98
+
99
+ editors[name] = substituteEditor;
100
+
101
+ if (Log) {
102
+ Log.log(`INFO: Replacing editor ${name} with ${replacementName}`);
103
+ }
104
+ };
105
+
82
106
  export const getWidget = (
83
107
  name: string,
84
108
  ): React.ComponentType<any> | null | undefined => {
@@ -106,12 +130,12 @@ export const getTransform = (
106
130
  return _.has(widgets, name) ? widgets[name].transform || _.identity : null;
107
131
  };
108
132
 
109
- export const getVersion = (name: string): Version | null | undefined => {
133
+ export const getVersion = (name: string): Version | undefined => {
110
134
  const widgetInfo = widgets[name];
111
135
  if (widgetInfo) {
112
136
  return widgets[name].version || {major: 0, minor: 0};
113
137
  }
114
- return null;
138
+ return;
115
139
  };
116
140
 
117
141
  export const getVersionVector = (): {
@@ -136,7 +160,7 @@ export const getPublicWidgets = (): ReadonlyArray<WidgetExports> => {
136
160
  );
137
161
  };
138
162
 
139
- export const isAccessible = (widgetInfo: WidgetInfo): boolean => {
163
+ export const isAccessible = (widgetInfo: PerseusWidget): boolean => {
140
164
  const accessible = widgets[widgetInfo.type].accessible;
141
165
  if (typeof accessible === "function") {
142
166
  return accessible(widgetInfo.options);
@@ -149,8 +173,8 @@ export const getAllWidgetTypes = (): ReadonlyArray<string> => {
149
173
  };
150
174
 
151
175
  export const upgradeWidgetInfoToLatestVersion = (
152
- oldWidgetInfo: WidgetInfo,
153
- ): WidgetInfo => {
176
+ oldWidgetInfo: PerseusWidget,
177
+ ): PerseusWidget => {
154
178
  const type = oldWidgetInfo.type;
155
179
  // TODO(LP-10707): Remove unnecessary type checking (`type` is a string)
156
180
  if (!_.isString(type)) {
@@ -271,9 +295,9 @@ export const upgradeWidgetInfoToLatestVersion = (
271
295
  };
272
296
 
273
297
  export const getRendererPropsForWidgetInfo = (
274
- widgetInfo: WidgetInfo,
298
+ widgetInfo: PerseusWidget,
275
299
  problemNum?: number,
276
- ): any => {
300
+ ): PerseusWidget => {
277
301
  const type = widgetInfo.type;
278
302
  const widgetExports = widgets[type];
279
303
  if (widgetExports == null) {
@@ -298,9 +322,9 @@ export const getRendererPropsForWidgetInfo = (
298
322
  };
299
323
 
300
324
  export const traverseChildWidgets = (
301
- widgetInfo: WidgetInfo,
325
+ widgetInfo: PerseusWidget,
302
326
  traverseRenderer: any,
303
- ): WidgetInfo => {
327
+ ): PerseusWidget => {
304
328
  if (!traverseRenderer) {
305
329
  throw new PerseusError(
306
330
  "traverseRenderer must be provided, but was not",