@memizy/oqse 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -15,58 +15,58 @@ function i(e) {
15
15
  function a(e) {
16
16
  return e.type === "mcq-multi";
17
17
  }
18
- function ee(e) {
18
+ function o(e) {
19
19
  return e.type === "short-answer";
20
20
  }
21
- function te(e) {
21
+ function ee(e) {
22
22
  return e.type === "fill-in-blanks";
23
23
  }
24
- function ne(e) {
24
+ function te(e) {
25
25
  return e.type === "fill-in-select";
26
26
  }
27
- function re(e) {
27
+ function ne(e) {
28
28
  return e.type === "match-pairs";
29
29
  }
30
- function ie(e) {
30
+ function re(e) {
31
31
  return e.type === "match-complex";
32
32
  }
33
- function ae(e) {
33
+ function ie(e) {
34
34
  return e.type === "sort-items";
35
35
  }
36
- function oe(e) {
36
+ function ae(e) {
37
37
  return e.type === "slider";
38
38
  }
39
- function se(e) {
39
+ function oe(e) {
40
40
  return e.type === "pin-on-image";
41
41
  }
42
- function ce(e) {
42
+ function se(e) {
43
43
  return e.type === "categorize";
44
44
  }
45
- function le(e) {
45
+ function ce(e) {
46
46
  return e.type === "timeline";
47
47
  }
48
- function ue(e) {
48
+ function le(e) {
49
49
  return e.type === "matrix";
50
50
  }
51
- function de(e) {
51
+ function ue(e) {
52
52
  return e.type === "math-input";
53
53
  }
54
- function fe(e) {
54
+ function de(e) {
55
55
  return e.type === "diagram-label";
56
56
  }
57
- function pe(e) {
57
+ function fe(e) {
58
58
  return e.type === "open-ended";
59
59
  }
60
- function me(e) {
60
+ function pe(e) {
61
61
  return e.type === "numeric-input";
62
62
  }
63
- function he(e) {
63
+ function me(e) {
64
64
  return e.type === "pin-on-model";
65
65
  }
66
- function ge(e) {
66
+ function he(e) {
67
67
  return e.type === "chess-puzzle";
68
68
  }
69
- function o(e) {
69
+ function ge(e) {
70
70
  return [
71
71
  "note",
72
72
  "flashcard",
@@ -75,52 +75,118 @@ function o(e) {
75
75
  ].includes(e.type);
76
76
  }
77
77
  function _e(e) {
78
- return !o(e);
78
+ return !ge(e);
79
+ }
80
+ //#endregion
81
+ //#region src/manifest.ts
82
+ var ve = [
83
+ "render",
84
+ "edit",
85
+ "validate",
86
+ "import",
87
+ "export"
88
+ ], s = [
89
+ "markdown",
90
+ "math",
91
+ "rtl",
92
+ "html",
93
+ "syntax-highlighting",
94
+ "mermaid",
95
+ "smiles",
96
+ "abc-notation",
97
+ "text-to-speech",
98
+ "voice-input",
99
+ "handwriting-recognition"
100
+ ], c = [
101
+ "hints",
102
+ "explanation",
103
+ "incorrectFeedback",
104
+ "sources",
105
+ "relatedItems",
106
+ "dependencyItems",
107
+ "timeLimit",
108
+ "lang",
109
+ "topic",
110
+ "pedagogy"
111
+ ], l = [
112
+ "description",
113
+ "thumbnail",
114
+ "subject",
115
+ "language",
116
+ "author",
117
+ "contributors",
118
+ "license",
119
+ "ageRestriction",
120
+ "tags",
121
+ "tagDefinitions",
122
+ "sourceMaterials",
123
+ "estimatedTime",
124
+ "prerequisites",
125
+ "translations",
126
+ "relatedSets"
127
+ ];
128
+ function u(e) {
129
+ return /^\d+\.\d+$/.test(e);
130
+ }
131
+ function ye(e) {
132
+ return /^\d+\.\d+\.\d+(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$/.test(e);
133
+ }
134
+ function d(e, t) {
135
+ let [n = 0, r = 0] = e.split(".").map(Number), [i = 0, a = 0] = t.split(".").map(Number);
136
+ return n === i ? r - a : n - i;
137
+ }
138
+ function be(e) {
139
+ if (typeof e != "object" || !e) return !1;
140
+ let t = e;
141
+ return typeof t.version == "string" && typeof t.id == "string" && typeof t.appName == "string" && t.appName !== "" && typeof t.capabilities == "object" && t.capabilities !== null && Array.isArray(t.capabilities.actions);
142
+ }
143
+ function xe(e, t) {
144
+ return !(!u(e) || t.minOqseVersion && u(t.minOqseVersion) && d(e, t.minOqseVersion) < 0 || t.maxOqseVersion && u(t.maxOqseVersion) && d(e, t.maxOqseVersion) > 0);
79
145
  }
80
146
  //#endregion
81
147
  //#region src/oqseValidation.ts
82
- var s = e.string().uuid({ message: "Neplatn+� form+�t UUID" }), c = e.string().min(2, "K+-d jazyka mus+� m+�t alespo+� 2 znaky").regex(/^[a-z]{2,3}(-[A-Z][a-z]{3})?(-[A-Z]{2})?$/, "Neplatn+� form+�t BCP 47 (nap+�. \"cs\", \"en-US\")"), l = e.string().min(1, "Identifik+�tor licence nesm+� b+�t pr+�zdn+�"), u = e.string().regex(/^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}(\.\d{3})?(Z|[+-]\d{2}:\d{2})?)?$/, "Neplatn+� form+�t ISO 8601 (nap+�. \"2025-11-21T14:30:00Z\")"), d = e.string().url({ message: "Mus+� b+�t platn+� absolutn+� URL adresa" }), f = e.string().regex(/^[a-z0-9_-]+$/, "Kl+��� assetu mus+� obsahovat pouze mal+� p+�smena, ��+�sla, poml��ky a podtr+�+�tka"), p = e.string().min(1, "Text nesm+� b+�t pr+�zdn+�"), m = e.string().min(1, "Obsah nesm+� b+�t pr+�zdn+�"), h = e.string().optional(), g = e.object({
83
- lang: c,
84
- value: e.string().min(1, "URI titulk+� nesm+� b+�t pr+�zdn+�"),
148
+ var f = e.string().uuid({ message: "Invalid UUID format" }), p = e.string().min(2, "Language code must have at least 2 characters").regex(/^[a-z]{2,3}(-[A-Z][a-z]{3})?(-[A-Z]{2})?$/, "Invalid BCP 47 format (e.g. \"cs\", \"en-US\")"), m = e.string().min(1, "License identifier must not be empty"), h = e.string().regex(/^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}(\.\d{3})?(Z|[+-]\d{2}:\d{2})?)?$/, "Invalid ISO 8601 format (e.g. \"2025-11-21T14:30:00Z\")"), g = e.string().url({ message: "Must be a valid absolute URL" }), _ = e.string().regex(/^[a-z0-9_-]+$/, "Asset key must contain only lowercase letters, numbers, hyphens and underscores"), v = e.string().min(1, "Text must not be empty"), y = e.string().min(1, "Content must not be empty"), b = e.string().optional(), Se = e.object({
149
+ lang: p,
150
+ value: e.string().min(1, "Subtitle URI must not be empty"),
85
151
  label: e.string().optional(),
86
152
  kind: e.enum([
87
153
  "captions",
88
154
  "subtitles",
89
155
  "descriptions"
90
156
  ]).optional()
91
- }), ve = e.object({
157
+ }), Ce = e.object({
92
158
  type: e.enum([
93
159
  "image",
94
160
  "audio",
95
161
  "video",
96
162
  "model"
97
163
  ]),
98
- value: e.string().min(1, "URI m+�dia nesm+� b+�t pr+�zdn+�"),
164
+ value: e.string().min(1, "Media URI must not be empty"),
99
165
  mimeType: e.string().optional(),
100
166
  altText: e.string().optional(),
101
- transcript: m.optional(),
102
- caption: m.optional(),
167
+ transcript: y.optional(),
168
+ caption: y.optional(),
103
169
  width: e.number().int().positive().optional(),
104
170
  height: e.number().int().positive().optional(),
105
171
  start: e.number().nonnegative().optional(),
106
172
  end: e.number().positive().optional(),
107
173
  loop: e.boolean().optional(),
108
- subtitles: e.array(g).optional(),
109
- license: l.optional(),
174
+ subtitles: e.array(Se).optional(),
175
+ license: m.optional(),
110
176
  attribution: e.string().optional(),
111
177
  checksums: e.record(e.string(), e.string()).optional()
112
178
  }).refine((e) => e.start !== void 0 && e.end !== void 0 ? e.start < e.end : !0, {
113
- message: "Po��+�te��n+� ��as mus+� b+�t men+�+� ne+� koncov+� ��as",
179
+ message: "Start time must be less than end time",
114
180
  path: ["end"]
115
181
  }).refine((e) => !(e.type === "image" && !e.altText), {
116
- message: "Obr+�zky mus+� m+�t definovan+� alternativn+� text (altText) pro p+�+�stupnost",
182
+ message: "Images must have alternative text (altText) defined for accessibility",
117
183
  path: ["altText"]
118
- }), _ = e.record(f, ve), v = e.object({
119
- name: p,
184
+ }), x = e.record(_, Ce), S = e.object({
185
+ name: v,
120
186
  role: e.string().optional(),
121
- email: e.string().email("Neplatn+� form+�t e-mailov+� adresy").optional(),
122
- url: d.optional()
123
- }), y = e.enum([
187
+ email: e.string().email("Invalid email format").optional(),
188
+ url: g.optional()
189
+ }), C = e.enum([
124
190
  "url",
125
191
  "doi",
126
192
  "isbn",
@@ -131,16 +197,16 @@ var s = e.string().uuid({ message: "Neplatn+� form+�t UUID" }), c = e.string
131
197
  "image",
132
198
  "model",
133
199
  "other"
134
- ]), b = e.object({
135
- id: p,
136
- type: y,
137
- value: p,
138
- title: p,
200
+ ]), w = e.object({
201
+ id: v,
202
+ type: C,
203
+ value: v,
204
+ title: v,
139
205
  description: e.string().optional(),
140
- authors: e.array(p).optional(),
141
- publishedDate: u.optional(),
142
- retrievedAt: u.optional(),
143
- license: l.optional()
206
+ authors: e.array(v).optional(),
207
+ publishedDate: h.optional(),
208
+ retrievedAt: h.optional(),
209
+ license: m.optional()
144
210
  }).refine((e) => {
145
211
  if ([
146
212
  "url",
@@ -155,261 +221,241 @@ var s = e.string().uuid({ message: "Neplatn+� form+�t UUID" }), c = e.string
155
221
  }
156
222
  return !0;
157
223
  }, {
158
- message: "Pro typy url, pdf, video, audio a image mus+� b+�t value platn+� URL adresa",
224
+ message: "For url, pdf, video, audio and image types, value must be a valid URL",
159
225
  path: ["value"]
160
- }), x = e.object({
161
- id: p,
226
+ }), T = e.object({
227
+ id: v,
162
228
  location: e.string().optional(),
163
- quote: m.optional()
164
- }), S = e.object({
165
- wikidataId: e.string().regex(/^Q\d+$/, "Wikidata ID mus+� m+�t form+�t Q n+�sledovan+� ��+�slem").optional(),
229
+ quote: y.optional()
230
+ }), E = e.object({
231
+ wikidataId: e.string().regex(/^Q\d+$/, "Wikidata ID must have format Q followed by number").optional(),
166
232
  description: e.string().optional()
167
- }), C = e.record(e.string(), S), w = e.object({
168
- features: e.array(e.string().min(1, "Kl+��� funkce nesm+� b+�t pr+�zdn+�")).optional(),
169
- latexPackages: e.array(e.string().min(1, "N+�zev bal+���ku nesm+� b+�t pr+�zdn+�")).optional(),
170
- itemProperties: e.array(e.string().min(1, "Kl+��� vlastnosti nesm+� b+�t pr+�zdn+�")).optional(),
171
- metaProperties: e.array(e.string().min(1, "Kl+��� vlastnosti nesm+� b+�t pr+�zdn+�")).optional()
172
- }), T = e.enum([
173
- "official",
174
- "experimental",
175
- "proprietary"
176
- ]), ye = e.enum([
177
- "math",
178
- "media-image",
179
- "media-audio",
180
- "media-video",
181
- "hotspots",
182
- "complex-pairing",
183
- "open-text"
184
- ]), E = e.object({
185
- name: p,
186
- type: T,
187
- vendor: e.string().optional()
188
- }).refine((e) => !(e.type === "proprietary" && !e.vendor), {
189
- message: "Propriet+�rn+� funkce mus+� m+�t definovan+� vendor (nap+�. \"memizy.com\")",
190
- path: ["vendor"]
191
- }), D = e.object({
192
- lang: c,
193
- id: s,
194
- title: p,
195
- downloadUrl: d.optional()
233
+ }), we = e.record(e.string(), E), D = e.object({
234
+ features: e.array(e.string().refine((e) => s.includes(e) || e.startsWith("x-"), { message: "Feature must be an official key or have prefix \"x-\"" })).optional(),
235
+ latexPackages: e.array(e.string().min(1, "Package name must not be empty")).optional(),
236
+ itemProperties: e.array(e.string().refine((e) => c.includes(e) || e.startsWith("x-"), { message: "Item property must be an official key or have prefix \"x-\"" })).optional(),
237
+ metaProperties: e.array(e.string().refine((e) => l.includes(e) || e.startsWith("x-"), { message: "Meta property must be an official key or have prefix \"x-\"" })).optional()
238
+ }), Te = e.object({
239
+ lang: p,
240
+ id: f,
241
+ title: v,
242
+ downloadUrl: g.optional()
196
243
  }), O = e.object({
197
- id: s,
198
- title: p,
199
- downloadUrl: d.optional()
200
- }), k = e.enum([
244
+ id: f,
245
+ title: v,
246
+ downloadUrl: g.optional()
247
+ }), Ee = e.enum([
201
248
  "remember",
202
249
  "understand",
203
250
  "apply",
204
251
  "analyze",
205
252
  "evaluate",
206
253
  "create"
207
- ]), A = e.enum([
254
+ ]), De = e.enum([
208
255
  "low",
209
256
  "medium",
210
257
  "high"
211
- ]), j = e.object({
212
- bloomLevel: k.optional(),
258
+ ]), Oe = e.object({
259
+ bloomLevel: Ee.optional(),
213
260
  irtDifficulty: e.number().optional(),
214
261
  irtDiscrimination: e.number().optional(),
215
- irtGuessing: e.number().min(0).max(1, "IRT guessing mus+� b+�t mezi 0 a 1").optional(),
262
+ irtGuessing: e.number().min(0).max(1, "IRT guessing must be between 0 and 1").optional(),
216
263
  avgTime: e.number().positive().optional(),
217
- cognitiveLoad: A.optional(),
264
+ cognitiveLoad: De.optional(),
218
265
  partialCredit: e.boolean().optional(),
219
- penaltyPerWrong: e.number().min(0).max(1, "Penalizace mus+� b+�t mezi 0 a 1").optional()
220
- }), M = e.enum(["katex", "mathjax"]), N = e.object({
221
- renderer: M.optional(),
266
+ penaltyPerWrong: e.number().min(0).max(1, "Penalty must be between 0 and 1").optional()
267
+ }), ke = e.enum(["katex", "mathjax"]), Ae = e.object({
268
+ renderer: ke.optional(),
222
269
  packages: e.array(e.string()).optional()
223
- }), P = e.object({
224
- id: s,
225
- language: c,
226
- title: p.max(500, "Titulek nesm+� b+�t del+�+� ne+� 500 znak+�"),
227
- description: m.max(5e3, "Popis nesm+� b+�t del+�+� ne+� 5000 znak+�").optional(),
228
- thumbnail: f.optional(),
229
- assets: _.optional(),
270
+ }), je = e.object({
271
+ id: f,
272
+ language: p,
273
+ title: v.max(500, "Title must not be longer than 500 characters"),
274
+ description: y.max(5e3, "Description must not be longer than 5000 characters").optional(),
275
+ thumbnail: _.optional(),
276
+ assets: x.optional(),
230
277
  ageMin: e.number().int().nonnegative().optional(),
231
278
  ageMax: e.number().int().nonnegative().optional(),
232
279
  subject: e.string().optional(),
233
- createdAt: u,
234
- updatedAt: u,
235
- author: v.optional(),
236
- contributors: e.array(v).optional(),
237
- license: l.optional(),
238
- licenseUrl: d.optional(),
239
- requirements: w.optional(),
240
- requiredFeatures: e.array(E).optional(),
241
- tags: e.array(p).optional(),
242
- tagDefinitions: C.optional(),
243
- translations: e.array(D).optional(),
244
- sourceMaterials: e.array(b).optional(),
280
+ createdAt: h,
281
+ updatedAt: h,
282
+ author: S.optional(),
283
+ contributors: e.array(S).optional(),
284
+ license: m.optional(),
285
+ licenseUrl: g.optional(),
286
+ requirements: D.optional(),
287
+ tags: e.array(v).optional(),
288
+ tagDefinitions: we.optional(),
289
+ translations: e.array(Te).optional(),
290
+ sourceMaterials: e.array(w).optional(),
245
291
  estimatedTime: e.number().positive().optional(),
246
292
  prerequisites: e.array(O).optional(),
247
293
  relatedSets: e.array(O).optional(),
248
- mathSettings: N.optional(),
294
+ mathSettings: Ae.optional(),
249
295
  customData: e.record(e.string(), e.unknown()).optional(),
250
296
  appSpecific: e.record(e.string(), e.unknown()).optional()
251
297
  }).refine((e) => e.ageMin !== void 0 && e.ageMax !== void 0 ? e.ageMin <= e.ageMax : !0, {
252
- message: "Minim+�ln+� v��k (ageMin) mus+� b+�t men+�+� nebo roven maxim+�ln+�mu v��ku (ageMax)",
298
+ message: "Minimum age (ageMin) must be less than or equal to maximum age (ageMax)",
253
299
  path: ["ageMax"]
254
300
  }).refine((e) => new Date(e.createdAt) <= new Date(e.updatedAt), {
255
- message: "Datum vytvo+�en+� (createdAt) mus+� b+�t p+�ed nebo stejn+� jako datum aktualizace (updatedAt)",
301
+ message: "Creation date (createdAt) must be before or equal to update date (updatedAt)",
256
302
  path: ["updatedAt"]
257
- }), F = e.object({
258
- id: s,
303
+ }), k = e.object({
304
+ id: f,
259
305
  type: e.string(),
260
- assets: _.optional(),
261
- lang: c.optional(),
262
- tags: e.array(p).optional(),
263
- difficulty: e.number().int().min(1, "Obt+�+�nost mus+� b+�t minim+�ln�� 1").max(5, "Obt+�+�nost mus+� b+�t maxim+�ln�� 5").optional(),
264
- timeLimit: e.number().positive("��asov+� limit mus+� b+�t kladn+� ��+�slo").optional(),
265
- hints: e.array(m.max(2e3, "N+�pov��da nesm+� b+�t del+�+� ne+� 2000 znak+�")).max(20, "Maxim+�ln�� 20 n+�pov��d na polo+�ku").optional(),
266
- explanation: m.max(1e4, "Vysv��tlen+� nesm+� b+�t del+�+� ne+� 10000 znak+�").optional(),
267
- incorrectFeedback: m.optional(),
268
- sources: e.array(x).optional(),
269
- relatedItems: e.array(s).optional(),
270
- dependencyItems: e.array(s).optional(),
271
- pedagogy: j.optional(),
306
+ assets: x.optional(),
307
+ lang: p.optional(),
308
+ tags: e.array(v).optional(),
309
+ difficulty: e.number().int().min(1, "Difficulty must be at least 1").max(5, "Difficulty must be at most 5").optional(),
310
+ timeLimit: e.number().positive("Time limit must be a positive number").optional(),
311
+ hints: e.array(y.max(2e3, "Hint must not be longer than 2000 characters")).max(20, "Maximum 20 hints per item").optional(),
312
+ explanation: y.max(1e4, "Explanation must not be longer than 10000 characters").optional(),
313
+ incorrectFeedback: y.optional(),
314
+ sources: e.array(T).optional(),
315
+ relatedItems: e.array(f).optional(),
316
+ dependencyItems: e.array(f).optional(),
317
+ pedagogy: Oe.optional(),
272
318
  customData: e.record(e.string(), e.unknown()).optional(),
273
319
  appSpecific: e.record(e.string(), e.unknown()).optional()
274
- }), I = e.object({
275
- options: e.array(m).min(1, "Mus+� b+�t alespo+� 1 mo+�nost"),
320
+ }), Me = e.object({
321
+ options: e.array(y).min(1, "Must have at least 1 option"),
276
322
  correctIndex: e.number().int().nonnegative()
277
323
  }).refine((e) => e.correctIndex < e.options.length, {
278
- message: "Index spr+�vn+� odpov��di odkazuje na neexistuj+�c+� mo+�nost",
324
+ message: "Correct answer index references non-existent option",
279
325
  path: ["correctIndex"]
280
- }), L = e.object({
326
+ }), A = e.object({
281
327
  type: e.literal("rect"),
282
328
  label: e.string().optional(),
283
- x: e.number().min(0).max(100, "X mus+� b+�t v rozmez+� 0-100%"),
284
- y: e.number().min(0).max(100, "Y mus+� b+�t v rozmez+� 0-100%"),
285
- width: e.number().min(0).max(100, "+�+�+�ka mus+� b+�t v rozmez+� 0-100%"),
286
- height: e.number().min(0).max(100, "V+�+�ka mus+� b+�t v rozmez+� 0-100%")
287
- }), R = e.object({
329
+ x: e.number().min(0).max(100, "X must be in range 0-100%"),
330
+ y: e.number().min(0).max(100, "Y must be in range 0-100%"),
331
+ width: e.number().min(0).max(100, "Width must be in range 0-100%"),
332
+ height: e.number().min(0).max(100, "Height must be in range 0-100%")
333
+ }), j = e.object({
288
334
  type: e.literal("circle"),
289
335
  label: e.string().optional(),
290
- x: e.number().min(0).max(100, "X mus+� b+�t v rozmez+� 0-100%"),
291
- y: e.number().min(0).max(100, "Y mus+� b+�t v rozmez+� 0-100%"),
292
- radius: e.number().min(0).max(100, "Polom��r mus+� b+�t v rozmez+� 0-100%")
293
- }), z = e.object({
336
+ x: e.number().min(0).max(100, "X must be in range 0-100%"),
337
+ y: e.number().min(0).max(100, "Y must be in range 0-100%"),
338
+ radius: e.number().min(0).max(100, "Radius must be in range 0-100%")
339
+ }), M = e.object({
294
340
  type: e.literal("polygon"),
295
341
  label: e.string().optional(),
296
342
  points: e.array(e.object({
297
343
  x: e.number().min(0).max(100),
298
344
  y: e.number().min(0).max(100)
299
- })).min(3, "Polygon mus+� m+�t alespo+� 3 body")
300
- }), B = e.object({
345
+ })).min(3, "Polygon must have at least 3 points")
346
+ }), N = e.object({
301
347
  type: e.literal("mesh"),
302
348
  label: e.string().optional(),
303
- targetName: p
304
- }), V = e.discriminatedUnion("type", [
305
- L,
306
- R,
307
- z,
308
- B
309
- ]), H = e.object({
349
+ targetName: v
350
+ }), P = e.discriminatedUnion("type", [
351
+ A,
352
+ j,
353
+ M,
354
+ N
355
+ ]), F = e.object({
310
356
  x: e.number(),
311
357
  y: e.number(),
312
358
  z: e.number()
313
- }), U = e.object({
314
- position: H.optional(),
315
- target: H.optional()
316
- }), be = e.object({
317
- id: p,
318
- text: m,
359
+ }), I = e.object({
360
+ position: F.optional(),
361
+ target: F.optional()
362
+ }), L = e.object({
363
+ id: v,
364
+ text: y,
319
365
  correctCategoryIndex: e.number().int().nonnegative()
320
- }), xe = e.enum([
366
+ }), R = e.enum([
321
367
  "year",
322
368
  "month",
323
369
  "day",
324
370
  "datetime"
325
- ]), Se = e.object({
326
- id: p,
327
- text: m,
328
- date: u,
329
- precision: xe.optional()
330
- }), Ce = e.union([
331
- L.extend({ correctLabelIndex: e.number().int().nonnegative() }),
332
- R.extend({ correctLabelIndex: e.number().int().nonnegative() }),
333
- z.extend({ correctLabelIndex: e.number().int().nonnegative() })
334
- ]), we = e.object({
335
- label: p,
336
- percentage: e.number().min(0, "Procenta mus+� b+�t nez+�porn+�").max(100, "Procenta nesm+� p+�es+�hnout 100"),
371
+ ]), z = e.object({
372
+ id: v,
373
+ text: y,
374
+ date: h,
375
+ precision: R.optional()
376
+ }), B = e.union([
377
+ A.extend({ correctLabelIndex: e.number().int().nonnegative() }),
378
+ j.extend({ correctLabelIndex: e.number().int().nonnegative() }),
379
+ M.extend({ correctLabelIndex: e.number().int().nonnegative() })
380
+ ]), V = e.object({
381
+ label: v,
382
+ percentage: e.number().min(0, "Percentage must be non-negative").max(100, "Percentage must not exceed 100"),
337
383
  description: e.string().optional()
338
- }), Te = e.object({ criteria: e.array(we).min(1, "Rubrika mus+� m+�t alespo+� 1 krit+�rium") }).refine((e) => e.criteria.reduce((e, t) => e + t.percentage, 0) > 0, {
339
- message: "Sou��et procent v+�ech krit+�ri+� mus+� b+�t v��t+�+� ne+� 0",
384
+ }), H = e.object({ criteria: e.array(V).min(1, "Rubric must have at least 1 criterion") }).refine((e) => e.criteria.reduce((e, t) => e + t.percentage, 0) > 0, {
385
+ message: "Sum of percentages of all criteria must be greater than 0",
340
386
  path: ["criteria"]
341
- }), Ee = e.object({
387
+ }), Ne = e.object({
342
388
  min: e.number(),
343
389
  max: e.number()
344
390
  }).refine((e) => e.min <= e.max, {
345
- message: "Minim+�ln+� hodnota mus+� b+�t men+�+� nebo rovna maxim+�ln+� hodnot��",
391
+ message: "Minimum value must be less than or equal to maximum value",
346
392
  path: ["max"]
347
- }), De = F.extend({
393
+ }), Pe = k.extend({
348
394
  type: e.literal("note"),
349
395
  title: e.string().optional(),
350
- content: m.max(1e4, "Obsah nesm+� b+�t del+�+� ne+� 10000 znak+�")
351
- }), Oe = F.extend({
396
+ content: y.max(1e4, "Content must not be longer than 10000 characters")
397
+ }), Fe = k.extend({
352
398
  type: e.literal("flashcard"),
353
- front: m.max(1e4, "P+�edn+� strana nesm+� b+�t del+�+� ne+� 10000 znak+�"),
354
- back: m.max(1e4, "Zadn+� strana nesm+� b+�t del+�+� ne+� 10000 znak+�")
355
- }), ke = F.extend({
399
+ front: y.max(1e4, "Front side must not be longer than 10000 characters"),
400
+ back: y.max(1e4, "Back side must not be longer than 10000 characters")
401
+ }), Ie = k.extend({
356
402
  type: e.literal("true-false"),
357
- question: m.max(1e4, "Ot+�zka nesm+� b+�t del+�+� ne+� 10000 znak+�"),
403
+ question: y.max(1e4, "Question must not be longer than 10000 characters"),
358
404
  answer: e.boolean()
359
- }), Ae = F.extend({
405
+ }), Le = k.extend({
360
406
  type: e.literal("mcq-single"),
361
- question: m.max(1e4, "Ot+�zka nesm+� b+�t del+�+� ne+� 10000 znak+�"),
362
- options: e.array(m.max(2e3, "Mo+�nost nesm+� b+�t del+�+� ne+� 2000 znak+�")).min(2, "Ot+�zka mus+� m+�t alespo+� 2 mo+�nosti").max(100, "Maxim+�ln�� 100 mo+�nost+�"),
407
+ question: y.max(1e4, "Question must not be longer than 10000 characters"),
408
+ options: e.array(y.max(2e3, "Option must not be longer than 2000 characters")).min(2, "Question must have at least 2 options").max(100, "Maximum 100 options"),
363
409
  correctIndex: e.number().int().nonnegative(),
364
410
  shuffleOptions: e.boolean().optional(),
365
- optionExplanations: e.array(e.union([m, e.null()])).optional()
411
+ optionExplanations: e.array(e.union([y, e.null()])).optional()
366
412
  }).refine((e) => e.correctIndex < e.options.length, {
367
- message: "Index spr+�vn+� odpov��di odkazuje na neexistuj+�c+� mo+�nost",
413
+ message: "Correct answer index references non-existent option",
368
414
  path: ["correctIndex"]
369
415
  }).refine((e) => e.optionExplanations ? e.optionExplanations.length === e.options.length : !0, {
370
- message: "Po��et vysv��tlen+� mo+�nost+� mus+� b+�t stejn+� jako po��et mo+�nost+�",
416
+ message: "Number of option explanations must match number of options",
371
417
  path: ["optionExplanations"]
372
- }), je = F.extend({
418
+ }), Re = k.extend({
373
419
  type: e.literal("mcq-multi"),
374
- question: m.max(1e4, "Ot+�zka nesm+� b+�t del+�+� ne+� 10000 znak+�"),
375
- options: e.array(m.max(2e3, "Mo+�nost nesm+� b+�t del+�+� ne+� 2000 znak+�")).min(2, "Ot+�zka mus+� m+�t alespo+� 2 mo+�nosti").max(100, "Maxim+�ln�� 100 mo+�nost+�"),
376
- correctIndices: e.array(e.number().int().nonnegative()).min(1, "Mus+� b+�t alespo+� 1 spr+�vn+� odpov����"),
420
+ question: y.max(1e4, "Question must not be longer than 10000 characters"),
421
+ options: e.array(y.max(2e3, "Option must not be longer than 2000 characters")).min(2, "Question must have at least 2 options").max(100, "Maximum 100 options"),
422
+ correctIndices: e.array(e.number().int().nonnegative()).min(1, "Must have at least 1 correct answer"),
377
423
  minSelections: e.number().int().positive().optional(),
378
424
  maxSelections: e.number().int().positive().optional(),
379
425
  shuffleOptions: e.boolean().optional(),
380
- optionExplanations: e.array(e.union([m, e.null()])).optional()
426
+ optionExplanations: e.array(e.union([y, e.null()])).optional()
381
427
  }).refine((e) => e.correctIndices.every((t) => t < e.options.length), {
382
- message: "N��kter+� z index+� spr+�vn+�ch odpov��d+� odkazuje na neexistuj+�c+� mo+�nost",
428
+ message: "Some of correct answer indices reference non-existent option",
383
429
  path: ["correctIndices"]
384
430
  }).refine((e) => new Set(e.correctIndices).size === e.correctIndices.length, {
385
- message: "Indexy spr+�vn+�ch odpov��d+� obsahuj+� duplicity",
431
+ message: "Correct answer indices contain duplicates",
386
432
  path: ["correctIndices"]
387
433
  }).refine((e) => e.minSelections && e.maxSelections ? e.minSelections <= e.maxSelections : !0, {
388
- message: "Minim+�ln+� po��et v+�b��r+� mus+� b+�t men+�+� nebo roven maxim+�ln+�mu po��tu",
434
+ message: "Minimum number of selections must be less than or equal to maximum",
389
435
  path: ["maxSelections"]
390
436
  }).refine((e) => e.maxSelections ? e.maxSelections <= e.options.length : !0, {
391
- message: "Maxim+�ln+� po��et v+�b��r+� nesm+� p+�es+�hnout po��et mo+�nost+�",
437
+ message: "Maximum number of selections must not exceed number of options",
392
438
  path: ["maxSelections"]
393
439
  }).refine((e) => e.optionExplanations ? e.optionExplanations.length === e.options.length : !0, {
394
- message: "Po��et vysv��tlen+� mo+�nost+� mus+� b+�t stejn+� jako po��et mo+�nost+�",
440
+ message: "Number of option explanations must match number of options",
395
441
  path: ["optionExplanations"]
396
- }), W = F.extend({
442
+ }), ze = k.extend({
397
443
  type: e.literal("short-answer"),
398
- question: m.max(1e4, "Ot+�zka nesm+� b+�t del+�+� ne+� 10000 znak+�"),
399
- answers: e.array(p).min(1, "Mus+� b+�t alespo+� 1 spr+�vn+� odpov����"),
444
+ question: y.max(1e4, "Question must not be longer than 10000 characters"),
445
+ answers: e.array(v).min(1, "Must have at least 1 correct answer"),
400
446
  caseSensitive: e.boolean().optional(),
401
447
  trimWhitespace: e.boolean().optional(),
402
448
  acceptPartial: e.boolean().optional(),
403
449
  ignoreDiacritics: e.boolean().optional()
404
- }), Me = F.extend({
450
+ }), Be = k.extend({
405
451
  type: e.literal("fill-in-blanks"),
406
- question: h,
407
- text: m.max(1e4, "Text nesm+� b+�t del+�+� ne+� 10000 znak+�"),
408
- blanks: e.record(e.string(), e.array(p).min(1, "Ka+�d+� mezera mus+� m+�t alespo+� 1 spr+�vnou odpov����")),
452
+ question: b,
453
+ text: y.max(1e4, "Text must not be longer than 10000 characters"),
454
+ blanks: e.record(e.string(), e.array(v).min(1, "Each blank must have at least 1 correct answer")),
409
455
  caseSensitive: e.boolean().optional(),
410
456
  trimWhitespace: e.boolean().optional()
411
457
  }).refine((e) => Object.keys(e.blanks).length > 0, {
412
- message: "Text mus+� obsahovat alespo+� 1 mezeru k dopln��n+�",
458
+ message: "Text must contain at least 1 blank to fill",
413
459
  path: ["blanks"]
414
460
  }).refine((e) => {
415
461
  let t = /<blank:([a-zA-Z0-9_-]{1,64})\s*\/>/g, n = /* @__PURE__ */ new Set(), r;
@@ -419,15 +465,15 @@ var s = e.string().uuid({ message: "Neplatn+� form+�t UUID" }), c = e.string
419
465
  for (let e of i) if (!n.has(e)) return !1;
420
466
  return !0;
421
467
  }, {
422
- message: "V+�echny tokeny v textu mus+� m+�t definici v blanks a v+�echny definice mus+� b+�t pou+�ity v textu",
468
+ message: "All tokens in text must have definition in blanks and all definitions must be used in text",
423
469
  path: ["blanks"]
424
- }), Ne = F.extend({
470
+ }), Ve = k.extend({
425
471
  type: e.literal("fill-in-select"),
426
- question: h,
427
- text: m.max(1e4, "Text nesm+� b+�t del+�+� ne+� 10000 znak+�"),
428
- blanks: e.record(e.string(), I)
472
+ question: b,
473
+ text: y.max(1e4, "Text must not be longer than 10000 characters"),
474
+ blanks: e.record(e.string(), Me)
429
475
  }).refine((e) => Object.keys(e.blanks).length > 0, {
430
- message: "Text mus+� obsahovat alespo+� 1 mezeru k v+�b��ru",
476
+ message: "Text must contain at least 1 blank to select",
431
477
  path: ["blanks"]
432
478
  }).refine((e) => {
433
479
  let t = /<blank:([a-zA-Z0-9_-]{1,64})\s*\/>/g, n = /* @__PURE__ */ new Set(), r;
@@ -437,95 +483,95 @@ var s = e.string().uuid({ message: "Neplatn+� form+�t UUID" }), c = e.string
437
483
  for (let e of i) if (!n.has(e)) return !1;
438
484
  return !0;
439
485
  }, {
440
- message: "V+�echny tokeny v textu mus+� m+�t definici v blanks a v+�echny definice mus+� b+�t pou+�ity v textu",
486
+ message: "All tokens in text must have definition in blanks and all definitions must be used in text",
441
487
  path: ["blanks"]
442
- }), Pe = F.extend({
488
+ }), He = k.extend({
443
489
  type: e.literal("match-pairs"),
444
- question: h,
445
- prompts: e.array(m).min(2, "Mus+� b+�t alespo+� 2 p+�ry k p+�i+�azen+�"),
446
- matches: e.array(m).min(2, "Mus+� b+�t alespo+� 2 p+�ry k p+�i+�azen+�")
490
+ question: b,
491
+ prompts: e.array(y).min(2, "Must have at least 2 pairs to match"),
492
+ matches: e.array(y).min(2, "Must have at least 2 pairs to match")
447
493
  }).refine((e) => e.prompts.length === e.matches.length, {
448
- message: "Po��et ot+�zek (prompts) mus+� b+�t stejn+� jako po��et odpov��d+� (matches)",
494
+ message: "Number of prompts must match number of matches",
449
495
  path: ["matches"]
450
- }), Fe = F.extend({
496
+ }), Ue = k.extend({
451
497
  type: e.literal("match-complex"),
452
- question: h,
453
- leftItems: e.array(m).min(1, "Mus+� b+�t alespo+� 1 polo+�ka vlevo"),
454
- rightItems: e.array(m).min(1, "Mus+� b+�t alespo+� 1 polo+�ka vpravo"),
455
- connections: e.array(e.tuple([e.number().int().nonnegative(), e.number().int().nonnegative()])).min(1, "Mus+� b+�t alespo+� 1 propojen+�"),
498
+ question: b,
499
+ leftItems: e.array(y).min(1, "Must have at least 1 item on left"),
500
+ rightItems: e.array(y).min(1, "Must have at least 1 item on right"),
501
+ connections: e.array(e.tuple([e.number().int().nonnegative(), e.number().int().nonnegative()])).min(1, "Must have at least 1 connection"),
456
502
  minCorrect: e.number().int().positive().optional()
457
503
  }).refine((e) => e.connections.every(([t, n]) => t < e.leftItems.length && n < e.rightItems.length), {
458
- message: "N��kter+� propojen+� odkazuje na neexistuj+�c+� polo+�ku",
504
+ message: "Some connection references non-existent item",
459
505
  path: ["connections"]
460
506
  }).refine((e) => new Set(e.connections.map((e) => `${e[0]}-${e[1]}`)).size === e.connections.length, {
461
- message: "Propojen+� obsahuj+� duplicity",
507
+ message: "Connections contain duplicates",
462
508
  path: ["connections"]
463
509
  }).refine((e) => e.minCorrect ? e.minCorrect <= e.connections.length : !0, {
464
- message: "Minim+�ln+� po��et spr+�vn+�ch odpov��d+� nesm+� p+�es+�hnout celkov+� po��et propojen+�",
510
+ message: "Minimum correct answers must not exceed total number of connections",
465
511
  path: ["minCorrect"]
466
- }), Ie = F.extend({
512
+ }), We = k.extend({
467
513
  type: e.literal("sort-items"),
468
- question: m.max(1e4, "Ot+�zka nesm+� b+�t del+�+� ne+� 10000 znak+�"),
469
- items: e.array(m).min(2, "Mus+� b+�t alespo+� 2 polo+�ky k se+�azen+�")
470
- }), Le = F.extend({
514
+ question: y.max(1e4, "Question must not be longer than 10000 characters"),
515
+ items: e.array(y).min(2, "Must have at least 2 items to sort")
516
+ }), Ge = k.extend({
471
517
  type: e.literal("slider"),
472
- question: m.max(1e4, "Ot+�zka nesm+� b+�t del+�+� ne+� 10000 znak+�"),
518
+ question: y.max(1e4, "Question must not be longer than 10000 characters"),
473
519
  min: e.number(),
474
520
  max: e.number(),
475
- step: e.number().positive("Krok mus+� b+�t kladn+� ��+�slo"),
521
+ step: e.number().positive("Step must be a positive number"),
476
522
  correctAnswer: e.number(),
477
- tolerance: e.number().nonnegative("Tolerance mus+� b+�t nez+�porn+�"),
523
+ tolerance: e.number().nonnegative("Tolerance must be non-negative"),
478
524
  unit: e.string().optional()
479
525
  }).refine((e) => e.min < e.max, {
480
- message: "Minim+�ln+� hodnota mus+� b+�t men+�+� ne+� maxim+�ln+� hodnota",
526
+ message: "Minimum value must be less than maximum value",
481
527
  path: ["max"]
482
528
  }).refine((e) => e.correctAnswer >= e.min && e.correctAnswer <= e.max, {
483
- message: "Spr+�vn+� odpov���� mus+� b+�t v rozmez+� min-max",
529
+ message: "Correct answer must be in range min-max",
484
530
  path: ["correctAnswer"]
485
531
  }).refine((e) => {
486
532
  let t = (e.correctAnswer - e.min) / e.step;
487
533
  return Math.abs(t - Math.round(t)) < 1e-4;
488
534
  }, {
489
- message: "Spr+�vn+� odpov���� mus+� b+�t dosa+�iteln+� pomoc+� definovan+�ho kroku",
535
+ message: "Correct answer must be reachable by defined step",
490
536
  path: ["correctAnswer"]
491
537
  }).refine((e) => e.tolerance <= (e.max - e.min) / 2, {
492
- message: "Tolerance nesm+� b+�t v��t+�+� ne+� polovina rozsahu hodnot",
538
+ message: "Tolerance must not be greater than half of value range",
493
539
  path: ["tolerance"]
494
- }), Re = F.extend({
540
+ }), Ke = k.extend({
495
541
  type: e.literal("pin-on-image"),
496
- question: m.max(1e4, "Ot+�zka nesm+� b+�t del+�+� ne+� 10000 znak+�"),
497
- targetAsset: f,
498
- hotspots: e.array(V).min(1, "Mus+� b+�t alespo+� 1 hotspot"),
542
+ question: y.max(1e4, "Question must not be longer than 10000 characters"),
543
+ targetAsset: _,
544
+ hotspots: e.array(P).min(1, "Must have at least 1 hotspot"),
499
545
  multipleCorrect: e.boolean().optional(),
500
546
  minCorrect: e.number().int().positive().optional()
501
547
  }).refine((e) => e.minCorrect ? e.minCorrect <= e.hotspots.length : !0, {
502
- message: "Minim+�ln+� po��et spr+�vn+�ch odpov��d+� nesm+� p+�es+�hnout po��et hotspot+�",
548
+ message: "Minimum correct answers must not exceed number of hotspots",
503
549
  path: ["minCorrect"]
504
- }), ze = F.extend({
550
+ }), qe = k.extend({
505
551
  type: e.literal("categorize"),
506
- question: m.max(1e4, "Ot+�zka nesm+� b+�t del+�+� ne+� 10000 znak+�"),
507
- categories: e.array(p).min(2, "Mus+� b+�t alespo+� 2 kategorie"),
508
- items: e.array(be).min(1, "Mus+� b+�t alespo+� 1 polo+�ka ke kategorizaci")
552
+ question: y.max(1e4, "Question must not be longer than 10000 characters"),
553
+ categories: e.array(v).min(2, "Must have at least 2 categories"),
554
+ items: e.array(L).min(1, "Must have at least 1 item to categorize")
509
555
  }).refine((e) => e.items.every((t) => t.correctCategoryIndex < e.categories.length), {
510
- message: "N��kter+� polo+�ka odkazuje na neexistuj+�c+� kategorii",
556
+ message: "Some item references non-existent category",
511
557
  path: ["items"]
512
- }), Be = F.extend({
558
+ }), Je = k.extend({
513
559
  type: e.literal("timeline"),
514
- question: m.max(1e4, "Ot+�zka nesm+� b+�t del+�+� ne+� 10000 znak+�"),
515
- events: e.array(Se).min(2, "Mus+� b+�t alespo+� 2 ud+�losti"),
560
+ question: y.max(1e4, "Question must not be longer than 10000 characters"),
561
+ events: e.array(z).min(2, "Must have at least 2 events"),
516
562
  randomize: e.boolean().optional()
517
- }), Ve = F.extend({
563
+ }), Ye = k.extend({
518
564
  type: e.literal("matrix"),
519
- question: m.max(1e4, "Ot+�zka nesm+� b+�t del+�+� ne+� 10000 znak+�"),
520
- rows: e.array(p).min(1, "Mus+� b+�t alespo+� 1 +�+�dek"),
521
- columns: e.array(p).min(1, "Mus+� b+�t alespo+� 1 sloupec"),
522
- correctCells: e.array(e.tuple([e.number().int().nonnegative(), e.number().int().nonnegative()])).min(1, "Mus+� b+�t alespo+� 1 spr+�vn+� bu+�ka"),
565
+ question: y.max(1e4, "Question must not be longer than 10000 characters"),
566
+ rows: e.array(v).min(1, "Must have at least 1 row"),
567
+ columns: e.array(v).min(1, "Must have at least 1 column"),
568
+ correctCells: e.array(e.tuple([e.number().int().nonnegative(), e.number().int().nonnegative()])).min(1, "Must have at least 1 correct cell"),
523
569
  multiplePerRow: e.boolean().optional()
524
570
  }).refine((e) => e.correctCells.every(([t, n]) => t < e.rows.length && n < e.columns.length), {
525
- message: "N��kter+� sou+�adnice bu+�ky odkazuj+� na neexistuj+�c+� +�+�dek nebo sloupec",
571
+ message: "Some cell coordinates reference non-existent row or column",
526
572
  path: ["correctCells"]
527
573
  }).refine((e) => new Set(e.correctCells.map((e) => `${e[0]}-${e[1]}`)).size === e.correctCells.length, {
528
- message: "Spr+�vn+� bu+�ky obsahuj+� duplicity",
574
+ message: "Correct cells contain duplicates",
529
575
  path: ["correctCells"]
530
576
  }).refine((e) => {
531
577
  if (!e.multiplePerRow) {
@@ -535,68 +581,60 @@ var s = e.string().uuid({ message: "Neplatn+� form+�t UUID" }), c = e.string
535
581
  }
536
582
  return !0;
537
583
  }, {
538
- message: "Pokud multiplePerRow je false, ka+�d+� +�+�dek sm+� m+�t maxim+�ln�� 1 spr+�vnou bu+�ku",
584
+ message: "If multiplePerRow is false, each row may have maximum 1 correct cell",
539
585
  path: ["correctCells"]
540
- }), He = F.extend({
586
+ }), Xe = k.extend({
541
587
  type: e.literal("math-input"),
542
- question: m.max(1e4, "Ot+�zka nesm+� b+�t del+�+� ne+� 10000 znak+�"),
543
- correctAnswer: p,
544
- alternativeAnswers: e.array(p).optional(),
588
+ question: y.max(1e4, "Question must not be longer than 10000 characters"),
589
+ correctAnswer: v,
590
+ alternativeAnswers: e.array(v).optional(),
545
591
  tolerance: e.number().nonnegative().optional()
546
- }), Ue = F.extend({
592
+ }), Ze = k.extend({
547
593
  type: e.literal("diagram-label"),
548
- question: m.max(1e4, "Ot+�zka nesm+� b+�t del+�+� ne+� 10000 znak+�"),
549
- targetAsset: f,
550
- labels: e.array(m).min(1, "Mus+� b+�t alespo+� 1 +�t+�tek"),
594
+ question: y.max(1e4, "Question must not be longer than 10000 characters"),
595
+ targetAsset: _,
596
+ labels: e.array(y).min(1, "Must have at least 1 label"),
551
597
  caseSensitive: e.boolean().optional(),
552
598
  requireTyping: e.boolean().optional(),
553
- zones: e.array(Ce).min(1, "Mus+� b+�t alespo+� 1 z+-na")
599
+ zones: e.array(B).min(1, "Must have at least 1 zone")
554
600
  }).refine((e) => e.zones.every((t) => t.correctLabelIndex < e.labels.length), {
555
- message: "N��kter+� z+-na odkazuje na neexistuj+�c+� +�t+�tek",
601
+ message: "Some zone references non-existent label",
556
602
  path: ["zones"]
557
- }), We = F.extend({
603
+ }), Qe = k.extend({
558
604
  type: e.literal("open-ended"),
559
- question: m.max(1e4, "Ot+�zka nesm+� b+�t del+�+� ne+� 10000 znak+�"),
605
+ question: y.max(1e4, "Question must not be longer than 10000 characters"),
560
606
  minWords: e.number().int().positive().optional(),
561
607
  maxWords: e.number().int().positive().optional(),
562
- sampleAnswer: m.optional(),
563
- rubric: Te.optional()
608
+ sampleAnswer: y.optional(),
609
+ rubric: H.optional()
564
610
  }).refine((e) => e.minWords && e.maxWords ? e.minWords <= e.maxWords : !0, {
565
- message: "Minim+�ln+� po��et slov mus+� b+�t men+�+� nebo roven maxim+�ln+�mu po��tu",
611
+ message: "Minimum word count must be less than or equal to maximum",
566
612
  path: ["maxWords"]
567
- }), Ge = F.extend({
613
+ }), $e = k.extend({
568
614
  type: e.literal("numeric-input"),
569
- question: m.max(1e4, "Ot+�zka nesm+� b+�t del+�+� ne+� 10000 znak+�"),
615
+ question: y.max(1e4, "Question must not be longer than 10000 characters"),
570
616
  value: e.number(),
571
617
  tolerance: e.number().nonnegative().optional(),
572
- range: Ee.optional(),
618
+ range: Ne.optional(),
573
619
  unit: e.string().optional()
574
- }), Ke = F.extend({
620
+ }), et = k.extend({
575
621
  type: e.literal("pin-on-model"),
576
- question: m.max(1e4, "Ot+�zka nesm+� b+�t del+�+� ne+� 10000 znak+�"),
577
- targetAsset: f,
578
- hotspots: e.array(B).min(1, "Mus+� b+�t alespo+� 1 hotspot"),
622
+ question: y.max(1e4, "Question must not be longer than 10000 characters"),
623
+ targetAsset: _,
624
+ hotspots: e.array(N).min(1, "Must have at least 1 hotspot"),
579
625
  multipleCorrect: e.boolean().optional(),
580
626
  minCorrect: e.number().int().positive().optional(),
581
- camera: U.optional()
627
+ camera: I.optional()
582
628
  }).refine((e) => e.minCorrect ? e.minCorrect <= e.hotspots.length : !0, {
583
- message: "Minim+�ln+� po��et spr+�vn+�ch odpov��d+� nesm+� p+�es+�hnout po��et hotspot+�",
629
+ message: "Minimum correct answers must not exceed number of hotspots",
584
630
  path: ["minCorrect"]
585
- }), qe = F.extend({
631
+ }), tt = k.extend({
586
632
  type: e.literal("chess-puzzle"),
587
- question: m.max(1e4, "Ot+�zka nesm+� b+�t del+�+� ne+� 10000 znak+�"),
588
- fen: p,
589
- answers: e.array(e.array(p).min(1, "Sekvence tah+� nesm+� b+�t pr+�zdn+�")).min(1, "Mus+� b+�t alespo+� 1 spr+�vn+� sekvence tah+�"),
590
- elo: e.number().int().nonnegative("ELO mus+� b+�t nez+�porn+� cel+� ��+�slo").optional()
591
- }), G = e.discriminatedUnion("type", [
592
- De,
593
- Oe,
594
- ke,
595
- Ae,
596
- je,
597
- W,
598
- Me,
599
- Ne,
633
+ question: y.max(1e4, "Question must not be longer than 10000 characters"),
634
+ fen: v,
635
+ answers: e.array(e.array(v).min(1, "Move sequence must not be empty")).min(1, "Must have at least 1 correct move sequence"),
636
+ elo: e.number().int().nonnegative("ELO must be non-negative integer").optional()
637
+ }), U = e.discriminatedUnion("type", [
600
638
  Pe,
601
639
  Fe,
602
640
  Ie,
@@ -610,12 +648,20 @@ var s = e.string().uuid({ message: "Neplatn+� form+�t UUID" }), c = e.string
610
648
  We,
611
649
  Ge,
612
650
  Ke,
613
- qe
614
- ]), K = e.object({
651
+ qe,
652
+ Je,
653
+ Ye,
654
+ Xe,
655
+ Ze,
656
+ Qe,
657
+ $e,
658
+ et,
659
+ tt
660
+ ]), W = e.object({
615
661
  $schema: e.string().url().optional(),
616
- version: e.string().regex(/^\d+\.\d+$/, "Verze musi byt ve formatu \"X.Y\" (napr. \"0.1\")"),
617
- meta: P,
618
- items: e.array(G).max(1e4, "Maxim+�ln�� 10000 polo+�ek na sadu")
662
+ version: e.string().regex(/^\d+\.\d+$/, "Version must be in MAJOR.MINOR format (e.g. \"0.1\")"),
663
+ meta: je,
664
+ items: e.array(U).max(1e4, "Maximum 10000 items per set")
619
665
  }).refine((e) => {
620
666
  let t = new Set(e.items.map((e) => e.id));
621
667
  for (let n of e.items) {
@@ -628,10 +674,10 @@ var s = e.string().uuid({ message: "Neplatn+� form+�t UUID" }), c = e.string
628
674
  }
629
675
  return !0;
630
676
  }, {
631
- message: "N��kter+� polo+�ka odkazuje na neexistuj+�c+� relatedItems nebo dependencyItems",
677
+ message: "Some item references non-existent relatedItems or dependencyItems",
632
678
  path: ["items"]
633
679
  }).refine((e) => e.meta.thumbnail && e.meta.assets ? e.meta.thumbnail in e.meta.assets : !0, {
634
- message: "Thumbnail odkazuje na neexistuj+�c+� asset",
680
+ message: "Thumbnail references non-existent asset",
635
681
  path: ["meta", "thumbnail"]
636
682
  }).refine((e) => {
637
683
  let t = new Set((e.meta.sourceMaterials || []).map((e) => e.id));
@@ -640,14 +686,14 @@ var s = e.string().uuid({ message: "Neplatn+� form+�t UUID" }), c = e.string
640
686
  }
641
687
  return !0;
642
688
  }, {
643
- message: "N��kter+� polo+�ka odkazuje na neexistuj+�c+� source material",
689
+ message: "Some item references non-existent source material",
644
690
  path: ["items"]
645
691
  });
646
- function Je(e) {
647
- return K.parse(e);
692
+ function nt(e) {
693
+ return W.parse(e);
648
694
  }
649
- function Ye(e) {
650
- let t = K.safeParse(e);
695
+ function rt(e) {
696
+ let t = W.safeParse(e);
651
697
  return t.success ? {
652
698
  success: !0,
653
699
  data: t.data
@@ -656,11 +702,11 @@ function Ye(e) {
656
702
  error: t.error
657
703
  };
658
704
  }
659
- function Xe(e) {
660
- return G.parse(e);
705
+ function it(e) {
706
+ return U.parse(e);
661
707
  }
662
- function Ze(e) {
663
- let t = G.safeParse(e);
708
+ function at(e) {
709
+ let t = U.safeParse(e);
664
710
  return t.success ? {
665
711
  success: !0,
666
712
  data: t.data
@@ -669,128 +715,96 @@ function Ze(e) {
669
715
  error: t.error
670
716
  };
671
717
  }
672
- function Qe(e) {
718
+ function ot(e) {
673
719
  return e.issues.map((e) => {
674
- let t = e.path.join(" ��� ");
675
- return t ? `${t}: ${e.message}` : e.message;
720
+ let t = "";
721
+ return e.path.forEach((n, r) => {
722
+ if (typeof n == "number") t += `[${n}]`;
723
+ else {
724
+ let i = r === 0 || typeof e.path[r - 1] == "number";
725
+ t += (i ? "" : ".") + String(n);
726
+ }
727
+ }), t ? `${t}: ${e.message}` : e.message;
676
728
  });
677
729
  }
678
730
  //#endregion
679
- //#region src/manifest.ts
680
- function q(e) {
681
- return /^\d+\.\d+$/.test(e);
682
- }
683
- function $e(e) {
684
- return /^\d+\.\d+\.\d+(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$/.test(e);
685
- }
686
- function J(e, t) {
687
- let [n = 0, r = 0] = e.split(".").map(Number), [i = 0, a = 0] = t.split(".").map(Number);
688
- return n === i ? r - a : n - i;
689
- }
690
- function et(e) {
691
- if (typeof e != "object" || !e) return !1;
692
- let t = e;
693
- return typeof t.version == "string" && typeof t.id == "string" && typeof t.appName == "string" && t.appName !== "" && typeof t.capabilities == "object" && t.capabilities !== null && Array.isArray(t.capabilities.actions);
694
- }
695
- function tt(e, t) {
696
- return !(!q(e) || t.minOqseVersion && q(t.minOqseVersion) && J(e, t.minOqseVersion) < 0 || t.maxOqseVersion && q(t.maxOqseVersion) && J(e, t.maxOqseVersion) > 0);
697
- }
698
- //#endregion
699
731
  //#region src/manifestValidation.ts
700
- var Y = e.string().min(1, "Hodnota nesm+� b+�t pr+�zdn+�").trim(), nt = e.string().url("Mus+� b+�t platn+� absolutn+� URL").refine((e) => e.startsWith("http://") || e.startsWith("https://"), { message: "URL mus+� pou+�+�vat sch+�ma http nebo https" }), X = e.string().regex(/^\d+\.\d+$/, "Verze mus+� b+�t ve form+�tu MAJOR.MINOR (nap+�. \"0.1\")"), rt = e.string().regex(/^\d+\.\d+\.\d+$/, "Verze mus+� b+�t ve form+�tu MAJOR.MINOR.PATCH (nap+�. \"1.2.3\")"), it = [
701
- "render",
702
- "edit",
703
- "validate",
704
- "import",
705
- "export"
706
- ], at = e.string().refine((e) => it.includes(e) || e.startsWith("x-"), { message: "Akce mus+� b+�t jedna z [render, edit, validate, import, export] nebo m+�t prefix \"x-\"" }), ot = e.enum([
732
+ var G = e.string().min(1, "Value must not be empty").trim(), st = e.string().url("Must be a valid absolute URL").refine((e) => e.startsWith("http://") || e.startsWith("https://"), { message: "URL must use http or https scheme" }), K = e.string().regex(/^\d+\.\d+$/, "Version must be in MAJOR.MINOR format (e.g. \"0.1\")"), ct = e.string().regex(/^\d+\.\d+\.\d+$/, "Version must be in MAJOR.MINOR.PATCH format (e.g. \"1.2.3\")"), lt = e.string().refine((e) => ve.includes(e) || e.startsWith("x-"), { message: "Action must be one of [render, edit, validate, import, export] or have prefix \"x-\"" }), ut = e.enum([
707
733
  "game",
708
734
  "fun",
709
735
  "drill"
710
- ]), st = e.enum([
736
+ ]), dt = e.enum([
711
737
  "low",
712
738
  "medium",
713
739
  "high"
714
- ]), ct = [
715
- "math",
716
- "media",
717
- "media-image",
718
- "media-audio",
719
- "media-video",
720
- "media-model",
721
- "hotspots",
722
- "hotspots-3d",
723
- "complex-pairing",
724
- "open-text",
725
- "chess"
726
- ], lt = e.string().refine((e) => ct.includes(e) || e.startsWith("x-"), { message: "Funkce mus+� b+�t jedna z ofici+�ln+�ch kl+���+� nebo m+�t prefix \"x-\"" }), ut = e.string().min(1, "Kl+��� vlastnosti polo+�ky nesm+� b+�t pr+�zdn+�"), dt = e.string().min(1, "Kl+��� vlastnosti metadat nesm+� b+�t pr+�zdn+�");
727
- function Z(t) {
740
+ ]), ft = e.string().refine((e) => s.includes(e) || e.startsWith("x-"), { message: "Feature must be one of official keys or have prefix \"x-\"" }), pt = e.string().refine((e) => c.includes(e) || e.startsWith("x-"), { message: "Item property must be an official key or have prefix \"x-\"" }), mt = e.string().refine((e) => l.includes(e) || e.startsWith("x-"), { message: "Meta property must be an official key or have prefix \"x-\"" });
741
+ function q(t) {
728
742
  return e.union([
729
743
  e.tuple([e.literal("*")]),
730
744
  e.array(t),
731
745
  e.null()
732
746
  ]);
733
747
  }
734
- var ft = e.string().refine((e) => e.startsWith("image/"), { message: "Mus+� b+�t platn+� MIME typ obr+�zku (image/...)" }), pt = e.string().refine((e) => e.startsWith("audio/"), { message: "Mus+� b+�t platn+� MIME typ zvuku (audio/...)" }), mt = e.string().refine((e) => e.startsWith("video/"), { message: "Mus+� b+�t platn+� MIME typ videa (video/...)" }), ht = e.string().refine((e) => e.startsWith("model/") || e === "application/octet-stream", { message: "Mus+� b+�t platn+� MIME typ 3D modelu (model/... nebo application/octet-stream)" }), gt = e.object({
735
- image: Z(ft).optional(),
736
- audio: Z(pt).optional(),
737
- video: Z(mt).optional(),
738
- model: Z(ht).optional()
739
- }), _t = w.extend({
740
- actions: e.array(at).min(1, "Aplikace mus+� podporovat alespo+� jednu akci"),
741
- types: Z(Y).optional(),
742
- assets: gt.optional()
743
- }), Q = e.object({
744
- $schema: nt.optional(),
745
- id: Y.regex(/^[a-z0-9-]+(\.[a-z0-9-]+)*$/, "ID mus+� b+�t ve tvaru reverse-domain (nap+�. \"com.acme.app\")"),
746
- appName: Y.max(100, "N+�zev nesm+� b+�t del+�+� ne+� 100 znak+�"),
747
- version: X,
748
- pluginVersion: rt.optional(),
749
- minOqseVersion: X.optional(),
750
- maxOqseVersion: X.optional(),
751
- capabilities: _t,
752
- author: e.string().max(100, "N+�zev autora nesm+� b+�t del+�+� ne+� 100 znak+�").optional(),
753
- authorUrl: nt.optional(),
754
- locales: e.array(Y).optional(),
755
- description: e.string().max(500, "Popis nesm+� b+�t del+�+� ne+� 500 znak+�").optional(),
748
+ var ht = e.string().refine((e) => e.startsWith("image/"), { message: "Must be a valid image MIME type (image/...)" }), gt = e.string().refine((e) => e.startsWith("audio/"), { message: "Must be a valid audio MIME type (audio/...)" }), _t = e.string().refine((e) => e.startsWith("video/"), { message: "Must be a valid video MIME type (video/...)" }), vt = e.string().refine((e) => e.startsWith("model/") || e === "application/octet-stream", { message: "Must be a valid 3D model MIME type (model/... or application/octet-stream)" }), yt = e.object({
749
+ image: q(ht).optional(),
750
+ audio: q(gt).optional(),
751
+ video: q(_t).optional(),
752
+ model: q(vt).optional()
753
+ }), bt = D.extend({
754
+ actions: e.array(lt).min(1, "Application must support at least one action"),
755
+ types: q(G).optional(),
756
+ assets: yt.optional()
757
+ }), J = e.object({
758
+ $schema: st.optional(),
759
+ id: G.regex(/^[a-z0-9-]+(\.[a-z0-9-]+)*$/, "ID must be in reverse-domain format (e.g. \"com.acme.app\")"),
760
+ appName: G.max(100, "Name must not be longer than 100 characters"),
761
+ version: K,
762
+ pluginVersion: ct.optional(),
763
+ minOqseVersion: K.optional(),
764
+ maxOqseVersion: K.optional(),
765
+ capabilities: bt,
766
+ author: e.string().max(100, "Author name must not be longer than 100 characters").optional(),
767
+ authorUrl: st.optional(),
768
+ locales: e.array(G).optional(),
769
+ description: e.string().max(500, "Description must not be longer than 500 characters").optional(),
756
770
  emoji: e.string().optional(),
757
- tags: e.array(Y).optional(),
758
- studyMode: ot.optional(),
759
- questionDensity: st.optional(),
771
+ tags: e.array(G).optional(),
772
+ studyMode: ut.optional(),
773
+ questionDensity: dt.optional(),
760
774
  appSpecific: e.record(e.string(), e.unknown()).optional()
761
775
  }).refine((e) => {
762
776
  if (!e.minOqseVersion || !e.maxOqseVersion) return !0;
763
- let t = e.minOqseVersion.split("."), n = e.maxOqseVersion.split("."), r = Number(t[0]), i = Number(t[1]), a = Number(n[0]), ee = Number(n[1]);
764
- return r === a ? i <= ee : r < a;
777
+ let t = e.minOqseVersion.split("."), n = e.maxOqseVersion.split("."), r = Number(t[0]), i = Number(t[1]), a = Number(n[0]), o = Number(n[1]);
778
+ return r === a ? i <= o : r < a;
765
779
  }, {
766
- message: "minOqseVersion nesm+� b+�t vy+�+�+� ne+� maxOqseVersion",
780
+ message: "minOqseVersion must not be greater than maxOqseVersion",
767
781
  path: ["minOqseVersion"]
768
782
  });
769
- function vt(e) {
770
- return Q.parse(e);
783
+ function xt(e) {
784
+ return J.parse(e);
771
785
  }
772
- function yt(e) {
773
- return Q.safeParse(e);
786
+ function St(e) {
787
+ return J.safeParse(e);
774
788
  }
775
- function bt(e) {
789
+ function Ct(e) {
776
790
  return e.issues.map((e) => {
777
791
  let t = e.path.map((e) => String(e)).join(".");
778
792
  return t ? `${t}: ${e.message}` : e.message;
779
793
  }).join("\n");
780
794
  }
781
- function xt(e) {
782
- return Q.safeParse(e).success;
795
+ function wt(e) {
796
+ return J.safeParse(e).success;
783
797
  }
784
798
  //#endregion
785
799
  //#region src/progressValidation.ts
786
- var St = e.object({
800
+ var Tt = e.object({
787
801
  attempts: e.number().int().nonnegative(),
788
802
  incorrect: e.number().int().nonnegative(),
789
803
  streak: e.number().int().nonnegative()
790
804
  }).refine((e) => e.incorrect <= e.attempts, {
791
- message: "incorrect nesmí být vyšší než attempts",
805
+ message: "incorrect cannot be higher than attempts",
792
806
  path: ["incorrect"]
793
- }), Ct = e.object({
807
+ }), Y = e.object({
794
808
  isCorrect: e.boolean(),
795
809
  confidence: e.union([
796
810
  e.literal(1),
@@ -798,14 +812,14 @@ var St = e.object({
798
812
  e.literal(3),
799
813
  e.literal(4)
800
814
  ]).optional(),
801
- answeredAt: u,
815
+ answeredAt: h,
802
816
  timeSpent: e.number().int().nonnegative().optional(),
803
817
  hintsUsed: e.number().int().nonnegative().optional(),
804
818
  isSkipped: e.boolean().optional()
805
819
  }).refine((e) => !e.isSkipped || e.isCorrect === !1, {
806
- message: "Pokud je isSkipped=true, isCorrect má být false",
820
+ message: "If isSkipped=true, isCorrect must be false",
807
821
  path: ["isCorrect"]
808
- }), wt = e.object({
822
+ }), Et = e.object({
809
823
  bucket: e.union([
810
824
  e.literal(0),
811
825
  e.literal(1),
@@ -813,33 +827,118 @@ var St = e.object({
813
827
  e.literal(3),
814
828
  e.literal(4)
815
829
  ]),
816
- nextReviewAt: u.optional(),
817
- stats: St,
818
- lastAnswer: Ct.optional(),
830
+ nextReviewAt: h.optional(),
831
+ stats: Tt,
832
+ lastAnswer: Y.optional(),
819
833
  appSpecific: e.record(e.string(), e.unknown()).optional()
820
- }), Tt = e.object({
821
- setId: s,
822
- exportedAt: u,
823
- algorithm: e.string().regex(/^[a-z0-9-]+$/, "algorithm musí mít formát lowercase alphanumeric s pomlčkami").optional()
824
- }), $ = e.object({
834
+ }), Dt = e.object({
835
+ setId: f,
836
+ exportedAt: h,
837
+ algorithm: e.string().regex(/^[a-z0-9-]+$/, "algorithm must be lowercase alphanumeric with hyphens format").optional()
838
+ }), X = e.object({
825
839
  $schema: e.string().url().optional(),
826
- version: e.string().regex(/^\d+\.\d+$/, "Verze musí být ve formátu MAJOR.MINOR"),
827
- meta: Tt,
828
- records: e.record(s, wt)
840
+ version: e.string().regex(/^\d+\.\d+$/, "Version must be in MAJOR.MINOR format"),
841
+ meta: Dt,
842
+ records: e.record(f, Et)
829
843
  });
830
- function Et(e) {
831
- return $.parse(e);
844
+ function Ot(e) {
845
+ return X.parse(e);
846
+ }
847
+ function kt(e) {
848
+ return X.safeParse(e);
849
+ }
850
+ //#endregion
851
+ //#region node_modules/uuid/dist/regex.js
852
+ var At = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/i;
853
+ //#endregion
854
+ //#region node_modules/uuid/dist/validate.js
855
+ function jt(e) {
856
+ return typeof e == "string" && At.test(e);
857
+ }
858
+ //#endregion
859
+ //#region node_modules/uuid/dist/stringify.js
860
+ var Z = [];
861
+ for (let e = 0; e < 256; ++e) Z.push((e + 256).toString(16).slice(1));
862
+ function Mt(e, t = 0) {
863
+ return (Z[e[t + 0]] + Z[e[t + 1]] + Z[e[t + 2]] + Z[e[t + 3]] + "-" + Z[e[t + 4]] + Z[e[t + 5]] + "-" + Z[e[t + 6]] + Z[e[t + 7]] + "-" + Z[e[t + 8]] + Z[e[t + 9]] + "-" + Z[e[t + 10]] + Z[e[t + 11]] + Z[e[t + 12]] + Z[e[t + 13]] + Z[e[t + 14]] + Z[e[t + 15]]).toLowerCase();
864
+ }
865
+ //#endregion
866
+ //#region node_modules/uuid/dist/rng.js
867
+ var Q, Nt = new Uint8Array(16);
868
+ function Pt() {
869
+ if (!Q) {
870
+ if (typeof crypto > "u" || !crypto.getRandomValues) throw Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");
871
+ Q = crypto.getRandomValues.bind(crypto);
872
+ }
873
+ return Q(Nt);
874
+ }
875
+ //#endregion
876
+ //#region node_modules/uuid/dist/v7.js
877
+ var $ = {};
878
+ function Ft(e, t, n) {
879
+ let r;
880
+ if (e) r = Lt(e.random ?? e.rng?.() ?? Pt(), e.msecs, e.seq, t, n);
881
+ else {
882
+ let e = Date.now(), i = Pt();
883
+ It($, e, i), r = Lt(i, $.msecs, $.seq, t, n);
884
+ }
885
+ return t ?? Mt(r);
832
886
  }
833
- function Dt(e) {
834
- return $.safeParse(e);
887
+ function It(e, t, n) {
888
+ return e.msecs ??= -Infinity, e.seq ??= 0, t > e.msecs ? (e.seq = n[6] << 23 | n[7] << 16 | n[8] << 8 | n[9], e.msecs = t) : (e.seq = e.seq + 1 | 0, e.seq === 0 && e.msecs++), e;
889
+ }
890
+ function Lt(e, t, n, r, i = 0) {
891
+ if (e.length < 16) throw Error("Random bytes length must be >= 16");
892
+ if (!r) r = new Uint8Array(16), i = 0;
893
+ else if (i < 0 || i + 16 > r.length) throw RangeError(`UUID byte range ${i}:${i + 15} is out of buffer bounds`);
894
+ return t ??= Date.now(), n ??= e[6] * 127 << 24 | e[7] << 16 | e[8] << 8 | e[9], r[i++] = t / 1099511627776 & 255, r[i++] = t / 4294967296 & 255, r[i++] = t / 16777216 & 255, r[i++] = t / 65536 & 255, r[i++] = t / 256 & 255, r[i++] = t & 255, r[i++] = 112 | n >>> 28 & 15, r[i++] = n >>> 20 & 255, r[i++] = 128 | n >>> 14 & 63, r[i++] = n >>> 6 & 255, r[i++] = n << 2 & 255 | e[10] & 3, r[i++] = e[11], r[i++] = e[12], r[i++] = e[13], r[i++] = e[14], r[i++] = e[15], r;
835
895
  }
836
896
  //#endregion
837
897
  //#region src/utils.ts
838
- function Ot(e) {
839
- return s.safeParse(e).success;
898
+ function Rt(e) {
899
+ return jt(e);
900
+ }
901
+ function zt() {
902
+ return Ft();
840
903
  }
841
- function kt() {
842
- return crypto.randomUUID();
904
+ //#endregion
905
+ //#region src/richTextProcessor.ts
906
+ function Bt(e) {
907
+ let t = {};
908
+ return {
909
+ text: e.replace(/<(asset|blank):([a-zA-Z0-9_-]+)\s*\/>/gi, (e, n, r) => {
910
+ let i = `[[__OQSE_TOKEN_${Math.random().toString(36).substring(2, 15)}__]]`;
911
+ return t[i] = {
912
+ type: n.toLowerCase(),
913
+ key: r.toLowerCase(),
914
+ originalTag: e
915
+ }, i;
916
+ }),
917
+ tokens: t
918
+ };
919
+ }
920
+ function Vt(e) {
921
+ let t = e.replace(/`{1,}[^`]*`{1,}/g, "").replace(/~{3,}[\s\S]*?~{3,}/g, "");
922
+ if (/<[a-zA-Z\/][^>]*>/.test(t)) throw Error("OQSE Security Error: Raw HTML tags are not allowed in Tier 1 (Pure Markdown). If the set requires HTML formatting, it MUST declare the 'html' feature in meta.requirements.");
923
+ }
924
+ function Ht(e, t, n) {
925
+ let r = e;
926
+ for (let [e, i] of Object.entries(t)) {
927
+ let t = i.originalTag;
928
+ i.type === "asset" && n.assetReplacer ? t = n.assetReplacer(i.key) : i.type === "blank" && n.blankReplacer && (t = n.blankReplacer(i.key)), r = r.replace(e, t);
929
+ }
930
+ return r;
931
+ }
932
+ function Ut(e, t, n) {
933
+ if (!e) return "";
934
+ let r = t?.features?.includes("html") ?? !1, { text: i, tokens: a } = Bt(e);
935
+ r || Vt(i);
936
+ let o = n.markdownParser(i);
937
+ if (r) {
938
+ if (!n.htmlSanitizer) throw Error("OQSE Security Error: Set requires 'html' (Tier 2), but no htmlSanitizer (like DOMPurify) was provided to the options.");
939
+ o = n.htmlSanitizer(o);
940
+ }
941
+ return Ht(o, a, n);
843
942
  }
844
943
  //#endregion
845
- export { d as AbsoluteURLSchema, _ as AssetDictionarySchema, f as AssetKeySchema, pt as AudioMimeTypeSchema, F as BaseItemSchema, k as BloomLevelSchema, U as CameraSetupSchema, be as CategorizeItemSchema, ze as CategorizeItemTypeSchema, qe as ChessPuzzleItemSchema, R as CircleHotspotSchema, A as CognitiveLoadSchema, Ue as DiagramLabelItemSchema, Ce as DiagramZoneSchema, lt as FeatureFlagSchema, w as FeatureProfileSchema, E as FeatureRequirementSchema, T as FeatureTypeSchema, Me as FillInBlanksItemSchema, Ne as FillInSelectItemSchema, Oe as FlashcardItemSchema, V as HotspotObjectSchema, u as ISO8601DateTimeSchema, ft as ImageMimeTypeSchema, ut as ItemPropertyKeySchema, c as LanguageCodeSchema, Ct as LastAnswerObjectSchema, O as LinkedSetObjectSchema, je as MCQMultiItemSchema, Ae as MCQSingleItemSchema, gt as ManifestAssetsSchema, _t as ManifestCapabilitiesSchema, Fe as MatchComplexItemSchema, Pe as MatchPairsItemSchema, He as MathInputItemSchema, M as MathRendererSchema, N as MathSettingsSchema, Ve as MatrixItemSchema, ve as MediaObjectSchema, B as MeshHotspotSchema, dt as MetaPropertyKeySchema, ht as ModelMimeTypeSchema, De as NoteItemSchema, Ge as NumericInputItemSchema, Ee as NumericRangeSchema, at as OQSEActionSchema, K as OQSEFileSchema, G as OQSEItemSchema, Q as OQSEManifestSchema, P as OQSEMetaSchema, $ as OQSEPFileSchema, st as OQSEQuestionDensitySchema, ot as OQSEStudyModeSchema, ye as OfficialFeatureNameSchema, We as OpenEndedItemSchema, h as OptionalRichContentSchema, j as PedagogySchema, v as PersonObjectSchema, Re as PinOnImageItemSchema, Ke as PinOnModelItemSchema, p as PlainTextSchema, z as PolygonHotspotSchema, Tt as ProgressMetaSchema, wt as ProgressRecordSchema, L as RectHotspotSchema, m as RichContentSchema, we as RubricCriterionSchema, Te as RubricSchema, l as SPDXLicenseSchema, I as SelectBlankObjectSchema, W as ShortAnswerItemSchema, Le as SliderItemSchema, Ie as SortItemsItemSchema, b as SourceMaterialSchema, y as SourceMaterialTypeSchema, x as SourceReferenceSchema, St as StatsObjectSchema, g as SubtitleTrackSchema, C as TagDefinitionDictionarySchema, S as TagDefinitionSchema, Se as TimelineEventSchema, Be as TimelineItemSchema, xe as TimelinePrecisionSchema, D as TranslationObjectSchema, ke as TrueFalseItemSchema, s as UUIDSchema, H as Vector3Schema, mt as VideoMimeTypeSchema, J as compareManifestVersions, bt as formatManifestErrors, Qe as formatValidationErrors, kt as generateUUID, ce as isCategorize, ge as isChessPuzzle, o as isCoreItem, fe as isDiagramLabel, _e as isExtendedItem, te as isFillInBlanks, ne as isFillInSelect, n as isFlashcard, a as isMCQMulti, i as isMCQSingle, ie as isMatchComplex, re as isMatchPairs, de as isMathInput, ue as isMatrix, t as isNote, me as isNumericInput, et as isOQSEManifest, pe as isOpenEnded, se as isPinOnImage, he as isPinOnModel, ee as isShortAnswer, oe as isSlider, ae as isSortItems, le as isTimeline, r as isTrueFalse, q as isValidManifestVersion, xt as isValidOQSEManifest, $e as isValidSemVer, Ot as isValidUUID, tt as isVersionCompatible, yt as safeValidateManifest, Ye as safeValidateOQSEFile, Ze as safeValidateOQSEItem, Dt as safeValidateOQSEPFile, vt as validateManifest, Je as validateOQSEFile, Xe as validateOQSEItem, Et as validateOQSEPFile };
944
+ export { g as AbsoluteURLSchema, x as AssetDictionarySchema, _ as AssetKeySchema, gt as AudioMimeTypeSchema, k as BaseItemSchema, Ee as BloomLevelSchema, I as CameraSetupSchema, L as CategorizeItemObjectSchema, qe as CategorizeItemSchema, tt as ChessPuzzleItemSchema, j as CircleHotspotSchema, De as CognitiveLoadSchema, Ze as DiagramLabelItemSchema, B as DiagramZoneSchema, ft as FeatureFlagSchema, D as FeatureProfileSchema, Be as FillInBlanksItemSchema, Ve as FillInSelectItemSchema, Fe as FlashcardItemSchema, P as HotspotObjectSchema, h as ISO8601DateTimeSchema, ht as ImageMimeTypeSchema, pt as ItemPropertyKeySchema, p as LanguageCodeSchema, Y as LastAnswerObjectSchema, O as LinkedSetObjectSchema, Re as MCQMultiItemSchema, Le as MCQSingleItemSchema, yt as ManifestAssetsSchema, bt as ManifestCapabilitiesSchema, Ue as MatchComplexItemSchema, He as MatchPairsItemSchema, Xe as MathInputItemSchema, ke as MathRendererSchema, Ae as MathSettingsSchema, Ye as MatrixItemSchema, Ce as MediaObjectSchema, N as MeshHotspotSchema, mt as MetaPropertyKeySchema, vt as ModelMimeTypeSchema, Pe as NoteItemSchema, $e as NumericInputItemSchema, Ne as NumericRangeSchema, ve as OFFICIAL_ACTIONS, s as OFFICIAL_FEATURE_KEYS, c as OFFICIAL_ITEM_PROPERTIES, l as OFFICIAL_META_PROPERTIES, lt as OQSEActionSchema, W as OQSEFileSchema, U as OQSEItemSchema, J as OQSEManifestSchema, je as OQSEMetaSchema, X as OQSEPFileSchema, dt as OQSEQuestionDensitySchema, ut as OQSEStudyModeSchema, Qe as OpenEndedItemSchema, b as OptionalRichContentSchema, Oe as PedagogySchema, S as PersonObjectSchema, Ke as PinOnImageItemSchema, et as PinOnModelItemSchema, v as PlainTextSchema, M as PolygonHotspotSchema, Dt as ProgressMetaSchema, Et as ProgressRecordSchema, A as RectHotspotSchema, y as RichContentSchema, V as RubricCriterionSchema, H as RubricSchema, m as SPDXLicenseSchema, Me as SelectBlankObjectSchema, ze as ShortAnswerItemSchema, Ge as SliderItemSchema, We as SortItemsItemSchema, w as SourceMaterialSchema, C as SourceMaterialTypeSchema, T as SourceReferenceSchema, Tt as StatsObjectSchema, Se as SubtitleTrackSchema, we as TagDefinitionDictionarySchema, E as TagDefinitionSchema, z as TimelineEventSchema, Je as TimelineItemSchema, R as TimelinePrecisionSchema, Te as TranslationObjectSchema, Ie as TrueFalseItemSchema, f as UUIDSchema, F as Vector3Schema, _t as VideoMimeTypeSchema, d as compareManifestVersions, Ht as detokenizeOqseTags, Ct as formatManifestErrors, ot as formatValidationErrors, zt as generateUUID, se as isCategorize, he as isChessPuzzle, ge as isCoreItem, de as isDiagramLabel, _e as isExtendedItem, ee as isFillInBlanks, te as isFillInSelect, n as isFlashcard, a as isMCQMulti, i as isMCQSingle, re as isMatchComplex, ne as isMatchPairs, ue as isMathInput, le as isMatrix, t as isNote, pe as isNumericInput, be as isOQSEManifest, fe as isOpenEnded, oe as isPinOnImage, me as isPinOnModel, o as isShortAnswer, ae as isSlider, ie as isSortItems, ce as isTimeline, r as isTrueFalse, u as isValidManifestVersion, wt as isValidOQSEManifest, ye as isValidSemVer, Rt as isValidUUID, xe as isVersionCompatible, Ut as prepareRichTextForDisplay, St as safeValidateManifest, rt as safeValidateOQSEFile, at as safeValidateOQSEItem, kt as safeValidateOQSEPFile, Bt as tokenizeOqseTags, xt as validateManifest, nt as validateOQSEFile, it as validateOQSEItem, Ot as validateOQSEPFile, Vt as validateTier1Markdown };