@memizy/oqse 0.1.2 → 0.1.3

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,97 @@ 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);
142
182
  }
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);
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;
191
+ }
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
+ }
145
206
  }
146
207
  //#endregion
147
208
  //#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"),
209
+ 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({
210
+ lang: y,
211
+ value: e.string().min(1, "Subtitle URI must not be empty").regex(/\.(vtt|srt)(\?.*)?$/i, "Subtitle URI must end with .vtt or .srt"),
151
212
  label: e.string().optional(),
152
213
  kind: e.enum([
153
214
  "captions",
154
215
  "subtitles",
155
216
  "descriptions"
156
217
  ]).optional()
157
- }), Ce = e.object({
218
+ }), k = e.object({
158
219
  type: e.enum([
159
220
  "image",
160
221
  "audio",
@@ -164,15 +225,15 @@ var f = e.string().uuid({ message: "Invalid UUID format" }), p = e.string().min(
164
225
  value: e.string().min(1, "Media URI must not be empty"),
165
226
  mimeType: e.string().optional(),
166
227
  altText: e.string().optional(),
167
- transcript: y.optional(),
168
- caption: y.optional(),
228
+ transcript: T.optional(),
229
+ caption: T.optional(),
169
230
  width: e.number().int().positive().optional(),
170
231
  height: e.number().int().positive().optional(),
171
232
  start: e.number().nonnegative().optional(),
172
233
  end: e.number().positive().optional(),
173
234
  loop: e.boolean().optional(),
174
- subtitles: e.array(Se).optional(),
175
- license: m.optional(),
235
+ subtitles: e.array(O).optional(),
236
+ license: b.optional(),
176
237
  attribution: e.string().optional(),
177
238
  checksums: e.record(e.string(), e.string()).optional()
178
239
  }).refine((e) => e.start !== void 0 && e.end !== void 0 ? e.start < e.end : !0, {
@@ -181,12 +242,12 @@ var f = e.string().uuid({ message: "Invalid UUID format" }), p = e.string().min(
181
242
  }).refine((e) => !(e.type === "image" && !e.altText), {
182
243
  message: "Images must have alternative text (altText) defined for accessibility",
183
244
  path: ["altText"]
184
- }), x = e.record(_, Ce), S = e.object({
185
- name: v,
245
+ }), A = e.record(C, k), j = e.object({
246
+ name: w,
186
247
  role: e.string().optional(),
187
248
  email: e.string().email("Invalid email format").optional(),
188
- url: g.optional()
189
- }), C = e.enum([
249
+ url: S.optional()
250
+ }), M = e.enum([
190
251
  "url",
191
252
  "doi",
192
253
  "isbn",
@@ -197,16 +258,16 @@ var f = e.string().uuid({ message: "Invalid UUID format" }), p = e.string().min(
197
258
  "image",
198
259
  "model",
199
260
  "other"
200
- ]), w = e.object({
201
- id: v,
202
- type: C,
203
- value: v,
204
- title: v,
261
+ ]), N = e.object({
262
+ id: w,
263
+ type: M,
264
+ value: w,
265
+ title: w,
205
266
  description: e.string().optional(),
206
- authors: e.array(v).optional(),
207
- publishedDate: h.optional(),
208
- retrievedAt: h.optional(),
209
- license: m.optional()
267
+ authors: e.array(w).optional(),
268
+ publishedDate: x.optional(),
269
+ retrievedAt: x.optional(),
270
+ license: b.optional()
210
271
  }).refine((e) => {
211
272
  if ([
212
273
  "url",
@@ -223,75 +284,71 @@ var f = e.string().uuid({ message: "Invalid UUID format" }), p = e.string().min(
223
284
  }, {
224
285
  message: "For url, pdf, video, audio and image types, value must be a valid URL",
225
286
  path: ["value"]
226
- }), T = e.object({
227
- id: v,
287
+ }), P = e.object({
288
+ id: w,
228
289
  location: e.string().optional(),
229
- quote: y.optional()
230
- }), E = e.object({
290
+ quote: T.optional()
291
+ }), Ae = e.object({
231
292
  wikidataId: e.string().regex(/^Q\d+$/, "Wikidata ID must have format Q followed by number").optional(),
232
293
  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(),
294
+ }), je = e.record(e.string(), Ae), F = e.object({
295
+ 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
296
  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([
297
+ 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(),
298
+ 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()
299
+ }), Me = e.object({
300
+ lang: y,
301
+ id: v,
302
+ title: w,
303
+ downloadUrl: S.optional()
304
+ }), I = e.object({
305
+ id: v,
306
+ title: w,
307
+ downloadUrl: S.optional()
308
+ }), Ne = e.enum([
248
309
  "remember",
249
310
  "understand",
250
311
  "apply",
251
312
  "analyze",
252
313
  "evaluate",
253
314
  "create"
254
- ]), De = e.enum([
315
+ ]), Pe = e.enum([
255
316
  "low",
256
317
  "medium",
257
318
  "high"
258
- ]), Oe = e.object({
259
- bloomLevel: Ee.optional(),
319
+ ]), Fe = e.object({
320
+ bloomLevel: Ne.optional(),
260
321
  irtDifficulty: e.number().optional(),
261
322
  irtDiscrimination: e.number().optional(),
262
323
  irtGuessing: e.number().min(0).max(1, "IRT guessing must be between 0 and 1").optional(),
263
324
  avgTime: e.number().positive().optional(),
264
- cognitiveLoad: De.optional(),
325
+ cognitiveLoad: Pe.optional(),
265
326
  partialCredit: e.boolean().optional(),
266
327
  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(),
328
+ }), L = e.object({
329
+ id: v,
330
+ language: y,
331
+ title: w.max(500, "Title must not be longer than 500 characters"),
332
+ description: T.max(5e3, "Description must not be longer than 5000 characters").optional(),
333
+ thumbnail: C.optional(),
334
+ assets: A.optional(),
277
335
  ageMin: e.number().int().nonnegative().optional(),
278
336
  ageMax: e.number().int().nonnegative().optional(),
279
337
  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(),
338
+ createdAt: x,
339
+ updatedAt: x,
340
+ author: j.optional(),
341
+ contributors: e.array(j).optional(),
342
+ license: b.optional(),
343
+ licenseUrl: S.optional(),
344
+ requirements: F.optional(),
345
+ tags: e.array(w).optional(),
346
+ tagDefinitions: je.optional(),
347
+ translations: e.array(Me).optional(),
348
+ sourceMaterials: e.array(N).optional(),
291
349
  estimatedTime: e.number().positive().optional(),
292
- prerequisites: e.array(O).optional(),
293
- relatedSets: e.array(O).optional(),
294
- mathSettings: Ae.optional(),
350
+ prerequisites: e.array(I).optional(),
351
+ relatedSets: e.array(I).optional(),
295
352
  customData: e.record(e.string(), e.unknown()).optional(),
296
353
  appSpecific: e.record(e.string(), e.unknown()).optional()
297
354
  }).refine((e) => e.ageMin !== void 0 && e.ageMax !== void 0 ? e.ageMin <= e.ageMax : !0, {
@@ -300,130 +357,139 @@ var f = e.string().uuid({ message: "Invalid UUID format" }), p = e.string().min(
300
357
  }).refine((e) => new Date(e.createdAt) <= new Date(e.updatedAt), {
301
358
  message: "Creation date (createdAt) must be before or equal to update date (updatedAt)",
302
359
  path: ["updatedAt"]
303
- }), k = e.object({
304
- id: f,
360
+ }), R = e.object({
361
+ id: v,
305
362
  type: e.string(),
306
- assets: x.optional(),
307
- lang: p.optional(),
308
- tags: e.array(v).optional(),
363
+ assets: A.optional(),
364
+ lang: y.optional(),
365
+ tags: e.array(w).optional(),
366
+ topic: w.optional(),
309
367
  difficulty: e.number().int().min(1, "Difficulty must be at least 1").max(5, "Difficulty must be at most 5").optional(),
310
368
  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(),
369
+ hints: e.array(T.max(2e3, "Hint must not be longer than 2000 characters")).max(20, "Maximum 20 hints per item").optional(),
370
+ explanation: T.max(1e4, "Explanation must not be longer than 10000 characters").optional(),
371
+ incorrectFeedback: T.optional(),
372
+ sources: e.array(P).optional(),
373
+ relatedItems: e.array(v).optional(),
374
+ dependencyItems: e.array(v).optional(),
375
+ pedagogy: Fe.optional(),
318
376
  customData: e.record(e.string(), e.unknown()).optional(),
319
377
  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"),
378
+ }), Ie = e.object({
379
+ options: e.array(T).min(1, "Must have at least 1 option"),
322
380
  correctIndex: e.number().int().nonnegative()
323
381
  }).refine((e) => e.correctIndex < e.options.length, {
324
382
  message: "Correct answer index references non-existent option",
325
383
  path: ["correctIndex"]
326
- }), A = e.object({
384
+ }), z = e.object({
327
385
  type: e.literal("rect"),
328
386
  label: e.string().optional(),
329
387
  x: e.number().min(0).max(100, "X must be in range 0-100%"),
330
388
  y: e.number().min(0).max(100, "Y must be in range 0-100%"),
331
389
  width: e.number().min(0).max(100, "Width must be in range 0-100%"),
332
390
  height: e.number().min(0).max(100, "Height must be in range 0-100%")
333
- }), j = e.object({
391
+ }), B = e.object({
334
392
  type: e.literal("circle"),
335
393
  label: e.string().optional(),
336
394
  x: e.number().min(0).max(100, "X must be in range 0-100%"),
337
395
  y: e.number().min(0).max(100, "Y must be in range 0-100%"),
338
396
  radius: e.number().min(0).max(100, "Radius must be in range 0-100%")
339
- }), M = e.object({
397
+ }), V = e.object({
340
398
  type: e.literal("polygon"),
341
399
  label: e.string().optional(),
342
400
  points: e.array(e.object({
343
401
  x: e.number().min(0).max(100),
344
402
  y: e.number().min(0).max(100)
345
403
  })).min(3, "Polygon must have at least 3 points")
346
- }), N = e.object({
404
+ }), H = e.object({
347
405
  type: e.literal("mesh"),
348
406
  label: e.string().optional(),
349
- targetName: v
350
- }), P = e.discriminatedUnion("type", [
351
- A,
352
- j,
353
- M,
354
- N
355
- ]), F = e.object({
407
+ targetName: w
408
+ }), Le = e.discriminatedUnion("type", [
409
+ z,
410
+ B,
411
+ V,
412
+ H
413
+ ]), Re = e.discriminatedUnion("type", [
414
+ z,
415
+ B,
416
+ V
417
+ ]), U = e.object({
356
418
  x: e.number(),
357
419
  y: e.number(),
358
420
  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,
421
+ }), ze = e.object({
422
+ position: U.optional(),
423
+ target: U.optional()
424
+ }), Be = e.object({
425
+ id: w,
426
+ text: T,
365
427
  correctCategoryIndex: e.number().int().nonnegative()
366
- }), R = e.enum([
428
+ }), Ve = e.enum([
367
429
  "year",
368
430
  "month",
369
431
  "day",
370
432
  "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,
433
+ ]), He = e.object({
434
+ id: w,
435
+ text: T,
436
+ date: x,
437
+ precision: Ve.optional()
438
+ }), Ue = e.union([
439
+ z.extend({ correctLabelIndex: e.number().int().nonnegative() }),
440
+ B.extend({ correctLabelIndex: e.number().int().nonnegative() }),
441
+ V.extend({ correctLabelIndex: e.number().int().nonnegative() })
442
+ ]), W = e.object({
443
+ label: w,
382
444
  percentage: e.number().min(0, "Percentage must be non-negative").max(100, "Percentage must not exceed 100"),
383
445
  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, {
446
+ }), We = e.object({ criteria: e.array(W).min(1, "Rubric must have at least 1 criterion") }).refine((e) => e.criteria.reduce((e, t) => e + t.percentage, 0) > 0, {
385
447
  message: "Sum of percentages of all criteria must be greater than 0",
386
448
  path: ["criteria"]
387
- }), Ne = e.object({
449
+ }), Ge = e.object({
388
450
  min: e.number(),
389
451
  max: e.number()
390
452
  }).refine((e) => e.min <= e.max, {
391
453
  message: "Minimum value must be less than or equal to maximum value",
392
454
  path: ["max"]
393
- }), Pe = k.extend({
455
+ }), Ke = R.extend({
394
456
  type: e.literal("note"),
395
457
  title: e.string().optional(),
396
- content: y.max(1e4, "Content must not be longer than 10000 characters")
397
- }), Fe = k.extend({
458
+ content: T.max(1e4, "Content must not be longer than 10000 characters"),
459
+ hiddenContent: T.max(1e4, "Content must not be longer than 10000 characters").optional()
460
+ }), qe = R.extend({
398
461
  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({
462
+ front: T.max(1e4, "Front side must not be longer than 10000 characters"),
463
+ back: T.max(1e4, "Back side must not be longer than 10000 characters")
464
+ }), Je = R.extend({
402
465
  type: e.literal("true-false"),
403
- question: y.max(1e4, "Question must not be longer than 10000 characters"),
466
+ question: T.max(1e4, "Question must not be longer than 10000 characters"),
404
467
  answer: e.boolean()
405
- }), Le = k.extend({
468
+ }), Ye = R.extend({
406
469
  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"),
470
+ question: T.max(1e4, "Question must not be longer than 10000 characters"),
471
+ 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
472
  correctIndex: e.number().int().nonnegative(),
410
473
  shuffleOptions: e.boolean().optional(),
411
- optionExplanations: e.array(e.union([y, e.null()])).optional()
474
+ optionExplanations: e.array(e.union([T, e.null()])).optional()
412
475
  }).refine((e) => e.correctIndex < e.options.length, {
413
476
  message: "Correct answer index references non-existent option",
414
477
  path: ["correctIndex"]
415
478
  }).refine((e) => e.optionExplanations ? e.optionExplanations.length === e.options.length : !0, {
416
479
  message: "Number of option explanations must match number of options",
417
480
  path: ["optionExplanations"]
418
- }), Re = k.extend({
481
+ }).refine((e) => new Set(e.options.map((e) => e.toLowerCase())).size === e.options.length, {
482
+ message: "Options must not contain duplicates (case-insensitive)",
483
+ path: ["options"]
484
+ }), Xe = R.extend({
419
485
  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"),
486
+ question: T.max(1e4, "Question must not be longer than 10000 characters"),
487
+ 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
488
  correctIndices: e.array(e.number().int().nonnegative()).min(1, "Must have at least 1 correct answer"),
423
489
  minSelections: e.number().int().positive().optional(),
424
490
  maxSelections: e.number().int().positive().optional(),
425
491
  shuffleOptions: e.boolean().optional(),
426
- optionExplanations: e.array(e.union([y, e.null()])).optional()
492
+ optionExplanations: e.array(e.union([T, e.null()])).optional()
427
493
  }).refine((e) => e.correctIndices.every((t) => t < e.options.length), {
428
494
  message: "Some of correct answer indices reference non-existent option",
429
495
  path: ["correctIndices"]
@@ -436,22 +502,28 @@ var f = e.string().uuid({ message: "Invalid UUID format" }), p = e.string().min(
436
502
  }).refine((e) => e.maxSelections ? e.maxSelections <= e.options.length : !0, {
437
503
  message: "Maximum number of selections must not exceed number of options",
438
504
  path: ["maxSelections"]
505
+ }).refine((e) => e.minSelections ? e.minSelections <= e.options.length : !0, {
506
+ message: "minSelections cannot be greater than the number of options",
507
+ path: ["minSelections"]
439
508
  }).refine((e) => e.optionExplanations ? e.optionExplanations.length === e.options.length : !0, {
440
509
  message: "Number of option explanations must match number of options",
441
510
  path: ["optionExplanations"]
442
- }), ze = k.extend({
511
+ }).refine((e) => new Set(e.options.map((e) => e.toLowerCase())).size === e.options.length, {
512
+ message: "Options must not contain duplicates (case-insensitive)",
513
+ path: ["options"]
514
+ }), Ze = R.extend({
443
515
  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"),
516
+ question: T.max(1e4, "Question must not be longer than 10000 characters"),
517
+ answers: e.array(w).min(1, "Must have at least 1 correct answer"),
446
518
  caseSensitive: e.boolean().optional(),
447
519
  trimWhitespace: e.boolean().optional(),
448
520
  acceptPartial: e.boolean().optional(),
449
521
  ignoreDiacritics: e.boolean().optional()
450
- }), Be = k.extend({
522
+ }), Qe = R.extend({
451
523
  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")),
524
+ question: E,
525
+ text: T.max(1e4, "Text must not be longer than 10000 characters"),
526
+ blanks: e.record(D, e.array(w).min(1, "Each blank must have at least 1 correct answer")),
455
527
  caseSensitive: e.boolean().optional(),
456
528
  trimWhitespace: e.boolean().optional()
457
529
  }).refine((e) => Object.keys(e.blanks).length > 0, {
@@ -467,11 +539,11 @@ var f = e.string().uuid({ message: "Invalid UUID format" }), p = e.string().min(
467
539
  }, {
468
540
  message: "All tokens in text must have definition in blanks and all definitions must be used in text",
469
541
  path: ["blanks"]
470
- }), Ve = k.extend({
542
+ }), $e = R.extend({
471
543
  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)
544
+ question: E,
545
+ text: T.max(1e4, "Text must not be longer than 10000 characters"),
546
+ blanks: e.record(D, Ie)
475
547
  }).refine((e) => Object.keys(e.blanks).length > 0, {
476
548
  message: "Text must contain at least 1 blank to select",
477
549
  path: ["blanks"]
@@ -485,19 +557,19 @@ var f = e.string().uuid({ message: "Invalid UUID format" }), p = e.string().min(
485
557
  }, {
486
558
  message: "All tokens in text must have definition in blanks and all definitions must be used in text",
487
559
  path: ["blanks"]
488
- }), He = k.extend({
560
+ }), et = R.extend({
489
561
  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")
562
+ question: E,
563
+ prompts: e.array(T).min(2, "Must have at least 2 pairs to match").max(100, "Maximum 100 pairs"),
564
+ matches: e.array(T).min(2, "Must have at least 2 pairs to match").max(100, "Maximum 100 pairs")
493
565
  }).refine((e) => e.prompts.length === e.matches.length, {
494
566
  message: "Number of prompts must match number of matches",
495
567
  path: ["matches"]
496
- }), Ue = k.extend({
568
+ }), tt = R.extend({
497
569
  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"),
570
+ question: E,
571
+ leftItems: e.array(T).min(1, "Must have at least 1 item on left"),
572
+ rightItems: e.array(T).min(1, "Must have at least 1 item on right"),
501
573
  connections: e.array(e.tuple([e.number().int().nonnegative(), e.number().int().nonnegative()])).min(1, "Must have at least 1 connection"),
502
574
  minCorrect: e.number().int().positive().optional()
503
575
  }).refine((e) => e.connections.every(([t, n]) => t < e.leftItems.length && n < e.rightItems.length), {
@@ -509,13 +581,13 @@ var f = e.string().uuid({ message: "Invalid UUID format" }), p = e.string().min(
509
581
  }).refine((e) => e.minCorrect ? e.minCorrect <= e.connections.length : !0, {
510
582
  message: "Minimum correct answers must not exceed total number of connections",
511
583
  path: ["minCorrect"]
512
- }), We = k.extend({
584
+ }), nt = R.extend({
513
585
  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({
586
+ question: T.max(1e4, "Question must not be longer than 10000 characters"),
587
+ items: e.array(T).min(2, "Must have at least 2 items to sort")
588
+ }), rt = R.extend({
517
589
  type: e.literal("slider"),
518
- question: y.max(1e4, "Question must not be longer than 10000 characters"),
590
+ question: T.max(1e4, "Question must not be longer than 10000 characters"),
519
591
  min: e.number(),
520
592
  max: e.number(),
521
593
  step: e.number().positive("Step must be a positive number"),
@@ -537,34 +609,37 @@ var f = e.string().uuid({ message: "Invalid UUID format" }), p = e.string().min(
537
609
  }).refine((e) => e.tolerance <= (e.max - e.min) / 2, {
538
610
  message: "Tolerance must not be greater than half of value range",
539
611
  path: ["tolerance"]
540
- }), Ke = k.extend({
612
+ }), it = R.extend({
541
613
  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"),
614
+ question: T.max(1e4, "Question must not be longer than 10000 characters"),
615
+ targetAsset: C,
616
+ hotspots: e.array(Re).min(1, "Must have at least 1 hotspot"),
545
617
  multipleCorrect: e.boolean().optional(),
546
618
  minCorrect: e.number().int().positive().optional()
547
619
  }).refine((e) => e.minCorrect ? e.minCorrect <= e.hotspots.length : !0, {
548
620
  message: "Minimum correct answers must not exceed number of hotspots",
549
621
  path: ["minCorrect"]
550
- }), qe = k.extend({
622
+ }), at = R.extend({
551
623
  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")
624
+ question: T.max(1e4, "Question must not be longer than 10000 characters"),
625
+ categories: e.array(w).min(2, "Must have at least 2 categories"),
626
+ items: e.array(Be).min(1, "Must have at least 1 item to categorize")
627
+ }).refine((e) => new Set(e.categories.map((e) => e.toLowerCase())).size === e.categories.length, {
628
+ message: "Categories must not contain duplicates (case-insensitive)",
629
+ path: ["categories"]
555
630
  }).refine((e) => e.items.every((t) => t.correctCategoryIndex < e.categories.length), {
556
631
  message: "Some item references non-existent category",
557
632
  path: ["items"]
558
- }), Je = k.extend({
633
+ }), ot = R.extend({
559
634
  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"),
635
+ question: T.max(1e4, "Question must not be longer than 10000 characters"),
636
+ events: e.array(He).min(2, "Must have at least 2 events"),
562
637
  randomize: e.boolean().optional()
563
- }), Ye = k.extend({
638
+ }), st = R.extend({
564
639
  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"),
640
+ question: T.max(1e4, "Question must not be longer than 10000 characters"),
641
+ rows: e.array(w).min(1, "Must have at least 1 row"),
642
+ columns: e.array(w).min(1, "Must have at least 1 column"),
568
643
  correctCells: e.array(e.tuple([e.number().int().nonnegative(), e.number().int().nonnegative()])).min(1, "Must have at least 1 correct cell"),
569
644
  multiplePerRow: e.boolean().optional()
570
645
  }).refine((e) => e.correctCells.every(([t, n]) => t < e.rows.length && n < e.columns.length), {
@@ -583,70 +658,58 @@ var f = e.string().uuid({ message: "Invalid UUID format" }), p = e.string().min(
583
658
  }, {
584
659
  message: "If multiplePerRow is false, each row may have maximum 1 correct cell",
585
660
  path: ["correctCells"]
586
- }), Xe = k.extend({
661
+ }), ct = R.extend({
587
662
  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(),
663
+ question: T.max(1e4, "Question must not be longer than 10000 characters"),
664
+ correctAnswer: w,
665
+ alternativeAnswers: e.array(w).optional(),
591
666
  tolerance: e.number().nonnegative().optional()
592
- }), Ze = k.extend({
667
+ }), lt = R.extend({
593
668
  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"),
669
+ question: T.max(1e4, "Question must not be longer than 10000 characters"),
670
+ targetAsset: C,
671
+ labels: e.array(T).min(1, "Must have at least 1 label"),
597
672
  caseSensitive: e.boolean().optional(),
598
673
  requireTyping: e.boolean().optional(),
599
- zones: e.array(B).min(1, "Must have at least 1 zone")
674
+ zones: e.array(Ue).min(1, "Must have at least 1 zone")
600
675
  }).refine((e) => e.zones.every((t) => t.correctLabelIndex < e.labels.length), {
601
676
  message: "Some zone references non-existent label",
602
677
  path: ["zones"]
603
- }), Qe = k.extend({
678
+ }), ut = R.extend({
604
679
  type: e.literal("open-ended"),
605
- question: y.max(1e4, "Question must not be longer than 10000 characters"),
680
+ question: T.max(1e4, "Question must not be longer than 10000 characters"),
606
681
  minWords: e.number().int().positive().optional(),
607
682
  maxWords: e.number().int().positive().optional(),
608
- sampleAnswer: y.optional(),
609
- rubric: H.optional()
683
+ sampleAnswer: T.optional(),
684
+ rubric: We.optional()
610
685
  }).refine((e) => e.minWords && e.maxWords ? e.minWords <= e.maxWords : !0, {
611
686
  message: "Minimum word count must be less than or equal to maximum",
612
687
  path: ["maxWords"]
613
- }), $e = k.extend({
688
+ }), dt = R.extend({
614
689
  type: e.literal("numeric-input"),
615
- question: y.max(1e4, "Question must not be longer than 10000 characters"),
690
+ question: T.max(1e4, "Question must not be longer than 10000 characters"),
616
691
  value: e.number(),
617
692
  tolerance: e.number().nonnegative().optional(),
618
- range: Ne.optional(),
693
+ range: Ge.optional(),
619
694
  unit: e.string().optional()
620
- }), et = k.extend({
695
+ }), ft = R.extend({
621
696
  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"),
697
+ question: T.max(1e4, "Question must not be longer than 10000 characters"),
698
+ targetAsset: C,
699
+ hotspots: e.array(H).min(1, "Must have at least 1 hotspot"),
625
700
  multipleCorrect: e.boolean().optional(),
626
701
  minCorrect: e.number().int().positive().optional(),
627
- camera: I.optional()
702
+ camera: ze.optional()
628
703
  }).refine((e) => e.minCorrect ? e.minCorrect <= e.hotspots.length : !0, {
629
704
  message: "Minimum correct answers must not exceed number of hotspots",
630
705
  path: ["minCorrect"]
631
- }), tt = k.extend({
706
+ }), pt = R.extend({
632
707
  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"),
708
+ question: T.max(1e4, "Question must not be longer than 10000 characters"),
709
+ fen: w,
710
+ 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
711
  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,
712
+ }), G = e.discriminatedUnion("type", [
650
713
  Ke,
651
714
  qe,
652
715
  Je,
@@ -656,25 +719,37 @@ var f = e.string().uuid({ message: "Invalid UUID format" }), p = e.string().min(
656
719
  Qe,
657
720
  $e,
658
721
  et,
659
- tt
660
- ]), W = e.object({
722
+ tt,
723
+ nt,
724
+ rt,
725
+ it,
726
+ at,
727
+ ot,
728
+ st,
729
+ ct,
730
+ lt,
731
+ ut,
732
+ dt,
733
+ ft,
734
+ pt
735
+ ]), K = e.object({
661
736
  $schema: e.string().url().optional(),
662
737
  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")
738
+ meta: L,
739
+ items: e.array(G).max(1e4, "Maximum 10000 items per set")
665
740
  }).refine((e) => {
666
741
  let t = new Set(e.items.map((e) => e.id));
667
742
  for (let n of e.items) {
668
743
  if (n.relatedItems) {
669
- for (let e of n.relatedItems) if (!t.has(e)) return !1;
744
+ for (let e of n.relatedItems) if (!t.has(e) || n.id === e) return !1;
670
745
  }
671
746
  if (n.dependencyItems) {
672
- for (let e of n.dependencyItems) if (!t.has(e)) return !1;
747
+ for (let e of n.dependencyItems) if (!t.has(e) || n.id === e) return !1;
673
748
  }
674
749
  }
675
750
  return !0;
676
751
  }, {
677
- message: "Some item references non-existent relatedItems or dependencyItems",
752
+ message: "Some item references non-existent relatedItems, dependencyItems, or references itself",
678
753
  path: ["items"]
679
754
  }).refine((e) => e.meta.thumbnail && e.meta.assets ? e.meta.thumbnail in e.meta.assets : !0, {
680
755
  message: "Thumbnail references non-existent asset",
@@ -689,11 +764,27 @@ var f = e.string().uuid({ message: "Invalid UUID format" }), p = e.string().min(
689
764
  message: "Some item references non-existent source material",
690
765
  path: ["items"]
691
766
  });
692
- function nt(e) {
693
- return W.parse(e);
767
+ function mt(t) {
768
+ let n = t instanceof Error ? t.message : "OQSE Security Error: Maximum nesting depth exceeded limit of 10 levels.";
769
+ return new e.ZodError([{
770
+ code: e.ZodIssueCode.custom,
771
+ message: n,
772
+ path: []
773
+ }]);
774
+ }
775
+ function ht(e) {
776
+ return _(e, 10), K.parse(e);
694
777
  }
695
- function rt(e) {
696
- let t = W.safeParse(e);
778
+ function gt(e) {
779
+ try {
780
+ _(e, 10);
781
+ } catch (e) {
782
+ return {
783
+ success: !1,
784
+ error: mt(e)
785
+ };
786
+ }
787
+ let t = K.safeParse(e);
697
788
  return t.success ? {
698
789
  success: !0,
699
790
  data: t.data
@@ -702,11 +793,19 @@ function rt(e) {
702
793
  error: t.error
703
794
  };
704
795
  }
705
- function it(e) {
706
- return U.parse(e);
796
+ function _t(e) {
797
+ return _(e, 10), G.parse(e);
707
798
  }
708
- function at(e) {
709
- let t = U.safeParse(e);
799
+ function vt(e) {
800
+ try {
801
+ _(e, 10);
802
+ } catch (e) {
803
+ return {
804
+ success: !1,
805
+ error: mt(e)
806
+ };
807
+ }
808
+ let t = G.safeParse(e);
710
809
  return t.success ? {
711
810
  success: !0,
712
811
  data: t.data
@@ -715,7 +814,7 @@ function at(e) {
715
814
  error: t.error
716
815
  };
717
816
  }
718
- function ot(e) {
817
+ function yt(e) {
719
818
  return e.issues.map((e) => {
720
819
  let t = "";
721
820
  return e.path.forEach((n, r) => {
@@ -729,48 +828,79 @@ function ot(e) {
729
828
  }
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,31 @@ 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);
916
+ function Lt(e) {
917
+ return Z.safeParse(e);
788
918
  }
789
- function Ct(e) {
919
+ function Rt(e) {
790
920
  return e.issues.map((e) => {
791
921
  let t = e.path.map((e) => String(e)).join(".");
792
922
  return t ? `${t}: ${e.message}` : e.message;
793
923
  }).join("\n");
794
924
  }
795
- function wt(e) {
796
- return J.safeParse(e).success;
925
+ function zt(e) {
926
+ return Z.safeParse(e).success;
797
927
  }
798
928
  //#endregion
799
929
  //#region src/progressValidation.ts
800
- var Tt = e.object({
930
+ var Bt = e.object({
801
931
  attempts: e.number().int().nonnegative(),
802
932
  incorrect: e.number().int().nonnegative(),
803
933
  streak: e.number().int().nonnegative()
804
934
  }).refine((e) => e.incorrect <= e.attempts, {
805
935
  message: "incorrect cannot be higher than attempts",
806
936
  path: ["incorrect"]
807
- }), Y = e.object({
937
+ }), Vt = e.object({
808
938
  isCorrect: e.boolean(),
809
939
  confidence: e.union([
810
940
  e.literal(1),
@@ -812,14 +942,11 @@ var Tt = e.object({
812
942
  e.literal(3),
813
943
  e.literal(4)
814
944
  ]).optional(),
815
- answeredAt: h,
945
+ answeredAt: x,
816
946
  timeSpent: e.number().int().nonnegative().optional(),
817
- hintsUsed: e.number().int().nonnegative().optional(),
947
+ hintsUsed: e.number().int().nonnegative().default(0),
818
948
  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({
949
+ }), Ht = e.object({
823
950
  bucket: e.union([
824
951
  e.literal(0),
825
952
  e.literal(1),
@@ -827,83 +954,51 @@ var Tt = e.object({
827
954
  e.literal(3),
828
955
  e.literal(4)
829
956
  ]),
830
- nextReviewAt: h.optional(),
831
- stats: Tt,
832
- lastAnswer: Y.optional(),
957
+ nextReviewAt: x.optional(),
958
+ stats: Bt,
959
+ lastAnswer: Vt.optional(),
833
960
  appSpecific: e.record(e.string(), e.unknown()).optional()
834
- }), Dt = e.object({
835
- setId: f,
836
- exportedAt: h,
961
+ }), Ut = e.object({
962
+ setId: v,
963
+ exportedAt: x,
837
964
  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(),
965
+ }), Q = e.object({
966
+ $schema: e.url().optional(),
840
967
  version: e.string().regex(/^\d+\.\d+$/, "Version must be in MAJOR.MINOR format"),
841
- meta: Dt,
842
- records: e.record(f, Et)
968
+ meta: Ut,
969
+ records: e.record(v, Ht)
843
970
  });
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);
971
+ function Wt(e) {
972
+ return Q.parse(e);
874
973
  }
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);
974
+ function Gt(e) {
975
+ return Q.safeParse(e);
886
976
  }
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);
977
+ var $ = e.object(L.shape).pick({
978
+ id: !0,
979
+ title: !0,
980
+ language: !0,
981
+ updatedAt: !0,
982
+ description: !0,
983
+ author: !0,
984
+ subject: !0,
985
+ tags: !0,
986
+ createdAt: !0,
987
+ estimatedTime: !0,
988
+ requirements: !0
989
+ }).partial({ createdAt: !0 }).extend({
990
+ url: S,
991
+ $schema: e.string().url().optional()
992
+ });
993
+ function Kt(e) {
994
+ return $.parse(e);
900
995
  }
901
- function zt() {
902
- return Ft();
996
+ function qt(e) {
997
+ return $.safeParse(e);
903
998
  }
904
999
  //#endregion
905
1000
  //#region src/richTextProcessor.ts
906
- function Bt(e) {
1001
+ function Jt(e) {
907
1002
  let t = {};
908
1003
  return {
909
1004
  text: e.replace(/<(asset|blank):([a-zA-Z0-9_-]+)\s*\/>/gi, (e, n, r) => {
@@ -917,11 +1012,11 @@ function Bt(e) {
917
1012
  tokens: t
918
1013
  };
919
1014
  }
920
- function Vt(e) {
1015
+ function Yt(e) {
921
1016
  let t = e.replace(/`{1,}[^`]*`{1,}/g, "").replace(/~{3,}[\s\S]*?~{3,}/g, "");
922
1017
  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
1018
  }
924
- function Ht(e, t, n) {
1019
+ function Xt(e, t, n) {
925
1020
  let r = e;
926
1021
  for (let [e, i] of Object.entries(t)) {
927
1022
  let t = i.originalTag;
@@ -929,16 +1024,16 @@ function Ht(e, t, n) {
929
1024
  }
930
1025
  return r;
931
1026
  }
932
- function Ut(e, t, n) {
1027
+ function Zt(e, t, n) {
933
1028
  if (!e) return "";
934
- let r = t?.features?.includes("html") ?? !1, { text: i, tokens: a } = Bt(e);
935
- r || Vt(i);
1029
+ let r = t?.features?.includes("html") ?? !1, { text: i, tokens: a } = Jt(e);
1030
+ r || Yt(i);
936
1031
  let o = n.markdownParser(i);
937
1032
  if (r) {
938
1033
  if (!n.htmlSanitizer) throw Error("OQSE Security Error: Set requires 'html' (Tier 2), but no htmlSanitizer (like DOMPurify) was provided to the options.");
939
1034
  o = n.htmlSanitizer(o);
940
1035
  }
941
- return Ht(o, a, n);
1036
+ return Xt(o, a, n);
942
1037
  }
943
1038
  //#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 };
1039
+ export { S as AbsoluteURLSchema, A as AssetDictionarySchema, C as AssetKeySchema, jt as AudioMimeTypeSchema, R as BaseItemSchema, D as BlankTokenSchema, Ne as BloomLevelSchema, ze as CameraSetupSchema, Be as CategorizeItemObjectSchema, at as CategorizeItemSchema, pt as ChessPuzzleItemSchema, B as CircleHotspotSchema, Pe as CognitiveLoadSchema, lt as DiagramLabelItemSchema, Ue as DiagramZoneSchema, Dt as FeatureFlagSchema, F as FeatureProfileSchema, Qe as FillInBlanksItemSchema, $e as FillInSelectItemSchema, qe as FlashcardItemSchema, Re as Hotspot2DSchema, Le as HotspotObjectSchema, x as ISO8601DateTimeSchema, At as ImageMimeTypeSchema, Ot as ItemPropertyKeySchema, y as LanguageCodeSchema, Vt as LastAnswerObjectSchema, I as LinkedSetObjectSchema, Xe as MCQMultiItemSchema, Ye as MCQSingleItemSchema, Pt as ManifestAssetsSchema, Ft as ManifestCapabilitiesSchema, tt as MatchComplexItemSchema, et as MatchPairsItemSchema, ct as MathInputItemSchema, st as MatrixItemSchema, k as MediaObjectSchema, H as MeshHotspotSchema, kt as MetaPropertyKeySchema, Nt as ModelMimeTypeSchema, Ke as NoteItemSchema, dt as NumericInputItemSchema, Ge 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 OQSEPFileSchema, Et as OQSEQuestionDensitySchema, Tt as OQSEStudyModeSchema, ut as OpenEndedItemSchema, E as OptionalRichContentSchema, Fe as PedagogySchema, j as PersonObjectSchema, it as PinOnImageItemSchema, ft as PinOnModelItemSchema, w as PlainTextSchema, V as PolygonHotspotSchema, Ut as ProgressMetaSchema, Ht as ProgressRecordSchema, z as RectHotspotSchema, T as RichContentSchema, W as RubricCriterionSchema, We as RubricSchema, b as SPDXLicenseSchema, Ie as SelectBlankObjectSchema, Ze as ShortAnswerItemSchema, rt as SliderItemSchema, nt as SortItemsItemSchema, N as SourceMaterialSchema, M as SourceMaterialTypeSchema, P as SourceReferenceSchema, Bt as StatsObjectSchema, O as SubtitleTrackSchema, je as TagDefinitionDictionarySchema, Ae as TagDefinitionSchema, He as TimelineEventSchema, ot as TimelineItemSchema, Ve as TimelinePrecisionSchema, Me as TranslationObjectSchema, Je as TrueFalseItemSchema, v as UUIDSchema, U as Vector3Schema, Mt as VideoMimeTypeSchema, p as compareManifestVersions, Xt as detokenizeOqseTags, Rt as formatManifestErrors, yt as formatValidationErrors, 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, zt as isValidOQSEManifest, _e as isValidSemVer, Oe as isValidUUID, ye as isVersionCompatible, Zt as prepareRichTextForDisplay, Lt as safeValidateManifest, gt as safeValidateOQSEFile, qt as safeValidateOQSEHeader, vt as safeValidateOQSEItem, Gt as safeValidateOQSEPFile, Jt as tokenizeOqseTags, _ as validateJsonDepth, It as validateManifest, ht as validateOQSEFile, Kt as validateOQSEHeader, _t as validateOQSEItem, Wt as validateOQSEPFile, Yt as validateTier1Markdown };