@memizy/oqse 0.1.2 → 0.1.4

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
@@ -66,7 +66,7 @@ function me(e) {
66
66
  function he(e) {
67
67
  return e.type === "chess-puzzle";
68
68
  }
69
- function ge(e) {
69
+ function s(e) {
70
70
  return [
71
71
  "note",
72
72
  "flashcard",
@@ -74,18 +74,18 @@ function ge(e) {
74
74
  "short-answer"
75
75
  ].includes(e.type);
76
76
  }
77
- function _e(e) {
78
- return !ge(e);
77
+ function ge(e) {
78
+ return !s(e);
79
79
  }
80
80
  //#endregion
81
81
  //#region src/manifest.ts
82
- var ve = [
82
+ var c = [
83
83
  "render",
84
84
  "edit",
85
85
  "validate",
86
86
  "import",
87
87
  "export"
88
- ], s = [
88
+ ], l = [
89
89
  "markdown",
90
90
  "math",
91
91
  "rtl",
@@ -97,7 +97,7 @@ var ve = [
97
97
  "text-to-speech",
98
98
  "voice-input",
99
99
  "handwriting-recognition"
100
- ], c = [
100
+ ], u = [
101
101
  "hints",
102
102
  "explanation",
103
103
  "incorrectFeedback",
@@ -108,7 +108,7 @@ var ve = [
108
108
  "lang",
109
109
  "topic",
110
110
  "pedagogy"
111
- ], l = [
111
+ ], d = [
112
112
  "description",
113
113
  "thumbnail",
114
114
  "subject",
@@ -125,36 +125,109 @@ var ve = [
125
125
  "translations",
126
126
  "relatedSets"
127
127
  ];
128
- function u(e) {
128
+ function f(e) {
129
129
  return /^\d+\.\d+$/.test(e);
130
130
  }
131
- function ye(e) {
131
+ function _e(e) {
132
132
  return /^\d+\.\d+\.\d+(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$/.test(e);
133
133
  }
134
- function d(e, t) {
134
+ function p(e, t) {
135
135
  let [n = 0, r = 0] = e.split(".").map(Number), [i = 0, a = 0] = t.split(".").map(Number);
136
136
  return n === i ? r - a : n - i;
137
137
  }
138
- function be(e) {
138
+ function ve(e) {
139
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);
140
+ let t = e, n = t.author;
141
+ return typeof t.version == "string" && typeof t.id == "string" && typeof t.appName == "string" && t.appName !== "" && (n === void 0 || typeof n == "object" && !!n) && typeof t.capabilities == "object" && t.capabilities !== null && Array.isArray(t.capabilities.actions);
142
+ }
143
+ function ye(e, t) {
144
+ return !(!f(e) || t.minOqseVersion && f(t.minOqseVersion) && p(e, t.minOqseVersion) < 0 || t.maxOqseVersion && f(t.maxOqseVersion) && p(e, t.maxOqseVersion) > 0);
145
+ }
146
+ //#endregion
147
+ //#region node_modules/uuid/dist/regex.js
148
+ var be = /^(?:[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;
149
+ //#endregion
150
+ //#region node_modules/uuid/dist/validate.js
151
+ function xe(e) {
152
+ return typeof e == "string" && be.test(e);
153
+ }
154
+ //#endregion
155
+ //#region node_modules/uuid/dist/stringify.js
156
+ var m = [];
157
+ for (let e = 0; e < 256; ++e) m.push((e + 256).toString(16).slice(1));
158
+ function Se(e, t = 0) {
159
+ return (m[e[t + 0]] + m[e[t + 1]] + m[e[t + 2]] + m[e[t + 3]] + "-" + m[e[t + 4]] + m[e[t + 5]] + "-" + m[e[t + 6]] + m[e[t + 7]] + "-" + m[e[t + 8]] + m[e[t + 9]] + "-" + m[e[t + 10]] + m[e[t + 11]] + m[e[t + 12]] + m[e[t + 13]] + m[e[t + 14]] + m[e[t + 15]]).toLowerCase();
160
+ }
161
+ //#endregion
162
+ //#region node_modules/uuid/dist/rng.js
163
+ var h, Ce = new Uint8Array(16);
164
+ function we() {
165
+ if (!h) {
166
+ if (typeof crypto > "u" || !crypto.getRandomValues) throw Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");
167
+ h = crypto.getRandomValues.bind(crypto);
168
+ }
169
+ return h(Ce);
170
+ }
171
+ //#endregion
172
+ //#region node_modules/uuid/dist/v7.js
173
+ var g = {};
174
+ function Te(e, t, n) {
175
+ let r;
176
+ if (e) r = De(e.random ?? e.rng?.() ?? we(), e.msecs, e.seq, t, n);
177
+ else {
178
+ let e = Date.now(), i = we();
179
+ Ee(g, e, i), r = De(i, g.msecs, g.seq, t, n);
180
+ }
181
+ return t ?? Se(r);
182
+ }
183
+ function Ee(e, t, n) {
184
+ 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;
185
+ }
186
+ function De(e, t, n, r, i = 0) {
187
+ if (e.length < 16) throw Error("Random bytes length must be >= 16");
188
+ if (!r) r = new Uint8Array(16), i = 0;
189
+ else if (i < 0 || i + 16 > r.length) throw RangeError(`UUID byte range ${i}:${i + 15} is out of buffer bounds`);
190
+ 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;
142
191
  }
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);
192
+ //#endregion
193
+ //#region src/utils.ts
194
+ function Oe(e) {
195
+ return xe(e);
196
+ }
197
+ function ke() {
198
+ return Te();
199
+ }
200
+ function _(e, t = 10, n = 0) {
201
+ if (n > t) throw Error(`OQSE Security Error: Maximum nesting depth exceeded limit of ${t} levels.`);
202
+ if (typeof e == "object" && e) {
203
+ let r = Array.isArray(e) ? e : Object.values(e);
204
+ for (let e of r) _(e, t, n + 1);
205
+ }
206
+ }
207
+ function Ae(e) {
208
+ return e.issues.map((e) => {
209
+ let t = "";
210
+ return e.path.forEach((n, r) => {
211
+ if (typeof n == "number") t += `[${n}]`;
212
+ else {
213
+ let i = r === 0 || typeof e.path[r - 1] == "number";
214
+ t += (i ? "" : ".") + String(n);
215
+ }
216
+ }), t ? `${t}: ${e.message}` : e.message;
217
+ });
145
218
  }
146
219
  //#endregion
147
220
  //#region src/oqseValidation.ts
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"),
221
+ var v = e.string().uuid({ message: "Invalid UUID format" }), y = 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\")"), b = e.string().min(1, "License identifier must not be empty"), x = 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\")"), S = e.string().url({ message: "Must be a valid absolute URL" }), C = e.string().regex(/^[a-z0-9_-]+$/, "Asset key must contain only lowercase letters, numbers, hyphens and underscores"), w = e.string().min(1, "Text must not be empty"), T = e.string().min(1, "Content must not be empty"), E = e.string().max(1e4, "Question must not be longer than 10000 characters").optional(), D = e.string().regex(/^[a-zA-Z0-9_-]{1,64}$/, "Token must be alphanumeric, max 64 chars"), O = e.object({
222
+ lang: y,
223
+ value: e.string().min(1, "Subtitle URI must not be empty").regex(/\.(vtt|srt)(\?.*)?$/i, "Subtitle URI must end with .vtt or .srt"),
151
224
  label: e.string().optional(),
152
225
  kind: e.enum([
153
226
  "captions",
154
227
  "subtitles",
155
228
  "descriptions"
156
229
  ]).optional()
157
- }), Ce = e.object({
230
+ }), k = e.object({
158
231
  type: e.enum([
159
232
  "image",
160
233
  "audio",
@@ -164,15 +237,15 @@ var f = e.string().uuid({ message: "Invalid UUID format" }), p = e.string().min(
164
237
  value: e.string().min(1, "Media URI must not be empty"),
165
238
  mimeType: e.string().optional(),
166
239
  altText: e.string().optional(),
167
- transcript: y.optional(),
168
- caption: y.optional(),
240
+ transcript: T.optional(),
241
+ caption: T.optional(),
169
242
  width: e.number().int().positive().optional(),
170
243
  height: e.number().int().positive().optional(),
171
244
  start: e.number().nonnegative().optional(),
172
245
  end: e.number().positive().optional(),
173
246
  loop: e.boolean().optional(),
174
- subtitles: e.array(Se).optional(),
175
- license: m.optional(),
247
+ subtitles: e.array(O).optional(),
248
+ license: b.optional(),
176
249
  attribution: e.string().optional(),
177
250
  checksums: e.record(e.string(), e.string()).optional()
178
251
  }).refine((e) => e.start !== void 0 && e.end !== void 0 ? e.start < e.end : !0, {
@@ -181,12 +254,12 @@ var f = e.string().uuid({ message: "Invalid UUID format" }), p = e.string().min(
181
254
  }).refine((e) => !(e.type === "image" && !e.altText), {
182
255
  message: "Images must have alternative text (altText) defined for accessibility",
183
256
  path: ["altText"]
184
- }), x = e.record(_, Ce), S = e.object({
185
- name: v,
257
+ }), A = e.record(C, k), j = e.object({
258
+ name: w,
186
259
  role: e.string().optional(),
187
260
  email: e.string().email("Invalid email format").optional(),
188
- url: g.optional()
189
- }), C = e.enum([
261
+ url: S.optional()
262
+ }), M = e.enum([
190
263
  "url",
191
264
  "doi",
192
265
  "isbn",
@@ -197,16 +270,16 @@ var f = e.string().uuid({ message: "Invalid UUID format" }), p = e.string().min(
197
270
  "image",
198
271
  "model",
199
272
  "other"
200
- ]), w = e.object({
201
- id: v,
202
- type: C,
203
- value: v,
204
- title: v,
273
+ ]), N = e.object({
274
+ id: w,
275
+ type: M,
276
+ value: w,
277
+ title: w,
205
278
  description: e.string().optional(),
206
- authors: e.array(v).optional(),
207
- publishedDate: h.optional(),
208
- retrievedAt: h.optional(),
209
- license: m.optional()
279
+ authors: e.array(w).optional(),
280
+ publishedDate: x.optional(),
281
+ retrievedAt: x.optional(),
282
+ license: b.optional()
210
283
  }).refine((e) => {
211
284
  if ([
212
285
  "url",
@@ -223,75 +296,71 @@ var f = e.string().uuid({ message: "Invalid UUID format" }), p = e.string().min(
223
296
  }, {
224
297
  message: "For url, pdf, video, audio and image types, value must be a valid URL",
225
298
  path: ["value"]
226
- }), T = e.object({
227
- id: v,
299
+ }), P = e.object({
300
+ id: w,
228
301
  location: e.string().optional(),
229
- quote: y.optional()
230
- }), E = e.object({
302
+ quote: T.optional()
303
+ }), je = e.object({
231
304
  wikidataId: e.string().regex(/^Q\d+$/, "Wikidata ID must have format Q followed by number").optional(),
232
305
  description: e.string().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(),
306
+ }), Me = e.record(e.string(), je), F = e.object({
307
+ features: e.array(e.string().refine((e) => l.includes(e) || e.startsWith("x-"), { message: "Feature must be an official key or have prefix \"x-\"" })).optional(),
235
308
  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()
243
- }), O = e.object({
244
- id: f,
245
- title: v,
246
- downloadUrl: g.optional()
247
- }), Ee = e.enum([
309
+ itemProperties: e.array(e.string().refine((e) => u.includes(e) || e.startsWith("x-"), { message: "Item property must be an official key or have prefix \"x-\"" })).optional(),
310
+ metaProperties: e.array(e.string().refine((e) => d.includes(e) || e.startsWith("x-"), { message: "Meta property must be an official key or have prefix \"x-\"" })).optional()
311
+ }), Ne = e.object({
312
+ lang: y,
313
+ id: v,
314
+ title: w,
315
+ downloadUrl: S.optional()
316
+ }), I = e.object({
317
+ id: v,
318
+ title: w,
319
+ downloadUrl: S.optional()
320
+ }), Pe = e.enum([
248
321
  "remember",
249
322
  "understand",
250
323
  "apply",
251
324
  "analyze",
252
325
  "evaluate",
253
326
  "create"
254
- ]), De = e.enum([
327
+ ]), Fe = e.enum([
255
328
  "low",
256
329
  "medium",
257
330
  "high"
258
- ]), Oe = e.object({
259
- bloomLevel: Ee.optional(),
331
+ ]), Ie = e.object({
332
+ bloomLevel: Pe.optional(),
260
333
  irtDifficulty: e.number().optional(),
261
334
  irtDiscrimination: e.number().optional(),
262
335
  irtGuessing: e.number().min(0).max(1, "IRT guessing must be between 0 and 1").optional(),
263
336
  avgTime: e.number().positive().optional(),
264
- cognitiveLoad: De.optional(),
337
+ cognitiveLoad: Fe.optional(),
265
338
  partialCredit: e.boolean().optional(),
266
339
  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(),
269
- packages: e.array(e.string()).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(),
340
+ }), L = e.object({
341
+ id: v,
342
+ language: y,
343
+ title: w.max(500, "Title must not be longer than 500 characters"),
344
+ description: T.max(5e3, "Description must not be longer than 5000 characters").optional(),
345
+ thumbnail: C.optional(),
346
+ assets: A.optional(),
277
347
  ageMin: e.number().int().nonnegative().optional(),
278
348
  ageMax: e.number().int().nonnegative().optional(),
279
349
  subject: e.string().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(),
350
+ createdAt: x,
351
+ updatedAt: x,
352
+ author: j.optional(),
353
+ contributors: e.array(j).optional(),
354
+ license: b.optional(),
355
+ licenseUrl: S.optional(),
356
+ requirements: F.optional(),
357
+ tags: e.array(w).optional(),
358
+ tagDefinitions: Me.optional(),
359
+ translations: e.array(Ne).optional(),
360
+ sourceMaterials: e.array(N).optional(),
291
361
  estimatedTime: e.number().positive().optional(),
292
- prerequisites: e.array(O).optional(),
293
- relatedSets: e.array(O).optional(),
294
- mathSettings: Ae.optional(),
362
+ prerequisites: e.array(I).optional(),
363
+ relatedSets: e.array(I).optional(),
295
364
  customData: e.record(e.string(), e.unknown()).optional(),
296
365
  appSpecific: e.record(e.string(), e.unknown()).optional()
297
366
  }).refine((e) => e.ageMin !== void 0 && e.ageMax !== void 0 ? e.ageMin <= e.ageMax : !0, {
@@ -300,130 +369,139 @@ var f = e.string().uuid({ message: "Invalid UUID format" }), p = e.string().min(
300
369
  }).refine((e) => new Date(e.createdAt) <= new Date(e.updatedAt), {
301
370
  message: "Creation date (createdAt) must be before or equal to update date (updatedAt)",
302
371
  path: ["updatedAt"]
303
- }), k = e.object({
304
- id: f,
372
+ }), R = e.object({
373
+ id: v,
305
374
  type: e.string(),
306
- assets: x.optional(),
307
- lang: p.optional(),
308
- tags: e.array(v).optional(),
375
+ assets: A.optional(),
376
+ lang: y.optional(),
377
+ tags: e.array(w).optional(),
378
+ topic: w.optional(),
309
379
  difficulty: e.number().int().min(1, "Difficulty must be at least 1").max(5, "Difficulty must be at most 5").optional(),
310
380
  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(),
381
+ hints: e.array(T.max(2e3, "Hint must not be longer than 2000 characters")).max(20, "Maximum 20 hints per item").optional(),
382
+ explanation: T.max(1e4, "Explanation must not be longer than 10000 characters").optional(),
383
+ incorrectFeedback: T.optional(),
384
+ sources: e.array(P).optional(),
385
+ relatedItems: e.array(v).optional(),
386
+ dependencyItems: e.array(v).optional(),
387
+ pedagogy: Ie.optional(),
318
388
  customData: e.record(e.string(), e.unknown()).optional(),
319
389
  appSpecific: e.record(e.string(), e.unknown()).optional()
320
- }), Me = e.object({
321
- options: e.array(y).min(1, "Must have at least 1 option"),
390
+ }), Le = e.object({
391
+ options: e.array(T).min(1, "Must have at least 1 option"),
322
392
  correctIndex: e.number().int().nonnegative()
323
393
  }).refine((e) => e.correctIndex < e.options.length, {
324
394
  message: "Correct answer index references non-existent option",
325
395
  path: ["correctIndex"]
326
- }), A = e.object({
396
+ }), z = e.object({
327
397
  type: e.literal("rect"),
328
398
  label: e.string().optional(),
329
399
  x: e.number().min(0).max(100, "X must be in range 0-100%"),
330
400
  y: e.number().min(0).max(100, "Y must be in range 0-100%"),
331
401
  width: e.number().min(0).max(100, "Width must be in range 0-100%"),
332
402
  height: e.number().min(0).max(100, "Height must be in range 0-100%")
333
- }), j = e.object({
403
+ }), B = e.object({
334
404
  type: e.literal("circle"),
335
405
  label: e.string().optional(),
336
406
  x: e.number().min(0).max(100, "X must be in range 0-100%"),
337
407
  y: e.number().min(0).max(100, "Y must be in range 0-100%"),
338
408
  radius: e.number().min(0).max(100, "Radius must be in range 0-100%")
339
- }), M = e.object({
409
+ }), V = e.object({
340
410
  type: e.literal("polygon"),
341
411
  label: e.string().optional(),
342
412
  points: e.array(e.object({
343
413
  x: e.number().min(0).max(100),
344
414
  y: e.number().min(0).max(100)
345
415
  })).min(3, "Polygon must have at least 3 points")
346
- }), N = e.object({
416
+ }), H = e.object({
347
417
  type: e.literal("mesh"),
348
418
  label: e.string().optional(),
349
- targetName: v
350
- }), P = e.discriminatedUnion("type", [
351
- A,
352
- j,
353
- M,
354
- N
355
- ]), F = e.object({
419
+ targetName: w
420
+ }), Re = e.discriminatedUnion("type", [
421
+ z,
422
+ B,
423
+ V,
424
+ H
425
+ ]), ze = e.discriminatedUnion("type", [
426
+ z,
427
+ B,
428
+ V
429
+ ]), U = e.object({
356
430
  x: e.number(),
357
431
  y: e.number(),
358
432
  z: e.number()
359
- }), I = e.object({
360
- position: F.optional(),
361
- target: F.optional()
362
- }), L = e.object({
363
- id: v,
364
- text: y,
433
+ }), W = e.object({
434
+ position: U.optional(),
435
+ target: U.optional()
436
+ }), Be = e.object({
437
+ id: w,
438
+ text: T,
365
439
  correctCategoryIndex: e.number().int().nonnegative()
366
- }), R = e.enum([
440
+ }), Ve = e.enum([
367
441
  "year",
368
442
  "month",
369
443
  "day",
370
444
  "datetime"
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,
445
+ ]), He = e.object({
446
+ id: w,
447
+ text: T,
448
+ date: x,
449
+ precision: Ve.optional()
450
+ }), Ue = e.union([
451
+ z.extend({ correctLabelIndex: e.number().int().nonnegative() }),
452
+ B.extend({ correctLabelIndex: e.number().int().nonnegative() }),
453
+ V.extend({ correctLabelIndex: e.number().int().nonnegative() })
454
+ ]), We = e.object({
455
+ label: w,
382
456
  percentage: e.number().min(0, "Percentage must be non-negative").max(100, "Percentage must not exceed 100"),
383
457
  description: e.string().optional()
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, {
458
+ }), Ge = e.object({ criteria: e.array(We).min(1, "Rubric must have at least 1 criterion") }).refine((e) => e.criteria.reduce((e, t) => e + t.percentage, 0) > 0, {
385
459
  message: "Sum of percentages of all criteria must be greater than 0",
386
460
  path: ["criteria"]
387
- }), Ne = e.object({
461
+ }), Ke = e.object({
388
462
  min: e.number(),
389
463
  max: e.number()
390
464
  }).refine((e) => e.min <= e.max, {
391
465
  message: "Minimum value must be less than or equal to maximum value",
392
466
  path: ["max"]
393
- }), Pe = k.extend({
467
+ }), qe = R.extend({
394
468
  type: e.literal("note"),
395
469
  title: e.string().optional(),
396
- content: y.max(1e4, "Content must not be longer than 10000 characters")
397
- }), Fe = k.extend({
470
+ content: T.max(1e4, "Content must not be longer than 10000 characters"),
471
+ hiddenContent: T.max(1e4, "Content must not be longer than 10000 characters").optional()
472
+ }), Je = R.extend({
398
473
  type: e.literal("flashcard"),
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({
474
+ front: T.max(1e4, "Front side must not be longer than 10000 characters"),
475
+ back: T.max(1e4, "Back side must not be longer than 10000 characters")
476
+ }), Ye = R.extend({
402
477
  type: e.literal("true-false"),
403
- question: y.max(1e4, "Question must not be longer than 10000 characters"),
478
+ question: T.max(1e4, "Question must not be longer than 10000 characters"),
404
479
  answer: e.boolean()
405
- }), Le = k.extend({
480
+ }), Xe = R.extend({
406
481
  type: e.literal("mcq-single"),
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"),
482
+ question: T.max(1e4, "Question must not be longer than 10000 characters"),
483
+ options: e.array(T.max(2e3, "Option must not be longer than 2000 characters")).min(2, "Question must have at least 2 options").max(100, "Maximum 100 options"),
409
484
  correctIndex: e.number().int().nonnegative(),
410
485
  shuffleOptions: e.boolean().optional(),
411
- optionExplanations: e.array(e.union([y, e.null()])).optional()
486
+ optionExplanations: e.array(e.union([T, e.null()])).optional()
412
487
  }).refine((e) => e.correctIndex < e.options.length, {
413
488
  message: "Correct answer index references non-existent option",
414
489
  path: ["correctIndex"]
415
490
  }).refine((e) => e.optionExplanations ? e.optionExplanations.length === e.options.length : !0, {
416
491
  message: "Number of option explanations must match number of options",
417
492
  path: ["optionExplanations"]
418
- }), Re = k.extend({
493
+ }).refine((e) => new Set(e.options.map((e) => e.toLowerCase())).size === e.options.length, {
494
+ message: "Options must not contain duplicates (case-insensitive)",
495
+ path: ["options"]
496
+ }), Ze = R.extend({
419
497
  type: e.literal("mcq-multi"),
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"),
498
+ question: T.max(1e4, "Question must not be longer than 10000 characters"),
499
+ options: e.array(T.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
500
  correctIndices: e.array(e.number().int().nonnegative()).min(1, "Must have at least 1 correct answer"),
423
501
  minSelections: e.number().int().positive().optional(),
424
502
  maxSelections: e.number().int().positive().optional(),
425
503
  shuffleOptions: e.boolean().optional(),
426
- optionExplanations: e.array(e.union([y, e.null()])).optional()
504
+ optionExplanations: e.array(e.union([T, e.null()])).optional()
427
505
  }).refine((e) => e.correctIndices.every((t) => t < e.options.length), {
428
506
  message: "Some of correct answer indices reference non-existent option",
429
507
  path: ["correctIndices"]
@@ -436,22 +514,28 @@ var f = e.string().uuid({ message: "Invalid UUID format" }), p = e.string().min(
436
514
  }).refine((e) => e.maxSelections ? e.maxSelections <= e.options.length : !0, {
437
515
  message: "Maximum number of selections must not exceed number of options",
438
516
  path: ["maxSelections"]
517
+ }).refine((e) => e.minSelections ? e.minSelections <= e.options.length : !0, {
518
+ message: "minSelections cannot be greater than the number of options",
519
+ path: ["minSelections"]
439
520
  }).refine((e) => e.optionExplanations ? e.optionExplanations.length === e.options.length : !0, {
440
521
  message: "Number of option explanations must match number of options",
441
522
  path: ["optionExplanations"]
442
- }), ze = k.extend({
523
+ }).refine((e) => new Set(e.options.map((e) => e.toLowerCase())).size === e.options.length, {
524
+ message: "Options must not contain duplicates (case-insensitive)",
525
+ path: ["options"]
526
+ }), Qe = R.extend({
443
527
  type: e.literal("short-answer"),
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"),
528
+ question: T.max(1e4, "Question must not be longer than 10000 characters"),
529
+ answers: e.array(w).min(1, "Must have at least 1 correct answer"),
446
530
  caseSensitive: e.boolean().optional(),
447
531
  trimWhitespace: e.boolean().optional(),
448
532
  acceptPartial: e.boolean().optional(),
449
533
  ignoreDiacritics: e.boolean().optional()
450
- }), Be = k.extend({
534
+ }), $e = R.extend({
451
535
  type: e.literal("fill-in-blanks"),
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")),
536
+ question: E,
537
+ text: T.max(1e4, "Text must not be longer than 10000 characters"),
538
+ blanks: e.record(D, e.array(w).min(1, "Each blank must have at least 1 correct answer")),
455
539
  caseSensitive: e.boolean().optional(),
456
540
  trimWhitespace: e.boolean().optional()
457
541
  }).refine((e) => Object.keys(e.blanks).length > 0, {
@@ -467,11 +551,11 @@ var f = e.string().uuid({ message: "Invalid UUID format" }), p = e.string().min(
467
551
  }, {
468
552
  message: "All tokens in text must have definition in blanks and all definitions must be used in text",
469
553
  path: ["blanks"]
470
- }), Ve = k.extend({
554
+ }), et = R.extend({
471
555
  type: e.literal("fill-in-select"),
472
- question: b,
473
- text: y.max(1e4, "Text must not be longer than 10000 characters"),
474
- blanks: e.record(e.string(), Me)
556
+ question: E,
557
+ text: T.max(1e4, "Text must not be longer than 10000 characters"),
558
+ blanks: e.record(D, Le)
475
559
  }).refine((e) => Object.keys(e.blanks).length > 0, {
476
560
  message: "Text must contain at least 1 blank to select",
477
561
  path: ["blanks"]
@@ -485,19 +569,19 @@ var f = e.string().uuid({ message: "Invalid UUID format" }), p = e.string().min(
485
569
  }, {
486
570
  message: "All tokens in text must have definition in blanks and all definitions must be used in text",
487
571
  path: ["blanks"]
488
- }), He = k.extend({
572
+ }), tt = R.extend({
489
573
  type: e.literal("match-pairs"),
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")
574
+ question: E,
575
+ prompts: e.array(T).min(2, "Must have at least 2 pairs to match").max(100, "Maximum 100 pairs"),
576
+ matches: e.array(T).min(2, "Must have at least 2 pairs to match").max(100, "Maximum 100 pairs")
493
577
  }).refine((e) => e.prompts.length === e.matches.length, {
494
578
  message: "Number of prompts must match number of matches",
495
579
  path: ["matches"]
496
- }), Ue = k.extend({
580
+ }), nt = R.extend({
497
581
  type: e.literal("match-complex"),
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"),
582
+ question: E,
583
+ leftItems: e.array(T).min(1, "Must have at least 1 item on left"),
584
+ rightItems: e.array(T).min(1, "Must have at least 1 item on right"),
501
585
  connections: e.array(e.tuple([e.number().int().nonnegative(), e.number().int().nonnegative()])).min(1, "Must have at least 1 connection"),
502
586
  minCorrect: e.number().int().positive().optional()
503
587
  }).refine((e) => e.connections.every(([t, n]) => t < e.leftItems.length && n < e.rightItems.length), {
@@ -509,13 +593,13 @@ var f = e.string().uuid({ message: "Invalid UUID format" }), p = e.string().min(
509
593
  }).refine((e) => e.minCorrect ? e.minCorrect <= e.connections.length : !0, {
510
594
  message: "Minimum correct answers must not exceed total number of connections",
511
595
  path: ["minCorrect"]
512
- }), We = k.extend({
596
+ }), rt = R.extend({
513
597
  type: e.literal("sort-items"),
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({
598
+ question: T.max(1e4, "Question must not be longer than 10000 characters"),
599
+ items: e.array(T).min(2, "Must have at least 2 items to sort")
600
+ }), it = R.extend({
517
601
  type: e.literal("slider"),
518
- question: y.max(1e4, "Question must not be longer than 10000 characters"),
602
+ question: T.max(1e4, "Question must not be longer than 10000 characters"),
519
603
  min: e.number(),
520
604
  max: e.number(),
521
605
  step: e.number().positive("Step must be a positive number"),
@@ -537,34 +621,37 @@ var f = e.string().uuid({ message: "Invalid UUID format" }), p = e.string().min(
537
621
  }).refine((e) => e.tolerance <= (e.max - e.min) / 2, {
538
622
  message: "Tolerance must not be greater than half of value range",
539
623
  path: ["tolerance"]
540
- }), Ke = k.extend({
624
+ }), at = R.extend({
541
625
  type: e.literal("pin-on-image"),
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"),
626
+ question: T.max(1e4, "Question must not be longer than 10000 characters"),
627
+ targetAsset: C,
628
+ hotspots: e.array(ze).min(1, "Must have at least 1 hotspot"),
545
629
  multipleCorrect: e.boolean().optional(),
546
630
  minCorrect: e.number().int().positive().optional()
547
631
  }).refine((e) => e.minCorrect ? e.minCorrect <= e.hotspots.length : !0, {
548
632
  message: "Minimum correct answers must not exceed number of hotspots",
549
633
  path: ["minCorrect"]
550
- }), qe = k.extend({
634
+ }), ot = R.extend({
551
635
  type: e.literal("categorize"),
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")
636
+ question: T.max(1e4, "Question must not be longer than 10000 characters"),
637
+ categories: e.array(w).min(2, "Must have at least 2 categories"),
638
+ items: e.array(Be).min(1, "Must have at least 1 item to categorize")
639
+ }).refine((e) => new Set(e.categories.map((e) => e.toLowerCase())).size === e.categories.length, {
640
+ message: "Categories must not contain duplicates (case-insensitive)",
641
+ path: ["categories"]
555
642
  }).refine((e) => e.items.every((t) => t.correctCategoryIndex < e.categories.length), {
556
643
  message: "Some item references non-existent category",
557
644
  path: ["items"]
558
- }), Je = k.extend({
645
+ }), st = R.extend({
559
646
  type: e.literal("timeline"),
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"),
647
+ question: T.max(1e4, "Question must not be longer than 10000 characters"),
648
+ events: e.array(He).min(2, "Must have at least 2 events"),
562
649
  randomize: e.boolean().optional()
563
- }), Ye = k.extend({
650
+ }), ct = R.extend({
564
651
  type: e.literal("matrix"),
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"),
652
+ question: T.max(1e4, "Question must not be longer than 10000 characters"),
653
+ rows: e.array(w).min(1, "Must have at least 1 row"),
654
+ columns: e.array(w).min(1, "Must have at least 1 column"),
568
655
  correctCells: e.array(e.tuple([e.number().int().nonnegative(), e.number().int().nonnegative()])).min(1, "Must have at least 1 correct cell"),
569
656
  multiplePerRow: e.boolean().optional()
570
657
  }).refine((e) => e.correctCells.every(([t, n]) => t < e.rows.length && n < e.columns.length), {
@@ -583,71 +670,58 @@ var f = e.string().uuid({ message: "Invalid UUID format" }), p = e.string().min(
583
670
  }, {
584
671
  message: "If multiplePerRow is false, each row may have maximum 1 correct cell",
585
672
  path: ["correctCells"]
586
- }), Xe = k.extend({
673
+ }), lt = R.extend({
587
674
  type: e.literal("math-input"),
588
- question: y.max(1e4, "Question must not be longer than 10000 characters"),
589
- correctAnswer: v,
590
- alternativeAnswers: e.array(v).optional(),
675
+ question: T.max(1e4, "Question must not be longer than 10000 characters"),
676
+ correctAnswer: w,
677
+ alternativeAnswers: e.array(w).optional(),
591
678
  tolerance: e.number().nonnegative().optional()
592
- }), Ze = k.extend({
679
+ }), ut = R.extend({
593
680
  type: e.literal("diagram-label"),
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"),
681
+ question: T.max(1e4, "Question must not be longer than 10000 characters"),
682
+ targetAsset: C,
683
+ labels: e.array(T).min(1, "Must have at least 1 label"),
597
684
  caseSensitive: e.boolean().optional(),
598
685
  requireTyping: e.boolean().optional(),
599
- zones: e.array(B).min(1, "Must have at least 1 zone")
686
+ zones: e.array(Ue).min(1, "Must have at least 1 zone")
600
687
  }).refine((e) => e.zones.every((t) => t.correctLabelIndex < e.labels.length), {
601
688
  message: "Some zone references non-existent label",
602
689
  path: ["zones"]
603
- }), Qe = k.extend({
690
+ }), dt = R.extend({
604
691
  type: e.literal("open-ended"),
605
- question: y.max(1e4, "Question must not be longer than 10000 characters"),
692
+ question: T.max(1e4, "Question must not be longer than 10000 characters"),
606
693
  minWords: e.number().int().positive().optional(),
607
694
  maxWords: e.number().int().positive().optional(),
608
- sampleAnswer: y.optional(),
609
- rubric: H.optional()
695
+ sampleAnswer: T.optional(),
696
+ rubric: Ge.optional()
610
697
  }).refine((e) => e.minWords && e.maxWords ? e.minWords <= e.maxWords : !0, {
611
698
  message: "Minimum word count must be less than or equal to maximum",
612
699
  path: ["maxWords"]
613
- }), $e = k.extend({
700
+ }), ft = R.extend({
614
701
  type: e.literal("numeric-input"),
615
- question: y.max(1e4, "Question must not be longer than 10000 characters"),
702
+ question: T.max(1e4, "Question must not be longer than 10000 characters"),
616
703
  value: e.number(),
617
704
  tolerance: e.number().nonnegative().optional(),
618
- range: Ne.optional(),
705
+ range: Ke.optional(),
619
706
  unit: e.string().optional()
620
- }), et = k.extend({
707
+ }), pt = R.extend({
621
708
  type: e.literal("pin-on-model"),
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"),
709
+ question: T.max(1e4, "Question must not be longer than 10000 characters"),
710
+ targetAsset: C,
711
+ hotspots: e.array(H).min(1, "Must have at least 1 hotspot"),
625
712
  multipleCorrect: e.boolean().optional(),
626
713
  minCorrect: e.number().int().positive().optional(),
627
- camera: I.optional()
714
+ camera: W.optional()
628
715
  }).refine((e) => e.minCorrect ? e.minCorrect <= e.hotspots.length : !0, {
629
716
  message: "Minimum correct answers must not exceed number of hotspots",
630
717
  path: ["minCorrect"]
631
- }), tt = k.extend({
718
+ }), mt = R.extend({
632
719
  type: e.literal("chess-puzzle"),
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"),
720
+ question: T.max(1e4, "Question must not be longer than 10000 characters"),
721
+ fen: w,
722
+ answers: e.array(e.array(w).min(1, "Move sequence must not be empty")).min(1, "Must have at least 1 correct move sequence"),
636
723
  elo: e.number().int().nonnegative("ELO must be non-negative integer").optional()
637
- }), U = e.discriminatedUnion("type", [
638
- Pe,
639
- Fe,
640
- Ie,
641
- Le,
642
- Re,
643
- ze,
644
- Be,
645
- Ve,
646
- He,
647
- Ue,
648
- We,
649
- Ge,
650
- Ke,
724
+ }), G = e.discriminatedUnion("type", [
651
725
  qe,
652
726
  Je,
653
727
  Ye,
@@ -656,25 +730,38 @@ var f = e.string().uuid({ message: "Invalid UUID format" }), p = e.string().min(
656
730
  Qe,
657
731
  $e,
658
732
  et,
659
- tt
660
- ]), W = e.object({
733
+ tt,
734
+ nt,
735
+ rt,
736
+ it,
737
+ at,
738
+ ot,
739
+ st,
740
+ ct,
741
+ lt,
742
+ ut,
743
+ dt,
744
+ ft,
745
+ pt,
746
+ mt
747
+ ]), K = e.object({
661
748
  $schema: e.string().url().optional(),
662
749
  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")
750
+ meta: L,
751
+ items: e.array(G).max(1e4, "Maximum 10000 items per set")
665
752
  }).refine((e) => {
666
753
  let t = new Set(e.items.map((e) => e.id));
667
754
  for (let n of e.items) {
668
755
  if (n.relatedItems) {
669
- for (let e of n.relatedItems) if (!t.has(e)) return !1;
756
+ for (let e of n.relatedItems) if (!t.has(e) || n.id === e) return !1;
670
757
  }
671
758
  if (n.dependencyItems) {
672
- for (let e of n.dependencyItems) if (!t.has(e)) return !1;
759
+ for (let e of n.dependencyItems) if (!t.has(e) || n.id === e) return !1;
673
760
  }
674
761
  }
675
762
  return !0;
676
763
  }, {
677
- message: "Some item references non-existent relatedItems or dependencyItems",
764
+ message: "Some item references non-existent relatedItems, dependencyItems, or references itself",
678
765
  path: ["items"]
679
766
  }).refine((e) => e.meta.thumbnail && e.meta.assets ? e.meta.thumbnail in e.meta.assets : !0, {
680
767
  message: "Thumbnail references non-existent asset",
@@ -689,11 +776,27 @@ var f = e.string().uuid({ message: "Invalid UUID format" }), p = e.string().min(
689
776
  message: "Some item references non-existent source material",
690
777
  path: ["items"]
691
778
  });
692
- function nt(e) {
693
- return W.parse(e);
779
+ function ht(t) {
780
+ let n = t instanceof Error ? t.message : "OQSE Security Error: Maximum nesting depth exceeded limit of 10 levels.";
781
+ return new e.ZodError([{
782
+ code: e.ZodIssueCode.custom,
783
+ message: n,
784
+ path: []
785
+ }]);
786
+ }
787
+ function gt(e) {
788
+ return _(e, 10), K.parse(e);
694
789
  }
695
- function rt(e) {
696
- let t = W.safeParse(e);
790
+ function _t(e) {
791
+ try {
792
+ _(e, 10);
793
+ } catch (e) {
794
+ return {
795
+ success: !1,
796
+ error: ht(e)
797
+ };
798
+ }
799
+ let t = K.safeParse(e);
697
800
  return t.success ? {
698
801
  success: !0,
699
802
  data: t.data
@@ -702,11 +805,19 @@ function rt(e) {
702
805
  error: t.error
703
806
  };
704
807
  }
705
- function it(e) {
706
- return U.parse(e);
808
+ function vt(e) {
809
+ return _(e, 10), G.parse(e);
707
810
  }
708
- function at(e) {
709
- let t = U.safeParse(e);
811
+ function yt(e) {
812
+ try {
813
+ _(e, 10);
814
+ } catch (e) {
815
+ return {
816
+ success: !1,
817
+ error: ht(e)
818
+ };
819
+ }
820
+ let t = G.safeParse(e);
710
821
  return t.success ? {
711
822
  success: !0,
712
823
  data: t.data
@@ -715,62 +826,81 @@ function at(e) {
715
826
  error: t.error
716
827
  };
717
828
  }
718
- function ot(e) {
719
- return e.issues.map((e) => {
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;
728
- });
729
- }
730
829
  //#endregion
731
830
  //#region src/manifestValidation.ts
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([
831
+ var q = e.string().min(1, "Value must not be empty").trim(), bt = e.string().regex(/^[a-zA-Z]{2,8}(-[a-zA-Z0-9\-]+)*$/, "Must be a valid BCP 47 locale (e.g., \"en\", \"cs\")"), J = 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" }), xt = e.string().regex(/^urn:uuid:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, "Must be a valid URN UUID (urn:uuid:...)"), Y = e.string().regex(/^\d+\.\d+$/, "Version must be in MAJOR.MINOR format (e.g. \"0.1\")"), St = [
832
+ "note",
833
+ "flashcard",
834
+ "true-false",
835
+ "mcq-single",
836
+ "mcq-multi",
837
+ "short-answer",
838
+ "fill-in-blanks",
839
+ "fill-in-select",
840
+ "match-pairs",
841
+ "match-complex",
842
+ "sort-items",
843
+ "slider",
844
+ "pin-on-image",
845
+ "categorize",
846
+ "timeline",
847
+ "matrix",
848
+ "math-input",
849
+ "diagram-label",
850
+ "open-ended",
851
+ "numeric-input",
852
+ "pin-on-model",
853
+ "chess-puzzle"
854
+ ], Ct = q.refine((e) => St.includes(e) || e.startsWith("x-"), { message: "Custom types MUST use the \"x-\" prefix" }), wt = e.string().refine((e) => c.includes(e) || e.startsWith("x-"), { message: "Action must be one of [render, edit, validate, import, export] or have prefix \"x-\"" }), Tt = e.enum([
733
855
  "game",
734
856
  "fun",
735
857
  "drill"
736
- ]), dt = e.enum([
858
+ ]), Et = e.enum([
737
859
  "low",
738
860
  "medium",
739
861
  "high"
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) {
862
+ ]), Dt = e.string().refine((e) => l.includes(e) || e.startsWith("x-"), { message: "Feature must be one of official keys or have prefix \"x-\"" }), Ot = e.string().refine((e) => u.includes(e) || e.startsWith("x-"), { message: "Item property must be an official key or have prefix \"x-\"" }), kt = e.string().refine((e) => d.includes(e) || e.startsWith("x-"), { message: "Meta property must be an official key or have prefix \"x-\"" });
863
+ function X(t) {
742
864
  return e.union([
743
865
  e.tuple([e.literal("*")]),
744
866
  e.array(t),
745
867
  e.null()
746
868
  ]);
747
869
  }
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(),
870
+ var At = e.string().refine((e) => e.startsWith("image/"), { message: "Must be a valid image MIME type (image/...)" }), jt = e.string().refine((e) => e.startsWith("audio/"), { message: "Must be a valid audio MIME type (audio/...)" }), Mt = e.string().refine((e) => e.startsWith("video/"), { message: "Must be a valid video MIME type (video/...)" }), Nt = 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)" }), Pt = e.object({
871
+ image: X(At).optional(),
872
+ audio: X(jt).optional(),
873
+ video: X(Mt).optional(),
874
+ model: X(Nt).optional()
875
+ }), Ft = F.extend({
876
+ actions: e.array(wt).min(1, "Application must support at least one action"),
877
+ types: X(Ct).optional(),
878
+ assets: Pt.optional()
879
+ }).superRefine((t, n) => {
880
+ (t.actions.includes("render") || t.actions.includes("edit")) && (!Array.isArray(t.types) || t.types.length === 0) && n.addIssue({
881
+ code: e.ZodIssueCode.custom,
882
+ message: "types array MUST be declared and non-empty when actions include \"render\" or \"edit\"",
883
+ path: ["types"]
884
+ });
885
+ }), Z = e.object({
886
+ $schema: J.optional(),
887
+ id: e.union([J, xt]),
888
+ appName: q.max(200, "Name must not be longer than 200 characters"),
889
+ version: Y,
890
+ pluginVersion: e.string().optional(),
891
+ minOqseVersion: Y.optional(),
892
+ maxOqseVersion: Y.optional(),
893
+ capabilities: Ft,
894
+ author: j.optional(),
895
+ contributors: e.array(j).optional(),
896
+ license: e.string().max(100, "License must not be longer than 100 characters").optional(),
897
+ licenseUrl: J.optional(),
898
+ locales: e.array(bt).optional(),
899
+ description: e.string().max(5e3, "Description must not be longer than 5000 characters").optional(),
770
900
  emoji: e.string().optional(),
771
- tags: e.array(G).optional(),
772
- studyMode: ut.optional(),
773
- questionDensity: dt.optional(),
901
+ tags: e.array(q).optional(),
902
+ studyMode: Tt.optional(),
903
+ questionDensity: Et.optional(),
774
904
  appSpecific: e.record(e.string(), e.unknown()).optional()
775
905
  }).refine((e) => {
776
906
  if (!e.minOqseVersion || !e.maxOqseVersion) return !0;
@@ -780,31 +910,25 @@ var ht = e.string().refine((e) => e.startsWith("image/"), { message: "Must be a
780
910
  message: "minOqseVersion must not be greater than maxOqseVersion",
781
911
  path: ["minOqseVersion"]
782
912
  });
783
- function xt(e) {
784
- return J.parse(e);
913
+ function It(e) {
914
+ return Z.parse(e);
785
915
  }
786
- function St(e) {
787
- return J.safeParse(e);
788
- }
789
- function Ct(e) {
790
- return e.issues.map((e) => {
791
- let t = e.path.map((e) => String(e)).join(".");
792
- return t ? `${t}: ${e.message}` : e.message;
793
- }).join("\n");
916
+ function Lt(e) {
917
+ return Z.safeParse(e);
794
918
  }
795
- function wt(e) {
796
- return J.safeParse(e).success;
919
+ function Rt(e) {
920
+ return Z.safeParse(e).success;
797
921
  }
798
922
  //#endregion
799
923
  //#region src/progressValidation.ts
800
- var Tt = e.object({
924
+ var zt = e.object({
801
925
  attempts: e.number().int().nonnegative(),
802
926
  incorrect: e.number().int().nonnegative(),
803
927
  streak: e.number().int().nonnegative()
804
928
  }).refine((e) => e.incorrect <= e.attempts, {
805
929
  message: "incorrect cannot be higher than attempts",
806
930
  path: ["incorrect"]
807
- }), Y = e.object({
931
+ }), Bt = e.object({
808
932
  isCorrect: e.boolean(),
809
933
  confidence: e.union([
810
934
  e.literal(1),
@@ -812,14 +936,11 @@ var Tt = e.object({
812
936
  e.literal(3),
813
937
  e.literal(4)
814
938
  ]).optional(),
815
- answeredAt: h,
939
+ answeredAt: x,
816
940
  timeSpent: e.number().int().nonnegative().optional(),
817
- hintsUsed: e.number().int().nonnegative().optional(),
941
+ hintsUsed: e.number().int().nonnegative().default(0),
818
942
  isSkipped: e.boolean().optional()
819
- }).refine((e) => !e.isSkipped || e.isCorrect === !1, {
820
- message: "If isSkipped=true, isCorrect must be false",
821
- path: ["isCorrect"]
822
- }), Et = e.object({
943
+ }), Vt = e.object({
823
944
  bucket: e.union([
824
945
  e.literal(0),
825
946
  e.literal(1),
@@ -827,83 +948,51 @@ var Tt = e.object({
827
948
  e.literal(3),
828
949
  e.literal(4)
829
950
  ]),
830
- nextReviewAt: h.optional(),
831
- stats: Tt,
832
- lastAnswer: Y.optional(),
951
+ nextReviewAt: x.optional(),
952
+ stats: zt,
953
+ lastAnswer: Bt.optional(),
833
954
  appSpecific: e.record(e.string(), e.unknown()).optional()
834
- }), Dt = e.object({
835
- setId: f,
836
- exportedAt: h,
955
+ }), Ht = e.object({
956
+ setId: v,
957
+ exportedAt: x,
837
958
  algorithm: e.string().regex(/^[a-z0-9-]+$/, "algorithm must be lowercase alphanumeric with hyphens format").optional()
838
- }), X = e.object({
839
- $schema: e.string().url().optional(),
959
+ }), Q = e.object({
960
+ $schema: e.url().optional(),
840
961
  version: e.string().regex(/^\d+\.\d+$/, "Version must be in MAJOR.MINOR format"),
841
- meta: Dt,
842
- records: e.record(f, Et)
962
+ meta: Ht,
963
+ records: e.record(v, Vt)
843
964
  });
844
- function Ot(e) {
845
- return X.parse(e);
846
- }
847
- function kt(e) {
848
- return X.safeParse(e);
965
+ function Ut(e) {
966
+ return Q.parse(e);
849
967
  }
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);
968
+ function Wt(e) {
969
+ return Q.safeParse(e);
857
970
  }
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);
886
- }
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;
895
- }
896
- //#endregion
897
- //#region src/utils.ts
898
- function Rt(e) {
899
- return jt(e);
971
+ var $ = e.object(L.shape).pick({
972
+ id: !0,
973
+ title: !0,
974
+ language: !0,
975
+ updatedAt: !0,
976
+ description: !0,
977
+ author: !0,
978
+ subject: !0,
979
+ tags: !0,
980
+ createdAt: !0,
981
+ estimatedTime: !0,
982
+ requirements: !0
983
+ }).partial({ createdAt: !0 }).extend({
984
+ url: S,
985
+ $schema: e.string().url().optional()
986
+ });
987
+ function Gt(e) {
988
+ return $.parse(e);
900
989
  }
901
- function zt() {
902
- return Ft();
990
+ function Kt(e) {
991
+ return $.safeParse(e);
903
992
  }
904
993
  //#endregion
905
994
  //#region src/richTextProcessor.ts
906
- function Bt(e) {
995
+ function qt(e) {
907
996
  let t = {};
908
997
  return {
909
998
  text: e.replace(/<(asset|blank):([a-zA-Z0-9_-]+)\s*\/>/gi, (e, n, r) => {
@@ -917,11 +1006,11 @@ function Bt(e) {
917
1006
  tokens: t
918
1007
  };
919
1008
  }
920
- function Vt(e) {
1009
+ function Jt(e) {
921
1010
  let t = e.replace(/`{1,}[^`]*`{1,}/g, "").replace(/~{3,}[\s\S]*?~{3,}/g, "");
922
1011
  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
1012
  }
924
- function Ht(e, t, n) {
1013
+ function Yt(e, t, n) {
925
1014
  let r = e;
926
1015
  for (let [e, i] of Object.entries(t)) {
927
1016
  let t = i.originalTag;
@@ -929,16 +1018,16 @@ function Ht(e, t, n) {
929
1018
  }
930
1019
  return r;
931
1020
  }
932
- function Ut(e, t, n) {
1021
+ function Xt(e, t, n) {
933
1022
  if (!e) return "";
934
- let r = t?.features?.includes("html") ?? !1, { text: i, tokens: a } = Bt(e);
935
- r || Vt(i);
1023
+ let r = t?.features?.includes("html") ?? !1, { text: i, tokens: a } = qt(e);
1024
+ r || Jt(i);
936
1025
  let o = n.markdownParser(i);
937
1026
  if (r) {
938
1027
  if (!n.htmlSanitizer) throw Error("OQSE Security Error: Set requires 'html' (Tier 2), but no htmlSanitizer (like DOMPurify) was provided to the options.");
939
1028
  o = n.htmlSanitizer(o);
940
1029
  }
941
- return Ht(o, a, n);
1030
+ return Yt(o, a, n);
942
1031
  }
943
1032
  //#endregion
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 };
1033
+ export { S as AbsoluteURLSchema, A as AssetDictionarySchema, C as AssetKeySchema, jt as AudioMimeTypeSchema, R as BaseItemSchema, D as BlankTokenSchema, Pe as BloomLevelSchema, W as CameraSetupSchema, Be as CategorizeItemObjectSchema, ot as CategorizeItemSchema, mt as ChessPuzzleItemSchema, B as CircleHotspotSchema, Fe as CognitiveLoadSchema, ut as DiagramLabelItemSchema, Ue as DiagramZoneSchema, Dt as FeatureFlagSchema, F as FeatureProfileSchema, $e as FillInBlanksItemSchema, et as FillInSelectItemSchema, Je as FlashcardItemSchema, ze as Hotspot2DSchema, Re as HotspotObjectSchema, x as ISO8601DateTimeSchema, At as ImageMimeTypeSchema, Ot as ItemPropertyKeySchema, y as LanguageCodeSchema, Bt as LastAnswerObjectSchema, I as LinkedSetObjectSchema, Ze as MCQMultiItemSchema, Xe as MCQSingleItemSchema, Pt as ManifestAssetsSchema, Ft as ManifestCapabilitiesSchema, nt as MatchComplexItemSchema, tt as MatchPairsItemSchema, lt as MathInputItemSchema, ct as MatrixItemSchema, k as MediaObjectSchema, H as MeshHotspotSchema, kt as MetaPropertyKeySchema, Nt as ModelMimeTypeSchema, qe as NoteItemSchema, ft as NumericInputItemSchema, Ke as NumericRangeSchema, c as OFFICIAL_ACTIONS, l as OFFICIAL_FEATURE_KEYS, u as OFFICIAL_ITEM_PROPERTIES, d as OFFICIAL_META_PROPERTIES, wt as OQSEActionSchema, K as OQSEFileSchema, $ as OQSEHeaderSchema, G as OQSEItemSchema, Z as OQSEManifestSchema, L as OQSEMetaSchema, Q as OQSEProgressSchema, Et as OQSEQuestionDensitySchema, Tt as OQSEStudyModeSchema, dt as OpenEndedItemSchema, E as OptionalRichContentSchema, Ie as PedagogySchema, j as PersonObjectSchema, at as PinOnImageItemSchema, pt as PinOnModelItemSchema, w as PlainTextSchema, V as PolygonHotspotSchema, Ht as ProgressMetaSchema, Vt as ProgressRecordSchema, z as RectHotspotSchema, T as RichContentSchema, We as RubricCriterionSchema, Ge as RubricSchema, b as SPDXLicenseSchema, Le as SelectBlankObjectSchema, Qe as ShortAnswerItemSchema, it as SliderItemSchema, rt as SortItemsItemSchema, N as SourceMaterialSchema, M as SourceMaterialTypeSchema, P as SourceReferenceSchema, zt as StatsObjectSchema, O as SubtitleTrackSchema, Me as TagDefinitionDictionarySchema, je as TagDefinitionSchema, He as TimelineEventSchema, st as TimelineItemSchema, Ve as TimelinePrecisionSchema, Ne as TranslationObjectSchema, Ye as TrueFalseItemSchema, v as UUIDSchema, U as Vector3Schema, Mt as VideoMimeTypeSchema, p as compareManifestVersions, Yt as detokenizeOqseTags, Ae as formatOQSEErrors, ke as generateUUID, se as isCategorize, he as isChessPuzzle, s as isCoreItem, de as isDiagramLabel, ge 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, ve 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, f as isValidManifestVersion, Rt as isValidOQSEManifest, _e as isValidSemVer, Oe as isValidUUID, ye as isVersionCompatible, Xt as prepareRichTextForDisplay, _t as safeValidateOQSEFile, Kt as safeValidateOQSEHeader, yt as safeValidateOQSEItem, Lt as safeValidateOQSEManifest, Wt as safeValidateOQSEProgress, qt as tokenizeOqseTags, _ as validateJsonDepth, gt as validateOQSEFile, Gt as validateOQSEHeader, vt as validateOQSEItem, It as validateOQSEManifest, Ut as validateOQSEProgress, Jt as validateTier1Markdown };