@matinfo/vitepress-plugin-quiz 0.9.9

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.
@@ -0,0 +1,451 @@
1
+ import { defineComponent as F, computed as _, ref as M, inject as $, watch as D, onMounted as X, openBlock as a, createElementBlock as o, normalizeClass as N, unref as g, createElementVNode as z, Fragment as q, renderList as R, toDisplayString as c, createTextVNode as V, createCommentVNode as I, withKeys as O, withModifiers as L, withDirectives as ee, vModelText as te, provide as E, normalizeStyle as re, renderSlot as ne } from "vue";
2
+ const se = ".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 j = !1;
4
+ function ie() {
5
+ if (typeof document > "u" || j) return;
6
+ const e = "vitepress-plugin-quiz-styles";
7
+ if (document.getElementById(e)) {
8
+ j = !0;
9
+ return;
10
+ }
11
+ const t = document.createElement("style");
12
+ t.id = e, t.textContent = se, document.head.appendChild(t), j = !0;
13
+ }
14
+ const ae = /^:::quiz\s*$/, oe = /^:::\s*$/;
15
+ function Fe(e) {
16
+ const t = e.utils.escapeHtml;
17
+ e.block.ruler.before(
18
+ "fence",
19
+ "quiz",
20
+ (r, u, n, w) => le(r, u, n, w, t),
21
+ { alt: ["paragraph", "reference", "blockquote", "list"] }
22
+ ), e.renderer.rules.quiz = (r, u) => r[u].content, e.core.ruler.push("quiz_page_wrap", (r) => {
23
+ if (!r.tokens.some((v) => v.type === "quiz")) return;
24
+ const n = new r.Token("html_block", "", 0);
25
+ n.content = `<QuizPage>
26
+ `, n.block = !0;
27
+ const w = new r.Token("html_block", "", 0);
28
+ w.content = `</QuizPage>
29
+ `, w.block = !0, r.tokens.unshift(n), r.tokens.push(w);
30
+ });
31
+ }
32
+ function le(e, t, r, u, n) {
33
+ const w = e.bMarks[t] + e.tShift[t], v = e.eMarks[t], i = e.src.slice(w, v);
34
+ if (!ae.test(i)) return !1;
35
+ if (u) return !0;
36
+ let x = t + 1, k = !1;
37
+ for (; x < r; ) {
38
+ const h = e.bMarks[x] + e.tShift[x], P = e.eMarks[x], S = e.src.slice(h, P);
39
+ if (oe.test(S)) {
40
+ k = !0;
41
+ break;
42
+ }
43
+ x++;
44
+ }
45
+ if (!k) return !1;
46
+ const f = [];
47
+ for (let h = t + 1; h < x; h++) {
48
+ const P = e.bMarks[h] + e.tShift[h], S = e.eMarks[h];
49
+ f.push(e.src.slice(P, S));
50
+ }
51
+ const m = ue(f);
52
+ if (!m) return !1;
53
+ const C = e.push("quiz", "", 0);
54
+ return C.content = ce(m, n), C.map = [t, x + 1], C.block = !0, e.line = x + 1, !0;
55
+ }
56
+ function ue(e) {
57
+ let t = "";
58
+ const r = [];
59
+ let u = "";
60
+ const n = [];
61
+ let w = !1;
62
+ for (const v of e) {
63
+ const i = v.trim();
64
+ i && (i.startsWith("question:") ? t = i.slice(9).trim() : i.startsWith("answer-correct:") ? r.push({ text: i.slice(15).trim(), correct: !0 }) : i.startsWith("answer-input:") ? n.push(i.slice(13).trim()) : i.startsWith("answer:") ? r.push({ text: i.slice(7).trim(), correct: !1 }) : i.startsWith("explanation:") || i.startsWith("explication:") ? u = i.slice(12).trim() : i.startsWith("shuffle:") && (w = i.slice(8).trim().toLowerCase() === "true"));
65
+ }
66
+ return t ? n.length > 0 ? { question: t, type: "input", answers: [], expected: n, explanation: u, shuffle: !1 } : r.length === 0 ? null : { question: t, type: "choice", answers: r, expected: [], explanation: u, shuffle: w } : null;
67
+ }
68
+ function ce(e, t) {
69
+ const r = JSON.stringify(e);
70
+ return `<QuizQuestion data-quiz="${t(r)}" />
71
+ `;
72
+ }
73
+ const U = {
74
+ en: {
75
+ answered: "answered",
76
+ validate: "Validate",
77
+ reset: "Restart",
78
+ correctAnswers: (e) => `correct answer${e !== 1 ? "s" : ""}`,
79
+ multipleHint: "Multiple answers possible",
80
+ explanation: "Explanation: ",
81
+ inputHint: "Type your answer",
82
+ inputPlaceholder: "Your answer…",
83
+ expectedAnswer: "Expected answer:"
84
+ },
85
+ fr: {
86
+ answered: "répondue(s)",
87
+ validate: "Valider",
88
+ reset: "Recommencer",
89
+ correctAnswers: (e) => `réponse${e > 1 ? "s" : ""} correcte${e > 1 ? "s" : ""}`,
90
+ multipleHint: "Plusieurs réponses possibles",
91
+ explanation: "Explication : ",
92
+ inputHint: "Saisissez votre réponse",
93
+ inputPlaceholder: "Votre réponse…",
94
+ expectedAnswer: "Réponse attendue :"
95
+ },
96
+ de: {
97
+ answered: "beantwortet",
98
+ validate: "Überprüfen",
99
+ reset: "Neu starten",
100
+ correctAnswers: (e) => `richtige Antwort${e !== 1 ? "en" : ""}`,
101
+ multipleHint: "Mehrere Antworten möglich",
102
+ explanation: "Erklärung:",
103
+ inputHint: "Geben Sie Ihre Antwort ein",
104
+ inputPlaceholder: "Ihre Antwort…",
105
+ expectedAnswer: "Erwartete Antwort:"
106
+ },
107
+ it: {
108
+ answered: "risposta/e",
109
+ validate: "Verifica",
110
+ reset: "Ricominciare",
111
+ correctAnswers: (e) => `rispost${e !== 1 ? "e corrette" : "a corretta"}`,
112
+ multipleHint: "Più risposte possibili",
113
+ explanation: "Spiegazione: ",
114
+ inputHint: "Digita la tua risposta",
115
+ inputPlaceholder: "La tua risposta…",
116
+ expectedAnswer: "Risposta attesa:"
117
+ },
118
+ es: {
119
+ answered: "respondida(s)",
120
+ validate: "Validar",
121
+ reset: "Reiniciar",
122
+ correctAnswers: (e) => `respuesta${e !== 1 ? "s correctas" : " correcta"}`,
123
+ multipleHint: "Varias respuestas posibles",
124
+ explanation: "Explicación: ",
125
+ inputHint: "Escribe tu respuesta",
126
+ inputPlaceholder: "Tu respuesta…",
127
+ expectedAnswer: "Respuesta esperada:"
128
+ }
129
+ };
130
+ function pe(e = "en") {
131
+ return U[e] ?? U.en;
132
+ }
133
+ function J(e) {
134
+ const t = [], r = /(\*\*(.+?)\*\*)|(\*(.+?)\*)|(`([^`]+)`)/g;
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;
139
+ }
140
+ const de = ["aria-label"], ve = { class: "quiz-question-title" }, fe = { key: 0 }, he = { key: 1 }, ge = { key: 2 }, ze = {
141
+ key: 0,
142
+ class: "quiz-hint"
143
+ }, be = ["aria-multiselectable"], xe = ["onClick", "aria-selected", "onKeydown"], we = {
144
+ class: "quiz-indicator",
145
+ "aria-hidden": "true"
146
+ }, qe = {
147
+ key: 0,
148
+ class: "quiz-check"
149
+ }, me = {
150
+ key: 1,
151
+ class: "quiz-empty"
152
+ }, ye = {
153
+ key: 0,
154
+ class: "quiz-check"
155
+ }, ke = {
156
+ key: 1,
157
+ class: "quiz-empty"
158
+ }, _e = { class: "quiz-answer-text" }, Se = { key: 0 }, Ae = { key: 1 }, Qe = { key: 2 }, Ce = { class: "quiz-hint" }, $e = { class: "quiz-input-wrapper" }, Ie = ["disabled", "placeholder", "aria-label"], Me = {
159
+ key: 0,
160
+ class: "quiz-expected"
161
+ }, Pe = {
162
+ key: 2,
163
+ class: "quiz-explanation",
164
+ role: "note"
165
+ }, Ee = { key: 0 }, He = { key: 1 }, Re = { key: 2 }, Ve = /* @__PURE__ */ F({
166
+ __name: "QuizQuestion",
167
+ props: {
168
+ dataQuiz: { type: String, required: !0 }
169
+ },
170
+ setup(e) {
171
+ const t = e, r = _(() => {
172
+ try {
173
+ return JSON.parse(t.dataQuiz);
174
+ } catch {
175
+ return null;
176
+ }
177
+ });
178
+ function u(p) {
179
+ const l = [...p];
180
+ for (let s = l.length - 1; s > 0; s--) {
181
+ const y = Math.floor(Math.random() * (s + 1));
182
+ [l[s], l[y]] = [l[y], l[s]];
183
+ }
184
+ return l;
185
+ }
186
+ const n = M([]);
187
+ function w() {
188
+ if (!r.value || r.value.type === "input") {
189
+ n.value = [];
190
+ return;
191
+ }
192
+ const p = r.value.answers.map((l, s) => ({ ...l, originalIndex: s }));
193
+ n.value = r.value.shuffle ? u(p) : p;
194
+ }
195
+ const v = _(() => r.value ? {
196
+ ...r.value,
197
+ answers: n.value
198
+ } : null), i = _(() => r.value?.type === "input"), x = _(
199
+ () => v.value && !i.value ? v.value.answers.filter((p) => p.correct).length : 0
200
+ ), k = _(() => x.value > 1), f = M(/* @__PURE__ */ new Set()), m = M(""), C = $("quiz-register", null), h = $("quiz-validated", M(!1)), P = $("quiz-reset", M(0)), S = $("quiz-locale"), H = $("quiz-question-id", null), d = $("quiz-save-answer", null), b = $("quiz-get-answer", null), Q = H ? H() : null, B = _(() => i.value ? m.value.trim().length > 0 : f.value.size > 0), T = _(() => {
201
+ if (!v.value || !B.value) return !1;
202
+ if (i.value) {
203
+ const l = m.value.trim().toLowerCase();
204
+ return r.value.expected.some((s) => l === s.trim().toLowerCase());
205
+ }
206
+ const p = new Set(
207
+ v.value.answers.map((l, s) => l.correct ? s : -1).filter((l) => l >= 0)
208
+ );
209
+ if (f.value.size !== p.size) return !1;
210
+ for (const l of f.value)
211
+ if (!p.has(l)) return !1;
212
+ return !0;
213
+ });
214
+ C && C({ answered: B, isCorrect: T }), D(P, () => {
215
+ f.value = /* @__PURE__ */ new Set(), m.value = "", w();
216
+ }), X(() => {
217
+ if (w(), b && Q !== null) {
218
+ const p = b(Q);
219
+ p && (p.type === "input" ? m.value = p.input : p.type === "choice" && (f.value = new Set(p.selected)));
220
+ }
221
+ });
222
+ function W(p) {
223
+ if (h.value) return;
224
+ const l = new Set(f.value);
225
+ k.value ? l.has(p) ? l.delete(p) : l.add(p) : (l.clear(), l.add(p)), f.value = l, K();
226
+ }
227
+ D(m, () => {
228
+ h.value || K();
229
+ });
230
+ function K() {
231
+ !d || Q === null || (i.value ? d(Q, { type: "input", input: m.value }) : d(Q, { type: "choice", selected: [...f.value] }));
232
+ }
233
+ function G(p) {
234
+ if (!h.value)
235
+ return f.value.has(p) ? "quiz-answer selected" : "quiz-answer";
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";
238
+ }
239
+ const Y = _(() => h.value ? T.value ? "quiz-input correct" : "quiz-input wrong" : "quiz-input");
240
+ return (p, l) => v.value ? (a(), o("fieldset", {
241
+ key: 0,
242
+ class: N(["quiz-question", { validated: g(h) }]),
243
+ "aria-label": v.value.question
244
+ }, [
245
+ z("legend", ve, [
246
+ (a(!0), o(q, null, R(g(J)(v.value.question), (s, y) => (a(), o(q, { key: y }, [
247
+ s.type === "bold" ? (a(), o("strong", fe, c(s.value), 1)) : s.type === "italic" ? (a(), o("em", he, c(s.value), 1)) : s.type === "code" ? (a(), o("code", ge, c(s.value), 1)) : (a(), o(q, { key: 3 }, [
248
+ V(c(s.value), 1)
249
+ ], 64))
250
+ ], 64))), 128))
251
+ ]),
252
+ i.value ? I("", !0) : (a(), o(q, { key: 0 }, [
253
+ k.value ? (a(), o("p", ze, c(g(S).multipleHint), 1)) : I("", !0),
254
+ z("ul", {
255
+ class: "quiz-answers",
256
+ role: "listbox",
257
+ "aria-multiselectable": k.value
258
+ }, [
259
+ (a(!0), o(q, null, R(v.value.answers, (s, y) => (a(), o("li", {
260
+ key: s.originalIndex,
261
+ class: N(G(y)),
262
+ onClick: (A) => W(y),
263
+ role: "option",
264
+ "aria-selected": f.value.has(y),
265
+ tabindex: "0",
266
+ onKeydown: [
267
+ O((A) => W(y), ["enter"]),
268
+ O(L((A) => W(y), ["prevent"]), ["space"])
269
+ ]
270
+ }, [
271
+ z("span", we, [
272
+ k.value ? (a(), o(q, { key: 0 }, [
273
+ f.value.has(y) ? (a(), o("span", qe, "✓")) : (a(), o("span", me, "☐"))
274
+ ], 64)) : (a(), o(q, { key: 1 }, [
275
+ f.value.has(y) ? (a(), o("span", ye, "●")) : (a(), o("span", ke, "○"))
276
+ ], 64))
277
+ ]),
278
+ z("span", _e, [
279
+ (a(!0), o(q, null, R(g(J)(s.text), (A, Z) => (a(), o(q, { key: Z }, [
280
+ A.type === "bold" ? (a(), o("strong", Se, c(A.value), 1)) : A.type === "italic" ? (a(), o("em", Ae, c(A.value), 1)) : A.type === "code" ? (a(), o("code", Qe, c(A.value), 1)) : (a(), o(q, { key: 3 }, [
281
+ V(c(A.value), 1)
282
+ ], 64))
283
+ ], 64))), 128))
284
+ ])
285
+ ], 42, xe))), 128))
286
+ ], 8, be)
287
+ ], 64)),
288
+ i.value ? (a(), o(q, { key: 1 }, [
289
+ z("p", Ce, c(g(S).inputHint), 1),
290
+ z("div", $e, [
291
+ ee(z("input", {
292
+ "onUpdate:modelValue": l[0] || (l[0] = (s) => m.value = s),
293
+ class: N(Y.value),
294
+ type: "text",
295
+ disabled: g(h),
296
+ placeholder: g(S).inputPlaceholder,
297
+ "aria-label": v.value.question,
298
+ autocomplete: "off",
299
+ spellcheck: "false",
300
+ onKeydown: l[1] || (l[1] = O(L(() => {
301
+ }, ["prevent"]), ["enter"]))
302
+ }, null, 42, Ie), [
303
+ [te, m.value]
304
+ ]),
305
+ g(h) && !T.value ? (a(), o("p", Me, [
306
+ V(c(g(S).expectedAnswer) + " ", 1),
307
+ z("code", null, c(r.value?.expected[0]), 1)
308
+ ])) : I("", !0)
309
+ ])
310
+ ], 64)) : I("", !0),
311
+ g(h) && v.value.explanation ? (a(), o("div", Pe, [
312
+ z("strong", null, c(g(S).explanation), 1),
313
+ (a(!0), o(q, null, R(g(J)(v.value.explanation), (s, y) => (a(), o(q, { key: y }, [
314
+ s.type === "bold" ? (a(), o("strong", Ee, c(s.value), 1)) : s.type === "italic" ? (a(), o("em", He, c(s.value), 1)) : s.type === "code" ? (a(), o("code", Re, c(s.value), 1)) : (a(), o(q, { key: 3 }, [
315
+ V(c(s.value), 1)
316
+ ], 64))
317
+ ], 64))), 128))
318
+ ])) : I("", !0)
319
+ ], 10, de)) : I("", !0);
320
+ }
321
+ }), Ne = {
322
+ class: "quiz-page",
323
+ role: "region",
324
+ "aria-label": "Quiz"
325
+ }, Te = ["aria-valuenow", "aria-valuemax", "aria-label"], We = { class: "quiz-progress-track" }, Oe = {
326
+ class: "quiz-progress-label",
327
+ "aria-live": "polite"
328
+ }, je = { class: "quiz-actions" }, Je = ["disabled"], Be = ["aria-label"], Ke = { class: "quiz-score-value" }, De = { class: "quiz-score-label" }, Le = /* @__PURE__ */ F({
329
+ __name: "QuizPage",
330
+ setup(e) {
331
+ const t = $("quiz-locale"), r = M([]), u = M(!1), n = typeof window < "u" ? "quiz-state:" + window.location.pathname : "";
332
+ S();
333
+ let w = 0;
334
+ E("quiz-validated", u), E("quiz-register", (d) => {
335
+ r.value.push(d);
336
+ }), E("quiz-question-id", () => w++), E("quiz-save-answer", (d, b) => {
337
+ if (n)
338
+ try {
339
+ sessionStorage.setItem(n + ":q" + d, JSON.stringify(b));
340
+ } catch {
341
+ }
342
+ }), E("quiz-get-answer", (d) => {
343
+ if (!n) return null;
344
+ try {
345
+ const b = sessionStorage.getItem(n + ":q" + d);
346
+ return b ? JSON.parse(b) : null;
347
+ } catch {
348
+ return null;
349
+ }
350
+ });
351
+ const v = M(0);
352
+ E("quiz-reset", v);
353
+ const i = _(() => r.value.length), x = _(
354
+ () => r.value.filter((d) => d.answered).length
355
+ ), k = _(
356
+ () => r.value.filter((d) => d.isCorrect).length
357
+ ), f = _(() => x.value === i.value), m = _(
358
+ () => i.value ? Math.round(x.value / i.value * 100) : 0
359
+ );
360
+ function C() {
361
+ u.value = !0, P();
362
+ }
363
+ function h() {
364
+ u.value = !1, v.value++, H();
365
+ }
366
+ function P() {
367
+ if (n)
368
+ try {
369
+ const d = { validated: u.value, ts: Date.now() };
370
+ sessionStorage.setItem(n, JSON.stringify(d));
371
+ } catch {
372
+ }
373
+ }
374
+ function S() {
375
+ if (n)
376
+ try {
377
+ const d = sessionStorage.getItem(n);
378
+ if (!d) return;
379
+ const b = JSON.parse(d);
380
+ b && b.validated && (u.value = !0);
381
+ } catch {
382
+ }
383
+ }
384
+ function H() {
385
+ if (n)
386
+ try {
387
+ const d = [];
388
+ for (let b = 0; b < sessionStorage.length; b++) {
389
+ const Q = sessionStorage.key(b);
390
+ Q && Q.startsWith(n) && d.push(Q);
391
+ }
392
+ d.forEach((b) => sessionStorage.removeItem(b));
393
+ } catch {
394
+ }
395
+ }
396
+ return (d, b) => (a(), o("div", Ne, [
397
+ z("div", {
398
+ class: "quiz-progress-bar",
399
+ role: "progressbar",
400
+ "aria-valuenow": x.value,
401
+ "aria-valuemin": 0,
402
+ "aria-valuemax": i.value,
403
+ "aria-label": x.value + " / " + i.value + " " + g(t).answered
404
+ }, [
405
+ z("div", We, [
406
+ z("div", {
407
+ class: N(["quiz-progress-fill", { complete: m.value === 100 }]),
408
+ style: re({ width: m.value + "%" })
409
+ }, null, 6)
410
+ ]),
411
+ z("span", Oe, c(x.value) + " / " + c(i.value) + " " + c(g(t).answered), 1)
412
+ ], 8, Te),
413
+ ne(d.$slots, "default"),
414
+ z("div", je, [
415
+ u.value ? I("", !0) : (a(), o("button", {
416
+ key: 0,
417
+ class: "quiz-btn quiz-btn-validate",
418
+ disabled: !f.value,
419
+ onClick: C
420
+ }, c(g(t).validate), 9, Je)),
421
+ u.value ? (a(), o(q, { key: 1 }, [
422
+ z("div", {
423
+ class: "quiz-score",
424
+ role: "status",
425
+ "aria-live": "polite",
426
+ "aria-label": k.value + " / " + i.value + " " + g(t).correctAnswers(k.value)
427
+ }, [
428
+ z("span", Ke, c(k.value) + " / " + c(i.value), 1),
429
+ z("span", De, c(g(t).correctAnswers(k.value)) + " (" + c(i.value ? Math.round(k.value / i.value * 100) : 0) + "%) ", 1)
430
+ ], 8, Be),
431
+ z("button", {
432
+ class: "quiz-btn quiz-btn-reset",
433
+ onClick: h
434
+ }, c(g(t).reset), 1)
435
+ ], 64)) : I("", !0)
436
+ ])
437
+ ]));
438
+ }
439
+ });
440
+ function Ge(e, t = "en") {
441
+ ie(), e.provide("quiz-locale", pe(t)), e.component("QuizQuestion", Ve), e.component("QuizPage", Le);
442
+ }
443
+ export {
444
+ Le as QuizPage,
445
+ Ve as QuizQuestion,
446
+ Ge as enhanceAppWithQuiz,
447
+ pe as getLocale,
448
+ U as locales,
449
+ Fe as quizMarkdownPlugin
450
+ };
451
+ //# sourceMappingURL=vitepress-plugin-quiz.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vitepress-plugin-quiz.js","sources":["../src/styleManager.ts","../src/md-plugin.ts","../src/locales.ts","../src/utils.ts","../src/QuizQuestion.vue","../src/QuizPage.vue","../src/index.ts"],"sourcesContent":["import quizCssInline from \"./quiz.css?inline\"\n\nlet stylesInjected = false\n\nexport function ensureStylesInjected(): void {\n if (typeof document === \"undefined\") return\n if (stylesInjected) return\n const styleId = \"vitepress-plugin-quiz-styles\"\n if (document.getElementById(styleId)) {\n stylesInjected = true\n return\n }\n const style = document.createElement(\"style\")\n style.id = styleId\n style.textContent = quizCssInline\n document.head.appendChild(style)\n stylesInjected = true\n}\n","import type MarkdownIt from \"markdown-it\"\nimport type StateBlock from \"markdown-it/lib/rules_block/state_block.mjs\"\nimport type { QuizData, QuizAnswer } from \"./types/quiz\"\n\nconst QUIZ_RE = /^:::quiz\\s*$/\nconst CLOSE_RE = /^:::\\s*$/\n\n/**\n * Register the quiz block rule on a markdown-it instance.\n * Use in VitePress config:\n * markdown: { config(md) { md.use(quizMarkdownPlugin) } }\n */\nexport function quizMarkdownPlugin(md: MarkdownIt): void {\n const escapeHtml = md.utils.escapeHtml\n\n md.block.ruler.before(\n \"fence\",\n \"quiz\",\n (state, startLine, endLine, silent) =>\n quizBlockRule(state, startLine, endLine, silent, escapeHtml),\n { alt: [\"paragraph\", \"reference\", \"blockquote\", \"list\"] },\n )\n\n md.renderer.rules.quiz = (tokens, idx) => tokens[idx].content\n\n // Wrap entire token stream with <QuizPage>…</QuizPage> if quiz tokens exist\n md.core.ruler.push(\"quiz_page_wrap\", (state) => {\n const hasQuiz = state.tokens.some((t) => t.type === \"quiz\")\n if (!hasQuiz) return\n\n const open = new state.Token(\"html_block\", \"\", 0)\n open.content = \"<QuizPage>\\n\"\n open.block = true\n\n const close = new state.Token(\"html_block\", \"\", 0)\n close.content = \"</QuizPage>\\n\"\n close.block = true\n\n state.tokens.unshift(open)\n state.tokens.push(close)\n })\n}\n\n/* ── block rule ──────────────────────────────────────────────────────── */\n\nfunction quizBlockRule(\n state: StateBlock,\n startLine: number,\n endLine: number,\n silent: boolean,\n escapeHtml: (s: string) => string,\n): boolean {\n const startPos = state.bMarks[startLine] + state.tShift[startLine]\n const startMax = state.eMarks[startLine]\n const lineText = state.src.slice(startPos, startMax)\n\n if (!QUIZ_RE.test(lineText)) return false\n if (silent) return true\n\n let nextLine = startLine + 1\n let found = false\n while (nextLine < endLine) {\n const pos = state.bMarks[nextLine] + state.tShift[nextLine]\n const max = state.eMarks[nextLine]\n const line = state.src.slice(pos, max)\n if (CLOSE_RE.test(line)) {\n found = true\n break\n }\n nextLine++\n }\n if (!found) return false\n\n const innerLines: string[] = []\n for (let i = startLine + 1; i < nextLine; i++) {\n const pos = state.bMarks[i] + state.tShift[i]\n const max = state.eMarks[i]\n innerLines.push(state.src.slice(pos, max))\n }\n\n const data = parseQuizBlock(innerLines)\n if (!data) return false\n\n const token = state.push(\"quiz\", \"\", 0)\n token.content = renderQuizComponent(data, escapeHtml)\n token.map = [startLine, nextLine + 1]\n token.block = true\n\n state.line = nextLine + 1\n return true\n}\n\n/* ── parser ──────────────────────────────────────────────────────────── */\n\nexport function parseQuizBlock(lines: string[]): QuizData | null {\n let question = \"\"\n const answers: QuizAnswer[] = []\n let explanation = \"\"\n const expected: string[] = []\n let shuffle = false\n\n for (const raw of lines) {\n const line = raw.trim()\n if (!line) continue\n\n if (line.startsWith(\"question:\")) {\n question = line.slice(\"question:\".length).trim()\n } else if (line.startsWith(\"answer-correct:\")) {\n answers.push({ text: line.slice(\"answer-correct:\".length).trim(), correct: true })\n } else if (line.startsWith(\"answer-input:\")) {\n expected.push(line.slice(\"answer-input:\".length).trim())\n } else if (line.startsWith(\"answer:\")) {\n answers.push({ text: line.slice(\"answer:\".length).trim(), correct: false })\n } else if (line.startsWith(\"explanation:\")) {\n explanation = line.slice(\"explanation:\".length).trim()\n } else if (line.startsWith(\"explication:\")) {\n // legacy French alias\n explanation = line.slice(\"explication:\".length).trim()\n } else if (line.startsWith(\"shuffle:\")) {\n shuffle = line.slice(\"shuffle:\".length).trim().toLowerCase() === \"true\"\n }\n }\n\n if (!question) return null\n\n if (expected.length > 0) {\n return { question, type: \"input\", answers: [], expected, explanation, shuffle: false }\n }\n\n if (answers.length === 0) return null\n return { question, type: \"choice\", answers, expected: [], explanation, shuffle }\n}\n\n/* ── renderer ────────────────────────────────────────────────────────── */\n\nfunction renderQuizComponent(data: QuizData, escapeHtml: (s: string) => string): string {\n const json = JSON.stringify(data)\n const escaped = escapeHtml(json)\n return `<QuizQuestion data-quiz=\"${escaped}\" />\\n`\n}\n","import type { QuizLocale } from \"./types/quiz\"\n\nexport const locales: Record<string, QuizLocale> = {\n en: {\n answered: \"answered\",\n validate: \"Validate\",\n reset: \"Restart\",\n correctAnswers: (n) => `correct answer${n !== 1 ? \"s\" : \"\"}`,\n multipleHint: \"Multiple answers possible\",\n explanation: \"Explanation: \",\n inputHint: \"Type your answer\",\n inputPlaceholder: \"Your answer…\",\n expectedAnswer: \"Expected answer:\",\n },\n fr: {\n answered: \"répondue(s)\",\n validate: \"Valider\",\n reset: \"Recommencer\",\n correctAnswers: (n) => `réponse${n > 1 ? \"s\" : \"\"} correcte${n > 1 ? \"s\" : \"\"}`,\n multipleHint: \"Plusieurs réponses possibles\",\n explanation: \"Explication : \",\n inputHint: \"Saisissez votre réponse\",\n inputPlaceholder: \"Votre réponse…\",\n expectedAnswer: \"Réponse attendue :\",\n },\n de: {\n answered: \"beantwortet\",\n validate: \"Überprüfen\",\n reset: \"Neu starten\",\n correctAnswers: (n) => `richtige Antwort${n !== 1 ? \"en\" : \"\"}`,\n multipleHint: \"Mehrere Antworten möglich\",\n explanation: \"Erklärung:\",\n inputHint: \"Geben Sie Ihre Antwort ein\",\n inputPlaceholder: \"Ihre Antwort…\",\n expectedAnswer: \"Erwartete Antwort:\",\n },\n it: {\n answered: \"risposta/e\",\n validate: \"Verifica\",\n reset: \"Ricominciare\",\n correctAnswers: (n) => `rispost${n !== 1 ? \"e corrette\" : \"a corretta\"}`,\n multipleHint: \"Più risposte possibili\",\n explanation: \"Spiegazione: \",\n inputHint: \"Digita la tua risposta\",\n inputPlaceholder: \"La tua risposta…\",\n expectedAnswer: \"Risposta attesa:\",\n },\n es: {\n answered: \"respondida(s)\",\n validate: \"Validar\",\n reset: \"Reiniciar\",\n correctAnswers: (n) => `respuesta${n !== 1 ? \"s correctas\" : \" correcta\"}`,\n multipleHint: \"Varias respuestas posibles\",\n explanation: \"Explicación: \",\n inputHint: \"Escribe tu respuesta\",\n inputPlaceholder: \"Tu respuesta…\",\n expectedAnswer: \"Respuesta esperada:\",\n },\n}\n\n/**\n * Get locale strings for a given language code.\n * Falls back to English if the language is not found.\n */\nexport function getLocale(lang = \"en\"): QuizLocale {\n return locales[lang] ?? locales.en\n}\n","/**\n * Inline markdown part — result of {@link parseRichText}.\n */\nexport type RichPart = { type: \"text\" | \"bold\" | \"italic\" | \"code\"; value: string }\n\n/**\n * Parse inline markdown subsets: **bold**, *italic*, `code` → typed parts array.\n * Used for question titles, answer text, and explanations.\n */\nexport function parseRichText(text: string): RichPart[] {\n const parts: RichPart[] = []\n const re = /(\\*\\*(.+?)\\*\\*)|(\\*(.+?)\\*)|(`([^`]+)`)/g\n let last = 0\n let m\n while ((m = re.exec(text)) !== null) {\n if (m.index > last) parts.push({ type: \"text\", value: text.slice(last, m.index) })\n if (m[2]) parts.push({ type: \"bold\", value: m[2] })\n else if (m[4]) parts.push({ type: \"italic\", value: m[4] })\n else if (m[6]) parts.push({ type: \"code\", value: m[6] })\n last = re.lastIndex\n }\n if (last < text.length) parts.push({ type: \"text\", value: text.slice(last) })\n return parts\n}\n","<script setup lang=\"ts\">\nimport { ref, computed, inject, watch, onMounted } from \"vue\"\nimport type { QuizData, QuizAnswer, QuizLocale, SavedAnswer } from \"./types/quiz\"\n\nconst props = defineProps({\n dataQuiz: { type: String, required: true },\n})\n\nconst rawQuiz = computed<QuizData | null>(() => {\n try {\n return JSON.parse(props.dataQuiz) as QuizData\n } catch {\n return null\n }\n})\n\n// Shuffle helper (Fisher-Yates)\nfunction shuffleArray<T>(arr: T[]): T[] {\n const a = [...arr]\n for (let i = a.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1))\n ;[a[i], a[j]] = [a[j], a[i]]\n }\n return a\n}\n\n// Shuffled answers — computed once at mount, re-shuffled on reset\nconst shuffledAnswers = ref<(QuizAnswer & { originalIndex: number })[]>([])\nfunction initAnswers() {\n if (!rawQuiz.value || rawQuiz.value.type === \"input\") {\n shuffledAnswers.value = []\n return\n }\n const indexed = rawQuiz.value.answers.map((a, i) => ({ ...a, originalIndex: i }))\n shuffledAnswers.value = rawQuiz.value.shuffle ? shuffleArray(indexed) : indexed\n}\n\n// Quiz data with shuffled answers\nconst quiz = computed(() => {\n if (!rawQuiz.value) return null\n return {\n ...rawQuiz.value,\n answers: shuffledAnswers.value,\n }\n})\n\nconst isInputMode = computed(() => rawQuiz.value?.type === 'input')\n\nconst correctCount = computed(() =>\n quiz.value && !isInputMode.value\n ? quiz.value.answers.filter((a) => a.correct).length\n : 0\n)\nconst isMultiple = computed(() => correctCount.value > 1)\n\n// Selected answer indices (for choice mode)\nconst selected = ref(new Set<number>())\n// Text input value (for fill-in-the-blank mode)\nconst inputValue = ref(\"\")\n\n// Registration with parent QuizPage\nconst register = inject<((q: { answered: typeof answered; isCorrect: typeof isCorrect }) => void) | null>(\"quiz-register\", null)\nconst validated = inject<ReturnType<typeof ref<boolean>>>(\"quiz-validated\", ref(false))\nconst resetCounter = inject<ReturnType<typeof ref<number>>>(\"quiz-reset\", ref(0))\nconst t = inject<QuizLocale>(\"quiz-locale\")!\n\n// Per-question persistence\nconst getQuestionId = inject<(() => number) | null>(\"quiz-question-id\", null)\nconst saveAnswer = inject<((id: number, data: SavedAnswer) => void) | null>(\"quiz-save-answer\", null)\nconst getAnswer = inject<((id: number) => SavedAnswer | null) | null>(\"quiz-get-answer\", null)\nconst myId: number | null = getQuestionId ? getQuestionId() : null\n\nconst answered = computed(() => {\n if (isInputMode.value) return inputValue.value.trim().length > 0\n return selected.value.size > 0\n})\n\nconst isCorrect = computed(() => {\n if (!quiz.value || !answered.value) return false\n\n if (isInputMode.value) {\n // Case-insensitive comparison against any accepted variant\n const input = inputValue.value.trim().toLowerCase()\n return rawQuiz.value!.expected.some((e) => input === e.trim().toLowerCase())\n }\n\n const correctIndices = new Set(\n quiz.value.answers\n .map((a, i) => (a.correct ? i : -1))\n .filter((i) => i >= 0)\n )\n if (selected.value.size !== correctIndices.size) return false\n for (const idx of selected.value) {\n if (!correctIndices.has(idx)) return false\n }\n return true\n})\n\n// Register this question with the parent page\nif (register) {\n register({ answered, isCorrect })\n}\n\n// Watch for reset from parent\nwatch(resetCounter, () => {\n selected.value = new Set()\n inputValue.value = ''\n initAnswers()\n})\n\nonMounted(() => {\n initAnswers()\n // Restore saved answer state\n if (getAnswer && myId !== null) {\n const saved = getAnswer(myId)\n if (saved) {\n if (saved.type === \"input\") {\n inputValue.value = saved.input\n } else if (saved.type === \"choice\") {\n selected.value = new Set(saved.selected)\n }\n }\n }\n})\n\nfunction toggle(idx: number) {\n if (validated.value) return\n const next = new Set(selected.value)\n if (isMultiple.value) {\n if (next.has(idx)) next.delete(idx)\n else next.add(idx)\n } else {\n next.clear()\n next.add(idx)\n }\n selected.value = next\n persistState()\n}\n\n// Save input value on change\nwatch(inputValue, () => {\n if (!validated.value) persistState()\n})\n\nfunction persistState() {\n if (!saveAnswer || myId === null) return\n if (isInputMode.value) {\n saveAnswer(myId, { type: \"input\", input: inputValue.value })\n } else {\n saveAnswer(myId, { type: \"choice\", selected: [...selected.value] })\n }\n}\n\nfunction answerClass(idx: number): string {\n if (!validated.value) {\n return selected.value.has(idx) ? \"quiz-answer selected\" : \"quiz-answer\"\n }\n const answer = quiz.value!.answers[idx]\n const wasPicked = selected.value.has(idx)\n if (answer.correct && wasPicked) return \"quiz-answer correct\"\n if (answer.correct && !wasPicked) return \"quiz-answer missed\"\n if (!answer.correct && wasPicked) return \"quiz-answer wrong\"\n return \"quiz-answer\"\n}\n\nconst inputClass = computed(() => {\n if (!validated.value) return \"quiz-input\"\n return isCorrect.value ? \"quiz-input correct\" : \"quiz-input wrong\"\n})\n\nimport { parseRichText, type RichPart } from './utils'\n</script>\n\n<template>\n <fieldset v-if=\"quiz\" class=\"quiz-question\" :class=\"{ validated: validated }\" :aria-label=\"quiz.question\">\n <legend class=\"quiz-question-title\">\n <template v-for=\"(part, pi) in parseRichText(quiz.question)\" :key=\"pi\">\n <strong v-if=\"part.type === 'bold'\">{{ part.value }}</strong>\n <em v-else-if=\"part.type === 'italic'\">{{ part.value }}</em>\n <code v-else-if=\"part.type === 'code'\">{{ part.value }}</code>\n <template v-else>{{ part.value }}</template>\n </template>\n </legend>\n\n <!-- Choice mode -->\n <template v-if=\"!isInputMode\">\n <p v-if=\"isMultiple\" class=\"quiz-hint\">{{ t.multipleHint }}</p>\n <ul class=\"quiz-answers\" role=\"listbox\" :aria-multiselectable=\"isMultiple\">\n <li\n v-for=\"(answer, idx) in quiz.answers\"\n :key=\"answer.originalIndex\"\n :class=\"answerClass(idx)\"\n @click=\"toggle(idx)\"\n role=\"option\"\n :aria-selected=\"selected.has(idx)\"\n tabindex=\"0\"\n @keydown.enter=\"toggle(idx)\"\n @keydown.space.prevent=\"toggle(idx)\"\n >\n <span class=\"quiz-indicator\" aria-hidden=\"true\">\n <template v-if=\"isMultiple\">\n <span v-if=\"selected.has(idx)\" class=\"quiz-check\">✓</span>\n <span v-else class=\"quiz-empty\">☐</span>\n </template>\n <template v-else>\n <span v-if=\"selected.has(idx)\" class=\"quiz-check\">●</span>\n <span v-else class=\"quiz-empty\">○</span>\n </template>\n </span>\n <span class=\"quiz-answer-text\">\n <template v-for=\"(part, pi) in parseRichText(answer.text)\" :key=\"pi\">\n <strong v-if=\"part.type === 'bold'\">{{ part.value }}</strong>\n <em v-else-if=\"part.type === 'italic'\">{{ part.value }}</em>\n <code v-else-if=\"part.type === 'code'\">{{ part.value }}</code>\n <template v-else>{{ part.value }}</template>\n </template>\n </span>\n </li>\n </ul>\n </template>\n\n <!-- Fill-in-the-blank mode -->\n <template v-if=\"isInputMode\">\n <p class=\"quiz-hint\">{{ t.inputHint }}</p>\n <div class=\"quiz-input-wrapper\">\n <input\n v-model=\"inputValue\"\n :class=\"inputClass\"\n type=\"text\"\n :disabled=\"validated\"\n :placeholder=\"t.inputPlaceholder\"\n :aria-label=\"quiz.question\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n @keydown.enter.prevent\n />\n <p v-if=\"validated && !isCorrect\" class=\"quiz-expected\">\n {{ t.expectedAnswer }} <code>{{ rawQuiz?.expected[0] }}</code>\n </p>\n </div>\n </template>\n\n <!-- Explanation (rich text: supports **bold** and `code`) -->\n <div v-if=\"validated && quiz.explanation\" class=\"quiz-explanation\" role=\"note\">\n <strong>{{ t.explanation }}</strong>\n <template v-for=\"(part, pi) in parseRichText(quiz.explanation)\" :key=\"pi\">\n <strong v-if=\"part.type === 'bold'\">{{ part.value }}</strong>\n <em v-else-if=\"part.type === 'italic'\">{{ part.value }}</em>\n <code v-else-if=\"part.type === 'code'\">{{ part.value }}</code>\n <template v-else>{{ part.value }}</template>\n </template>\n </div>\n </fieldset>\n</template>\n","<script setup lang=\"ts\">\nimport { ref, computed, provide, inject } from \"vue\"\nimport type { QuizLocale, QuizState, SavedAnswer } from \"./types/quiz\"\n\nconst t = inject<QuizLocale>(\"quiz-locale\")!\nconst questions = ref<QuizState[]>([])\nconst validated = ref(false)\n\n// Generate a storage key from the page path — set eagerly so children can read on mount\n// (Vue mounts children before parent, so onMounted would be too late)\nconst storageKey = typeof window !== 'undefined'\n ? 'quiz-state:' + window.location.pathname\n : ''\n\n// Restore quiz-level state immediately so validated is set before children mount\nrestoreState()\n\n// Question index counter for stable per-question storage keys\nlet questionIdx = 0\n\nprovide(\"quiz-validated\", validated)\nprovide(\"quiz-register\", (q: QuizState) => {\n questions.value.push(q)\n})\n\n// Per-question persistence: each question gets a unique sub-key\nprovide(\"quiz-question-id\", () => questionIdx++)\nprovide(\"quiz-save-answer\", (qId: number, data: SavedAnswer) => {\n if (!storageKey) return\n try {\n sessionStorage.setItem(storageKey + \":q\" + qId, JSON.stringify(data))\n } catch { /* ignore */ }\n})\nprovide(\"quiz-get-answer\", (qId: number): SavedAnswer | null => {\n if (!storageKey) return null\n try {\n const raw = sessionStorage.getItem(storageKey + \":q\" + qId)\n return raw ? JSON.parse(raw) : null\n } catch { return null }\n})\n\n// Provide a reset trigger for child components\nconst resetCounter = ref(0)\nprovide(\"quiz-reset\", resetCounter)\n\nconst totalQuestions = computed(() => questions.value.length)\nconst answeredCount = computed(() =>\n questions.value.filter((q) => q.answered).length\n)\nconst correctCount = computed(() =>\n questions.value.filter((q) => q.isCorrect).length\n)\nconst allAnswered = computed(() => answeredCount.value === totalQuestions.value)\nconst progressPct = computed(() =>\n totalQuestions.value ? Math.round((answeredCount.value / totalQuestions.value) * 100) : 0\n)\n\nfunction validate() {\n validated.value = true\n saveState()\n}\n\nfunction reset() {\n validated.value = false\n resetCounter.value++\n clearState()\n}\n\n/* ── sessionStorage persistence ───────────────────────────────────── */\nfunction saveState() {\n if (!storageKey) return\n try {\n const data = { validated: validated.value, ts: Date.now() }\n sessionStorage.setItem(storageKey, JSON.stringify(data))\n } catch { /* storage full or unavailable */ }\n}\n\nfunction restoreState() {\n if (!storageKey) return\n try {\n const raw = sessionStorage.getItem(storageKey)\n if (!raw) return\n const data = JSON.parse(raw)\n if (data && data.validated) {\n validated.value = true\n }\n } catch { /* corrupted – ignore */ }\n}\n\nfunction clearState() {\n if (!storageKey) return\n try {\n const keysToRemove: string[] = []\n for (let i = 0; i < sessionStorage.length; i++) {\n const key = sessionStorage.key(i)\n if (key && key.startsWith(storageKey)) {\n keysToRemove.push(key)\n }\n }\n keysToRemove.forEach((k) => sessionStorage.removeItem(k))\n } catch { /* ignore */ }\n}\n</script>\n\n<template>\n <div class=\"quiz-page\" role=\"region\" aria-label=\"Quiz\">\n <div class=\"quiz-progress-bar\" role=\"progressbar\"\n :aria-valuenow=\"answeredCount\"\n :aria-valuemin=\"0\"\n :aria-valuemax=\"totalQuestions\"\n :aria-label=\"answeredCount + ' / ' + totalQuestions + ' ' + t.answered\"\n >\n <div class=\"quiz-progress-track\">\n <div\n class=\"quiz-progress-fill\"\n :style=\"{ width: progressPct + '%' }\"\n :class=\"{ complete: progressPct === 100 }\"\n ></div>\n </div>\n <span class=\"quiz-progress-label\" aria-live=\"polite\">\n {{ answeredCount }} / {{ totalQuestions }} {{ t.answered }}\n </span>\n </div>\n\n <slot />\n\n <div class=\"quiz-actions\">\n <button\n v-if=\"!validated\"\n class=\"quiz-btn quiz-btn-validate\"\n :disabled=\"!allAnswered\"\n @click=\"validate\"\n >\n {{ t.validate }}\n </button>\n\n <template v-if=\"validated\">\n <div class=\"quiz-score\" role=\"status\" aria-live=\"polite\"\n :aria-label=\"correctCount + ' / ' + totalQuestions + ' ' + t.correctAnswers(correctCount)\"\n >\n <span class=\"quiz-score-value\">{{ correctCount }} / {{ totalQuestions }}</span>\n <span class=\"quiz-score-label\">\n {{ t.correctAnswers(correctCount) }}\n ({{ totalQuestions ? Math.round((correctCount / totalQuestions) * 100) : 0 }}%)\n </span>\n </div>\n <button class=\"quiz-btn quiz-btn-reset\" @click=\"reset\">\n {{ t.reset }}\n </button>\n </template>\n </div>\n </div>\n</template>\n","import type { App } from \"vue\"\nimport { ensureStylesInjected } from \"./styleManager\"\n\nexport { quizMarkdownPlugin } from \"./md-plugin\"\nexport { getLocale, locales } from \"./locales\"\nexport type { QuizData, QuizAnswer, QuizLocale, QuizState, SavedAnswer } from \"./types/quiz\"\n\nimport QuizQuestion from \"./QuizQuestion.vue\"\nimport QuizPage from \"./QuizPage.vue\"\nimport { getLocale as _getLocale } from \"./locales\"\n\nexport { QuizQuestion, QuizPage }\n\n/**\n * Register quiz components and locale in a VitePress `enhanceApp` hook.\n *\n * @example\n * // .vitepress/theme/index.ts\n * import { enhanceAppWithQuiz } from 'vitepress-plugin-quiz'\n * export default {\n * enhanceApp({ app }) {\n * enhanceAppWithQuiz(app) // English (default)\n * enhanceAppWithQuiz(app, 'fr') // French\n * }\n * }\n */\nexport function enhanceAppWithQuiz(app: App, lang = \"en\"): void {\n ensureStylesInjected()\n app.provide(\"quiz-locale\", _getLocale(lang))\n app.component(\"QuizQuestion\", QuizQuestion)\n app.component(\"QuizPage\", QuizPage)\n}\n"],"names":["stylesInjected","ensureStylesInjected","styleId","style","quizCssInline","QUIZ_RE","CLOSE_RE","quizMarkdownPlugin","md","escapeHtml","state","startLine","endLine","silent","quizBlockRule","tokens","idx","t","open","close","startPos","startMax","lineText","nextLine","found","pos","max","line","innerLines","i","data","parseQuizBlock","token","renderQuizComponent","lines","question","answers","explanation","expected","shuffle","raw","json","locales","n","getLocale","lang","parseRichText","text","parts","re","last","m","props","__props","rawQuiz","computed","shuffleArray","arr","a","j","shuffledAnswers","ref","initAnswers","indexed","quiz","isInputMode","correctCount","isMultiple","selected","inputValue","register","inject","validated","resetCounter","getQuestionId","saveAnswer","getAnswer","myId","answered","isCorrect","input","e","correctIndices","watch","onMounted","saved","toggle","next","persistState","answerClass","answer","wasPicked","inputClass","_createElementBlock","_normalizeClass","_unref","_createElementVNode","_hoisted_2","_Fragment","_renderList","part","pi","_hoisted_3","_toDisplayString","_hoisted_4","_hoisted_5","_createTextVNode","_openBlock","_hoisted_6","$event","_withKeys","_withModifiers","_hoisted_9","_hoisted_10","_hoisted_11","_hoisted_12","_hoisted_13","_hoisted_14","_hoisted_15","_hoisted_16","_hoisted_17","_hoisted_18","_hoisted_19","_hoisted_21","_hoisted_22","_hoisted_23","_hoisted_24","_hoisted_25","questions","storageKey","restoreState","questionIdx","provide","q","qId","totalQuestions","answeredCount","allAnswered","progressPct","validate","saveState","reset","clearState","keysToRemove","key","k","_hoisted_1","_renderSlot","_ctx","_hoisted_8","enhanceAppWithQuiz","app","_getLocale","QuizQuestion","QuizPage"],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ (function(w,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],e):(w=typeof globalThis<"u"?globalThis:w||self,e(w.VitepressPluginQuiz={},w.Vue))})(this,(function(w,e){"use strict";const I=".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)}";let E=!1;function P(){if(typeof document>"u"||E)return;const t="vitepress-plugin-quiz-styles";if(document.getElementById(t)){E=!0;return}const n=document.createElement("style");n.id=t,n.textContent=I,document.head.appendChild(n),E=!0}const j=/^:::quiz\s*$/,F=/^:::\s*$/;function T(t){const n=t.utils.escapeHtml;t.block.ruler.before("fence","quiz",(r,l,o,h)=>H(r,l,o,h,n),{alt:["paragraph","reference","blockquote","list"]}),t.renderer.rules.quiz=(r,l)=>r[l].content,t.core.ruler.push("quiz_page_wrap",r=>{if(!r.tokens.some(d=>d.type==="quiz"))return;const o=new r.Token("html_block","",0);o.content=`<QuizPage>
2
+ `,o.block=!0;const h=new r.Token("html_block","",0);h.content=`</QuizPage>
3
+ `,h.block=!0,r.tokens.unshift(o),r.tokens.push(h)})}function H(t,n,r,l,o){const h=t.bMarks[n]+t.tShift[n],d=t.eMarks[n],i=t.src.slice(h,d);if(!j.test(i))return!1;if(l)return!0;let m=n+1,b=!1;for(;m<r;){const f=t.bMarks[m]+t.tShift[m],v=t.eMarks[m],x=t.src.slice(f,v);if(F.test(x)){b=!0;break}m++}if(!b)return!1;const u=[];for(let f=n+1;f<m;f++){const v=t.bMarks[f]+t.tShift[f],x=t.eMarks[f];u.push(t.src.slice(v,x))}const k=R(u);if(!k)return!1;const _=t.push("quiz","",0);return _.content=W(k,o),_.map=[n,m+1],_.block=!0,t.line=m+1,!0}function R(t){let n="";const r=[];let l="";const o=[];let h=!1;for(const d of t){const i=d.trim();i&&(i.startsWith("question:")?n=i.slice(9).trim():i.startsWith("answer-correct:")?r.push({text:i.slice(15).trim(),correct:!0}):i.startsWith("answer-input:")?o.push(i.slice(13).trim()):i.startsWith("answer:")?r.push({text:i.slice(7).trim(),correct:!1}):i.startsWith("explanation:")||i.startsWith("explication:")?l=i.slice(12).trim():i.startsWith("shuffle:")&&(h=i.slice(8).trim().toLowerCase()==="true"))}return n?o.length>0?{question:n,type:"input",answers:[],expected:o,explanation:l,shuffle:!1}:r.length===0?null:{question:n,type:"choice",answers:r,expected:[],explanation:l,shuffle:h}:null}function W(t,n){const r=JSON.stringify(t);return`<QuizQuestion data-quiz="${n(r)}" />
4
+ `}const S={en:{answered:"answered",validate:"Validate",reset:"Restart",correctAnswers:t=>`correct answer${t!==1?"s":""}`,multipleHint:"Multiple answers possible",explanation:"Explanation: ",inputHint:"Type your answer",inputPlaceholder:"Your answer…",expectedAnswer:"Expected answer:"},fr:{answered:"répondue(s)",validate:"Valider",reset:"Recommencer",correctAnswers:t=>`réponse${t>1?"s":""} correcte${t>1?"s":""}`,multipleHint:"Plusieurs réponses possibles",explanation:"Explication : ",inputHint:"Saisissez votre réponse",inputPlaceholder:"Votre réponse…",expectedAnswer:"Réponse attendue :"},de:{answered:"beantwortet",validate:"Überprüfen",reset:"Neu starten",correctAnswers:t=>`richtige Antwort${t!==1?"en":""}`,multipleHint:"Mehrere Antworten möglich",explanation:"Erklärung:",inputHint:"Geben Sie Ihre Antwort ein",inputPlaceholder:"Ihre Antwort…",expectedAnswer:"Erwartete Antwort:"},it:{answered:"risposta/e",validate:"Verifica",reset:"Ricominciare",correctAnswers:t=>`rispost${t!==1?"e corrette":"a corretta"}`,multipleHint:"Più risposte possibili",explanation:"Spiegazione: ",inputHint:"Digita la tua risposta",inputPlaceholder:"La tua risposta…",expectedAnswer:"Risposta attesa:"},es:{answered:"respondida(s)",validate:"Validar",reset:"Reiniciar",correctAnswers:t=>`respuesta${t!==1?"s correctas":" correcta"}`,multipleHint:"Varias respuestas posibles",explanation:"Explicación: ",inputHint:"Escribe tu respuesta",inputPlaceholder:"Tu respuesta…",expectedAnswer:"Respuesta esperada:"}};function D(t="en"){return S[t]??S.en}function V(t){const n=[],r=/(\*\*(.+?)\*\*)|(\*(.+?)\*)|(`([^`]+)`)/g;let l=0,o;for(;(o=r.exec(t))!==null;)o.index>l&&n.push({type:"text",value:t.slice(l,o.index)}),o[2]?n.push({type:"bold",value:o[2]}):o[4]?n.push({type:"italic",value:o[4]}):o[6]&&n.push({type:"code",value:o[6]}),l=r.lastIndex;return l<t.length&&n.push({type:"text",value:t.slice(l)}),n}const L=["aria-label"],O={class:"quiz-question-title"},K={key:0},J={key:1},U={key:2},G={key:0,class:"quiz-hint"},Y=["aria-multiselectable"],Z=["onClick","aria-selected","onKeydown"],X={class:"quiz-indicator","aria-hidden":"true"},ee={key:0,class:"quiz-check"},te={key:1,class:"quiz-empty"},ne={key:0,class:"quiz-check"},re={key:1,class:"quiz-empty"},oe={class:"quiz-answer-text"},ae={key:0},ie={key:1},se={key:2},le={class:"quiz-hint"},ce={class:"quiz-input-wrapper"},pe=["disabled","placeholder","aria-label"],de={key:0,class:"quiz-expected"},ue={key:2,class:"quiz-explanation",role:"note"},fe={key:0},ge={key:1},me={key:2},Q=e.defineComponent({__name:"QuizQuestion",props:{dataQuiz:{type:String,required:!0}},setup(t){const n=t,r=e.computed(()=>{try{return JSON.parse(n.dataQuiz)}catch{return null}});function l(c){const s=[...c];for(let a=s.length-1;a>0;a--){const z=Math.floor(Math.random()*(a+1));[s[a],s[z]]=[s[z],s[a]]}return s}const o=e.ref([]);function h(){if(!r.value||r.value.type==="input"){o.value=[];return}const c=r.value.answers.map((s,a)=>({...s,originalIndex:a}));o.value=r.value.shuffle?l(c):c}const d=e.computed(()=>r.value?{...r.value,answers:o.value}:null),i=e.computed(()=>r.value?.type==="input"),m=e.computed(()=>d.value&&!i.value?d.value.answers.filter(c=>c.correct).length:0),b=e.computed(()=>m.value>1),u=e.ref(new Set),k=e.ref(""),_=e.inject("quiz-register",null),f=e.inject("quiz-validated",e.ref(!1)),v=e.inject("quiz-reset",e.ref(0)),x=e.inject("quiz-locale"),B=e.inject("quiz-question-id",null),p=e.inject("quiz-save-answer",null),g=e.inject("quiz-get-answer",null),q=B?B():null,$=e.computed(()=>i.value?k.value.trim().length>0:u.value.size>0),N=e.computed(()=>{if(!d.value||!$.value)return!1;if(i.value){const s=k.value.trim().toLowerCase();return r.value.expected.some(a=>s===a.trim().toLowerCase())}const c=new Set(d.value.answers.map((s,a)=>s.correct?a:-1).filter(s=>s>=0));if(u.value.size!==c.size)return!1;for(const s of u.value)if(!c.has(s))return!1;return!0});_&&_({answered:$,isCorrect:N}),e.watch(v,()=>{u.value=new Set,k.value="",h()}),e.onMounted(()=>{if(h(),g&&q!==null){const c=g(q);c&&(c.type==="input"?k.value=c.input:c.type==="choice"&&(u.value=new Set(c.selected)))}});function C(c){if(f.value)return;const s=new Set(u.value);b.value?s.has(c)?s.delete(c):s.add(c):(s.clear(),s.add(c)),u.value=s,M()}e.watch(k,()=>{f.value||M()});function M(){!p||q===null||(i.value?p(q,{type:"input",input:k.value}):p(q,{type:"choice",selected:[...u.value]}))}function Be(c){if(!f.value)return u.value.has(c)?"quiz-answer selected":"quiz-answer";const s=d.value.answers[c],a=u.value.has(c);return s.correct&&a?"quiz-answer correct":s.correct&&!a?"quiz-answer missed":!s.correct&&a?"quiz-answer wrong":"quiz-answer"}const Ee=e.computed(()=>f.value?N.value?"quiz-input correct":"quiz-input wrong":"quiz-input");return(c,s)=>d.value?(e.openBlock(),e.createElementBlock("fieldset",{key:0,class:e.normalizeClass(["quiz-question",{validated:e.unref(f)}]),"aria-label":d.value.question},[e.createElementVNode("legend",O,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(e.unref(V)(d.value.question),(a,z)=>(e.openBlock(),e.createElementBlock(e.Fragment,{key:z},[a.type==="bold"?(e.openBlock(),e.createElementBlock("strong",K,e.toDisplayString(a.value),1)):a.type==="italic"?(e.openBlock(),e.createElementBlock("em",J,e.toDisplayString(a.value),1)):a.type==="code"?(e.openBlock(),e.createElementBlock("code",U,e.toDisplayString(a.value),1)):(e.openBlock(),e.createElementBlock(e.Fragment,{key:3},[e.createTextVNode(e.toDisplayString(a.value),1)],64))],64))),128))]),i.value?e.createCommentVNode("",!0):(e.openBlock(),e.createElementBlock(e.Fragment,{key:0},[b.value?(e.openBlock(),e.createElementBlock("p",G,e.toDisplayString(e.unref(x).multipleHint),1)):e.createCommentVNode("",!0),e.createElementVNode("ul",{class:"quiz-answers",role:"listbox","aria-multiselectable":b.value},[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(d.value.answers,(a,z)=>(e.openBlock(),e.createElementBlock("li",{key:a.originalIndex,class:e.normalizeClass(Be(z)),onClick:y=>C(z),role:"option","aria-selected":u.value.has(z),tabindex:"0",onKeydown:[e.withKeys(y=>C(z),["enter"]),e.withKeys(e.withModifiers(y=>C(z),["prevent"]),["space"])]},[e.createElementVNode("span",X,[b.value?(e.openBlock(),e.createElementBlock(e.Fragment,{key:0},[u.value.has(z)?(e.openBlock(),e.createElementBlock("span",ee,"✓")):(e.openBlock(),e.createElementBlock("span",te,"☐"))],64)):(e.openBlock(),e.createElementBlock(e.Fragment,{key:1},[u.value.has(z)?(e.openBlock(),e.createElementBlock("span",ne,"●")):(e.openBlock(),e.createElementBlock("span",re,"○"))],64))]),e.createElementVNode("span",oe,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(e.unref(V)(a.text),(y,Se)=>(e.openBlock(),e.createElementBlock(e.Fragment,{key:Se},[y.type==="bold"?(e.openBlock(),e.createElementBlock("strong",ae,e.toDisplayString(y.value),1)):y.type==="italic"?(e.openBlock(),e.createElementBlock("em",ie,e.toDisplayString(y.value),1)):y.type==="code"?(e.openBlock(),e.createElementBlock("code",se,e.toDisplayString(y.value),1)):(e.openBlock(),e.createElementBlock(e.Fragment,{key:3},[e.createTextVNode(e.toDisplayString(y.value),1)],64))],64))),128))])],42,Z))),128))],8,Y)],64)),i.value?(e.openBlock(),e.createElementBlock(e.Fragment,{key:1},[e.createElementVNode("p",le,e.toDisplayString(e.unref(x).inputHint),1),e.createElementVNode("div",ce,[e.withDirectives(e.createElementVNode("input",{"onUpdate:modelValue":s[0]||(s[0]=a=>k.value=a),class:e.normalizeClass(Ee.value),type:"text",disabled:e.unref(f),placeholder:e.unref(x).inputPlaceholder,"aria-label":d.value.question,autocomplete:"off",spellcheck:"false",onKeydown:s[1]||(s[1]=e.withKeys(e.withModifiers(()=>{},["prevent"]),["enter"]))},null,42,pe),[[e.vModelText,k.value]]),e.unref(f)&&!N.value?(e.openBlock(),e.createElementBlock("p",de,[e.createTextVNode(e.toDisplayString(e.unref(x).expectedAnswer)+" ",1),e.createElementVNode("code",null,e.toDisplayString(r.value?.expected[0]),1)])):e.createCommentVNode("",!0)])],64)):e.createCommentVNode("",!0),e.unref(f)&&d.value.explanation?(e.openBlock(),e.createElementBlock("div",ue,[e.createElementVNode("strong",null,e.toDisplayString(e.unref(x).explanation),1),(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(e.unref(V)(d.value.explanation),(a,z)=>(e.openBlock(),e.createElementBlock(e.Fragment,{key:z},[a.type==="bold"?(e.openBlock(),e.createElementBlock("strong",fe,e.toDisplayString(a.value),1)):a.type==="italic"?(e.openBlock(),e.createElementBlock("em",ge,e.toDisplayString(a.value),1)):a.type==="code"?(e.openBlock(),e.createElementBlock("code",me,e.toDisplayString(a.value),1)):(e.openBlock(),e.createElementBlock(e.Fragment,{key:3},[e.createTextVNode(e.toDisplayString(a.value),1)],64))],64))),128))])):e.createCommentVNode("",!0)],10,L)):e.createCommentVNode("",!0)}}),he={class:"quiz-page",role:"region","aria-label":"Quiz"},ke=["aria-valuenow","aria-valuemax","aria-label"],ze={class:"quiz-progress-track"},be={class:"quiz-progress-label","aria-live":"polite"},we={class:"quiz-actions"},xe=["disabled"],ye=["aria-label"],qe={class:"quiz-score-value"},_e={class:"quiz-score-label"},A=e.defineComponent({__name:"QuizPage",setup(t){const n=e.inject("quiz-locale"),r=e.ref([]),l=e.ref(!1),o=typeof window<"u"?"quiz-state:"+window.location.pathname:"";x();let h=0;e.provide("quiz-validated",l),e.provide("quiz-register",p=>{r.value.push(p)}),e.provide("quiz-question-id",()=>h++),e.provide("quiz-save-answer",(p,g)=>{if(o)try{sessionStorage.setItem(o+":q"+p,JSON.stringify(g))}catch{}}),e.provide("quiz-get-answer",p=>{if(!o)return null;try{const g=sessionStorage.getItem(o+":q"+p);return g?JSON.parse(g):null}catch{return null}});const d=e.ref(0);e.provide("quiz-reset",d);const i=e.computed(()=>r.value.length),m=e.computed(()=>r.value.filter(p=>p.answered).length),b=e.computed(()=>r.value.filter(p=>p.isCorrect).length),u=e.computed(()=>m.value===i.value),k=e.computed(()=>i.value?Math.round(m.value/i.value*100):0);function _(){l.value=!0,v()}function f(){l.value=!1,d.value++,B()}function v(){if(o)try{const p={validated:l.value,ts:Date.now()};sessionStorage.setItem(o,JSON.stringify(p))}catch{}}function x(){if(o)try{const p=sessionStorage.getItem(o);if(!p)return;const g=JSON.parse(p);g&&g.validated&&(l.value=!0)}catch{}}function B(){if(o)try{const p=[];for(let g=0;g<sessionStorage.length;g++){const q=sessionStorage.key(g);q&&q.startsWith(o)&&p.push(q)}p.forEach(g=>sessionStorage.removeItem(g))}catch{}}return(p,g)=>(e.openBlock(),e.createElementBlock("div",he,[e.createElementVNode("div",{class:"quiz-progress-bar",role:"progressbar","aria-valuenow":m.value,"aria-valuemin":0,"aria-valuemax":i.value,"aria-label":m.value+" / "+i.value+" "+e.unref(n).answered},[e.createElementVNode("div",ze,[e.createElementVNode("div",{class:e.normalizeClass(["quiz-progress-fill",{complete:k.value===100}]),style:e.normalizeStyle({width:k.value+"%"})},null,6)]),e.createElementVNode("span",be,e.toDisplayString(m.value)+" / "+e.toDisplayString(i.value)+" "+e.toDisplayString(e.unref(n).answered),1)],8,ke),e.renderSlot(p.$slots,"default"),e.createElementVNode("div",we,[l.value?e.createCommentVNode("",!0):(e.openBlock(),e.createElementBlock("button",{key:0,class:"quiz-btn quiz-btn-validate",disabled:!u.value,onClick:_},e.toDisplayString(e.unref(n).validate),9,xe)),l.value?(e.openBlock(),e.createElementBlock(e.Fragment,{key:1},[e.createElementVNode("div",{class:"quiz-score",role:"status","aria-live":"polite","aria-label":b.value+" / "+i.value+" "+e.unref(n).correctAnswers(b.value)},[e.createElementVNode("span",qe,e.toDisplayString(b.value)+" / "+e.toDisplayString(i.value),1),e.createElementVNode("span",_e,e.toDisplayString(e.unref(n).correctAnswers(b.value))+" ("+e.toDisplayString(i.value?Math.round(b.value/i.value*100):0)+"%) ",1)],8,ye),e.createElementVNode("button",{class:"quiz-btn quiz-btn-reset",onClick:f},e.toDisplayString(e.unref(n).reset),1)],64)):e.createCommentVNode("",!0)])]))}});function ve(t,n="en"){P(),t.provide("quiz-locale",D(n)),t.component("QuizQuestion",Q),t.component("QuizPage",A)}w.QuizPage=A,w.QuizQuestion=Q,w.enhanceAppWithQuiz=ve,w.getLocale=D,w.locales=S,w.quizMarkdownPlugin=T,Object.defineProperty(w,Symbol.toStringTag,{value:"Module"})}));
5
+ //# sourceMappingURL=vitepress-plugin-quiz.umd.cjs.map