@longsightgroup/qti3-core 0.9.3 → 0.9.5

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 (133) hide show
  1. package/README.md +88 -8
  2. package/dist/adaptive-turn-materializer.d.ts +2 -0
  3. package/dist/adaptive-turn-materializer.d.ts.map +1 -1
  4. package/dist/adaptive-turn-materializer.js +25 -19
  5. package/dist/adaptive-turn-materializer.js.map +1 -1
  6. package/dist/adaptive-turn.d.ts +8 -1
  7. package/dist/adaptive-turn.d.ts.map +1 -1
  8. package/dist/adaptive-turn.js +15 -5
  9. package/dist/adaptive-turn.js.map +1 -1
  10. package/dist/delivery-preparation.d.ts +20 -0
  11. package/dist/delivery-preparation.d.ts.map +1 -0
  12. package/dist/delivery-preparation.js +71 -0
  13. package/dist/delivery-preparation.js.map +1 -0
  14. package/dist/delivery-redaction.d.ts +5 -0
  15. package/dist/delivery-redaction.d.ts.map +1 -1
  16. package/dist/delivery-redaction.js +26 -5
  17. package/dist/delivery-redaction.js.map +1 -1
  18. package/dist/delivery-security.js +2 -2
  19. package/dist/delivery-security.js.map +1 -1
  20. package/dist/index.d.ts +6 -0
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +6 -0
  23. package/dist/index.js.map +1 -1
  24. package/dist/item-scoring-expectation.d.ts +4 -0
  25. package/dist/item-scoring-expectation.d.ts.map +1 -0
  26. package/dist/item-scoring-expectation.js +6 -0
  27. package/dist/item-scoring-expectation.js.map +1 -0
  28. package/dist/item-submission-materialization.d.ts +25 -0
  29. package/dist/item-submission-materialization.d.ts.map +1 -0
  30. package/dist/item-submission-materialization.js +68 -0
  31. package/dist/item-submission-materialization.js.map +1 -0
  32. package/dist/qti-package-assets.d.ts +8 -0
  33. package/dist/qti-package-assets.d.ts.map +1 -0
  34. package/dist/qti-package-assets.js +173 -0
  35. package/dist/qti-package-assets.js.map +1 -0
  36. package/dist/qti-package-items.d.ts +14 -0
  37. package/dist/qti-package-items.d.ts.map +1 -0
  38. package/dist/qti-package-items.js +138 -0
  39. package/dist/qti-package-items.js.map +1 -0
  40. package/dist/qti-package-manifest.d.ts +13 -0
  41. package/dist/qti-package-manifest.d.ts.map +1 -0
  42. package/dist/qti-package-manifest.js +109 -0
  43. package/dist/qti-package-manifest.js.map +1 -0
  44. package/dist/qti-package-metadata.d.ts +8 -0
  45. package/dist/qti-package-metadata.d.ts.map +1 -0
  46. package/dist/qti-package-metadata.js +115 -0
  47. package/dist/qti-package-metadata.js.map +1 -0
  48. package/dist/qti-package-paths.d.ts +6 -0
  49. package/dist/qti-package-paths.d.ts.map +1 -0
  50. package/dist/qti-package-paths.js +32 -0
  51. package/dist/qti-package-paths.js.map +1 -0
  52. package/dist/qti-package-types.d.ts +98 -0
  53. package/dist/qti-package-types.d.ts.map +1 -0
  54. package/dist/qti-package-types.js +2 -0
  55. package/dist/qti-package-types.js.map +1 -0
  56. package/dist/qti-package-xml.d.ts +21 -0
  57. package/dist/qti-package-xml.d.ts.map +1 -0
  58. package/dist/qti-package-xml.js +68 -0
  59. package/dist/qti-package-xml.js.map +1 -0
  60. package/dist/qti-package-zip.d.ts +24 -0
  61. package/dist/qti-package-zip.d.ts.map +1 -0
  62. package/dist/qti-package-zip.js +185 -0
  63. package/dist/qti-package-zip.js.map +1 -0
  64. package/dist/qti-package.d.ts +7 -0
  65. package/dist/qti-package.d.ts.map +1 -0
  66. package/dist/qti-package.js +76 -0
  67. package/dist/qti-package.js.map +1 -0
  68. package/dist/response-input.d.ts +9 -0
  69. package/dist/response-input.d.ts.map +1 -0
  70. package/dist/response-input.js +9 -0
  71. package/dist/response-input.js.map +1 -0
  72. package/dist/response-validation-policy.d.ts +31 -0
  73. package/dist/response-validation-policy.d.ts.map +1 -0
  74. package/dist/response-validation-policy.js +166 -0
  75. package/dist/response-validation-policy.js.map +1 -0
  76. package/dist/response-validation.d.ts +23 -0
  77. package/dist/response-validation.d.ts.map +1 -0
  78. package/dist/response-validation.js +170 -0
  79. package/dist/response-validation.js.map +1 -0
  80. package/dist/scoring-disposition-policy.d.ts +8 -0
  81. package/dist/scoring-disposition-policy.d.ts.map +1 -0
  82. package/dist/scoring-disposition-policy.js +24 -0
  83. package/dist/scoring-disposition-policy.js.map +1 -0
  84. package/dist/template-presentation-materializer.d.ts +14 -0
  85. package/dist/template-presentation-materializer.d.ts.map +1 -0
  86. package/dist/template-presentation-materializer.js +143 -0
  87. package/dist/template-presentation-materializer.js.map +1 -0
  88. package/dist/trusted-item-session.d.ts +25 -8
  89. package/dist/trusted-item-session.d.ts.map +1 -1
  90. package/dist/trusted-item-session.js +51 -46
  91. package/dist/trusted-item-session.js.map +1 -1
  92. package/dist/trusted-session-materialization.d.ts +33 -0
  93. package/dist/trusted-session-materialization.d.ts.map +1 -0
  94. package/dist/trusted-session-materialization.js +26 -0
  95. package/dist/trusted-session-materialization.js.map +1 -0
  96. package/dist/validation-interactions.js +1 -0
  97. package/dist/validation-interactions.js.map +1 -1
  98. package/dist/validation-primitives.d.ts +1 -0
  99. package/dist/validation-primitives.d.ts.map +1 -1
  100. package/dist/validation-primitives.js +5 -0
  101. package/dist/validation-primitives.js.map +1 -1
  102. package/dist/variable-snapshot.d.ts +9 -0
  103. package/dist/variable-snapshot.d.ts.map +1 -0
  104. package/dist/variable-snapshot.js +9 -0
  105. package/dist/variable-snapshot.js.map +1 -0
  106. package/package.json +1 -1
  107. package/src/adaptive-turn-materializer.ts +29 -16
  108. package/src/adaptive-turn.ts +29 -6
  109. package/src/delivery-preparation.ts +121 -0
  110. package/src/delivery-redaction.ts +36 -5
  111. package/src/delivery-security.ts +2 -2
  112. package/src/index.ts +65 -0
  113. package/src/item-scoring-expectation.ts +9 -0
  114. package/src/item-submission-materialization.ts +120 -0
  115. package/src/qti-package-assets.ts +256 -0
  116. package/src/qti-package-items.ts +240 -0
  117. package/src/qti-package-manifest.ts +210 -0
  118. package/src/qti-package-metadata.ts +143 -0
  119. package/src/qti-package-paths.ts +56 -0
  120. package/src/qti-package-types.ts +117 -0
  121. package/src/qti-package-xml.ts +97 -0
  122. package/src/qti-package-zip.ts +325 -0
  123. package/src/qti-package.ts +176 -0
  124. package/src/response-input.ts +19 -0
  125. package/src/response-validation-policy.ts +226 -0
  126. package/src/response-validation.ts +298 -0
  127. package/src/scoring-disposition-policy.ts +37 -0
  128. package/src/template-presentation-materializer.ts +219 -0
  129. package/src/trusted-item-session.ts +80 -74
  130. package/src/trusted-session-materialization.ts +67 -0
  131. package/src/validation-interactions.ts +1 -0
  132. package/src/validation-primitives.ts +5 -0
  133. package/src/variable-snapshot.ts +20 -0
