@longsightgroup/qti3-core 0.10.2 → 0.10.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (188) hide show
  1. package/README.md +21 -2
  2. package/dist/attempt-state.d.ts.map +1 -1
  3. package/dist/attempt-state.js +20 -27
  4. package/dist/attempt-state.js.map +1 -1
  5. package/dist/content-text.d.ts +4 -0
  6. package/dist/content-text.d.ts.map +1 -1
  7. package/dist/content-text.js +137 -12
  8. package/dist/content-text.js.map +1 -1
  9. package/dist/index.d.ts +6 -1
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +6 -1
  12. package/dist/index.js.map +1 -1
  13. package/dist/media-definition.d.ts +55 -0
  14. package/dist/media-definition.d.ts.map +1 -0
  15. package/dist/media-definition.js +97 -0
  16. package/dist/media-definition.js.map +1 -0
  17. package/dist/package-xml.d.ts +1 -0
  18. package/dist/package-xml.d.ts.map +1 -1
  19. package/dist/package-xml.js +1 -0
  20. package/dist/package-xml.js.map +1 -1
  21. package/dist/parser-custom-interactions.js +1 -0
  22. package/dist/parser-custom-interactions.js.map +1 -1
  23. package/dist/parser-declarations.d.ts +4 -4
  24. package/dist/parser-declarations.d.ts.map +1 -1
  25. package/dist/parser-declarations.js +87 -46
  26. package/dist/parser-declarations.js.map +1 -1
  27. package/dist/parser-item-metadata.d.ts.map +1 -1
  28. package/dist/parser-item-metadata.js +5 -3
  29. package/dist/parser-item-metadata.js.map +1 -1
  30. package/dist/parser-processing.js +10 -9
  31. package/dist/parser-processing.js.map +1 -1
  32. package/dist/parser-values.d.ts +6 -0
  33. package/dist/parser-values.d.ts.map +1 -1
  34. package/dist/parser-values.js +35 -2
  35. package/dist/parser-values.js.map +1 -1
  36. package/dist/parser.d.ts.map +1 -1
  37. package/dist/parser.js +81 -47
  38. package/dist/parser.js.map +1 -1
  39. package/dist/processing-evaluator-collection.d.ts.map +1 -1
  40. package/dist/processing-evaluator-collection.js +8 -2
  41. package/dist/processing-evaluator-collection.js.map +1 -1
  42. package/dist/processing-evaluator-comparison.d.ts.map +1 -1
  43. package/dist/processing-evaluator-comparison.js +22 -6
  44. package/dist/processing-evaluator-comparison.js.map +1 -1
  45. package/dist/processing-evaluator-numeric.d.ts.map +1 -1
  46. package/dist/processing-evaluator-numeric.js +8 -1
  47. package/dist/processing-evaluator-numeric.js.map +1 -1
  48. package/dist/processing-evaluator-variable.d.ts.map +1 -1
  49. package/dist/processing-evaluator-variable.js +1 -1
  50. package/dist/processing-evaluator-variable.js.map +1 -1
  51. package/dist/processing-expression-children.d.ts.map +1 -1
  52. package/dist/processing-expression-children.js +2 -1
  53. package/dist/processing-expression-children.js.map +1 -1
  54. package/dist/processing-limits.d.ts +3 -0
  55. package/dist/processing-limits.d.ts.map +1 -0
  56. package/dist/processing-limits.js +3 -0
  57. package/dist/processing-limits.js.map +1 -0
  58. package/dist/processing-mapping.d.ts.map +1 -1
  59. package/dist/processing-mapping.js +28 -9
  60. package/dist/processing-mapping.js.map +1 -1
  61. package/dist/processing-operators.d.ts +2 -0
  62. package/dist/processing-operators.d.ts.map +1 -1
  63. package/dist/processing-operators.js +34 -5
  64. package/dist/processing-operators.js.map +1 -1
  65. package/dist/processing-values.d.ts +4 -4
  66. package/dist/processing-values.d.ts.map +1 -1
  67. package/dist/processing-values.js +28 -14
  68. package/dist/processing-values.js.map +1 -1
  69. package/dist/processing-variables.d.ts +3 -1
  70. package/dist/processing-variables.d.ts.map +1 -1
  71. package/dist/processing-variables.js +38 -2
  72. package/dist/processing-variables.js.map +1 -1
  73. package/dist/qti-namespaces.d.ts +7 -0
  74. package/dist/qti-namespaces.d.ts.map +1 -0
  75. package/dist/qti-namespaces.js +7 -0
  76. package/dist/qti-namespaces.js.map +1 -0
  77. package/dist/qti-package-items.d.ts.map +1 -1
  78. package/dist/qti-package-items.js +23 -13
  79. package/dist/qti-package-items.js.map +1 -1
  80. package/dist/qti-package-manifest.d.ts.map +1 -1
  81. package/dist/qti-package-manifest.js +4 -3
  82. package/dist/qti-package-manifest.js.map +1 -1
  83. package/dist/qti-package-metadata.d.ts.map +1 -1
  84. package/dist/qti-package-metadata.js +3 -2
  85. package/dist/qti-package-metadata.js.map +1 -1
  86. package/dist/qti-package-xml.d.ts +4 -2
  87. package/dist/qti-package-xml.d.ts.map +1 -1
  88. package/dist/qti-package-xml.js +10 -5
  89. package/dist/qti-package-xml.js.map +1 -1
  90. package/dist/qti-package-zip.d.ts +17 -1
  91. package/dist/qti-package-zip.d.ts.map +1 -1
  92. package/dist/qti-package-zip.js +60 -5
  93. package/dist/qti-package-zip.js.map +1 -1
  94. package/dist/qti-package.d.ts +3 -3
  95. package/dist/qti-package.d.ts.map +1 -1
  96. package/dist/qti-package.js +10 -4
  97. package/dist/qti-package.js.map +1 -1
  98. package/dist/response-validation-policy.d.ts.map +1 -1
  99. package/dist/response-validation-policy.js +5 -6
  100. package/dist/response-validation-policy.js.map +1 -1
  101. package/dist/response-validation.d.ts +12 -2
  102. package/dist/response-validation.d.ts.map +1 -1
  103. package/dist/response-validation.js +122 -19
  104. package/dist/response-validation.js.map +1 -1
  105. package/dist/serializer-processing-expressions.js +1 -1
  106. package/dist/serializer-processing-expressions.js.map +1 -1
  107. package/dist/session.js +1 -1
  108. package/dist/session.js.map +1 -1
  109. package/dist/slider-definition.d.ts +59 -0
  110. package/dist/slider-definition.d.ts.map +1 -0
  111. package/dist/slider-definition.js +198 -0
  112. package/dist/slider-definition.js.map +1 -0
  113. package/dist/support-evidence.d.ts +6 -2
  114. package/dist/support-evidence.d.ts.map +1 -1
  115. package/dist/support-evidence.js +15 -11
  116. package/dist/support-evidence.js.map +1 -1
  117. package/dist/support.d.ts.map +1 -1
  118. package/dist/support.js +96 -100
  119. package/dist/support.js.map +1 -1
  120. package/dist/trusted-item-session.d.ts.map +1 -1
  121. package/dist/trusted-item-session.js +5 -3
  122. package/dist/trusted-item-session.js.map +1 -1
  123. package/dist/types.d.ts +5 -0
  124. package/dist/types.d.ts.map +1 -1
  125. package/dist/validation-declaration-entries.d.ts +13 -0
  126. package/dist/validation-declaration-entries.d.ts.map +1 -0
  127. package/dist/validation-declaration-entries.js +136 -0
  128. package/dist/validation-declaration-entries.js.map +1 -0
  129. package/dist/validation-interactions.d.ts.map +1 -1
  130. package/dist/validation-interactions.js +14 -46
  131. package/dist/validation-interactions.js.map +1 -1
  132. package/dist/validation-primitives.d.ts +5 -1
  133. package/dist/validation-primitives.d.ts.map +1 -1
  134. package/dist/validation-primitives.js +41 -3
  135. package/dist/validation-primitives.js.map +1 -1
  136. package/dist/validation-processing.d.ts.map +1 -1
  137. package/dist/validation-processing.js +125 -1
  138. package/dist/validation-processing.js.map +1 -1
  139. package/dist/validation.d.ts.map +1 -1
  140. package/dist/validation.js +8 -134
  141. package/dist/validation.js.map +1 -1
  142. package/dist/xml.d.ts.map +1 -1
  143. package/dist/xml.js +31 -2
  144. package/dist/xml.js.map +1 -1
  145. package/package.json +1 -1
  146. package/src/attempt-state.ts +22 -26
  147. package/src/content-text.ts +174 -14
  148. package/src/index.ts +28 -0
  149. package/src/media-definition.ts +174 -0
  150. package/src/package-xml.ts +2 -0
  151. package/src/parser-custom-interactions.ts +1 -0
  152. package/src/parser-declarations.ts +134 -40
  153. package/src/parser-item-metadata.ts +5 -3
  154. package/src/parser-processing.ts +10 -9
  155. package/src/parser-values.ts +35 -2
  156. package/src/parser.ts +137 -103
  157. package/src/processing-evaluator-collection.ts +7 -2
  158. package/src/processing-evaluator-comparison.ts +30 -5
  159. package/src/processing-evaluator-numeric.ts +5 -1
  160. package/src/processing-evaluator-variable.ts +1 -0
  161. package/src/processing-expression-children.ts +2 -1
  162. package/src/processing-limits.ts +2 -0
  163. package/src/processing-mapping.ts +32 -8
  164. package/src/processing-operators.ts +38 -5
  165. package/src/processing-values.ts +59 -14
  166. package/src/processing-variables.ts +47 -2
  167. package/src/qti-namespaces.ts +8 -0
  168. package/src/qti-package-items.ts +56 -49
  169. package/src/qti-package-manifest.ts +13 -4
  170. package/src/qti-package-metadata.ts +3 -2
  171. package/src/qti-package-xml.ts +16 -3
  172. package/src/qti-package-zip.ts +128 -3
  173. package/src/qti-package.ts +12 -3
  174. package/src/response-validation-policy.ts +5 -5
  175. package/src/response-validation.ts +185 -20
  176. package/src/serializer-processing-expressions.ts +1 -1
  177. package/src/session.ts +1 -0
  178. package/src/slider-definition.ts +363 -0
  179. package/src/support-evidence.ts +15 -17
  180. package/src/support.ts +106 -102
  181. package/src/trusted-item-session.ts +5 -3
  182. package/src/types.ts +10 -1
  183. package/src/validation-declaration-entries.ts +162 -0
  184. package/src/validation-interactions.ts +14 -64
  185. package/src/validation-primitives.ts +44 -4
  186. package/src/validation-processing.ts +145 -1
  187. package/src/validation.ts +11 -151
  188. package/src/xml.ts +40 -4
