@citolab/qti-components 7.28.0 → 7.28.1

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.
Files changed (50) hide show
  1. package/cdn/index.global.js +1 -1
  2. package/cdn/index.js +188 -188
  3. package/custom-elements.json +91 -1
  4. package/dist/base.d.ts +2 -2
  5. package/dist/base.js +5 -1
  6. package/dist/chunk-3WBG257S.js +697 -0
  7. package/dist/chunk-3WBG257S.js.map +1 -0
  8. package/dist/{chunk-Z2SUBRH5.js → chunk-3XV26R5M.js} +6 -1
  9. package/dist/chunk-3XV26R5M.js.map +1 -0
  10. package/dist/{chunk-LQZCSHN5.js → chunk-AQ5RJFM6.js} +2 -2
  11. package/dist/{chunk-N7S3GNUP.js → chunk-FLJAKWXL.js} +2 -2
  12. package/dist/{chunk-PINGOK2F.js → chunk-HFCZFWSH.js} +27 -48
  13. package/dist/chunk-HFCZFWSH.js.map +1 -0
  14. package/dist/{chunk-FK2IVMS3.js → chunk-MPC7LIPC.js} +3 -3
  15. package/dist/{chunk-YLIYPNMK.js → chunk-REI3AMCZ.js} +2 -2
  16. package/dist/{chunk-U2FLSHK7.js → chunk-RLTYVS2I.js} +25 -5
  17. package/dist/chunk-RLTYVS2I.js.map +1 -0
  18. package/dist/{chunk-F6WP6WEF.js → chunk-SP6S2WMG.js} +2 -2
  19. package/dist/{chunk-OQ77SE2W.js → chunk-WDO2TRFM.js} +4 -4
  20. package/dist/elements.js +4 -4
  21. package/dist/index.d.ts +3 -3
  22. package/dist/index.js +14 -10
  23. package/dist/interactions.d.ts +1 -1
  24. package/dist/interactions.js +3 -3
  25. package/dist/item.d.ts +7 -0
  26. package/dist/item.js +4 -4
  27. package/dist/loader.js +2 -2
  28. package/dist/processing.d.ts +2 -2
  29. package/dist/processing.js +2 -2
  30. package/dist/qti-components-jsx.d.ts +178 -151
  31. package/dist/{qti-condition-expression-B1BYmCcq.d.ts → qti-condition-expression-Dam-RER6.d.ts} +1 -1
  32. package/dist/{qti-transform-test-DMx816H0.d.ts → qti-transform-test-DoZaWItm.d.ts} +11 -9
  33. package/dist/qti.context-CejJMlfZ.d.ts +50 -0
  34. package/dist/test.d.ts +5 -3
  35. package/dist/test.js +6 -6
  36. package/dist/transformers.d.ts +1 -1
  37. package/dist/transformers.js +1 -1
  38. package/package.json +6 -6
  39. package/dist/chunk-BPIDAS3T.js +0 -495
  40. package/dist/chunk-BPIDAS3T.js.map +0 -1
  41. package/dist/chunk-PINGOK2F.js.map +0 -1
  42. package/dist/chunk-U2FLSHK7.js.map +0 -1
  43. package/dist/chunk-Z2SUBRH5.js.map +0 -1
  44. package/dist/qti.context-B8PSyIWm.d.ts +0 -14
  45. /package/dist/{chunk-LQZCSHN5.js.map → chunk-AQ5RJFM6.js.map} +0 -0
  46. /package/dist/{chunk-N7S3GNUP.js.map → chunk-FLJAKWXL.js.map} +0 -0
  47. /package/dist/{chunk-FK2IVMS3.js.map → chunk-MPC7LIPC.js.map} +0 -0
  48. /package/dist/{chunk-YLIYPNMK.js.map → chunk-REI3AMCZ.js.map} +0 -0
  49. /package/dist/{chunk-F6WP6WEF.js.map → chunk-SP6S2WMG.js.map} +0 -0
  50. /package/dist/{chunk-OQ77SE2W.js.map → chunk-WDO2TRFM.js.map} +0 -0
