@khanacademy/perseus 6.5.0 → 6.5.1
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/CHANGELOG.md +7 -0
- package/dist/es/index.css +24 -21
- package/dist/es/index.js +7 -5
- package/dist/es/index.js.map +1 -1
- package/dist/index.css +24 -21
- package/dist/index.js +7 -6
- package/dist/index.js.map +1 -1
- package/dist/interaction-tracker.d.ts +3 -3
- package/dist/interaction-tracker.js.flow +4 -2
- package/dist/perseus-api.d.ts +5 -1
- package/dist/perseus-api.js.flow +7 -1
- package/dist/server-item-renderer.js.flow +4 -4
- package/dist/types.d.ts +5 -1
- package/dist/types.js.flow +5 -1
- package/dist/widgets/radio/choice.js.flow +1 -4
- package/package.json +1 -1
- package/src/interaction-tracker.ts +4 -3
- package/src/styles/widgets/passage.less +37 -28
- package/src/types.ts +9 -1
- package/src/widgets/__stories__/passage-ref.stories.tsx +18 -7
- package/src/widgets/__stories__/passage.stories.tsx +16 -3
- package/src/widgets/__tests__/__snapshots__/passage-ref.test.ts.snap +6 -6
- package/src/widgets/__tests__/__snapshots__/passage.test.tsx.snap +12 -12
- package/src/widgets/passage.tsx +13 -2
- package/tsconfig-build.tsbuildinfo +1 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { APIOptions } from "./types";
|
|
1
2
|
/**
|
|
2
3
|
* Wrapper for the trackInteraction apiOption.
|
|
3
4
|
*/
|
|
@@ -8,8 +9,7 @@ declare class InteractionTracker {
|
|
|
8
9
|
trackApi: any;
|
|
9
10
|
widgetID: string;
|
|
10
11
|
widgetType: string;
|
|
11
|
-
constructor(trackApi:
|
|
12
|
-
widgetType: string, widgetID: string, setting: "" | "all");
|
|
12
|
+
constructor(trackApi: APIOptions["trackInteraction"], widgetType: string, widgetID: string, setting: "" | "all");
|
|
13
13
|
/**
|
|
14
14
|
* Function that actually calls the API to mark the interaction. This is
|
|
15
15
|
* private. The public version is just `.track` and is bound to this object
|
|
@@ -18,6 +18,6 @@ declare class InteractionTracker {
|
|
|
18
18
|
* @param extraData Any extra data to track about the event.
|
|
19
19
|
* @private
|
|
20
20
|
*/
|
|
21
|
-
_track: (extraData:
|
|
21
|
+
_track: (extraData: Record<string, any>) => void;
|
|
22
22
|
}
|
|
23
23
|
export default InteractionTracker;
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* Flowgen v1.21.0
|
|
5
5
|
* @flow
|
|
6
6
|
*/
|
|
7
|
+
import type { APIOptions } from "./types";
|
|
8
|
+
|
|
7
9
|
/**
|
|
8
10
|
* Wrapper for the trackInteraction apiOption.
|
|
9
11
|
*/
|
|
@@ -15,7 +17,7 @@ declare class InteractionTracker {
|
|
|
15
17
|
widgetID: string;
|
|
16
18
|
widgetType: string;
|
|
17
19
|
constructor(
|
|
18
|
-
trackApi:
|
|
20
|
+
trackApi: $PropertyType<APIOptions, "trackInteraction">,
|
|
19
21
|
widgetType: string,
|
|
20
22
|
widgetID: string,
|
|
21
23
|
setting: "" | "all"
|
|
@@ -28,6 +30,6 @@ declare class InteractionTracker {
|
|
|
28
30
|
* @param extraData Any extra data to track about the event.
|
|
29
31
|
* @private
|
|
30
32
|
*/
|
|
31
|
-
_track: (extraData:
|
|
33
|
+
_track: (extraData: { [key: string]: any }) => void;
|
|
32
34
|
}
|
|
33
35
|
declare export default typeof InteractionTracker;
|
package/dist/perseus-api.d.ts
CHANGED
|
@@ -78,7 +78,11 @@ export declare const ApiOptions: {
|
|
|
78
78
|
Link: React.ComponentType<any>;
|
|
79
79
|
} | undefined;
|
|
80
80
|
imagePreloader?: ((dimensions: import("./types").Dimensions) => React.ReactNode) | undefined;
|
|
81
|
-
trackInteraction?: ((
|
|
81
|
+
trackInteraction?: ((args: {
|
|
82
|
+
type: string;
|
|
83
|
+
id: string;
|
|
84
|
+
correct?: boolean | undefined;
|
|
85
|
+
}) => void) | undefined;
|
|
82
86
|
customKeypad?: boolean | undefined;
|
|
83
87
|
nativeKeypadProxy?: (() => unknown) | undefined;
|
|
84
88
|
isMobile?: boolean | undefined;
|
package/dist/perseus-api.js.flow
CHANGED
|
@@ -78,7 +78,13 @@ declare export var ApiOptions: {|
|
|
|
78
78
|
imagePreloader?:
|
|
79
79
|
| ((dimensions: $Flowgen$Import$_2e__2f_types.Dimensions) => React.Node)
|
|
80
80
|
| void,
|
|
81
|
-
trackInteraction?:
|
|
81
|
+
trackInteraction?:
|
|
82
|
+
| ((args: {|
|
|
83
|
+
type: string,
|
|
84
|
+
id: string,
|
|
85
|
+
correct?: boolean | void,
|
|
86
|
+
|}) => void)
|
|
87
|
+
| void,
|
|
82
88
|
customKeypad?: boolean | void,
|
|
83
89
|
nativeKeypadProxy?: (() => mixed) | void,
|
|
84
90
|
isMobile?: boolean | void,
|
|
@@ -112,8 +112,8 @@ declare export class ServerItemRenderer
|
|
|
112
112
|
setAssetStatus: (assetKey: string, status: boolean) => void;
|
|
113
113
|
render(): React.Node;
|
|
114
114
|
}
|
|
115
|
-
declare var ref: React.
|
|
116
|
-
|
|
115
|
+
declare var ref: React.AbstractComponent<
|
|
116
|
+
$Diff<
|
|
117
117
|
{|
|
|
118
118
|
...KeypadProps,
|
|
119
119
|
...{|
|
|
@@ -131,6 +131,6 @@ declare var ref: React.ForwardRefExoticComponent<{|
|
|
|
131
131
|
|},
|
|
132
132
|
{ onRendered: any }
|
|
133
133
|
>,
|
|
134
|
-
|
|
135
|
-
|
|
134
|
+
ServerItemRenderer
|
|
135
|
+
>;
|
|
136
136
|
declare export default typeof ref;
|
package/dist/types.d.ts
CHANGED
|
@@ -108,7 +108,11 @@ export type APIOptions = Readonly<{
|
|
|
108
108
|
Link: React.ComponentType<any>;
|
|
109
109
|
};
|
|
110
110
|
imagePreloader?: (dimensions: Dimensions) => React.ReactNode;
|
|
111
|
-
trackInteraction?: (
|
|
111
|
+
trackInteraction?: (args: {
|
|
112
|
+
type: string;
|
|
113
|
+
id: string;
|
|
114
|
+
correct?: boolean;
|
|
115
|
+
}) => void;
|
|
112
116
|
customKeypad?: boolean;
|
|
113
117
|
nativeKeypadProxy?: () => unknown;
|
|
114
118
|
isMobile?: boolean;
|
package/dist/types.js.flow
CHANGED
|
@@ -132,7 +132,11 @@ export type APIOptions = $ReadOnly<{|
|
|
|
132
132
|
Link: React.ComponentType<any>,
|
|
133
133
|
|},
|
|
134
134
|
imagePreloader?: (dimensions: Dimensions) => React.Node,
|
|
135
|
-
trackInteraction?: (
|
|
135
|
+
trackInteraction?: (args: {|
|
|
136
|
+
type: string,
|
|
137
|
+
id: string,
|
|
138
|
+
correct?: boolean,
|
|
139
|
+
|}) => void,
|
|
136
140
|
customKeypad?: boolean,
|
|
137
141
|
nativeKeypadProxy?: () => mixed,
|
|
138
142
|
isMobile?: boolean,
|
|
@@ -25,8 +25,5 @@ export type ChoiceProps = {|
|
|
|
25
25
|
crossedOut: boolean,
|
|
26
26
|
|}) => void,
|
|
27
27
|
|};
|
|
28
|
-
declare var _default: React.
|
|
29
|
-
...ChoiceProps,
|
|
30
|
-
...React.RefAttributes<HTMLButtonElement>,
|
|
31
|
-
|}>;
|
|
28
|
+
declare var _default: React.AbstractComponent<ChoiceProps, HTMLButtonElement>;
|
|
32
29
|
declare export default typeof _default;
|
package/package.json
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type {APIOptions} from "./types";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* This alternate version of `.track` does nothing as an optimization.
|
|
3
5
|
*/
|
|
@@ -19,7 +21,7 @@ class InteractionTracker {
|
|
|
19
21
|
widgetType: string;
|
|
20
22
|
|
|
21
23
|
constructor(
|
|
22
|
-
trackApi:
|
|
24
|
+
trackApi: APIOptions["trackInteraction"],
|
|
23
25
|
widgetType: string,
|
|
24
26
|
widgetID: string,
|
|
25
27
|
setting: "" | "all", // "" means track once
|
|
@@ -44,7 +46,7 @@ class InteractionTracker {
|
|
|
44
46
|
* @param extraData Any extra data to track about the event.
|
|
45
47
|
* @private
|
|
46
48
|
*/
|
|
47
|
-
_track: (extraData:
|
|
49
|
+
_track: (extraData: Record<string, any>) => void = (extraData) => {
|
|
48
50
|
if (this._tracked && !this.setting) {
|
|
49
51
|
return;
|
|
50
52
|
}
|
|
@@ -52,7 +54,6 @@ class InteractionTracker {
|
|
|
52
54
|
this.trackApi({
|
|
53
55
|
type: this.widgetType,
|
|
54
56
|
id: this.widgetID,
|
|
55
|
-
// @ts-expect-error [FEI-5003] - TS2698 - Spread types may only be created from object types.
|
|
56
57
|
...extraData,
|
|
57
58
|
});
|
|
58
59
|
};
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
// this selector increases specificity to beat out other stylesheets while still
|
|
2
|
+
// allowing for more than one passage widget on a page
|
|
3
|
+
[id^="perseus-widget-passage-container"] {
|
|
2
4
|
// NOTE(mdr): This is similar to Wonder Blocks "BodySerif" typesetting, but
|
|
3
5
|
// not quite: it's a bit smaller, for consistency with the sorta-small
|
|
4
6
|
// type styles in rest of the Perseus.
|
|
@@ -8,7 +10,7 @@
|
|
|
8
10
|
@font-size: 16px;
|
|
9
11
|
@line-height: 20px;
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
[id^="perseus-widget-passage"] {
|
|
12
14
|
line-height: @line-height;
|
|
13
15
|
margin: 22px;
|
|
14
16
|
position: relative;
|
|
@@ -31,35 +33,43 @@
|
|
|
31
33
|
// switch to the BodySerif component (TP-3112), and remove this
|
|
32
34
|
// special font-family rule.
|
|
33
35
|
div.paragraph {
|
|
34
|
-
font-family: "minion-pro", KaTeX_Main, Times, "Times New Roman",
|
|
36
|
+
font-family: "minion-pro", KaTeX_Main, Times, "Times New Roman",
|
|
37
|
+
serif;
|
|
35
38
|
}
|
|
36
|
-
}
|
|
37
|
-
.katex {
|
|
38
|
-
line-height: @line-height - 2;
|
|
39
|
-
}
|
|
40
|
-
.passage-title div.paragraph {
|
|
41
|
-
font-family: "Noto Serif", serif;
|
|
42
|
-
font-weight: 700;
|
|
43
|
-
font-size: 20px;
|
|
44
|
-
line-height: 22px;
|
|
45
39
|
|
|
46
|
-
|
|
47
|
-
|
|
40
|
+
.passage-title div.paragraph {
|
|
41
|
+
font-family: "Noto Serif", serif;
|
|
42
|
+
font-weight: 700;
|
|
43
|
+
font-size: 20px;
|
|
44
|
+
line-height: 22px;
|
|
48
45
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
// The margin should probably be 0 or the line height
|
|
52
|
-
.passage-text div.paragraph {
|
|
53
|
-
font-weight: 400;
|
|
54
|
-
font-size: @font-size;
|
|
55
|
-
line-height: @line-height;
|
|
56
|
-
text-indent: 20px;
|
|
57
|
-
margin: 0;
|
|
46
|
+
margin: 0 0 10px;
|
|
47
|
+
}
|
|
58
48
|
|
|
59
|
-
|
|
60
|
-
|
|
49
|
+
// note(matthewc): If you need to change any of this,
|
|
50
|
+
// check that line numbers line up correctly.
|
|
51
|
+
// The margin should probably be 0 or the line height
|
|
52
|
+
.passage-text div.paragraph {
|
|
53
|
+
font-weight: 400;
|
|
54
|
+
font-size: @font-size;
|
|
55
|
+
line-height: @line-height;
|
|
56
|
+
text-indent: 20px;
|
|
57
|
+
margin: 0;
|
|
58
|
+
|
|
59
|
+
span {
|
|
60
|
+
text-indent: 0;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
em {
|
|
64
|
+
// prevents italicized text from disrupting the line height
|
|
65
|
+
line-height: 0;
|
|
66
|
+
}
|
|
61
67
|
}
|
|
62
68
|
}
|
|
69
|
+
.katex {
|
|
70
|
+
line-height: @line-height - 2;
|
|
71
|
+
}
|
|
72
|
+
|
|
63
73
|
.footnotes {
|
|
64
74
|
margin-top: 22px;
|
|
65
75
|
div.paragraph {
|
|
@@ -68,10 +78,10 @@
|
|
|
68
78
|
}
|
|
69
79
|
}
|
|
70
80
|
.perseus-highlight {
|
|
71
|
-
background-color: #
|
|
81
|
+
background-color: #fffabe;
|
|
72
82
|
}
|
|
73
83
|
.perseus-review-highlight {
|
|
74
|
-
background-color: #
|
|
84
|
+
background-color: #eee7b2;
|
|
75
85
|
}
|
|
76
86
|
.perseus-passage-square-label,
|
|
77
87
|
.perseus-passage-circle-label,
|
|
@@ -138,7 +148,6 @@
|
|
|
138
148
|
}
|
|
139
149
|
|
|
140
150
|
.perseus-widget-passage-editor {
|
|
141
|
-
|
|
142
151
|
.perseus-single-editor {
|
|
143
152
|
font-family: Times, "Times New Roman", serif;
|
|
144
153
|
|
package/src/types.ts
CHANGED
|
@@ -183,7 +183,11 @@ export type APIOptions = Readonly<{
|
|
|
183
183
|
// include type and id, both strings, at least and can optionally
|
|
184
184
|
// include a boolean "correct" value. This is used for keeping
|
|
185
185
|
// track of widget interactions.
|
|
186
|
-
trackInteraction?: (
|
|
186
|
+
trackInteraction?: (args: {
|
|
187
|
+
type: string;
|
|
188
|
+
id: string;
|
|
189
|
+
correct?: boolean;
|
|
190
|
+
}) => void;
|
|
187
191
|
// A boolean that indicates whether or not a custom keypad is
|
|
188
192
|
// being used. For mobile web this will be the ProvidedKeypad
|
|
189
193
|
// component. In this situation we use the MathInput component
|
|
@@ -462,6 +466,10 @@ export type WidgetProps<RenderProps, Rubric> = RenderProps & {
|
|
|
462
466
|
findWidgets: (arg1: FilterCriterion) => ReadonlyArray<Widget>;
|
|
463
467
|
reviewModeRubric: Rubric;
|
|
464
468
|
onChange: ChangeHandler;
|
|
469
|
+
// This is slightly different from the `trackInteraction` function in
|
|
470
|
+
// APIOptions. This provides the widget an easy way to notify the renderer
|
|
471
|
+
// of an interaction. The Renderer then enriches the data provided with the
|
|
472
|
+
// widget's id and type before calling APIOptions.trackInteraction.
|
|
465
473
|
trackInteraction: (extraData?: any) => void;
|
|
466
474
|
isLastUsedWidget: boolean;
|
|
467
475
|
// provided by widget-container.jsx#render()
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import {View} from "@khanacademy/wonder-blocks-core";
|
|
1
2
|
import * as React from "react";
|
|
2
3
|
|
|
3
4
|
import {RendererWithDebugUI} from "../../../../../testing/renderer-with-debug-ui";
|
|
4
5
|
import {question1, question2} from "../__testdata__/passage-ref.testdata";
|
|
5
6
|
|
|
6
|
-
type
|
|
7
|
+
import type {PerseusRenderer} from "../../perseus-types";
|
|
7
8
|
|
|
8
9
|
type Story = {
|
|
9
10
|
title: string;
|
|
@@ -13,10 +14,20 @@ export default {
|
|
|
13
14
|
title: "Perseus/Widgets/PassageRef",
|
|
14
15
|
} as Story;
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
const Template = (props: {question: PerseusRenderer}): React.ReactElement => (
|
|
18
|
+
<View
|
|
19
|
+
style={{
|
|
20
|
+
paddingLeft: 20,
|
|
21
|
+
}}
|
|
22
|
+
>
|
|
23
|
+
<RendererWithDebugUI question={props.question} />
|
|
24
|
+
</View>
|
|
25
|
+
);
|
|
19
26
|
|
|
20
|
-
export const
|
|
21
|
-
|
|
22
|
-
|
|
27
|
+
export const ShortPassage = (): React.ReactElement => (
|
|
28
|
+
<Template question={question1} />
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
export const LongPassage = (): React.ReactElement => (
|
|
32
|
+
<Template question={question2} />
|
|
33
|
+
);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import {View} from "@khanacademy/wonder-blocks-core";
|
|
1
2
|
import * as React from "react";
|
|
2
3
|
|
|
3
4
|
import {RendererWithDebugUI} from "../../../../../testing/renderer-with-debug-ui";
|
|
@@ -7,20 +8,32 @@ import {
|
|
|
7
8
|
question3,
|
|
8
9
|
} from "../__testdata__/passage.testdata";
|
|
9
10
|
|
|
11
|
+
import type {PerseusRenderer} from "../../perseus-types";
|
|
12
|
+
|
|
10
13
|
export default {
|
|
11
14
|
title: "Perseus/Widgets/Passage",
|
|
12
15
|
};
|
|
13
16
|
|
|
14
17
|
type StoryArgs = Record<any, any>;
|
|
15
18
|
|
|
19
|
+
const Template = (props: {question: PerseusRenderer}): React.ReactElement => (
|
|
20
|
+
<View
|
|
21
|
+
style={{
|
|
22
|
+
paddingLeft: 20,
|
|
23
|
+
}}
|
|
24
|
+
>
|
|
25
|
+
<RendererWithDebugUI question={props.question} />
|
|
26
|
+
</View>
|
|
27
|
+
);
|
|
28
|
+
|
|
16
29
|
export const SimpleQuestion = (args: StoryArgs): React.ReactElement => {
|
|
17
|
-
return <
|
|
30
|
+
return <Template question={question1} />;
|
|
18
31
|
};
|
|
19
32
|
|
|
20
33
|
export const MultiPassageQuestion = (args: StoryArgs): React.ReactElement => {
|
|
21
|
-
return <
|
|
34
|
+
return <Template question={question2} />;
|
|
22
35
|
};
|
|
23
36
|
|
|
24
37
|
export const SingleNumberedPassage = (args: StoryArgs): React.ReactElement => {
|
|
25
|
-
return <
|
|
38
|
+
return <Template question={question3} />;
|
|
26
39
|
};
|
|
@@ -17,7 +17,7 @@ exports[`passage-ref widget should render with invalid reference 1`] = `
|
|
|
17
17
|
>
|
|
18
18
|
<div>
|
|
19
19
|
<div
|
|
20
|
-
|
|
20
|
+
id="perseus-widget-passage-container-"
|
|
21
21
|
>
|
|
22
22
|
<div
|
|
23
23
|
class="perseus-widget-passage-instructions"
|
|
@@ -26,7 +26,7 @@ exports[`passage-ref widget should render with invalid reference 1`] = `
|
|
|
26
26
|
|
|
27
27
|
</div>
|
|
28
28
|
<div
|
|
29
|
-
|
|
29
|
+
id="perseus-widget-passage-"
|
|
30
30
|
>
|
|
31
31
|
<h3
|
|
32
32
|
class="perseus-sr-only"
|
|
@@ -158,7 +158,7 @@ exports[`passage-ref widget should render with multi-line reference 1`] = `
|
|
|
158
158
|
>
|
|
159
159
|
<div>
|
|
160
160
|
<div
|
|
161
|
-
|
|
161
|
+
id="perseus-widget-passage-container-"
|
|
162
162
|
>
|
|
163
163
|
<div
|
|
164
164
|
class="perseus-widget-passage-instructions"
|
|
@@ -167,7 +167,7 @@ exports[`passage-ref widget should render with multi-line reference 1`] = `
|
|
|
167
167
|
|
|
168
168
|
</div>
|
|
169
169
|
<div
|
|
170
|
-
|
|
170
|
+
id="perseus-widget-passage-"
|
|
171
171
|
>
|
|
172
172
|
<h3
|
|
173
173
|
class="perseus-sr-only"
|
|
@@ -304,7 +304,7 @@ exports[`passage-ref widget should render with single-line reference 1`] = `
|
|
|
304
304
|
>
|
|
305
305
|
<div>
|
|
306
306
|
<div
|
|
307
|
-
|
|
307
|
+
id="perseus-widget-passage-container-"
|
|
308
308
|
>
|
|
309
309
|
<div
|
|
310
310
|
class="perseus-widget-passage-instructions"
|
|
@@ -313,7 +313,7 @@ exports[`passage-ref widget should render with single-line reference 1`] = `
|
|
|
313
313
|
|
|
314
314
|
</div>
|
|
315
315
|
<div
|
|
316
|
-
|
|
316
|
+
id="perseus-widget-passage-"
|
|
317
317
|
>
|
|
318
318
|
<h3
|
|
319
319
|
class="perseus-sr-only"
|
|
@@ -97,7 +97,7 @@ exports[`passage widget should snapshot multiple passages (mobile: false) 1`] =
|
|
|
97
97
|
>
|
|
98
98
|
<div>
|
|
99
99
|
<div
|
|
100
|
-
|
|
100
|
+
id="perseus-widget-passage-container-passage-1"
|
|
101
101
|
>
|
|
102
102
|
<div
|
|
103
103
|
class="perseus-widget-passage-instructions"
|
|
@@ -136,7 +136,7 @@ exports[`passage widget should snapshot multiple passages (mobile: false) 1`] =
|
|
|
136
136
|
</div>
|
|
137
137
|
</div>
|
|
138
138
|
<div
|
|
139
|
-
|
|
139
|
+
id="perseus-widget-passage-passage-1"
|
|
140
140
|
>
|
|
141
141
|
<h3
|
|
142
142
|
class="passage-title"
|
|
@@ -590,7 +590,7 @@ exports[`passage widget should snapshot multiple passages (mobile: false) 1`] =
|
|
|
590
590
|
>
|
|
591
591
|
<div>
|
|
592
592
|
<div
|
|
593
|
-
|
|
593
|
+
id="perseus-widget-passage-container-passage-2"
|
|
594
594
|
>
|
|
595
595
|
<div
|
|
596
596
|
class="perseus-widget-passage-instructions"
|
|
@@ -626,7 +626,7 @@ exports[`passage widget should snapshot multiple passages (mobile: false) 1`] =
|
|
|
626
626
|
</div>
|
|
627
627
|
</div>
|
|
628
628
|
<div
|
|
629
|
-
|
|
629
|
+
id="perseus-widget-passage-passage-2"
|
|
630
630
|
>
|
|
631
631
|
<h3
|
|
632
632
|
class="passage-title"
|
|
@@ -956,7 +956,7 @@ exports[`passage widget should snapshot multiple passages (mobile: true) 1`] = `
|
|
|
956
956
|
>
|
|
957
957
|
<div>
|
|
958
958
|
<div
|
|
959
|
-
|
|
959
|
+
id="perseus-widget-passage-container-passage-1"
|
|
960
960
|
>
|
|
961
961
|
<div
|
|
962
962
|
class="perseus-widget-passage-instructions"
|
|
@@ -995,7 +995,7 @@ exports[`passage widget should snapshot multiple passages (mobile: true) 1`] = `
|
|
|
995
995
|
</div>
|
|
996
996
|
</div>
|
|
997
997
|
<div
|
|
998
|
-
|
|
998
|
+
id="perseus-widget-passage-passage-1"
|
|
999
999
|
>
|
|
1000
1000
|
<h3
|
|
1001
1001
|
class="passage-title"
|
|
@@ -1449,7 +1449,7 @@ exports[`passage widget should snapshot multiple passages (mobile: true) 1`] = `
|
|
|
1449
1449
|
>
|
|
1450
1450
|
<div>
|
|
1451
1451
|
<div
|
|
1452
|
-
|
|
1452
|
+
id="perseus-widget-passage-container-passage-2"
|
|
1453
1453
|
>
|
|
1454
1454
|
<div
|
|
1455
1455
|
class="perseus-widget-passage-instructions"
|
|
@@ -1485,7 +1485,7 @@ exports[`passage widget should snapshot multiple passages (mobile: true) 1`] = `
|
|
|
1485
1485
|
</div>
|
|
1486
1486
|
</div>
|
|
1487
1487
|
<div
|
|
1488
|
-
|
|
1488
|
+
id="perseus-widget-passage-passage-2"
|
|
1489
1489
|
>
|
|
1490
1490
|
<h3
|
|
1491
1491
|
class="passage-title"
|
|
@@ -1778,7 +1778,7 @@ exports[`passage widget should snapshot simple passage (mobile: false) 1`] = `
|
|
|
1778
1778
|
>
|
|
1779
1779
|
<div>
|
|
1780
1780
|
<div
|
|
1781
|
-
|
|
1781
|
+
id="perseus-widget-passage-container-"
|
|
1782
1782
|
>
|
|
1783
1783
|
<div
|
|
1784
1784
|
class="perseus-widget-passage-instructions"
|
|
@@ -1787,7 +1787,7 @@ exports[`passage widget should snapshot simple passage (mobile: false) 1`] = `
|
|
|
1787
1787
|
|
|
1788
1788
|
</div>
|
|
1789
1789
|
<div
|
|
1790
|
-
|
|
1790
|
+
id="perseus-widget-passage-"
|
|
1791
1791
|
>
|
|
1792
1792
|
<h3
|
|
1793
1793
|
class="perseus-sr-only"
|
|
@@ -1875,7 +1875,7 @@ exports[`passage widget should snapshot simple passage (mobile: true) 1`] = `
|
|
|
1875
1875
|
>
|
|
1876
1876
|
<div>
|
|
1877
1877
|
<div
|
|
1878
|
-
|
|
1878
|
+
id="perseus-widget-passage-container-"
|
|
1879
1879
|
>
|
|
1880
1880
|
<div
|
|
1881
1881
|
class="perseus-widget-passage-instructions"
|
|
@@ -1884,7 +1884,7 @@ exports[`passage widget should snapshot simple passage (mobile: true) 1`] = `
|
|
|
1884
1884
|
|
|
1885
1885
|
</div>
|
|
1886
1886
|
<div
|
|
1887
|
-
|
|
1887
|
+
id="perseus-widget-passage-"
|
|
1888
1888
|
>
|
|
1889
1889
|
<h3
|
|
1890
1890
|
class="perseus-sr-only"
|
package/src/widgets/passage.tsx
CHANGED
|
@@ -509,12 +509,13 @@ export class Passage extends React.Component<PassageProps, PassageState> {
|
|
|
509
509
|
);
|
|
510
510
|
// Check if the title has any non-empty text in it.
|
|
511
511
|
const hasTitle = /\S/.test(this.props.passageTitle);
|
|
512
|
+
const joinedTitle = joinString(this.props.passageTitle);
|
|
512
513
|
|
|
513
514
|
return (
|
|
514
515
|
<div>
|
|
515
|
-
<div
|
|
516
|
+
<div id={"perseus-widget-passage-container" + joinedTitle}>
|
|
516
517
|
{this._renderInstructions(parseState)}
|
|
517
|
-
<div
|
|
518
|
+
<div id={"perseus-widget-passage" + joinedTitle}>
|
|
518
519
|
{hasTitle && (
|
|
519
520
|
<h3 className="passage-title">
|
|
520
521
|
<Renderer
|
|
@@ -567,6 +568,16 @@ export class Passage extends React.Component<PassageProps, PassageState> {
|
|
|
567
568
|
}
|
|
568
569
|
}
|
|
569
570
|
|
|
571
|
+
// That's All, Folks! => -thats-all-folks
|
|
572
|
+
const joinString = (title: string): string =>
|
|
573
|
+
"-" +
|
|
574
|
+
title
|
|
575
|
+
.toLowerCase()
|
|
576
|
+
.replace(/[^\w\s]/gi, "")
|
|
577
|
+
.trim()
|
|
578
|
+
.split(/\s+/)
|
|
579
|
+
.join("-");
|
|
580
|
+
|
|
570
581
|
export default {
|
|
571
582
|
name: "passage",
|
|
572
583
|
displayName: "Passage (SAT only)",
|