@longsightgroup/qti3-core 0.9.9 → 0.9.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/parser-processing.d.ts.map +1 -1
- package/dist/parser-processing.js +4 -0
- package/dist/parser-processing.js.map +1 -1
- package/dist/processing-expression-collection.d.ts +4 -0
- package/dist/processing-expression-collection.d.ts.map +1 -0
- package/dist/processing-expression-collection.js +44 -0
- package/dist/processing-expression-collection.js.map +1 -0
- package/dist/qti-package-assets.d.ts +3 -1
- package/dist/qti-package-assets.d.ts.map +1 -1
- package/dist/qti-package-assets.js +22 -0
- package/dist/qti-package-assets.js.map +1 -1
- package/dist/qti-package-items.d.ts +2 -1
- package/dist/qti-package-items.d.ts.map +1 -1
- package/dist/qti-package-items.js +96 -18
- package/dist/qti-package-items.js.map +1 -1
- package/dist/qti-package-manifest.d.ts.map +1 -1
- package/dist/qti-package-manifest.js +2 -0
- package/dist/qti-package-manifest.js.map +1 -1
- package/dist/qti-package-metadata.d.ts +5 -2
- package/dist/qti-package-metadata.d.ts.map +1 -1
- package/dist/qti-package-metadata.js +116 -8
- package/dist/qti-package-metadata.js.map +1 -1
- package/dist/qti-package-types.d.ts +62 -0
- package/dist/qti-package-types.d.ts.map +1 -1
- package/dist/qti-package-xml.d.ts.map +1 -1
- package/dist/qti-package-xml.js +1 -1
- package/dist/qti-package-xml.js.map +1 -1
- package/dist/qti-package.d.ts +2 -1
- package/dist/qti-package.d.ts.map +1 -1
- package/dist/qti-package.js +2 -0
- package/dist/qti-package.js.map +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +9 -0
- package/src/parser-processing.ts +4 -0
- package/src/processing-expression-collection.ts +57 -0
- package/src/qti-package-assets.ts +30 -0
- package/src/qti-package-items.ts +190 -29
- package/src/qti-package-manifest.ts +2 -0
- package/src/qti-package-metadata.ts +174 -7
- package/src/qti-package-types.ts +69 -0
- package/src/qti-package-xml.ts +2 -1
- package/src/qti-package.ts +9 -0
- package/src/types.ts +2 -0
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import type { QtiPackageXmlNode } from "./package-xml.js";
|
|
2
2
|
import { parseXmlBoolean } from "./parser-values.js";
|
|
3
|
-
import {
|
|
3
|
+
import { pushPackageDiagnostic } from "./qti-package-paths.js";
|
|
4
|
+
import { childPackageElements, packageDescendants } from "./qti-package-xml.js";
|
|
4
5
|
import type {
|
|
5
6
|
QtiAssessmentTestPackageModel,
|
|
6
7
|
QtiPackageItem,
|
|
8
|
+
QtiItemSessionControl,
|
|
7
9
|
QtiStandardAlignment,
|
|
10
|
+
QtiTimeLimits,
|
|
8
11
|
QtiTimingMetadata,
|
|
9
12
|
} from "./qti-package-types.js";
|
|
13
|
+
import type { QtiDiagnostic } from "./types.js";
|
|
10
14
|
|
|
11
15
|
/** Known QTI / IMS CP alignment element names plus attribute-driven manifest metadata. */
|
|
12
16
|
const STANDARD_ALIGNMENT_ELEMENT_NAMES = new Set([
|
|
@@ -27,18 +31,78 @@ const STANDARD_ALIGNMENT_ATTRIBUTE_NAMES = new Set([
|
|
|
27
31
|
export function parseTimingMetadata(
|
|
28
32
|
root: QtiPackageXmlNode,
|
|
29
33
|
sourcePath: string,
|
|
34
|
+
diagnostics: QtiDiagnostic[],
|
|
35
|
+
parsedTimeLimits?: QtiTimeLimits,
|
|
30
36
|
): QtiTimingMetadata | undefined {
|
|
31
|
-
const
|
|
37
|
+
const timeLimitsNode = childPackageElements(root, "qti-time-limits")[0];
|
|
38
|
+
const timeLimits = parsedTimeLimits ?? parseTimeLimits(timeLimitsNode, sourcePath, diagnostics);
|
|
32
39
|
const timeDependent = parseXmlBoolean(root.attributes["time-dependent"]);
|
|
33
|
-
if (!
|
|
40
|
+
if (!timeLimitsNode && timeDependent === undefined) return undefined;
|
|
34
41
|
|
|
35
42
|
return {
|
|
36
43
|
sourcePath,
|
|
37
44
|
timeDependent,
|
|
38
|
-
minTime:
|
|
39
|
-
maxTime:
|
|
40
|
-
allowLateSubmission:
|
|
41
|
-
attributes:
|
|
45
|
+
minTime: timeLimitsNode?.attributes["min-time"],
|
|
46
|
+
maxTime: timeLimitsNode?.attributes["max-time"],
|
|
47
|
+
allowLateSubmission: timeLimits?.allowLateSubmission,
|
|
48
|
+
attributes: timeLimitsNode ? { ...timeLimitsNode.attributes } : {},
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function parseTimeLimits(
|
|
53
|
+
node: QtiPackageXmlNode | undefined,
|
|
54
|
+
sourcePath: string,
|
|
55
|
+
diagnostics: QtiDiagnostic[],
|
|
56
|
+
): QtiTimeLimits | undefined {
|
|
57
|
+
if (!node) return undefined;
|
|
58
|
+
|
|
59
|
+
const minTimeSeconds = parseNonNegativeNumberAttribute(node, "min-time", sourcePath, diagnostics);
|
|
60
|
+
const maxTimeSeconds = parseNonNegativeNumberAttribute(node, "max-time", sourcePath, diagnostics);
|
|
61
|
+
const allowLateSubmission = parseBooleanAttribute(
|
|
62
|
+
node,
|
|
63
|
+
"allow-late-submission",
|
|
64
|
+
sourcePath,
|
|
65
|
+
diagnostics,
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
if (
|
|
69
|
+
minTimeSeconds !== undefined &&
|
|
70
|
+
maxTimeSeconds !== undefined &&
|
|
71
|
+
minTimeSeconds > maxTimeSeconds
|
|
72
|
+
) {
|
|
73
|
+
pushPackageDiagnostic(
|
|
74
|
+
diagnostics,
|
|
75
|
+
"package.timing.range.invalid",
|
|
76
|
+
"error",
|
|
77
|
+
`qti-time-limits min-time ${minTimeSeconds} exceeds max-time ${maxTimeSeconds}.`,
|
|
78
|
+
sourcePath,
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
minTimeSeconds,
|
|
84
|
+
maxTimeSeconds,
|
|
85
|
+
allowLateSubmission,
|
|
86
|
+
attributes: { ...node.attributes },
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function parseItemSessionControl(
|
|
91
|
+
node: QtiPackageXmlNode | undefined,
|
|
92
|
+
sourcePath: string,
|
|
93
|
+
diagnostics: QtiDiagnostic[],
|
|
94
|
+
): QtiItemSessionControl | undefined {
|
|
95
|
+
if (!node) return undefined;
|
|
96
|
+
|
|
97
|
+
return {
|
|
98
|
+
maxAttempts: parseNonNegativeNumberAttribute(node, "max-attempts", sourcePath, diagnostics),
|
|
99
|
+
showFeedback: parseBooleanAttribute(node, "show-feedback", sourcePath, diagnostics),
|
|
100
|
+
allowReview: parseBooleanAttribute(node, "allow-review", sourcePath, diagnostics),
|
|
101
|
+
showSolution: parseBooleanAttribute(node, "show-solution", sourcePath, diagnostics),
|
|
102
|
+
allowComment: parseBooleanAttribute(node, "allow-comment", sourcePath, diagnostics),
|
|
103
|
+
allowSkipping: parseBooleanAttribute(node, "allow-skipping", sourcePath, diagnostics),
|
|
104
|
+
validateResponses: parseBooleanAttribute(node, "validate-responses", sourcePath, diagnostics),
|
|
105
|
+
attributes: { ...node.attributes },
|
|
42
106
|
};
|
|
43
107
|
}
|
|
44
108
|
|
|
@@ -76,6 +140,52 @@ export function parseStandardAlignments(
|
|
|
76
140
|
attributes: { ...node.attributes },
|
|
77
141
|
});
|
|
78
142
|
}
|
|
143
|
+
alignments.push(...parseCurriculumStandardsMetadata(root, sourcePath));
|
|
144
|
+
return alignments;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function parseCurriculumStandardsMetadata(
|
|
148
|
+
root: QtiPackageXmlNode,
|
|
149
|
+
sourcePath: string,
|
|
150
|
+
): QtiStandardAlignment[] {
|
|
151
|
+
const alignments: QtiStandardAlignment[] = [];
|
|
152
|
+
for (const metadataSet of packageDescendants(root, "curriculumStandardsMetadataSet")) {
|
|
153
|
+
const resourceLabel = firstAttribute(metadataSet, ["resourceLabel"]);
|
|
154
|
+
const resourcePartIdentifier = firstAttribute(metadataSet, ["resourcePartId"]);
|
|
155
|
+
const weight = optionalFiniteNumber(firstAttribute(metadataSet, ["weight"]));
|
|
156
|
+
|
|
157
|
+
for (const metadata of childPackageElements(metadataSet, "curriculumStandardsMetadata")) {
|
|
158
|
+
const providerIdentifier = firstAttribute(metadata, [
|
|
159
|
+
"providerId",
|
|
160
|
+
"providerID",
|
|
161
|
+
"domainId",
|
|
162
|
+
"domainID",
|
|
163
|
+
]);
|
|
164
|
+
for (const labelledGuid of packageDescendants(metadata, "labelledGUID")) {
|
|
165
|
+
const identifier = childText(labelledGuid, "GUID");
|
|
166
|
+
const targetName = childText(labelledGuid, "label");
|
|
167
|
+
const targetUrl =
|
|
168
|
+
childText(labelledGuid, "caseItemURI") ??
|
|
169
|
+
childText(labelledGuid, "uri") ??
|
|
170
|
+
childText(labelledGuid, "URI");
|
|
171
|
+
if (!identifier && !targetName && !targetUrl) continue;
|
|
172
|
+
|
|
173
|
+
alignments.push({
|
|
174
|
+
sourcePath,
|
|
175
|
+
qtiName: "curriculumStandardsMetadata",
|
|
176
|
+
identifier,
|
|
177
|
+
targetName,
|
|
178
|
+
targetUrl,
|
|
179
|
+
text: targetName,
|
|
180
|
+
providerIdentifier,
|
|
181
|
+
resourceLabel,
|
|
182
|
+
resourcePartIdentifier,
|
|
183
|
+
weight,
|
|
184
|
+
attributes: { ...metadataSet.attributes, ...metadata.attributes },
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
79
189
|
return alignments;
|
|
80
190
|
}
|
|
81
191
|
|
|
@@ -106,6 +216,10 @@ export function uniqueStandards(
|
|
|
106
216
|
standard.targetName ?? "",
|
|
107
217
|
standard.targetUrl ?? "",
|
|
108
218
|
standard.text ?? "",
|
|
219
|
+
standard.providerIdentifier ?? "",
|
|
220
|
+
standard.resourceLabel ?? "",
|
|
221
|
+
standard.resourcePartIdentifier ?? "",
|
|
222
|
+
standard.weight?.toString() ?? "",
|
|
109
223
|
].join("\u0000");
|
|
110
224
|
if (seen.has(key)) continue;
|
|
111
225
|
seen.add(key);
|
|
@@ -114,6 +228,59 @@ export function uniqueStandards(
|
|
|
114
228
|
return unique;
|
|
115
229
|
}
|
|
116
230
|
|
|
231
|
+
function parseNonNegativeNumberAttribute(
|
|
232
|
+
node: QtiPackageXmlNode,
|
|
233
|
+
name: string,
|
|
234
|
+
sourcePath: string,
|
|
235
|
+
diagnostics: QtiDiagnostic[],
|
|
236
|
+
): number | undefined {
|
|
237
|
+
const raw = node.attributes[name];
|
|
238
|
+
if (raw === undefined) return undefined;
|
|
239
|
+
const value = Number(raw);
|
|
240
|
+
if (Number.isFinite(value) && value >= 0) return value;
|
|
241
|
+
|
|
242
|
+
pushPackageDiagnostic(
|
|
243
|
+
diagnostics,
|
|
244
|
+
`package.attribute.${name}.number`,
|
|
245
|
+
"error",
|
|
246
|
+
`${node.localName} ${name} must be a non-negative number, found ${raw}.`,
|
|
247
|
+
sourcePath,
|
|
248
|
+
);
|
|
249
|
+
return undefined;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function parseBooleanAttribute(
|
|
253
|
+
node: QtiPackageXmlNode,
|
|
254
|
+
name: string,
|
|
255
|
+
sourcePath: string,
|
|
256
|
+
diagnostics: QtiDiagnostic[],
|
|
257
|
+
): boolean | undefined {
|
|
258
|
+
const raw = node.attributes[name];
|
|
259
|
+
if (raw === undefined) return undefined;
|
|
260
|
+
const value = parseXmlBoolean(raw);
|
|
261
|
+
if (value !== undefined) return value;
|
|
262
|
+
|
|
263
|
+
pushPackageDiagnostic(
|
|
264
|
+
diagnostics,
|
|
265
|
+
`package.attribute.${name}.boolean`,
|
|
266
|
+
"error",
|
|
267
|
+
`${node.localName} ${name} must be an XML boolean, found ${raw}.`,
|
|
268
|
+
sourcePath,
|
|
269
|
+
);
|
|
270
|
+
return undefined;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function childText(node: QtiPackageXmlNode, localName: string): string | undefined {
|
|
274
|
+
const text = childPackageElements(node, localName)[0]?.text.trim();
|
|
275
|
+
return text ? text : undefined;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function optionalFiniteNumber(raw: string | undefined): number | undefined {
|
|
279
|
+
if (raw === undefined) return undefined;
|
|
280
|
+
const value = Number(raw);
|
|
281
|
+
return Number.isFinite(value) ? value : undefined;
|
|
282
|
+
}
|
|
283
|
+
|
|
117
284
|
export function primaryTiming(
|
|
118
285
|
assessmentTest: QtiAssessmentTestPackageModel | undefined,
|
|
119
286
|
items: readonly QtiPackageItem[],
|
package/src/qti-package-types.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { QtiDiagnostic, QtiDocument } from "./types.js";
|
|
2
|
+
import type { QtiPackageEntry } from "./qti-package-zip.js";
|
|
2
3
|
|
|
3
4
|
export type {
|
|
4
5
|
QtiPackageInflateContext,
|
|
@@ -31,6 +32,7 @@ export interface QtiManifestResource {
|
|
|
31
32
|
readonly href?: string | undefined;
|
|
32
33
|
readonly files: readonly QtiManifestFile[];
|
|
33
34
|
readonly dependencies: readonly string[];
|
|
35
|
+
readonly standards: readonly QtiStandardAlignment[];
|
|
34
36
|
readonly attributes: Record<string, string>;
|
|
35
37
|
}
|
|
36
38
|
|
|
@@ -44,6 +46,32 @@ export interface QtiTimingMetadata {
|
|
|
44
46
|
readonly attributes: Record<string, string>;
|
|
45
47
|
}
|
|
46
48
|
|
|
49
|
+
/** Parsed qti-time-limits attributes for one assessment-test structure node. */
|
|
50
|
+
export interface QtiTimeLimits {
|
|
51
|
+
readonly minTimeSeconds?: number | undefined;
|
|
52
|
+
readonly maxTimeSeconds?: number | undefined;
|
|
53
|
+
readonly allowLateSubmission?: boolean | undefined;
|
|
54
|
+
readonly attributes: Record<string, string>;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Parsed qti-item-session-control attributes for an assessment item reference. */
|
|
58
|
+
export interface QtiItemSessionControl {
|
|
59
|
+
readonly maxAttempts?: number | undefined;
|
|
60
|
+
readonly showFeedback?: boolean | undefined;
|
|
61
|
+
readonly allowReview?: boolean | undefined;
|
|
62
|
+
readonly showSolution?: boolean | undefined;
|
|
63
|
+
readonly allowComment?: boolean | undefined;
|
|
64
|
+
readonly allowSkipping?: boolean | undefined;
|
|
65
|
+
readonly validateResponses?: boolean | undefined;
|
|
66
|
+
readonly attributes: Record<string, string>;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Navigation mode declared by a QTI assessment-test part. */
|
|
70
|
+
export type QtiTestPartNavigationMode = "linear" | "nonlinear";
|
|
71
|
+
|
|
72
|
+
/** Submission mode declared by a QTI assessment-test part. */
|
|
73
|
+
export type QtiTestPartSubmissionMode = "individual" | "simultaneous";
|
|
74
|
+
|
|
47
75
|
/** Neutral standard-alignment metadata discovered in package XML. */
|
|
48
76
|
export interface QtiStandardAlignment {
|
|
49
77
|
readonly sourcePath: string;
|
|
@@ -53,6 +81,10 @@ export interface QtiStandardAlignment {
|
|
|
53
81
|
readonly targetName?: string | undefined;
|
|
54
82
|
readonly targetUrl?: string | undefined;
|
|
55
83
|
readonly text?: string | undefined;
|
|
84
|
+
readonly providerIdentifier?: string | undefined;
|
|
85
|
+
readonly resourceLabel?: string | undefined;
|
|
86
|
+
readonly resourcePartIdentifier?: string | undefined;
|
|
87
|
+
readonly weight?: number | undefined;
|
|
56
88
|
readonly attributes: Record<string, string>;
|
|
57
89
|
}
|
|
58
90
|
|
|
@@ -60,6 +92,33 @@ export interface QtiStandardAlignment {
|
|
|
60
92
|
export interface QtiAssessmentTestItemRef {
|
|
61
93
|
readonly identifier?: string | undefined;
|
|
62
94
|
readonly href: string;
|
|
95
|
+
readonly testPartIdentifier?: string | undefined;
|
|
96
|
+
readonly sectionIdentifier?: string | undefined;
|
|
97
|
+
readonly timeLimits?: QtiTimeLimits | undefined;
|
|
98
|
+
readonly itemSessionControl?: QtiItemSessionControl | undefined;
|
|
99
|
+
readonly attributes: Record<string, string>;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** Parsed assessment section, including nested sections and directly owned item references. */
|
|
103
|
+
export interface QtiAssessmentSectionPackageModel {
|
|
104
|
+
readonly identifier: string;
|
|
105
|
+
readonly title?: string | undefined;
|
|
106
|
+
readonly visible?: boolean | undefined;
|
|
107
|
+
readonly testPartIdentifier: string;
|
|
108
|
+
readonly parentSectionIdentifier?: string | undefined;
|
|
109
|
+
readonly timeLimits?: QtiTimeLimits | undefined;
|
|
110
|
+
readonly itemRefs: readonly QtiAssessmentTestItemRef[];
|
|
111
|
+
readonly sections: readonly QtiAssessmentSectionPackageModel[];
|
|
112
|
+
readonly attributes: Record<string, string>;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** Parsed QTI assessment-test part and its section hierarchy. */
|
|
116
|
+
export interface QtiTestPartPackageModel {
|
|
117
|
+
readonly identifier: string;
|
|
118
|
+
readonly navigationMode?: QtiTestPartNavigationMode | undefined;
|
|
119
|
+
readonly submissionMode?: QtiTestPartSubmissionMode | undefined;
|
|
120
|
+
readonly timeLimits?: QtiTimeLimits | undefined;
|
|
121
|
+
readonly sections: readonly QtiAssessmentSectionPackageModel[];
|
|
63
122
|
readonly attributes: Record<string, string>;
|
|
64
123
|
}
|
|
65
124
|
|
|
@@ -70,7 +129,9 @@ export interface QtiAssessmentTestPackageModel {
|
|
|
70
129
|
readonly title?: string | undefined;
|
|
71
130
|
readonly manifestResourceIdentifier?: string | undefined;
|
|
72
131
|
readonly itemRefs: readonly QtiAssessmentTestItemRef[];
|
|
132
|
+
readonly testParts: readonly QtiTestPartPackageModel[];
|
|
73
133
|
readonly timing?: QtiTimingMetadata | undefined;
|
|
134
|
+
readonly timeLimits?: QtiTimeLimits | undefined;
|
|
74
135
|
readonly standards: readonly QtiStandardAlignment[];
|
|
75
136
|
readonly assetHrefs: readonly string[];
|
|
76
137
|
readonly diagnostics: readonly QtiDiagnostic[];
|
|
@@ -88,6 +149,7 @@ export interface QtiPackageItem {
|
|
|
88
149
|
readonly title?: string | undefined;
|
|
89
150
|
readonly document?: QtiDocument | undefined;
|
|
90
151
|
readonly timing?: QtiTimingMetadata | undefined;
|
|
152
|
+
readonly timeLimits?: QtiTimeLimits | undefined;
|
|
91
153
|
readonly standards: readonly QtiStandardAlignment[];
|
|
92
154
|
readonly assetHrefs: readonly string[];
|
|
93
155
|
readonly diagnostics: readonly QtiDiagnostic[];
|
|
@@ -102,10 +164,17 @@ export interface QtiPackageAsset {
|
|
|
102
164
|
readonly referencedBy: readonly string[];
|
|
103
165
|
}
|
|
104
166
|
|
|
167
|
+
/** Package-local asset references discovered in one XML document. */
|
|
168
|
+
export interface QtiPackageContentAssetDiscovery {
|
|
169
|
+
readonly hrefs: readonly string[];
|
|
170
|
+
readonly diagnostics: readonly QtiDiagnostic[];
|
|
171
|
+
}
|
|
172
|
+
|
|
105
173
|
/** Parsed QTI package manifest/resource graph and item/test projection. */
|
|
106
174
|
export interface QtiPackageParseResult {
|
|
107
175
|
readonly ok: boolean;
|
|
108
176
|
readonly title: string;
|
|
177
|
+
readonly entries: readonly QtiPackageEntry[];
|
|
109
178
|
readonly packageShape: QtiPackageShape;
|
|
110
179
|
readonly items: readonly QtiPackageItem[];
|
|
111
180
|
readonly assets: readonly QtiPackageAsset[];
|
package/src/qti-package-xml.ts
CHANGED
|
@@ -88,7 +88,8 @@ export function scopeDiagnosticToPackagePath(
|
|
|
88
88
|
diagnostic: QtiDiagnostic,
|
|
89
89
|
): QtiDiagnostic {
|
|
90
90
|
const localPath = diagnostic.path ?? diagnostic.source?.path;
|
|
91
|
-
const path =
|
|
91
|
+
const path =
|
|
92
|
+
!localPath || localPath === packagePath ? packagePath : joinPackagePath(packagePath, localPath);
|
|
92
93
|
return {
|
|
93
94
|
...diagnostic,
|
|
94
95
|
path,
|
package/src/qti-package.ts
CHANGED
|
@@ -36,22 +36,30 @@ import {
|
|
|
36
36
|
import type { QtiDiagnostic } from "./types.js";
|
|
37
37
|
|
|
38
38
|
export { decodeUtf8, readQtiPackageZipEntries };
|
|
39
|
+
export { discoverQtiPackageContentAssets } from "./qti-package-assets.js";
|
|
39
40
|
export { normalizePackagePath } from "./qti-package-paths.js";
|
|
40
41
|
export { QTI_ITEM_RESOURCE_TYPE, QTI_PACKAGE_MANIFEST_PATH } from "./qti-package-manifest.js";
|
|
41
42
|
export type { QtiPackageEntry };
|
|
42
43
|
|
|
43
44
|
export type {
|
|
45
|
+
QtiAssessmentSectionPackageModel,
|
|
44
46
|
QtiAssessmentTestItemRef,
|
|
45
47
|
QtiAssessmentTestPackageModel,
|
|
46
48
|
QtiManifestFile,
|
|
47
49
|
QtiManifestResource,
|
|
48
50
|
QtiPackageAsset,
|
|
51
|
+
QtiPackageContentAssetDiscovery,
|
|
49
52
|
QtiPackageAssetSource,
|
|
50
53
|
QtiPackageItem,
|
|
51
54
|
QtiPackageItemSource,
|
|
52
55
|
QtiPackageParseResult,
|
|
53
56
|
QtiPackageShape,
|
|
57
|
+
QtiItemSessionControl,
|
|
54
58
|
QtiStandardAlignment,
|
|
59
|
+
QtiTestPartNavigationMode,
|
|
60
|
+
QtiTestPartPackageModel,
|
|
61
|
+
QtiTestPartSubmissionMode,
|
|
62
|
+
QtiTimeLimits,
|
|
55
63
|
QtiTimingMetadata,
|
|
56
64
|
} from "./qti-package-types.js";
|
|
57
65
|
|
|
@@ -159,6 +167,7 @@ function parseQtiPackageEntries(
|
|
|
159
167
|
return {
|
|
160
168
|
ok: diagnostics.every((diagnostic) => diagnostic.severity !== "error"),
|
|
161
169
|
title,
|
|
170
|
+
entries,
|
|
162
171
|
packageShape,
|
|
163
172
|
items,
|
|
164
173
|
assets,
|
package/src/types.ts
CHANGED
|
@@ -494,6 +494,8 @@ export interface QtiResponseProcessing {
|
|
|
494
494
|
template?: string | undefined;
|
|
495
495
|
rules: QtiResponseRule[];
|
|
496
496
|
conditions: QtiResponseCondition[];
|
|
497
|
+
/** Direct processing expressions retained even when they are not wrapped in a response rule. */
|
|
498
|
+
expressions?: QtiProcessingExpression[] | undefined;
|
|
497
499
|
}
|
|
498
500
|
|
|
499
501
|
export interface QtiResponseCondition {
|