@matinfo/vitepress-plugin-quiz 1.0.4 → 1.0.6
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/README.md +7 -0
- package/dist/src/utils.d.ts +5 -0
- package/dist/vitepress-plugin-quiz.js +302 -244
- package/dist/vitepress-plugin-quiz.js.map +1 -1
- package/dist/vitepress-plugin-quiz.umd.cjs +4 -4
- package/dist/vitepress-plugin-quiz.umd.cjs.map +1 -1
- package/package.json +29 -21
- package/dist/src/__tests__/locales.test.d.ts +0 -1
- package/dist/src/__tests__/mdPlugin.test.d.ts +0 -1
- package/dist/src/__tests__/richText.test.d.ts +0 -1
|
@@ -1,76 +1,117 @@
|
|
|
1
|
-
import { defineComponent as F, computed as _, ref as M, inject as
|
|
2
|
-
const
|
|
3
|
-
let
|
|
4
|
-
function
|
|
5
|
-
if (typeof document > "u" ||
|
|
1
|
+
import { defineComponent as F, computed as _, ref as M, inject as C, onUnmounted as X, watch as D, onMounted as ee, openBlock as a, createElementBlock as o, normalizeClass as R, unref as z, createElementVNode as w, Fragment as k, renderList as H, toDisplayString as p, createTextVNode as N, createCommentVNode as Q, withKeys as T, withModifiers as U, withDirectives as te, vModelText as ne, provide as E, normalizeStyle as re, renderSlot as se } from "vue";
|
|
2
|
+
const ie = ".quiz-progress-bar{position:sticky;top:var(--vp-nav-height, 64px);z-index:20;display:flex;align-items:center;gap:12px;margin:-20px -24px 24px;padding:12px 24px;background:var(--vp-c-bg);border-bottom:1px solid var(--vp-c-divider)}@media(max-width:959px){.quiz-progress-bar{top:calc(var(--vp-nav-height, 64px) - 16px)}}.quiz-progress-track{flex:1;height:8px;background:var(--vp-c-bg-soft);border-radius:4px;overflow:hidden}.quiz-progress-fill{height:100%;background:var(--vp-c-brand-1);border-radius:4px;transition:width .35s ease}.quiz-progress-fill.complete{background:var(--vp-c-green-1, #10b981)}.quiz-progress-label{font-size:13px;color:var(--vp-c-text-2);white-space:nowrap}.quiz-question{border:1px solid var(--vp-c-divider);border-radius:8px;padding:20px 24px;margin-bottom:16px;background:var(--vp-c-bg);transition:border-color .2s}.quiz-question-title{font-weight:600;font-size:15px;margin:0 0 6px;padding:0 5px;color:var(--vp-c-text-1);float:none;width:auto}.quiz-hint{font-size:13px;color:var(--vp-c-text-3);margin:0 0 10px;font-style:italic}.quiz-answers{list-style:none;padding:0;margin:0}.quiz-answer{display:flex;align-items:baseline;gap:10px;padding:8px 12px;margin:4px 0;border:1px solid transparent;border-radius:6px;cursor:pointer;transition:background-color .15s,border-color .15s;user-select:none;font-size:14px;color:var(--vp-c-text-1)}.quiz-answer:hover:not(.correct):not(.wrong):not(.missed){background:var(--vp-c-bg-soft)}.quiz-answer.selected{border-color:var(--vp-c-brand-1);background:var(--vp-c-brand-soft)}.quiz-answer.correct{border-color:var(--vp-c-green-1, #10b981);background:var(--vp-c-green-soft, rgba(16, 185, 129, .12));cursor:default}.quiz-answer.wrong{border-color:var(--vp-c-red-1, #ef4444);background:var(--vp-c-red-soft, rgba(239, 68, 68, .12));cursor:default}.quiz-answer.missed{border-color:var(--vp-c-yellow-1, #f59e0b);background:var(--vp-c-yellow-soft, rgba(245, 158, 11, .1));cursor:default}.validated .quiz-answer{pointer-events:none}.quiz-indicator{flex-shrink:0;width:18px;text-align:center;font-size:15px;line-height:1}.quiz-empty{color:var(--vp-c-text-3)}.quiz-check{color:var(--vp-c-brand-1)}.quiz-answer.correct .quiz-check{color:var(--vp-c-green-1, #10b981)}.quiz-answer.wrong .quiz-check{color:var(--vp-c-red-1, #ef4444)}.quiz-answer-text code{font-family:var(--vp-font-family-mono);font-size:13px;padding:1px 5px;border-radius:4px;background:var(--vp-c-bg-soft);color:var(--vp-c-text-1)}.quiz-explanation{margin-top:12px;padding:10px 14px;border-left:3px solid var(--vp-c-brand-1);background:var(--vp-c-bg-soft);border-radius:0 6px 6px 0;font-size:13px;color:var(--vp-c-text-2)}.quiz-actions{display:flex;flex-wrap:wrap;align-items:center;gap:16px;margin-top:24px;padding-top:20px;border-top:1px solid var(--vp-c-divider)}.quiz-btn{display:inline-flex;align-items:center;justify-content:center;padding:10px 28px;font-size:14px;font-weight:600;border:1px solid transparent;border-radius:8px;cursor:pointer;transition:opacity .2s,background .2s}.quiz-btn:disabled{opacity:.45;cursor:not-allowed}.quiz-btn-validate{background:var(--vp-c-brand-1);color:var(--vp-c-white, #fff)}.quiz-btn-validate:hover:not(:disabled){opacity:.88}.quiz-btn-reset{background:var(--vp-c-bg-soft);border-color:var(--vp-c-divider);color:var(--vp-c-text-1)}.quiz-btn-reset:hover{background:var(--vp-c-bg-mute)}.quiz-score{display:flex;align-items:baseline;gap:8px}.quiz-score-value{font-size:22px;font-weight:700;color:var(--vp-c-brand-1)}.quiz-score-label{font-size:14px;color:var(--vp-c-text-2)}.quiz-input-wrapper{margin-top:8px}.quiz-input{width:100%;max-width:400px;padding:8px 12px;font-size:14px;font-family:var(--vp-font-family-mono);border:1px solid var(--vp-c-divider);border-radius:6px;background:var(--vp-c-bg);color:var(--vp-c-text-1);outline:none;transition:border-color .15s}.quiz-input:focus{border-color:var(--vp-c-brand-1)}.quiz-input:disabled{cursor:not-allowed;opacity:.8}.quiz-input.correct{border-color:var(--vp-c-green-1, #10b981);background:var(--vp-c-green-soft, rgba(16, 185, 129, .12))}.quiz-input.wrong{border-color:var(--vp-c-red-1, #ef4444);background:var(--vp-c-red-soft, rgba(239, 68, 68, .12))}.quiz-expected{margin-top:6px;font-size:13px;color:var(--vp-c-text-2)}.quiz-expected code{font-family:var(--vp-font-family-mono);font-size:13px;padding:1px 5px;border-radius:4px;background:var(--vp-c-bg-soft);color:var(--vp-c-green-1, #10b981)}";
|
|
3
|
+
let K = !1;
|
|
4
|
+
function ae() {
|
|
5
|
+
if (typeof document > "u" || K) return;
|
|
6
6
|
const e = "vitepress-plugin-quiz-styles";
|
|
7
7
|
if (document.getElementById(e)) {
|
|
8
|
-
|
|
8
|
+
K = !0;
|
|
9
9
|
return;
|
|
10
10
|
}
|
|
11
|
-
const
|
|
12
|
-
|
|
11
|
+
const n = document.createElement("style");
|
|
12
|
+
n.id = e, n.textContent = ie, document.head.appendChild(n), K = !0;
|
|
13
13
|
}
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
const oe = /^:::quiz\s*$/, le = /^:::\s*$/, ue = /^([A-Za-z-]+):(.*)$/, ce = /* @__PURE__ */ new Set([
|
|
15
|
+
"question",
|
|
16
|
+
"answer",
|
|
17
|
+
"answer-correct",
|
|
18
|
+
"answer-input",
|
|
19
|
+
"explanation",
|
|
20
|
+
"explication",
|
|
21
|
+
"shuffle"
|
|
22
|
+
]);
|
|
23
|
+
function Le(e) {
|
|
24
|
+
const n = e.utils.escapeHtml;
|
|
17
25
|
e.block.ruler.before(
|
|
18
26
|
"fence",
|
|
19
27
|
"quiz",
|
|
20
|
-
(r,
|
|
28
|
+
(r, c, s, m) => pe(r, c, s, m, n),
|
|
21
29
|
{ alt: ["paragraph", "reference", "blockquote", "list"] }
|
|
22
|
-
), e.renderer.rules.quiz = (r,
|
|
23
|
-
if (!r.tokens.some((
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
`,
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
`,
|
|
30
|
+
), e.renderer.rules.quiz = (r, c) => r[c].content, e.core.ruler.push("quiz_page_wrap", (r) => {
|
|
31
|
+
if (!r.tokens.some((d) => d.type === "quiz")) return;
|
|
32
|
+
const s = new r.Token("html_block", "", 0);
|
|
33
|
+
s.content = `<QuizPage>
|
|
34
|
+
`, s.block = !0;
|
|
35
|
+
const m = new r.Token("html_block", "", 0);
|
|
36
|
+
m.content = `</QuizPage>
|
|
37
|
+
`, m.block = !0, r.tokens.unshift(s), r.tokens.push(m);
|
|
30
38
|
});
|
|
31
39
|
}
|
|
32
|
-
function
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
if (
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
function pe(e, n, r, c, s) {
|
|
41
|
+
if (e.sCount[n] - e.blkIndent >= 4) return !1;
|
|
42
|
+
const m = e.bMarks[n] + e.tShift[n], d = e.eMarks[n], v = e.src.slice(m, d);
|
|
43
|
+
if (!oe.test(v)) return !1;
|
|
44
|
+
if (c) return !0;
|
|
45
|
+
let h = n + 1, q = !1;
|
|
46
|
+
for (; h < r; ) {
|
|
47
|
+
const l = e.bMarks[h] + e.tShift[h], I = e.eMarks[h], A = e.src.slice(l, I);
|
|
48
|
+
if (le.test(A)) {
|
|
49
|
+
q = !0;
|
|
41
50
|
break;
|
|
42
51
|
}
|
|
43
|
-
|
|
52
|
+
h++;
|
|
44
53
|
}
|
|
45
|
-
if (!
|
|
46
|
-
const
|
|
47
|
-
for (let
|
|
48
|
-
const
|
|
49
|
-
|
|
54
|
+
if (!q) return !1;
|
|
55
|
+
const x = [];
|
|
56
|
+
for (let l = n + 1; l < h; l++) {
|
|
57
|
+
const I = e.bMarks[l] + e.tShift[l], A = e.eMarks[l];
|
|
58
|
+
x.push(e.src.slice(I, A));
|
|
50
59
|
}
|
|
51
|
-
const
|
|
52
|
-
if (!
|
|
53
|
-
|
|
54
|
-
|
|
60
|
+
const g = de(x);
|
|
61
|
+
if (g?.type === "choice" && !g.answers.some((l) => l.correct) && console.warn(
|
|
62
|
+
`[vitepress-plugin-quiz] :quiz block at line ${n + 1} has no 'answer-correct:'; it can never be answered correctly.`
|
|
63
|
+
), !g)
|
|
64
|
+
return console.warn(
|
|
65
|
+
`[vitepress-plugin-quiz] Ignored invalid :::quiz block at line ${n + 1}: needs a 'question:' and at least one 'answer:'/'answer-correct:' or 'answer-input:'.`
|
|
66
|
+
), !1;
|
|
67
|
+
const S = e.push("quiz", "", 0);
|
|
68
|
+
return S.content = ve(g, s), S.map = [n, h + 1], S.block = !0, e.line = h + 1, !0;
|
|
55
69
|
}
|
|
56
|
-
function
|
|
57
|
-
let
|
|
70
|
+
function de(e) {
|
|
71
|
+
let n = "";
|
|
58
72
|
const r = [];
|
|
59
|
-
let
|
|
60
|
-
const
|
|
61
|
-
let
|
|
73
|
+
let c = "";
|
|
74
|
+
const s = [];
|
|
75
|
+
let m = !1, d = null;
|
|
62
76
|
for (const v of e) {
|
|
63
|
-
const
|
|
64
|
-
|
|
77
|
+
const h = v.trim();
|
|
78
|
+
if (!h) continue;
|
|
79
|
+
const q = ue.exec(h), x = q?.[1].toLowerCase();
|
|
80
|
+
if (!q || !x || !ce.has(x)) {
|
|
81
|
+
d?.(h);
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
const g = q[2].trim(), S = (l, I) => l ? `${l} ${I}` : I;
|
|
85
|
+
switch (x) {
|
|
86
|
+
case "question":
|
|
87
|
+
n = g, d = (l) => n = S(n, l);
|
|
88
|
+
break;
|
|
89
|
+
case "answer-correct":
|
|
90
|
+
case "answer": {
|
|
91
|
+
const l = { text: g, correct: x === "answer-correct" };
|
|
92
|
+
r.push(l), d = (I) => l.text = S(l.text, I);
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
case "answer-input":
|
|
96
|
+
g && s.push(g), d = null;
|
|
97
|
+
break;
|
|
98
|
+
case "explanation":
|
|
99
|
+
case "explication":
|
|
100
|
+
c = g, d = (l) => c = S(c, l);
|
|
101
|
+
break;
|
|
102
|
+
case "shuffle":
|
|
103
|
+
m = g.toLowerCase() === "true", d = null;
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
65
106
|
}
|
|
66
|
-
return
|
|
107
|
+
return n ? s.length > 0 ? { question: n, type: "input", answers: [], expected: s, explanation: c, shuffle: !1 } : r.length === 0 ? null : { question: n, type: "choice", answers: r, expected: [], explanation: c, shuffle: m } : null;
|
|
67
108
|
}
|
|
68
|
-
function
|
|
109
|
+
function ve(e, n) {
|
|
69
110
|
const r = JSON.stringify(e);
|
|
70
|
-
return `<QuizQuestion data-quiz="${
|
|
111
|
+
return `<QuizQuestion data-quiz="${n(r)}" />
|
|
71
112
|
`;
|
|
72
113
|
}
|
|
73
|
-
const
|
|
114
|
+
const W = {
|
|
74
115
|
en: {
|
|
75
116
|
answered: "answered",
|
|
76
117
|
validate: "Validate",
|
|
@@ -127,325 +168,342 @@ const U = {
|
|
|
127
168
|
expectedAnswer: "Respuesta esperada:"
|
|
128
169
|
}
|
|
129
170
|
};
|
|
130
|
-
function
|
|
131
|
-
return
|
|
171
|
+
function fe(e = "en") {
|
|
172
|
+
return W[e] ?? W.en;
|
|
173
|
+
}
|
|
174
|
+
function j(e) {
|
|
175
|
+
const n = [], r = /(\*\*(?!\s)(.+?)\*\*)|(\*(?!\s)(.+?)(?<!\s)\*)|(`([^`]+)`)/g;
|
|
176
|
+
let c = 0, s;
|
|
177
|
+
for (; (s = r.exec(e)) !== null; )
|
|
178
|
+
s.index > c && n.push({ type: "text", value: e.slice(c, s.index) }), s[2] ? n.push({ type: "bold", value: s[2] }) : s[4] ? n.push({ type: "italic", value: s[4] }) : s[6] && n.push({ type: "code", value: s[6] }), c = r.lastIndex;
|
|
179
|
+
return c < e.length && n.push({ type: "text", value: e.slice(c) }), n;
|
|
132
180
|
}
|
|
133
|
-
function
|
|
134
|
-
|
|
135
|
-
let u = 0, n;
|
|
136
|
-
for (; (n = r.exec(e)) !== null; )
|
|
137
|
-
n.index > u && t.push({ type: "text", value: e.slice(u, n.index) }), n[2] ? t.push({ type: "bold", value: n[2] }) : n[4] ? t.push({ type: "italic", value: n[4] }) : n[6] && t.push({ type: "code", value: n[6] }), u = r.lastIndex;
|
|
138
|
-
return u < e.length && t.push({ type: "text", value: e.slice(u) }), t;
|
|
181
|
+
function Y(e) {
|
|
182
|
+
return e.normalize("NFD").replace(/\p{M}/gu, "").trim().replace(/\s+/g, " ").toLowerCase();
|
|
139
183
|
}
|
|
140
|
-
const
|
|
184
|
+
const ge = ["aria-label"], xe = { class: "quiz-question-title" }, he = { key: 0 }, be = { key: 1 }, ze = { key: 2 }, we = {
|
|
141
185
|
key: 0,
|
|
142
186
|
class: "quiz-hint"
|
|
143
|
-
},
|
|
187
|
+
}, qe = ["aria-multiselectable"], ye = ["onClick", "aria-selected", "onKeydown"], me = {
|
|
144
188
|
class: "quiz-indicator",
|
|
145
189
|
"aria-hidden": "true"
|
|
146
|
-
},
|
|
190
|
+
}, ke = {
|
|
147
191
|
key: 0,
|
|
148
192
|
class: "quiz-check"
|
|
149
|
-
},
|
|
193
|
+
}, _e = {
|
|
150
194
|
key: 1,
|
|
151
195
|
class: "quiz-empty"
|
|
152
|
-
},
|
|
196
|
+
}, Se = {
|
|
153
197
|
key: 0,
|
|
154
198
|
class: "quiz-check"
|
|
155
|
-
},
|
|
199
|
+
}, Ie = {
|
|
156
200
|
key: 1,
|
|
157
201
|
class: "quiz-empty"
|
|
158
|
-
},
|
|
202
|
+
}, Ae = { class: "quiz-answer-text" }, $e = { key: 0 }, Ce = { key: 1 }, Qe = { key: 2 }, Me = { class: "quiz-hint" }, Ee = { class: "quiz-input-wrapper" }, Pe = ["disabled", "placeholder", "aria-label"], He = {
|
|
159
203
|
key: 0,
|
|
160
204
|
class: "quiz-expected"
|
|
161
|
-
},
|
|
205
|
+
}, Ne = {
|
|
162
206
|
key: 2,
|
|
163
207
|
class: "quiz-explanation",
|
|
164
208
|
role: "note"
|
|
165
|
-
},
|
|
209
|
+
}, Re = { key: 0 }, Ve = { key: 1 }, Oe = { key: 2 }, Te = /* @__PURE__ */ F({
|
|
166
210
|
__name: "QuizQuestion",
|
|
167
211
|
props: {
|
|
168
212
|
dataQuiz: { type: String, required: !0 }
|
|
169
213
|
},
|
|
170
214
|
setup(e) {
|
|
171
|
-
const
|
|
215
|
+
const n = e, r = _(() => {
|
|
172
216
|
try {
|
|
173
|
-
return JSON.parse(
|
|
217
|
+
return JSON.parse(n.dataQuiz);
|
|
174
218
|
} catch {
|
|
175
219
|
return null;
|
|
176
220
|
}
|
|
177
221
|
});
|
|
178
|
-
function u
|
|
179
|
-
const
|
|
180
|
-
for (let
|
|
181
|
-
const y = Math.floor(Math.random() * (
|
|
182
|
-
[
|
|
222
|
+
function c(u) {
|
|
223
|
+
const i = [...u];
|
|
224
|
+
for (let t = i.length - 1; t > 0; t--) {
|
|
225
|
+
const y = Math.floor(Math.random() * (t + 1));
|
|
226
|
+
[i[t], i[y]] = [i[y], i[t]];
|
|
183
227
|
}
|
|
184
|
-
return
|
|
228
|
+
return i;
|
|
185
229
|
}
|
|
186
|
-
const
|
|
187
|
-
function
|
|
230
|
+
const s = M([]);
|
|
231
|
+
function m() {
|
|
188
232
|
if (!r.value || r.value.type === "input") {
|
|
189
|
-
|
|
233
|
+
s.value = [];
|
|
190
234
|
return;
|
|
191
235
|
}
|
|
192
|
-
const
|
|
193
|
-
|
|
236
|
+
const u = r.value.answers.map((i, t) => ({ ...i, originalIndex: t }));
|
|
237
|
+
s.value = r.value.shuffle ? c(u) : u;
|
|
194
238
|
}
|
|
195
|
-
const
|
|
239
|
+
const d = _(() => r.value ? {
|
|
196
240
|
...r.value,
|
|
197
|
-
answers:
|
|
198
|
-
} : null),
|
|
199
|
-
() =>
|
|
200
|
-
),
|
|
201
|
-
if (!
|
|
202
|
-
if (
|
|
203
|
-
const
|
|
204
|
-
return r.value.expected.some((
|
|
241
|
+
answers: s.value
|
|
242
|
+
} : null), v = _(() => r.value?.type === "input"), h = _(
|
|
243
|
+
() => d.value && !v.value ? d.value.answers.filter((u) => u.correct).length : 0
|
|
244
|
+
), q = _(() => h.value > 1), x = M(/* @__PURE__ */ new Set()), g = M(""), S = C("quiz-register", null), l = C("quiz-validated", M(!1)), I = C("quiz-reset", M(0)), A = C("quiz-locale"), P = C("quiz-question-id", null), f = C("quiz-save-answer", null), b = C("quiz-get-answer", null), $ = P ? P() : null, J = _(() => v.value ? g.value.trim().length > 0 : x.value.size > 0), V = _(() => {
|
|
245
|
+
if (!d.value || !J.value) return !1;
|
|
246
|
+
if (v.value) {
|
|
247
|
+
const i = Y(g.value);
|
|
248
|
+
return r.value.expected.some((t) => i === Y(t));
|
|
205
249
|
}
|
|
206
|
-
const
|
|
207
|
-
|
|
250
|
+
const u = new Set(
|
|
251
|
+
r.value.answers.map((i, t) => i.correct ? t : -1).filter((i) => i >= 0)
|
|
208
252
|
);
|
|
209
|
-
if (
|
|
210
|
-
for (const
|
|
211
|
-
if (!
|
|
253
|
+
if (x.value.size !== u.size) return !1;
|
|
254
|
+
for (const i of x.value)
|
|
255
|
+
if (!u.has(i)) return !1;
|
|
212
256
|
return !0;
|
|
213
257
|
});
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
258
|
+
if (S && r.value) {
|
|
259
|
+
const u = S({ answered: J, isCorrect: V });
|
|
260
|
+
X(u);
|
|
261
|
+
}
|
|
262
|
+
D(I, () => {
|
|
263
|
+
x.value = /* @__PURE__ */ new Set(), g.value = "", m();
|
|
264
|
+
}), ee(() => {
|
|
265
|
+
if (m(), b && $ !== null) {
|
|
266
|
+
const u = b($);
|
|
267
|
+
if (u) {
|
|
268
|
+
if (u.type === "input" && v.value && typeof u.input == "string")
|
|
269
|
+
g.value = u.input;
|
|
270
|
+
else if (u.type === "choice" && !v.value && Array.isArray(u.selected)) {
|
|
271
|
+
const i = r.value?.answers.length ?? 0;
|
|
272
|
+
x.value = new Set(
|
|
273
|
+
u.selected.filter((t) => Number.isInteger(t) && t >= 0 && t < i)
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
220
277
|
}
|
|
221
278
|
});
|
|
222
|
-
function
|
|
223
|
-
if (
|
|
224
|
-
const
|
|
225
|
-
|
|
279
|
+
function O(u) {
|
|
280
|
+
if (l.value) return;
|
|
281
|
+
const i = new Set(x.value);
|
|
282
|
+
q.value ? i.has(u) ? i.delete(u) : i.add(u) : (i.clear(), i.add(u)), x.value = i, B();
|
|
226
283
|
}
|
|
227
|
-
D(
|
|
228
|
-
|
|
284
|
+
D(g, () => {
|
|
285
|
+
l.value || B();
|
|
229
286
|
});
|
|
230
|
-
function
|
|
231
|
-
!
|
|
287
|
+
function B() {
|
|
288
|
+
!f || $ === null || (v.value ? f($, { type: "input", input: g.value }) : f($, { type: "choice", selected: [...x.value] }));
|
|
232
289
|
}
|
|
233
|
-
function
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
const l = v.value.answers[p], s = f.value.has(p);
|
|
237
|
-
return l.correct && s ? "quiz-answer correct" : l.correct && !s ? "quiz-answer missed" : !l.correct && s ? "quiz-answer wrong" : "quiz-answer";
|
|
290
|
+
function Z(u) {
|
|
291
|
+
const i = x.value.has(u.originalIndex);
|
|
292
|
+
return l.value ? u.correct && i ? "quiz-answer correct" : u.correct && !i ? "quiz-answer missed" : !u.correct && i ? "quiz-answer wrong" : "quiz-answer" : i ? "quiz-answer selected" : "quiz-answer";
|
|
238
293
|
}
|
|
239
|
-
const
|
|
240
|
-
return (
|
|
294
|
+
const G = _(() => l.value ? V.value ? "quiz-input correct" : "quiz-input wrong" : "quiz-input");
|
|
295
|
+
return (u, i) => d.value ? (a(), o("fieldset", {
|
|
241
296
|
key: 0,
|
|
242
|
-
class:
|
|
243
|
-
"aria-label":
|
|
297
|
+
class: R(["quiz-question", { validated: z(l) }]),
|
|
298
|
+
"aria-label": d.value.question
|
|
244
299
|
}, [
|
|
245
|
-
|
|
246
|
-
(a(!0), o(
|
|
247
|
-
|
|
248
|
-
|
|
300
|
+
w("legend", xe, [
|
|
301
|
+
(a(!0), o(k, null, H(z(j)(d.value.question), (t, y) => (a(), o(k, { key: y }, [
|
|
302
|
+
t.type === "bold" ? (a(), o("strong", he, p(t.value), 1)) : t.type === "italic" ? (a(), o("em", be, p(t.value), 1)) : t.type === "code" ? (a(), o("code", ze, p(t.value), 1)) : (a(), o(k, { key: 3 }, [
|
|
303
|
+
N(p(t.value), 1)
|
|
249
304
|
], 64))
|
|
250
305
|
], 64))), 128))
|
|
251
306
|
]),
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
307
|
+
v.value ? Q("", !0) : (a(), o(k, { key: 0 }, [
|
|
308
|
+
q.value ? (a(), o("p", we, p(z(A).multipleHint), 1)) : Q("", !0),
|
|
309
|
+
w("ul", {
|
|
255
310
|
class: "quiz-answers",
|
|
256
311
|
role: "listbox",
|
|
257
|
-
"aria-multiselectable":
|
|
312
|
+
"aria-multiselectable": q.value
|
|
258
313
|
}, [
|
|
259
|
-
(a(!0), o(
|
|
260
|
-
key:
|
|
261
|
-
class:
|
|
262
|
-
onClick: (
|
|
314
|
+
(a(!0), o(k, null, H(d.value.answers, (t) => (a(), o("li", {
|
|
315
|
+
key: t.originalIndex,
|
|
316
|
+
class: R(Z(t)),
|
|
317
|
+
onClick: (y) => O(t.originalIndex),
|
|
263
318
|
role: "option",
|
|
264
|
-
"aria-selected":
|
|
319
|
+
"aria-selected": x.value.has(t.originalIndex),
|
|
265
320
|
tabindex: "0",
|
|
266
321
|
onKeydown: [
|
|
267
|
-
|
|
268
|
-
|
|
322
|
+
T((y) => O(t.originalIndex), ["enter"]),
|
|
323
|
+
T(U((y) => O(t.originalIndex), ["prevent"]), ["space"])
|
|
269
324
|
]
|
|
270
325
|
}, [
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
], 64)) : (a(), o(
|
|
275
|
-
|
|
326
|
+
w("span", me, [
|
|
327
|
+
q.value ? (a(), o(k, { key: 0 }, [
|
|
328
|
+
x.value.has(t.originalIndex) ? (a(), o("span", ke, "✓")) : (a(), o("span", _e, "☐"))
|
|
329
|
+
], 64)) : (a(), o(k, { key: 1 }, [
|
|
330
|
+
x.value.has(t.originalIndex) ? (a(), o("span", Se, "●")) : (a(), o("span", Ie, "○"))
|
|
276
331
|
], 64))
|
|
277
332
|
]),
|
|
278
|
-
|
|
279
|
-
(a(!0), o(
|
|
280
|
-
|
|
281
|
-
|
|
333
|
+
w("span", Ae, [
|
|
334
|
+
(a(!0), o(k, null, H(z(j)(t.text), (y, L) => (a(), o(k, { key: L }, [
|
|
335
|
+
y.type === "bold" ? (a(), o("strong", $e, p(y.value), 1)) : y.type === "italic" ? (a(), o("em", Ce, p(y.value), 1)) : y.type === "code" ? (a(), o("code", Qe, p(y.value), 1)) : (a(), o(k, { key: 3 }, [
|
|
336
|
+
N(p(y.value), 1)
|
|
282
337
|
], 64))
|
|
283
338
|
], 64))), 128))
|
|
284
339
|
])
|
|
285
|
-
], 42,
|
|
286
|
-
], 8,
|
|
340
|
+
], 42, ye))), 128))
|
|
341
|
+
], 8, qe)
|
|
287
342
|
], 64)),
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
"onUpdate:modelValue":
|
|
293
|
-
class:
|
|
343
|
+
v.value ? (a(), o(k, { key: 1 }, [
|
|
344
|
+
w("p", Me, p(z(A).inputHint), 1),
|
|
345
|
+
w("div", Ee, [
|
|
346
|
+
te(w("input", {
|
|
347
|
+
"onUpdate:modelValue": i[0] || (i[0] = (t) => g.value = t),
|
|
348
|
+
class: R(G.value),
|
|
294
349
|
type: "text",
|
|
295
|
-
disabled:
|
|
296
|
-
placeholder:
|
|
297
|
-
"aria-label":
|
|
350
|
+
disabled: z(l),
|
|
351
|
+
placeholder: z(A).inputPlaceholder,
|
|
352
|
+
"aria-label": d.value.question,
|
|
298
353
|
autocomplete: "off",
|
|
299
354
|
spellcheck: "false",
|
|
300
|
-
onKeydown:
|
|
355
|
+
onKeydown: i[1] || (i[1] = T(U(() => {
|
|
301
356
|
}, ["prevent"]), ["enter"]))
|
|
302
|
-
}, null, 42,
|
|
303
|
-
[
|
|
357
|
+
}, null, 42, Pe), [
|
|
358
|
+
[ne, g.value]
|
|
304
359
|
]),
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
])) :
|
|
360
|
+
z(l) && !V.value ? (a(), o("p", He, [
|
|
361
|
+
N(p(z(A).expectedAnswer) + " ", 1),
|
|
362
|
+
w("code", null, p(r.value?.expected[0]), 1)
|
|
363
|
+
])) : Q("", !0)
|
|
309
364
|
])
|
|
310
|
-
], 64)) :
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
(a(!0), o(
|
|
314
|
-
|
|
315
|
-
|
|
365
|
+
], 64)) : Q("", !0),
|
|
366
|
+
z(l) && d.value.explanation ? (a(), o("div", Ne, [
|
|
367
|
+
w("strong", null, p(z(A).explanation), 1),
|
|
368
|
+
(a(!0), o(k, null, H(z(j)(d.value.explanation), (t, y) => (a(), o(k, { key: y }, [
|
|
369
|
+
t.type === "bold" ? (a(), o("strong", Re, p(t.value), 1)) : t.type === "italic" ? (a(), o("em", Ve, p(t.value), 1)) : t.type === "code" ? (a(), o("code", Oe, p(t.value), 1)) : (a(), o(k, { key: 3 }, [
|
|
370
|
+
N(p(t.value), 1)
|
|
316
371
|
], 64))
|
|
317
372
|
], 64))), 128))
|
|
318
|
-
])) :
|
|
319
|
-
], 10,
|
|
373
|
+
])) : Q("", !0)
|
|
374
|
+
], 10, ge)) : Q("", !0);
|
|
320
375
|
}
|
|
321
|
-
}),
|
|
376
|
+
}), Ke = {
|
|
322
377
|
class: "quiz-page",
|
|
323
378
|
role: "region",
|
|
324
379
|
"aria-label": "Quiz"
|
|
325
|
-
},
|
|
380
|
+
}, je = ["aria-valuenow", "aria-valuemax", "aria-label"], Je = { class: "quiz-progress-track" }, Be = {
|
|
326
381
|
class: "quiz-progress-label",
|
|
327
382
|
"aria-live": "polite"
|
|
328
|
-
},
|
|
383
|
+
}, De = { class: "quiz-actions" }, Ue = ["disabled"], We = ["aria-label"], Ye = { class: "quiz-score-value" }, Fe = { class: "quiz-score-label" }, Ze = /* @__PURE__ */ F({
|
|
329
384
|
__name: "QuizPage",
|
|
330
385
|
setup(e) {
|
|
331
|
-
const
|
|
332
|
-
|
|
333
|
-
let
|
|
334
|
-
E("quiz-validated",
|
|
335
|
-
r.value.
|
|
336
|
-
|
|
337
|
-
|
|
386
|
+
const n = C("quiz-locale"), r = M([]), c = M(!1), s = typeof window < "u" ? "quiz-state:" + window.location.pathname : "";
|
|
387
|
+
A();
|
|
388
|
+
let m = 0;
|
|
389
|
+
E("quiz-validated", c), E("quiz-register", (f) => (r.value.push(f), () => {
|
|
390
|
+
const b = r.value.indexOf(f);
|
|
391
|
+
b >= 0 && r.value.splice(b, 1);
|
|
392
|
+
})), E("quiz-question-id", () => m++), E("quiz-save-answer", (f, b) => {
|
|
393
|
+
if (s)
|
|
338
394
|
try {
|
|
339
|
-
sessionStorage.setItem(
|
|
395
|
+
sessionStorage.setItem(s + ":q" + f, JSON.stringify(b));
|
|
340
396
|
} catch {
|
|
341
397
|
}
|
|
342
|
-
}), E("quiz-get-answer", (
|
|
343
|
-
if (!
|
|
398
|
+
}), E("quiz-get-answer", (f) => {
|
|
399
|
+
if (!s) return null;
|
|
344
400
|
try {
|
|
345
|
-
const b = sessionStorage.getItem(
|
|
401
|
+
const b = sessionStorage.getItem(s + ":q" + f);
|
|
346
402
|
return b ? JSON.parse(b) : null;
|
|
347
403
|
} catch {
|
|
348
404
|
return null;
|
|
349
405
|
}
|
|
350
406
|
});
|
|
351
|
-
const
|
|
352
|
-
E("quiz-reset",
|
|
353
|
-
const
|
|
354
|
-
() => r.value.filter((
|
|
355
|
-
),
|
|
356
|
-
() => r.value.filter((
|
|
357
|
-
),
|
|
358
|
-
() =>
|
|
407
|
+
const d = M(0);
|
|
408
|
+
E("quiz-reset", d);
|
|
409
|
+
const v = _(() => r.value.length), h = _(
|
|
410
|
+
() => r.value.filter((f) => f.answered).length
|
|
411
|
+
), q = _(
|
|
412
|
+
() => r.value.filter((f) => f.isCorrect).length
|
|
413
|
+
), x = _(
|
|
414
|
+
() => v.value > 0 && h.value === v.value
|
|
415
|
+
), g = _(
|
|
416
|
+
() => v.value ? Math.round(h.value / v.value * 100) : 0
|
|
359
417
|
);
|
|
360
|
-
function
|
|
361
|
-
|
|
418
|
+
function S() {
|
|
419
|
+
c.value = !0, I();
|
|
362
420
|
}
|
|
363
|
-
function
|
|
364
|
-
|
|
421
|
+
function l() {
|
|
422
|
+
c.value = !1, d.value++, P();
|
|
365
423
|
}
|
|
366
|
-
function
|
|
367
|
-
if (
|
|
424
|
+
function I() {
|
|
425
|
+
if (s)
|
|
368
426
|
try {
|
|
369
|
-
const
|
|
370
|
-
sessionStorage.setItem(
|
|
427
|
+
const f = { validated: c.value, ts: Date.now() };
|
|
428
|
+
sessionStorage.setItem(s, JSON.stringify(f));
|
|
371
429
|
} catch {
|
|
372
430
|
}
|
|
373
431
|
}
|
|
374
|
-
function
|
|
375
|
-
if (
|
|
432
|
+
function A() {
|
|
433
|
+
if (s)
|
|
376
434
|
try {
|
|
377
|
-
const
|
|
378
|
-
if (!
|
|
379
|
-
const b = JSON.parse(
|
|
380
|
-
b && b.validated && (
|
|
435
|
+
const f = sessionStorage.getItem(s);
|
|
436
|
+
if (!f) return;
|
|
437
|
+
const b = JSON.parse(f);
|
|
438
|
+
b && b.validated && (c.value = !0);
|
|
381
439
|
} catch {
|
|
382
440
|
}
|
|
383
441
|
}
|
|
384
|
-
function
|
|
385
|
-
if (
|
|
442
|
+
function P() {
|
|
443
|
+
if (s)
|
|
386
444
|
try {
|
|
387
|
-
const
|
|
445
|
+
const f = [];
|
|
388
446
|
for (let b = 0; b < sessionStorage.length; b++) {
|
|
389
|
-
const
|
|
390
|
-
|
|
447
|
+
const $ = sessionStorage.key(b);
|
|
448
|
+
$ && $.startsWith(s) && f.push($);
|
|
391
449
|
}
|
|
392
|
-
|
|
450
|
+
f.forEach((b) => sessionStorage.removeItem(b));
|
|
393
451
|
} catch {
|
|
394
452
|
}
|
|
395
453
|
}
|
|
396
|
-
return (
|
|
397
|
-
|
|
454
|
+
return (f, b) => (a(), o("div", Ke, [
|
|
455
|
+
w("div", {
|
|
398
456
|
class: "quiz-progress-bar",
|
|
399
457
|
role: "progressbar",
|
|
400
|
-
"aria-valuenow":
|
|
458
|
+
"aria-valuenow": h.value,
|
|
401
459
|
"aria-valuemin": 0,
|
|
402
|
-
"aria-valuemax":
|
|
403
|
-
"aria-label":
|
|
460
|
+
"aria-valuemax": v.value,
|
|
461
|
+
"aria-label": h.value + " / " + v.value + " " + z(n).answered
|
|
404
462
|
}, [
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
class:
|
|
408
|
-
style: re({ width:
|
|
463
|
+
w("div", Je, [
|
|
464
|
+
w("div", {
|
|
465
|
+
class: R(["quiz-progress-fill", { complete: g.value === 100 }]),
|
|
466
|
+
style: re({ width: g.value + "%" })
|
|
409
467
|
}, null, 6)
|
|
410
468
|
]),
|
|
411
|
-
|
|
412
|
-
], 8,
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
469
|
+
w("span", Be, p(h.value) + " / " + p(v.value) + " " + p(z(n).answered), 1)
|
|
470
|
+
], 8, je),
|
|
471
|
+
se(f.$slots, "default"),
|
|
472
|
+
w("div", De, [
|
|
473
|
+
c.value ? Q("", !0) : (a(), o("button", {
|
|
416
474
|
key: 0,
|
|
417
475
|
class: "quiz-btn quiz-btn-validate",
|
|
418
|
-
disabled: !
|
|
419
|
-
onClick:
|
|
420
|
-
},
|
|
421
|
-
|
|
422
|
-
|
|
476
|
+
disabled: !x.value,
|
|
477
|
+
onClick: S
|
|
478
|
+
}, p(z(n).validate), 9, Ue)),
|
|
479
|
+
c.value ? (a(), o(k, { key: 1 }, [
|
|
480
|
+
w("div", {
|
|
423
481
|
class: "quiz-score",
|
|
424
482
|
role: "status",
|
|
425
483
|
"aria-live": "polite",
|
|
426
|
-
"aria-label":
|
|
484
|
+
"aria-label": q.value + " / " + v.value + " " + z(n).correctAnswers(q.value)
|
|
427
485
|
}, [
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
], 8,
|
|
431
|
-
|
|
486
|
+
w("span", Ye, p(q.value) + " / " + p(v.value), 1),
|
|
487
|
+
w("span", Fe, p(z(n).correctAnswers(q.value)) + " (" + p(v.value ? Math.round(q.value / v.value * 100) : 0) + "%) ", 1)
|
|
488
|
+
], 8, We),
|
|
489
|
+
w("button", {
|
|
432
490
|
class: "quiz-btn quiz-btn-reset",
|
|
433
|
-
onClick:
|
|
434
|
-
},
|
|
435
|
-
], 64)) :
|
|
491
|
+
onClick: l
|
|
492
|
+
}, p(z(n).reset), 1)
|
|
493
|
+
], 64)) : Q("", !0)
|
|
436
494
|
])
|
|
437
495
|
]));
|
|
438
496
|
}
|
|
439
497
|
});
|
|
440
|
-
function
|
|
441
|
-
|
|
498
|
+
function Xe(e, n = "en") {
|
|
499
|
+
ae(), e.provide("quiz-locale", fe(n)), e.component("QuizQuestion", Te), e.component("QuizPage", Ze);
|
|
442
500
|
}
|
|
443
501
|
export {
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
502
|
+
Ze as QuizPage,
|
|
503
|
+
Te as QuizQuestion,
|
|
504
|
+
Xe as enhanceAppWithQuiz,
|
|
505
|
+
fe as getLocale,
|
|
506
|
+
W as locales,
|
|
507
|
+
Le as quizMarkdownPlugin
|
|
450
508
|
};
|
|
451
509
|
//# sourceMappingURL=vitepress-plugin-quiz.js.map
|