package/README.md CHANGED
@@ -58,18 +58,18 @@ High-stakes delivery systems can redact answer-bearing item XML before sending i
58
58
  a browser:
59
59
 
60
60
  ```ts
61
- import { buildQtiDeliverySafeXml } from "@longsightgroup/qti3-core";
61
+ import { prepareQtiDeliveryXml } from "@longsightgroup/qti3-core";
62
62
 
63
- const delivery = buildQtiDeliverySafeXml(authoritativeItemXml);
63
+ const delivery = prepareQtiDeliveryXml(authoritativeItemXml, { mode: "static" });
64
64
 
65
65
  if (!delivery.ok) {
66
66
  throw new Error(delivery.diagnostics.map((item) => item.message).join("; "));
67
67
  }
68
68
 
69
- sendToCandidate(delivery.xml);
69
+ sendToCandidate(delivery.candidateSafeXml);
70
70
  ```
71
71
 
72
- Use `buildQtiDeliverySafeXml().ok` for deliverability. The
72
+ Use `prepareQtiDeliveryXml().ok` for deliverability. The
73
73
  `analyzeQtiDeliverySecurity().deliverySafe` flag describes the exact XML being analyzed,
74
74
  so it is normally `false` for an authoritative scorable item before redaction and `true`
75
75
  only for the redacted output.
@@ -82,10 +82,34 @@ template processing, set-correct-response, and adaptive response processing.
82
82
  String-range redaction uses the same dependency-free XML parser as `parseQtiXml`, with
83
83
  source ranges recorded during parsing. XML parse failures are reported as `xml.parse`
84
84
  error diagnostics; hosts must treat those diagnostics, `parseQtiXml().ok === false`,
85
- and `buildQtiDeliverySafeXml().ok === false` as non-deliverable. The redacted output is
85
+ and `prepareQtiDeliveryXml().ok === false` as non-deliverable. The redacted output is
86
86
  re-analyzed before `ok` is returned, but hosts should still treat redacted XML as
87
87
  untrusted presentation input.
88
88
 
89
+ `prepareQtiDeliveryXml()` is the high-level host API. Use `mode: "static"` for
90
+ non-adaptive delivery where all response processing and feedback are removed. Use
91
+ `mode: "server-materialized-adaptive"` only after the server has authoritative outcomes
92
+ for the current adaptive view; pass those outcomes so visible feedback can be retained.
93
+ Pass `templateValues` when the item uses template-derived presentation (`qti-printed-variable`,
94
+ `qti-template-block`, or `qti-template-inline`). Adaptive turn processing supplies these
95
+ from session state automatically; hosts calling `prepareQtiDeliveryXml()` directly must
96
+ provide the same authoritative template snapshot. Generated answer keys, template and response
97
+ processing, mappings, lookup tables, declaration defaults, and hidden feedback are
98
+ stripped from candidate XML. Static delivery fails closed for adaptive response or
99
+ template processing where server materialization is required.
100
+
101
+ Use `analyzeQtiDeliverySecurity()` when a host only needs diagnostics about a specific
102
+ XML string, and `buildQtiDeliverySafeXml()` when a host explicitly wants the lower-level
103
+ static redaction primitive. Most delivery services should call `prepareQtiDeliveryXml()`
104
+ instead.
105
+
106
+ `prepareQtiDeliveryXml()` returns normalized `delivery.preparation.*` diagnostic codes
107
+ for delivery preparation failures across both modes. Hosts can key on
108
+ `result.diagnostics[].code` for logging, i18n, HTTP mapping, or telemetry when using the
109
+ facade. `result.analysis.findings[].kind` remains available as the structured semantic
110
+ contract for hosts that prefer mode-independent finding data. Lower-level APIs keep
111
+ their own diagnostic namespaces for callers that intentionally use those primitives.
112
+
89
113
  The parser does not resolve external entities, process DTD entity declarations, or access
90
114
  the network or filesystem. Unknown named entities are preserved verbatim, and numeric
91
115
  character references expand to at most one valid XML character.
@@ -123,6 +147,61 @@ then runs response processing. It does not run candidate response-validation pol
123
147
  as required interactions, cardinality limits, or min/max response counts; delivery hosts
124
148
  should enforce that policy before accepting a submission or finalizing an attempt.
125
149
 
150
+ For the same response-validation policy the browser player uses, call
151
+ `validateQtiResponseVariables()` against a parsed assessment item before scoring or
152
+ persisting a submission:
153
+
154
+ ```ts
155
+ import { parseQtiXml, validateQtiResponseVariables } from "@longsightgroup/qti3-core";
156
+
157
+ const parsed = parseQtiXml(authoritativeItemXml);
158
+ if (!parsed.ok) throw new Error("invalid item");
159
+
160
+ const validation = validateQtiResponseVariables({
161
+ item: parsed.document.item,
162
+ responses: { RESPONSE: "A" },
163
+ allowedUndeclaredResponseIdentifiers: ["duration"],
164
+ });
165
+
166
+ if (!validation.ok) {
167
+ throw new Error(validation.diagnostics.map((item) => item.message).join("; "));
168
+ }
169
+ ```
170
+
171
+ `validateQtiResponseVariables()` uses the same runtime diagnostic codes as the player
172
+ (`response.required`, `response.maximum`, `response.matchMax`, and related codes). It
173
+ checks cardinality shape, required responses, min/max choice and association bounds, and
174
+ per-choice `match-max` limits. It does not render custom validation messages in the DOM
175
+ or validate media play counts beyond what the item model exposes.
176
+
177
+ Use `materializeQtiItemSubmission()` when a server needs the reusable QTI mechanics behind
178
+ finalization: response validation, trusted response application, response processing,
179
+ adaptive turn materialization, normalized response/outcome snapshots, and a generic scoring
180
+ disposition:
181
+
182
+ ```ts
183
+ import { materializeQtiItemSubmission } from "@longsightgroup/qti3-core";
184
+
185
+ const materialized = materializeQtiItemSubmission({
186
+ itemXml: authoritativeItemXml,
187
+ existingState: priorAttemptState,
188
+ trustedResponses: { RESPONSE: "A" },
189
+ });
190
+
191
+ if (!materialized.ok) {
192
+ throw new Error(materialized.diagnostics.map((item) => item.message).join("; "));
193
+ }
194
+
195
+ console.log(materialized.scoringDisposition);
196
+ console.log(materialized.responseVariables);
197
+ console.log(materialized.outcomeVariables);
198
+ ```
199
+
200
+ `scoringDisposition` uses a default generic taxonomy from `qti3-core`: `scored`,
201
+ `manual-scoring-required`, `unscored-reference`, or `invalid`. Host applications can map
202
+ these dispositions to product-specific finalization statuses, grading queues, result
203
+ aggregation, and external exports.
204
+
126
205
  Delivery redaction, server-style scoring, and secure adaptive turn handling are library
127
206
  APIs. Dedicated CLI commands for those operations are planned separately.
128
207
 
@@ -161,9 +240,10 @@ player.restore(turn.state);
161
240
  Refresh turns with no new submission still return updated materialized XML derived from restored outcomes, so a resume flow should load both values again even when the candidate does not submit a new response.
162
241
 
163
242
  The static delivery redactor still fails closed for adaptive response processing. Use
164
- `processQtiAdaptiveItemTurn()` when a host needs a server-materialized candidate view
165
- and updated authoritative outcomes for the next adaptive turn. The low-level adaptive-turn
166
- redactor is internal to the core package; hosts should not call it directly.
243
+ `processQtiAdaptiveItemTurn()` when a host needs both a server-materialized candidate
244
+ view and updated authoritative outcomes for the next adaptive turn. Use
245
+ `prepareQtiDeliveryXml(..., { mode: "server-materialized-adaptive", outcomes })` only
246
+ when the host already owns the authoritative outcomes and needs to prepare candidate XML.
167
247
 
