@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/README.md +12 -2
- package/dist/index.cjs +2 -2
- package/dist/index.d.ts +2 -0
- package/dist/index.js +448 -353
- package/dist/src/header.d.ts +7 -0
- package/dist/src/headerValidation.d.ts +5 -0
- package/dist/src/headerValidation.test.d.ts +1 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/manifest.d.ts +15 -16
- package/dist/src/manifestValidation.d.ts +16 -4
- package/dist/src/oqse.d.ts +11 -24
- package/dist/src/oqseValidation.d.ts +95 -37
- package/dist/src/progress.d.ts +2 -2
- package/dist/src/utils.d.ts +5 -0
- package/dist/src/utils.test.d.ts +1 -0
- package/package.json +1 -1
- package/schemas/oqse-header-v0.1.json +120 -0
- package/schemas/oqse-manifest-v0.1.json +68 -9
- package/schemas/{oqsep-v0.1.json → oqse-progress-v0.1.json} +3 -1
- package/schemas/oqse-v0.1.json +153 -69
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
|
|
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
|
|
78
|
-
return !
|
|
77
|
+
function ge(e) {
|
|
78
|
+
return !s(e);
|
|
79
79
|
}
|
|
80
80
|
//#endregion
|
|
81
81
|
//#region src/manifest.ts
|
|
82
|
-
var
|
|
82
|
+
var c = [
|
|
83
83
|
"render",
|
|
84
84
|
"edit",
|
|
85
85
|
"validate",
|
|
86
86
|
"import",
|
|
87
87
|
"export"
|
|
88
|
-
],
|
|
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
|
-
],
|
|
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
|
-
],
|
|
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
|
|
128
|
+
function f(e) {
|
|
129
129
|
return /^\d+\.\d+$/.test(e);
|
|
130
130
|
}
|
|
131
|
-
function
|
|
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
|
|
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
|
|
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
|
|
144
|
-
return
|
|
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
|
|
149
|
-
lang:
|
|
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
|
-
}),
|
|
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:
|
|
168
|
-
caption:
|
|
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(
|
|
175
|
-
license:
|
|
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
|
-
}),
|
|
185
|
-
name:
|
|
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:
|
|
189
|
-
}),
|
|
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
|
-
]),
|
|
201
|
-
id:
|
|
202
|
-
type:
|
|
203
|
-
value:
|
|
204
|
-
title:
|
|
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(
|
|
207
|
-
publishedDate:
|
|
208
|
-
retrievedAt:
|
|
209
|
-
license:
|
|
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
|
-
}),
|
|
227
|
-
id:
|
|
287
|
+
}), P = e.object({
|
|
288
|
+
id: w,
|
|
228
289
|
location: e.string().optional(),
|
|
229
|
-
quote:
|
|
230
|
-
}),
|
|
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
|
-
}),
|
|
234
|
-
features: e.array(e.string().refine((e) =>
|
|
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) =>
|
|
237
|
-
metaProperties: e.array(e.string().refine((e) =>
|
|
238
|
-
}),
|
|
239
|
-
lang:
|
|
240
|
-
id:
|
|
241
|
-
title:
|
|
242
|
-
downloadUrl:
|
|
243
|
-
}),
|
|
244
|
-
id:
|
|
245
|
-
title:
|
|
246
|
-
downloadUrl:
|
|
247
|
-
}),
|
|
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
|
-
]),
|
|
315
|
+
]), Pe = e.enum([
|
|
255
316
|
"low",
|
|
256
317
|
"medium",
|
|
257
318
|
"high"
|
|
258
|
-
]),
|
|
259
|
-
bloomLevel:
|
|
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:
|
|
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
|
-
}),
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
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:
|
|
281
|
-
updatedAt:
|
|
282
|
-
author:
|
|
283
|
-
contributors: e.array(
|
|
284
|
-
license:
|
|
285
|
-
licenseUrl:
|
|
286
|
-
requirements:
|
|
287
|
-
tags: e.array(
|
|
288
|
-
tagDefinitions:
|
|
289
|
-
translations: e.array(
|
|
290
|
-
sourceMaterials: e.array(
|
|
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(
|
|
293
|
-
relatedSets: e.array(
|
|
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
|
-
}),
|
|
304
|
-
id:
|
|
360
|
+
}), R = e.object({
|
|
361
|
+
id: v,
|
|
305
362
|
type: e.string(),
|
|
306
|
-
assets:
|
|
307
|
-
lang:
|
|
308
|
-
tags: e.array(
|
|
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(
|
|
312
|
-
explanation:
|
|
313
|
-
incorrectFeedback:
|
|
314
|
-
sources: e.array(
|
|
315
|
-
relatedItems: e.array(
|
|
316
|
-
dependencyItems: e.array(
|
|
317
|
-
pedagogy:
|
|
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
|
-
}),
|
|
321
|
-
options: e.array(
|
|
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
|
-
}),
|
|
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
|
-
}),
|
|
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
|
-
}),
|
|
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
|
-
}),
|
|
404
|
+
}), H = e.object({
|
|
347
405
|
type: e.literal("mesh"),
|
|
348
406
|
label: e.string().optional(),
|
|
349
|
-
targetName:
|
|
350
|
-
}),
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
]),
|
|
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
|
-
}),
|
|
360
|
-
position:
|
|
361
|
-
target:
|
|
362
|
-
}),
|
|
363
|
-
id:
|
|
364
|
-
text:
|
|
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
|
-
}),
|
|
428
|
+
}), Ve = e.enum([
|
|
367
429
|
"year",
|
|
368
430
|
"month",
|
|
369
431
|
"day",
|
|
370
432
|
"datetime"
|
|
371
|
-
]),
|
|
372
|
-
id:
|
|
373
|
-
text:
|
|
374
|
-
date:
|
|
375
|
-
precision:
|
|
376
|
-
}),
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
]),
|
|
381
|
-
label:
|
|
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
|
-
}),
|
|
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
|
-
}),
|
|
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
|
-
}),
|
|
455
|
+
}), Ke = R.extend({
|
|
394
456
|
type: e.literal("note"),
|
|
395
457
|
title: e.string().optional(),
|
|
396
|
-
content:
|
|
397
|
-
|
|
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:
|
|
400
|
-
back:
|
|
401
|
-
}),
|
|
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:
|
|
466
|
+
question: T.max(1e4, "Question must not be longer than 10000 characters"),
|
|
404
467
|
answer: e.boolean()
|
|
405
|
-
}),
|
|
468
|
+
}), Ye = R.extend({
|
|
406
469
|
type: e.literal("mcq-single"),
|
|
407
|
-
question:
|
|
408
|
-
options: e.array(
|
|
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([
|
|
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
|
-
})
|
|
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:
|
|
421
|
-
options: e.array(
|
|
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([
|
|
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
|
-
})
|
|
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:
|
|
445
|
-
answers: e.array(
|
|
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
|
-
}),
|
|
522
|
+
}), Qe = R.extend({
|
|
451
523
|
type: e.literal("fill-in-blanks"),
|
|
452
|
-
question:
|
|
453
|
-
text:
|
|
454
|
-
blanks: e.record(
|
|
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
|
-
}),
|
|
542
|
+
}), $e = R.extend({
|
|
471
543
|
type: e.literal("fill-in-select"),
|
|
472
|
-
question:
|
|
473
|
-
text:
|
|
474
|
-
blanks: e.record(
|
|
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
|
-
}),
|
|
560
|
+
}), et = R.extend({
|
|
489
561
|
type: e.literal("match-pairs"),
|
|
490
|
-
question:
|
|
491
|
-
prompts: e.array(
|
|
492
|
-
matches: e.array(
|
|
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
|
-
}),
|
|
568
|
+
}), tt = R.extend({
|
|
497
569
|
type: e.literal("match-complex"),
|
|
498
|
-
question:
|
|
499
|
-
leftItems: e.array(
|
|
500
|
-
rightItems: e.array(
|
|
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
|
-
}),
|
|
584
|
+
}), nt = R.extend({
|
|
513
585
|
type: e.literal("sort-items"),
|
|
514
|
-
question:
|
|
515
|
-
items: e.array(
|
|
516
|
-
}),
|
|
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:
|
|
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
|
-
}),
|
|
612
|
+
}), it = R.extend({
|
|
541
613
|
type: e.literal("pin-on-image"),
|
|
542
|
-
question:
|
|
543
|
-
targetAsset:
|
|
544
|
-
hotspots: e.array(
|
|
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
|
-
}),
|
|
622
|
+
}), at = R.extend({
|
|
551
623
|
type: e.literal("categorize"),
|
|
552
|
-
question:
|
|
553
|
-
categories: e.array(
|
|
554
|
-
items: e.array(
|
|
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
|
-
}),
|
|
633
|
+
}), ot = R.extend({
|
|
559
634
|
type: e.literal("timeline"),
|
|
560
|
-
question:
|
|
561
|
-
events: e.array(
|
|
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
|
-
}),
|
|
638
|
+
}), st = R.extend({
|
|
564
639
|
type: e.literal("matrix"),
|
|
565
|
-
question:
|
|
566
|
-
rows: e.array(
|
|
567
|
-
columns: e.array(
|
|
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
|
-
}),
|
|
661
|
+
}), ct = R.extend({
|
|
587
662
|
type: e.literal("math-input"),
|
|
588
|
-
question:
|
|
589
|
-
correctAnswer:
|
|
590
|
-
alternativeAnswers: e.array(
|
|
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
|
-
}),
|
|
667
|
+
}), lt = R.extend({
|
|
593
668
|
type: e.literal("diagram-label"),
|
|
594
|
-
question:
|
|
595
|
-
targetAsset:
|
|
596
|
-
labels: e.array(
|
|
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(
|
|
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
|
-
}),
|
|
678
|
+
}), ut = R.extend({
|
|
604
679
|
type: e.literal("open-ended"),
|
|
605
|
-
question:
|
|
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:
|
|
609
|
-
rubric:
|
|
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
|
-
}),
|
|
688
|
+
}), dt = R.extend({
|
|
614
689
|
type: e.literal("numeric-input"),
|
|
615
|
-
question:
|
|
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:
|
|
693
|
+
range: Ge.optional(),
|
|
619
694
|
unit: e.string().optional()
|
|
620
|
-
}),
|
|
695
|
+
}), ft = R.extend({
|
|
621
696
|
type: e.literal("pin-on-model"),
|
|
622
|
-
question:
|
|
623
|
-
targetAsset:
|
|
624
|
-
hotspots: e.array(
|
|
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:
|
|
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
|
-
}),
|
|
706
|
+
}), pt = R.extend({
|
|
632
707
|
type: e.literal("chess-puzzle"),
|
|
633
|
-
question:
|
|
634
|
-
fen:
|
|
635
|
-
answers: e.array(e.array(
|
|
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
|
-
}),
|
|
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
|
-
|
|
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:
|
|
664
|
-
items: e.array(
|
|
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
|
|
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
|
|
693
|
-
|
|
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
|
|
696
|
-
|
|
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
|
|
706
|
-
return
|
|
796
|
+
function _t(e) {
|
|
797
|
+
return _(e, 10), G.parse(e);
|
|
707
798
|
}
|
|
708
|
-
function
|
|
709
|
-
|
|
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
|
|
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
|
|
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
|
-
]),
|
|
858
|
+
]), Et = e.enum([
|
|
737
859
|
"low",
|
|
738
860
|
"medium",
|
|
739
861
|
"high"
|
|
740
|
-
]),
|
|
741
|
-
function
|
|
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
|
|
749
|
-
image:
|
|
750
|
-
audio:
|
|
751
|
-
video:
|
|
752
|
-
model:
|
|
753
|
-
}),
|
|
754
|
-
actions: e.array(
|
|
755
|
-
types:
|
|
756
|
-
assets:
|
|
757
|
-
}),
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
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(
|
|
772
|
-
studyMode:
|
|
773
|
-
questionDensity:
|
|
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
|
|
784
|
-
return
|
|
913
|
+
function It(e) {
|
|
914
|
+
return Z.parse(e);
|
|
785
915
|
}
|
|
786
|
-
function
|
|
787
|
-
return
|
|
916
|
+
function Lt(e) {
|
|
917
|
+
return Z.safeParse(e);
|
|
788
918
|
}
|
|
789
|
-
function
|
|
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
|
|
796
|
-
return
|
|
925
|
+
function zt(e) {
|
|
926
|
+
return Z.safeParse(e).success;
|
|
797
927
|
}
|
|
798
928
|
//#endregion
|
|
799
929
|
//#region src/progressValidation.ts
|
|
800
|
-
var
|
|
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
|
-
}),
|
|
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:
|
|
945
|
+
answeredAt: x,
|
|
816
946
|
timeSpent: e.number().int().nonnegative().optional(),
|
|
817
|
-
hintsUsed: e.number().int().nonnegative().
|
|
947
|
+
hintsUsed: e.number().int().nonnegative().default(0),
|
|
818
948
|
isSkipped: e.boolean().optional()
|
|
819
|
-
})
|
|
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:
|
|
831
|
-
stats:
|
|
832
|
-
lastAnswer:
|
|
957
|
+
nextReviewAt: x.optional(),
|
|
958
|
+
stats: Bt,
|
|
959
|
+
lastAnswer: Vt.optional(),
|
|
833
960
|
appSpecific: e.record(e.string(), e.unknown()).optional()
|
|
834
|
-
}),
|
|
835
|
-
setId:
|
|
836
|
-
exportedAt:
|
|
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
|
-
}),
|
|
839
|
-
$schema: e.
|
|
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:
|
|
842
|
-
records: e.record(
|
|
968
|
+
meta: Ut,
|
|
969
|
+
records: e.record(v, Ht)
|
|
843
970
|
});
|
|
844
|
-
function
|
|
845
|
-
return
|
|
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
|
-
|
|
876
|
-
|
|
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
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
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
|
|
902
|
-
return
|
|
996
|
+
function qt(e) {
|
|
997
|
+
return $.safeParse(e);
|
|
903
998
|
}
|
|
904
999
|
//#endregion
|
|
905
1000
|
//#region src/richTextProcessor.ts
|
|
906
|
-
function
|
|
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
|
|
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
|
|
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
|
|
1027
|
+
function Zt(e, t, n) {
|
|
933
1028
|
if (!e) return "";
|
|
934
|
-
let r = t?.features?.includes("html") ?? !1, { text: i, tokens: a } =
|
|
935
|
-
r ||
|
|
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
|
|
1036
|
+
return Xt(o, a, n);
|
|
942
1037
|
}
|
|
943
1038
|
//#endregion
|
|
944
|
-
export {
|
|
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 };
|