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