168
248
  ## Scope
169
249
 
@@ -3,6 +3,8 @@ import type { QtiDiagnostic, QtiValue } from "./types.js";
3
3
  export interface QtiAdaptiveCandidateMaterializationInput {
4
4
  itemXml: string;
5
5
  outcomes: Record<string, QtiValue>;
6
+ templateValues?: Record<string, QtiValue>;
7
+ responses?: Record<string, QtiValue>;
6
8
  }
7
9
  export interface QtiAdaptiveCandidateMaterializationResult {
8
10
  ok: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"adaptive-turn-materializer.d.ts","sourceRoot":"","sources":["../src/adaptive-turn-materializer.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,2BAA2B,EAEjC,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAW1D,MAAM,WAAW,wCAAwC;IACvD,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,yCAAyC;IACxD,EAAE,EAAE,OAAO,CAAC;IACZ,WAAW,EAAE,aAAa,EAAE,CAAC;IAC7B,QAAQ,EAAE,2BAA2B,CAAC;IACtC,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1B;AAED,wBAAgB,gCAAgC,CAC9C,KAAK,EAAE,wCAAwC,GAC9C,yCAAyC,CAE3C"}
1
+ {"version":3,"file":"adaptive-turn-materializer.d.ts","sourceRoot":"","sources":["../src/adaptive-turn-materializer.ts"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,2BAA2B,EAEjC,MAAM,yBAAyB,CAAC;AAEjC,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAQ1D,MAAM,WAAW,wCAAwC;IACvD,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACnC,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,yCAAyC;IACxD,EAAE,EAAE,OAAO,CAAC;IACZ,WAAW,EAAE,aAAa,EAAE,CAAC;IAC7B,QAAQ,EAAE,2BAA2B,CAAC;IACtC,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1B;AAED,wBAAgB,gCAAgC,CAC9C,KAAK,EAAE,wCAAwC,GAC9C,yCAAyC,CAiB3C"}
@@ -1,12 +1,25 @@
1
- import { FORBIDDEN_DELIVERY_SECRET_ELEMENT_NAMES, isDeclarationDefaultValue, redactDeliveryXml, } from "./delivery-redaction.js";
1
+ import { FORBIDDEN_DELIVERY_SECRET_ELEMENT_NAMES, analyzeDeliveryXml, isDeclarationDefaultValue, parseDeliveryXml, redactDeliveryXml, } from "./delivery-redaction.js";
2
+ import { materializeTemplatePresentation } from "./template-presentation-materializer.js";
2
3
  import { qtiValueToString } from "./value-format.js";
3
- const UNSUPPORTED_MATERIALIZATION_ELEMENT_NAMES = new Set([
4
- "template-processing",
5
- "set-correct-response",
6
- ]);
4
+ const TEMPLATE_PROCESSING_ELEMENT_NAMES = new Set(["template-processing", "set-correct-response"]);
7
5
  const FEEDBACK_ELEMENT_NAMES = new Set(["feedback-inline", "feedback-block", "modal-feedback"]);
8
6
  export function materializeAdaptiveCandidateView(input) {
9
- return redactDeliveryXml(input.itemXml, adaptiveMaterializationPolicy(input.outcomes));
7
+ const policy = adaptiveMaterializationPolicy(input.outcomes);
8
+ const templateMaterialization = materializeTemplatePresentation(input.itemXml, {
9
+ outcomes: input.outcomes,
10
+ templateValues: input.templateValues ?? {},
11
+ responses: input.responses,
12
+ });
13
+ if (!templateMaterialization.ok) {
14
+ const analysis = analyzeDeliveryXml(parseDeliveryXml(input.itemXml), policy);
15
+ const diagnostics = [...templateMaterialization.diagnostics, ...analysis.diagnostics];
16
+ return {
17
+ ok: false,
18
+ diagnostics,
19
+ analysis,
20
+ };
21
+ }
22
+ return redactDeliveryXml(templateMaterialization.xml, policy);
10
23
  }
11
24
  function shouldPreserveFeedback(node, outcomes) {
12
25
  if (node.attributes["show-hide"] === "hide")
@@ -28,27 +41,20 @@ function adaptiveMaterializationPolicy(outcomes) {
28
41
  isForbiddenElement(node, normalizedName) {
29
42
  if (isFeedbackElement(normalizedName))
30
43
  return !shouldPreserveFeedback(node, outcomes);
31
- return (FORBIDDEN_DELIVERY_SECRET_ELEMENT_NAMES.has(normalizedName) ||
44
+ return (TEMPLATE_PROCESSING_ELEMENT_NAMES.has(normalizedName) ||
45
+ FORBIDDEN_DELIVERY_SECRET_ELEMENT_NAMES.has(normalizedName) ||
32
46
  isDeclarationDefaultValue(node, normalizedName));
33
47
  },
34
- unsupportedFinding(node, normalizedName) {
35
- if (!UNSUPPORTED_MATERIALIZATION_ELEMENT_NAMES.has(normalizedName))
36
- return null;
37
- return {
38
- kind: "unsupported-secure-delivery-element",
39
- qtiName: node.name,
40
- localName: node.localName,
41
- message: `${node.name} is not supported by adaptive candidate materialization v1.`,
42
- source: node.source,
43
- };
48
+ unsupportedFinding() {
49
+ return null;
44
50
  },
45
- diagnosticCodeForFinding,
51
+ diagnosticCodeForFinding: adaptiveMaterializationDiagnosticCodeForFinding,
46
52
  forbiddenElementMessage(node) {
47
53
  return `${node.name} exposes answer keys, scoring, mapping, feedback, or solution information during adaptive delivery.`;
48
54
  },
49
55
  };
50
56
  }
51
- function diagnosticCodeForFinding(kind) {
57
+ function adaptiveMaterializationDiagnosticCodeForFinding(kind) {
52
58
  return kind === "unsupported-secure-delivery-element"
53
59
  ? "adaptiveTurn.materialization.unsupported"
54
60
  : "adaptiveTurn.materialization.forbiddenElement";
@@ -1 +1 @@
1
- {"version":3,"file":"adaptive-turn-materializer.js","sourceRoot":"","sources":["../src/adaptive-turn-materializer.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uCAAuC,EACvC,yBAAyB,EACzB,iBAAiB,GAIlB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAGrD,MAAM,yCAAyC,GAAG,IAAI,GAAG,CAAC;IACxD,qBAAqB;IACrB,sBAAsB;CACvB,CAAC,CAAC;AAEH,MAAM,sBAAsB,GAAG,IAAI,GAAG,CAAC,CAAC,iBAAiB,EAAE,gBAAgB,EAAE,gBAAgB,CAAC,CAAC,CAAC;AAchG,MAAM,UAAU,gCAAgC,CAC9C,KAA+C;IAE/C,OAAO,iBAAiB,CAAC,KAAK,CAAC,OAAO,EAAE,6BAA6B,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;AACzF,CAAC;AAED,SAAS,sBAAsB,CAAC,IAAa,EAAE,QAAkC;IAC/E,IAAI,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,MAAM;QAAE,OAAO,KAAK,CAAC;IAC1D,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;IAC9C,MAAM,iBAAiB,GAAG,IAAI,CAAC,UAAU,CAAC,oBAAoB,CAAC,CAAC;IAChE,IAAI,CAAC,UAAU,IAAI,CAAC,iBAAiB;QAAE,OAAO,KAAK,CAAC;IAEpD,MAAM,OAAO,GAAG,QAAQ,CAAC,iBAAiB,CAAC,IAAI,IAAI,CAAC;IACpD,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,OAAO,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IAChE,OAAO,gBAAgB,CAAC,OAAO,CAAC,KAAK,UAAU,CAAC;AAClD,CAAC;AAED,SAAS,iBAAiB,CAAC,cAAsB;IAC/C,OAAO,sBAAsB,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;AACpD,CAAC;AAED,SAAS,6BAA6B,CACpC,QAAkC;IAElC,OAAO;QACL,kBAAkB,CAAC,IAAI,EAAE,cAAc;YACrC,IAAI,iBAAiB,CAAC,cAAc,CAAC;gBAAE,OAAO,CAAC,sBAAsB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;YACtF,OAAO,CACL,uCAAuC,CAAC,GAAG,CAAC,cAAc,CAAC;gBAC3D,yBAAyB,CAAC,IAAI,EAAE,cAAc,CAAC,CAChD,CAAC;QACJ,CAAC;QACD,kBAAkB,CAAC,IAAI,EAAE,cAAc;YACrC,IAAI,CAAC,yCAAyC,CAAC,GAAG,CAAC,cAAc,CAAC;gBAAE,OAAO,IAAI,CAAC;YAChF,OAAO;gBACL,IAAI,EAAE,qCAAqC;gBAC3C,OAAO,EAAE,IAAI,CAAC,IAAI;gBAClB,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,OAAO,EAAE,GAAG,IAAI,CAAC,IAAI,6DAA6D;gBAClF,MAAM,EAAE,IAAI,CAAC,MAAM;aACpB,CAAC;QACJ,CAAC;QACD,wBAAwB;QACxB,uBAAuB,CAAC,IAAI;YAC1B,OAAO,GAAG,IAAI,CAAC,IAAI,qGAAqG,CAAC;QAC3H,CAAC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,wBAAwB,CAAC,IAAoC;IACpE,OAAO,IAAI,KAAK,qCAAqC;QACnD,CAAC,CAAC,0CAA0C;QAC5C,CAAC,CAAC,+CAA+C,CAAC;AACtD,CAAC"}
1
+ {"version":3,"file":"adaptive-turn-materializer.js","sourceRoot":"","sources":["../src/adaptive-turn-materializer.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import type { QtiAttemptStateV1, QtiDiagnostic, QtiValue } from "./types.js";
2
- import { type QtiTrustedItemParseOptions, type QtiTrustedResponseApplication, type QtiTrustedResponseInput } from "./trusted-item-session.js";
2
+ import { type QtiTrustedInputDiagnosticPrefix, type QtiTrustedItemDocument, type QtiTrustedItemParseOptions, type QtiTrustedResponseInput, type QtiTrustedResponseApplication, type QtiTrustedSubmissionValidation } from "./trusted-item-session.js";
3
3
  export type QtiAdaptiveTurnResponseInput = QtiTrustedResponseInput;
4
4
  export interface QtiAdaptiveTurnInput extends QtiTrustedItemParseOptions, QtiTrustedResponseApplication {
5
5
  itemXml: string;
@@ -9,6 +9,12 @@ export interface QtiAdaptiveTurnInput extends QtiTrustedItemParseOptions, QtiTru
9
9
  */
10
10
  priorState?: unknown;
11
11
  }
12
+ export interface TrustedAdaptiveItemTurnInput extends QtiAdaptiveTurnInput {
13
+ parsedItem?: QtiTrustedItemDocument | undefined;
14
+ diagnosticPrefix: QtiTrustedInputDiagnosticPrefix;
15
+ submissionValidation?: QtiTrustedSubmissionValidation | undefined;
16
+ allowIncompleteResponses?: boolean | undefined;
17
+ }
12
18
  export interface QtiAdaptiveTurnResult {
13
19
  ok: boolean;
14
20
  diagnostics: QtiDiagnostic[];
@@ -20,4 +26,5 @@ export interface QtiAdaptiveTurnResult {
20
26
  candidateSafeXml?: string | undefined;
21
27
  }
22
28
  export declare function processQtiAdaptiveItemTurn(input: QtiAdaptiveTurnInput): QtiAdaptiveTurnResult;
29
+ export declare function runTrustedAdaptiveItemTurn(input: TrustedAdaptiveItemTurnInput): QtiAdaptiveTurnResult;
23
30
  //# sourceMappingURL=adaptive-turn.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"adaptive-turn.d.ts","sourceRoot":"","sources":["../src/adaptive-turn.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC7E,OAAO,EAGL,KAAK,0BAA0B,EAC/B,KAAK,6BAA6B,EAClC,KAAK,uBAAuB,EAC7B,MAAM,2BAA2B,CAAC;AAEnC,MAAM,MAAM,4BAA4B,GAAG,uBAAuB,CAAC;AAEnE,MAAM,WAAW,oBACf,SAAQ,0BAA0B,EAAE,6BAA6B;IACjE,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,OAAO,CAAC;IACZ,WAAW,EAAE,aAAa,EAAE,CAAC;IAC7B,KAAK,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAChC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACpC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACnC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,gBAAgB,EAAE,QAAQ,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACvC;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,oBAAoB,GAAG,qBAAqB,CA0D7F"}
1
+ {"version":3,"file":"adaptive-turn.d.ts","sourceRoot":"","sources":["../src/adaptive-turn.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC7E,OAAO,EAGL,KAAK,+BAA+B,EACpC,KAAK,sBAAsB,EAC3B,KAAK,0BAA0B,EAC/B,KAAK,uBAAuB,EAC5B,KAAK,6BAA6B,EAClC,KAAK,8BAA8B,EACpC,MAAM,2BAA2B,CAAC;AAEnC,MAAM,MAAM,4BAA4B,GAAG,uBAAuB,CAAC;AAEnE,MAAM,WAAW,oBACf,SAAQ,0BAA0B,EAAE,6BAA6B;IACjE,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,4BAA6B,SAAQ,oBAAoB;IACxE,UAAU,CAAC,EAAE,sBAAsB,GAAG,SAAS,CAAC;IAChD,gBAAgB,EAAE,+BAA+B,CAAC;IAClD,oBAAoB,CAAC,EAAE,8BAA8B,GAAG,SAAS,CAAC;IAClE,wBAAwB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAChD;AAED,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,OAAO,CAAC;IACZ,WAAW,EAAE,aAAa,EAAE,CAAC;IAC7B,KAAK,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAChC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACpC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACnC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,gBAAgB,EAAE,QAAQ,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACvC;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,oBAAoB,GAAG,qBAAqB,CAE7F;AAED,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,4BAA4B,GAClC,qBAAqB,CAiEvB"}
@@ -1,13 +1,18 @@
1
1
  import { materializeAdaptiveCandidateView } from "./adaptive-turn-materializer.js";
2
2
  import { readPriorAttemptState, runTrustedItemSession, } from "./trusted-item-session.js";
3
3
  export function processQtiAdaptiveItemTurn(input) {
4
- const priorStateResult = readPriorAttemptState(input.priorState, "adaptiveTurn");
4
+ return runTrustedAdaptiveItemTurn({ ...input, diagnosticPrefix: "adaptiveTurn" });
5
+ }
6
+ export function runTrustedAdaptiveItemTurn(input) {
7
+ const diagnosticPrefix = input.diagnosticPrefix;
8
+ const priorStateResult = readPriorAttemptState(input.priorState, diagnosticPrefix);
5
9
  if (priorStateResult.diagnostics.some((diagnostic) => diagnostic.severity === "error")) {
6
10
  return failed(priorStateResult.diagnostics);
7
11
  }
8
12
  const sessionResult = runTrustedItemSession({
9
13
  itemXml: input.itemXml,
10
- diagnosticPrefix: "adaptiveTurn",
14
+ parsedItem: input.parsedItem,
15
+ diagnosticPrefix,
11
16
  allowedUndeclaredResponseIdentifiers: input.allowedUndeclaredResponseIdentifiers,
12
17
  priorState: priorStateResult.state,
13
18
  submission: {
@@ -16,6 +21,8 @@ export function processQtiAdaptiveItemTurn(input) {
16
21
  },
17
22
  scoring: "onSubmission",
18
23
  requireNumericScore: true,
24
+ submissionValidation: input.submissionValidation,
25
+ allowIncompleteResponses: input.allowIncompleteResponses,
19
26
  });
20
27
  if (!sessionResult.ok) {
21
28
  return failed(sessionResult.diagnostics, sessionResult.state, sessionResult.outcomes, sessionResult.score);
@@ -23,13 +30,16 @@ export function processQtiAdaptiveItemTurn(input) {
23
30
  const delivery = materializeAdaptiveCandidateView({
24
31
  itemXml: input.itemXml,
25
32
  outcomes: sessionResult.outcomes,
33
+ responses: sessionResult.responses,
34
+ templateValues: sessionResult.state.templateValues ?? {},
26
35
  });
27
36
  const deliveryDiagnostics = [...sessionResult.diagnostics, ...delivery.diagnostics];
28
- if (!delivery.ok || !delivery.xml) {
37
+ const candidateSafeXml = delivery.xml;
38
+ if (!delivery.ok || !candidateSafeXml) {
29
39
  return failed([
30
40
  ...deliveryDiagnostics,
31
41
  {
32
- code: "adaptiveTurn.delivery.materialization",
42
+ code: `${diagnosticPrefix}.delivery.materialization`,
33
43
  severity: "error",
34
44
  message: "Adaptive turn did not produce candidate-safe item XML.",
35
45
  },
@@ -43,7 +53,7 @@ export function processQtiAdaptiveItemTurn(input) {
43
53
  outcomes: sessionResult.outcomes,
44
54
  score: sessionResult.score,
45
55
  completionStatus: sessionResult.outcomes.completionStatus ?? null,
46
- candidateSafeXml: delivery.xml,
56
+ candidateSafeXml,
47
57
  };
48
58
  }
49
59
  function failed(diagnostics, state = null, outcomes = {}, score = null) {
@@ -1 +1 @@
1
- {"version":3,"file":"adaptive-turn.js","sourceRoot":"","sources":["../src/adaptive-turn.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gCAAgC,EAAE,MAAM,iCAAiC,CAAC;AAEnF,OAAO,EACL,qBAAqB,EACrB,qBAAqB,GAItB,MAAM,2BAA2B,CAAC;AAyBnC,MAAM,UAAU,0BAA0B,CAAC,KAA2B;IACpE,MAAM,gBAAgB,GAAG,qBAAqB,CAAC,KAAK,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;IACjF,IAAI,gBAAgB,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,KAAK,OAAO,CAAC,EAAE,CAAC;QACvF,OAAO,MAAM,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC;IAC9C,CAAC;IAED,MAAM,aAAa,GAAG,qBAAqB,CAAC;QAC1C,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,gBAAgB,EAAE,cAAc;QAChC,oCAAoC,EAAE,KAAK,CAAC,oCAAoC;QAChF,UAAU,EAAE,gBAAgB,CAAC,KAAK;QAClC,UAAU,EAAE;YACV,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;YACxC,wBAAwB,EAAE,KAAK,CAAC,wBAAwB;SACzD;QACD,OAAO,EAAE,cAAc;QACvB,mBAAmB,EAAE,IAAI;KAC1B,CAAC,CAAC;IACH,IAAI,CAAC,aAAa,CAAC,EAAE,EAAE,CAAC;QACtB,OAAO,MAAM,CACX,aAAa,CAAC,WAAW,EACzB,aAAa,CAAC,KAAK,EACnB,aAAa,CAAC,QAAQ,EACtB,aAAa,CAAC,KAAK,CACpB,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,gCAAgC,CAAC;QAChD,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,QAAQ,EAAE,aAAa,CAAC,QAAQ;KACjC,CAAC,CAAC;IACH,MAAM,mBAAmB,GAAG,CAAC,GAAG,aAAa,CAAC,WAAW,EAAE,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAC;IACpF,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;QAClC,OAAO,MAAM,CACX;YACE,GAAG,mBAAmB;YACtB;gBACE,IAAI,EAAE,uCAAuC;gBAC7C,QAAQ,EAAE,OAAO;gBACjB,OAAO,EAAE,wDAAwD;aAClE;SACF,EACD,aAAa,CAAC,KAAK,EACnB,aAAa,CAAC,QAAQ,EACtB,aAAa,CAAC,KAAK,CACpB,CAAC;IACJ,CAAC;IAED,OAAO;QACL,EAAE,EAAE,IAAI;QACR,WAAW,EAAE,mBAAmB;QAChC,KAAK,EAAE,aAAa,CAAC,KAAK;QAC1B,SAAS,EAAE,aAAa,CAAC,SAAS;QAClC,QAAQ,EAAE,aAAa,CAAC,QAAQ;QAChC,KAAK,EAAE,aAAa,CAAC,KAAK;QAC1B,gBAAgB,EAAE,aAAa,CAAC,QAAQ,CAAC,gBAAgB,IAAI,IAAI;QACjE,gBAAgB,EAAE,QAAQ,CAAC,GAAG;KAC/B,CAAC;AACJ,CAAC;AAED,SAAS,MAAM,CACb,WAA4B,EAC5B,QAAkC,IAAI,EACtC,WAAqC,EAAE,EACvC,QAAuB,IAAI;IAE3B,OAAO;QACL,EAAE,EAAE,KAAK;QACT,WAAW;QACX,KAAK;QACL,SAAS,EAAE,KAAK,EAAE,SAAS,IAAI,EAAE;QACjC,QAAQ;QACR,KAAK;QACL,gBAAgB,EAAE,QAAQ,CAAC,gBAAgB,IAAI,IAAI;KACpD,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"adaptive-turn.js","sourceRoot":"","sources":["../src/adaptive-turn.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { QtiDeliverySecurityAnalysis } from "./delivery-redaction.js";
2
+ import type { QtiValue } from "./types.js";
3
+ export type QtiDeliveryPreparationMode = "static" | "server-materialized-adaptive";
4
+ export type QtiDeliveryPreparationOptions = {
5
+ mode: "static";
6
+ } | {
7
+ mode: "server-materialized-adaptive";
8
+ outcomes: Record<string, QtiValue>;
9
+ templateValues?: Record<string, QtiValue>;
10
+ };
11
+ export interface QtiDeliveryPreparationResult {
12
+ ok: boolean;
13
+ mode: QtiDeliveryPreparationMode;
14
+ diagnostics: QtiDeliverySecurityAnalysis["diagnostics"];
15
+ analysis: QtiDeliverySecurityAnalysis;
16
+ candidateSafeXml?: string | undefined;
17
+ }
18
+ /** Prepare candidate-safe XML for a supported QTI delivery mode. */
19
+ export declare function prepareQtiDeliveryXml(xml: string, options: QtiDeliveryPreparationOptions): QtiDeliveryPreparationResult;
20
+ //# sourceMappingURL=delivery-preparation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delivery-preparation.d.ts","sourceRoot":"","sources":["../src/delivery-preparation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,2BAA2B,EAG5B,MAAM,yBAAyB,CAAC;AAEjC,OAAO,KAAK,EAAiB,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE1D,MAAM,MAAM,0BAA0B,GAAG,QAAQ,GAAG,8BAA8B,CAAC;AAEnF,MAAM,MAAM,6BAA6B,GACrC;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAClB;IACE,IAAI,EAAE,8BAA8B,CAAC;IACrC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACnC,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;CAC3C,CAAC;AAEN,MAAM,WAAW,4BAA4B;IAC3C,EAAE,EAAE,OAAO,CAAC;IACZ,IAAI,EAAE,0BAA0B,CAAC;IACjC,WAAW,EAAE,2BAA2B,CAAC,aAAa,CAAC,CAAC;IACxD,QAAQ,EAAE,2BAA2B,CAAC;IACtC,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACvC;AAED,oEAAoE;AACpE,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,6BAA6B,GACrC,4BAA4B,CAmB9B"}
@@ -0,0 +1,71 @@
1
+ import { materializeAdaptiveCandidateView } from "./adaptive-turn-materializer.js";
2
+ import { buildQtiDeliverySafeXml } from "./delivery-security.js";
3
+ /** Prepare candidate-safe XML for a supported QTI delivery mode. */
4
+ export function prepareQtiDeliveryXml(xml, options) {
5
+ const redaction = options.mode === "static"
6
+ ? buildQtiDeliverySafeXml(xml)
7
+ : materializeAdaptiveCandidateView({
8
+ itemXml: xml,
9
+ outcomes: options.outcomes,
10
+ ...(options.templateValues === undefined
11
+ ? {}
12
+ : { templateValues: options.templateValues }),
13
+ });
14
+ return {
15
+ ok: redaction.ok,
16
+ mode: options.mode,
17
+ diagnostics: normalizePreparationDiagnostics(redaction, options.mode),
18
+ analysis: redaction.analysis,
19
+ candidateSafeXml: redaction.xml,
20
+ };
21
+ }
22
+ function normalizePreparationDiagnostics(redaction, mode) {
23
+ const findingCodes = redaction.analysis.findings.map((finding) => preparationDiagnosticCodeForFinding(finding.kind, mode));
24
+ let findingIndex = 0;
25
+ return redaction.diagnostics.map((diagnostic) => {
26
+ if (!isDeliveryFindingDiagnosticCode(diagnostic.code))
27
+ return diagnostic;
28
+ if (diagnostic.code === "adaptiveTurn.materialization.unsupported") {
29
+ return {
30
+ ...diagnostic,
31
+ code: preparationDiagnosticCodeForLowerLevelCode(diagnostic.code, mode),
32
+ };
33
+ }
34
+ const code = findingCodes[findingIndex];
35
+ findingIndex += 1;
36
+ return {
37
+ ...diagnostic,
38
+ code: code ?? preparationDiagnosticCodeForLowerLevelCode(diagnostic.code, mode),
39
+ };
40
+ });
41
+ }
42
+ function preparationDiagnosticCodeForFinding(kind, mode) {
43
+ if (kind === "forbidden-delivery-element")
44
+ return "delivery.preparation.forbiddenElement";
45
+ if (kind === "unsupported-adaptive-response-processing") {
46
+ return "delivery.preparation.unsupportedAdaptiveResponseProcessing";
47
+ }
48
+ return mode === "server-materialized-adaptive"
49
+ ? "delivery.preparation.unsupportedMaterialization"
50
+ : "delivery.preparation.unsupportedSecureDelivery";
51
+ }
52
+ function isDeliveryFindingDiagnosticCode(code) {
53
+ return (code === "delivery.forbiddenElement" ||
54
+ code === "delivery.unsupportedSecureDelivery" ||
55
+ code === "delivery.unsupportedAdaptiveResponseProcessing" ||
56
+ code === "adaptiveTurn.materialization.forbiddenElement" ||
57
+ code === "adaptiveTurn.materialization.unsupported");
58
+ }
59
+ function preparationDiagnosticCodeForLowerLevelCode(code, mode) {
60
+ if (code === "delivery.forbiddenElement" ||
61
+ code === "adaptiveTurn.materialization.forbiddenElement") {
62
+ return "delivery.preparation.forbiddenElement";
63
+ }
64
+ if (code === "delivery.unsupportedAdaptiveResponseProcessing") {
65
+ return "delivery.preparation.unsupportedAdaptiveResponseProcessing";
66
+ }
67
+ return mode === "server-materialized-adaptive"
68
+ ? "delivery.preparation.unsupportedMaterialization"
69
+ : "delivery.preparation.unsupportedSecureDelivery";
70
+ }
71
+ //# sourceMappingURL=delivery-preparation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delivery-preparation.js","sourceRoot":"","sources":["../src/delivery-preparation.ts"],"names":[],"mappings":"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"}
@@ -39,6 +39,7 @@ export declare function analyzeDeliveryXml(parsed: ParsedDeliveryXml, policy: De
39
39
  export declare function redactDeliveryXml(xml: string, policy: DeliveryRedactionPolicy): RedactedDeliveryXmlResult;
40
40
  export declare function readRedactionRanges(nodes: readonly XmlNode[], shouldRedact: (node: XmlNode, normalizedName: string) => boolean): RedactionRange[];
41
41
  export declare function sourceRangeFor(node: XmlNode): RedactionRange[];
42
+ export declare function applySourceRangeEdits(xml: string, edits: readonly SourceRangeEdit[]): string;
42
43
  export declare function removeSourceRanges(xml: string, ranges: readonly RedactionRange[]): string;
43
44
  export declare function normalizedQtiElementName(localName: string): string;
44
45
  export declare function parseXmlBoolean(value: string | undefined): boolean | undefined;
@@ -47,4 +48,8 @@ export interface RedactionRange {
47
48
  startOffset: number;
48
49
  endOffset: number;
49
50
  }
51
+ export interface SourceRangeEdit extends RedactionRange {
52
+ /** When omitted, the source range is removed. When set, the range is replaced with this text. */
53
+ text?: string | undefined;
54
+ }
50
55
  //# sourceMappingURL=delivery-redaction.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"delivery-redaction.d.ts","sourceRoot":"","sources":["../src/delivery-redaction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACnE,OAAO,EAA6B,KAAK,OAAO,EAAE,MAAM,UAAU,CAAC;AAEnE,eAAO,MAAM,uCAAuC,aAIlD,CAAC;AAEH,eAAO,MAAM,uCAAuC,aAOlD,CAAC;AAEH,MAAM,MAAM,8BAA8B,GACtC,4BAA4B,GAC5B,qCAAqC,GACrC,0CAA0C,CAAC;AAE/C,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,8BAA8B,CAAC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;CACxC;AAED,MAAM,WAAW,2BAA2B;IAC1C,WAAW,EAAE,aAAa,EAAE,CAAC;IAC7B,QAAQ,EAAE,0BAA0B,EAAE,CAAC;IACvC,yFAAyF;IACzF,YAAY,EAAE,OAAO,CAAC;IACtB,yEAAyE;IACzE,uBAAuB,EAAE,OAAO,CAAC;CAClC;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,OAAO,GAAG,SAAS,CAAC;IAC1B,WAAW,EAAE,aAAa,EAAE,CAAC;CAC9B;AAED,MAAM,WAAW,uBAAuB;IACtC,kBAAkB,CAAC,IAAI,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC;IACnE,kBAAkB,CAAC,CACjB,IAAI,EAAE,OAAO,EACb,cAAc,EAAE,MAAM,EACtB,KAAK,EAAE,SAAS,OAAO,EAAE,GACxB,0BAA0B,GAAG,IAAI,CAAC;IACrC,wBAAwB,CAAC,IAAI,EAAE,8BAA8B,GAAG,MAAM,CAAC;IACvE,uBAAuB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC;CAChD;AAED,MAAM,WAAW,yBAAyB;IACxC,EAAE,EAAE,OAAO,CAAC;IACZ,WAAW,EAAE,aAAa,EAAE,CAAC;IAC7B,QAAQ,EAAE,2BAA2B,CAAC;IACtC,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1B;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,iBAAiB,CA8B/D;AAED,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,iBAAiB,EACzB,MAAM,EAAE,uBAAuB,GAC9B,2BAA2B,CA2C7B;AAED,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,uBAAuB,GAC9B,yBAAyB,CAuC3B;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,SAAS,OAAO,EAAE,EACzB,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,KAAK,OAAO,GAC/D,cAAc,EAAE,CAOlB;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,GAAG,cAAc,EAAE,CAI9D;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,cAAc,EAAE,GAAG,MAAM,CAQzF;AAED,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAGlE;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAM9E;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAOxF;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB"}
1
+ {"version":3,"file":"delivery-redaction.d.ts","sourceRoot":"","sources":["../src/delivery-redaction.ts"],"names":[],"mappings":"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"}
@@ -93,7 +93,10 @@ export function redactDeliveryXml(xml, policy) {
93
93
  };
94
94
  }
95
95
  const redactionRanges = readRedactionRanges([parsed.root, ...descendants(parsed.root, () => true)], (node, normalizedName) => policy.isForbiddenElement(node, normalizedName));
96
- const redactedXml = removeSourceRanges(xml, redactionRanges);
96
+ const redactedXml = applySourceRangeEdits(xml, redactionRanges.map((range) => ({
97
+ startOffset: range.startOffset,
98
+ endOffset: range.endOffset,
99
+ })));
97
100
  const redactedAnalysis = analyzeDeliveryXml(parseDeliveryXml(redactedXml), policy);
98
101
  if (!redactedAnalysis.deliverySafe || !redactedAnalysis.secureDeliverySupported) {
99
102
  return {
@@ -124,15 +127,33 @@ export function sourceRangeFor(node) {
124
127
  return [];
125
128
  return [{ startOffset: node.sourceRange.startOffset, endOffset }];
126
129
  }
127
- export function removeSourceRanges(xml, ranges) {
130
+ export function applySourceRangeEdits(xml, edits) {
131
+ if (edits.length === 0)
132
+ return xml;
133
+ const sorted = edits.toSorted((left, right) => left.startOffset - right.startOffset);
134
+ assertNonOverlappingSourceRangeEdits(sorted);
128
135
  let output = "";
129
136
  let cursor = 0;
130
- for (const range of ranges) {
131
- output += xml.slice(cursor, range.startOffset);
132
- cursor = range.endOffset;
137
+ for (const edit of sorted) {
138
+ output += xml.slice(cursor, edit.startOffset);
139
+ if (edit.text !== undefined)
140
+ output += edit.text;
141
+ cursor = edit.endOffset;
133
142
  }
134
143
  return output + xml.slice(cursor);
135
144
  }
145
+ function assertNonOverlappingSourceRangeEdits(edits) {
146
+ for (let index = 1; index < edits.length; index += 1) {
147
+ const previous = edits[index - 1];
148
+ const current = edits[index];
149
+ if (!previous || !current || current.startOffset >= previous.endOffset)
150
+ continue;
151
+ throw new Error("Source range edits must not overlap.");
152
+ }
153
+ }
154
+ export function removeSourceRanges(xml, ranges) {
155
+ return applySourceRangeEdits(xml, ranges.map((range) => ({ startOffset: range.startOffset, endOffset: range.endOffset })));
156
+ }
136
157
  export function normalizedQtiElementName(localName) {
137
158
  const lower = localName.toLowerCase();
138
159
  return lower.startsWith("qti-") ? lower.slice("qti-".length) : lower;
@@ -1 +1 @@
1
- {"version":3,"file":"delivery-redaction.js","sourceRoot":"","sources":["../src/delivery-redaction.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"delivery-redaction.js","sourceRoot":"","sources":["../src/delivery-redaction.ts"],"names":[],"mappings":"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"}
@@ -43,12 +43,12 @@ const staticDeliveryPolicy = {
43
43
  }
44
44
  return null;
45
45
  },
46
- diagnosticCodeForFinding,
46
+ diagnosticCodeForFinding: staticDiagnosticCodeForFinding,
47
47
  forbiddenElementMessage(node) {
48
48
  return `${node.name} exposes answer keys, scoring, mapping, feedback, or solution information during delivery.`;
49
49
  },
50
50
  };
51
- function diagnosticCodeForFinding(kind) {
51
+ function staticDiagnosticCodeForFinding(kind) {
52
52
  if (kind === "forbidden-delivery-element")
53
53
  return "delivery.forbiddenElement";
54
54
  if (kind === "unsupported-adaptive-response-processing") {
@@ -1 +1 @@
1
- {"version":3,"file":"delivery-security.js","sourceRoot":"","sources":["../src/delivery-security.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uCAAuC,EACvC,kBAAkB,EAClB,yBAAyB,EACzB,wBAAwB,EACxB,gBAAgB,EAChB,eAAe,EACf,iBAAiB,GAIlB,MAAM,yBAAyB,CAAC;AASjC,MAAM,gCAAgC,GAAG,IAAI,GAAG,CAAC;IAC/C,GAAG,uCAAuC;IAC1C,iBAAiB;IACjB,gBAAgB;IAChB,gBAAgB;CACjB,CAAC,CAAC;AAEH,MAAM,yCAAyC,GAAG,IAAI,GAAG,CAAC;IACxD,qBAAqB;IACrB,sBAAsB;CACvB,CAAC,CAAC;AASH,MAAM,UAAU,0BAA0B,CAAC,GAAW;IACpD,OAAO,kBAAkB,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,oBAAoB,CAAC,CAAC;AACzE,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,GAAW;IACjD,OAAO,iBAAiB,CAAC,GAAG,EAAE,oBAAoB,CAAC,CAAC;AACtD,CAAC;AAED,MAAM,oBAAoB,GAA4B;IACpD,kBAAkB,CAAC,IAAI,EAAE,cAAc;QACrC,OAAO,CACL,gCAAgC,CAAC,GAAG,CAAC,cAAc,CAAC;YACpD,yBAAyB,CAAC,IAAI,EAAE,cAAc,CAAC,CAChD,CAAC;IACJ,CAAC;IACD,kBAAkB,CAAC,IAAI,EAAE,cAAc,EAAE,KAAK;QAC5C,IAAI,yCAAyC,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,CAAC;YAClE,OAAO;gBACL,IAAI,EAAE,qCAAqC;gBAC3C,OAAO,EAAE,IAAI,CAAC,IAAI;gBAClB,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,OAAO,EAAE,GAAG,IAAI,CAAC,IAAI,oDAAoD;gBACzE,MAAM,EAAE,IAAI,CAAC,MAAM;aACpB,CAAC;QACJ,CAAC;QAED,IACE,IAAI,CAAC,MAAM,KAAK,SAAS;YACzB,eAAe,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,KAAK,IAAI;YAClD,KAAK,CAAC,IAAI,CACR,CAAC,SAAS,EAAE,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,SAAS,CAAC,KAAK,qBAAqB,CACvF,EACD,CAAC;YACD,OAAO;gBACL,IAAI,EAAE,0CAA0C;gBAChD,OAAO,EAAE,IAAI,CAAC,IAAI;gBAClB,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,OAAO,EACL,gGAAgG;gBAClG,MAAM,EAAE,IAAI,CAAC,MAAM;aACpB,CAAC;QACJ,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IACD,wBAAwB;IACxB,uBAAuB,CAAC,IAAa;QACnC,OAAO,GAAG,IAAI,CAAC,IAAI,4FAA4F,CAAC;IAClH,CAAC;CACF,CAAC;AAEF,SAAS,wBAAwB,CAAC,IAAoC;IACpE,IAAI,IAAI,KAAK,4BAA4B;QAAE,OAAO,2BAA2B,CAAC;IAC9E,IAAI,IAAI,KAAK,0CAA0C,EAAE,CAAC;QACxD,OAAO,gDAAgD,CAAC;IAC1D,CAAC;IACD,OAAO,oCAAoC,CAAC;AAC9C,CAAC"}
1
+ {"version":3,"file":"delivery-security.js","sourceRoot":"","sources":["../src/delivery-security.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uCAAuC,EACvC,kBAAkB,EAClB,yBAAyB,EACzB,wBAAwB,EACxB,gBAAgB,EAChB,eAAe,EACf,iBAAiB,GAIlB,MAAM,yBAAyB,CAAC;AASjC,MAAM,gCAAgC,GAAG,IAAI,GAAG,CAAC;IAC/C,GAAG,uCAAuC;IAC1C,iBAAiB;IACjB,gBAAgB;IAChB,gBAAgB;CACjB,CAAC,CAAC;AAEH,MAAM,yCAAyC,GAAG,IAAI,GAAG,CAAC;IACxD,qBAAqB;IACrB,sBAAsB;CACvB,CAAC,CAAC;AASH,MAAM,UAAU,0BAA0B,CAAC,GAAW;IACpD,OAAO,kBAAkB,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,oBAAoB,CAAC,CAAC;AACzE,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,GAAW;IACjD,OAAO,iBAAiB,CAAC,GAAG,EAAE,oBAAoB,CAAC,CAAC;AACtD,CAAC;AAED,MAAM,oBAAoB,GAA4B;IACpD,kBAAkB,CAAC,IAAI,EAAE,cAAc;QACrC,OAAO,CACL,gCAAgC,CAAC,GAAG,CAAC,cAAc,CAAC;YACpD,yBAAyB,CAAC,IAAI,EAAE,cAAc,CAAC,CAChD,CAAC;IACJ,CAAC;IACD,kBAAkB,CAAC,IAAI,EAAE,cAAc,EAAE,KAAK;QAC5C,IAAI,yCAAyC,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,CAAC;YAClE,OAAO;gBACL,IAAI,EAAE,qCAAqC;gBAC3C,OAAO,EAAE,IAAI,CAAC,IAAI;gBAClB,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,OAAO,EAAE,GAAG,IAAI,CAAC,IAAI,oDAAoD;gBACzE,MAAM,EAAE,IAAI,CAAC,MAAM;aACpB,CAAC;QACJ,CAAC;QAED,IACE,IAAI,CAAC,MAAM,KAAK,SAAS;YACzB,eAAe,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,KAAK,IAAI;YAClD,KAAK,CAAC,IAAI,CACR,CAAC,SAAS,EAAE,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,SAAS,CAAC,KAAK,qBAAqB,CACvF,EACD,CAAC;YACD,OAAO;gBACL,IAAI,EAAE,0CAA0C;gBAChD,OAAO,EAAE,IAAI,CAAC,IAAI;gBAClB,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,OAAO,EACL,gGAAgG;gBAClG,MAAM,EAAE,IAAI,CAAC,MAAM;aACpB,CAAC;QACJ,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IACD,wBAAwB,EAAE,8BAA8B;IACxD,uBAAuB,CAAC,IAAa;QACnC,OAAO,GAAG,IAAI,CAAC,IAAI,4FAA4F,CAAC;IAClH,CAAC;CACF,CAAC;AAEF,SAAS,8BAA8B,CAAC,IAAoC;IAC1E,IAAI,IAAI,KAAK,4BAA4B;QAAE,OAAO,2BAA2B,CAAC;IAC9E,IAAI,IAAI,KAAK,0CAA0C,EAAE,CAAC;QACxD,OAAO,gDAAgD,CAAC;IAC1D,CAAC;IACD,OAAO,oCAAoC,CAAC;AAC9C,CAAC"}
package/dist/index.d.ts CHANGED
@@ -3,13 +3,19 @@ export { assertNever } from "./assert-never.js";
3
3
  export { createCatalogSupportResolution, type QtiCatalogSupportResolution, type QtiCatalogSupportResolutionOptions, type QtiResolvedCatalogReference, type QtiResolvedCatalogSupport, } from "./catalog.js";
4
4
  export { createCompanionMaterialsResolution, type QtiCompanionMaterialsResolution, type QtiCompanionMaterialsResolutionOptions, type QtiResolvedCompanionMaterialUnparsedChild, type QtiResolvedDigitalCompanionMaterial, type QtiResolvedPhysicalCompanionMaterial, } from "./companion-materials-resolution.js";
5
5
  export { isResolvableAssetUrl } from "./asset-url.js";
6
+ export { materializeQtiItemSubmission, type QtiItemSubmissionMaterializationInput, type QtiItemSubmissionMaterializationResult, type QtiItemSubmissionResponseInput, type QtiItemSubmissionScoringDisposition, type QtiVariableSnapshot, } from "./item-submission-materialization.js";
7
+ export { prepareQtiDeliveryXml, type QtiDeliveryPreparationMode, type QtiDeliveryPreparationOptions, type QtiDeliveryPreparationResult, } from "./delivery-preparation.js";
6
8
  export { analyzeQtiDeliverySecurity, buildQtiDeliverySafeXml, type QtiDeliverySafeXmlResult, type QtiDeliverySecurityAnalysis, type QtiDeliverySecurityFinding, type QtiDeliverySecurityFindingKind, } from "./delivery-security.js";
7
9
  export { compileQtiPatternMask, isValidQtiPatternMask } from "./pattern-mask.js";
8
10
  export { parseQtiPackageXmlTree, type QtiPackageXmlNode, type QtiPackageXmlTree, } from "./package-xml.js";
11
+ export { parseQtiPackage, type QtiAssessmentTestItemRef, type QtiAssessmentTestPackageModel, type QtiManifestFile, type QtiManifestResource, type QtiPackageAsset, type QtiPackageAssetSource, type QtiPackageInflateContext, type QtiPackageInflateRaw, type QtiPackageItem, type QtiPackageItemSource, type QtiPackageParseOptions, type QtiPackageParseResult, type QtiPackageShape, type QtiStandardAlignment, type QtiTimingMetadata, } from "./qti-package.js";
12
+ export { detectPackageMediaType } from "./qti-package-assets.js";
9
13
  export { parseQtiXml } from "./parser.js";
10
14
  export { numericTuple3, numericTuple4 } from "./parser-values.js";
11
15
  export { isConformanceParseDiagnostic } from "./parse-diagnostics.js";
12
16
  export { scoreQtiItemServerSide, type QtiServerScoringInput, type QtiServerScoringResponseInput, type QtiServerScoringResult, } from "./server-scoring.js";
17
+ export { associationMaximumResponses, choiceMatchLimitExceeded, choiceMatchMaximum, directedPairChoiceUseCount, matchMaxDiagnostics, maximumAllowedResponses, maximumMediaPlays, maximumResponseDiagnostic, mediaPlayCount, minimumMediaPlays, minimumRequiredResponses, orderSubsetLimitsActive, parseUnlimitedMaximum, requiredResponseDiagnostic, responseCount, responseIsEmpty, responseLimitAttribute, responseValidationPolicy, wouldExceedChoiceMatchMaximum, type DirectedPairUseSide, type QtiResponseValidationPolicy, } from "./response-validation-policy.js";
18
+ export { validateQtiResponseVariables, type QtiResponseValidationDiagnostic, type QtiResponseValidationDiagnosticCode, type QtiResponseValidationInput, type QtiResponseValidationResult, type QtiResponseVariableInput, type QtiResponseVariablesInput, } from "./response-validation.js";
13
19
  export { serializeResponseProcessing, type QtiSerializeResponseProcessingResult, } from "./serializer-processing.js";
14
20
  export { createTextToSpeechTraversal, parseQtiDataSsml, validateQtiDataSsmlMetadata, type QtiDataSsml, type QtiDataSsmlBreak, type QtiDataSsmlBreakStrength, type QtiDataSsmlParseResult, type QtiDataSsmlPhoneme, type QtiDataSsmlProsody, type QtiDataSsmlSayAs, type QtiDataSsmlSub, type QtiTextToSpeechSegment, type QtiTextToSpeechSegmentKind, type QtiTextToSpeechTraversal, } from "./tts.js";
15
21
  export { assertQtiAttemptStateV1, createItemSession, isQtiAttemptStateV1, visibleModalFeedback, type QtiCustomOperatorContext, type QtiCustomOperatorHandler, type QtiCustomOperatorRegistry, type QtiItemSession, type QtiItemSessionOptions, } from "./session.js";