@erudit-js/prose 4.0.0-dev.4 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app/default/Inliners.vue +11 -11
- package/dist/app/default/Mix.vue +11 -11
- package/dist/app/default/Text.vue +25 -25
- package/dist/app/shared/Prose.vue +40 -40
- package/dist/app/shared/Render.vue +51 -51
- package/dist/app/shared/block/AsideMenu.vue +44 -44
- package/dist/app/shared/block/AsideMenuButton.vue +51 -53
- package/dist/app/shared/block/AsideMenuCopyLink.vue +40 -40
- package/dist/app/shared/block/AsideMenuSeparator.vue +3 -3
- package/dist/app/shared/block/Block.vue +270 -275
- package/dist/app/shared/inliner/Inliner.vue +11 -11
- package/dist/app/shared/photoswipe/style.css +22 -26
- package/dist/elements/accent/Accent.vue +88 -92
- package/dist/elements/accent/AccentColumnSection.vue +61 -61
- package/dist/elements/accent/AccentRowSections.vue +64 -65
- package/dist/elements/callout/Callout.vue +81 -85
- package/dist/elements/callout/_global.d.ts +15 -15
- package/dist/elements/caption/Caption.vue +44 -47
- package/dist/elements/caption/_global.d.ts +26 -26
- package/dist/elements/details/Details.vue +49 -50
- package/dist/elements/details/_global.d.ts +27 -27
- package/dist/elements/diagram/Diagram.vue +360 -374
- package/dist/elements/diagram/_global.d.ts +19 -19
- package/dist/elements/diagram/core.d.ts +0 -4
- package/dist/elements/diagram/core.js +1 -7
- package/dist/elements/emphasis/Emphasis.vue +25 -25
- package/dist/elements/emphasis/_global.d.ts +18 -18
- package/dist/elements/flex/Flex.vue +36 -38
- package/dist/elements/flex/_global.d.ts +23 -23
- package/dist/elements/gallery/Gallery.vue +56 -56
- package/dist/elements/gallery/_global.d.ts +18 -18
- package/dist/elements/heading/Heading.vue +44 -44
- package/dist/elements/heading/_global.d.ts +42 -45
- package/dist/elements/heading/core.js +7 -14
- package/dist/elements/horizontalLine/HorizontalLine.vue +6 -6
- package/dist/elements/horizontalLine/_global.d.ts +17 -17
- package/dist/elements/image/Image.vue +15 -15
- package/dist/elements/image/ImageElement.vue +80 -80
- package/dist/elements/image/_global.d.ts +18 -18
- package/dist/elements/lineBreak/LineBreak.vue +3 -3
- package/dist/elements/lineBreak/_global.d.ts +18 -18
- package/dist/elements/link/BlockLink.vue +108 -110
- package/dist/elements/link/Link.vue +92 -96
- package/dist/elements/link/dependency/_global.d.ts +47 -47
- package/dist/elements/link/reference/_global.d.ts +49 -49
- package/dist/elements/list/List.vue +58 -65
- package/dist/elements/list/_global.d.ts +50 -50
- package/dist/elements/math/_global.d.ts +72 -72
- package/dist/elements/math/_global.ts +3 -3
- package/dist/elements/math/components/BlockMath.vue +30 -30
- package/dist/elements/math/components/InlinerMath.vue +65 -65
- package/dist/elements/math/components/Katex.vue +88 -89
- package/dist/elements/math/components/MathGroup.vue +41 -41
- package/dist/elements/math/katex.js +17 -6
- package/dist/elements/paragraph/Paragraph.vue +25 -27
- package/dist/elements/paragraph/_global.d.ts +27 -27
- package/dist/elements/problem/_global.d.ts +112 -112
- package/dist/elements/problem/components/Problem.vue +22 -22
- package/dist/elements/problem/components/ProblemButton.vue +20 -21
- package/dist/elements/problem/components/ProblemContainer.vue +8 -8
- package/dist/elements/problem/components/ProblemContent.vue +356 -371
- package/dist/elements/problem/components/ProblemExpander.vue +7 -7
- package/dist/elements/problem/components/ProblemExpanderSection.vue +57 -57
- package/dist/elements/problem/components/ProblemHeader.vue +100 -102
- package/dist/elements/problem/components/Problems.vue +83 -87
- package/dist/elements/problem/components/SubProblem.vue +14 -14
- package/dist/elements/problem/components/expanders/Check.vue +153 -150
- package/dist/elements/problem/components/expanders/Checks.vue +146 -83
- package/dist/elements/problem/components/expanders/DefaultPlusSections.vue +38 -38
- package/dist/elements/problem/components/expanders/Hint.vue +26 -26
- package/dist/elements/problem/core.d.ts +23 -23
- package/dist/elements/problem/problemContent.d.ts +134 -30
- package/dist/elements/problem/problemContent.js +157 -197
- package/dist/elements/problem/problemScript.d.ts +2 -2
- package/dist/elements/problem/problemScript.js +2 -2
- package/dist/elements/problem/rng.d.ts +1 -1
- package/dist/elements/problem/rng.js +1 -1
- package/dist/elements/table/Table.vue +100 -102
- package/dist/elements/table/_global.d.ts +36 -36
- package/dist/elements/video/Video.vue +110 -109
- package/dist/elements/video/_global.d.ts +18 -18
- package/package.json +42 -43
- package/types.d.ts +4 -4
|
@@ -1,150 +1,153 @@
|
|
|
1
|
-
<script lang="ts"
|
|
2
|
-
import { useTemplateRef, ref, watch } from 'vue';
|
|
3
|
-
import type { ProseElement } from '@jsprose/core';
|
|
4
|
-
|
|
5
|
-
import { checkValue, type problemCheckSchema } from '../../problemContent.js';
|
|
6
|
-
import checkIcon from '../../assets/actions/check.svg?raw';
|
|
7
|
-
import plusIcon from '../../../../app/shared/assets/plus.svg?raw';
|
|
8
|
-
import successIcon from '../../../../app/shared/assets/check.svg?raw';
|
|
9
|
-
import { useFormatText } from '../../../../app/composables/formatText.js';
|
|
10
|
-
import { useProseContext } from '../../../../app/index.js';
|
|
11
|
-
import { useProblemPhrase } from '../../composables/phrase.js';
|
|
12
|
-
|
|
13
|
-
type CheckStatus = 'default' | 'correct' | 'wrong';
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
state.value =
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { useTemplateRef, ref, watch } from 'vue';
|
|
3
|
+
import type { ProseElement } from '@jsprose/core';
|
|
4
|
+
|
|
5
|
+
import { checkValue, type problemCheckSchema } from '../../problemContent.js';
|
|
6
|
+
import checkIcon from '../../assets/actions/check.svg?raw';
|
|
7
|
+
import plusIcon from '../../../../app/shared/assets/plus.svg?raw';
|
|
8
|
+
import successIcon from '../../../../app/shared/assets/check.svg?raw';
|
|
9
|
+
import { useFormatText } from '../../../../app/composables/formatText.js';
|
|
10
|
+
import { useProseContext } from '../../../../app/index.js';
|
|
11
|
+
import { useProblemPhrase } from '../../composables/phrase.js';
|
|
12
|
+
|
|
13
|
+
type CheckStatus = 'default' | 'correct' | 'wrong';
|
|
14
|
+
|
|
15
|
+
type CheckState = {
|
|
16
|
+
icon: string;
|
|
17
|
+
iconClass?: string;
|
|
18
|
+
labelClass: string;
|
|
19
|
+
inputClass: string;
|
|
20
|
+
buttonClass: string;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const { check, script } = defineProps<{
|
|
24
|
+
check: ProseElement<typeof problemCheckSchema>;
|
|
25
|
+
script?: {
|
|
26
|
+
check: (answer: string | undefined) => boolean;
|
|
27
|
+
clear: () => void;
|
|
28
|
+
};
|
|
29
|
+
}>();
|
|
30
|
+
|
|
31
|
+
const emit = defineEmits<{
|
|
32
|
+
(event: 'status-change', status: CheckStatus): void;
|
|
33
|
+
}>();
|
|
34
|
+
|
|
35
|
+
const states: Record<CheckStatus, CheckState> = {
|
|
36
|
+
default: {
|
|
37
|
+
icon: checkIcon,
|
|
38
|
+
labelClass: 'text-text-muted',
|
|
39
|
+
inputClass: 'border-border text-text',
|
|
40
|
+
buttonClass:
|
|
41
|
+
'text-text-muted border-border hocus:border-text-muted hocus:text-text',
|
|
42
|
+
},
|
|
43
|
+
correct: {
|
|
44
|
+
icon: successIcon,
|
|
45
|
+
labelClass: 'text-lime-600',
|
|
46
|
+
inputClass: 'text-lime-600 border-lime-500',
|
|
47
|
+
buttonClass: 'text-lime-600 border-lime-500',
|
|
48
|
+
},
|
|
49
|
+
wrong: {
|
|
50
|
+
icon: plusIcon,
|
|
51
|
+
iconClass: 'rotate-45',
|
|
52
|
+
labelClass: 'text-red-700 dark:text-red-400',
|
|
53
|
+
inputClass: 'text-red-700 dark:text-red-400 border-red-400',
|
|
54
|
+
buttonClass: 'text-red-700 dark:text-red-400 border-red-400',
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const state = ref<CheckStatus>('default');
|
|
59
|
+
|
|
60
|
+
const formatText = useFormatText();
|
|
61
|
+
const { EruditIcon, EruditTransition } = useProseContext();
|
|
62
|
+
const phrase = await useProblemPhrase();
|
|
63
|
+
|
|
64
|
+
const answerInputElement = useTemplateRef<HTMLInputElement>('answer');
|
|
65
|
+
const answerInput = ref('');
|
|
66
|
+
const lastCheckedInput = ref<string | undefined | null>(null);
|
|
67
|
+
|
|
68
|
+
watch(answerInput, () => {
|
|
69
|
+
state.value = 'default';
|
|
70
|
+
lastCheckedInput.value = null;
|
|
71
|
+
script?.clear();
|
|
72
|
+
emit('status-change', 'default');
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
function doCheck() {
|
|
76
|
+
const newInput = answerInput.value.trim().replace(/\s+/g, ' ') || undefined;
|
|
77
|
+
|
|
78
|
+
if (newInput === lastCheckedInput.value) return;
|
|
79
|
+
|
|
80
|
+
lastCheckedInput.value = newInput;
|
|
81
|
+
|
|
82
|
+
if (script) {
|
|
83
|
+
const ok = script.check(newInput);
|
|
84
|
+
state.value = ok ? 'correct' : 'wrong';
|
|
85
|
+
emit('status-change', state.value);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
state.value = checkValue(newInput, check.data) ? 'correct' : 'wrong';
|
|
90
|
+
|
|
91
|
+
emit('status-change', state.value);
|
|
92
|
+
}
|
|
93
|
+
</script>
|
|
94
|
+
|
|
95
|
+
<template>
|
|
96
|
+
<div class="gap-small flex w-full flex-col">
|
|
97
|
+
<div
|
|
98
|
+
:class="[
|
|
99
|
+
'text-main-sm font-medium transition-[color]',
|
|
100
|
+
states[state].labelClass,
|
|
101
|
+
]"
|
|
102
|
+
>
|
|
103
|
+
<span @click="answerInputElement?.focus()">
|
|
104
|
+
{{ formatText(check.data.label ?? phrase.action_answer) + ':' }}
|
|
105
|
+
</span>
|
|
106
|
+
</div>
|
|
107
|
+
|
|
108
|
+
<form class="flex" @submit.prevent="doCheck">
|
|
109
|
+
<input
|
|
110
|
+
ref="answer"
|
|
111
|
+
v-model="answerInput"
|
|
112
|
+
type="text"
|
|
113
|
+
autocomplete="off"
|
|
114
|
+
:placeholder="check.data.placeholder"
|
|
115
|
+
:class="[
|
|
116
|
+
`bg-bg-main text-main-sm relative z-10 min-w-0 flex-1 rounded
|
|
117
|
+
rounded-tr-none rounded-br-none border border-r-0 px-2.5 py-1
|
|
118
|
+
transition-[border,color,background]`,
|
|
119
|
+
states[state].inputClass,
|
|
120
|
+
]"
|
|
121
|
+
/>
|
|
122
|
+
|
|
123
|
+
<button
|
|
124
|
+
type="submit"
|
|
125
|
+
:class="[
|
|
126
|
+
`bg-bg-main relative w-[50px] cursor-pointer rounded rounded-tl-none
|
|
127
|
+
rounded-bl-none border outline-0 transition-[border,color,background]`,
|
|
128
|
+
states[state].buttonClass,
|
|
129
|
+
]"
|
|
130
|
+
>
|
|
131
|
+
<EruditIcon
|
|
132
|
+
:key="state"
|
|
133
|
+
:name="states[state].icon"
|
|
134
|
+
:class="['invisible m-auto text-[1.2em]', states[state].iconClass]"
|
|
135
|
+
/>
|
|
136
|
+
<EruditTransition>
|
|
137
|
+
<EruditIcon
|
|
138
|
+
:key="state"
|
|
139
|
+
:name="states[state].icon"
|
|
140
|
+
:class="[
|
|
141
|
+
'absolute top-1/2 left-1/2 -translate-1/2 text-[1.2em]',
|
|
142
|
+
states[state].iconClass,
|
|
143
|
+
]"
|
|
144
|
+
/>
|
|
145
|
+
</EruditTransition>
|
|
146
|
+
</button>
|
|
147
|
+
</form>
|
|
148
|
+
|
|
149
|
+
<div class="text-text-dimmed text-main-xs italic">
|
|
150
|
+
{{ check.data.hint ? formatText(check.data.hint) : '' }}
|
|
151
|
+
</div>
|
|
152
|
+
</div>
|
|
153
|
+
</template>
|
|
@@ -1,83 +1,146 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import { ref } from 'vue';
|
|
3
|
-
import type
|
|
4
|
-
|
|
5
|
-
import type {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed, ref } from 'vue';
|
|
3
|
+
import { isProseElement, type ProseElement } from '@jsprose/core';
|
|
4
|
+
|
|
5
|
+
import type { CheckFunction } from '../../problemContent.js';
|
|
6
|
+
import { problemCheckSchema } from '../../problemContent.js';
|
|
7
|
+
import ProblemExpander from '../ProblemExpander.vue';
|
|
8
|
+
import Check from './Check.vue';
|
|
9
|
+
|
|
10
|
+
type CheckProseElement = ProseElement<typeof problemCheckSchema>;
|
|
11
|
+
type CheckStatus = 'default' | 'correct' | 'wrong';
|
|
12
|
+
|
|
13
|
+
const { value } = defineProps<{
|
|
14
|
+
value: {
|
|
15
|
+
checkElements: CheckProseElement[];
|
|
16
|
+
checkFunction?: CheckFunction;
|
|
17
|
+
};
|
|
18
|
+
}>();
|
|
19
|
+
|
|
20
|
+
let checkIdCounter = 0;
|
|
21
|
+
const checkIdMap = new WeakMap<CheckProseElement, string>();
|
|
22
|
+
|
|
23
|
+
function getCheckId(check: CheckProseElement) {
|
|
24
|
+
if (!checkIdMap.has(check)) {
|
|
25
|
+
checkIdMap.set(check, `check-${++checkIdCounter}`);
|
|
26
|
+
}
|
|
27
|
+
return checkIdMap.get(check)!;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function collectAllChecks(
|
|
31
|
+
checks: CheckProseElement[],
|
|
32
|
+
parent?: CheckProseElement,
|
|
33
|
+
): CheckProseElement[] {
|
|
34
|
+
const result: CheckProseElement[] = [];
|
|
35
|
+
|
|
36
|
+
for (const check of checks) {
|
|
37
|
+
// attach parent reference if not present
|
|
38
|
+
(check as any)._parent = parent ?? null;
|
|
39
|
+
result.push(check);
|
|
40
|
+
|
|
41
|
+
const children = (check.children ?? []).filter((child) =>
|
|
42
|
+
isProseElement(child, problemCheckSchema),
|
|
43
|
+
) as CheckProseElement[];
|
|
44
|
+
|
|
45
|
+
if (children.length) {
|
|
46
|
+
result.push(...collectAllChecks(children, check));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const allChecks = computed(() => collectAllChecks(value.checkElements));
|
|
54
|
+
|
|
55
|
+
const checkStatus = ref<Record<string, CheckStatus>>({});
|
|
56
|
+
|
|
57
|
+
function setStatus(check: CheckProseElement, status: CheckStatus) {
|
|
58
|
+
checkStatus.value[getCheckId(check)] = status;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function isVisible(check: CheckProseElement) {
|
|
62
|
+
const parent = (check as any)._parent as CheckProseElement | null;
|
|
63
|
+
|
|
64
|
+
if (!parent) return true;
|
|
65
|
+
|
|
66
|
+
// Check all ancestors in the parent tree
|
|
67
|
+
let current: CheckProseElement | null = parent;
|
|
68
|
+
while (current) {
|
|
69
|
+
const status = checkStatus.value[getCheckId(current)];
|
|
70
|
+
if (status !== 'correct') {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
current = (current as any)._parent as CheckProseElement | null;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const scriptAnswers = ref<Record<string, string | undefined>>({});
|
|
80
|
+
|
|
81
|
+
const scriptCheckNameMap = computed(() => {
|
|
82
|
+
const map = new Map<CheckProseElement, string>();
|
|
83
|
+
for (const check of allChecks.value) {
|
|
84
|
+
if (check.data.script) {
|
|
85
|
+
map.set(check, check.data.script);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return map;
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
function scriptCheckFunction(
|
|
92
|
+
check: CheckProseElement,
|
|
93
|
+
answer: string | undefined,
|
|
94
|
+
) {
|
|
95
|
+
if (!value.checkFunction) {
|
|
96
|
+
console.warn('No check function defined for script checks!');
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const name = scriptCheckNameMap.value.get(check)!;
|
|
101
|
+
|
|
102
|
+
const result = value.checkFunction({
|
|
103
|
+
name,
|
|
104
|
+
answer,
|
|
105
|
+
answers: scriptAnswers.value,
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
if (result === true) {
|
|
109
|
+
scriptAnswers.value[name] = answer;
|
|
110
|
+
} else {
|
|
111
|
+
delete scriptAnswers.value[name];
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return result;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function scriptClearFunction(check: CheckProseElement) {
|
|
118
|
+
const name = scriptCheckNameMap.value.get(check);
|
|
119
|
+
if (name) delete scriptAnswers.value[name];
|
|
120
|
+
}
|
|
121
|
+
</script>
|
|
122
|
+
|
|
123
|
+
<template>
|
|
124
|
+
<ProblemExpander>
|
|
125
|
+
<div
|
|
126
|
+
class="micro:grid-cols-2 grid gap-(--proseAsideWidth)
|
|
127
|
+
p-(--proseAsideWidth)"
|
|
128
|
+
>
|
|
129
|
+
<Check
|
|
130
|
+
v-for="check in allChecks"
|
|
131
|
+
:key="getCheckId(check)"
|
|
132
|
+
:check="check"
|
|
133
|
+
v-show="isVisible(check)"
|
|
134
|
+
:script="
|
|
135
|
+
check.data.script
|
|
136
|
+
? {
|
|
137
|
+
check: (answer) => scriptCheckFunction(check, answer),
|
|
138
|
+
clear: () => scriptClearFunction(check),
|
|
139
|
+
}
|
|
140
|
+
: undefined
|
|
141
|
+
"
|
|
142
|
+
@status-change="(status) => setStatus(check, status)"
|
|
143
|
+
/>
|
|
144
|
+
</div>
|
|
145
|
+
</ProblemExpander>
|
|
146
|
+
</template>
|
|
@@ -1,38 +1,38 @@
|
|
|
1
|
-
<script lang="ts" setup>
|
|
2
|
-
import { watchEffect } from 'vue';
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
} from '@jsprose/core';
|
|
8
|
-
|
|
9
|
-
import { problemSectionSchema } from '../../problemContent.js';
|
|
10
|
-
import { useArrayContainsAnchor } from '../../../../app/composables/anchor.js';
|
|
11
|
-
import ProblemExpander from '../ProblemExpander.vue';
|
|
12
|
-
import ProblemExpanderSection from '../ProblemExpanderSection.vue';
|
|
13
|
-
import Render from '../../../../app/shared/Render.vue';
|
|
14
|
-
|
|
15
|
-
const { value } = defineProps<{ value: ProseElement<AnySchema> }>();
|
|
16
|
-
|
|
17
|
-
const defaultBlocks = value.children!.filter(
|
|
18
|
-
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
const sections = value.children!.filter((element) =>
|
|
22
|
-
|
|
23
|
-
) as ProseElement<typeof problemSectionSchema>[];
|
|
24
|
-
</script>
|
|
25
|
-
|
|
26
|
-
<template>
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
</template>
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { watchEffect } from 'vue';
|
|
3
|
+
import {
|
|
4
|
+
isProseElement,
|
|
5
|
+
type AnySchema,
|
|
6
|
+
type ProseElement,
|
|
7
|
+
} from '@jsprose/core';
|
|
8
|
+
|
|
9
|
+
import { problemSectionSchema } from '../../problemContent.js';
|
|
10
|
+
import { useArrayContainsAnchor } from '../../../../app/composables/anchor.js';
|
|
11
|
+
import ProblemExpander from '../ProblemExpander.vue';
|
|
12
|
+
import ProblemExpanderSection from '../ProblemExpanderSection.vue';
|
|
13
|
+
import Render from '../../../../app/shared/Render.vue';
|
|
14
|
+
|
|
15
|
+
const { value } = defineProps<{ value: ProseElement<AnySchema> }>();
|
|
16
|
+
|
|
17
|
+
const defaultBlocks = value.children!.filter(
|
|
18
|
+
(element) => !isProseElement(element, problemSectionSchema),
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
const sections = value.children!.filter((element) =>
|
|
22
|
+
isProseElement(element, problemSectionSchema),
|
|
23
|
+
) as ProseElement<typeof problemSectionSchema>[];
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<template>
|
|
27
|
+
<ProblemExpander>
|
|
28
|
+
<div v-if="defaultBlocks.length" class="py-(--proseAsideWidth)">
|
|
29
|
+
<Render v-for="child of defaultBlocks" :element="child" />
|
|
30
|
+
</div>
|
|
31
|
+
<ProblemExpanderSection
|
|
32
|
+
v-if="sections.length"
|
|
33
|
+
v-for="section of sections"
|
|
34
|
+
:title="section.data"
|
|
35
|
+
:element="section"
|
|
36
|
+
/>
|
|
37
|
+
</ProblemExpander>
|
|
38
|
+
</template>
|