@citolab/qti-components 7.28.1 → 8.0.0

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 (82) hide show
  1. package/cdn/index.global.js +1 -1
  2. package/cdn/index.js +6205 -2973
  3. package/dist/base.d.ts +9 -50
  4. package/dist/base.js +27 -6
  5. package/dist/chunk-5QYII4OZ.js +1374 -0
  6. package/dist/chunk-5QYII4OZ.js.map +1 -0
  7. package/dist/{chunk-MPC7LIPC.js → chunk-5SJS36BI.js} +4264 -3647
  8. package/dist/chunk-5SJS36BI.js.map +1 -0
  9. package/dist/chunk-64XSIBGO.js +241 -0
  10. package/dist/chunk-64XSIBGO.js.map +1 -0
  11. package/dist/{chunk-SP6S2WMG.js → chunk-7V4HJFHW.js} +3 -3
  12. package/dist/{chunk-SP6S2WMG.js.map → chunk-7V4HJFHW.js.map} +1 -1
  13. package/dist/{chunk-3XV26R5M.js → chunk-H3J7LFRO.js} +829 -1005
  14. package/dist/chunk-H3J7LFRO.js.map +1 -0
  15. package/dist/{chunk-3WBG257S.js → chunk-IJD53WY6.js} +96 -74
  16. package/dist/chunk-IJD53WY6.js.map +1 -0
  17. package/dist/chunk-KYEZRYO6.js +1608 -0
  18. package/dist/chunk-KYEZRYO6.js.map +1 -0
  19. package/dist/{chunk-HFCZFWSH.js → chunk-LZJHHZQ2.js} +1954 -1729
  20. package/dist/chunk-LZJHHZQ2.js.map +1 -0
  21. package/dist/chunk-MGF5F3S2.js +11 -0
  22. package/dist/chunk-MGF5F3S2.js.map +1 -0
  23. package/dist/chunk-MJVPNN7W.js +11 -0
  24. package/dist/chunk-MJVPNN7W.js.map +1 -0
  25. package/dist/{chunk-REI3AMCZ.js → chunk-NA2N2WSG.js} +1303 -1193
  26. package/dist/chunk-NA2N2WSG.js.map +1 -0
  27. package/dist/chunk-V5G7X53Y.js +11 -0
  28. package/dist/chunk-V5G7X53Y.js.map +1 -0
  29. package/dist/chunk-W4QZPCNC.js +294 -0
  30. package/dist/chunk-W4QZPCNC.js.map +1 -0
  31. package/dist/chunk-WCQ26LV7.js +102 -0
  32. package/dist/chunk-WCQ26LV7.js.map +1 -0
  33. package/dist/{chunk-WDO2TRFM.js → chunk-WVVMNF74.js} +851 -925
  34. package/dist/chunk-WVVMNF74.js.map +1 -0
  35. package/dist/{chunk-FLJAKWXL.js → chunk-X3E5HXG2.js} +2 -2
  36. package/dist/corrections.d.ts +1 -0
  37. package/dist/corrections.js +84 -0
  38. package/dist/elements.d.ts +1 -399
  39. package/dist/elements.js +6 -5
  40. package/dist/index.d.ts +9 -23
  41. package/dist/index.js +185 -76
  42. package/dist/interactions.d.ts +1 -915
  43. package/dist/interactions.js +19 -15
  44. package/dist/item.css +4118 -1920
  45. package/dist/item.d.ts +1 -134
  46. package/dist/item.js +6 -11
  47. package/dist/loader.d.ts +1 -22
  48. package/dist/loader.js +2 -3
  49. package/dist/processing.d.ts +1 -731
  50. package/dist/processing.js +2 -3
  51. package/dist/qti-components-jsx.d.ts +5220 -2571
  52. package/dist/test.d.ts +1 -539
  53. package/dist/test.js +26 -11
  54. package/dist/transformers.d.ts +1 -18
  55. package/dist/transformers.js +1 -2
  56. package/package.json +19 -15
  57. package/custom-elements.json +0 -43251
  58. package/dist/chunk-3WBG257S.js.map +0 -1
  59. package/dist/chunk-3XV26R5M.js.map +0 -1
  60. package/dist/chunk-AQ5RJFM6.js +0 -3673
  61. package/dist/chunk-AQ5RJFM6.js.map +0 -1
  62. package/dist/chunk-HFCZFWSH.js.map +0 -1
  63. package/dist/chunk-MPC7LIPC.js.map +0 -1
  64. package/dist/chunk-QXBXORM3.js +0 -27
  65. package/dist/chunk-REI3AMCZ.js.map +0 -1
  66. package/dist/chunk-RLTYVS2I.js +0 -530
  67. package/dist/chunk-RLTYVS2I.js.map +0 -1
  68. package/dist/chunk-WDO2TRFM.js.map +0 -1
  69. package/dist/computed-item.context-DfsW_96S.d.ts +0 -22
  70. package/dist/computed.context-DHbxad0N.d.ts +0 -45
  71. package/dist/config.context-BjZ2bZSY.d.ts +0 -42
  72. package/dist/interaction-Bgzlw7Iu.d.ts +0 -110
  73. package/dist/item.context-CkUeDcaO.d.ts +0 -15
  74. package/dist/qti-condition-expression-Dam-RER6.d.ts +0 -26
  75. package/dist/qti-feedback-ChmXhZuf.d.ts +0 -21
  76. package/dist/qti-rule-base-ajOnfGXY.d.ts +0 -16
  77. package/dist/qti-transform-test-DoZaWItm.d.ts +0 -70
  78. package/dist/qti.context-CejJMlfZ.d.ts +0 -50
  79. package/dist/test.context-CByZZjkR.d.ts +0 -15
  80. package/dist/variables-CMYcDbyW.d.ts +0 -70
  81. /package/dist/{chunk-FLJAKWXL.js.map → chunk-X3E5HXG2.js.map} +0 -0
  82. /package/dist/{chunk-QXBXORM3.js.map → corrections.js.map} +0 -0
