postext 1.58.2 → 1.59.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/__tests__/exercises/config.test.d.ts +2 -0
- package/dist/__tests__/exercises/config.test.d.ts.map +1 -0
- package/dist/__tests__/exercises/config.test.js +63 -0
- package/dist/__tests__/exercises/config.test.js.map +1 -0
- package/dist/__tests__/exercises/digital.test.d.ts +2 -0
- package/dist/__tests__/exercises/digital.test.d.ts.map +1 -0
- package/dist/__tests__/exercises/digital.test.js +163 -0
- package/dist/__tests__/exercises/digital.test.js.map +1 -0
- package/dist/__tests__/exercises/languages.test.d.ts +2 -0
- package/dist/__tests__/exercises/languages.test.d.ts.map +1 -0
- package/dist/__tests__/exercises/languages.test.js +109 -0
- package/dist/__tests__/exercises/languages.test.js.map +1 -0
- package/dist/__tests__/exercises/layout.test.d.ts +2 -0
- package/dist/__tests__/exercises/layout.test.d.ts.map +1 -0
- package/dist/__tests__/exercises/layout.test.js +77 -0
- package/dist/__tests__/exercises/layout.test.js.map +1 -0
- package/dist/__tests__/exercises/model.test.d.ts +2 -0
- package/dist/__tests__/exercises/model.test.d.ts.map +1 -0
- package/dist/__tests__/exercises/model.test.js +90 -0
- package/dist/__tests__/exercises/model.test.js.map +1 -0
- package/dist/__tests__/exercises/parse.test.d.ts +2 -0
- package/dist/__tests__/exercises/parse.test.d.ts.map +1 -0
- package/dist/__tests__/exercises/parse.test.js +37 -0
- package/dist/__tests__/exercises/parse.test.js.map +1 -0
- package/dist/__tests__/exercises/refs.test.d.ts +2 -0
- package/dist/__tests__/exercises/refs.test.d.ts.map +1 -0
- package/dist/__tests__/exercises/refs.test.js +46 -0
- package/dist/__tests__/exercises/refs.test.js.map +1 -0
- package/dist/__tests__/exercises/solutions.test.d.ts +2 -0
- package/dist/__tests__/exercises/solutions.test.d.ts.map +1 -0
- package/dist/__tests__/exercises/solutions.test.js +53 -0
- package/dist/__tests__/exercises/solutions.test.js.map +1 -0
- package/dist/__tests__/exports.test.js +14 -0
- package/dist/__tests__/exports.test.js.map +1 -1
- package/dist/__tests__/parse/containers.test.js +2 -2
- package/dist/__tests__/parse/containers.test.js.map +1 -1
- package/dist/__tests__/pipeline/pageShorterThanLine.test.d.ts +2 -0
- package/dist/__tests__/pipeline/pageShorterThanLine.test.d.ts.map +1 -0
- package/dist/__tests__/pipeline/pageShorterThanLine.test.js +29 -0
- package/dist/__tests__/pipeline/pageShorterThanLine.test.js.map +1 -0
- package/dist/__tests__/pipeline/spanHeadingMidPage.test.js +11 -0
- package/dist/__tests__/pipeline/spanHeadingMidPage.test.js.map +1 -1
- package/dist/canvas-backend/blockRender.d.ts.map +1 -1
- package/dist/canvas-backend/blockRender.js +18 -0
- package/dist/canvas-backend/blockRender.js.map +1 -1
- package/dist/canvas-backend/chip.d.ts +3 -0
- package/dist/canvas-backend/chip.d.ts.map +1 -1
- package/dist/canvas-backend/chip.js +31 -1
- package/dist/canvas-backend/chip.js.map +1 -1
- package/dist/configWarnings.d.ts +3 -1
- package/dist/configWarnings.d.ts.map +1 -1
- package/dist/configWarnings.js +5 -1
- package/dist/configWarnings.js.map +1 -1
- package/dist/defaults/chipStyles.d.ts.map +1 -1
- package/dist/defaults/chipStyles.js +7 -0
- package/dist/defaults/chipStyles.js.map +1 -1
- package/dist/defaults/exercises.d.ts +111 -0
- package/dist/defaults/exercises.d.ts.map +1 -0
- package/dist/defaults/exercises.js +255 -0
- package/dist/defaults/exercises.js.map +1 -0
- package/dist/defaults/index.d.ts +2 -0
- package/dist/defaults/index.d.ts.map +1 -1
- package/dist/defaults/index.js +16 -0
- package/dist/defaults/index.js.map +1 -1
- package/dist/defaults/shared.d.ts +4 -0
- package/dist/defaults/shared.d.ts.map +1 -1
- package/dist/defaults/shared.js +6 -0
- package/dist/defaults/shared.js.map +1 -1
- package/dist/design/elementKeys.d.ts +2 -0
- package/dist/design/elementKeys.d.ts.map +1 -1
- package/dist/design/elementKeys.js +1 -1
- package/dist/design/elementKeys.js.map +1 -1
- package/dist/exercises/build.d.ts +60 -0
- package/dist/exercises/build.d.ts.map +1 -0
- package/dist/exercises/build.js +177 -0
- package/dist/exercises/build.js.map +1 -0
- package/dist/exercises/configWarnings.d.ts +11 -0
- package/dist/exercises/configWarnings.d.ts.map +1 -0
- package/dist/exercises/configWarnings.js +175 -0
- package/dist/exercises/configWarnings.js.map +1 -0
- package/dist/exercises/designs.d.ts +38 -0
- package/dist/exercises/designs.d.ts.map +1 -0
- package/dist/exercises/designs.js +143 -0
- package/dist/exercises/designs.js.map +1 -0
- package/dist/exercises/digital.d.ts +69 -0
- package/dist/exercises/digital.d.ts.map +1 -0
- package/dist/exercises/digital.js +58 -0
- package/dist/exercises/digital.js.map +1 -0
- package/dist/exercises/expand.d.ts +74 -0
- package/dist/exercises/expand.d.ts.map +1 -0
- package/dist/exercises/expand.js +1089 -0
- package/dist/exercises/expand.js.map +1 -0
- package/dist/exercises/grids.d.ts +62 -0
- package/dist/exercises/grids.d.ts.map +1 -0
- package/dist/exercises/grids.js +535 -0
- package/dist/exercises/grids.js.map +1 -0
- package/dist/exercises/model.d.ts +24 -0
- package/dist/exercises/model.d.ts.map +1 -0
- package/dist/exercises/model.js +360 -0
- package/dist/exercises/model.js.map +1 -0
- package/dist/exercises/record.d.ts +94 -0
- package/dist/exercises/record.d.ts.map +1 -0
- package/dist/exercises/record.js +9 -0
- package/dist/exercises/record.js.map +1 -0
- package/dist/exercises/runtime.d.ts +65 -0
- package/dist/exercises/runtime.d.ts.map +1 -0
- package/dist/exercises/runtime.js +1261 -0
- package/dist/exercises/runtime.js.map +1 -0
- package/dist/exercises/shuffle.d.ts +13 -0
- package/dist/exercises/shuffle.d.ts.map +1 -0
- package/dist/exercises/shuffle.js +56 -0
- package/dist/exercises/shuffle.js.map +1 -0
- package/dist/exercises/styles.d.ts +51 -0
- package/dist/exercises/styles.d.ts.map +1 -0
- package/dist/exercises/styles.js +221 -0
- package/dist/exercises/styles.js.map +1 -0
- package/dist/exercises/text.d.ts +31 -0
- package/dist/exercises/text.d.ts.map +1 -0
- package/dist/exercises/text.js +82 -0
- package/dist/exercises/text.js.map +1 -0
- package/dist/exercises/types.d.ts +125 -0
- package/dist/exercises/types.d.ts.map +1 -0
- package/dist/exercises/types.js +9 -0
- package/dist/exercises/types.js.map +1 -0
- package/dist/exercises/warnings.d.ts +16 -0
- package/dist/exercises/warnings.d.ts.map +1 -0
- package/dist/exercises/warnings.js +55 -0
- package/dist/exercises/warnings.js.map +1 -0
- package/dist/html-backend.d.ts +6 -0
- package/dist/html-backend.d.ts.map +1 -1
- package/dist/html-backend.js +67 -6
- package/dist/html-backend.js.map +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/measure/cache.d.ts.map +1 -1
- package/dist/measure/cache.js +6 -1
- package/dist/measure/cache.js.map +1 -1
- package/dist/measure/rich.d.ts.map +1 -1
- package/dist/measure/rich.js +11 -1
- package/dist/measure/rich.js.map +1 -1
- package/dist/migrate/markdownRuns.js +1 -1
- package/dist/migrate/markdownRuns.js.map +1 -1
- package/dist/numbering.d.ts +3 -0
- package/dist/numbering.d.ts.map +1 -1
- package/dist/numbering.js +6 -0
- package/dist/numbering.js.map +1 -1
- package/dist/parse/blockParser.d.ts.map +1 -1
- package/dist/parse/blockParser.js +47 -4
- package/dist/parse/blockParser.js.map +1 -1
- package/dist/parse/exerciseGaps.d.ts +50 -0
- package/dist/parse/exerciseGaps.d.ts.map +1 -0
- package/dist/parse/exerciseGaps.js +151 -0
- package/dist/parse/exerciseGaps.js.map +1 -0
- package/dist/parse/index.d.ts +1 -1
- package/dist/parse/index.d.ts.map +1 -1
- package/dist/parse/index.js.map +1 -1
- package/dist/parse/sourceMapping.d.ts.map +1 -1
- package/dist/parse/sourceMapping.js +21 -0
- package/dist/parse/sourceMapping.js.map +1 -1
- package/dist/parse/types.d.ts +49 -1
- package/dist/parse/types.d.ts.map +1 -1
- package/dist/pipeline/build.d.ts.map +1 -1
- package/dist/pipeline/build.js +51 -9
- package/dist/pipeline/build.js.map +1 -1
- package/dist/pipeline/calloutLayout.d.ts.map +1 -1
- package/dist/pipeline/calloutLayout.js +1 -0
- package/dist/pipeline/calloutLayout.js.map +1 -1
- package/dist/pipeline/chips.d.ts.map +1 -1
- package/dist/pipeline/chips.js +2 -0
- package/dist/pipeline/chips.js.map +1 -1
- package/dist/pipeline/config.d.ts.map +1 -1
- package/dist/pipeline/config.js +6 -0
- package/dist/pipeline/config.js.map +1 -1
- package/dist/pipeline/contentWarnings.d.ts.map +1 -1
- package/dist/pipeline/contentWarnings.js +29 -1
- package/dist/pipeline/contentWarnings.js.map +1 -1
- package/dist/pipeline/continuation.d.ts.map +1 -1
- package/dist/pipeline/continuation.js +21 -6
- package/dist/pipeline/continuation.js.map +1 -1
- package/dist/pipeline/measureContentBlock.d.ts.map +1 -1
- package/dist/pipeline/measureContentBlock.js +3 -2
- package/dist/pipeline/measureContentBlock.js.map +1 -1
- package/dist/pipeline/outline.d.ts.map +1 -1
- package/dist/pipeline/outline.js +1 -0
- package/dist/pipeline/outline.js.map +1 -1
- package/dist/pipeline/textWrap.js +1 -1
- package/dist/pipeline/textWrap.js.map +1 -1
- package/dist/types.d.ts +303 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/vdt.d.ts +67 -0
- package/dist/vdt.d.ts.map +1 -1
- package/dist/vdt.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reading the exercises of a document (#1225): each `:::exercise` fence's
|
|
3
|
+
* blocks read into an {@link ExerciseModel} — its kind (written or told by
|
|
4
|
+
* its content), instruction, items, answers, solutions and hints. Pure: the
|
|
5
|
+
* blocks are not changed.
|
|
6
|
+
*/
|
|
7
|
+
import { EXERCISE_KINDS } from './types.js';
|
|
8
|
+
import { runOf, sliceRun, splitRun, trimRun } from './text.js';
|
|
9
|
+
/** Whether the blocks hold an exercise. */
|
|
10
|
+
export function hasExercises(blocks) {
|
|
11
|
+
return blocks.some((b) => b.type === 'containerStart' && b.containerName === 'exercise');
|
|
12
|
+
}
|
|
13
|
+
/** The index of the marker closing the container opened at `start`. */
|
|
14
|
+
export function containerEndOf(blocks, start) {
|
|
15
|
+
const id = blocks[start].containerId;
|
|
16
|
+
for (let k = start + 1; k < blocks.length; k++) {
|
|
17
|
+
const b = blocks[k];
|
|
18
|
+
if (b.type === 'containerEnd' && b.containerId === id)
|
|
19
|
+
return k;
|
|
20
|
+
}
|
|
21
|
+
return blocks.length - 1;
|
|
22
|
+
}
|
|
23
|
+
/** The pair separator of a `match` item: ` -> `, `→`, `⟶`. */
|
|
24
|
+
export const PAIR_RE = /\s*(?:->|→|⟶)\s*/;
|
|
25
|
+
/** What separates the items of a `sort` category. */
|
|
26
|
+
const CATEGORY_ITEM_RE = /\s*[,;、,;،؛]\s*/;
|
|
27
|
+
/** The colon after a category or a crossword word. */
|
|
28
|
+
const COLON_RE = /\s*[::]\s*/;
|
|
29
|
+
/** The kinds a fence may name, with a few spellings authors reach for. */
|
|
30
|
+
const KIND_ALIASES = {
|
|
31
|
+
multiplechoice: 'choice', mcq: 'choice', quiz: 'choice', test: 'choice',
|
|
32
|
+
tf: 'truefalse', 'true-false': 'truefalse', truefalse: 'truefalse',
|
|
33
|
+
cloze: 'gaps', gap: 'gaps', blanks: 'gaps', fill: 'gaps',
|
|
34
|
+
matching: 'match', pairs: 'match', ordering: 'order', sequence: 'order',
|
|
35
|
+
sorting: 'sort', classify: 'sort', categories: 'sort',
|
|
36
|
+
free: 'open', essay: 'open', answer: 'open', 'word-search': 'wordsearch', 'crossword-puzzle': 'crossword',
|
|
37
|
+
operations: 'arithmetic', column: 'arithmetic', vertical: 'arithmetic',
|
|
38
|
+
};
|
|
39
|
+
export function exerciseKindOf(type) {
|
|
40
|
+
if (type === undefined)
|
|
41
|
+
return undefined;
|
|
42
|
+
const t = type.trim().toLowerCase();
|
|
43
|
+
if (EXERCISE_KINDS.includes(t))
|
|
44
|
+
return t;
|
|
45
|
+
return KIND_ALIASES[t];
|
|
46
|
+
}
|
|
47
|
+
const isListItem = (b) => b.type === 'listItem';
|
|
48
|
+
const isTask = (b) => b.type === 'listItem' && b.listKind === 'task';
|
|
49
|
+
/** The kind the content tells when the fence names none. */
|
|
50
|
+
function inferredKind(blocks, body, gaps) {
|
|
51
|
+
if (body.some((k) => isTask(blocks[k])))
|
|
52
|
+
return 'choice';
|
|
53
|
+
if (body.some((k) => isListItem(blocks[k]) && PAIR_RE.test(blocks[k].text)))
|
|
54
|
+
return 'match';
|
|
55
|
+
if (gaps > 0)
|
|
56
|
+
return 'gaps';
|
|
57
|
+
return 'open';
|
|
58
|
+
}
|
|
59
|
+
/** The digits of `n` in the script `like` is written in (Arabic-Indic and
|
|
60
|
+
* Persian digits kept). */
|
|
61
|
+
function digitsLike(n, like) {
|
|
62
|
+
if (/[٠-٩]/.test(like))
|
|
63
|
+
return n.replace(/[0-9]/g, (d) => String.fromCharCode(0x0660 + Number(d)));
|
|
64
|
+
if (/[۰-۹]/.test(like))
|
|
65
|
+
return n.replace(/[0-9]/g, (d) => String.fromCharCode(0x06f0 + Number(d)));
|
|
66
|
+
return n;
|
|
67
|
+
}
|
|
68
|
+
const ascii = (s) => s
|
|
69
|
+
.replace(/[٠-٩]/g, (d) => String(d.charCodeAt(0) - 0x0660))
|
|
70
|
+
.replace(/[۰-۹]/g, (d) => String(d.charCodeAt(0) - 0x06f0));
|
|
71
|
+
const OPERATION_RE = /^\s*(\d+)\s*([+\-−×xX*·⋅÷:/])\s*(\d+)\s*(?:=\s*)?$/u;
|
|
72
|
+
/** The sign an operation prints, from the one written: a German `216 · 4`
|
|
73
|
+
* keeps its dot, a `864 : 4` its colon; ASCII stand-ins become the signs. */
|
|
74
|
+
const PRINTED_SIGN = { '-': '−', x: '×', X: '×', '*': '×', '⋅': '·', '/': '÷' };
|
|
75
|
+
/** An operation item (`345 + 278`), its result worked out: whole numbers. */
|
|
76
|
+
export function readOperation(text, block) {
|
|
77
|
+
const m = OPERATION_RE.exec(ascii(text));
|
|
78
|
+
if (!m)
|
|
79
|
+
return undefined;
|
|
80
|
+
const [a, b] = [m[1], m[3]];
|
|
81
|
+
const sign = m[2];
|
|
82
|
+
const op = sign === '+' ? '+' : sign === '-' || sign === '−' ? '-' : sign === '÷' || sign === ':' || sign === '/' ? '÷' : '×';
|
|
83
|
+
const x = BigInt(a);
|
|
84
|
+
const y = BigInt(b);
|
|
85
|
+
let result;
|
|
86
|
+
let remainder;
|
|
87
|
+
if (op === '+')
|
|
88
|
+
result = x + y;
|
|
89
|
+
else if (op === '-')
|
|
90
|
+
result = x - y;
|
|
91
|
+
else if (op === '×')
|
|
92
|
+
result = x * y;
|
|
93
|
+
else {
|
|
94
|
+
if (y === 0n)
|
|
95
|
+
return undefined;
|
|
96
|
+
result = x / y;
|
|
97
|
+
remainder = x % y;
|
|
98
|
+
}
|
|
99
|
+
const raw = text.trim();
|
|
100
|
+
return {
|
|
101
|
+
block,
|
|
102
|
+
a: digitsLike(a, raw),
|
|
103
|
+
b: digitsLike(b, raw),
|
|
104
|
+
op,
|
|
105
|
+
sign: PRINTED_SIGN[sign] ?? sign,
|
|
106
|
+
result: digitsLike(result.toString(), raw),
|
|
107
|
+
...(remainder !== undefined && remainder !== 0n ? { remainder: digitsLike(remainder.toString(), raw) } : {}),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
/** Read every exercise of `blocks`, in order. A `:::solution` or `:::hint`
|
|
111
|
+
* outside an exercise, and an exercise inside another, are reported. */
|
|
112
|
+
export function readExercises(blocks) {
|
|
113
|
+
const exercises = [];
|
|
114
|
+
const issues = [];
|
|
115
|
+
for (let i = 0; i < blocks.length; i++) {
|
|
116
|
+
const b = blocks[i];
|
|
117
|
+
if (b.type !== 'containerStart')
|
|
118
|
+
continue;
|
|
119
|
+
if (b.containerName === 'solution' || b.containerName === 'hint') {
|
|
120
|
+
issues.push({ kind: 'solutionOutside', sourceStart: b.sourceStart, sourceEnd: b.sourceEnd });
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
if (b.containerName !== 'exercise')
|
|
124
|
+
continue;
|
|
125
|
+
const end = containerEndOf(blocks, i);
|
|
126
|
+
exercises.push(readExercise(blocks, i, end, exercises.length, issues));
|
|
127
|
+
i = end;
|
|
128
|
+
}
|
|
129
|
+
return { exercises, issues };
|
|
130
|
+
}
|
|
131
|
+
function readExercise(blocks, start, end, ordinal, issues) {
|
|
132
|
+
const open = blocks[start];
|
|
133
|
+
const attrs = open.containerAttrs ?? {};
|
|
134
|
+
const id = open.containerId;
|
|
135
|
+
const solutions = [];
|
|
136
|
+
const hints = [];
|
|
137
|
+
const banks = [];
|
|
138
|
+
const instruction = [];
|
|
139
|
+
const body = [];
|
|
140
|
+
let leading = true;
|
|
141
|
+
for (let k = start + 1; k < end; k++) {
|
|
142
|
+
const b = blocks[k];
|
|
143
|
+
if (b.type === 'containerStart' && (b.containerName === 'solution' || b.containerName === 'hint')) {
|
|
144
|
+
const close = containerEndOf(blocks, k);
|
|
145
|
+
(b.containerName === 'solution' ? solutions : hints).push({ start: k, end: close });
|
|
146
|
+
k = close;
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
if (b.type === 'containerStart' && b.containerName === 'exercise') {
|
|
150
|
+
issues.push({ kind: 'exerciseNested', exercise: id, sourceStart: b.sourceStart, sourceEnd: b.sourceEnd });
|
|
151
|
+
const close = containerEndOf(blocks, k);
|
|
152
|
+
for (let j = k + 1; j < close; j++)
|
|
153
|
+
body.push(j);
|
|
154
|
+
k = close;
|
|
155
|
+
leading = false;
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
if (b.type === 'directive' && b.directiveName === 'bank') {
|
|
159
|
+
banks.push(k);
|
|
160
|
+
leading = false;
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
const gapless = !b.spans.some((s) => s.chip?.gap);
|
|
164
|
+
if (leading && b.type === 'paragraph' && gapless) {
|
|
165
|
+
instruction.push(k);
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
leading = false;
|
|
169
|
+
body.push(k);
|
|
170
|
+
}
|
|
171
|
+
const gaps = [];
|
|
172
|
+
for (const k of body) {
|
|
173
|
+
blocks[k].spans.forEach((s, span) => {
|
|
174
|
+
if (s.chip?.gap)
|
|
175
|
+
gaps.push({ block: k, span, gap: s.chip.gap, n: gaps.length + 1 });
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
const written = exerciseKindOf(attrs.type);
|
|
179
|
+
if (attrs.type !== undefined && !written) {
|
|
180
|
+
issues.push({ kind: 'exerciseUnknownType', exercise: id, detail: attrs.type, sourceStart: open.sourceStart, sourceEnd: open.sourceEnd });
|
|
181
|
+
}
|
|
182
|
+
const kind = written ?? inferredKind(blocks, body, gaps.length);
|
|
183
|
+
const model = {
|
|
184
|
+
id, ordinal, kind, attrs, start, end, instruction, body, items: new Set(), solutions, hints, banks, gaps,
|
|
185
|
+
questions: [], pairs: [], sequence: [], sentences: [], categories: [], entries: [], operations: [],
|
|
186
|
+
sourceStart: open.sourceStart, sourceEnd: blocks[end].sourceEnd,
|
|
187
|
+
};
|
|
188
|
+
readItems(blocks, model, issues);
|
|
189
|
+
if (gradedWithoutAnswer(model)) {
|
|
190
|
+
issues.push({ kind: 'exerciseNoAnswer', exercise: id, sourceStart: open.sourceStart, sourceEnd: open.sourceEnd });
|
|
191
|
+
}
|
|
192
|
+
return model;
|
|
193
|
+
}
|
|
194
|
+
/** A graded exercise with nothing to grade: no right option, no gap, no
|
|
195
|
+
* pair… */
|
|
196
|
+
function gradedWithoutAnswer(m) {
|
|
197
|
+
switch (m.kind) {
|
|
198
|
+
case 'choice': return m.questions.length === 0 ? m.gaps.length === 0 : m.questions.some((q) => !q.options.some((o) => o.correct));
|
|
199
|
+
case 'truefalse': return m.questions.length === 0;
|
|
200
|
+
case 'gaps':
|
|
201
|
+
case 'mark': return m.gaps.length === 0;
|
|
202
|
+
case 'match': return !m.pairs.some((p) => p.left.text !== '');
|
|
203
|
+
case 'order': return m.sequence.length < 2;
|
|
204
|
+
case 'scramble': return m.sentences.length === 0;
|
|
205
|
+
case 'sort': return m.categories.length === 0;
|
|
206
|
+
case 'wordsearch':
|
|
207
|
+
case 'crossword': return m.entries.length === 0;
|
|
208
|
+
case 'arithmetic': return m.operations.length === 0;
|
|
209
|
+
case 'open': return false;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
/** The text of a list item after its marker (the parser keeps only the
|
|
213
|
+
* item's own text). */
|
|
214
|
+
const itemRun = (b) => trimRun(runOf(b));
|
|
215
|
+
function readItems(blocks, m, issues) {
|
|
216
|
+
const select = m.attrs.select?.trim().toLowerCase();
|
|
217
|
+
const unread = (k) => {
|
|
218
|
+
const b = blocks[k];
|
|
219
|
+
issues.push({ kind: 'exerciseUnreadItem', exercise: m.id, detail: b.text, sourceStart: b.sourceStart, sourceEnd: b.sourceEnd });
|
|
220
|
+
};
|
|
221
|
+
switch (m.kind) {
|
|
222
|
+
case 'choice': {
|
|
223
|
+
let current;
|
|
224
|
+
let currentDepth = -1;
|
|
225
|
+
for (let j = 0; j < m.body.length; j++) {
|
|
226
|
+
const k = m.body[j];
|
|
227
|
+
const b = blocks[k];
|
|
228
|
+
if (isTask(b)) {
|
|
229
|
+
const depth = b.depth ?? 0;
|
|
230
|
+
if (!current || depth !== currentDepth) {
|
|
231
|
+
// A list item right before at the depth above is the stem.
|
|
232
|
+
const prev = j > 0 ? blocks[m.body[j - 1]] : undefined;
|
|
233
|
+
const stem = prev && isListItem(prev) && !isTask(prev) && (prev.depth ?? 0) === depth - 1 ? m.body[j - 1] : undefined;
|
|
234
|
+
current = { ...(stem !== undefined ? { stem } : {}), options: [], multiple: false };
|
|
235
|
+
currentDepth = depth;
|
|
236
|
+
m.questions.push(current);
|
|
237
|
+
}
|
|
238
|
+
current.options.push({ block: k, correct: b.checked === true });
|
|
239
|
+
m.items.add(k);
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
if (isListItem(b) && (b.depth ?? 0) < currentDepth) {
|
|
243
|
+
current = undefined;
|
|
244
|
+
currentDepth = -1;
|
|
245
|
+
}
|
|
246
|
+
else if (!isListItem(b)) {
|
|
247
|
+
current = undefined;
|
|
248
|
+
currentDepth = -1;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
for (const q of m.questions) {
|
|
252
|
+
if (q.stem !== undefined)
|
|
253
|
+
m.items.add(q.stem);
|
|
254
|
+
const right = q.options.filter((o) => o.correct).length;
|
|
255
|
+
q.multiple = select === 'many' || select === 'multiple' || (select !== 'one' && select !== 'single' && right > 1);
|
|
256
|
+
}
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
case 'truefalse':
|
|
260
|
+
for (const k of m.body) {
|
|
261
|
+
const b = blocks[k];
|
|
262
|
+
if (!isTask(b))
|
|
263
|
+
continue;
|
|
264
|
+
m.questions.push({ options: [{ block: k, correct: b.checked === true }], multiple: false });
|
|
265
|
+
m.items.add(k);
|
|
266
|
+
}
|
|
267
|
+
return;
|
|
268
|
+
case 'match':
|
|
269
|
+
for (const k of m.body) {
|
|
270
|
+
const b = blocks[k];
|
|
271
|
+
if (!isListItem(b))
|
|
272
|
+
continue;
|
|
273
|
+
const run = itemRun(b);
|
|
274
|
+
const at = PAIR_RE.exec(run.text);
|
|
275
|
+
if (!at) {
|
|
276
|
+
unread(k);
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
279
|
+
m.pairs.push({ block: k, left: trimRun(sliceRun(run, 0, at.index)), right: trimRun(sliceRun(run, at.index + at[0].length)) });
|
|
280
|
+
m.items.add(k);
|
|
281
|
+
}
|
|
282
|
+
return;
|
|
283
|
+
case 'order': {
|
|
284
|
+
// The items of the list's top level (depth 1).
|
|
285
|
+
const top = Math.min(...m.body.filter((k) => isListItem(blocks[k])).map((k) => blocks[k].depth ?? 1));
|
|
286
|
+
const lists = m.body.filter((k) => isListItem(blocks[k]) && (blocks[k].depth ?? 1) === top);
|
|
287
|
+
m.sequence.push(...lists);
|
|
288
|
+
lists.forEach((k) => m.items.add(k));
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
case 'scramble':
|
|
292
|
+
for (const k of m.body) {
|
|
293
|
+
const b = blocks[k];
|
|
294
|
+
if (!isListItem(b))
|
|
295
|
+
continue;
|
|
296
|
+
const run = itemRun(b);
|
|
297
|
+
const pieces = /\s\/\s|\//.test(run.text) ? splitRun(run, /\s*\/\s*/) : splitRun(run, /\s+/);
|
|
298
|
+
m.sentences.push({ block: k, pieces: pieces.filter((p) => p.text !== '') });
|
|
299
|
+
m.items.add(k);
|
|
300
|
+
}
|
|
301
|
+
return;
|
|
302
|
+
case 'sort':
|
|
303
|
+
for (const k of m.body) {
|
|
304
|
+
const b = blocks[k];
|
|
305
|
+
if (!isListItem(b))
|
|
306
|
+
continue;
|
|
307
|
+
const run = itemRun(b);
|
|
308
|
+
const at = COLON_RE.exec(run.text);
|
|
309
|
+
if (!at) {
|
|
310
|
+
unread(k);
|
|
311
|
+
continue;
|
|
312
|
+
}
|
|
313
|
+
const cat = {
|
|
314
|
+
block: k,
|
|
315
|
+
name: trimRun(sliceRun(run, 0, at.index)),
|
|
316
|
+
items: splitRun(sliceRun(run, at.index + at[0].length), CATEGORY_ITEM_RE).filter((r) => r.text !== ''),
|
|
317
|
+
};
|
|
318
|
+
m.categories.push(cat);
|
|
319
|
+
m.items.add(k);
|
|
320
|
+
}
|
|
321
|
+
return;
|
|
322
|
+
case 'wordsearch':
|
|
323
|
+
case 'crossword':
|
|
324
|
+
for (const k of m.body) {
|
|
325
|
+
const b = blocks[k];
|
|
326
|
+
if (!isListItem(b))
|
|
327
|
+
continue;
|
|
328
|
+
const run = itemRun(b);
|
|
329
|
+
const at = COLON_RE.exec(run.text);
|
|
330
|
+
const word = (at ? run.text.slice(0, at.index) : run.text).replace(/[\s\-‐]+/gu, '');
|
|
331
|
+
if (!word) {
|
|
332
|
+
unread(k);
|
|
333
|
+
continue;
|
|
334
|
+
}
|
|
335
|
+
const entry = { block: k, word, ...(at ? { clue: trimRun(sliceRun(run, at.index + at[0].length)) } : {}) };
|
|
336
|
+
m.entries.push(entry);
|
|
337
|
+
m.items.add(k);
|
|
338
|
+
}
|
|
339
|
+
return;
|
|
340
|
+
case 'arithmetic':
|
|
341
|
+
for (const k of m.body) {
|
|
342
|
+
const b = blocks[k];
|
|
343
|
+
if (!isListItem(b))
|
|
344
|
+
continue;
|
|
345
|
+
const op = readOperation(b.text, k);
|
|
346
|
+
if (!op) {
|
|
347
|
+
unread(k);
|
|
348
|
+
continue;
|
|
349
|
+
}
|
|
350
|
+
m.operations.push(op);
|
|
351
|
+
m.items.add(k);
|
|
352
|
+
}
|
|
353
|
+
return;
|
|
354
|
+
case 'gaps':
|
|
355
|
+
case 'mark':
|
|
356
|
+
case 'open':
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
//# sourceMappingURL=model.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model.js","sourceRoot":"","sources":["../../src/exercises/model.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What an exercise leaves for the digital outputs (#1230): its slots — the
|
|
3
|
+
* places it is answered on the page — and what each accepts, its key, its
|
|
4
|
+
* worked solution and hints as text. The layout carries one record per
|
|
5
|
+
* exercise laid out (`VDTDocument.exercises`); the HTML and EPUB outputs
|
|
6
|
+
* write them into the page for the exercise script.
|
|
7
|
+
*/
|
|
8
|
+
import type { ExerciseKind } from './types.js';
|
|
9
|
+
/** How a slot is answered. */
|
|
10
|
+
export type ExerciseSlotKind =
|
|
11
|
+
/** Typed into a blank; `accept` lists the right answers. */
|
|
12
|
+
'gap'
|
|
13
|
+
/** One option (or several, `multiple`) of `options` ticked; `correct`
|
|
14
|
+
* are the right ones, 1-based in printed order. Its options are the
|
|
15
|
+
* slots `<key>o<n>`. */
|
|
16
|
+
| 'choice'
|
|
17
|
+
/** A statement: `correct` is `[1]` when true, `[2]` when false; its
|
|
18
|
+
* boxes the slots `<key>t` and `<key>f` (or itself, typed, in the
|
|
19
|
+
* bracket look). */
|
|
20
|
+
| 'truefalse'
|
|
21
|
+
/** A word to mark; `correct` `[1]` (a word of the text not to mark has
|
|
22
|
+
* no slot). */
|
|
23
|
+
| 'mark'
|
|
24
|
+
/** A left item of a match: `correct` is the 1-based printed position of
|
|
25
|
+
* its partner in the right column; in the letters look, `accept` its
|
|
26
|
+
* printed label. */
|
|
27
|
+
| 'pair'
|
|
28
|
+
/** An item to number (order): `accept` is its rank. */
|
|
29
|
+
| 'rank'
|
|
30
|
+
/** A word of a sort exercise's bank: `accept` is its category. */
|
|
31
|
+
| 'category'
|
|
32
|
+
/** Text written on an area (open, scramble, sort): `accept` the model
|
|
33
|
+
* answers, which an open question only shows. */
|
|
34
|
+
| 'text'
|
|
35
|
+
/** A cell of a grid (crossword, operation): `accept` its character. */
|
|
36
|
+
| 'cell'
|
|
37
|
+
/** A word to find in a word search: `accept` its cells, `r,c` each. */
|
|
38
|
+
| 'word';
|
|
39
|
+
export interface ExerciseSlot {
|
|
40
|
+
key: string;
|
|
41
|
+
kind: ExerciseSlotKind;
|
|
42
|
+
accept?: string[];
|
|
43
|
+
correct?: number[];
|
|
44
|
+
options?: number;
|
|
45
|
+
multiple?: boolean;
|
|
46
|
+
/** The container id of the drawn box the slot stands on (an area, a
|
|
47
|
+
* grid): the digital outputs find its frame by it. */
|
|
48
|
+
box?: number;
|
|
49
|
+
/** A cell's place in its grid: row and column from 0. */
|
|
50
|
+
cell?: [number, number];
|
|
51
|
+
/** A writing area's line spacing, points. */
|
|
52
|
+
linePt?: number;
|
|
53
|
+
}
|
|
54
|
+
/** A grid's geometry, for the digital outputs to place its cells. */
|
|
55
|
+
export interface ExerciseGridInfo {
|
|
56
|
+
box: number;
|
|
57
|
+
kind: 'match' | 'wordsearch' | 'crossword' | 'arithmetic';
|
|
58
|
+
rows: number;
|
|
59
|
+
cols: number;
|
|
60
|
+
/** A cell's side over the box's width (the grid starts at the box's top
|
|
61
|
+
* left, in the flow's direction). */
|
|
62
|
+
cellPt: number;
|
|
63
|
+
/** The grid's left and top inside its box, points. */
|
|
64
|
+
xPt: number;
|
|
65
|
+
yPt: number;
|
|
66
|
+
/** Match: the middle of each row, points from the box's top, and the
|
|
67
|
+
* left and right dots' x. */
|
|
68
|
+
rowsPt?: number[];
|
|
69
|
+
dotsPt?: [number, number];
|
|
70
|
+
}
|
|
71
|
+
export interface ExerciseRecord {
|
|
72
|
+
/** The fence's container id (the box's `containerId` in the layout). */
|
|
73
|
+
id: number;
|
|
74
|
+
ordinal: number;
|
|
75
|
+
number: string;
|
|
76
|
+
kind: ExerciseKind;
|
|
77
|
+
style: string;
|
|
78
|
+
slots: ExerciseSlot[];
|
|
79
|
+
/** The key as one line of text. */
|
|
80
|
+
key: string;
|
|
81
|
+
/** The worked solution's paragraphs, as text. */
|
|
82
|
+
solution?: string[];
|
|
83
|
+
hints?: string[];
|
|
84
|
+
/** The fence's `{#id}`. */
|
|
85
|
+
anchor?: string;
|
|
86
|
+
/** What a reference to it prints ("Exercise 3"). */
|
|
87
|
+
anchorText?: string;
|
|
88
|
+
/** The fence's `title`. */
|
|
89
|
+
title?: string;
|
|
90
|
+
/** A mark exercise's `mark` (`circle`, `underline`…). */
|
|
91
|
+
mark?: string;
|
|
92
|
+
grids?: ExerciseGridInfo[];
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=record.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"record.d.ts","sourceRoot":"","sources":["../../src/exercises/record.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,8BAA8B;AAC9B,MAAM,MAAM,gBAAgB;AAC1B,4DAA4D;AAC1D,KAAK;AACP;;yBAEyB;GACvB,QAAQ;AACV;;qBAEqB;GACnB,WAAW;AACb;gBACgB;GACd,MAAM;AACR;;qBAEqB;GACnB,MAAM;AACR,uDAAuD;GACrD,MAAM;AACR,kEAAkE;GAChE,UAAU;AACZ;kDACkD;GAChD,MAAM;AACR,uEAAuE;GACrE,MAAM;AACR,uEAAuE;GACrE,MAAM,CAAC;AAEX,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,gBAAgB,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;2DACuD;IACvD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,yDAAyD;IACzD,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxB,6CAA6C;IAC7C,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,qEAAqE;AACrE,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,OAAO,GAAG,YAAY,GAAG,WAAW,GAAG,YAAY,CAAC;IAC1D,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb;0CACsC;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,sDAAsD;IACtD,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ;kCAC8B;IAC9B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc;IAC7B,wEAAwE;IACxE,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,mCAAmC;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,iDAAiD;IACjD,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,2BAA2B;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oDAAoD;IACpD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2BAA2B;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yDAAyD;IACzD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,gBAAgB,EAAE,CAAC;CAC5B"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What an exercise leaves for the digital outputs (#1230): its slots — the
|
|
3
|
+
* places it is answered on the page — and what each accepts, its key, its
|
|
4
|
+
* worked solution and hints as text. The layout carries one record per
|
|
5
|
+
* exercise laid out (`VDTDocument.exercises`); the HTML and EPUB outputs
|
|
6
|
+
* write them into the page for the exercise script.
|
|
7
|
+
*/
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=record.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"record.js","sourceRoot":"","sources":["../../src/exercises/record.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The exercise script (#1230, #1231): makes the exercises of an HTML or EPUB
|
|
3
|
+
* output answerable, checks the answers and keeps them.
|
|
4
|
+
*
|
|
5
|
+
* The HTML output marks where an exercise is answered — its slots
|
|
6
|
+
* (`.pt-ex-slot[data-pt-ex][data-pt-slot]`, the chips of blanks, options,
|
|
7
|
+
* words) and its boxes (`.pt-ex-box[data-pt-box]`, the outer frame, the
|
|
8
|
+
* writing areas and grids) — and writes the records once, in
|
|
9
|
+
* `<script type="application/json" class="pt-exercises">`. The script lays
|
|
10
|
+
* its controls over those places: an input in a blank or a grid cell, a
|
|
11
|
+
* toggle on an option, lines between the dots of a match, a capsule in a
|
|
12
|
+
* word search, a text area on a writing area, a chooser on a word to sort;
|
|
13
|
+
* and a bar per exercise with Check, Show solution and Try again, a score
|
|
14
|
+
* read out to assistive technology (`aria-live`) and right or wrong marks
|
|
15
|
+
* that do not rest on colour alone (✓ and ✗).
|
|
16
|
+
*
|
|
17
|
+
* The whole runtime is one function with nothing from outside it, so the
|
|
18
|
+
* same code runs from the package (`attachExercises`) and as a standalone
|
|
19
|
+
* script (`EXERCISE_SCRIPT`, its source text). It keeps to syntax every
|
|
20
|
+
* reading system and transpiler leaves as it is: no spread, no `for…of`,
|
|
21
|
+
* no `async`.
|
|
22
|
+
*/
|
|
23
|
+
import type { ExerciseData } from './digital.js';
|
|
24
|
+
import type { ExerciseRecord, ExerciseSlot } from './record.js';
|
|
25
|
+
export interface AttachExercisesOptions {
|
|
26
|
+
/** What the answers are kept under (with each exercise's anchor or id):
|
|
27
|
+
* a book and chapter, say. Default: the page's path. */
|
|
28
|
+
storageKey?: string;
|
|
29
|
+
/** Keep the answers in `localStorage`. Default: the document's
|
|
30
|
+
* `exercises.digital.persist`. */
|
|
31
|
+
persist?: boolean;
|
|
32
|
+
/** `'button'`: checked on demand; `'instant'`: as answered. Default: the
|
|
33
|
+
* document's `exercises.digital.check`. */
|
|
34
|
+
check?: 'button' | 'instant';
|
|
35
|
+
/** The exercise data, for a host that patches the pages and so holds
|
|
36
|
+
* it itself (`HtmlRenderIndex.exercises`); otherwise read from the
|
|
37
|
+
* `script.pt-exercises` elements under the root. */
|
|
38
|
+
data?: ExerciseData;
|
|
39
|
+
}
|
|
40
|
+
/** What a reader answered in a slot: text typed, the options ticked
|
|
41
|
+
* (1-based), a true/false (1 or 2), a mark, a right item of a match, the
|
|
42
|
+
* ends of the words found in a word search (`r,c-r,c`). */
|
|
43
|
+
export type ExerciseValue = string | number | number[] | boolean | string[] | null | undefined;
|
|
44
|
+
/** An answer as the exercise script compares it (see `attachExercises`). */
|
|
45
|
+
export declare const normalizeAnswer: (text: string) => string;
|
|
46
|
+
/** Whether a slot counts in an exercise's score. */
|
|
47
|
+
export declare const isGradedSlot: (slot: ExerciseSlot, record: Pick<ExerciseRecord, 'kind'>) => boolean;
|
|
48
|
+
/** Whether `value` answers `slot` rightly (`true`), wrongly (`false`), or
|
|
49
|
+
* is no answer or not graded (`null`). `trueFalse` are the style's true
|
|
50
|
+
* and false labels, for a typed true/false. */
|
|
51
|
+
export declare const checkExerciseSlot: (slot: ExerciseSlot, value: ExerciseValue, record: Pick<ExerciseRecord, 'kind'>, trueFalse?: [string, string]) => boolean | null;
|
|
52
|
+
/** What a slot shows when the solution is shown. */
|
|
53
|
+
export declare const exerciseSolutionValue: (slot: ExerciseSlot, record: Pick<ExerciseRecord, 'kind'>, trueFalse?: [string, string]) => ExerciseValue;
|
|
54
|
+
/** Makes the exercises of the HTML output under `root` answerable (see the
|
|
55
|
+
* module comment). Call it once the markup is in place, again after the
|
|
56
|
+
* markup changes (calling the previous call's return value first).
|
|
57
|
+
* Returns a function that takes every control off and puts the page's
|
|
58
|
+
* markup back as it was. */
|
|
59
|
+
export declare function attachExercises(root: Element | ShadowRoot | Document, options?: AttachExercisesOptions): () => void;
|
|
60
|
+
/** The exercise script as a standalone script, for an output with no host
|
|
61
|
+
* page to call `attachExercises`: the HTML file of the command line, an
|
|
62
|
+
* EPUB content document. It attaches to the document once it is parsed;
|
|
63
|
+
* the answers are kept under the page's path. */
|
|
64
|
+
export declare const EXERCISE_SCRIPT: string;
|
|
65
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/exercises/runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhE,MAAM,WAAW,sBAAsB;IACrC;6DACyD;IACzD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;uCACmC;IACnC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;gDAC4C;IAC5C,KAAK,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC7B;;yDAEqD;IACrD,IAAI,CAAC,EAAE,YAAY,CAAC;CACrB;AAED;;4DAE4D;AAC5D,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,OAAO,GAAG,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,CAAC;AA4+B/F,4EAA4E;AAC5E,eAAO,MAAM,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAgC,CAAC;AAEjF,oDAAoD;AACpD,eAAO,MAAM,YAAY,EAAE,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,MAAM,CAAC,KAAK,OAA0B,CAAC;AAEpH;;gDAEgD;AAChD,eAAO,MAAM,iBAAiB,EAAE,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,MAAM,CAAC,EAAE,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,OAAO,GAAG,IAAwB,CAAC;AAErL,oDAAoD;AACpD,eAAO,MAAM,qBAAqB,EAAE,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,MAAM,CAAC,EAAE,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,aAAqC,CAAC;AAEtK;;;;6BAI6B;AAC7B,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,UAAU,GAAG,QAAQ,EAAE,OAAO,CAAC,EAAE,sBAAsB,GAAG,MAAM,IAAI,CAEnH;AAED;;;kDAGkD;AAClD,eAAO,MAAM,eAAe,QAM3B,CAAC"}
|