@longsightgroup/qti3-migrator 0.9.6 → 0.9.8
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/README.md +54 -0
- package/dist/assets.d.ts +10 -0
- package/dist/assets.d.ts.map +1 -0
- package/dist/assets.js +19 -0
- package/dist/assets.js.map +1 -0
- package/dist/diagnostics.d.ts +2 -1
- package/dist/diagnostics.d.ts.map +1 -1
- package/dist/diagnostics.js +7 -0
- package/dist/diagnostics.js.map +1 -1
- package/dist/identifiers.d.ts +3 -0
- package/dist/identifiers.d.ts.map +1 -0
- package/dist/identifiers.js +11 -0
- package/dist/identifiers.js.map +1 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -133
- package/dist/index.js.map +1 -1
- package/dist/item-finalize.d.ts +12 -0
- package/dist/item-finalize.d.ts.map +1 -0
- package/dist/item-finalize.js +93 -0
- package/dist/item-finalize.js.map +1 -0
- package/dist/item-hrefs.d.ts +2 -0
- package/dist/item-hrefs.d.ts.map +1 -0
- package/dist/item-hrefs.js +19 -0
- package/dist/item-hrefs.js.map +1 -0
- package/dist/migrate-items.d.ts +6 -0
- package/dist/migrate-items.d.ts.map +1 -0
- package/dist/migrate-items.js +31 -0
- package/dist/migrate-items.js.map +1 -0
- package/dist/package-result.d.ts +12 -0
- package/dist/package-result.d.ts.map +1 -0
- package/dist/package-result.js +109 -0
- package/dist/package-result.js.map +1 -0
- package/dist/paths.d.ts +4 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +16 -0
- package/dist/paths.js.map +1 -0
- package/dist/resource-migration.d.ts +4 -0
- package/dist/resource-migration.d.ts.map +1 -0
- package/dist/resource-migration.js +128 -0
- package/dist/resource-migration.js.map +1 -0
- package/dist/source.d.ts +5 -0
- package/dist/source.d.ts.map +1 -1
- package/dist/source.js +26 -6
- package/dist/source.js.map +1 -1
- package/dist/types.d.ts +43 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/assets.ts +23 -0
- package/src/diagnostics.ts +12 -0
- package/src/identifiers.ts +12 -0
- package/src/index.ts +45 -176
- package/src/item-finalize.ts +133 -0
- package/src/item-hrefs.ts +23 -0
- package/src/migrate-items.ts +39 -0
- package/src/package-result.ts +157 -0
- package/src/paths.ts +33 -0
- package/src/resource-migration.ts +197 -0
- package/src/source.ts +40 -6
- package/src/types.ts +53 -1
package/README.md
CHANGED
|
@@ -10,4 +10,58 @@ import { migrateQtiToQti3 } from "@longsightgroup/qti3-migrator";
|
|
|
10
10
|
const result = await migrateQtiToQti3({ filename: "quiz.zip", bytes });
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
+
Use `migrateQtiToQti3Package` for complete legacy QTI packages when the output should be passed directly to
|
|
14
|
+
`@longsightgroup/qti3-writer` package APIs. Package migration preserves manifest item and asset
|
|
15
|
+
paths from the source package:
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { migrateQtiToQti3Package } from "@longsightgroup/qti3-migrator";
|
|
19
|
+
import { writeQti3PackageZipResult } from "@longsightgroup/qti3-writer";
|
|
20
|
+
|
|
21
|
+
const migrated = await migrateQtiToQti3Package({ filename: "quiz.zip", bytes });
|
|
22
|
+
|
|
23
|
+
if (migrated.ok) {
|
|
24
|
+
const qti3Package = writeQti3PackageZipResult(migrated.package);
|
|
25
|
+
console.log(qti3Package);
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Use `migrateQtiResourceToQti3` when a host package, such as IMS Common Cartridge, has already
|
|
30
|
+
identified one QTI resource and can provide that resource's local file closure. The result includes
|
|
31
|
+
launchable QTI 3 package entries, a `launchHref`, item hrefs, and diagnostics:
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
import { migrateQtiResourceToQti3 } from "@longsightgroup/qti3-migrator";
|
|
35
|
+
|
|
36
|
+
const migrated = await migrateQtiResourceToQti3({
|
|
37
|
+
sourcePath: "assessment/quiz.xml",
|
|
38
|
+
files: {
|
|
39
|
+
"assessment/quiz.xml": quizXmlBytes,
|
|
40
|
+
"assessment/map.png": mapPngBytes,
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
if (migrated.ok) {
|
|
45
|
+
console.log(migrated.title);
|
|
46
|
+
console.log(migrated.launchHref);
|
|
47
|
+
console.log(migrated.entries);
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
`files` is the local file closure for one IMS Common Cartridge QTI resource: keys are package-relative
|
|
52
|
+
paths within that resource, backslashes are normalized to forward slashes, and `sourcePath` must match
|
|
53
|
+
one of those keys after normalization. On success, `entries` is a standalone QTI 3 package file set
|
|
54
|
+
rooted at `imsmanifest.xml`; the caller decides where to store or repackage those files.
|
|
55
|
+
|
|
56
|
+
QTI 1.2 XML resources that contain multiple `<item>` elements are emitted as stable sibling item
|
|
57
|
+
paths so package output does not duplicate item paths while source-relative asset references keep the
|
|
58
|
+
same base directory.
|
|
59
|
+
|
|
60
|
+
Resource migration attaches every non-XML file in the provided closure to each migrated item. The
|
|
61
|
+
writer emits shared asset paths once when the referenced bytes are identical across items.
|
|
62
|
+
|
|
13
63
|
Defaults are strict: source repair is disabled and unsupported interactions are reported as diagnostics instead of silently converted.
|
|
64
|
+
|
|
65
|
+
QTI assessment-test structure preservation is not implemented yet. When a legacy package contains an
|
|
66
|
+
assessment-test resource, migration returns a flat review part and reports
|
|
67
|
+
`assessment_test_structure_not_migrated`.
|
package/dist/assets.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { MigrationEntry } from "./source.js";
|
|
2
|
+
import type { QtiMigrationAsset } from "./types.js";
|
|
3
|
+
export declare function migrationPackageAssets(entries: readonly MigrationEntry[]): QtiMigrationAsset[];
|
|
4
|
+
/**
|
|
5
|
+
* Asset hrefs for resource-level migration. Every migrated item receives the full non-XML file
|
|
6
|
+
* closure so host-provided dependencies remain available regardless of which sibling item references
|
|
7
|
+
* them.
|
|
8
|
+
*/
|
|
9
|
+
export declare function resourceClosureAssetHrefs(entries: readonly MigrationEntry[]): readonly string[];
|
|
10
|
+
//# sourceMappingURL=assets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../src/assets.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,SAAS,cAAc,EAAE,GAAG,iBAAiB,EAAE,CAQ9F;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,SAAS,cAAc,EAAE,GAAG,SAAS,MAAM,EAAE,CAE/F"}
|
package/dist/assets.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { detectPackageMediaType } from "@longsightgroup/qti3-core";
|
|
2
|
+
export function migrationPackageAssets(entries) {
|
|
3
|
+
return entries
|
|
4
|
+
.filter((entry) => !entry.path.toLowerCase().endsWith(".xml"))
|
|
5
|
+
.map((entry) => ({
|
|
6
|
+
path: entry.path,
|
|
7
|
+
data: entry.bytes,
|
|
8
|
+
mediaType: detectPackageMediaType(entry.path),
|
|
9
|
+
}));
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Asset hrefs for resource-level migration. Every migrated item receives the full non-XML file
|
|
13
|
+
* closure so host-provided dependencies remain available regardless of which sibling item references
|
|
14
|
+
* them.
|
|
15
|
+
*/
|
|
16
|
+
export function resourceClosureAssetHrefs(entries) {
|
|
17
|
+
return migrationPackageAssets(entries).map((asset) => asset.path);
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=assets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assets.js","sourceRoot":"","sources":["../src/assets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAKnE,MAAM,UAAU,sBAAsB,CAAC,OAAkC;IACvE,OAAO,OAAO;SACX,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;SAC7D,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACf,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,IAAI,EAAE,KAAK,CAAC,KAAK;QACjB,SAAS,EAAE,sBAAsB,CAAC,KAAK,CAAC,IAAI,CAAC;KAC9C,CAAC,CAAC,CAAC;AACR,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,yBAAyB,CAAC,OAAkC;IAC1E,OAAO,sBAAsB,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AACpE,CAAC"}
|
package/dist/diagnostics.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import type { QtiMigrationDiagnostic, QtiMigrationDiagnosticSeverity, QtiMigrationSourceFormat } from "./types.js";
|
|
1
|
+
import type { QtiMigrationDiagnostic, QtiMigrationDiagnosticSeverity, QtiMigrationResult, QtiMigrationSourceFormat } from "./types.js";
|
|
2
2
|
export declare function diagnostic(code: string, severity: QtiMigrationDiagnosticSeverity, message: string, options?: {
|
|
3
3
|
readonly path?: string | undefined;
|
|
4
4
|
readonly sourceFormat?: QtiMigrationSourceFormat | undefined;
|
|
5
5
|
}): QtiMigrationDiagnostic;
|
|
6
6
|
export declare function hasErrors(diagnostics: readonly QtiMigrationDiagnostic[]): boolean;
|
|
7
|
+
export declare function aggregateMigrationDiagnostics(migration: QtiMigrationResult, extraDiagnostics?: readonly QtiMigrationDiagnostic[]): readonly QtiMigrationDiagnostic[];
|
|
7
8
|
//# sourceMappingURL=diagnostics.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../src/diagnostics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,sBAAsB,EACtB,8BAA8B,EAC9B,wBAAwB,EACzB,MAAM,YAAY,CAAC;AAEpB,wBAAgB,UAAU,CACxB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,8BAA8B,EACxC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;IACP,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,QAAQ,CAAC,YAAY,CAAC,EAAE,wBAAwB,GAAG,SAAS,CAAC;CACzD,GACL,sBAAsB,CAExB;AAED,wBAAgB,SAAS,CAAC,WAAW,EAAE,SAAS,sBAAsB,EAAE,GAAG,OAAO,CAEjF"}
|
|
1
|
+
{"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../src/diagnostics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,sBAAsB,EACtB,8BAA8B,EAC9B,kBAAkB,EAClB,wBAAwB,EACzB,MAAM,YAAY,CAAC;AAEpB,wBAAgB,UAAU,CACxB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,8BAA8B,EACxC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;IACP,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,QAAQ,CAAC,YAAY,CAAC,EAAE,wBAAwB,GAAG,SAAS,CAAC;CACzD,GACL,sBAAsB,CAExB;AAED,wBAAgB,SAAS,CAAC,WAAW,EAAE,SAAS,sBAAsB,EAAE,GAAG,OAAO,CAEjF;AAED,wBAAgB,6BAA6B,CAC3C,SAAS,EAAE,kBAAkB,EAC7B,gBAAgB,GAAE,SAAS,sBAAsB,EAAO,GACvD,SAAS,sBAAsB,EAAE,CAMnC"}
|
package/dist/diagnostics.js
CHANGED
|
@@ -4,4 +4,11 @@ export function diagnostic(code, severity, message, options = {}) {
|
|
|
4
4
|
export function hasErrors(diagnostics) {
|
|
5
5
|
return diagnostics.some((entry) => entry.severity === "error");
|
|
6
6
|
}
|
|
7
|
+
export function aggregateMigrationDiagnostics(migration, extraDiagnostics = []) {
|
|
8
|
+
return [
|
|
9
|
+
...migration.diagnostics,
|
|
10
|
+
...migration.items.flatMap((item) => item.diagnostics),
|
|
11
|
+
...extraDiagnostics,
|
|
12
|
+
];
|
|
13
|
+
}
|
|
7
14
|
//# sourceMappingURL=diagnostics.js.map
|
package/dist/diagnostics.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diagnostics.js","sourceRoot":"","sources":["../src/diagnostics.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"diagnostics.js","sourceRoot":"","sources":["../src/diagnostics.ts"],"names":[],"mappings":"AAOA,MAAM,UAAU,UAAU,CACxB,IAAY,EACZ,QAAwC,EACxC,OAAe,EACf,UAGI,EAAE;IAEN,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,WAA8C;IACtE,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,6BAA6B,CAC3C,SAA6B,EAC7B,mBAAsD,EAAE;IAExD,OAAO;QACL,GAAG,SAAS,CAAC,WAAW;QACxB,GAAG,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC;QACtD,GAAG,gBAAgB;KACpB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identifiers.d.ts","sourceRoot":"","sources":["../src/identifiers.ts"],"names":[],"mappings":"AAAA,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhE"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export function migrationPathIdentifier(path) {
|
|
2
|
+
return sanitizeMigrationIdentifier(path, "ITEM", "ITEM");
|
|
3
|
+
}
|
|
4
|
+
export function migrationPackageIdentifier(title) {
|
|
5
|
+
return sanitizeMigrationIdentifier(title, "PACKAGE", "PACKAGE");
|
|
6
|
+
}
|
|
7
|
+
function sanitizeMigrationIdentifier(value, fallback, prefix) {
|
|
8
|
+
const normalized = value.replace(/\.[^.]+$/, "").replace(/[^A-Za-z0-9_]/g, "_") || fallback;
|
|
9
|
+
return /^[A-Za-z_]/.test(normalized) ? normalized : `${prefix}_${normalized}`;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=identifiers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identifiers.js","sourceRoot":"","sources":["../src/identifiers.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,uBAAuB,CAAC,IAAY;IAClD,OAAO,2BAA2B,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,KAAa;IACtD,OAAO,2BAA2B,CAAC,KAAK,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;AAClE,CAAC;AAED,SAAS,2BAA2B,CAAC,KAAa,EAAE,QAAgB,EAAE,MAAc;IAClF,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,gBAAgB,EAAE,GAAG,CAAC,IAAI,QAAQ,CAAC;IAC5F,OAAO,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,UAAU,EAAE,CAAC;AAChF,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import { migrateQtiResourceToQti3 } from "./resource-migration.js";
|
|
1
2
|
import { detectQtiMigrationSource } from "./source.js";
|
|
2
|
-
import type { QtiMigrationItemResult, QtiMigrationOptions, QtiMigrationResult, QtiMigrationSourceInput } from "./types.js";
|
|
3
|
-
export { detectQtiMigrationSource };
|
|
4
|
-
export type { QtiMigrationAsset, QtiMigrationDetectionResult, QtiMigrationDiagnostic, QtiMigrationDiagnosticSeverity, QtiMigrationItemResult, QtiMigrationOptions, QtiMigrationPart, QtiMigrationRepairPolicy, QtiMigrationResult, QtiMigrationSourceFormat, QtiMigrationSourceInput, QtiMigrationUnsupportedPolicy, } from "./types.js";
|
|
3
|
+
import type { QtiMigrationItemResult, QtiMigrationOptions, QtiMigrationResult, QtiMigrationSourceInput, QtiPackageMigrationResult } from "./types.js";
|
|
4
|
+
export { detectQtiMigrationSource, migrateQtiResourceToQti3 };
|
|
5
|
+
export type { QtiMigrationAsset, QtiMigrationDetectionResult, QtiMigrationDiagnostic, QtiMigrationDiagnosticSeverity, QtiMigrationItemResult, QtiMigrationOptions, QtiPackageMigrationResult, QtiMigrationPart, QtiMigrationResourceEntry, QtiMigrationResourceInput, QtiMigrationRepairPolicy, QtiMigrationResult, QtiMigrationSourceFormat, QtiMigrationSourceInput, QtiMigrationUnsupportedPolicy, QtiResourceMigrationResult, QtiResourceMigrationStatus, } from "./types.js";
|
|
5
6
|
export declare function migrateQtiToQti3(input: QtiMigrationSourceInput, options?: QtiMigrationOptions): Promise<QtiMigrationResult>;
|
|
7
|
+
export declare function migrateQtiToQti3Package(input: QtiMigrationSourceInput, options?: QtiMigrationOptions): Promise<QtiPackageMigrationResult>;
|
|
6
8
|
export declare function migrateQtiItemToQti3(input: QtiMigrationSourceInput, options?: QtiMigrationOptions): QtiMigrationItemResult;
|
|
7
9
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAEL,wBAAwB,EAIzB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAGV,sBAAsB,EACtB,mBAAmB,EAEnB,kBAAkB,EAClB,uBAAuB,EACvB,yBAAyB,EAC1B,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,CAAC;AAC9D,YAAY,EACV,iBAAiB,EACjB,2BAA2B,EAC3B,sBAAsB,EACtB,8BAA8B,EAC9B,sBAAsB,EACtB,mBAAmB,EACnB,yBAAyB,EACzB,gBAAgB,EAChB,yBAAyB,EACzB,yBAAyB,EACzB,wBAAwB,EACxB,kBAAkB,EAClB,wBAAwB,EACxB,uBAAuB,EACvB,6BAA6B,EAC7B,0BAA0B,EAC1B,0BAA0B,GAC3B,MAAM,YAAY,CAAC;AAEpB,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,uBAAuB,EAC9B,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,kBAAkB,CAAC,CA4B7B;AAED,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,uBAAuB,EAC9B,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,yBAAyB,CAAC,CAGpC;AAED,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,uBAAuB,EAC9B,OAAO,GAAE,mBAAwB,GAChC,sBAAsB,CA8CxB"}
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { diagnostic } from "./diagnostics.js";
|
|
2
|
+
import { migrationPathIdentifier } from "./identifiers.js";
|
|
3
|
+
import { finalizeItemResult, finalizeItemResults } from "./item-finalize.js";
|
|
4
|
+
import { migrateItemXml } from "./migrate-items.js";
|
|
5
|
+
import { migrationPackageAssets } from "./assets.js";
|
|
4
6
|
import { resolveOptions } from "./options.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
+
import { migrationResultToPackage } from "./package-result.js";
|
|
8
|
+
import { migrateQtiResourceToQti3 } from "./resource-migration.js";
|
|
7
9
|
import { detectMigrationSource, detectQtiMigrationSource, parseLegacyManifest, readMigrationSource, } from "./source.js";
|
|
8
|
-
export { detectQtiMigrationSource };
|
|
10
|
+
export { detectQtiMigrationSource, migrateQtiResourceToQti3 };
|
|
9
11
|
export async function migrateQtiToQti3(input, options = {}) {
|
|
10
12
|
const resolvedOptions = resolveOptions(options);
|
|
11
13
|
const source = readMigrationSource(input);
|
|
@@ -29,6 +31,10 @@ export async function migrateQtiToQti3(input, options = {}) {
|
|
|
29
31
|
: migrateItemSource(source, detection, resolvedOptions);
|
|
30
32
|
return Promise.resolve(migrated);
|
|
31
33
|
}
|
|
34
|
+
export async function migrateQtiToQti3Package(input, options = {}) {
|
|
35
|
+
const migration = await migrateQtiToQti3(input, options);
|
|
36
|
+
return migrationResultToPackage(migration);
|
|
37
|
+
}
|
|
32
38
|
export function migrateQtiItemToQti3(input, options = {}) {
|
|
33
39
|
const resolvedOptions = resolveOptions(options);
|
|
34
40
|
const source = readMigrationSource(input);
|
|
@@ -85,6 +91,12 @@ function migratePackageSource(source, detection, options) {
|
|
|
85
91
|
diagnostics.push(diagnostic("assessment_test_structure_not_migrated", "warning", "QTI assessment-test structure is not migrated yet; items are returned in a flat review part.", { sourceFormat, path: "imsmanifest.xml" }));
|
|
86
92
|
}
|
|
87
93
|
const entriesByPath = new Map(source.entries.map((entry) => [entry.path, entry]));
|
|
94
|
+
const assetHrefsByItemHref = new Map();
|
|
95
|
+
for (const resource of manifest.resources) {
|
|
96
|
+
if (!resource.href)
|
|
97
|
+
continue;
|
|
98
|
+
assetHrefsByItemHref.set(resource.href, resource.files.filter((file) => file !== resource.href && !file.toLowerCase().endsWith(".xml")));
|
|
99
|
+
}
|
|
88
100
|
const itemHrefs = manifest.itemHrefs.length
|
|
89
101
|
? manifest.itemHrefs
|
|
90
102
|
: source.entries
|
|
@@ -95,7 +107,7 @@ function migratePackageSource(source, detection, options) {
|
|
|
95
107
|
const entry = entriesByPath.get(href) ?? entriesByPath.get(href.replace(/^\.\//, ""));
|
|
96
108
|
if (!entry?.text) {
|
|
97
109
|
items.push({
|
|
98
|
-
identifier:
|
|
110
|
+
identifier: migrationPathIdentifier(href),
|
|
99
111
|
title: href,
|
|
100
112
|
href,
|
|
101
113
|
diagnostics: [
|
|
@@ -107,9 +119,9 @@ function migratePackageSource(source, detection, options) {
|
|
|
107
119
|
});
|
|
108
120
|
continue;
|
|
109
121
|
}
|
|
110
|
-
const migratedItems = migrateItemXml(entry.text, href, sourceFormat, options);
|
|
122
|
+
const migratedItems = finalizeItemResults(migrateItemXml(entry.text, href, sourceFormat, options), href, options);
|
|
111
123
|
for (const item of migratedItems) {
|
|
112
|
-
items.push(
|
|
124
|
+
items.push({ ...item, assetHrefs: assetHrefsByItemHref.get(href) ?? [] });
|
|
113
125
|
}
|
|
114
126
|
}
|
|
115
127
|
return {
|
|
@@ -117,14 +129,15 @@ function migratePackageSource(source, detection, options) {
|
|
|
117
129
|
sourceFormat,
|
|
118
130
|
parts: [partFromItems("PART_1", manifest.title, items)],
|
|
119
131
|
items,
|
|
120
|
-
assets:
|
|
132
|
+
assets: migrationPackageAssets(source.entries),
|
|
121
133
|
diagnostics,
|
|
122
134
|
};
|
|
123
135
|
}
|
|
124
136
|
function migrateItemSource(source, detection, options) {
|
|
125
137
|
const sourceFormat = detection.sourceFormat;
|
|
126
138
|
const xml = source.xml ?? "";
|
|
127
|
-
const
|
|
139
|
+
const href = source.filename ?? "item.xml";
|
|
140
|
+
const migratedItems = finalizeItemResults(migrateItemXml(xml, href, sourceFormat, options), href, options);
|
|
128
141
|
return {
|
|
129
142
|
title: migratedItems[0]?.title ?? source.filename ?? "Imported QTI Item",
|
|
130
143
|
sourceFormat,
|
|
@@ -134,129 +147,7 @@ function migrateItemSource(source, detection, options) {
|
|
|
134
147
|
diagnostics: [],
|
|
135
148
|
};
|
|
136
149
|
}
|
|
137
|
-
function migrateItemXml(xml, path, sourceFormat, options) {
|
|
138
|
-
if (sourceFormat === "qti12") {
|
|
139
|
-
return migrateQti12Xml(xml, path, options).map((result, index) => ({
|
|
140
|
-
identifier: result.authoringItem?.identifier ?? `ITEM_${index + 1}`,
|
|
141
|
-
title: result.authoringItem?.title ?? itemTitleFromXmlSafe(xml),
|
|
142
|
-
authoringItem: result.authoringItem,
|
|
143
|
-
diagnostics: result.diagnostics,
|
|
144
|
-
}));
|
|
145
|
-
}
|
|
146
|
-
const result = migrateQti2ItemXml(xml, path, sourceFormat, options);
|
|
147
|
-
return [
|
|
148
|
-
{
|
|
149
|
-
identifier: result.authoringItem?.identifier ?? pathIdentifier(path),
|
|
150
|
-
title: result.authoringItem?.title ?? itemTitleFromXmlSafe(xml),
|
|
151
|
-
authoringItem: result.authoringItem,
|
|
152
|
-
diagnostics: result.diagnostics,
|
|
153
|
-
},
|
|
154
|
-
];
|
|
155
|
-
}
|
|
156
|
-
function finalizeItemResult(pending, href, options) {
|
|
157
|
-
const diagnostics = [...pending.diagnostics];
|
|
158
|
-
if (pending.authoringItem && !hasErrors(diagnostics)) {
|
|
159
|
-
const writer = writeQti3AssessmentItemResult(pending.authoringItem);
|
|
160
|
-
if (writer.ok) {
|
|
161
|
-
diagnostics.push(...validateWrittenXml(writer.xml));
|
|
162
|
-
return {
|
|
163
|
-
identifier: pending.identifier,
|
|
164
|
-
title: pending.title,
|
|
165
|
-
href,
|
|
166
|
-
authoringItem: pending.authoringItem,
|
|
167
|
-
xml: writer.xml,
|
|
168
|
-
diagnostics,
|
|
169
|
-
};
|
|
170
|
-
}
|
|
171
|
-
diagnostics.push({
|
|
172
|
-
code: "writer_diagnostics",
|
|
173
|
-
severity: "error",
|
|
174
|
-
message: "QTI 3 writer rejected migrated authoring item.",
|
|
175
|
-
writerDiagnostics: writer.diagnostics,
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
|
-
if (options.unsupportedPolicy === "stub") {
|
|
179
|
-
const stub = stubItem(pending.identifier, pending.title);
|
|
180
|
-
const writer = writeQti3AssessmentItemResult(stub);
|
|
181
|
-
return {
|
|
182
|
-
identifier: pending.identifier,
|
|
183
|
-
title: pending.title,
|
|
184
|
-
href,
|
|
185
|
-
authoringItem: stub,
|
|
186
|
-
xml: writer.ok ? writer.xml : undefined,
|
|
187
|
-
diagnostics: [
|
|
188
|
-
...diagnostics,
|
|
189
|
-
diagnostic("unsupported_item_stubbed", "warning", "Unsupported item migrated as an extended-text review stub."),
|
|
190
|
-
],
|
|
191
|
-
};
|
|
192
|
-
}
|
|
193
|
-
return {
|
|
194
|
-
identifier: pending.identifier,
|
|
195
|
-
title: pending.title,
|
|
196
|
-
href,
|
|
197
|
-
authoringItem: options.unsupportedPolicy === "skip" ? undefined : pending.authoringItem,
|
|
198
|
-
diagnostics,
|
|
199
|
-
};
|
|
200
|
-
}
|
|
201
|
-
function validateWrittenXml(xml) {
|
|
202
|
-
const parsed = parseQtiXml(xml);
|
|
203
|
-
const diagnostics = [];
|
|
204
|
-
if (!parsed.ok || !parsed.document) {
|
|
205
|
-
diagnostics.push(...coreDiagnostics("core_parse", parsed.diagnostics));
|
|
206
|
-
return diagnostics;
|
|
207
|
-
}
|
|
208
|
-
const validation = validateAssessmentItem(parsed.document);
|
|
209
|
-
if (!validation.ok)
|
|
210
|
-
diagnostics.push(...coreDiagnostics("core_validate", validation.diagnostics));
|
|
211
|
-
return diagnostics;
|
|
212
|
-
}
|
|
213
|
-
function coreDiagnostics(prefix, diagnostics) {
|
|
214
|
-
return diagnostics.map((entry) => diagnostic(`${prefix}.${entry.code}`, entry.severity === "error" ? "error" : "warning", entry.message));
|
|
215
|
-
}
|
|
216
|
-
function stubItem(identifier, title) {
|
|
217
|
-
return {
|
|
218
|
-
interactionType: "extendedText",
|
|
219
|
-
identifier,
|
|
220
|
-
title,
|
|
221
|
-
bodyHtml: qti3TrustedXmlFragment("<p>This item requires manual migration review.</p>"),
|
|
222
|
-
responseIdentifier: "RESPONSE",
|
|
223
|
-
responseBaseType: "string",
|
|
224
|
-
responseCardinality: "single",
|
|
225
|
-
expectedLines: 6,
|
|
226
|
-
};
|
|
227
|
-
}
|
|
228
|
-
function packageAssets(entries) {
|
|
229
|
-
return entries
|
|
230
|
-
.filter((entry) => !entry.path.toLowerCase().endsWith(".xml"))
|
|
231
|
-
.map((entry) => ({ path: entry.path, data: entry.bytes, mediaType: mediaType(entry.path) }));
|
|
232
|
-
}
|
|
233
150
|
function partFromItems(identifier, title, items) {
|
|
234
151
|
return { identifier, title, itemHrefs: items.map((item) => item.href) };
|
|
235
152
|
}
|
|
236
|
-
function pathIdentifier(path) {
|
|
237
|
-
return path.replace(/\.[^.]+$/, "").replace(/[^A-Za-z0-9_]/g, "_") || "ITEM";
|
|
238
|
-
}
|
|
239
|
-
function itemTitleFromXmlSafe(xml) {
|
|
240
|
-
try {
|
|
241
|
-
return itemTitleFromXml(xml);
|
|
242
|
-
}
|
|
243
|
-
catch {
|
|
244
|
-
return "Imported Item";
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
function mediaType(path) {
|
|
248
|
-
if (/\.png$/i.test(path))
|
|
249
|
-
return "image/png";
|
|
250
|
-
if (/\.jpe?g$/i.test(path))
|
|
251
|
-
return "image/jpeg";
|
|
252
|
-
if (/\.gif$/i.test(path))
|
|
253
|
-
return "image/gif";
|
|
254
|
-
if (/\.svg$/i.test(path))
|
|
255
|
-
return "image/svg+xml";
|
|
256
|
-
if (/\.mp3$/i.test(path))
|
|
257
|
-
return "audio/mpeg";
|
|
258
|
-
if (/\.mp4$/i.test(path))
|
|
259
|
-
return "video/mp4";
|
|
260
|
-
return undefined;
|
|
261
|
-
}
|
|
262
153
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EACL,qBAAqB,EACrB,wBAAwB,EACxB,mBAAmB,EACnB,mBAAmB,GAEpB,MAAM,aAAa,CAAC;AAYrB,OAAO,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,CAAC;AAqB9D,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,KAA8B,EAC9B,UAA+B,EAAE;IAEjC,MAAM,eAAe,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;IAChD,MAAM,MAAM,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC;IAC1C,MAAM,SAAS,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAChD,IAAI,CAAC,SAAS,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,CAAC;QACpD,OAAO;YACL,KAAK,EAAE,KAAK,CAAC,QAAQ,IAAI,cAAc;YACvC,YAAY,EAAE,SAAS,CAAC,YAAY;YACpC,KAAK,EAAE,EAAE;YACT,KAAK,EAAE,EAAE;YACT,MAAM,EAAE,EAAE;YACV,WAAW,EAAE;gBACX,UAAU,CACR,oBAAoB,EACpB,OAAO,EACP,qCAAqC,SAAS,CAAC,MAAM,GAAG,EACxD;oBACE,YAAY,EAAE,SAAS,CAAC,YAAY;iBACrC,CACF;aACF;SACF,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAS;QAC/B,CAAC,CAAC,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,eAAe,CAAC;QAC1D,CAAC,CAAC,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,eAAe,CAAC,CAAC;IAC1D,OAAO,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,KAA8B,EAC9B,UAA+B,EAAE;IAEjC,MAAM,SAAS,GAAG,MAAM,gBAAgB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACzD,OAAO,wBAAwB,CAAC,SAAS,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,KAA8B,EAC9B,UAA+B,EAAE;IAEjC,MAAM,eAAe,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;IAChD,MAAM,MAAM,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC;IAC1C,MAAM,SAAS,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAChD,IAAI,CAAC,SAAS,CAAC,YAAY,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;QAC3C,OAAO;YACL,UAAU,EAAE,MAAM;YAClB,KAAK,EAAE,KAAK,CAAC,QAAQ,IAAI,eAAe;YACxC,IAAI,EAAE,UAAU;YAChB,WAAW,EAAE;gBACX,UAAU,CACR,qBAAqB,EACrB,OAAO,EACP,+CAA+C,EAC/C;oBACE,YAAY,EAAE,SAAS,CAAC,YAAY;iBACrC,CACF;aACF;SACF,CAAC;IACJ,CAAC;IACD,MAAM,OAAO,GAAG,cAAc,CAC5B,MAAM,CAAC,GAAG,EACV,KAAK,CAAC,QAAQ,IAAI,UAAU,EAC5B,SAAS,CAAC,YAAY,EACtB,eAAe,CAChB,CAAC;IACF,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAC1B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO;YACL,UAAU,EAAE,MAAM;YAClB,KAAK,EAAE,KAAK,CAAC,QAAQ,IAAI,eAAe;YACxC,IAAI,EAAE,UAAU;YAChB,WAAW,EAAE;gBACX,UAAU,CACR,sBAAsB,EACtB,OAAO,EACP,8CAA8C,EAC9C;oBACE,YAAY,EAAE,SAAS,CAAC,YAAY;iBACrC,CACF;aACF;SACF,CAAC;IACJ,CAAC;IACD,OAAO,kBAAkB,CAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,IAAI,GAAG,MAAM,CAAC,UAAU,MAAM,EAAE,eAAe,CAAC,CAAC;AACnG,CAAC;AAED,SAAS,oBAAoB,CAC3B,MAAuB,EACvB,SAAsC,EACtC,OAA0C;IAE1C,MAAM,YAAY,GAAG,SAAS,CAAC,YAAa,CAAC;IAC7C,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CACvC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,iBAAiB,CAC1D,CAAC;IACF,MAAM,WAAW,GAA6B,EAAE,CAAC;IACjD,IAAI,CAAC,aAAa,EAAE,IAAI,EAAE,CAAC;QACzB,WAAW,CAAC,IAAI,CACd,UAAU,CAAC,kBAAkB,EAAE,OAAO,EAAE,yCAAyC,EAAE;YACjF,YAAY;YACZ,IAAI,EAAE,iBAAiB;SACxB,CAAC,CACH,CAAC;QACF,OAAO;YACL,KAAK,EAAE,MAAM,CAAC,QAAQ,IAAI,sBAAsB;YAChD,YAAY;YACZ,KAAK,EAAE,EAAE;YACT,KAAK,EAAE,EAAE;YACT,MAAM,EAAE,EAAE;YACV,WAAW;SACZ,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,mBAAmB,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IACzD,WAAW,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,CAAC;IACvF,IAAI,QAAQ,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;QAC9B,WAAW,CAAC,IAAI,CACd,UAAU,CACR,wCAAwC,EACxC,SAAS,EACT,8FAA8F,EAC9F,EAAE,YAAY,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAC1C,CACF,CAAC;IACJ,CAAC;IACD,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IAClF,MAAM,oBAAoB,GAAG,IAAI,GAAG,EAA6B,CAAC;IAClE,KAAK,MAAM,QAAQ,IAAI,QAAQ,CAAC,SAAS,EAAE,CAAC;QAC1C,IAAI,CAAC,QAAQ,CAAC,IAAI;YAAE,SAAS;QAC7B,oBAAoB,CAAC,GAAG,CACtB,QAAQ,CAAC,IAAI,EACb,QAAQ,CAAC,KAAK,CAAC,MAAM,CACnB,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,QAAQ,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CACzE,CACF,CAAC;IACJ,CAAC;IACD,MAAM,SAAS,GAAG,QAAQ,CAAC,SAAS,CAAC,MAAM;QACzC,CAAC,CAAC,QAAQ,CAAC,SAAS;QACpB,CAAC,CAAC,MAAM,CAAC,OAAO;aACX,MAAM,CACL,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,iBAAiB,CACzF;aACA,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,KAAK,GAA6B,EAAE,CAAC;IAC3C,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;QACtF,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC;YACjB,KAAK,CAAC,IAAI,CAAC;gBACT,UAAU,EAAE,uBAAuB,CAAC,IAAI,CAAC;gBACzC,KAAK,EAAE,IAAI;gBACX,IAAI;gBACJ,WAAW,EAAE;oBACX,UAAU,CAAC,sBAAsB,EAAE,OAAO,EAAE,gBAAgB,IAAI,iBAAiB,EAAE;wBACjF,IAAI,EAAE,IAAI;wBACV,YAAY;qBACb,CAAC;iBACH;aACF,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QACD,MAAM,aAAa,GAAG,mBAAmB,CACvC,cAAc,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,CAAC,EACvD,IAAI,EACJ,OAAO,CACR,CAAC;QACF,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;YACjC,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,EAAE,UAAU,EAAE,oBAAoB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC5E,CAAC;IACH,CAAC;IACD,OAAO;QACL,KAAK,EAAE,QAAQ,CAAC,KAAK;QACrB,YAAY;QACZ,KAAK,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QACvD,KAAK;QACL,MAAM,EAAE,sBAAsB,CAAC,MAAM,CAAC,OAAO,CAAC;QAC9C,WAAW;KACZ,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB,CACxB,MAAuB,EACvB,SAAsC,EACtC,OAA0C;IAE1C,MAAM,YAAY,GAAG,SAAS,CAAC,YAAa,CAAC;IAC7C,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;IAC7B,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,IAAI,UAAU,CAAC;IAC3C,MAAM,aAAa,GAAG,mBAAmB,CACvC,cAAc,CAAC,GAAG,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,CAAC,EAChD,IAAI,EACJ,OAAO,CACR,CAAC;IACF,OAAO;QACL,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,MAAM,CAAC,QAAQ,IAAI,mBAAmB;QACxE,YAAY;QACZ,KAAK,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,gBAAgB,EAAE,aAAa,CAAC,CAAC;QACjE,KAAK,EAAE,aAAa;QACpB,MAAM,EAAE,EAAE;QACV,WAAW,EAAE,EAAE;KAChB,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CACpB,UAAkB,EAClB,KAAa,EACb,KAAwC;IAExC,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AAC1E,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type Qti3AuthoringItem } from "@longsightgroup/qti3-writer";
|
|
2
|
+
import type { QtiMigrationDiagnostic, QtiMigrationItemResult } from "./types.js";
|
|
3
|
+
import type { ResolvedQtiMigrationOptions } from "./types.js";
|
|
4
|
+
export interface PendingMigrationItem {
|
|
5
|
+
readonly identifier: string;
|
|
6
|
+
readonly title: string;
|
|
7
|
+
readonly authoringItem?: Qti3AuthoringItem | undefined;
|
|
8
|
+
readonly diagnostics: readonly QtiMigrationDiagnostic[];
|
|
9
|
+
}
|
|
10
|
+
export declare function finalizeItemResults(pendingItems: readonly PendingMigrationItem[], sourceHref: string, options: ResolvedQtiMigrationOptions): readonly QtiMigrationItemResult[];
|
|
11
|
+
export declare function finalizeItemResult(pending: PendingMigrationItem, href: string, options: ResolvedQtiMigrationOptions): QtiMigrationItemResult;
|
|
12
|
+
//# sourceMappingURL=item-finalize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"item-finalize.d.ts","sourceRoot":"","sources":["../src/item-finalize.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,iBAAiB,EACvB,MAAM,6BAA6B,CAAC;AAIrC,OAAO,KAAK,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AACjF,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAC;AAE9D,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,aAAa,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;IACvD,QAAQ,CAAC,WAAW,EAAE,SAAS,sBAAsB,EAAE,CAAC;CACzD;AAED,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,SAAS,oBAAoB,EAAE,EAC7C,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,2BAA2B,GACnC,SAAS,sBAAsB,EAAE,CAenC;AAED,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,oBAAoB,EAC7B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,2BAA2B,GACnC,sBAAsB,CAkDxB"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { parseQtiXml, validateAssessmentItem } from "@longsightgroup/qti3-core";
|
|
2
|
+
import { qti3TrustedXmlFragment, writeQti3AssessmentItemResult, } from "@longsightgroup/qti3-writer";
|
|
3
|
+
import { diagnostic, hasErrors } from "./diagnostics.js";
|
|
4
|
+
import { uniqueSiblingItemHref } from "./item-hrefs.js";
|
|
5
|
+
export function finalizeItemResults(pendingItems, sourceHref, options) {
|
|
6
|
+
if (pendingItems.length <= 1) {
|
|
7
|
+
return pendingItems.map((item) => finalizeItemResult(item, sourceHref, options));
|
|
8
|
+
}
|
|
9
|
+
const identifiers = new Set();
|
|
10
|
+
const paths = new Set();
|
|
11
|
+
return pendingItems.map((item, index) => {
|
|
12
|
+
const identifier = item.identifier.trim();
|
|
13
|
+
const uniqueIdentifier = identifier && !identifiers.has(identifier);
|
|
14
|
+
if (uniqueIdentifier)
|
|
15
|
+
identifiers.add(identifier);
|
|
16
|
+
const suffix = uniqueIdentifier ? identifier : `ITEM_${index + 1}`;
|
|
17
|
+
const href = uniqueSiblingItemHref(sourceHref, suffix, paths);
|
|
18
|
+
return finalizeItemResult(item, href, options);
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
export function finalizeItemResult(pending, href, options) {
|
|
22
|
+
const diagnostics = [...pending.diagnostics];
|
|
23
|
+
if (pending.authoringItem && !hasErrors(diagnostics)) {
|
|
24
|
+
const writer = writeQti3AssessmentItemResult(pending.authoringItem);
|
|
25
|
+
if (writer.ok) {
|
|
26
|
+
diagnostics.push(...validateWrittenXml(writer.xml));
|
|
27
|
+
return {
|
|
28
|
+
identifier: pending.identifier,
|
|
29
|
+
title: pending.title,
|
|
30
|
+
href,
|
|
31
|
+
authoringItem: pending.authoringItem,
|
|
32
|
+
xml: writer.xml,
|
|
33
|
+
diagnostics,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
diagnostics.push({
|
|
37
|
+
code: "writer_diagnostics",
|
|
38
|
+
severity: "error",
|
|
39
|
+
message: "QTI 3 writer rejected migrated authoring item.",
|
|
40
|
+
writerDiagnostics: writer.diagnostics,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
if (options.unsupportedPolicy === "stub") {
|
|
44
|
+
const stub = stubItem(pending.identifier, pending.title);
|
|
45
|
+
const writer = writeQti3AssessmentItemResult(stub);
|
|
46
|
+
return {
|
|
47
|
+
identifier: pending.identifier,
|
|
48
|
+
title: pending.title,
|
|
49
|
+
href,
|
|
50
|
+
authoringItem: stub,
|
|
51
|
+
xml: writer.ok ? writer.xml : undefined,
|
|
52
|
+
diagnostics: [
|
|
53
|
+
...diagnostics,
|
|
54
|
+
diagnostic("unsupported_item_stubbed", "warning", "Unsupported item migrated as an extended-text review stub."),
|
|
55
|
+
],
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
identifier: pending.identifier,
|
|
60
|
+
title: pending.title,
|
|
61
|
+
href,
|
|
62
|
+
authoringItem: options.unsupportedPolicy === "skip" ? undefined : pending.authoringItem,
|
|
63
|
+
diagnostics,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function validateWrittenXml(xml) {
|
|
67
|
+
const parsed = parseQtiXml(xml);
|
|
68
|
+
const diagnostics = [];
|
|
69
|
+
if (!parsed.ok || !parsed.document) {
|
|
70
|
+
diagnostics.push(...coreDiagnostics("core_parse", parsed.diagnostics));
|
|
71
|
+
return diagnostics;
|
|
72
|
+
}
|
|
73
|
+
const validation = validateAssessmentItem(parsed.document);
|
|
74
|
+
if (!validation.ok)
|
|
75
|
+
diagnostics.push(...coreDiagnostics("core_validate", validation.diagnostics));
|
|
76
|
+
return diagnostics;
|
|
77
|
+
}
|
|
78
|
+
function coreDiagnostics(prefix, diagnostics) {
|
|
79
|
+
return diagnostics.map((entry) => diagnostic(`${prefix}.${entry.code}`, entry.severity === "error" ? "error" : "warning", entry.message));
|
|
80
|
+
}
|
|
81
|
+
function stubItem(identifier, title) {
|
|
82
|
+
return {
|
|
83
|
+
interactionType: "extendedText",
|
|
84
|
+
identifier,
|
|
85
|
+
title,
|
|
86
|
+
bodyHtml: qti3TrustedXmlFragment("<p>This item requires manual migration review.</p>"),
|
|
87
|
+
responseIdentifier: "RESPONSE",
|
|
88
|
+
responseBaseType: "string",
|
|
89
|
+
responseCardinality: "single",
|
|
90
|
+
expectedLines: 6,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=item-finalize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"item-finalize.js","sourceRoot":"","sources":["../src/item-finalize.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"item-hrefs.d.ts","sourceRoot":"","sources":["../src/item-hrefs.ts"],"names":[],"mappings":"AAEA,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,GACrB,MAAM,CAgBR"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { migrationPathIdentifier } from "./identifiers.js";
|
|
2
|
+
export function uniqueSiblingItemHref(sourceHref, suffix, usedPaths) {
|
|
3
|
+
const slashIndex = sourceHref.lastIndexOf("/");
|
|
4
|
+
const directory = slashIndex >= 0 ? sourceHref.slice(0, slashIndex + 1) : "";
|
|
5
|
+
const fileName = slashIndex >= 0 ? sourceHref.slice(slashIndex + 1) : sourceHref;
|
|
6
|
+
const dotIndex = fileName.toLowerCase().endsWith(".xml")
|
|
7
|
+
? fileName.length - 4
|
|
8
|
+
: fileName.lastIndexOf(".");
|
|
9
|
+
const baseName = dotIndex > 0 ? fileName.slice(0, dotIndex) : fileName || "item";
|
|
10
|
+
const extension = dotIndex > 0 ? fileName.slice(dotIndex) : ".xml";
|
|
11
|
+
const safeSuffix = migrationPathIdentifier(suffix);
|
|
12
|
+
let candidate = `${directory}${baseName}_${safeSuffix}${extension}`;
|
|
13
|
+
for (let index = 2; usedPaths.has(candidate); index += 1) {
|
|
14
|
+
candidate = `${directory}${baseName}_${safeSuffix}_${index}${extension}`;
|
|
15
|
+
}
|
|
16
|
+
usedPaths.add(candidate);
|
|
17
|
+
return candidate;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=item-hrefs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"item-hrefs.js","sourceRoot":"","sources":["../src/item-hrefs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAE3D,MAAM,UAAU,qBAAqB,CACnC,UAAkB,EAClB,MAAc,EACd,SAAsB;IAEtB,MAAM,UAAU,GAAG,UAAU,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC/C,MAAM,SAAS,GAAG,UAAU,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7E,MAAM,QAAQ,GAAG,UAAU,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;IACjF,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC;QACtD,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;QACrB,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC9B,MAAM,QAAQ,GAAG,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,IAAI,MAAM,CAAC;IACjF,MAAM,SAAS,GAAG,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IACnE,MAAM,UAAU,GAAG,uBAAuB,CAAC,MAAM,CAAC,CAAC;IACnD,IAAI,SAAS,GAAG,GAAG,SAAS,GAAG,QAAQ,IAAI,UAAU,GAAG,SAAS,EAAE,CAAC;IACpE,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACzD,SAAS,GAAG,GAAG,SAAS,GAAG,QAAQ,IAAI,UAAU,IAAI,KAAK,GAAG,SAAS,EAAE,CAAC;IAC3E,CAAC;IACD,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACzB,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { PendingMigrationItem } from "./item-finalize.js";
|
|
2
|
+
import type { QtiMigrationSourceFormat } from "./types.js";
|
|
3
|
+
import type { ResolvedQtiMigrationOptions } from "./types.js";
|
|
4
|
+
export declare function migrateItemXml(xml: string, path: string, sourceFormat: QtiMigrationSourceFormat, options: ResolvedQtiMigrationOptions): readonly PendingMigrationItem[];
|
|
5
|
+
export declare function itemTitleFromXmlSafe(xml: string): string;
|
|
6
|
+
//# sourceMappingURL=migrate-items.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate-items.d.ts","sourceRoot":"","sources":["../src/migrate-items.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAG/D,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAC3D,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAC;AAE9D,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,wBAAwB,EACtC,OAAO,EAAE,2BAA2B,GACnC,SAAS,oBAAoB,EAAE,CAkBjC;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAMxD"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { migrationPathIdentifier } from "./identifiers.js";
|
|
2
|
+
import { migrateQti12Xml } from "./qti12-item.js";
|
|
3
|
+
import { itemTitleFromXml, migrateQti2ItemXml } from "./qti2-item.js";
|
|
4
|
+
export function migrateItemXml(xml, path, sourceFormat, options) {
|
|
5
|
+
if (sourceFormat === "qti12") {
|
|
6
|
+
return migrateQti12Xml(xml, path, options).map((result, index) => ({
|
|
7
|
+
identifier: result.authoringItem?.identifier ?? `ITEM_${index + 1}`,
|
|
8
|
+
title: result.authoringItem?.title ?? itemTitleFromXmlSafe(xml),
|
|
9
|
+
authoringItem: result.authoringItem,
|
|
10
|
+
diagnostics: result.diagnostics,
|
|
11
|
+
}));
|
|
12
|
+
}
|
|
13
|
+
const result = migrateQti2ItemXml(xml, path, sourceFormat, options);
|
|
14
|
+
return [
|
|
15
|
+
{
|
|
16
|
+
identifier: result.authoringItem?.identifier ?? migrationPathIdentifier(path),
|
|
17
|
+
title: result.authoringItem?.title ?? itemTitleFromXmlSafe(xml),
|
|
18
|
+
authoringItem: result.authoringItem,
|
|
19
|
+
diagnostics: result.diagnostics,
|
|
20
|
+
},
|
|
21
|
+
];
|
|
22
|
+
}
|
|
23
|
+
export function itemTitleFromXmlSafe(xml) {
|
|
24
|
+
try {
|
|
25
|
+
return itemTitleFromXml(xml);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return "Imported Item";
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=migrate-items.js.map
|