@khanacademy/perseus-core 0.0.0-PR973-20240207193807 → 0.0.0-PR973-20240207194831

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/.babelrc.js ADDED
@@ -0,0 +1,8 @@
1
+ /**
2
+ * HACK(kevinb): Due to https://github.com/facebook/jest/issues/11741,
3
+ * we need to have this file, or updating inline snapshots can fail rather
4
+ * cryptically.
5
+ *
6
+ * We should remove this when jest is fixed.
7
+ */
8
+ module.exports = require("../../config/build/babel.config");
package/.eslintrc.js ADDED
@@ -0,0 +1,12 @@
1
+ /* eslint-disable @typescript-eslint/no-var-requires */
2
+ /* eslint-disable import/no-commonjs */
3
+ const path = require("path");
4
+
5
+ module.exports = {
6
+ rules: {
7
+ "import/no-extraneous-dependencies": [
8
+ "error",
9
+ {packageDir: [__dirname, path.join(__dirname, "../../")]},
10
+ ],
11
+ },
12
+ };
package/CHANGELOG.md ADDED
@@ -0,0 +1,97 @@
1
+ # @khanacademy/perseus-core
2
+
3
+ ## 0.0.0-PR973-20240207194831
4
+
5
+ ### Patch Changes
6
+
7
+ - [#973](https://github.com/Khan/perseus/pull/973) [`2ffc6971`](https://github.com/Khan/perseus/commit/2ffc6971e7003cbc64a8a3988337c6ca6019c9db) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - Include 'types' key in package.json and move types to 'types' package subdirectory
8
+
9
+ ## 1.4.2
10
+
11
+ ### Patch Changes
12
+
13
+ - [#971](https://github.com/Khan/perseus/pull/971) [`90ff7a48`](https://github.com/Khan/perseus/commit/90ff7a483b01552a556c7852427e98153cc20417) Thanks [@benchristel](https://github.com/benchristel)! - Remove source files from the distributed NPM package
14
+
15
+ ## 1.4.1
16
+
17
+ ### Patch Changes
18
+
19
+ - [#860](https://github.com/Khan/perseus/pull/860) [`1f4e17ba`](https://github.com/Khan/perseus/commit/1f4e17ba77e1491523813655af18a70285a25989) Thanks [@nixterrimus](https://github.com/nixterrimus)! - Add hover states in label-image widget
20
+
21
+ * [#848](https://github.com/Khan/perseus/pull/848) [`8857950b`](https://github.com/Khan/perseus/commit/8857950bdeeb6e13bc3766b1c6545289b21cbe2a) Thanks [@nixterrimus](https://github.com/nixterrimus)! - Add analytics for label image
22
+
23
+ ## 1.4.0
24
+
25
+ ### Minor Changes
26
+
27
+ - [#794](https://github.com/Khan/perseus/pull/794) [`a91c84fe`](https://github.com/Khan/perseus/commit/a91c84fe53827ff4333220777a9918882b7fe9f0) Thanks [@SonicScrewdriver](https://github.com/SonicScrewdriver)! - Removing the useV2Keypad apiOption as the V1 keypad is no longer in use.
28
+
29
+ ### Patch Changes
30
+
31
+ - [#814](https://github.com/Khan/perseus/pull/814) [`105d2060`](https://github.com/Khan/perseus/commit/105d20603d935d35cff237b17f0bfb57ca751e4c) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - Minor build change to how we provide Typescript type definitions (should be no change to build output).
32
+
33
+ ## 1.3.0
34
+
35
+ ### Minor Changes
36
+
37
+ - [#783](https://github.com/Khan/perseus/pull/783) [`79403e06`](https://github.com/Khan/perseus/commit/79403e06eedb597d7818d6c858bbba6f51ff3fe1) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - Adds 'widgetId' to the 'perseus:widget-rendering-error' analytics event.
38
+
39
+ ## 1.2.0
40
+
41
+ ### Minor Changes
42
+
43
+ - [#780](https://github.com/Khan/perseus/pull/780) [`376eb0e4`](https://github.com/Khan/perseus/commit/376eb0e4aaaa4c7a90fd6107a84bb74d382b077c) Thanks [@jeremywiebe](https://github.com/jeremywiebe)! - Added 'perseus:widget-rendering-error' analytics event.
44
+
45
+ ## 1.1.2
46
+
47
+ ### Patch Changes
48
+
49
+ - 22a9c408: Fix bug caused by package version diagnostics
50
+
51
+ ## 1.1.1
52
+
53
+ ### Patch Changes
54
+
55
+ - 55d4cd00: Print package name and version when loaded in the page
56
+
57
+ ## 1.1.0
58
+
59
+ ### Minor Changes
60
+
61
+ - 4f4fe4f9: Added new analytics event "perseus:expression-focused"
62
+
63
+ ## 1.0.0
64
+
65
+ ### Major Changes
66
+
67
+ - 2af4f9fa: Switch from using ProvideKeypad in ArticleRenderer to passing the keypad element down instead
68
+
69
+ ## 0.2.0
70
+
71
+ ### Minor Changes
72
+
73
+ - dd800c22: Rename analytics prop from onEvent to onAnalyticsEvent
74
+
75
+ ## 0.1.1
76
+
77
+ ### Patch Changes
78
+
79
+ - 57f75510: Commented RendererInterface
80
+
81
+ ## 0.1.0
82
+
83
+ ### Minor Changes
84
+
85
+ - b4c06409: Add perseus-core to changeset
86
+
87
+ ## 0.0.2
88
+
89
+ ### Patch Changes
90
+
91
+ - 71c631ea: Add keypad opened and closed analytics events
92
+
93
+ ## 0.0.1
94
+
95
+ ### Patch Changes
96
+
97
+ - 1f3fdc6c: Introducing `perseus-core` for types and functionality shared across the Perseus ecosystem
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "Shared Perseus infrastructure",
4
4
  "author": "Khan Academy",
5
5
  "license": "MIT",
6
- "version": "0.0.0-PR973-20240207193807",
6
+ "version": "0.0.0-PR973-20240207194831",
7
7
  "publishConfig": {
8
8
  "access": "public"
9
9
  },
@@ -19,9 +19,6 @@
19
19
  "main": "dist/index.js",
20
20
  "source": "src/index.ts",
21
21
  "types": "dist/types/index.d.ts",
22
- "files": [
23
- "dist"
24
- ],
25
22
  "scripts": {
26
23
  "test": "bash -c 'yarn --silent --cwd \"../..\" test ${@:0} $($([[ ${@: -1} = -* ]] || [[ ${@: -1} = bash ]]) && echo $PWD)'"
27
24
  },
@@ -0,0 +1,64 @@
1
+ export type VirtualKeypadVersion =
2
+ | "MATH_INPUT_KEYPAD_V2"
3
+ | "REACT_NATIVE_KEYPAD";
4
+
5
+ /**
6
+ * A type union of all the events that any package in the Perseus ecosystem can
7
+ * send.
8
+ */
9
+ export type PerseusAnalyticsEvent =
10
+ | {
11
+ type: "perseus:expression-evaluated";
12
+ payload: {
13
+ virtualKeypadVersion: VirtualKeypadVersion;
14
+ result: "correct" | "incorrect" | "invalid";
15
+ };
16
+ }
17
+ | {
18
+ type: "perseus:expression-focused";
19
+ payload: null;
20
+ }
21
+ | {
22
+ type: "perseus:widget-rendering-error";
23
+ payload: {
24
+ widgetType: string;
25
+ widgetId: string;
26
+ };
27
+ }
28
+ | {
29
+ type: "perseus:label-image:toggle-answers-hidden";
30
+ payload: null;
31
+ }
32
+ | {
33
+ type: "perseus:label-image:marker-interacted-with";
34
+ payload: null;
35
+ }
36
+ | {
37
+ type: "perseus:label-image:choiced-interacted-with";
38
+ payload: null;
39
+ }
40
+ | {
41
+ type: "math-input:keypad-closed";
42
+ payload: {
43
+ virtualKeypadVersion: VirtualKeypadVersion;
44
+ };
45
+ }
46
+ | {
47
+ type: "math-input:keypad-opened";
48
+ payload: {
49
+ virtualKeypadVersion: VirtualKeypadVersion;
50
+ };
51
+ };
52
+
53
+ // Add more events here as needed. Note that each event should have a `type`
54
+ // key and a payload that varies by type.
55
+ // | {type: "b"; payload: {name: string}};
56
+ //
57
+ // Event types should be formatted as "package-name:event-name" (where the
58
+ // package name is the name of the package that emits the event without the
59
+ // `@khanacademy/` prefix and then the name of the event.)
60
+
61
+ /** A function that is called when Perseus emits an analytics event. */
62
+ export type AnalyticsEventHandlerFn = (
63
+ event: PerseusAnalyticsEvent,
64
+ ) => Promise<void>;
package/src/index.ts ADDED
@@ -0,0 +1,11 @@
1
+ export type {PerseusAnalyticsEvent, AnalyticsEventHandlerFn} from "./analytics";
2
+ export type {
3
+ KEScore,
4
+ KeypadContextRendererInterface,
5
+ RendererInterface,
6
+ } from "./types";
7
+
8
+ // Careful, `version.ts` uses this function so it _must_ be imported above it
9
+ export {addLibraryVersionToPerseusDebug} from "./utils/add-library-version-to-perseus-debug";
10
+
11
+ export {libVersion} from "./version";
package/src/types.ts ADDED
@@ -0,0 +1,30 @@
1
+ // Types that can be shared between Perseus packages
2
+ // ideally without causing circular dependencies
3
+
4
+ // Used by KeypadContext to pass around a renderer reference
5
+ export interface KeypadContextRendererInterface {
6
+ blur(): void;
7
+ }
8
+
9
+ // TODO: this should be typed
10
+ type State = any;
11
+
12
+ // Interfact currently only implemented by
13
+ // ServerItemRenderer
14
+ export interface RendererInterface {
15
+ getSerializedState(): State;
16
+ restoreSerializedState(state: State, callback?: () => void): void;
17
+ scoreInput(): KEScore;
18
+ blur(): void;
19
+ focus(): boolean | null | undefined;
20
+ props: any;
21
+ }
22
+
23
+ export type KEScore = {
24
+ empty: boolean;
25
+ correct: boolean;
26
+ message?: string | null | undefined;
27
+ suppressAlmostThere?: boolean | null | undefined;
28
+ guess: any;
29
+ state: any;
30
+ };
@@ -0,0 +1,109 @@
1
+ import {addLibraryVersionToPerseusDebug} from "./add-library-version-to-perseus-debug";
2
+
3
+ describe("add-library-version-to-perseus-debug", () => {
4
+ beforeEach(() => {
5
+ delete globalThis.__perseus_debug__;
6
+ });
7
+
8
+ it("should add the given library to __perseus_debug__", () => {
9
+ // Array
10
+
11
+ // Act
12
+ addLibraryVersionToPerseusDebug("test-lib", "1.0.0");
13
+
14
+ // Assert
15
+ expect(globalThis.__perseus_debug__).toMatchInlineSnapshot(`
16
+ {
17
+ "test-lib": "v1.0.0",
18
+ }
19
+ `);
20
+ });
21
+
22
+ it("should extend __perseus_debug__ when multiple libraries registered", () => {
23
+ // Arrange
24
+
25
+ // Act
26
+ addLibraryVersionToPerseusDebug("test-lib", "1.0.0");
27
+ addLibraryVersionToPerseusDebug("sample-lib", "2.0.0");
28
+ addLibraryVersionToPerseusDebug("utility-lib", "3.0.0");
29
+
30
+ // Assert
31
+ expect(globalThis.__perseus_debug__).toMatchInlineSnapshot(`
32
+ {
33
+ "sample-lib": "v2.0.0",
34
+ "test-lib": "v1.0.0",
35
+ "utility-lib": "v3.0.0",
36
+ }
37
+ `);
38
+ });
39
+
40
+ it("should convert library entry to array when multiple versions of the same library registered", () => {
41
+ // Arrange
42
+ jest.spyOn(console, "warn").mockImplementation();
43
+
44
+ // Act
45
+ addLibraryVersionToPerseusDebug("test-lib", "1.0.1");
46
+ addLibraryVersionToPerseusDebug("test-lib", "4.1.8");
47
+ addLibraryVersionToPerseusDebug("test-lib", "1.0.0");
48
+ addLibraryVersionToPerseusDebug("test-lib", "2.0.0");
49
+
50
+ // Assert
51
+ expect(globalThis.__perseus_debug__).toMatchInlineSnapshot(`
52
+ {
53
+ "test-lib": [
54
+ "v1.0.0",
55
+ "v1.0.1",
56
+ "v2.0.0",
57
+ "v4.1.8",
58
+ ],
59
+ }
60
+ `);
61
+ });
62
+
63
+ it("should warn when multiple versions of the same library registered", () => {
64
+ // Arrange
65
+ const warnSpy = jest.spyOn(console, "warn").mockImplementation();
66
+
67
+ // Act
68
+ addLibraryVersionToPerseusDebug("test-lib", "1.0.1");
69
+ addLibraryVersionToPerseusDebug("test-lib", "4.1.8");
70
+ addLibraryVersionToPerseusDebug("test-lib", "1.0.0");
71
+ addLibraryVersionToPerseusDebug("test-lib", "2.0.0");
72
+
73
+ // Assert
74
+ expect(warnSpy).toHaveBeenCalledWith(
75
+ expect.stringMatching(
76
+ /Multiple versions of test-lib loaded on this page/,
77
+ ),
78
+ );
79
+ });
80
+
81
+ it("should not register duplicates for duplicate calls of the same library and version", () => {
82
+ // Arrange
83
+
84
+ // Act
85
+ addLibraryVersionToPerseusDebug("test-lib", "1.0.0");
86
+ addLibraryVersionToPerseusDebug("test-lib", "1.0.0");
87
+ addLibraryVersionToPerseusDebug("test-lib", "1.0.0");
88
+
89
+ // Assert
90
+ expect(globalThis.__perseus_debug__).toMatchInlineSnapshot(`
91
+ {
92
+ "test-lib": "v1.0.0",
93
+ }
94
+ `);
95
+ });
96
+
97
+ it("should not warn for duplicate calls for a library of the same library and version", () => {
98
+ // Arrange
99
+ const warnSpy = jest.spyOn(console, "warn").mockImplementation();
100
+
101
+ // Act
102
+ addLibraryVersionToPerseusDebug("test-lib", "1.0.0");
103
+ addLibraryVersionToPerseusDebug("test-lib", "1.0.0");
104
+ addLibraryVersionToPerseusDebug("test-lib", "1.0.0");
105
+
106
+ // Assert
107
+ expect(warnSpy).not.toHaveBeenCalled();
108
+ });
109
+ });
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Adds the given perseus library version information to the __perseus_debug__
3
+ * object and ensures that the object is attached to `globalThis` (`window` in
4
+ * browser environments).
5
+ *
6
+ * This allows each library to provide runtime version information to assist in
7
+ * debugging in production environments.
8
+ */
9
+ export const addLibraryVersionToPerseusDebug = (
10
+ libraryName: string,
11
+ libraryVersion: string,
12
+ ) => {
13
+ // If the library version is the default value, then we don't want to
14
+ // prefix it with a "v" to indicate that it is a version number.
15
+ let prefix = "v";
16
+ if (libraryVersion === "__lib_version__") {
17
+ prefix = "";
18
+ }
19
+ const formattedVersion = `${prefix}${libraryVersion}`;
20
+
21
+ if (typeof globalThis !== "undefined") {
22
+ globalThis.__perseus_debug__ = globalThis.__perseus_debug__ ?? {};
23
+
24
+ const existingVersionEntry = globalThis.__perseus_debug__[libraryName];
25
+ if (existingVersionEntry) {
26
+ // If we already have an entry and it doesn't match the registered
27
+ // version, we morph the entry into an array and log a warning.
28
+ if (existingVersionEntry !== formattedVersion) {
29
+ // Existing entry might be an array already (oops, at least 2
30
+ // versions of the library already loaded!).
31
+ const allVersions = Array.isArray(existingVersionEntry)
32
+ ? existingVersionEntry
33
+ : [existingVersionEntry];
34
+ allVersions.push(formattedVersion);
35
+
36
+ globalThis.__perseus_debug__[libraryName] = allVersions;
37
+
38
+ // eslint-disable-next-line no-console
39
+ console.warn(
40
+ `Multiple versions of ${libraryName} loaded on this page: ${allVersions
41
+ .sort()
42
+ .join(", ")}`,
43
+ );
44
+ }
45
+ } else {
46
+ globalThis.__perseus_debug__[libraryName] = formattedVersion;
47
+ }
48
+ } else {
49
+ // eslint-disable-next-line no-console
50
+ console.warn(`globalThis not found found (${formattedVersion})`);
51
+ }
52
+ };
package/src/version.ts ADDED
@@ -0,0 +1,10 @@
1
+ // This file is processed by a Rollup plugin (replace) to inject the production
2
+ // version number during the release build.
3
+ // In dev, you'll never see the version number.
4
+
5
+ import {addLibraryVersionToPerseusDebug} from "./utils/add-library-version-to-perseus-debug";
6
+
7
+ const libName = "@khanacademy/perseus-core";
8
+ export const libVersion = "__lib_version__";
9
+
10
+ addLibraryVersionToPerseusDebug(libName, libVersion);
@@ -0,0 +1,19 @@
1
+ {
2
+ "extends": "../tsconfig-shared.json",
3
+ "compilerOptions": {
4
+ "outDir": "./dist/types",
5
+ "rootDir": "src",
6
+ "paths": {
7
+ // NOTE(kevinb): We have to repeat this here because TS doesn't do
8
+ // intelligent merge of tsconfig.json files when using `extends`.
9
+ "@khanacademy/*": [
10
+ "../*/src"
11
+ ]
12
+ }
13
+ },
14
+ "references": [
15
+ /* Add in-repo pacakge references here, like this:
16
+ {"path": "../path/to/package/tsconfig-build.json"}
17
+ */
18
+ ]
19
+ }