@khanacademy/perseus 6.4.4 → 6.5.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/CHANGELOG.md +12 -0
- package/dist/es/index.css +583 -367
- package/dist/es/index.js +5 -3
- package/dist/es/index.js.map +1 -1
- package/dist/index.css +583 -367
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/__stories__/item-renderer.stories.tsx +5 -0
- package/src/__testdata__/item-renderer.testdata.ts +139 -0
- package/src/multi-items/__tests__/__snapshots__/multi-renderer.test.tsx.snap +8 -8
- package/src/styles/articles.less +24 -18
- package/src/styles/khan-exercise.css +577 -365
- package/src/widgets/__tests__/__snapshots__/group.test.tsx.snap +8 -8
- package/src/widgets/__tests__/__snapshots__/radio.test.ts.snap +49 -49
- package/src/widgets/radio/base-radio.tsx +2 -1
- package/src/widgets/radio/choice.tsx +1 -0
- package/tsconfig-build.tsbuildinfo +1 -1
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "Core Perseus API (includes renderers and widgets)",
|
|
4
4
|
"author": "Khan Academy",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"version": "6.
|
|
6
|
+
"version": "6.5.0",
|
|
7
7
|
"publishConfig": {
|
|
8
8
|
"access": "public"
|
|
9
9
|
},
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@khanacademy/kas": "^0.3.1",
|
|
25
25
|
"@khanacademy/kmath": "^0.1.1",
|
|
26
|
-
"@khanacademy/math-input": "^6.0.
|
|
26
|
+
"@khanacademy/math-input": "^6.0.3",
|
|
27
27
|
"@khanacademy/perseus-core": "0.0.2",
|
|
28
28
|
"@khanacademy/perseus-linter": "^0.3.1",
|
|
29
29
|
"@khanacademy/pure-markdown": "^0.2.3",
|
|
@@ -4,6 +4,7 @@ import {ItemRendererWithDebugUI} from "../../../../testing/item-renderer-with-de
|
|
|
4
4
|
import {
|
|
5
5
|
itemWithInput,
|
|
6
6
|
labelImageItem,
|
|
7
|
+
codeblockItem,
|
|
7
8
|
} from "../__testdata__/item-renderer.testdata";
|
|
8
9
|
|
|
9
10
|
type StoryArgs = Record<any, any>;
|
|
@@ -23,3 +24,7 @@ export const InputNumberItem = (args: StoryArgs): React.ReactElement => {
|
|
|
23
24
|
export const LabelImageItem = (args: StoryArgs): React.ReactElement => {
|
|
24
25
|
return <ItemRendererWithDebugUI item={labelImageItem} />;
|
|
25
26
|
};
|
|
27
|
+
|
|
28
|
+
export const CodeblockItem = (args: StoryArgs): React.ReactElement => {
|
|
29
|
+
return <ItemRendererWithDebugUI item={codeblockItem} />;
|
|
30
|
+
};
|
|
@@ -5,6 +5,145 @@ import type {
|
|
|
5
5
|
PerseusRenderer,
|
|
6
6
|
} from "../perseus-types";
|
|
7
7
|
|
|
8
|
+
export const codeblockItem: PerseusItem = {
|
|
9
|
+
question: {
|
|
10
|
+
content:
|
|
11
|
+
'Charlotte is writing code to turn sentences into Pig Latin.\n\nThis is what she has so far:\n\n```\nsentence ← ""\nword1 ← "Hello"\nfirstLetter1 ← SUBSTRING(word1, 1, 1)\notherLetters1 ← SUBSTRING(word1, 2, LENGTH(word1) - 1)\npigLatin1 ← CONCAT(otherLetters1, firstLetter1, "ay")\nsentence ← CONCAT(sentence, pigLatin1, " ")\nword2 ← "Mister"\nfirstLetter2 ← SUBSTRING(word2, 1, 1)\notherLetters2 ← SUBSTRING(word2, 2, LENGTH(word2) - 1)\npigLatin2 ← CONCAT(otherLetters2, firstLetter2, "ay")\nsentence ← CONCAT(sentence, pigLatin2, " ")\nword3 ← "Rogers"\nfirstLetter3 ← SUBSTRING(word3, 1, 1)\notherLetters3 ← SUBSTRING(word3, 2, LENGTH(word3) - 1)\npigLatin3 ← CONCAT(otherLetters3, firstLetter3, "ay")\nsentence ← CONCAT(sentence, pigLatin3, " ")\nDISPLAY(sentence)\n```\n\nThe code relies on two string procedures:\n\nName | Description\n- | - | -\n`CONCATENATE (string1, string2, ...)` | Returns a single string that combines the provided strings together in order.\n`SUBSTRING (string, startPos, numChars)` | Returns a substring of `string` starting at `startPos` of length `numChars`. The first character in the string is at position 1.\n\nA friend points out that she can reduce the complexity of her code by using the abstractions of lists and loops. \n\nCharlotte decides to "refactor" the code, to rewrite it so that it produces the same output but is structured better.\n\n**Which of these is the best refactor of the code?**\n\n[[☃ radio 1]]\n\n🤔[[☃ explanation 1]]',
|
|
12
|
+
images: {},
|
|
13
|
+
widgets: {
|
|
14
|
+
"radio 1": {
|
|
15
|
+
type: "radio",
|
|
16
|
+
alignment: "default",
|
|
17
|
+
static: false,
|
|
18
|
+
graded: true,
|
|
19
|
+
options: {
|
|
20
|
+
choices: [
|
|
21
|
+
{
|
|
22
|
+
content:
|
|
23
|
+
'```\nwords ← ["Hello", "Mister", "Rogers"]\nsentence ← ""\nFOR EACH word IN words\n{\n firstLetter ← SUBSTRING(word, 1, 1)\n otherLetters ← SUBSTRING(word, 2, LENGTH(word) - 1)\n pigLatin ← CONCAT(otherLetters, firstLetter, "ay")\n sentence ← CONCAT(sentence, pigLatin, " ")\n}\nDISPLAY(sentence)\n```',
|
|
24
|
+
correct: true,
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
content:
|
|
28
|
+
'```\nwords ← ["Hello", "Mister", "Rogers"]\nsentence ← ""\nFOR EACH word IN words\n{\n firstLetter ← SUBSTRING(words[1], 1, 1)\n otherLetters ← SUBSTRING(words[1], 2, LENGTH(words[1]) - 1)\n pigLatin ← CONCAT(otherLetters, firstLetter, "ay")\n sentence ← CONCAT(sentence, pigLatin, " ")\n}\nDISPLAY(sentence)\n```',
|
|
29
|
+
correct: false,
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
isNoneOfTheAbove: false,
|
|
33
|
+
content:
|
|
34
|
+
'```\nwords ← ["Hello", "Mister", "Rogers"]\nFOR EACH word IN words\n{\n sentence ← ""\n firstLetter ← SUBSTRING(word, 1, 1)\n otherLetters ← SUBSTRING(word, 2, LENGTH(word) - 1)\n pigLatin ← CONCAT(otherLetters, firstLetter, "ay")\n sentence ← CONCAT(sentence, pigLatin, " ")\n}\nDISPLAY(sentence)\n```',
|
|
35
|
+
correct: false,
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
isNoneOfTheAbove: false,
|
|
39
|
+
content:
|
|
40
|
+
'```\nwords ← ["Hello", "Mister", "Rogers"]\nsentence ← ""\nFOR EACH word IN words\n{\n firstLetter ← SUBSTRING(word, 1, 1)\n otherLetters ← SUBSTRING(word, 2, LENGTH(word) - 1)\n pigLatin ← CONCAT(otherLetters, firstLetter, "ay")\n sentence ← CONCAT(sentence, pigLatin, " ")\n DISPLAY(sentence)\n}\n```',
|
|
41
|
+
correct: false,
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
isNoneOfTheAbove: false,
|
|
45
|
+
content:
|
|
46
|
+
'```\nwords ← ["Hello", "Mister", "Rogers"]\nFOR EACH word IN words\n{\n sentence ← ""\n firstLetter ← SUBSTRING(word, 1, 1)\n otherLetters ← SUBSTRING(word, 2, LENGTH(word) - 1)\n pigLatin ← CONCAT(otherLetters, firstLetter, "ay")\n sentence ← CONCAT(sentence, pigLatin, " ")\n DISPLAY(sentence)\n}\n```',
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
randomize: true,
|
|
50
|
+
multipleSelect: false,
|
|
51
|
+
countChoices: false,
|
|
52
|
+
displayCount: null,
|
|
53
|
+
hasNoneOfTheAbove: false,
|
|
54
|
+
deselectEnabled: false,
|
|
55
|
+
},
|
|
56
|
+
version: {
|
|
57
|
+
major: 1,
|
|
58
|
+
minor: 0,
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
"explanation 1": {
|
|
62
|
+
type: "explanation",
|
|
63
|
+
alignment: "default",
|
|
64
|
+
static: false,
|
|
65
|
+
graded: true,
|
|
66
|
+
options: {
|
|
67
|
+
static: false,
|
|
68
|
+
showPrompt: "What language is the code in?",
|
|
69
|
+
hidePrompt: "Hide explanation",
|
|
70
|
+
explanation:
|
|
71
|
+
"This code is written in **pseudocode**. You can't actually run pseudocode, but we use it for planning programs and for thinking about code independently of specific programming language. \n\nAP CSP exam questions use pseudocode, so it's helpful to become familiar with it.\n\nHere is a reference for the pseudocode used here:\n\n****\n\n`a ← expression`\n\nEvaluates `expression` and assigns the result to the variable `a`.\n\n****\n\n`list ← [value1, value2, value3]`\n\nCreates a list with 3 values. The first value is located at index 1, the second at index 2, the third at index 3.\n\n****\n\n```\nFOR EACH value IN list\n{\n <instructions>\n}\n```\n\nAssigns `value` to the value of each element in `list` sequentially, starting from the first element and ending with the last element. Executes the code in `instructions` once for each `value`.\n",
|
|
72
|
+
widgets: {},
|
|
73
|
+
},
|
|
74
|
+
version: {
|
|
75
|
+
major: 0,
|
|
76
|
+
minor: 0,
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
answerArea: {
|
|
82
|
+
calculator: false,
|
|
83
|
+
chi2Table: false,
|
|
84
|
+
periodicTable: false,
|
|
85
|
+
tTable: false,
|
|
86
|
+
zTable: false,
|
|
87
|
+
},
|
|
88
|
+
itemDataVersion: {
|
|
89
|
+
major: 0,
|
|
90
|
+
minor: 1,
|
|
91
|
+
},
|
|
92
|
+
hints: [
|
|
93
|
+
{
|
|
94
|
+
replace: false,
|
|
95
|
+
content:
|
|
96
|
+
'The first step in refactoring this code is to recognize the related variables that can be combined into a list.\n\nIn this case, that\'s `word1`, `word2`, and `word3` from the original code. We can tell they\'re related from the naming, but more importantly, from the way the same code is repeated for each of them.\n\nWe\'ll store the values of those 3 variables in a single list:\n\n```words ← ["Hello", "Mister", "Rogers"]```',
|
|
97
|
+
images: {},
|
|
98
|
+
widgets: {},
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
replace: false,
|
|
102
|
+
content:
|
|
103
|
+
"The next step in refactoring this code is to identify the code that is only executed once versus the code that is executed for each element in that list.",
|
|
104
|
+
images: {},
|
|
105
|
+
widgets: {},
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
replace: false,
|
|
109
|
+
content:
|
|
110
|
+
'We can see that there are 3 blocks of code that deal with each of the original variables.\n\nCode for `word1`:\n\n```\nword1 ← "Hello"\nfirstLetter1 ← SUBSTRING(word1, 1, 1)\notherLetters1 ← SUBSTRING(word1, 2, LENGTH(word1) - 1)\npigLatin1 ← CONCAT(otherLetters1, firstLetter1, "ay")\nsentence ← CONCAT(sentence, pigLatin1, " ")\n```\n\n\nCode for `word2`:\n\n```\nword2 ← "Mister"\nfirstLetter2 ← SUBSTRING(word2, 1, 1)\notherLetters2 ← SUBSTRING(word2, 2, LENGTH(word2) - 1)\npigLatin2 ← CONCAT(otherLetters2, firstLetter2, "ay")\nsentence ← CONCAT(sentence, pigLatin2, " ")\n```\n\nCode for `word3`:\n\n```\nword3 ← "Rogers"\nfirstLetter3 ← SUBSTRING(word3, 1, 1)\notherLetters3 ← SUBSTRING(word3, 2, LENGTH(word3) - 1)\npigLatin3 ← CONCAT(otherLetters3, firstLetter3, "ay")\nsentence ← CONCAT(sentence, pigLatin3, " ")\n```\n\nEach of these blocks of code do the same operations:\n\n1. store the word in a variable\n2. store a substring of the word, the first letter in it\n3. store another substring of the word, the rest of the letters\n4. store a new string that concatenates the two substrings and "ay"\n5. concatenate that string with the existing `sentence`',
|
|
111
|
+
images: {},
|
|
112
|
+
widgets: {},
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
replace: false,
|
|
116
|
+
content:
|
|
117
|
+
'Now that we\'ve put the variables into a list, we can use a loop to execute those same operations on each element:\n\n```\nFOR EACH word in words\n{\n firstLetter ← SUBSTRING(word, 1, 1)\n otherLetters ← SUBSTRING(word, 2, LENGTH(word) - 1)\n pigLatin ← CONCAT(otherLetters, firstLetter, "ay")\n sentence ← CONCAT(sentence, pigLatin, " ")\n}\n```\n\nYou\'ll notice there are only four lines of code inside the loop, versus the five lines in the grouped blocks from before. That\'s because the `FOR EACH` header takes care of storing the current list element in `word`. The value of `word` will first be "Hello", then "Mister", then "Rogers", according to the order of the values in the list.\n',
|
|
118
|
+
images: {},
|
|
119
|
+
widgets: {},
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
replace: false,
|
|
123
|
+
content:
|
|
124
|
+
'There are two lines of code that we haven\'t refactored yet.\n\nOne is the very first line of the original code:\n\n`sentence ← ""`\n\nIn the new code, this needs to happen _before_ the `FOR EACH` loop, since the value of `sentence` is manipulated inside the loop.',
|
|
125
|
+
images: {},
|
|
126
|
+
widgets: {},
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
replace: false,
|
|
130
|
+
content:
|
|
131
|
+
"The remaining line is the very last line of the original code:\n\n```DISPLAY(sentence)```\n\nIn the new code, this needs to happen _after_ the `FOR EACH` loop, since it should display the value after all the concatenations happen.",
|
|
132
|
+
images: {},
|
|
133
|
+
widgets: {},
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
replace: false,
|
|
137
|
+
content:
|
|
138
|
+
'Thus, this is the best refactor of the original code to use lists and loops:\n\n```\nwords ← ["Hello", "Mister", "Rogers"]\nsentence ← ""\nFOR EACH word IN words\n{\n firstLetter ← SUBSTRING(word, 1, 1)\n otherLetters ← SUBSTRING(word, 2, LENGTH(word) - 1)\n pigLatin ← CONCAT(otherLetters, firstLetter, "ay")\n sentence ← CONCAT(sentence, pigLatin, " ")\n}\nDISPLAY(sentence)\n```',
|
|
139
|
+
images: {},
|
|
140
|
+
widgets: {},
|
|
141
|
+
},
|
|
142
|
+
],
|
|
143
|
+
_multi: null,
|
|
144
|
+
answer: null,
|
|
145
|
+
};
|
|
146
|
+
|
|
8
147
|
export const itemWithInput: PerseusItem = {
|
|
9
148
|
question: {
|
|
10
149
|
content:
|
|
@@ -105,10 +105,10 @@ exports[`multi-item renderer should snapshot: initial render 1`] = `
|
|
|
105
105
|
class="perseus-widget-container widget-nohighlight widget-block"
|
|
106
106
|
>
|
|
107
107
|
<div
|
|
108
|
-
class="
|
|
108
|
+
class="responsiveContainer_12z1v8o"
|
|
109
109
|
>
|
|
110
110
|
<fieldset
|
|
111
|
-
class="perseus-widget-radio-fieldset
|
|
111
|
+
class="perseus-widget-radio-fieldset responsiveFieldset_le06t6"
|
|
112
112
|
>
|
|
113
113
|
<legend
|
|
114
114
|
class="perseus-sr-only"
|
|
@@ -117,7 +117,7 @@ exports[`multi-item renderer should snapshot: initial render 1`] = `
|
|
|
117
117
|
</legend>
|
|
118
118
|
<div
|
|
119
119
|
aria-hidden="true"
|
|
120
|
-
class="instructions
|
|
120
|
+
class="instructions instructions_f9jkqj"
|
|
121
121
|
>
|
|
122
122
|
Choose 1 answer:
|
|
123
123
|
</div>
|
|
@@ -133,7 +133,7 @@ exports[`multi-item renderer should snapshot: initial render 1`] = `
|
|
|
133
133
|
style="flex-direction: column; color: rgb(33, 36, 44);"
|
|
134
134
|
>
|
|
135
135
|
<div
|
|
136
|
-
style="display: flex; flex-direction: row; opacity: 1;"
|
|
136
|
+
style="display: flex; flex-direction: row; opacity: 1; overflow: auto;"
|
|
137
137
|
>
|
|
138
138
|
<div
|
|
139
139
|
class="perseus-sr-only"
|
|
@@ -300,7 +300,7 @@ exports[`multi-item renderer should snapshot: initial render 1`] = `
|
|
|
300
300
|
style="flex-direction: column; color: rgb(33, 36, 44);"
|
|
301
301
|
>
|
|
302
302
|
<div
|
|
303
|
-
style="display: flex; flex-direction: row; opacity: 1;"
|
|
303
|
+
style="display: flex; flex-direction: row; opacity: 1; overflow: auto;"
|
|
304
304
|
>
|
|
305
305
|
<div
|
|
306
306
|
class="perseus-sr-only"
|
|
@@ -467,7 +467,7 @@ exports[`multi-item renderer should snapshot: initial render 1`] = `
|
|
|
467
467
|
style="flex-direction: column; color: rgb(33, 36, 44);"
|
|
468
468
|
>
|
|
469
469
|
<div
|
|
470
|
-
style="display: flex; flex-direction: row; opacity: 1;"
|
|
470
|
+
style="display: flex; flex-direction: row; opacity: 1; overflow: auto;"
|
|
471
471
|
>
|
|
472
472
|
<div
|
|
473
473
|
class="perseus-sr-only"
|
|
@@ -634,7 +634,7 @@ exports[`multi-item renderer should snapshot: initial render 1`] = `
|
|
|
634
634
|
style="flex-direction: column; color: rgb(33, 36, 44);"
|
|
635
635
|
>
|
|
636
636
|
<div
|
|
637
|
-
style="display: flex; flex-direction: row; opacity: 1;"
|
|
637
|
+
style="display: flex; flex-direction: row; opacity: 1; overflow: auto;"
|
|
638
638
|
>
|
|
639
639
|
<div
|
|
640
640
|
class="perseus-sr-only"
|
|
@@ -801,7 +801,7 @@ exports[`multi-item renderer should snapshot: initial render 1`] = `
|
|
|
801
801
|
style="flex-direction: column; color: rgb(33, 36, 44);"
|
|
802
802
|
>
|
|
803
803
|
<div
|
|
804
|
-
style="display: flex; flex-direction: row; opacity: 1;"
|
|
804
|
+
style="display: flex; flex-direction: row; opacity: 1; overflow: auto;"
|
|
805
805
|
>
|
|
806
806
|
<div
|
|
807
807
|
class="perseus-sr-only"
|
package/src/styles/articles.less
CHANGED
|
@@ -129,7 +129,9 @@
|
|
|
129
129
|
margin-top: 32px;
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
-
h4,
|
|
132
|
+
h4,
|
|
133
|
+
h5,
|
|
134
|
+
h6 {
|
|
133
135
|
font-family: inherit;
|
|
134
136
|
font-size: 22px;
|
|
135
137
|
font-weight: 700;
|
|
@@ -175,7 +177,8 @@
|
|
|
175
177
|
|
|
176
178
|
// Some images use an image widget, but some are just inlined in the
|
|
177
179
|
// paragraph. Inlined images need legacy typography, too.
|
|
178
|
-
.unresponsive-svg-image,
|
|
180
|
+
.unresponsive-svg-image,
|
|
181
|
+
.svg-image {
|
|
179
182
|
.legacy-typography;
|
|
180
183
|
}
|
|
181
184
|
.perseus-block-math {
|
|
@@ -201,7 +204,12 @@
|
|
|
201
204
|
// If the article starts with a heading, remove its unnecessary top margin.
|
|
202
205
|
> .clearfix:first-child {
|
|
203
206
|
> .perseus-renderer:first-child > .paragraph:first-child {
|
|
204
|
-
h1,
|
|
207
|
+
h1,
|
|
208
|
+
h2,
|
|
209
|
+
h3,
|
|
210
|
+
h4,
|
|
211
|
+
h5,
|
|
212
|
+
h6 {
|
|
205
213
|
&:first-child {
|
|
206
214
|
margin-top: 0;
|
|
207
215
|
}
|
|
@@ -235,10 +243,10 @@
|
|
|
235
243
|
color: @gray17;
|
|
236
244
|
font-size: 18px;
|
|
237
245
|
padding: 16px;
|
|
238
|
-
white-space: pre
|
|
246
|
+
white-space: pre;
|
|
247
|
+
overflow: auto;
|
|
239
248
|
margin: 0 -16px 32px -16px;
|
|
240
249
|
}
|
|
241
|
-
|
|
242
250
|
}
|
|
243
251
|
|
|
244
252
|
// HACK(emily): This is a copy of a bunch of the mixins from the block of
|
|
@@ -343,7 +351,8 @@
|
|
|
343
351
|
// 06/08/2016, there are 188 articles and exercises that use H4 (and
|
|
344
352
|
// just 8 that use H5 or H6). As such, we provide style support for H4,
|
|
345
353
|
// since it's still quite common--but we just replicate the H3 style.
|
|
346
|
-
h3,
|
|
354
|
+
h3,
|
|
355
|
+
h4 {
|
|
347
356
|
.header(@fontSize, @lineHeight, @gray41, @paddingTopMultiplier);
|
|
348
357
|
}
|
|
349
358
|
}
|
|
@@ -421,7 +430,6 @@
|
|
|
421
430
|
|
|
422
431
|
.math(@blockMathTextSize; @blockMathLineHeight;
|
|
423
432
|
@inlineMathTextSize; @inlineMathLineHeight) {
|
|
424
|
-
|
|
425
433
|
.katex {
|
|
426
434
|
font-size: @inlineMathTextSize;
|
|
427
435
|
line-height: @inlineMathLineHeight;
|
|
@@ -446,7 +454,6 @@
|
|
|
446
454
|
|
|
447
455
|
.code(@codeTextSize; @codeTextLineHeight;
|
|
448
456
|
@codeBlockHorizontalMarginMultiplier) {
|
|
449
|
-
|
|
450
457
|
code {
|
|
451
458
|
font-family: Courier, monospace;
|
|
452
459
|
}
|
|
@@ -458,9 +465,8 @@
|
|
|
458
465
|
font-size: @codeTextSize;
|
|
459
466
|
line-height: @codeTextLineHeight;
|
|
460
467
|
padding: @baseUnit;
|
|
461
|
-
white-space: pre
|
|
462
|
-
|
|
463
|
-
// However, negative margins overlap with question answers (A/B/C)
|
|
468
|
+
white-space: pre;
|
|
469
|
+
overflow: auto;
|
|
464
470
|
}
|
|
465
471
|
}
|
|
466
472
|
|
|
@@ -529,7 +535,8 @@
|
|
|
529
535
|
// Support for nested lists
|
|
530
536
|
.perseus-renderer > .paragraph ol,
|
|
531
537
|
.perseus-renderer > .paragraph ul:not(.perseus-widget-radio) {
|
|
532
|
-
ol,
|
|
538
|
+
ol,
|
|
539
|
+
ul:not(.perseus-widget-radio) {
|
|
533
540
|
padding-top: 1.5 * @baseUnit;
|
|
534
541
|
}
|
|
535
542
|
}
|
|
@@ -537,7 +544,7 @@
|
|
|
537
544
|
// Disable the Safari tap highlight for block math, which is now tappable
|
|
538
545
|
// via the tap-to-zoom functionality.
|
|
539
546
|
.perseus-block-math {
|
|
540
|
-
-webkit-tap-highlight-color: rgba(0,0,0,0);
|
|
547
|
+
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
|
541
548
|
-webkit-touch-callout: none;
|
|
542
549
|
}
|
|
543
550
|
|
|
@@ -652,7 +659,8 @@
|
|
|
652
659
|
|
|
653
660
|
// Some images use an image widget, but some are just inlined in the
|
|
654
661
|
// paragraph. Inlined images need legacy typography, too.
|
|
655
|
-
.unresponsive-svg-image,
|
|
662
|
+
.unresponsive-svg-image,
|
|
663
|
+
.svg-image {
|
|
656
664
|
.legacy-typography;
|
|
657
665
|
}
|
|
658
666
|
|
|
@@ -673,8 +681,6 @@
|
|
|
673
681
|
}
|
|
674
682
|
}
|
|
675
683
|
|
|
676
|
-
|
|
677
|
-
|
|
678
684
|
/* Derived from the MIT-licensed zoom.js:
|
|
679
685
|
https://github.com/fat/zoom.js/blob/fd4f3e43153da7596da0bade198e99f98b47791e/
|
|
680
686
|
*/
|
|
@@ -704,7 +710,7 @@ img.zoom-img {
|
|
|
704
710
|
}
|
|
705
711
|
|
|
706
712
|
.zoom-transition {
|
|
707
|
-
transition:
|
|
713
|
+
transition: transform @zoomAnimationDurationMs ease;
|
|
708
714
|
}
|
|
709
715
|
|
|
710
716
|
.zoom-overlay {
|
|
@@ -739,7 +745,7 @@ img.zoom-img {
|
|
|
739
745
|
bottom: 0;
|
|
740
746
|
background: white;
|
|
741
747
|
opacity: 0;
|
|
742
|
-
transition:
|
|
748
|
+
transition: opacity @zoomAnimationDurationMs;
|
|
743
749
|
}
|
|
744
750
|
|
|
745
751
|
.zoom-overlay-open > .zoom-backdrop {
|