@@ -1,4 +1,4 @@
1
- // ../qti-transformers/src/item/cdata.ts
1
+ // ../qti-transformers/dist/item/cdata.js
2
2
  function convertCDATAtoComment(xmlFragment) {
3
3
  const cdataElements = xmlFragment.querySelectorAll('qti-custom-operator[class="js.org"] > qti-base-value');
4
4
  cdataElements.forEach((element) => {
@@ -7,7 +7,7 @@ function convertCDATAtoComment(xmlFragment) {
7
7
  });
8
8
  }
9
9
 
10
- // ../qti-transformers/src/item/configure-pci.ts
10
+ // ../qti-transformers/dist/item/configure-pci.js
11
11
  async function configurePci(xmlFragment, baseUrl, getModuleResolutionConfig, selector = "qti-portable-custom-interaction") {
12
12
  const customInteractionTypeIdentifiers = [];
13
13
  const portableCustomInteractions = xmlFragment.querySelectorAll(selector);
@@ -26,10 +26,7 @@ async function configurePci(xmlFragment, baseUrl, getModuleResolutionConfig, sel
26
26
  }
27
27
  if (moduleResolutionFallbackConfig === null) {
28
28
  try {
29
- moduleResolutionFallbackConfig = await getModuleResolutionConfig(
30
- baseUrl,
31
- "/modules/fallback_module_resolution.js"
32
- );
29
+ moduleResolutionFallbackConfig = await getModuleResolutionConfig(baseUrl, "/modules/fallback_module_resolution.js");
33
30
  } catch {
34
31
  moduleResolutionFallbackConfig = null;
35
32
  }
@@ -146,12 +143,10 @@ async function configurePci(xmlFragment, baseUrl, getModuleResolutionConfig, sel
146
143
  }
147
144
  }
148
145
 
149
- // ../qti-transformers/src/item/extend.ts
146
+ // ../qti-transformers/dist/item/extend.js
150
147
  function extendElementName(xmlFragment, tagName, extension) {
151
148
  const allElements = Array.from(xmlFragment.getElementsByTagName("*"));
152
- const matchingElements = allElements.filter(
153
- (element) => element.localName === tagName || element.localName?.toLowerCase() === tagName.toLowerCase()
154
- );
149
+ const matchingElements = allElements.filter((element) => element.localName === tagName || element.localName?.toLowerCase() === tagName.toLowerCase());
155
150
  matchingElements.forEach((element) => {
156
151
  const newTagName = `${tagName}-${extension}`;
157
152
  const newElement = createElementWithNewTagName(element, newTagName);
@@ -184,7 +179,7 @@ function createElementWithNewTagName(element, newTagName) {
184
179
  return newElement;
185
180
  }
186
181
 
187
- // ../qti-transformers/src/item/pci-hooks.ts
182
+ // ../qti-transformers/dist/item/pci-hooks.js
188
183
  function pciHooks(xmlFragment, uri) {
189
184
  const attributes = ["hook", "module"];
190
185
  const documentPath = uri.substring(0, uri.lastIndexOf("/"));
@@ -200,7 +195,7 @@ function pciHooks(xmlFragment, uri) {
200
195
  }
201
196
  }
202
197
 
203
- // ../qti-transformers/src/shared/prng.ts
198
+ // ../qti-transformers/dist/shared/prng.js
204
199
  var SeededRandom = class _SeededRandom {
205
200
  #state;
206
201
  constructor(seed) {
@@ -269,7 +264,7 @@ function finalizeHash(hash) {
269
264
  return (h ^ h >>> 16) >>> 0;
270
265
  }
271
266
 
272
- // ../qti-transformers/src/shared/shuffle.ts
267
+ // ../qti-transformers/dist/shared/shuffle.js
273
268
  var randomValue = (source) => typeof source === "function" ? source() : source.random();
274
269
  function shuffleKeepingFixed(units, random) {
275
270
  const movable = units.filter((unit) => !unit.fixed);
@@ -281,7 +276,7 @@ function shuffleKeepingFixed(units, random) {
281
276
  return units.map((unit) => unit.fixed ? unit : movable[movableIndex++]);
282
277
  }
283
278
 
284
- // ../qti-transformers/src/item/shuffle-interactions.ts
279
+ // ../qti-transformers/dist/item/shuffle-interactions.js
285
280
  function getShuffleQuerySelectorByTagName(tagName) {
286
281
  switch (tagName) {
287
282
  case "qti-choice-interaction":
@@ -304,9 +299,7 @@ function getShuffleQuerySelectorByTagName(tagName) {
304
299
  }
305
300
  function shuffleInteractions(xmlFragment, seed) {
306
301
  const shuffleElements = xmlFragment.querySelectorAll(`[shuffle="true"]`);
307
- const shuffleInteractions2 = Array.from(shuffleElements).filter(
308
- (e) => e.tagName?.toLowerCase().endsWith("-interaction")
309
- );
302
+ const shuffleInteractions2 = Array.from(shuffleElements).filter((e) => e.tagName?.toLowerCase().endsWith("-interaction"));
310
303
  const seeded = seed != null && `${seed}`.length > 0;
311
304
  const itemId = xmlFragment.querySelector?.("qti-assessment-item")?.getAttribute("identifier") ?? "";
312
305
  let interactionIndex = 0;
@@ -318,12 +311,11 @@ function shuffleInteractions(xmlFragment, seed) {
318
311
  let shuffledAny = false;
319
312
  let queryIndex = 0;
320
313
  for (const q of queries) {
321
- if (!q) continue;
314
+ if (!q)
315
+ continue;
322
316
  const random = seeded ? createSeededRandom(`${seed}:${itemId}:${responseId}:${queryIndex}`) : Math.random;
323
317
  queryIndex++;
324
- const choices = Array.from(shuffleInteraction.querySelectorAll(q)).filter(
325
- (choice) => choice.parentElement !== null
326
- );
318
+ const choices = Array.from(shuffleInteraction.querySelectorAll(q)).filter((choice) => choice.parentElement !== null);
327
319
  if (choices.filter((choice) => choice.getAttribute("fixed") !== "true").length <= 1) {
328
320
  console.warn("Shuffling is not possible with fewer than 2 non-fixed elements.");
329
321
  continue;
@@ -334,13 +326,10 @@ function shuffleInteractions(xmlFragment, seed) {
334
326
  continue;
335
327
  }
336
328
  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
- );
329
+ const orderedChoices = shuffleKeepingFixed(choices.map((choice) => ({
330
+ element: choice,
331
+ fixed: choice.getAttribute("fixed") === "true"
332
+ })), random);
344
333
  for (const choice of choices) {
345
334
  choice.remove();
346
335
  }
@@ -355,12 +344,21 @@ function shuffleInteractions(xmlFragment, seed) {
355
344
  }
356
345
  }
357
346
 
358
- // ../qti-transformers/src/item/stylesheets.ts
347
+ // ../qti-transformers/dist/item/stylesheets.js
359
348
  function stripStyleSheets(xmlFragment) {
360
349
  xmlFragment.querySelectorAll("qti-stylesheet").forEach((stylesheet) => stylesheet.remove());
361
350
  }
362
351
 
363
- // ../qti-transformers/src/shared/xml.ts
352
+ // ../qti-transformers/dist/shared/missing-seed-warning.js
353
+ var missingSeedWarned = false;
354
+ function warnMissingSeed(scope, fallbackSeed) {
355
+ if (missingSeedWarned)
356
+ return;
357
+ missingSeedWarned = true;
358
+ console.warn(`[${scope}] No QTI_CONTEXT.seed provided; using "${fallbackSeed}" as deterministic fallback seed.`);
359
+ }
360
+
361
+ // ../qti-transformers/dist/shared/xml.js
364
362
  function loadXML(url, signal) {
365
363
  return fetch(url, { signal }).then((response) => {
366
364
  if (!response.ok) {
@@ -382,12 +380,12 @@ function parseXML(xmlDocument) {
382
380
  const xmlFragment = parser.parseFromString(xmlDocument, "text/xml");
383
381
  return xmlFragment;
384
382
  }
385
- function stripNamespaces(node, doc) {
383
+ function stripNamespaces(node, doc, registry) {
386
384
  if (node.nodeType === Node.ELEMENT_NODE) {
387
385
  const el = node;
388
386
  let newEl;
389
387
  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);
388
+ newEl = registry ? doc.createElement(el.localName, { customElementRegistry: registry }) : doc.createElement(el.localName);
391
389
  } else {
392
390
  newEl = doc.createElementNS(el.namespaceURI, el.tagName);
393
391
  }
@@ -396,16 +394,16 @@ function stripNamespaces(node, doc) {
396
394
  newEl.setAttribute(attr.localName, attr.value);
397
395
  }
398
396
  for (let i = 0; i < el.childNodes.length; i++) {
399
- newEl.appendChild(stripNamespaces(el.childNodes[i], doc));
397
+ newEl.appendChild(stripNamespaces(el.childNodes[i], doc, registry));
400
398
  }
401
399
  return newEl;
402
400
  }
403
401
  return node.cloneNode(false);
404
402
  }
405
- function toHTML(xmlFragment) {
403
+ function toHTML(xmlFragment, registry) {
406
404
  const fragment = document.createDocumentFragment();
407
405
  for (let i = 0; i < xmlFragment.childNodes.length; i++) {
408
- fragment.appendChild(stripNamespaces(xmlFragment.childNodes[i], document));
406
+ fragment.appendChild(stripNamespaces(xmlFragment.childNodes[i], document, registry));
409
407
  }
410
408
  return fragment;
411
409
  }
@@ -425,7 +423,7 @@ function setLocation(xmlFragment, location) {
425
423
  });
426
424
  }
427
425
 
428
- // ../qti-transformers/src/qti-transform-item.ts
426
+ // ../qti-transformers/dist/qti-transform-item.js
429
427
  var qtiTransformItem = () => {
430
428
  let xmlFragment;
431
429
  let xmlUri = "";
@@ -463,9 +461,7 @@ var qtiTransformItem = () => {
463
461
  const normalizedSeed = typeof seed === "string" ? seed.trim() : seed;
464
462
  if (normalizedSeed === null || normalizedSeed === void 0 || normalizedSeed === "") {
465
463
  const fallbackSeed = xmlUri || "default-item-seed";
466
- console.warn(
467
- `[qtiTransformItem] No QTI_CONTEXT.seed provided; using "${fallbackSeed}" as deterministic fallback seed.`
468
- );
464
+ warnMissingSeed("qtiTransformItem", fallbackSeed);
469
465
  shuffleInteractions(xmlFragment, fallbackSeed);
470
466
  return api;
471
467
  }
@@ -508,11 +504,11 @@ var qtiTransformItem = () => {
508
504
  xml() {
509
505
  return new XMLSerializer().serializeToString(xmlFragment);
510
506
  },
511
- htmlDoc() {
507
+ htmlDoc(registry) {
512
508
  if (xmlUri !== null) {
513
509
  setLocation(xmlFragment, xmlUri.substring(0, xmlUri.lastIndexOf("/")));
514
510
  }
515
- return toHTML(xmlFragment);
511
+ return toHTML(xmlFragment, registry);
516
512
  },
517
513
  xmlDoc() {
518
514
  return xmlFragment;
@@ -521,7 +517,7 @@ var qtiTransformItem = () => {
521
517
  return api;
522
518
  };
523
519
 
524
- // ../qti-transformers/src/qti-transform-manifest.ts
520
+ // ../qti-transformers/dist/qti-transform-manifest.js
525
521
  var qtiTransformManifest = () => {
526
522
  let xmlFragment;
527
523
  const api = {
@@ -544,7 +540,7 @@ var qtiTransformManifest = () => {
544
540
  return api;
545
541
  };
546
542
 
547
- // ../qti-transformers/src/test/items.ts
543
+ // ../qti-transformers/dist/test/items.js
548
544
  function itemsFromTest(xmlFragment) {
549
545
  const items = [];
550
546
  xmlFragment.querySelectorAll("qti-assessment-item-ref").forEach((el) => {
@@ -556,7 +552,7 @@ function itemsFromTest(xmlFragment) {
556
552
  return items;
557
553
  }
558
554
 
559
- // ../qti-transformers/src/test/shuffle-sections.ts
555
+ // ../qti-transformers/dist/test/shuffle-sections.js
560
556
  var isLocal = (el, ...names) => names.includes(el.localName) || names.includes(el.localName?.toLowerCase?.());
561
557
  var isItemRef = (el) => isLocal(el, "qti-assessment-item-ref", "assessmentitemref");
562
558
  var isSection = (el) => isLocal(el, "qti-assessment-section", "assessmentsection");
@@ -564,10 +560,37 @@ var attrIsTrue = (el, ...names) => names.some((n) => {
564
560
  const v = (el.getAttribute(n) ?? "").trim().toLowerCase();
565
561
  return v === "true" || v === "1";
566
562
  });
567
- var shuffleOrderingElements = (section) => Array.from(section.children).filter(
568
- (child) => isLocal(child, "qti-ordering", "ordering") && attrIsTrue(child, "shuffle")
569
- );
563
+ var attrIsFalse = (el, ...names) => names.some((n) => {
564
+ const v = (el.getAttribute(n) ?? "").trim().toLowerCase();
565
+ return v === "false" || v === "0";
566
+ });
567
+ var isOrdering = (el) => isLocal(el, "qti-ordering", "ordering");
568
+ var isSelection = (el) => isLocal(el, "qti-selection", "selection");
569
+ var shuffleOrderingElements = (section) => Array.from(section.children).filter((child) => isOrdering(child) && attrIsTrue(child, "shuffle"));
570
570
  var rngFor = (seed, key) => createSeededRandom(`${seed}:${key}`);
571
+ function collectItemRefsDeep(section) {
572
+ const itemRefs = [];
573
+ const dropped = [];
574
+ const walk = (el) => {
575
+ for (const child of Array.from(el.children)) {
576
+ if (isItemRef(child)) {
577
+ itemRefs.push(child);
578
+ } else if (isSection(child)) {
579
+ walk(child);
580
+ } else if (!isOrdering(child) && !isSelection(child)) {
581
+ dropped.push(child.localName);
582
+ }
583
+ }
584
+ };
585
+ walk(section);
586
+ return { itemRefs, dropped };
587
+ }
588
+ function warnDroppedChildren(section, dropped) {
589
+ if (dropped.length === 0)
590
+ return;
591
+ const identifier = section.getAttribute("identifier") ?? "(no identifier)";
592
+ console.warn(`[qtiTransformTest] Subsection "${identifier}" is consumed by section ordering; discarding its ${[...new Set(dropped)].join(", ")}.`);
593
+ }
571
594
  function orderSection(section, seed) {
572
595
  for (const child of Array.from(section.children)) {
573
596
  if (isSection(child)) {
@@ -585,26 +608,19 @@ function orderSection(section, seed) {
585
608
  units.push({ nodes: [child], fixed: attrIsTrue(child, "fixed") });
586
609
  toDetach.push(child);
587
610
  } 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
- }
611
+ const { itemRefs, dropped } = collectItemRefsDeep(child);
612
+ warnDroppedChildren(child, dropped);
613
+ if (attrIsFalse(child, "keep-together", "keeptogether")) {
614
+ for (const itemRef of itemRefs) {
615
+ units.push({ nodes: [itemRef], fixed: attrIsTrue(itemRef, "fixed") });
597
616
  }
598
- toDetach.push(child);
617
+ } else if (itemRefs.length > 0) {
618
+ units.push({ nodes: itemRefs, fixed: attrIsTrue(child, "fixed") });
599
619
  }
620
+ toDetach.push(child);
600
621
  }
601
622
  }
602
- if (units.length <= 1) {
603
- for (const orderingEl of orderingEls) {
604
- orderingEl.remove();
605
- }
606
- return;
607
- }
623
+ const anchor = toDetach.length > 0 ? toDetach[toDetach.length - 1].nextSibling : null;
608
624
  const sectionKey = section.getAttribute("identifier") ?? "";
609
625
  const ordered = shuffleKeepingFixed(units, rngFor(seed, sectionKey));
610
626
  for (const el of toDetach) {
@@ -612,24 +628,29 @@ function orderSection(section, seed) {
612
628
  }
613
629
  for (const unit of ordered) {
614
630
  for (const node of unit.nodes) {
615
- section.appendChild(node);
631
+ section.insertBefore(node, anchor);
616
632
  }
617
633
  }
618
634
  for (const orderingEl of orderingEls) {
619
635
  orderingEl.remove();
620
636
  }
621
637
  }
638
+ function hasShuffleOrdering(doc) {
639
+ return Array.from(doc.getElementsByTagName("*")).some((el) => isOrdering(el) && attrIsTrue(el, "shuffle"));
640
+ }
622
641
  function shuffleSectionsOrdering(doc, seed) {
623
642
  const sections = Array.from(doc.getElementsByTagName("*")).filter((el) => isSection(el));
624
643
  for (const section of sections) {
644
+ if (!section.parentNode)
645
+ continue;
625
646
  const parent = section.parentElement;
626
- if (!parent || !isSection(parent)) {
627
- orderSection(section, seed);
628
- }
647
+ if (parent && isSection(parent))
648
+ continue;
649
+ orderSection(section, seed);
629
650
  }
630
651
  }
631
652
 
632
- // ../qti-transformers/src/qti-transform-test.ts
653
+ // ../qti-transformers/dist/qti-transform-test.js
633
654
  var qtiTransformTest = () => {
634
655
  let xmlFragment;
635
656
  let xmlUri = "";
@@ -658,12 +679,13 @@ var qtiTransformTest = () => {
658
679
  return api;
659
680
  },
660
681
  shuffleOrdering(seed) {
682
+ if (!hasShuffleOrdering(xmlFragment)) {
683
+ return api;
684
+ }
661
685
  const normalizedSeed = typeof seed === "string" ? seed.trim() : seed;
662
686
  if (normalizedSeed === null || normalizedSeed === void 0 || normalizedSeed === "") {
663
687
  const fallbackSeed = xmlUri || "default-test-seed";
664
- console.warn(
665
- `[qtiTransformTest] No QTI_CONTEXT.seed provided; using "${fallbackSeed}" as deterministic fallback seed.`
666
- );
688
+ warnMissingSeed("qtiTransformTest", fallbackSeed);
667
689
  shuffleSectionsOrdering(xmlFragment, fallbackSeed);
668
690
  return api;
669
691
  }
@@ -679,8 +701,8 @@ var qtiTransformTest = () => {
679
701
  xml() {
680
702
  return new XMLSerializer().serializeToString(xmlFragment);
681
703
  },
682
- htmlDoc() {
683
- return toHTML(xmlFragment);
704
+ htmlDoc(registry) {
705
+ return toHTML(xmlFragment, registry);
684
706
  },
685
707
  xmlDoc() {
686
708
  return xmlFragment;
@@ -694,4 +716,4 @@ export {
694
716
  qtiTransformManifest,
695
717
  qtiTransformTest
696
718
  };
697
- //# sourceMappingURL=chunk-3WBG257S.js.map
719
+ //# sourceMappingURL=chunk-IJD53WY6.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../qti-transformers/src/item/cdata.ts","../../qti-transformers/src/item/configure-pci.ts","../../qti-transformers/src/item/extend.ts","../../qti-transformers/src/item/pci-hooks.ts","../../qti-transformers/src/shared/prng.ts","../../qti-transformers/src/shared/shuffle.ts","../../qti-transformers/src/item/shuffle-interactions.ts","../../qti-transformers/src/item/stylesheets.ts","../../qti-transformers/src/shared/missing-seed-warning.ts","../../qti-transformers/src/shared/xml.ts","../../qti-transformers/src/qti-transform-item.ts","../../qti-transformers/src/qti-transform-manifest.ts","../../qti-transformers/src/test/items.ts","../../qti-transformers/src/test/shuffle-sections.ts","../../qti-transformers/src/qti-transform-test.ts"],"sourcesContent":["export function convertCDATAtoComment(xmlFragment: DocumentFragment) {\n const cdataElements = xmlFragment.querySelectorAll('qti-custom-operator[class=\"js.org\"] > qti-base-value');\n cdataElements.forEach(element => {\n const commentText = document.createComment(element.textContent);\n element.replaceChild(commentText, element.firstChild);\n });\n}\n","// Type definition for module resolution config\nexport interface ModuleResolutionConfig {\n waitSeconds?: number;\n context?: string;\n catchError?: boolean;\n urlArgs?: string;\n paths: {\n [key: string]: string | string[];\n };\n shim?: {\n [key: string]: {\n deps?: string[]; // Array of dependencies\n exports?: string; // The global variable to use as the module's value\n };\n };\n}\n\nexport async function configurePci(\n xmlFragment: XMLDocument,\n baseUrl: string,\n getModuleResolutionConfig: (baseUrl: string, fileUrl: string) => Promise<ModuleResolutionConfig>,\n selector = 'qti-portable-custom-interaction'\n): Promise<void> {\n const customInteractionTypeIdentifiers: string[] = [];\n const portableCustomInteractions = xmlFragment.querySelectorAll(selector);\n\n // Avoid fetching module resolution configs for items that do not contain any PCIs.\n // This prevents unnecessary network requests when configurePci() is called for every item.\n if (portableCustomInteractions.length === 0) {\n return;\n }\n\n // Lazily load (and cache) the default module resolution configs.\n let moduleResolutionConfig: ModuleResolutionConfig | null = null;\n let moduleResolutionFallbackConfig: ModuleResolutionConfig | null = null;\n const ensureDefaultModuleResolutionConfigs = async () => {\n if (moduleResolutionConfig === null) {\n try {\n moduleResolutionConfig = await getModuleResolutionConfig(baseUrl, '/modules/module_resolution.js');\n } catch {\n moduleResolutionConfig = null;\n }\n }\n if (moduleResolutionFallbackConfig === null) {\n try {\n moduleResolutionFallbackConfig = await getModuleResolutionConfig(\n baseUrl,\n '/modules/fallback_module_resolution.js'\n );\n } catch {\n moduleResolutionFallbackConfig = null;\n }\n }\n };\n\n for (const interaction of Array.from(portableCustomInteractions)) {\n // set data-base-url\n interaction.setAttribute('data-base-url', baseUrl);\n\n let customInteractionTypeIdentifier = interaction.getAttribute('custom-interaction-type-identifier');\n if (customInteractionTypeIdentifier && customInteractionTypeIdentifiers.includes(customInteractionTypeIdentifier)) {\n customInteractionTypeIdentifier = customInteractionTypeIdentifier + customInteractionTypeIdentifiers.length;\n interaction.setAttribute('custom-interaction-type-identifier', customInteractionTypeIdentifier);\n customInteractionTypeIdentifiers.push(customInteractionTypeIdentifier);\n }\n if (customInteractionTypeIdentifier) {\n customInteractionTypeIdentifiers.push(customInteractionTypeIdentifier);\n }\n\n // Check if qti-interaction-modules already exists\n let modulesElement = interaction.querySelector('qti-interaction-modules');\n\n // If it exists and has primary-configuration, handle that format\n if (modulesElement && modulesElement.getAttribute('primary-configuration')) {\n await ensureDefaultModuleResolutionConfigs();\n const primaryConfigPath = modulesElement.getAttribute('primary-configuration');\n if (primaryConfigPath) {\n try {\n // Load the primary configuration\n const primaryConfig = await getModuleResolutionConfig(baseUrl, `/${primaryConfigPath}`);\n\n // Get existing module elements that only have id attributes\n const existingModules = Array.from(modulesElement.querySelectorAll('qti-interaction-module'));\n\n // Update existing modules with paths from config\n for (const moduleEl of existingModules) {\n const moduleId = moduleEl.getAttribute('id');\n if (moduleId && primaryConfig.paths && primaryConfig.paths[moduleId]) {\n const primaryPath = primaryConfig.paths[moduleId];\n const primaryPathString = Array.isArray(primaryPath) ? primaryPath[0] : primaryPath;\n moduleEl.setAttribute('primary-path', primaryPathString);\n\n // Check for fallback path\n if (\n moduleResolutionFallbackConfig &&\n moduleResolutionFallbackConfig.paths &&\n moduleResolutionFallbackConfig.paths[moduleId]\n ) {\n const fallbackPath = moduleResolutionFallbackConfig.paths[moduleId];\n if (Array.isArray(fallbackPath)) {\n moduleEl.setAttribute('fallback-path', fallbackPath[0]);\n } else {\n moduleEl.setAttribute('fallback-path', fallbackPath);\n }\n }\n }\n }\n\n // Add any additional modules from primary config that aren't already present\n if (primaryConfig.paths) {\n for (const moduleId in primaryConfig.paths) {\n const existingModule = modulesElement.querySelector(`qti-interaction-module[id=\"${moduleId}\"]`);\n if (!existingModule) {\n const newModuleElement = xmlFragment.createElement('qti-interaction-module');\n newModuleElement.setAttribute('id', moduleId);\n const primaryPathString = Array.isArray(primaryConfig.paths[moduleId])\n ? primaryConfig.paths[moduleId][0]\n : primaryConfig.paths[moduleId];\n newModuleElement.setAttribute('primary-path', primaryPathString);\n\n // Check for fallback path\n if (\n moduleResolutionFallbackConfig &&\n moduleResolutionFallbackConfig.paths &&\n moduleResolutionFallbackConfig.paths[moduleId]\n ) {\n const fallbackPath = moduleResolutionFallbackConfig.paths[moduleId];\n if (Array.isArray(fallbackPath)) {\n newModuleElement.setAttribute('fallback-path', fallbackPath[0]);\n } else {\n newModuleElement.setAttribute('fallback-path', fallbackPath);\n }\n }\n\n modulesElement.appendChild(newModuleElement);\n }\n }\n }\n\n // Apply urlArgs if present in config\n if (primaryConfig.urlArgs) {\n modulesElement.setAttribute('url-args', primaryConfig.urlArgs);\n }\n } catch (error) {\n console.warn(`Failed to load primary configuration: ${primaryConfigPath}`, error);\n }\n }\n } else {\n // Original logic for when there's no existing qti-interaction-modules or no primary-configuration\n await ensureDefaultModuleResolutionConfigs();\n if (moduleResolutionConfig) {\n // Create qti-interaction-modules if it doesn't exist\n if (interaction.querySelector('qti-interaction-modules') === null) {\n modulesElement = xmlFragment.createElement('qti-interaction-modules');\n interaction.appendChild(modulesElement);\n } else {\n modulesElement = interaction.querySelector('qti-interaction-modules');\n }\n\n for (const module in moduleResolutionConfig.paths) {\n const path = moduleResolutionConfig.paths[module];\n let fallbackPath: string | string[] = '';\n\n if (\n moduleResolutionFallbackConfig &&\n moduleResolutionFallbackConfig.paths &&\n moduleResolutionFallbackConfig.paths[module]\n ) {\n fallbackPath = moduleResolutionFallbackConfig.paths[module];\n }\n\n const primaryArray = Array.isArray(path) ? path : [path];\n const fallbackPathArray = Array.isArray(fallbackPath) ? fallbackPath : [fallbackPath];\n\n // create an array with primary and fallback paths.\n const paths = primaryArray.map((primaryPath, i) => {\n const fallbackPath = fallbackPathArray.length > i ? fallbackPathArray[i] : '';\n return {\n primaryPath,\n fallbackPath\n };\n });\n\n // check if all fallbackPath elements are in the array: paths, otherwise add\n for (const fallbackPath of fallbackPathArray) {\n if (!paths.some(p => p.fallbackPath === fallbackPath)) {\n paths.push({\n primaryPath: primaryArray.length > 0 ? primaryArray[0] : fallbackPath,\n fallbackPath\n });\n }\n }\n\n // add the paths to the qti-interaction-modules\n for (const path of paths) {\n const moduleElement = xmlFragment.createElement('qti-interaction-module');\n if (path.fallbackPath) {\n moduleElement.setAttribute('fallback-path', path.fallbackPath);\n }\n moduleElement.setAttribute('id', module);\n moduleElement.setAttribute('primary-path', path.primaryPath);\n\n if (modulesElement) {\n modulesElement.appendChild(moduleElement);\n }\n }\n }\n }\n }\n }\n}\n","// Function to extend elements with a specific tag name by adding an extension suffix\n// Uses localName matching to handle namespaced XML documents where querySelectorAll may not work\nexport function extendElementName(xmlFragment: XMLDocument, tagName: string, extension: string) {\n // Use getElementsByTagName with '*' to find all elements, then filter by localName\n // This works correctly for both namespaced and non-namespaced XML documents\n const allElements = Array.from(xmlFragment.getElementsByTagName('*'));\n const matchingElements = allElements.filter(\n element => element.localName === tagName || element.localName?.toLowerCase() === tagName.toLowerCase()\n );\n\n matchingElements.forEach(element => {\n const newTagName = `${tagName}-${extension}`;\n const newElement = createElementWithNewTagName(element, newTagName);\n element.replaceWith(newElement);\n });\n}\n\n// Function to extend any element with a specific class pattern (e.g., \"extend:suffix\")\nexport function extendElementsWithClass(xmlFragment: XMLDocument, classNamePattern: string) {\n xmlFragment.querySelectorAll('*').forEach(element => {\n const classList = element.classList;\n if (classList) {\n classList.forEach(className => {\n if (className.startsWith(`${classNamePattern}:`)) {\n const suffix = className.slice(`${classNamePattern}:`.length);\n const newTagName = `${element.nodeName}-${suffix}`;\n const newElement = createElementWithNewTagName(element, newTagName);\n element.replaceWith(newElement);\n }\n });\n }\n });\n}\n\n// Helper function to create a new element with a new tag name and copy attributes and children\nfunction createElementWithNewTagName(element: Element, newTagName: string) {\n // create Elements on the ownerDocument which is usually the XMLDocument\n const newElement = element.ownerDocument.createElement(newTagName);\n // Copy attributes\n for (const attr of element.attributes) {\n newElement.setAttribute(attr.name, attr.value);\n }\n // Copy child nodes\n while (element.firstChild) {\n newElement.appendChild(element.firstChild);\n }\n return newElement;\n}\n","export function pciHooks(xmlFragment: XMLDocument, uri: string): void {\n const attributes = ['hook', 'module'];\n const documentPath = uri.substring(0, uri.lastIndexOf('/'));\n for (const attribute of attributes) {\n const srcAttributes = xmlFragment.querySelectorAll('[' + attribute + ']');\n srcAttributes.forEach(node => {\n const srcValue = node.getAttribute(attribute)!;\n if (!srcValue.startsWith('data:') && !srcValue.startsWith('http')) {\n // Just paste the relative path of the src location after the documentrootPath\n // old pcis can have a .js, new pci's don't\n node.setAttribute('base-url', uri);\n node.setAttribute('module', documentPath + '/' + encodeURI(srcValue + (srcValue.endsWith('.js') ? '' : '.js')));\n }\n });\n }\n}\n","export interface SeededRandomSource {\n random(): number;\n}\n\n/**\n * Small, dependency-free seeded PRNG used for deterministic QTI shuffling\n * (sections and interactions). It intentionally exposes a `random()` method,\n * matching the TC39 seeded-random proposal shape so this can be swapped when a\n * standard implementation is available.\n *\n * xmur3-style seed hashing feeds mulberry32 (fast 32-bit generator).\n */\nexport class SeededRandom implements SeededRandomSource {\n #state: number;\n\n constructor(seed: Uint8Array) {\n if (!(seed instanceof Uint8Array)) {\n throw new TypeError('SeededRandom seed must be a Uint8Array.');\n }\n if (seed.length > 32) {\n throw new RangeError('SeededRandom seed must be 32 bytes or less.');\n }\n\n const paddedSeed = new Uint8Array(32);\n paddedSeed.set(seed, 32 - seed.length);\n this.#state = hashBytes(paddedSeed);\n }\n\n static fromSeed(seed: Uint8Array): SeededRandom {\n if (seed.length !== 32) {\n throw new RangeError('SeededRandom.fromSeed requires a 32-byte seed.');\n }\n return new SeededRandom(seed);\n }\n\n static fromFixed(byte: number): SeededRandom {\n if (typeof byte !== 'number') {\n throw new TypeError('SeededRandom.fromFixed requires a number.');\n }\n if (!Number.isInteger(byte) || byte < 0 || byte > 255) {\n throw new RangeError('SeededRandom.fromFixed requires an integer from 0 to 255.');\n }\n\n const seed = new Uint8Array(32);\n seed[31] = byte;\n return new SeededRandom(seed);\n }\n\n static fromSeedKey(seedKey: string | number): SeededRandom {\n const random = new SeededRandom(new Uint8Array());\n random.#state = hashString(`${seedKey}`);\n return random;\n }\n\n random(): number {\n this.#state |= 0;\n this.#state = (this.#state + 0x6d2b79f5) | 0;\n let t = Math.imul(this.#state ^ (this.#state >>> 15), 1 | this.#state);\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n }\n}\n\nexport function createSeededRandom(seedKey: string | number): SeededRandomSource {\n return SeededRandom.fromSeedKey(seedKey);\n}\n\nfunction hashString(seedKey: string): number {\n let h = 1779033703 ^ seedKey.length;\n for (let i = 0; i < seedKey.length; i++) {\n h = Math.imul(h ^ seedKey.charCodeAt(i), 3432918353);\n h = (h << 13) | (h >>> 19);\n }\n return finalizeHash(h);\n}\n\nfunction hashBytes(seed: Uint8Array): number {\n let h = 1779033703 ^ seed.length;\n for (let i = 0; i < seed.length; i++) {\n h = Math.imul(h ^ seed[i], 3432918353);\n h = (h << 13) | (h >>> 19);\n }\n return finalizeHash(h);\n}\n\nfunction finalizeHash(hash: number): number {\n let h = Math.imul(hash ^ (hash >>> 16), 2246822507);\n h = Math.imul(h ^ (h >>> 13), 3266489909);\n return (h ^ (h >>> 16)) >>> 0;\n}\n","import type { SeededRandomSource } from './prng';\n\nexport type RandomSource = SeededRandomSource | (() => number);\n\nconst randomValue = (source: RandomSource): number => (typeof source === 'function' ? source() : source.random());\n\n/**\n * Fisher-Yates over non-fixed units only. Fixed units keep their authored slot\n * index while movable units are shuffled into the remaining slots.\n */\nexport function shuffleKeepingFixed<T extends { fixed: boolean }>(units: T[], random: RandomSource): T[] {\n const movable = units.filter(unit => !unit.fixed);\n\n for (let i = movable.length - 1; i > 0; i--) {\n const j = Math.floor(randomValue(random) * (i + 1));\n [movable[i], movable[j]] = [movable[j], movable[i]];\n }\n\n let movableIndex = 0;\n return units.map(unit => (unit.fixed ? unit : movable[movableIndex++]));\n}\n","import { createSeededRandom } from '../shared/prng';\nimport { shuffleKeepingFixed } from '../shared/shuffle';\n\nfunction getShuffleQuerySelectorByTagName(tagName: string): string | string[] | null {\n switch (tagName) {\n case 'qti-choice-interaction':\n case 'qti-order-interaction':\n return 'qti-simple-choice';\n case 'qti-inline-choice-interaction':\n return 'qti-inline-choice';\n case 'qti-match-interaction':\n return [\n 'qti-simple-match-set:first-of-type qti-simple-associable-choice',\n 'qti-simple-match-set:last-of-type > qti-simple-associable-choice'\n ];\n case 'qti-gap-match-interaction':\n return 'qti-gap-text';\n case 'qti-associate-interaction':\n return 'qti-simple-associable-choice';\n default:\n return null;\n }\n}\n\n/**\n * Shuffles the choices inside every interaction marked `shuffle=\"true\"`. When\n * `seed` is supplied, shuffling is deterministic and reproducible across\n * reloads; each interaction/group draws its own stream so they are independent\n * and stable even if siblings change. When `seed` is null/undefined, falls back\n * to Math.random.\n */\nexport function shuffleInteractions(xmlFragment: XMLDocument, seed?: string | number | null): void {\n const shuffleElements = xmlFragment.querySelectorAll(`[shuffle=\"true\"]`);\n const shuffleInteractions = Array.from(shuffleElements).filter(e =>\n e.tagName?.toLowerCase().endsWith('-interaction')\n );\n\n const seeded = seed != null && `${seed}`.length > 0;\n const itemId = xmlFragment.querySelector?.('qti-assessment-item')?.getAttribute('identifier') ?? '';\n\n let interactionIndex = 0;\n for (const shuffleInteraction of shuffleInteractions) {\n const responseId = shuffleInteraction.getAttribute('response-identifier') ?? `${interactionIndex}`;\n interactionIndex++;\n const query = getShuffleQuerySelectorByTagName(shuffleInteraction.tagName.toLowerCase());\n const queries = Array.isArray(query) ? query : [query];\n let shuffledAny = false;\n\n let queryIndex = 0;\n for (const q of queries) {\n if (!q) continue;\n const random = seeded ? createSeededRandom(`${seed}:${itemId}:${responseId}:${queryIndex}`) : Math.random;\n queryIndex++;\n const choices = (Array.from(shuffleInteraction.querySelectorAll(q)) as HTMLElement[]).filter(\n choice => choice.parentElement !== null\n );\n\n if (choices.filter(choice => choice.getAttribute('fixed') !== 'true').length <= 1) {\n console.warn('Shuffling is not possible with fewer than 2 non-fixed elements.');\n continue;\n }\n\n const parent = choices[0].parentElement;\n if (!parent || choices.some(choice => choice.parentElement !== parent)) {\n console.warn('Shuffling is not possible when choices do not share the same parent element.');\n continue;\n }\n\n const anchor = choices[choices.length - 1].nextSibling;\n const orderedChoices = shuffleKeepingFixed(\n choices.map(choice => ({\n element: choice,\n fixed: choice.getAttribute('fixed') === 'true'\n })),\n random\n );\n\n for (const choice of choices) {\n choice.remove();\n }\n for (const { element } of orderedChoices) {\n parent.insertBefore(element, anchor);\n }\n\n shuffledAny = true;\n }\n\n if (shuffledAny) {\n shuffleInteraction.removeAttribute('shuffle');\n }\n }\n}\n","export function stripStyleSheets(xmlFragment: DocumentFragment) {\n // remove qti-stylesheet tag\n xmlFragment.querySelectorAll('qti-stylesheet').forEach(stylesheet => stylesheet.remove());\n}\n","/**\n * The missing-seed warning is advice about configuration, not about the document being\n * transformed — say it once per session, shared by the item and test transformers since\n * both are pointing at the same missing `QTI_CONTEXT.seed`.\n *\n * Deliberately not re-exported from the package entry: `resetMissingSeedWarning` exists so\n * tests can restore the once-per-session state, not as public API.\n */\nlet missingSeedWarned = false;\n\nexport function warnMissingSeed(scope: string, fallbackSeed: string): void {\n if (missingSeedWarned) return;\n missingSeedWarned = true;\n console.warn(`[${scope}] No QTI_CONTEXT.seed provided; using \"${fallbackSeed}\" as deterministic fallback seed.`);\n}\n\nexport function resetMissingSeedWarning(): void {\n missingSeedWarned = false;\n}\n","export function loadXML(url: string, signal?: AbortSignal): Promise<XMLDocument | null> {\n return fetch(url, { signal })\n .then(response => {\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n return response.text();\n })\n .then(text => {\n const parser = new DOMParser();\n return parser.parseFromString(text, 'text/xml');\n })\n .catch(error => {\n if (error.name === 'AbortError') {\n throw error;\n }\n throw new Error(`Failed to load XML: ${error.message}`);\n });\n}\n\nexport function parseXML(xmlDocument: string) {\n const parser = new DOMParser();\n const xmlFragment = parser.parseFromString(xmlDocument, 'text/xml');\n return xmlFragment;\n}\n\n// Function to strip unsupported namespaces (qti) from the nodes sent to the browser\nfunction stripNamespaces(node: Node, doc: Document, registry?: CustomElementRegistry): Node {\n if (node.nodeType === Node.ELEMENT_NODE) {\n const el = node as Element;\n let newEl: Element;\n\n if (\n !el.namespaceURI ||\n el.namespaceURI.startsWith('http://www.imsglobal.org/xsd/qti/') ||\n el.namespaceURI.startsWith('http://www.imsglobal.org/xsd/imsqti')\n ) {\n newEl = registry\n ? doc.createElement(el.localName, { customElementRegistry: registry })\n : doc.createElement(el.localName);\n } else {\n newEl = doc.createElementNS(el.namespaceURI, el.tagName);\n }\n\n for (let i = 0; i < el.attributes.length; i++) {\n const attr = el.attributes[i];\n newEl.setAttribute(attr.localName, attr.value);\n }\n for (let i = 0; i < el.childNodes.length; i++) {\n newEl.appendChild(stripNamespaces(el.childNodes[i], doc, registry));\n }\n return newEl;\n }\n return node.cloneNode(false);\n}\n\nexport function toHTML(xmlFragment: Document, registry?: CustomElementRegistry): DocumentFragment {\n const fragment = document.createDocumentFragment();\n for (let i = 0; i < xmlFragment.childNodes.length; i++) {\n fragment.appendChild(stripNamespaces(xmlFragment.childNodes[i], document, registry));\n }\n return fragment;\n}\n\n// Updates src and href attributes with the base location\n// Uses querySelectorAll('*') to find all elements, then checks attributes manually\n// This handles namespaced XML documents where attribute selectors like [href] may not work\n// Note: primary-path is NOT processed here because it is resolved separately\n// by the PCI component using data-base-url in the iframe's module resolution\nexport function setLocation(xmlFragment: DocumentFragment, location: string) {\n if (!location.endsWith('/')) {\n location += '/';\n }\n\n // querySelectorAll('*') finds all descendant elements regardless of namespace\n const allElements = xmlFragment.querySelectorAll('*');\n\n allElements.forEach(el => {\n // Check each attribute we care about\n // src, srcset and poster are URLDType or xs:anyURI everywhere they're used, so we care about them\n // Note: primary-path is excluded - PCI handles module path resolution via data-base-url\n for (const attr of ['src', 'href', 'srcset', 'poster'] as const) {\n const attrValue = el.getAttribute(attr)?.trim();\n\n if (attrValue && !/^(data:|https?:|blob:)/.test(attrValue)) {\n const newValue = location + encodeURI(attrValue);\n el.setAttribute(attr, newValue);\n }\n }\n });\n}\n","/**\n * Browser based QTI-XML to HTML transformer.\n * Returns an object with methods to load, parse, transform and serialize QTI XML items.\n * @returns An object with methods to load, parse, transform and serialize QTI XML items.\n * @example\n * const qtiTransformer = qtiTransformItem();\n * await qtiTransformer.load('path/to/xml/file.xml');\n * qtiTransformer.path('/assessmentItem/itemBody');\n * const html = qtiTransformer.html();\n * const xml = qtiTransformer.xml();\n * const htmldoc = qtiTransformer.htmldoc();\n * const xmldoc = qtiTransformer.xmldoc();\n *\n * qtiTransformItem().parse(storyXML).html()\n */\nimport { convertCDATAtoComment } from './item/cdata';\nimport { configurePci, type ModuleResolutionConfig } from './item/configure-pci';\nimport { extendElementName, extendElementsWithClass } from './item/extend';\nimport { pciHooks } from './item/pci-hooks';\nimport { shuffleInteractions } from './item/shuffle-interactions';\nimport { stripStyleSheets } from './item/stylesheets';\nimport { warnMissingSeed } from './shared/missing-seed-warning';\nimport { loadXML, parseXML, setLocation, toHTML } from './shared/xml';\n\nexport type { ModuleResolutionConfig };\n\nexport type transformItemApi = {\n load: (uri: string, signal?: AbortSignal) => Promise<transformItemApi>;\n parse: (xmlString: string) => transformItemApi;\n path: (location: string) => transformItemApi;\n fn: (fn: (xmlFragment: XMLDocument) => void) => transformItemApi;\n pciHooks: (uri: string) => transformItemApi;\n configurePci: (\n baseUrl: string,\n getModuleResolutionConfig: (baseUrl: string, fileUrl: string) => Promise<ModuleResolutionConfig>,\n selector?: string\n ) => Promise<transformItemApi>;\n extendElementName: (elementName: string, extend: string) => transformItemApi;\n extendElementsWithClass: (param?: string) => transformItemApi;\n customInteraction: (baseRef: string, baseItem: string) => transformItemApi;\n convertCDATAtoComment: () => transformItemApi;\n shuffleInteractions: (seed?: string | number | null) => transformItemApi;\n stripStyleSheets: () => transformItemApi;\n html: () => string;\n xml: () => string;\n htmlDoc: (registry?: CustomElementRegistry) => DocumentFragment;\n xmlDoc: () => XMLDocument;\n};\n\nexport const qtiTransformItem = () => {\n let xmlFragment: XMLDocument;\n let xmlUri = '';\n\n const api: transformItemApi = {\n load(uri: string, signal?: AbortSignal) {\n xmlUri = uri;\n return loadXML(uri, signal).then(xml => {\n xmlFragment = xml;\n return api;\n });\n },\n parse(xmlString: string): typeof api {\n xmlFragment = parseXML(xmlString);\n xmlUri = '';\n return api;\n },\n path: (location: string): typeof api => {\n setLocation(xmlFragment, location);\n xmlUri = null;\n return api;\n },\n fn(fn: (xmlFragment: XMLDocument) => void): typeof api {\n fn(xmlFragment);\n return api;\n },\n pciHooks(uri: string): typeof api {\n pciHooks(xmlFragment, uri);\n return api;\n },\n async configurePci(\n baseUrl: string,\n getModuleResolutionConfig: (baseUrl: string, fileUrl: string) => Promise<ModuleResolutionConfig>,\n selector = 'qti-portable-custom-interaction'\n ): Promise<typeof api> {\n await configurePci(xmlFragment, baseUrl, getModuleResolutionConfig, selector);\n return api;\n },\n shuffleInteractions(seed?: string | number | null): typeof api {\n const normalizedSeed = typeof seed === 'string' ? seed.trim() : seed;\n\n if (normalizedSeed === null || normalizedSeed === undefined || normalizedSeed === '') {\n const fallbackSeed = xmlUri || 'default-item-seed';\n warnMissingSeed('qtiTransformItem', fallbackSeed);\n shuffleInteractions(xmlFragment, fallbackSeed);\n return api;\n }\n\n shuffleInteractions(xmlFragment, normalizedSeed);\n return api;\n },\n extendElementName: (tagName: string, extension: string): typeof api => {\n extendElementName(xmlFragment, tagName, extension);\n return api;\n },\n extendElementsWithClass: (param: string = 'extend'): typeof api => {\n extendElementsWithClass(xmlFragment, param);\n return api;\n },\n customInteraction(baseRef: string, baseItem: string): typeof api {\n const qtiCustomInteraction = xmlFragment.querySelector('qti-custom-interaction');\n const qtiCustomInteractionObject = qtiCustomInteraction.querySelector('object');\n\n qtiCustomInteraction.setAttribute('data-base-ref', baseRef);\n qtiCustomInteraction.setAttribute('data-base-item', baseRef + baseItem);\n qtiCustomInteraction.setAttribute('data', qtiCustomInteractionObject.getAttribute('data'));\n qtiCustomInteraction.setAttribute('width', qtiCustomInteractionObject.getAttribute('width'));\n qtiCustomInteraction.setAttribute('height', qtiCustomInteractionObject.getAttribute('height'));\n\n qtiCustomInteraction.removeChild(qtiCustomInteractionObject);\n return api;\n },\n convertCDATAtoComment(): typeof api {\n convertCDATAtoComment(xmlFragment);\n return api;\n },\n stripStyleSheets(): typeof api {\n stripStyleSheets(xmlFragment);\n return api;\n },\n html() {\n if (xmlUri !== null) {\n setLocation(xmlFragment, xmlUri.substring(0, xmlUri.lastIndexOf('/')));\n }\n return new XMLSerializer().serializeToString(toHTML(xmlFragment));\n },\n xml(): string {\n return new XMLSerializer().serializeToString(xmlFragment);\n },\n htmlDoc(registry?: CustomElementRegistry) {\n if (xmlUri !== null) {\n setLocation(xmlFragment, xmlUri.substring(0, xmlUri.lastIndexOf('/')));\n }\n return toHTML(xmlFragment, registry);\n },\n xmlDoc(): XMLDocument {\n return xmlFragment; // new XMLSerializer().serializeToString(xmlFragment);\n }\n };\n return api;\n};\n","import { loadXML, parseXML } from './shared/xml';\n\nexport const qtiTransformManifest = (): {\n load: (uri: string, signal?: AbortSignal) => Promise<typeof api>;\n assessmentTest: () => { href: string; identifier: string };\n} => {\n let xmlFragment: XMLDocument;\n\n const api = {\n async load(uri: string, signal: AbortSignal) {\n return new Promise<typeof api>(resolve => {\n loadXML(uri, signal).then(xml => {\n xmlFragment = xml;\n return resolve(api);\n });\n });\n },\n parse(xmlString: string) {\n xmlFragment = parseXML(xmlString);\n },\n assessmentTest() {\n const el = xmlFragment.querySelector('resource[type=\"imsqti_test_xmlv3p0\"]');\n return { href: el.getAttribute('href'), identifier: el.getAttribute('identifier') };\n }\n };\n return api;\n};\n","export function itemsFromTest(xmlFragment: DocumentFragment) {\n const items: { identifier: string; href: string; category: string }[] = [];\n xmlFragment.querySelectorAll('qti-assessment-item-ref').forEach(el => {\n const identifier = el.getAttribute('identifier');\n const href = el.getAttribute('href');\n const category = el.getAttribute('category');\n items.push({ identifier, href, category });\n });\n return items;\n}\n","import { createSeededRandom } from '../shared/prng';\nimport { shuffleKeepingFixed } from '../shared/shuffle';\n\nconst isLocal = (el: Element, ...names: string[]): boolean =>\n names.includes(el.localName) || names.includes(el.localName?.toLowerCase?.());\n\nconst isItemRef = (el: Element): boolean => isLocal(el, 'qti-assessment-item-ref', 'assessmentitemref');\n\nconst isSection = (el: Element): boolean => isLocal(el, 'qti-assessment-section', 'assessmentsection');\n\nconst attrIsTrue = (el: Element, ...names: string[]): boolean =>\n names.some(n => {\n const v = (el.getAttribute(n) ?? '').trim().toLowerCase();\n return v === 'true' || v === '1';\n });\n\nconst attrIsFalse = (el: Element, ...names: string[]): boolean =>\n names.some(n => {\n const v = (el.getAttribute(n) ?? '').trim().toLowerCase();\n return v === 'false' || v === '0';\n });\n\nconst isOrdering = (el: Element): boolean => isLocal(el, 'qti-ordering', 'ordering');\n\nconst isSelection = (el: Element): boolean => isLocal(el, 'qti-selection', 'selection');\n\nconst shuffleOrderingElements = (section: Element): Element[] =>\n Array.from(section.children).filter(child => isOrdering(child) && attrIsTrue(child, 'shuffle'));\n\nconst rngFor = (seed: string | number, key: string) => createSeededRandom(`${seed}:${key}`);\n\n/** A movable unit in a section: one or more sibling nodes that move together. */\ntype Unit = { nodes: Element[]; fixed: boolean };\n\n/**\n * The item refs of a subsection, in document order, plus the element children\n * that consuming the wrapper would discard.\n *\n * Descendant subsections are collected transitively: `orderSection` returns\n * early for a section without <qti-ordering>, so a wrapper nested inside a\n * non-shuffling subsection is never consumed there and has to be gathered here.\n */\nfunction collectItemRefsDeep(section: Element): { itemRefs: Element[]; dropped: string[] } {\n const itemRefs: Element[] = [];\n const dropped: string[] = [];\n\n const walk = (el: Element): void => {\n for (const child of Array.from(el.children)) {\n if (isItemRef(child)) {\n itemRefs.push(child);\n } else if (isSection(child)) {\n walk(child);\n } else if (!isOrdering(child) && !isSelection(child)) {\n // Ordering/selection directives are transform config; anything else\n // (a rubric block, say) is authored content that the lift loses.\n dropped.push(child.localName);\n }\n }\n };\n walk(section);\n\n return { itemRefs, dropped };\n}\n\nfunction warnDroppedChildren(section: Element, dropped: string[]): void {\n if (dropped.length === 0) return;\n const identifier = section.getAttribute('identifier') ?? '(no identifier)';\n console.warn(\n `[qtiTransformTest] Subsection \"${identifier}\" is consumed by section ordering; ` +\n `discarding its ${[...new Set(dropped)].join(', ')}.`\n );\n}\n\n/**\n * Seed-deterministic QTI section shuffling.\n *\n * Reorders the children of every <qti-assessment-section> that carries a\n * <qti-ordering shuffle=\"true\">, following QTI 3.0 ordering rules:\n *\n * - Depth-first: a subsection orders its own children before the parent\n * reorders it.\n * - Item refs with fixed=\"true\" stay in their authored position; the other\n * units shuffle around them.\n * - A subsection is a grouping device, not a delivered section: its item refs\n * are lifted into the parent and the wrapper is consumed, just as the\n * <qti-ordering> directive itself is. Nothing nested survives into the DOM,\n * so the player only ever sees the authored top-level sections.\n * - By default (QTI 3.0 defaults keep-together to true) a subsection travels as\n * one unit: its items stay contiguous and keep their authored order, while\n * the parent's remaining items shuffle around the block. Add fixed=\"true\" to\n * pin the block itself to its authored slot.\n * - Only an explicit keep-together=\"false\" dissolves a subsection: its\n * (already internally ordered) item refs are poured into the parent pool and\n * interleaved with the parent's own units.\n *\n * The same `seed` always produces the same order, so a restarted session keeps\n * its sequence. Each section draws from its own PRNG stream (seed + section id)\n * so sibling sections are independent and stable.\n */\nfunction orderSection(section: Element, seed: string | number): void {\n // Depth-first: let every child section order itself first.\n for (const child of Array.from(section.children)) {\n if (isSection(child)) {\n orderSection(child, seed);\n }\n }\n\n const orderingEls = shuffleOrderingElements(section);\n if (orderingEls.length === 0) {\n return;\n }\n\n // Build the pool of movable units in document order. Config/structural\n // children (qti-ordering, qti-selection, rubric-block, …) are left in place.\n const units: Unit[] = [];\n const toDetach: Element[] = [];\n\n for (const child of Array.from(section.children)) {\n if (isItemRef(child)) {\n units.push({ nodes: [child], fixed: attrIsTrue(child, 'fixed') });\n toDetach.push(child);\n } else if (isSection(child)) {\n // Internal order is already settled: the depth-first pass above shuffled\n // this subsection if it carried its own <qti-ordering shuffle=\"true\">, and\n // left the authored order alone otherwise.\n const { itemRefs, dropped } = collectItemRefsDeep(child);\n warnDroppedChildren(child, dropped);\n\n if (attrIsFalse(child, 'keep-together', 'keeptogether')) {\n // Explicitly dissolved: the items join the parent pool individually and\n // interleave with the parent's own items.\n for (const itemRef of itemRefs) {\n units.push({ nodes: [itemRef], fixed: attrIsTrue(itemRef, 'fixed') });\n }\n } else if (itemRefs.length > 0) {\n // One multi-node unit, so the items stay contiguous and keep their order\n // wherever the block lands.\n units.push({ nodes: itemRefs, fixed: attrIsTrue(child, 'fixed') });\n }\n\n toDetach.push(child); // the grouping wrapper is consumed\n }\n }\n\n // Where the reordered units go back in: after the last node we took out, so\n // any trailing structural children (a rubric block, say) keep their position.\n // Captured before detaching, and never itself a detached node.\n const anchor = toDetach.length > 0 ? toDetach[toDetach.length - 1].nextSibling : null;\n\n const sectionKey = section.getAttribute('identifier') ?? '';\n // A no-op for 0 or 1 movable units, but the re-insertion below still has to\n // run so consumed wrappers are lifted rather than left in the DOM.\n const ordered = shuffleKeepingFixed(units, rngFor(seed, sectionKey));\n\n for (const el of toDetach) {\n el.remove();\n }\n for (const unit of ordered) {\n for (const node of unit.nodes) {\n section.insertBefore(node, anchor);\n }\n }\n\n // Ordering directives are consumed by this transform step.\n for (const orderingEl of orderingEls) {\n orderingEl.remove();\n }\n}\n\n/** Whether anything in `doc` asks to be shuffled at all. */\nexport function hasShuffleOrdering(doc: XMLDocument): boolean {\n return Array.from(doc.getElementsByTagName('*')).some(el => isOrdering(el) && attrIsTrue(el, 'shuffle'));\n}\n\n/**\n * Mutates `doc` in place: shuffles every section flagged with\n * <qti-ordering shuffle=\"true\">, deterministically from `seed`.\n */\nexport function shuffleSectionsOrdering(doc: XMLDocument, seed: string | number): void {\n const sections = Array.from(doc.getElementsByTagName('*')).filter(el => isSection(el));\n // Kick off recursion only for top-level sections; orderSection handles nesting\n // depth-first, so descendants are not double-processed.\n for (const section of sections) {\n // The snapshot above can contain wrappers that an ancestor has since\n // consumed. A detached element has no parentNode; a document element still\n // has one (the document), so this does not skip a section-rooted document.\n if (!section.parentNode) continue;\n\n const parent = section.parentElement;\n if (parent && isSection(parent)) continue;\n\n orderSection(section, seed);\n }\n}\n","/**\n * Returns an object with methods to load, parse and transform QTI tests.\n * @returns An object with methods to load, parse and transform QTI tests.\n * @example\n * const qtiTransformer = qtiTransformTest();\n * await qtiTransformer.load('https://example.com/test.xml');\n * const items = qtiTransformer.items();\n * const html = qtiTransformer.html();\n * const xml = qtiTransformer.xml();\n */\n\nimport { warnMissingSeed } from './shared/missing-seed-warning';\nimport { loadXML, parseXML, setLocation, toHTML } from './shared/xml';\nimport { itemsFromTest } from './test/items';\nimport { hasShuffleOrdering, shuffleSectionsOrdering } from './test/shuffle-sections';\n\nexport type transformTestApi = {\n load: (uri: string, signal?: AbortSignal) => Promise<transformTestApi>;\n parse: (xmlString: string) => transformTestApi;\n path: (location: string) => transformTestApi;\n fn: (fn: (xmlFragment: XMLDocument) => void) => transformTestApi;\n /**\n * Deterministically shuffle the children of every section that carries a\n * <qti-ordering shuffle=\"true\">, honoring fixed items and nested\n * keep-together / visible rules. The same seed reproduces the same order.\n */\n shuffleOrdering: (seed?: string | number | null) => transformTestApi;\n items: () => { identifier: string; href: string; category: string }[];\n html: () => string;\n xml: () => string;\n htmlDoc: (registry?: CustomElementRegistry) => DocumentFragment;\n xmlDoc: () => XMLDocument;\n};\n\nexport const qtiTransformTest = (): transformTestApi => {\n let xmlFragment: XMLDocument;\n let xmlUri = '';\n\n const api: transformTestApi = {\n async load(uri, signal) {\n return new Promise<transformTestApi>((resolve, _) => {\n loadXML(uri, signal).then(xml => {\n xmlFragment = xml;\n xmlUri = uri;\n\n api.path(uri.substring(0, uri.lastIndexOf('/')));\n return resolve(api);\n });\n });\n },\n parse(xmlString: string) {\n xmlFragment = parseXML(xmlString);\n xmlUri = '';\n return api;\n },\n path: (location: string): typeof api => {\n setLocation(xmlFragment, location);\n return api;\n },\n fn(fn: (xmlFragment: XMLDocument) => void) {\n fn(xmlFragment);\n return api;\n },\n shuffleOrdering(seed?: string | number | null) {\n // No section asks to be shuffled: leave the test alone, and stay quiet\n // about a missing seed that would never have been used.\n if (!hasShuffleOrdering(xmlFragment)) {\n return api;\n }\n\n const normalizedSeed = typeof seed === 'string' ? seed.trim() : seed;\n\n if (normalizedSeed === null || normalizedSeed === undefined || normalizedSeed === '') {\n const fallbackSeed = xmlUri || 'default-test-seed';\n warnMissingSeed('qtiTransformTest', fallbackSeed);\n shuffleSectionsOrdering(xmlFragment, fallbackSeed);\n return api;\n }\n\n shuffleSectionsOrdering(xmlFragment, normalizedSeed);\n return api;\n },\n items() {\n return itemsFromTest(xmlFragment);\n },\n html() {\n return new XMLSerializer().serializeToString(toHTML(xmlFragment));\n },\n xml(): string {\n return new XMLSerializer().serializeToString(xmlFragment);\n },\n htmlDoc(registry?: CustomElementRegistry) {\n return toHTML(xmlFragment, registry);\n },\n xmlDoc(): XMLDocument {\n return xmlFragment;\n }\n };\n return api;\n};\n"],"mappings":"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","names":["fallbackPath","path","shuffleInteractions"]}