package/src/support.ts CHANGED
@@ -11,9 +11,14 @@ import type {
11
11
  import {
12
12
  browserFeedbackTests,
13
13
  browserHarnessTests,
14
+ coreIntegrationTest,
14
15
  interactionSupportFixtures,
15
16
  interactionSupportTests,
16
17
  processingBrowserEvidence,
18
+ processingMappingTest,
19
+ processingOperatorsTest,
20
+ processingResponseTest,
21
+ processingTemplateTest,
17
22
  } from "./support-evidence.js";
18
23
 
19
24
  export const interactionSupport: QtiInteractionElementSupport[] = [
@@ -52,15 +57,19 @@ export const deprecatedInteractionSupport: QtiInteractionElementSupport[] = [
52
57
  render: false,
53
58
  process: false,
54
59
  fixtures: [],
55
- tests: ["packages/core/src/core.test.ts"],
60
+ tests: [coreIntegrationTest],
56
61
  notes: "Deprecated in favor of qti-portable-custom-interaction.",
57
62
  },
58
63
  ];
59
64
 
65
+ const templateProcessingEntry = processingEntryFor(processingTemplateTest);
66
+ const responseProcessingEntry = processingEntryFor(processingResponseTest);
67
+ const mappingProcessingEntry = processingEntryFor(processingMappingTest);
68
+ const operatorProcessingEntry = processingEntryFor(processingOperatorsTest);
69
+
60
70
  export const processingSupport: QtiProcessingElementSupport[] = [
61
- processingEntry(
71
+ templateProcessingEntry(
62
72
  "qti-template-processing",
63
- "packages/core/src/core.test.ts",
64
73
  [
65
74
  "packages/fixtures/xml/template-processing-reference.xml",
66
75
  "packages/fixtures/xml/random-integer-template-reference.xml",
@@ -68,9 +77,8 @@ export const processingSupport: QtiProcessingElementSupport[] = [
68
77
  ],
69
78
  [...processingBrowserEvidence["qti-template-processing"]],
70
79
  ),
71
- processingEntry(
80
+ responseProcessingEntry(
72
81
  "qti-response-processing",
73
- "packages/core/src/core.test.ts",
74
82
  [
75
83
  "packages/fixtures/xml/mapping-processing-reference.xml",
76
84
  "packages/fixtures/xml/generic-match-processing-reference.xml",
@@ -79,64 +87,64 @@ export const processingSupport: QtiProcessingElementSupport[] = [
79
87
  ],
80
88
  [...processingBrowserEvidence["qti-response-processing"]],
81
89
  ),
82
- processingEntry("qti-set-template-value", "packages/core/src/core.test.ts", [
90
+ templateProcessingEntry("qti-set-template-value", [
83
91
  "packages/fixtures/xml/template-processing-reference.xml",
84
92
  "packages/fixtures/xml/random-integer-template-reference.xml",
85
93
  "packages/fixtures/xml/template-content-reference.xml",
86
94
  ]),
87
- processingEntry("qti-set-default-value", "packages/core/src/core.test.ts"),
88
- processingEntry("qti-set-correct-response", "packages/core/src/core.test.ts", [
95
+ templateProcessingEntry("qti-set-default-value"),
96
+ templateProcessingEntry("qti-set-correct-response", [
89
97
  "packages/fixtures/xml/template-processing-reference.xml",
90
98
  "packages/fixtures/xml/random-integer-template-reference.xml",
91
99
  ]),
92
- processingEntry("qti-template-condition", "packages/core/src/core.test.ts"),
93
- processingEntry("qti-template-if", "packages/core/src/core.test.ts"),
94
- processingEntry("qti-template-else-if", "packages/core/src/core.test.ts"),
95
- processingEntry("qti-template-else", "packages/core/src/core.test.ts"),
96
- processingEntry("qti-template-constraint", "packages/core/src/core.test.ts"),
97
- processingEntry("qti-response-condition", "packages/core/src/core.test.ts", [
100
+ templateProcessingEntry("qti-template-condition"),
101
+ templateProcessingEntry("qti-template-if"),
102
+ templateProcessingEntry("qti-template-else-if"),
103
+ templateProcessingEntry("qti-template-else"),
104
+ templateProcessingEntry("qti-template-constraint"),
105
+ responseProcessingEntry("qti-response-condition", [
98
106
  "packages/fixtures/xml/generic-match-processing-reference.xml",
99
107
  "packages/fixtures/xml/advanced-processing-reference.xml",
100
108
  "packages/fixtures/xml/adaptive-feedback-reference.xml",
101
109
  ]),
102
- processingEntry("qti-response-if", "packages/core/src/core.test.ts", [
110
+ responseProcessingEntry("qti-response-if", [
103
111
  "packages/fixtures/xml/generic-match-processing-reference.xml",
104
112
  "packages/fixtures/xml/advanced-processing-reference.xml",
105
113
  "packages/fixtures/xml/adaptive-feedback-reference.xml",
106
114
  ]),
107
- processingEntry("qti-response-else-if", "packages/core/src/core.test.ts"),
108
- processingEntry("qti-response-else", "packages/core/src/core.test.ts", [
115
+ responseProcessingEntry("qti-response-else-if"),
116
+ responseProcessingEntry("qti-response-else", [
109
117
  "packages/fixtures/xml/generic-match-processing-reference.xml",
110
118
  ]),
111
- processingEntry("qti-set-outcome-value", "packages/core/src/core.test.ts", [
119
+ responseProcessingEntry("qti-set-outcome-value", [
112
120
  "packages/fixtures/xml/generic-match-processing-reference.xml",
113
121
  "packages/fixtures/xml/advanced-processing-reference.xml",
114
122
  "packages/fixtures/xml/adaptive-feedback-reference.xml",
115
123
  ]),
116
- processingEntry("qti-lookup-outcome-value", "packages/core/src/core.test.ts"),
117
- processingEntry("qti-exit-response", "packages/core/src/core.test.ts"),
118
- processingEntry("qti-exit-template", "packages/core/src/core.test.ts"),
119
- processingEntry("qti-response-processing-fragment", "packages/core/src/core.test.ts"),
120
- processingEntry("qti-base-value", "packages/core/src/core.test.ts", [
124
+ mappingProcessingEntry("qti-lookup-outcome-value"),
125
+ responseProcessingEntry("qti-exit-response"),
126
+ templateProcessingEntry("qti-exit-template"),
127
+ responseProcessingEntry("qti-response-processing-fragment"),
128
+ operatorProcessingEntry("qti-base-value", [
121
129
  "packages/fixtures/xml/generic-match-processing-reference.xml",
122
130
  "packages/fixtures/xml/template-processing-reference.xml",
123
131
  "packages/fixtures/xml/advanced-processing-reference.xml",
124
132
  ]),
125
- processingEntry("qti-null", "packages/core/src/core.test.ts"),
126
- processingEntry("qti-match-table", "packages/core/src/core.test.ts"),
127
- processingEntry("qti-match-table-entry", "packages/core/src/core.test.ts"),
128
- processingEntry("qti-interpolation-table", "packages/core/src/core.test.ts"),
129
- processingEntry("qti-interpolation-table-entry", "packages/core/src/core.test.ts"),
130
- processingEntry("qti-is-null", "packages/core/src/core.test.ts"),
131
- processingEntry("qti-match", "packages/core/src/core.test.ts", [
133
+ operatorProcessingEntry("qti-null"),
134
+ mappingProcessingEntry("qti-match-table"),
135
+ mappingProcessingEntry("qti-match-table-entry"),
136
+ mappingProcessingEntry("qti-interpolation-table"),
137
+ mappingProcessingEntry("qti-interpolation-table-entry"),
138
+ operatorProcessingEntry("qti-is-null"),
139
+ mappingProcessingEntry("qti-match", [
132
140
  "packages/fixtures/xml/generic-match-processing-reference.xml",
133
141
  "packages/fixtures/xml/advanced-processing-reference.xml",
134
142
  ]),
135
- processingEntry("qti-correct", "packages/core/src/core.test.ts"),
136
- processingEntry("qti-default", "packages/core/src/core.test.ts"),
137
- processingEntry("qti-map-response", "packages/core/src/core.test.ts"),
138
- processingEntry("qti-map-response-point", "packages/core/src/core.test.ts"),
139
- processingEntry("qti-variable", "packages/core/src/core.test.ts", [
143
+ mappingProcessingEntry("qti-correct"),
144
+ mappingProcessingEntry("qti-default"),
145
+ mappingProcessingEntry("qti-map-response"),
146
+ mappingProcessingEntry("qti-map-response-point"),
147
+ responseProcessingEntry("qti-variable", [
140
148
  "packages/fixtures/xml/generic-match-processing-reference.xml",
141
149
  "packages/fixtures/xml/template-processing-reference.xml",
142
150
  "packages/fixtures/xml/random-integer-template-reference.xml",
@@ -144,81 +152,74 @@ export const processingSupport: QtiProcessingElementSupport[] = [
144
152
  "packages/fixtures/xml/advanced-processing-reference.xml",
145
153
  "packages/fixtures/xml/adaptive-feedback-reference.xml",
146
154
  ]),
147
- processingEntry(
155
+ templateProcessingEntry(
148
156
  "qti-random-integer",
149
- "packages/core/src/core.test.ts",
150
157
  ["packages/fixtures/xml/random-integer-template-reference.xml"],
151
158
  [...processingBrowserEvidence["qti-random-integer"]],
152
159
  ),
153
- processingEntry("qti-random-float", "packages/core/src/core.test.ts"),
154
- processingEntry("qti-random", "packages/core/src/core.test.ts"),
155
- processingEntry("qti-multiple", "packages/core/src/core.test.ts", [
160
+ operatorProcessingEntry("qti-random-float"),
161
+ operatorProcessingEntry("qti-random"),
162
+ operatorProcessingEntry("qti-multiple", [
156
163
  "packages/fixtures/xml/advanced-processing-reference.xml",
157
164
  ]),
158
- processingEntry("qti-ordered", "packages/core/src/core.test.ts", [
165
+ operatorProcessingEntry("qti-ordered", [
159
166
  "packages/fixtures/xml/advanced-processing-reference.xml",
160
167
  ]),
161
- processingEntry("qti-index", "packages/core/src/core.test.ts"),
162
- processingEntry("qti-contains", "packages/core/src/core.test.ts"),
163
- processingEntry("qti-container-size", "packages/core/src/core.test.ts", [
168
+ operatorProcessingEntry("qti-index"),
169
+ operatorProcessingEntry("qti-contains"),
170
+ operatorProcessingEntry("qti-container-size", [
164
171
  "packages/fixtures/xml/advanced-processing-reference.xml",
165
172
  ]),
166
- processingEntry("qti-sum", "packages/core/src/core.test.ts", [
173
+ operatorProcessingEntry("qti-sum", [
167
174
  "packages/fixtures/xml/template-processing-reference.xml",
168
175
  "packages/fixtures/xml/random-integer-template-reference.xml",
169
176
  ]),
170
- processingEntry("qti-product", "packages/core/src/core.test.ts", [
177
+ operatorProcessingEntry("qti-product", [
171
178
  "packages/fixtures/xml/random-integer-template-reference.xml",
172
179
  ]),
173
- processingEntry("qti-min", "packages/core/src/core.test.ts"),
174
- processingEntry("qti-max", "packages/core/src/core.test.ts"),
175
- processingEntry("qti-subtract", "packages/core/src/core.test.ts"),
176
- processingEntry("qti-divide", "packages/core/src/core.test.ts"),
177
- processingEntry("qti-power", "packages/core/src/core.test.ts"),
178
- processingEntry("qti-integer-divide", "packages/core/src/core.test.ts"),
179
- processingEntry("qti-integer-modulus", "packages/core/src/core.test.ts"),
180
- processingEntry("qti-round", "packages/core/src/core.test.ts"),
181
- processingEntry("qti-round-to", "packages/core/src/core.test.ts"),
182
- processingEntry("qti-truncate", "packages/core/src/core.test.ts"),
183
- processingEntry("qti-integer-to-float", "packages/core/src/core.test.ts"),
184
- processingEntry("qti-and", "packages/core/src/core.test.ts"),
185
- processingEntry("qti-any-n", "packages/core/src/core.test.ts"),
186
- processingEntry("qti-or", "packages/core/src/core.test.ts"),
187
- processingEntry("qti-not", "packages/core/src/core.test.ts"),
188
- processingEntry("qti-equal", "packages/core/src/core.test.ts"),
189
- processingEntry("qti-equal-rounded", "packages/core/src/core.test.ts", [
190
- "packages/fixtures/xml/advanced-processing-reference.xml",
191
- ]),
192
- processingEntry("qti-field-value", "packages/core/src/core.test.ts"),
193
- processingEntry("qti-lt", "packages/core/src/core.test.ts"),
194
- processingEntry("qti-lte", "packages/core/src/core.test.ts"),
195
- processingEntry("qti-gt", "packages/core/src/core.test.ts"),
196
- processingEntry("qti-gte", "packages/core/src/core.test.ts"),
197
- processingEntry("qti-string-match", "packages/core/src/core.test.ts"),
198
- processingEntry("qti-substring", "packages/core/src/core.test.ts"),
199
- processingEntry("qti-pattern-match", "packages/core/src/core.test.ts"),
200
- processingEntry("qti-member", "packages/core/src/core.test.ts"),
201
- processingEntry("qti-delete", "packages/core/src/core.test.ts"),
202
- processingEntry("qti-duration-gte", "packages/core/src/core.test.ts"),
203
- processingEntry("qti-duration-lt", "packages/core/src/core.test.ts"),
204
- processingEntry("qti-gcd", "packages/core/src/core.test.ts", [
205
- "packages/fixtures/xml/advanced-processing-reference.xml",
206
- ]),
207
- processingEntry("qti-inside", "packages/core/src/core.test.ts", [
180
+ operatorProcessingEntry("qti-min"),
181
+ operatorProcessingEntry("qti-max"),
182
+ operatorProcessingEntry("qti-subtract"),
183
+ operatorProcessingEntry("qti-divide"),
184
+ operatorProcessingEntry("qti-power"),
185
+ operatorProcessingEntry("qti-integer-divide"),
186
+ operatorProcessingEntry("qti-integer-modulus"),
187
+ operatorProcessingEntry("qti-round"),
188
+ operatorProcessingEntry("qti-round-to"),
189
+ operatorProcessingEntry("qti-truncate"),
190
+ operatorProcessingEntry("qti-integer-to-float"),
191
+ operatorProcessingEntry("qti-and"),
192
+ operatorProcessingEntry("qti-any-n"),
193
+ operatorProcessingEntry("qti-or"),
194
+ operatorProcessingEntry("qti-not"),
195
+ operatorProcessingEntry("qti-equal"),
196
+ operatorProcessingEntry("qti-equal-rounded", [
208
197
  "packages/fixtures/xml/advanced-processing-reference.xml",
209
198
  ]),
210
- processingEntry("qti-lcm", "packages/core/src/core.test.ts", [
199
+ mappingProcessingEntry("qti-field-value"),
200
+ operatorProcessingEntry("qti-lt"),
201
+ operatorProcessingEntry("qti-lte"),
202
+ operatorProcessingEntry("qti-gt"),
203
+ operatorProcessingEntry("qti-gte"),
204
+ operatorProcessingEntry("qti-string-match"),
205
+ operatorProcessingEntry("qti-substring"),
206
+ operatorProcessingEntry("qti-pattern-match"),
207
+ operatorProcessingEntry("qti-member"),
208
+ operatorProcessingEntry("qti-delete"),
209
+ operatorProcessingEntry("qti-duration-gte"),
210
+ operatorProcessingEntry("qti-duration-lt"),
211
+ operatorProcessingEntry("qti-gcd", ["packages/fixtures/xml/advanced-processing-reference.xml"]),
212
+ mappingProcessingEntry("qti-inside", ["packages/fixtures/xml/advanced-processing-reference.xml"]),
213
+ operatorProcessingEntry("qti-lcm", ["packages/fixtures/xml/advanced-processing-reference.xml"]),
214
+ operatorProcessingEntry("qti-math-constant"),
215
+ operatorProcessingEntry("qti-math-operator"),
216
+ operatorProcessingEntry("qti-repeat", [
211
217
  "packages/fixtures/xml/advanced-processing-reference.xml",
212
218
  ]),
213
- processingEntry("qti-math-constant", "packages/core/src/core.test.ts"),
214
- processingEntry("qti-math-operator", "packages/core/src/core.test.ts"),
215
- processingEntry("qti-repeat", "packages/core/src/core.test.ts", [
219
+ operatorProcessingEntry("qti-stats-operator", [
216
220
  "packages/fixtures/xml/advanced-processing-reference.xml",
217
221
  ]),
218
- processingEntry("qti-stats-operator", "packages/core/src/core.test.ts", [
219
- "packages/fixtures/xml/advanced-processing-reference.xml",
220
- ]),
221
- processingEntry("qti-custom-operator", "packages/core/src/core.test.ts"),
222
+ operatorProcessingEntry("qti-custom-operator"),
222
223
  ];
223
224
 
224
225
  export const itemMetadataSupport: QtiItemMetadataElementSupport[] = [
@@ -234,11 +235,7 @@ export const itemMetadataSupport: QtiItemMetadataElementSupport[] = [
234
235
  fixtures: [
235
236
  "packages/fixtures/packages/basic-item-player/valid-item-only/items/tolerance-extra-features.xml",
236
237
  ],
237
- tests: [
238
- "packages/core/src/core.test.ts",
239
- "packages/core/src/parser-item-metadata.test.ts",
240
- ...browserHarnessTests,
241
- ],
238
+ tests: ["packages/core/src/parser-item-metadata.test.ts", ...browserHarnessTests],
242
239
  notes:
243
240
  "Parsed by parser-item-metadata.ts and validated by validateCatalogInfo. Duplicate containers emit item.child.duplicate. Manual harness debugger coverage is in player-harness.spec.ts.",
244
241
  },
@@ -255,7 +252,6 @@ export const itemMetadataSupport: QtiItemMetadataElementSupport[] = [
255
252
  "packages/fixtures/packages/basic-item-player/valid-item-only/items/tolerance-extra-features.xml",
256
253
  ],
257
254
  tests: [
258
- "packages/core/src/core.test.ts",
259
255
  "packages/core/src/parser-item-metadata.test.ts",
260
256
  "tests/browser/player-package.spec.ts",
261
257
  ...browserHarnessTests,
@@ -266,20 +262,20 @@ export const itemMetadataSupport: QtiItemMetadataElementSupport[] = [
266
262
  {
267
263
  qtiName: "qti-modal-feedback",
268
264
  category: "itemMetadata",
269
- support: "parsed",
265
+ support: "rendered",
270
266
  specReference: "QTI 3.0.1 ASI",
271
267
  parse: true,
272
268
  validate: true,
273
- render: false,
274
- process: false,
269
+ render: true,
270
+ process: true,
275
271
  fixtures: ["packages/fixtures/src/index.ts"],
276
272
  tests: [
277
- "packages/core/src/core.test.ts",
273
+ processingResponseTest,
278
274
  "packages/core/src/parser-item-metadata.test.ts",
279
275
  ...browserFeedbackTests,
280
276
  ],
281
277
  notes:
282
- "Parsed by parser-item-metadata.ts and validated by validateModalFeedback. Player renders outcome-gated modal feedback in player-feedback.spec.ts.",
278
+ "Parsed by parser-item-metadata.ts and validated by validateModalFeedback. Response processing supplies the outcome value used for visibility, and the player renders the matching feedback in player-feedback.spec.ts.",
283
279
  },
284
280
  {
285
281
  qtiName: "qti-companion-materials-info",
@@ -430,9 +426,17 @@ function pciEntry(): QtiInteractionElementSupport {
430
426
  };
431
427
  }
432
428
 
429
+ function processingEntryFor(coreTest: string) {
430
+ return (
431
+ qtiName: string,
432
+ fixtures: string[] = [],
433
+ extraTests: string[] = [],
434
+ ): QtiProcessingElementSupport => processingEntry(coreTest, qtiName, fixtures, extraTests);
435
+ }
436
+
433
437
  function processingEntry(
438
+ coreTest: string,
434
439
  qtiName: string,
435
- test: string,
436
440
  fixtures: string[] = [],
437
441
  extraTests: string[] = [],
438
442
  ): QtiProcessingElementSupport {
@@ -446,6 +450,6 @@ function processingEntry(
446
450
  render: false,
447
451
  process: true,
448
452
  fixtures,
449
- tests: [test, ...extraTests],
453
+ tests: [coreTest, ...extraTests],
450
454
  };
451
455
  }
@@ -1,6 +1,6 @@
1
1
  import { parseQtiXml } from "./parser.js";
2
2
  import { itemExpectsAutomatedScore } from "./item-scoring-expectation.js";
3
- import { validateQtiResponseVariables } from "./response-validation.js";
3
+ import { parseQtiResponseVariables } from "./response-validation.js";
4
4
  import { createItemSession, isQtiAttemptStateV1, type QtiItemSession } from "./session.js";
5
5
  import type {
6
6
  QtiAttemptStateV1,
@@ -163,8 +163,9 @@ export function runTrustedItemSession(
163
163
 
164
164
  if (input.attemptStatus) sessionResult.session.setStatus(input.attemptStatus);
165
165
 
166
+ let submission = input.submission;
166
167
  if (input.submissionValidation === "strict") {
167
- const validation = validateQtiResponseVariables({
168
+ const validation = parseQtiResponseVariables({
168
169
  item: parsedResult.parsed.document.item,
169
170
  responses: input.submission.trustedResponses ?? {},
170
171
  allowIncompleteResponses: input.allowIncompleteResponses,
@@ -173,12 +174,13 @@ export function runTrustedItemSession(
173
174
  if (!validation.ok) {
174
175
  return emptyTrustedItemSessionFailure(validation.diagnostics);
175
176
  }
177
+ submission = { ...input.submission, trustedResponses: validation.responses };
176
178
  }
177
179
 
178
180
  const applicationResult = applyTrustedResponseApplication(
179
181
  sessionResult.session,
180
182
  parsedResult.parsed,
181
- input.submission,
183
+ submission,
182
184
  input.allowedUndeclaredResponseIdentifiers,
183
185
  input.diagnosticPrefix,
184
186
  );
package/src/types.ts CHANGED
@@ -339,6 +339,8 @@ export interface QtiTextContent {
339
339
  export interface QtiElementContent {
340
340
  kind: "element";
341
341
  qtiName: string;
342
+ /** Expanded XML namespace retained so consumers do not infer semantics from local names alone. */
343
+ namespaceUri?: string | undefined;
342
344
  attributes: Record<string, string>;
343
345
  children: QtiContentNode[];
344
346
  source?: QtiSourceLocation | undefined;
@@ -687,7 +689,14 @@ export type QtiProcessingExpression = (
687
689
  | { type: "mathConstant"; name: string }
688
690
  | { type: "mathOperator"; name: string; expressions: QtiProcessingExpression[] }
689
691
  | { type: "repeat"; numberRepeats: string; expressions: QtiProcessingExpression[] }
690
- | { type: "statsOperator"; name: string; expression: QtiProcessingExpression }
692
+ | {
693
+ type: "statsOperator";
694
+ name: string;
695
+ /** First child retained for compatibility with manually constructed expressions. */
696
+ expression: QtiProcessingExpression;
697
+ /** Authored children, including invalid zero- or multi-child forms, when parsed from XML. */
698
+ expressions?: QtiProcessingExpression[] | undefined;
699
+ }
691
700
  | {
692
701
  type: "customOperator";
693
702
  definition?: string | undefined;
@@ -0,0 +1,162 @@
1
+ import type { QtiDiagnostic, QtiLookupTable } from "./types.js";
2
+ import {
3
+ hasValidShapeCoordinateCount,
4
+ isAreaShape,
5
+ isNumericCsv,
6
+ numericCsv,
7
+ } from "./validation-geometry.js";
8
+ import { isFiniteNumber, isInteger } from "./validation-primitives.js";
9
+
10
+ interface DeclarationEntryAttributes {
11
+ attributes: Record<string, string>;
12
+ source?: QtiDiagnostic["source"] | undefined;
13
+ }
14
+
15
+ /** Append diagnostics for raw qti-map-entry attributes. */
16
+ export function validateMapEntryAttributes(
17
+ declarationIdentifier: string,
18
+ entry: DeclarationEntryAttributes,
19
+ diagnostics: QtiDiagnostic[],
20
+ ): void {
21
+ if (!entry.attributes["map-key"]) {
22
+ diagnostics.push({
23
+ code: "mapEntry.mapKey.required",
24
+ severity: "error",
25
+ message: `Response declaration ${declarationIdentifier} map entry requires map-key.`,
26
+ path: entry.source?.path,
27
+ source: entry.source,
28
+ });
29
+ }
30
+
31
+ const mappedValue = entry.attributes["mapped-value"];
32
+ if (mappedValue === undefined) {
33
+ diagnostics.push({
34
+ code: "mapEntry.mappedValue.required",
35
+ severity: "error",
36
+ message: `Response declaration ${declarationIdentifier} map entry requires mapped-value.`,
37
+ path: entry.source?.path,
38
+ source: entry.source,
39
+ });
40
+ } else if (!isFiniteNumber(mappedValue)) {
41
+ diagnostics.push({
42
+ code: "mapEntry.mappedValue",
43
+ severity: "error",
44
+ message: `Response declaration ${declarationIdentifier} map entry requires numeric mapped-value.`,
45
+ path: entry.source?.path,
46
+ source: entry.source,
47
+ });
48
+ }
49
+ }
50
+
51
+ /** Append diagnostics for raw qti-area-map-entry attributes. */
52
+ export function validateAreaMapEntryAttributes(
53
+ declarationIdentifier: string,
54
+ entry: DeclarationEntryAttributes,
55
+ diagnostics: QtiDiagnostic[],
56
+ ): void {
57
+ const shape = entry.attributes.shape;
58
+ const coords = entry.attributes.coords;
59
+ const mappedValue = entry.attributes["mapped-value"];
60
+
61
+ if (!shape) {
62
+ diagnostics.push({
63
+ code: "areaMapEntry.shape.required",
64
+ severity: "error",
65
+ message: `Response declaration ${declarationIdentifier} area map entry requires shape.`,
66
+ path: entry.source?.path,
67
+ source: entry.source,
68
+ });
69
+ } else if (!isAreaShape(shape)) {
70
+ diagnostics.push({
71
+ code: "areaMapEntry.shape",
72
+ severity: "error",
73
+ message: `Response declaration ${declarationIdentifier} area map entry has unsupported shape ${shape}.`,
74
+ path: entry.source?.path,
75
+ source: entry.source,
76
+ });
77
+ }
78
+
79
+ if (!coords) {
80
+ diagnostics.push({
81
+ code: "areaMapEntry.coords.required",
82
+ severity: "error",
83
+ message: `Response declaration ${declarationIdentifier} area map entry requires coords.`,
84
+ path: entry.source?.path,
85
+ source: entry.source,
86
+ });
87
+ } else if (!isNumericCsv(coords)) {
88
+ diagnostics.push({
89
+ code: "areaMapEntry.coords",
90
+ severity: "error",
91
+ message: `Response declaration ${declarationIdentifier} area map entry requires comma-separated numeric coords.`,
92
+ path: entry.source?.path,
93
+ source: entry.source,
94
+ });
95
+ } else if (
96
+ shape &&
97
+ isAreaShape(shape) &&
98
+ !hasValidShapeCoordinateCount(shape, numericCsv(coords))
99
+ ) {
100
+ diagnostics.push({
101
+ code: "areaMapEntry.coords.shape",
102
+ severity: "error",
103
+ message: `Response declaration ${declarationIdentifier} area map entry shape ${shape} has invalid coords arity.`,
104
+ path: entry.source?.path,
105
+ source: entry.source,
106
+ });
107
+ }
108
+
109
+ if (mappedValue === undefined) {
110
+ diagnostics.push({
111
+ code: "areaMapEntry.mappedValue.required",
112
+ severity: "error",
113
+ message: `Response declaration ${declarationIdentifier} area map entry requires mapped-value.`,
114
+ path: entry.source?.path,
115
+ source: entry.source,
116
+ });
117
+ } else if (!isFiniteNumber(mappedValue)) {
118
+ diagnostics.push({
119
+ code: "areaMapEntry.mappedValue",
120
+ severity: "error",
121
+ message: `Response declaration ${declarationIdentifier} area map entry requires numeric mapped-value.`,
122
+ path: entry.source?.path,
123
+ source: entry.source,
124
+ });
125
+ }
126
+ }
127
+
128
+ /** Append diagnostics for raw lookup-table entry attributes. */
129
+ export function validateLookupTableEntryAttributes(
130
+ tableType: QtiLookupTable["type"],
131
+ entry: DeclarationEntryAttributes,
132
+ diagnostics: QtiDiagnostic[],
133
+ ): void {
134
+ const sourceValue = entry.attributes["source-value"];
135
+ if (sourceValue === undefined || !isFiniteNumber(sourceValue)) {
136
+ diagnostics.push({
137
+ code: "lookupTable.entry.sourceValue",
138
+ severity: "error",
139
+ message: "Lookup table entry requires numeric source-value.",
140
+ path: entry.source?.path,
141
+ source: entry.source,
142
+ });
143
+ }
144
+ if (entry.attributes["target-value"] === undefined) {
145
+ diagnostics.push({
146
+ code: "lookupTable.entry.targetValue",
147
+ severity: "error",
148
+ message: "Lookup table entry requires target-value.",
149
+ path: entry.source?.path,
150
+ source: entry.source,
151
+ });
152
+ }
153
+ if (tableType === "match" && sourceValue !== undefined && !isInteger(sourceValue)) {
154
+ diagnostics.push({
155
+ code: "lookupTable.match.sourceValue",
156
+ severity: "error",
157
+ message: "qti-match-table-entry source-value must be an integer.",
158
+ path: entry.source?.path,
159
+ source: entry.source,
160
+ });
161
+ }
162
+ }