@@ -0,0 +1,697 @@
1
+ // ../qti-transformers/src/item/cdata.ts
2
+ function convertCDATAtoComment(xmlFragment) {
3
+ const cdataElements = xmlFragment.querySelectorAll('qti-custom-operator[class="js.org"] > qti-base-value');
4
+ cdataElements.forEach((element) => {
5
+ const commentText = document.createComment(element.textContent);
6
+ element.replaceChild(commentText, element.firstChild);
7
+ });
8
+ }
9
+
10
+ // ../qti-transformers/src/item/configure-pci.ts
11
+ async function configurePci(xmlFragment, baseUrl, getModuleResolutionConfig, selector = "qti-portable-custom-interaction") {
12
+ const customInteractionTypeIdentifiers = [];
13
+ const portableCustomInteractions = xmlFragment.querySelectorAll(selector);
14
+ if (portableCustomInteractions.length === 0) {
15
+ return;
16
+ }
17
+ let moduleResolutionConfig = null;
18
+ let moduleResolutionFallbackConfig = null;
19
+ const ensureDefaultModuleResolutionConfigs = async () => {
20
+ if (moduleResolutionConfig === null) {
21
+ try {
22
+ moduleResolutionConfig = await getModuleResolutionConfig(baseUrl, "/modules/module_resolution.js");
23
+ } catch {
24
+ moduleResolutionConfig = null;
25
+ }
26
+ }
27
+ if (moduleResolutionFallbackConfig === null) {
28
+ try {
29
+ moduleResolutionFallbackConfig = await getModuleResolutionConfig(
30
+ baseUrl,
31
+ "/modules/fallback_module_resolution.js"
32
+ );
33
+ } catch {
34
+ moduleResolutionFallbackConfig = null;
35
+ }
36
+ }
37
+ };
38
+ for (const interaction of Array.from(portableCustomInteractions)) {
39
+ interaction.setAttribute("data-base-url", baseUrl);
40
+ let customInteractionTypeIdentifier = interaction.getAttribute("custom-interaction-type-identifier");
41
+ if (customInteractionTypeIdentifier && customInteractionTypeIdentifiers.includes(customInteractionTypeIdentifier)) {
42
+ customInteractionTypeIdentifier = customInteractionTypeIdentifier + customInteractionTypeIdentifiers.length;
43
+ interaction.setAttribute("custom-interaction-type-identifier", customInteractionTypeIdentifier);
44
+ customInteractionTypeIdentifiers.push(customInteractionTypeIdentifier);
45
+ }
46
+ if (customInteractionTypeIdentifier) {
47
+ customInteractionTypeIdentifiers.push(customInteractionTypeIdentifier);
48
+ }
49
+ let modulesElement = interaction.querySelector("qti-interaction-modules");
50
+ if (modulesElement && modulesElement.getAttribute("primary-configuration")) {
51
+ await ensureDefaultModuleResolutionConfigs();
52
+ const primaryConfigPath = modulesElement.getAttribute("primary-configuration");
53
+ if (primaryConfigPath) {
54
+ try {
55
+ const primaryConfig = await getModuleResolutionConfig(baseUrl, `/${primaryConfigPath}`);
56
+ const existingModules = Array.from(modulesElement.querySelectorAll("qti-interaction-module"));
57
+ for (const moduleEl of existingModules) {
58
+ const moduleId = moduleEl.getAttribute("id");
59
+ if (moduleId && primaryConfig.paths && primaryConfig.paths[moduleId]) {
60
+ const primaryPath = primaryConfig.paths[moduleId];
61
+ const primaryPathString = Array.isArray(primaryPath) ? primaryPath[0] : primaryPath;
62
+ moduleEl.setAttribute("primary-path", primaryPathString);
63
+ if (moduleResolutionFallbackConfig && moduleResolutionFallbackConfig.paths && moduleResolutionFallbackConfig.paths[moduleId]) {
64
+ const fallbackPath = moduleResolutionFallbackConfig.paths[moduleId];
65
+ if (Array.isArray(fallbackPath)) {
66
+ moduleEl.setAttribute("fallback-path", fallbackPath[0]);
67
+ } else {
68
+ moduleEl.setAttribute("fallback-path", fallbackPath);
69
+ }
70
+ }
71
+ }
72
+ }
73
+ if (primaryConfig.paths) {
74
+ for (const moduleId in primaryConfig.paths) {
75
+ const existingModule = modulesElement.querySelector(`qti-interaction-module[id="${moduleId}"]`);
76
+ if (!existingModule) {
77
+ const newModuleElement = xmlFragment.createElement("qti-interaction-module");
78
+ newModuleElement.setAttribute("id", moduleId);
79
+ const primaryPathString = Array.isArray(primaryConfig.paths[moduleId]) ? primaryConfig.paths[moduleId][0] : primaryConfig.paths[moduleId];
80
+ newModuleElement.setAttribute("primary-path", primaryPathString);
81
+ if (moduleResolutionFallbackConfig && moduleResolutionFallbackConfig.paths && moduleResolutionFallbackConfig.paths[moduleId]) {
82
+ const fallbackPath = moduleResolutionFallbackConfig.paths[moduleId];
83
+ if (Array.isArray(fallbackPath)) {
84
+ newModuleElement.setAttribute("fallback-path", fallbackPath[0]);
85
+ } else {
86
+ newModuleElement.setAttribute("fallback-path", fallbackPath);
87
+ }
88
+ }
89
+ modulesElement.appendChild(newModuleElement);
90
+ }
91
+ }
92
+ }
93
+ if (primaryConfig.urlArgs) {
94
+ modulesElement.setAttribute("url-args", primaryConfig.urlArgs);
95
+ }
96
+ } catch (error) {
97
+ console.warn(`Failed to load primary configuration: ${primaryConfigPath}`, error);
98
+ }
99
+ }
100
+ } else {
101
+ await ensureDefaultModuleResolutionConfigs();
102
+ if (moduleResolutionConfig) {
103
+ if (interaction.querySelector("qti-interaction-modules") === null) {
104
+ modulesElement = xmlFragment.createElement("qti-interaction-modules");
105
+ interaction.appendChild(modulesElement);
106
+ } else {
107
+ modulesElement = interaction.querySelector("qti-interaction-modules");
108
+ }
109
+ for (const module in moduleResolutionConfig.paths) {
110
+ const path = moduleResolutionConfig.paths[module];
111
+ let fallbackPath = "";
112
+ if (moduleResolutionFallbackConfig && moduleResolutionFallbackConfig.paths && moduleResolutionFallbackConfig.paths[module]) {
113
+ fallbackPath = moduleResolutionFallbackConfig.paths[module];
114
+ }
115
+ const primaryArray = Array.isArray(path) ? path : [path];
116
+ const fallbackPathArray = Array.isArray(fallbackPath) ? fallbackPath : [fallbackPath];
117
+ const paths = primaryArray.map((primaryPath, i) => {
118
+ const fallbackPath2 = fallbackPathArray.length > i ? fallbackPathArray[i] : "";
119
+ return {
120
+ primaryPath,
121
+ fallbackPath: fallbackPath2
122
+ };
123
+ });
124
+ for (const fallbackPath2 of fallbackPathArray) {
125
+ if (!paths.some((p) => p.fallbackPath === fallbackPath2)) {
126
+ paths.push({
127
+ primaryPath: primaryArray.length > 0 ? primaryArray[0] : fallbackPath2,
128
+ fallbackPath: fallbackPath2
129
+ });
130
+ }
131
+ }
132
+ for (const path2 of paths) {
133
+ const moduleElement = xmlFragment.createElement("qti-interaction-module");
134
+ if (path2.fallbackPath) {
135
+ moduleElement.setAttribute("fallback-path", path2.fallbackPath);
136
+ }
137
+ moduleElement.setAttribute("id", module);
138
+ moduleElement.setAttribute("primary-path", path2.primaryPath);
139
+ if (modulesElement) {
140
+ modulesElement.appendChild(moduleElement);
141
+ }
142
+ }
143
+ }
144
+ }
145
+ }
146
+ }
147
+ }
148
+
149
+ // ../qti-transformers/src/item/extend.ts
150
+ function extendElementName(xmlFragment, tagName, extension) {
151
+ const allElements = Array.from(xmlFragment.getElementsByTagName("*"));
152
+ const matchingElements = allElements.filter(
153
+ (element) => element.localName === tagName || element.localName?.toLowerCase() === tagName.toLowerCase()
154
+ );
155
+ matchingElements.forEach((element) => {
156
+ const newTagName = `${tagName}-${extension}`;
157
+ const newElement = createElementWithNewTagName(element, newTagName);
158
+ element.replaceWith(newElement);
159
+ });
160
+ }
161
+ function extendElementsWithClass(xmlFragment, classNamePattern) {
162
+ xmlFragment.querySelectorAll("*").forEach((element) => {
163
+ const classList = element.classList;
164
+ if (classList) {
165
+ classList.forEach((className) => {
166
+ if (className.startsWith(`${classNamePattern}:`)) {
167
+ const suffix = className.slice(`${classNamePattern}:`.length);
168
+ const newTagName = `${element.nodeName}-${suffix}`;
169
+ const newElement = createElementWithNewTagName(element, newTagName);
170
+ element.replaceWith(newElement);
171
+ }
172
+ });
173
+ }
174
+ });
175
+ }
176
+ function createElementWithNewTagName(element, newTagName) {
177
+ const newElement = element.ownerDocument.createElement(newTagName);
178
+ for (const attr of element.attributes) {
179
+ newElement.setAttribute(attr.name, attr.value);
180
+ }
181
+ while (element.firstChild) {
182
+ newElement.appendChild(element.firstChild);
183
+ }
184
+ return newElement;
185
+ }
186
+
187
+ // ../qti-transformers/src/item/pci-hooks.ts
188
+ function pciHooks(xmlFragment, uri) {
189
+ const attributes = ["hook", "module"];
190
+ const documentPath = uri.substring(0, uri.lastIndexOf("/"));
191
+ for (const attribute of attributes) {
192
+ const srcAttributes = xmlFragment.querySelectorAll("[" + attribute + "]");
193
+ srcAttributes.forEach((node) => {
194
+ const srcValue = node.getAttribute(attribute);
195
+ if (!srcValue.startsWith("data:") && !srcValue.startsWith("http")) {
196
+ node.setAttribute("base-url", uri);
197
+ node.setAttribute("module", documentPath + "/" + encodeURI(srcValue + (srcValue.endsWith(".js") ? "" : ".js")));
198
+ }
199
+ });
200
+ }
201
+ }
202
+
203
+ // ../qti-transformers/src/shared/prng.ts
204
+ var SeededRandom = class _SeededRandom {
205
+ #state;
206
+ constructor(seed) {
207
+ if (!(seed instanceof Uint8Array)) {
208
+ throw new TypeError("SeededRandom seed must be a Uint8Array.");
209
+ }
210
+ if (seed.length > 32) {
211
+ throw new RangeError("SeededRandom seed must be 32 bytes or less.");
212
+ }
213
+ const paddedSeed = new Uint8Array(32);
214
+ paddedSeed.set(seed, 32 - seed.length);
215
+ this.#state = hashBytes(paddedSeed);
216
+ }
217
+ static fromSeed(seed) {
218
+ if (seed.length !== 32) {
219
+ throw new RangeError("SeededRandom.fromSeed requires a 32-byte seed.");
220
+ }
221
+ return new _SeededRandom(seed);
222
+ }
223
+ static fromFixed(byte) {
224
+ if (typeof byte !== "number") {
225
+ throw new TypeError("SeededRandom.fromFixed requires a number.");
226
+ }
227
+ if (!Number.isInteger(byte) || byte < 0 || byte > 255) {
228
+ throw new RangeError("SeededRandom.fromFixed requires an integer from 0 to 255.");
229
+ }
230
+ const seed = new Uint8Array(32);
231
+ seed[31] = byte;
232
+ return new _SeededRandom(seed);
233
+ }
234
+ static fromSeedKey(seedKey) {
235
+ const random = new _SeededRandom(new Uint8Array());
236
+ random.#state = hashString(`${seedKey}`);
237
+ return random;
238
+ }
239
+ random() {
240
+ this.#state |= 0;
241
+ this.#state = this.#state + 1831565813 | 0;
242
+ let t = Math.imul(this.#state ^ this.#state >>> 15, 1 | this.#state);
243
+ t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
244
+ return ((t ^ t >>> 14) >>> 0) / 4294967296;
245
+ }
246
+ };
247
+ function createSeededRandom(seedKey) {
248
+ return SeededRandom.fromSeedKey(seedKey);
249
+ }
250
+ function hashString(seedKey) {
251
+ let h = 1779033703 ^ seedKey.length;
252
+ for (let i = 0; i < seedKey.length; i++) {
253
+ h = Math.imul(h ^ seedKey.charCodeAt(i), 3432918353);
254
+ h = h << 13 | h >>> 19;
255
+ }
256
+ return finalizeHash(h);
257
+ }
258
+ function hashBytes(seed) {
259
+ let h = 1779033703 ^ seed.length;
260
+ for (let i = 0; i < seed.length; i++) {
261
+ h = Math.imul(h ^ seed[i], 3432918353);
262
+ h = h << 13 | h >>> 19;
263
+ }
264
+ return finalizeHash(h);
265
+ }
266
+ function finalizeHash(hash) {
267
+ let h = Math.imul(hash ^ hash >>> 16, 2246822507);
268
+ h = Math.imul(h ^ h >>> 13, 3266489909);
269
+ return (h ^ h >>> 16) >>> 0;
270
+ }
271
+
272
+ // ../qti-transformers/src/shared/shuffle.ts
273
+ var randomValue = (source) => typeof source === "function" ? source() : source.random();
274
+ function shuffleKeepingFixed(units, random) {
275
+ const movable = units.filter((unit) => !unit.fixed);
276
+ for (let i = movable.length - 1; i > 0; i--) {
277
+ const j = Math.floor(randomValue(random) * (i + 1));
278
+ [movable[i], movable[j]] = [movable[j], movable[i]];
279
+ }
280
+ let movableIndex = 0;
281
+ return units.map((unit) => unit.fixed ? unit : movable[movableIndex++]);
282
+ }
283
+
284
+ // ../qti-transformers/src/item/shuffle-interactions.ts
285
+ function getShuffleQuerySelectorByTagName(tagName) {
286
+ switch (tagName) {
287
+ case "qti-choice-interaction":
288
+ case "qti-order-interaction":
289
+ return "qti-simple-choice";
290
+ case "qti-inline-choice-interaction":
291
+ return "qti-inline-choice";
292
+ case "qti-match-interaction":
293
+ return [
294
+ "qti-simple-match-set:first-of-type qti-simple-associable-choice",
295
+ "qti-simple-match-set:last-of-type > qti-simple-associable-choice"
296
+ ];
297
+ case "qti-gap-match-interaction":
298
+ return "qti-gap-text";
299
+ case "qti-associate-interaction":
300
+ return "qti-simple-associable-choice";
301
+ default:
302
+ return null;
303
+ }
304
+ }
305
+ function shuffleInteractions(xmlFragment, seed) {
306
+ const shuffleElements = xmlFragment.querySelectorAll(`[shuffle="true"]`);
307
+ const shuffleInteractions2 = Array.from(shuffleElements).filter(
308
+ (e) => e.tagName?.toLowerCase().endsWith("-interaction")
309
+ );
310
+ const seeded = seed != null && `${seed}`.length > 0;
311
+ const itemId = xmlFragment.querySelector?.("qti-assessment-item")?.getAttribute("identifier") ?? "";
312
+ let interactionIndex = 0;
313
+ for (const shuffleInteraction of shuffleInteractions2) {
314
+ const responseId = shuffleInteraction.getAttribute("response-identifier") ?? `${interactionIndex}`;
315
+ interactionIndex++;
316
+ const query = getShuffleQuerySelectorByTagName(shuffleInteraction.tagName.toLowerCase());
317
+ const queries = Array.isArray(query) ? query : [query];
318
+ let shuffledAny = false;
319
+ let queryIndex = 0;
320
+ for (const q of queries) {
321
+ if (!q) continue;
322
+ const random = seeded ? createSeededRandom(`${seed}:${itemId}:${responseId}:${queryIndex}`) : Math.random;
323
+ queryIndex++;
324
+ const choices = Array.from(shuffleInteraction.querySelectorAll(q)).filter(
325
+ (choice) => choice.parentElement !== null
326
+ );
327
+ if (choices.filter((choice) => choice.getAttribute("fixed") !== "true").length <= 1) {
328
+ console.warn("Shuffling is not possible with fewer than 2 non-fixed elements.");
329
+ continue;
330
+ }
331
+ const parent = choices[0].parentElement;
332
+ if (!parent || choices.some((choice) => choice.parentElement !== parent)) {
333
+ console.warn("Shuffling is not possible when choices do not share the same parent element.");
334
+ continue;
335
+ }
336
+ const anchor = choices[choices.length - 1].nextSibling;
337
+ const orderedChoices = shuffleKeepingFixed(
338
+ choices.map((choice) => ({
339
+ element: choice,
340
+ fixed: choice.getAttribute("fixed") === "true"
341
+ })),
342
+ random
343
+ );
344
+ for (const choice of choices) {
345
+ choice.remove();
346
+ }
347
+ for (const { element } of orderedChoices) {
348
+ parent.insertBefore(element, anchor);
349
+ }
350
+ shuffledAny = true;
351
+ }
352
+ if (shuffledAny) {
353
+ shuffleInteraction.removeAttribute("shuffle");
354
+ }
355
+ }
356
+ }
357
+
358
+ // ../qti-transformers/src/item/stylesheets.ts
359
+ function stripStyleSheets(xmlFragment) {
360
+ xmlFragment.querySelectorAll("qti-stylesheet").forEach((stylesheet) => stylesheet.remove());
361
+ }
362
+
363
+ // ../qti-transformers/src/shared/xml.ts
364
+ function loadXML(url, signal) {
365
+ return fetch(url, { signal }).then((response) => {
366
+ if (!response.ok) {
367
+ throw new Error(`HTTP error! status: ${response.status}`);
368
+ }
369
+ return response.text();
370
+ }).then((text) => {
371
+ const parser = new DOMParser();
372
+ return parser.parseFromString(text, "text/xml");
373
+ }).catch((error) => {
374
+ if (error.name === "AbortError") {
375
+ throw error;
376
+ }
377
+ throw new Error(`Failed to load XML: ${error.message}`);
378
+ });
379
+ }
380
+ function parseXML(xmlDocument) {
381
+ const parser = new DOMParser();
382
+ const xmlFragment = parser.parseFromString(xmlDocument, "text/xml");
383
+ return xmlFragment;
384
+ }
385
+ function stripNamespaces(node, doc) {
386
+ if (node.nodeType === Node.ELEMENT_NODE) {
387
+ const el = node;
388
+ let newEl;
389
+ if (!el.namespaceURI || el.namespaceURI.startsWith("http://www.imsglobal.org/xsd/qti/") || el.namespaceURI.startsWith("http://www.imsglobal.org/xsd/imsqti")) {
390
+ newEl = doc.createElement(el.localName);
391
+ } else {
392
+ newEl = doc.createElementNS(el.namespaceURI, el.tagName);
393
+ }
394
+ for (let i = 0; i < el.attributes.length; i++) {
395
+ const attr = el.attributes[i];
396
+ newEl.setAttribute(attr.localName, attr.value);
397
+ }
398
+ for (let i = 0; i < el.childNodes.length; i++) {
399
+ newEl.appendChild(stripNamespaces(el.childNodes[i], doc));
400
+ }
401
+ return newEl;
402
+ }
403
+ return node.cloneNode(false);
404
+ }
405
+ function toHTML(xmlFragment) {
406
+ const fragment = document.createDocumentFragment();
407
+ for (let i = 0; i < xmlFragment.childNodes.length; i++) {
408
+ fragment.appendChild(stripNamespaces(xmlFragment.childNodes[i], document));
409
+ }
410
+ return fragment;
411
+ }
412
+ function setLocation(xmlFragment, location) {
413
+ if (!location.endsWith("/")) {
414
+ location += "/";
415
+ }
416
+ const allElements = xmlFragment.querySelectorAll("*");
417
+ allElements.forEach((el) => {
418
+ for (const attr of ["src", "href", "srcset", "poster"]) {
419
+ const attrValue = el.getAttribute(attr)?.trim();
420
+ if (attrValue && !/^(data:|https?:|blob:)/.test(attrValue)) {
421
+ const newValue = location + encodeURI(attrValue);
422
+ el.setAttribute(attr, newValue);
423
+ }
424
+ }
425
+ });
426
+ }
427
+
428
+ // ../qti-transformers/src/qti-transform-item.ts
429
+ var qtiTransformItem = () => {
430
+ let xmlFragment;
431
+ let xmlUri = "";
432
+ const api = {
433
+ load(uri, signal) {
434
+ xmlUri = uri;
435
+ return loadXML(uri, signal).then((xml) => {
436
+ xmlFragment = xml;
437
+ return api;
438
+ });
439
+ },
440
+ parse(xmlString) {
441
+ xmlFragment = parseXML(xmlString);
442
+ xmlUri = "";
443
+ return api;
444
+ },
445
+ path: (location) => {
446
+ setLocation(xmlFragment, location);
447
+ xmlUri = null;
448
+ return api;
449
+ },
450
+ fn(fn) {
451
+ fn(xmlFragment);
452
+ return api;
453
+ },
454
+ pciHooks(uri) {
455
+ pciHooks(xmlFragment, uri);
456
+ return api;
457
+ },
458
+ async configurePci(baseUrl, getModuleResolutionConfig, selector = "qti-portable-custom-interaction") {
459
+ await configurePci(xmlFragment, baseUrl, getModuleResolutionConfig, selector);
460
+ return api;
461
+ },
462
+ shuffleInteractions(seed) {
463
+ const normalizedSeed = typeof seed === "string" ? seed.trim() : seed;
464
+ if (normalizedSeed === null || normalizedSeed === void 0 || normalizedSeed === "") {
465
+ const fallbackSeed = xmlUri || "default-item-seed";
466
+ console.warn(
467
+ `[qtiTransformItem] No QTI_CONTEXT.seed provided; using "${fallbackSeed}" as deterministic fallback seed.`
468
+ );
469
+ shuffleInteractions(xmlFragment, fallbackSeed);
470
+ return api;
471
+ }
472
+ shuffleInteractions(xmlFragment, normalizedSeed);
473
+ return api;
474
+ },
475
+ extendElementName: (tagName, extension) => {
476
+ extendElementName(xmlFragment, tagName, extension);
477
+ return api;
478
+ },
479
+ extendElementsWithClass: (param = "extend") => {
480
+ extendElementsWithClass(xmlFragment, param);
481
+ return api;
482
+ },
483
+ customInteraction(baseRef, baseItem) {
484
+ const qtiCustomInteraction = xmlFragment.querySelector("qti-custom-interaction");
485
+ const qtiCustomInteractionObject = qtiCustomInteraction.querySelector("object");
486
+ qtiCustomInteraction.setAttribute("data-base-ref", baseRef);
487
+ qtiCustomInteraction.setAttribute("data-base-item", baseRef + baseItem);
488
+ qtiCustomInteraction.setAttribute("data", qtiCustomInteractionObject.getAttribute("data"));
489
+ qtiCustomInteraction.setAttribute("width", qtiCustomInteractionObject.getAttribute("width"));
490
+ qtiCustomInteraction.setAttribute("height", qtiCustomInteractionObject.getAttribute("height"));
491
+ qtiCustomInteraction.removeChild(qtiCustomInteractionObject);
492
+ return api;
493
+ },
494
+ convertCDATAtoComment() {
495
+ convertCDATAtoComment(xmlFragment);
496
+ return api;
497
+ },
498
+ stripStyleSheets() {
499
+ stripStyleSheets(xmlFragment);
500
+ return api;
501
+ },
502
+ html() {
503
+ if (xmlUri !== null) {
504
+ setLocation(xmlFragment, xmlUri.substring(0, xmlUri.lastIndexOf("/")));
505
+ }
506
+ return new XMLSerializer().serializeToString(toHTML(xmlFragment));
507
+ },
508
+ xml() {
509
+ return new XMLSerializer().serializeToString(xmlFragment);
510
+ },
511
+ htmlDoc() {
512
+ if (xmlUri !== null) {
513
+ setLocation(xmlFragment, xmlUri.substring(0, xmlUri.lastIndexOf("/")));
514
+ }
515
+ return toHTML(xmlFragment);
516
+ },
517
+ xmlDoc() {
518
+ return xmlFragment;
519
+ }
520
+ };
521
+ return api;
522
+ };
523
+
524
+ // ../qti-transformers/src/qti-transform-manifest.ts
525
+ var qtiTransformManifest = () => {
526
+ let xmlFragment;
527
+ const api = {
528
+ async load(uri, signal) {
529
+ return new Promise((resolve) => {
530
+ loadXML(uri, signal).then((xml) => {
531
+ xmlFragment = xml;
532
+ return resolve(api);
533
+ });
534
+ });
535
+ },
536
+ parse(xmlString) {
537
+ xmlFragment = parseXML(xmlString);
538
+ },
539
+ assessmentTest() {
540
+ const el = xmlFragment.querySelector('resource[type="imsqti_test_xmlv3p0"]');
541
+ return { href: el.getAttribute("href"), identifier: el.getAttribute("identifier") };
542
+ }
543
+ };
544
+ return api;
545
+ };
546
+
547
+ // ../qti-transformers/src/test/items.ts
548
+ function itemsFromTest(xmlFragment) {
549
+ const items = [];
550
+ xmlFragment.querySelectorAll("qti-assessment-item-ref").forEach((el) => {
551
+ const identifier = el.getAttribute("identifier");
552
+ const href = el.getAttribute("href");
553
+ const category = el.getAttribute("category");
554
+ items.push({ identifier, href, category });
555
+ });
556
+ return items;
557
+ }
558
+
559
+ // ../qti-transformers/src/test/shuffle-sections.ts
560
+ var isLocal = (el, ...names) => names.includes(el.localName) || names.includes(el.localName?.toLowerCase?.());
561
+ var isItemRef = (el) => isLocal(el, "qti-assessment-item-ref", "assessmentitemref");
562
+ var isSection = (el) => isLocal(el, "qti-assessment-section", "assessmentsection");
563
+ var attrIsTrue = (el, ...names) => names.some((n) => {
564
+ const v = (el.getAttribute(n) ?? "").trim().toLowerCase();
565
+ return v === "true" || v === "1";
566
+ });
567
+ var shuffleOrderingElements = (section) => Array.from(section.children).filter(
568
+ (child) => isLocal(child, "qti-ordering", "ordering") && attrIsTrue(child, "shuffle")
569
+ );
570
+ var rngFor = (seed, key) => createSeededRandom(`${seed}:${key}`);
571
+ function orderSection(section, seed) {
572
+ for (const child of Array.from(section.children)) {
573
+ if (isSection(child)) {
574
+ orderSection(child, seed);
575
+ }
576
+ }
577
+ const orderingEls = shuffleOrderingElements(section);
578
+ if (orderingEls.length === 0) {
579
+ return;
580
+ }
581
+ const units = [];
582
+ const toDetach = [];
583
+ for (const child of Array.from(section.children)) {
584
+ if (isItemRef(child)) {
585
+ units.push({ nodes: [child], fixed: attrIsTrue(child, "fixed") });
586
+ toDetach.push(child);
587
+ } else if (isSection(child)) {
588
+ const asBlock = attrIsTrue(child, "keep-together", "keeptogether") || attrIsTrue(child, "visible");
589
+ if (asBlock) {
590
+ units.push({ nodes: [child], fixed: attrIsTrue(child, "fixed") });
591
+ toDetach.push(child);
592
+ } else {
593
+ for (const inner of Array.from(child.children)) {
594
+ if (isItemRef(inner) || isSection(inner)) {
595
+ units.push({ nodes: [inner], fixed: attrIsTrue(inner, "fixed") });
596
+ }
597
+ }
598
+ toDetach.push(child);
599
+ }
600
+ }
601
+ }
602
+ if (units.length <= 1) {
603
+ for (const orderingEl of orderingEls) {
604
+ orderingEl.remove();
605
+ }
606
+ return;
607
+ }
608
+ const sectionKey = section.getAttribute("identifier") ?? "";
609
+ const ordered = shuffleKeepingFixed(units, rngFor(seed, sectionKey));
610
+ for (const el of toDetach) {
611
+ el.remove();
612
+ }
613
+ for (const unit of ordered) {
614
+ for (const node of unit.nodes) {
615
+ section.appendChild(node);
616
+ }
617
+ }
618
+ for (const orderingEl of orderingEls) {
619
+ orderingEl.remove();
620
+ }
621
+ }
622
+ function shuffleSectionsOrdering(doc, seed) {
623
+ const sections = Array.from(doc.getElementsByTagName("*")).filter((el) => isSection(el));
624
+ for (const section of sections) {
625
+ const parent = section.parentElement;
626
+ if (!parent || !isSection(parent)) {
627
+ orderSection(section, seed);
628
+ }
629
+ }
630
+ }
631
+
632
+ // ../qti-transformers/src/qti-transform-test.ts
633
+ var qtiTransformTest = () => {
634
+ let xmlFragment;
635
+ let xmlUri = "";
636
+ const api = {
637
+ async load(uri, signal) {
638
+ return new Promise((resolve, _) => {
639
+ loadXML(uri, signal).then((xml) => {
640
+ xmlFragment = xml;
641
+ xmlUri = uri;
642
+ api.path(uri.substring(0, uri.lastIndexOf("/")));
643
+ return resolve(api);
644
+ });
645
+ });
646
+ },
647
+ parse(xmlString) {
648
+ xmlFragment = parseXML(xmlString);
649
+ xmlUri = "";
650
+ return api;
651
+ },
652
+ path: (location) => {
653
+ setLocation(xmlFragment, location);
654
+ return api;
655
+ },
656
+ fn(fn) {
657
+ fn(xmlFragment);
658
+ return api;
659
+ },
660
+ shuffleOrdering(seed) {
661
+ const normalizedSeed = typeof seed === "string" ? seed.trim() : seed;
662
+ if (normalizedSeed === null || normalizedSeed === void 0 || normalizedSeed === "") {
663
+ const fallbackSeed = xmlUri || "default-test-seed";
664
+ console.warn(
665
+ `[qtiTransformTest] No QTI_CONTEXT.seed provided; using "${fallbackSeed}" as deterministic fallback seed.`
666
+ );
667
+ shuffleSectionsOrdering(xmlFragment, fallbackSeed);
668
+ return api;
669
+ }
670
+ shuffleSectionsOrdering(xmlFragment, normalizedSeed);
671
+ return api;
672
+ },
673
+ items() {
674
+ return itemsFromTest(xmlFragment);
675
+ },
676
+ html() {
677
+ return new XMLSerializer().serializeToString(toHTML(xmlFragment));
678
+ },
679
+ xml() {
680
+ return new XMLSerializer().serializeToString(xmlFragment);
681
+ },
682
+ htmlDoc() {
683
+ return toHTML(xmlFragment);
684
+ },
685
+ xmlDoc() {
686
+ return xmlFragment;
687
+ }
688
+ };
689
+ return api;
690
+ };
691
+
692
+ export {
693
+ qtiTransformItem,
694
+ qtiTransformManifest,
695
+ qtiTransformTest
696
+ };
697
+ //# sourceMappingURL=chunk-3WBG257S.js.map