@longsightgroup/qti3-migrator 0.9.6 → 0.9.7
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 +16 -0
- 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 +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +23 -24
- package/dist/index.js.map +1 -1
- package/dist/package-result.d.ts +3 -0
- package/dist/package-result.d.ts.map +1 -0
- package/dist/package-result.js +77 -0
- package/dist/package-result.js.map +1 -0
- package/dist/types.d.ts +10 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/identifiers.ts +12 -0
- package/src/index.ts +38 -20
- package/src/package-result.ts +111 -0
- package/src/types.ts +14 -1
package/README.md
CHANGED
|
@@ -10,4 +10,20 @@ import { migrateQtiToQti3 } from "@longsightgroup/qti3-migrator";
|
|
|
10
10
|
const result = await migrateQtiToQti3({ filename: "quiz.zip", bytes });
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
+
Use `migrateQtiToQti3Package` 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
|
+
|
|
13
29
|
Defaults are strict: source repair is disabled and unsupported interactions are reported as diagnostics instead of silently converted.
|
|
@@ -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,8 @@
|
|
|
1
1
|
import { detectQtiMigrationSource } from "./source.js";
|
|
2
|
-
import type { QtiMigrationItemResult, QtiMigrationOptions, QtiMigrationResult, QtiMigrationSourceInput } from "./types.js";
|
|
2
|
+
import type { QtiMigrationItemResult, QtiMigrationOptions, QtiPackageMigrationResult, QtiMigrationResult, QtiMigrationSourceInput } from "./types.js";
|
|
3
3
|
export { detectQtiMigrationSource };
|
|
4
|
-
export type { QtiMigrationAsset, QtiMigrationDetectionResult, QtiMigrationDiagnostic, QtiMigrationDiagnosticSeverity, QtiMigrationItemResult, QtiMigrationOptions, QtiMigrationPart, QtiMigrationRepairPolicy, QtiMigrationResult, QtiMigrationSourceFormat, QtiMigrationSourceInput, QtiMigrationUnsupportedPolicy, } from "./types.js";
|
|
4
|
+
export type { QtiMigrationAsset, QtiMigrationDetectionResult, QtiMigrationDiagnostic, QtiMigrationDiagnosticSeverity, QtiMigrationItemResult, QtiMigrationOptions, QtiPackageMigrationResult, QtiMigrationPart, QtiMigrationRepairPolicy, QtiMigrationResult, QtiMigrationSourceFormat, QtiMigrationSourceInput, QtiMigrationUnsupportedPolicy, } from "./types.js";
|
|
5
5
|
export declare function migrateQtiToQti3(input: QtiMigrationSourceInput, options?: QtiMigrationOptions): Promise<QtiMigrationResult>;
|
|
6
|
+
export declare function migrateQtiToQti3Package(input: QtiMigrationSourceInput, options?: QtiMigrationOptions): Promise<QtiPackageMigrationResult>;
|
|
6
7
|
export declare function migrateQtiItemToQti3(input: QtiMigrationSourceInput, options?: QtiMigrationOptions): QtiMigrationItemResult;
|
|
7
8
|
//# 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":"AAiBA,OAAO,EAEL,wBAAwB,EAKzB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAIV,sBAAsB,EACtB,mBAAmB,EACnB,yBAAyB,EAEzB,kBAAkB,EAElB,uBAAuB,EACxB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,wBAAwB,EAAE,CAAC;AACpC,YAAY,EACV,iBAAiB,EACjB,2BAA2B,EAC3B,sBAAsB,EACtB,8BAA8B,EAC9B,sBAAsB,EACtB,mBAAmB,EACnB,yBAAyB,EACzB,gBAAgB,EAChB,wBAAwB,EACxB,kBAAkB,EAClB,wBAAwB,EACxB,uBAAuB,EACvB,6BAA6B,GAC9B,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,7 +1,9 @@
|
|
|
1
|
-
import { parseQtiXml, validateAssessmentItem } from "@longsightgroup/qti3-core";
|
|
1
|
+
import { detectPackageMediaType, parseQtiXml, validateAssessmentItem, } from "@longsightgroup/qti3-core";
|
|
2
2
|
import { qti3TrustedXmlFragment, writeQti3AssessmentItemResult, } from "@longsightgroup/qti3-writer";
|
|
3
3
|
import { diagnostic, hasErrors } from "./diagnostics.js";
|
|
4
|
+
import { migrationPathIdentifier } from "./identifiers.js";
|
|
4
5
|
import { resolveOptions } from "./options.js";
|
|
6
|
+
import { migrationResultToPackage } from "./package-result.js";
|
|
5
7
|
import { migrateQti12Xml } from "./qti12-item.js";
|
|
6
8
|
import { itemTitleFromXml, migrateQti2ItemXml } from "./qti2-item.js";
|
|
7
9
|
import { detectMigrationSource, detectQtiMigrationSource, parseLegacyManifest, readMigrationSource, } from "./source.js";
|
|
@@ -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: [
|
|
@@ -109,7 +121,8 @@ function migratePackageSource(source, detection, options) {
|
|
|
109
121
|
}
|
|
110
122
|
const migratedItems = migrateItemXml(entry.text, href, sourceFormat, options);
|
|
111
123
|
for (const item of migratedItems) {
|
|
112
|
-
|
|
124
|
+
const finalized = finalizeItemResult(item, href, options);
|
|
125
|
+
items.push({ ...finalized, assetHrefs: assetHrefsByItemHref.get(href) ?? [] });
|
|
113
126
|
}
|
|
114
127
|
}
|
|
115
128
|
return {
|
|
@@ -124,7 +137,7 @@ function migratePackageSource(source, detection, options) {
|
|
|
124
137
|
function migrateItemSource(source, detection, options) {
|
|
125
138
|
const sourceFormat = detection.sourceFormat;
|
|
126
139
|
const xml = source.xml ?? "";
|
|
127
|
-
const migratedItems = migrateItemXml(xml, source.filename ?? "item.xml", sourceFormat, options).map((item) => finalizeItemResult(item, `${item.identifier}.xml`, options));
|
|
140
|
+
const migratedItems = migrateItemXml(xml, source.filename ?? "item.xml", sourceFormat, options).map((item) => finalizeItemResult(item, source.filename ?? `${item.identifier}.xml`, options));
|
|
128
141
|
return {
|
|
129
142
|
title: migratedItems[0]?.title ?? source.filename ?? "Imported QTI Item",
|
|
130
143
|
sourceFormat,
|
|
@@ -146,7 +159,7 @@ function migrateItemXml(xml, path, sourceFormat, options) {
|
|
|
146
159
|
const result = migrateQti2ItemXml(xml, path, sourceFormat, options);
|
|
147
160
|
return [
|
|
148
161
|
{
|
|
149
|
-
identifier: result.authoringItem?.identifier ??
|
|
162
|
+
identifier: result.authoringItem?.identifier ?? migrationPathIdentifier(path),
|
|
150
163
|
title: result.authoringItem?.title ?? itemTitleFromXmlSafe(xml),
|
|
151
164
|
authoringItem: result.authoringItem,
|
|
152
165
|
diagnostics: result.diagnostics,
|
|
@@ -228,14 +241,15 @@ function stubItem(identifier, title) {
|
|
|
228
241
|
function packageAssets(entries) {
|
|
229
242
|
return entries
|
|
230
243
|
.filter((entry) => !entry.path.toLowerCase().endsWith(".xml"))
|
|
231
|
-
.map((entry) => ({
|
|
244
|
+
.map((entry) => ({
|
|
245
|
+
path: entry.path,
|
|
246
|
+
data: entry.bytes,
|
|
247
|
+
mediaType: detectPackageMediaType(entry.path),
|
|
248
|
+
}));
|
|
232
249
|
}
|
|
233
250
|
function partFromItems(identifier, title, items) {
|
|
234
251
|
return { identifier, title, itemHrefs: items.map((item) => item.href) };
|
|
235
252
|
}
|
|
236
|
-
function pathIdentifier(path) {
|
|
237
|
-
return path.replace(/\.[^.]+$/, "").replace(/[^A-Za-z0-9_]/g, "_") || "ITEM";
|
|
238
|
-
}
|
|
239
253
|
function itemTitleFromXmlSafe(xml) {
|
|
240
254
|
try {
|
|
241
255
|
return itemTitleFromXml(xml);
|
|
@@ -244,19 +258,4 @@ function itemTitleFromXmlSafe(xml) {
|
|
|
244
258
|
return "Imported Item";
|
|
245
259
|
}
|
|
246
260
|
}
|
|
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
261
|
//# 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,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-result.d.ts","sourceRoot":"","sources":["../src/package-result.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAGV,kBAAkB,EAClB,yBAAyB,EAC1B,MAAM,YAAY,CAAC;AAEpB,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,kBAAkB,GAAG,yBAAyB,CAuB9F"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { diagnostic, hasErrors } from "./diagnostics.js";
|
|
2
|
+
import { migrationPackageIdentifier } from "./identifiers.js";
|
|
3
|
+
export function migrationResultToPackage(result) {
|
|
4
|
+
const itemDiagnostics = result.items.flatMap((item) => item.diagnostics);
|
|
5
|
+
const assetDiagnostics = [];
|
|
6
|
+
const assetsByPath = migrationAssetsByPath(result.assets, assetDiagnostics);
|
|
7
|
+
const itemBuildDiagnostics = [];
|
|
8
|
+
const items = buildPackageItems(result, assetsByPath, itemBuildDiagnostics);
|
|
9
|
+
const diagnostics = [
|
|
10
|
+
...result.diagnostics,
|
|
11
|
+
...itemDiagnostics,
|
|
12
|
+
...assetDiagnostics,
|
|
13
|
+
...itemBuildDiagnostics,
|
|
14
|
+
];
|
|
15
|
+
if (hasErrors(diagnostics))
|
|
16
|
+
return { ok: false, diagnostics };
|
|
17
|
+
return {
|
|
18
|
+
ok: true,
|
|
19
|
+
package: {
|
|
20
|
+
identifier: migrationPackageIdentifier(result.title),
|
|
21
|
+
title: result.title,
|
|
22
|
+
items,
|
|
23
|
+
},
|
|
24
|
+
diagnostics,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function buildPackageItems(result, assetsByPath, diagnostics) {
|
|
28
|
+
const items = [];
|
|
29
|
+
for (const item of result.items) {
|
|
30
|
+
if (!item.xml) {
|
|
31
|
+
diagnostics.push(diagnostic("package_item_xml_missing", "error", "Migrated item has no QTI 3 XML.", {
|
|
32
|
+
path: item.href,
|
|
33
|
+
sourceFormat: result.sourceFormat,
|
|
34
|
+
}));
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
items.push({
|
|
38
|
+
kind: "xml",
|
|
39
|
+
path: item.href,
|
|
40
|
+
identifier: item.identifier,
|
|
41
|
+
xml: item.xml,
|
|
42
|
+
assets: packageItemAssets(item.assetHrefs ?? [], assetsByPath, diagnostics),
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
return items;
|
|
46
|
+
}
|
|
47
|
+
function migrationAssetsByPath(assets, diagnostics) {
|
|
48
|
+
const assetsByPath = new Map();
|
|
49
|
+
for (const asset of assets) {
|
|
50
|
+
if (!asset.data) {
|
|
51
|
+
diagnostics.push(diagnostic("package_asset_data_missing", "error", "Migrated package asset has no data.", {
|
|
52
|
+
path: asset.path,
|
|
53
|
+
}));
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
assetsByPath.set(asset.path, {
|
|
57
|
+
path: asset.path,
|
|
58
|
+
data: asset.data,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
return assetsByPath;
|
|
62
|
+
}
|
|
63
|
+
function packageItemAssets(hrefs, assetsByPath, diagnostics) {
|
|
64
|
+
const assets = [];
|
|
65
|
+
for (const href of hrefs) {
|
|
66
|
+
const asset = assetsByPath.get(href);
|
|
67
|
+
if (!asset) {
|
|
68
|
+
diagnostics.push(diagnostic("package_asset_missing", "error", "Migrated package item references missing asset.", {
|
|
69
|
+
path: href,
|
|
70
|
+
}));
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
assets.push(asset);
|
|
74
|
+
}
|
|
75
|
+
return assets;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=package-result.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-result.js","sourceRoot":"","sources":["../src/package-result.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Qti3AuthoringItem, Qti3WriterDiagnostic } from "@longsightgroup/qti3-writer";
|
|
1
|
+
import type { Qti3AuthoringItem, Qti3PackageAuthoringInput, Qti3WriterDiagnostic } from "@longsightgroup/qti3-writer";
|
|
2
2
|
export type QtiMigrationSourceFormat = "qti12" | "qti21" | "qti22";
|
|
3
3
|
export type QtiMigrationRepairPolicy = "none" | "safe";
|
|
4
4
|
export type QtiMigrationUnsupportedPolicy = "diagnostic" | "stub" | "skip";
|
|
@@ -46,6 +46,7 @@ export interface QtiMigrationItemResult {
|
|
|
46
46
|
readonly identifier: string;
|
|
47
47
|
readonly title: string;
|
|
48
48
|
readonly href: string;
|
|
49
|
+
readonly assetHrefs?: readonly string[] | undefined;
|
|
49
50
|
readonly authoringItem?: Qti3AuthoringItem | undefined;
|
|
50
51
|
readonly xml?: string | undefined;
|
|
51
52
|
readonly diagnostics: readonly QtiMigrationDiagnostic[];
|
|
@@ -58,4 +59,12 @@ export interface QtiMigrationResult {
|
|
|
58
59
|
readonly assets: readonly QtiMigrationAsset[];
|
|
59
60
|
readonly diagnostics: readonly QtiMigrationDiagnostic[];
|
|
60
61
|
}
|
|
62
|
+
export type QtiPackageMigrationResult = {
|
|
63
|
+
readonly ok: true;
|
|
64
|
+
readonly package: Qti3PackageAuthoringInput;
|
|
65
|
+
readonly diagnostics: readonly QtiMigrationDiagnostic[];
|
|
66
|
+
} | {
|
|
67
|
+
readonly ok: false;
|
|
68
|
+
readonly diagnostics: readonly QtiMigrationDiagnostic[];
|
|
69
|
+
};
|
|
61
70
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@longsightgroup/qti3-migrator",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.7",
|
|
4
4
|
"description": "Framework-neutral QTI 1.2 and QTI 2.x to QTI 3 migration utilities.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"assessment",
|
|
@@ -49,8 +49,8 @@
|
|
|
49
49
|
"dependencies": {
|
|
50
50
|
"@xmldom/xmldom": "^0.8.11",
|
|
51
51
|
"fflate": "^0.8.2",
|
|
52
|
-
"@longsightgroup/qti3-writer": "0.9.
|
|
53
|
-
"@longsightgroup/qti3-core": "0.9.
|
|
52
|
+
"@longsightgroup/qti3-writer": "0.9.7",
|
|
53
|
+
"@longsightgroup/qti3-core": "0.9.7"
|
|
54
54
|
},
|
|
55
55
|
"scripts": {}
|
|
56
56
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export function migrationPathIdentifier(path: string): string {
|
|
2
|
+
return sanitizeMigrationIdentifier(path, "ITEM", "ITEM");
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function migrationPackageIdentifier(title: string): string {
|
|
6
|
+
return sanitizeMigrationIdentifier(title, "PACKAGE", "PACKAGE");
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function sanitizeMigrationIdentifier(value: string, fallback: string, prefix: string): string {
|
|
10
|
+
const normalized = value.replace(/\.[^.]+$/, "").replace(/[^A-Za-z0-9_]/g, "_") || fallback;
|
|
11
|
+
return /^[A-Za-z_]/.test(normalized) ? normalized : `${prefix}_${normalized}`;
|
|
12
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
detectPackageMediaType,
|
|
3
|
+
parseQtiXml,
|
|
4
|
+
validateAssessmentItem,
|
|
5
|
+
type QtiDiagnostic,
|
|
6
|
+
} from "@longsightgroup/qti3-core";
|
|
2
7
|
import {
|
|
3
8
|
qti3TrustedXmlFragment,
|
|
4
9
|
writeQti3AssessmentItemResult,
|
|
5
10
|
type Qti3AuthoringItem,
|
|
6
11
|
} from "@longsightgroup/qti3-writer";
|
|
7
12
|
import { diagnostic, hasErrors } from "./diagnostics.js";
|
|
13
|
+
import { migrationPathIdentifier } from "./identifiers.js";
|
|
8
14
|
import { resolveOptions } from "./options.js";
|
|
15
|
+
import { migrationResultToPackage } from "./package-result.js";
|
|
9
16
|
import { migrateQti12Xml } from "./qti12-item.js";
|
|
10
17
|
import { itemTitleFromXml, migrateQti2ItemXml } from "./qti2-item.js";
|
|
11
18
|
import {
|
|
@@ -22,6 +29,7 @@ import type {
|
|
|
22
29
|
QtiMigrationDiagnostic,
|
|
23
30
|
QtiMigrationItemResult,
|
|
24
31
|
QtiMigrationOptions,
|
|
32
|
+
QtiPackageMigrationResult,
|
|
25
33
|
QtiMigrationPart,
|
|
26
34
|
QtiMigrationResult,
|
|
27
35
|
QtiMigrationSourceFormat,
|
|
@@ -36,6 +44,7 @@ export type {
|
|
|
36
44
|
QtiMigrationDiagnosticSeverity,
|
|
37
45
|
QtiMigrationItemResult,
|
|
38
46
|
QtiMigrationOptions,
|
|
47
|
+
QtiPackageMigrationResult,
|
|
39
48
|
QtiMigrationPart,
|
|
40
49
|
QtiMigrationRepairPolicy,
|
|
41
50
|
QtiMigrationResult,
|
|
@@ -77,6 +86,14 @@ export async function migrateQtiToQti3(
|
|
|
77
86
|
return Promise.resolve(migrated);
|
|
78
87
|
}
|
|
79
88
|
|
|
89
|
+
export async function migrateQtiToQti3Package(
|
|
90
|
+
input: QtiMigrationSourceInput,
|
|
91
|
+
options: QtiMigrationOptions = {},
|
|
92
|
+
): Promise<QtiPackageMigrationResult> {
|
|
93
|
+
const migration = await migrateQtiToQti3(input, options);
|
|
94
|
+
return migrationResultToPackage(migration);
|
|
95
|
+
}
|
|
96
|
+
|
|
80
97
|
export function migrateQtiItemToQti3(
|
|
81
98
|
input: QtiMigrationSourceInput,
|
|
82
99
|
options: QtiMigrationOptions = {},
|
|
@@ -168,6 +185,16 @@ function migratePackageSource(
|
|
|
168
185
|
);
|
|
169
186
|
}
|
|
170
187
|
const entriesByPath = new Map(source.entries.map((entry) => [entry.path, entry]));
|
|
188
|
+
const assetHrefsByItemHref = new Map<string, readonly string[]>();
|
|
189
|
+
for (const resource of manifest.resources) {
|
|
190
|
+
if (!resource.href) continue;
|
|
191
|
+
assetHrefsByItemHref.set(
|
|
192
|
+
resource.href,
|
|
193
|
+
resource.files.filter(
|
|
194
|
+
(file) => file !== resource.href && !file.toLowerCase().endsWith(".xml"),
|
|
195
|
+
),
|
|
196
|
+
);
|
|
197
|
+
}
|
|
171
198
|
const itemHrefs = manifest.itemHrefs.length
|
|
172
199
|
? manifest.itemHrefs
|
|
173
200
|
: source.entries
|
|
@@ -180,7 +207,7 @@ function migratePackageSource(
|
|
|
180
207
|
const entry = entriesByPath.get(href) ?? entriesByPath.get(href.replace(/^\.\//, ""));
|
|
181
208
|
if (!entry?.text) {
|
|
182
209
|
items.push({
|
|
183
|
-
identifier:
|
|
210
|
+
identifier: migrationPathIdentifier(href),
|
|
184
211
|
title: href,
|
|
185
212
|
href,
|
|
186
213
|
diagnostics: [
|
|
@@ -194,7 +221,8 @@ function migratePackageSource(
|
|
|
194
221
|
}
|
|
195
222
|
const migratedItems = migrateItemXml(entry.text, href, sourceFormat, options);
|
|
196
223
|
for (const item of migratedItems) {
|
|
197
|
-
|
|
224
|
+
const finalized = finalizeItemResult(item, href, options);
|
|
225
|
+
items.push({ ...finalized, assetHrefs: assetHrefsByItemHref.get(href) ?? [] });
|
|
198
226
|
}
|
|
199
227
|
}
|
|
200
228
|
return {
|
|
@@ -219,7 +247,7 @@ function migrateItemSource(
|
|
|
219
247
|
source.filename ?? "item.xml",
|
|
220
248
|
sourceFormat,
|
|
221
249
|
options,
|
|
222
|
-
).map((item) => finalizeItemResult(item, `${item.identifier}.xml`, options));
|
|
250
|
+
).map((item) => finalizeItemResult(item, source.filename ?? `${item.identifier}.xml`, options));
|
|
223
251
|
return {
|
|
224
252
|
title: migratedItems[0]?.title ?? source.filename ?? "Imported QTI Item",
|
|
225
253
|
sourceFormat,
|
|
@@ -247,7 +275,7 @@ function migrateItemXml(
|
|
|
247
275
|
const result = migrateQti2ItemXml(xml, path, sourceFormat, options);
|
|
248
276
|
return [
|
|
249
277
|
{
|
|
250
|
-
identifier: result.authoringItem?.identifier ??
|
|
278
|
+
identifier: result.authoringItem?.identifier ?? migrationPathIdentifier(path),
|
|
251
279
|
title: result.authoringItem?.title ?? itemTitleFromXmlSafe(xml),
|
|
252
280
|
authoringItem: result.authoringItem,
|
|
253
281
|
diagnostics: result.diagnostics,
|
|
@@ -359,7 +387,11 @@ function stubItem(identifier: string, title: string): Qti3AuthoringItem {
|
|
|
359
387
|
function packageAssets(entries: readonly MigrationEntry[]): QtiMigrationAsset[] {
|
|
360
388
|
return entries
|
|
361
389
|
.filter((entry) => !entry.path.toLowerCase().endsWith(".xml"))
|
|
362
|
-
.map((entry) => ({
|
|
390
|
+
.map((entry) => ({
|
|
391
|
+
path: entry.path,
|
|
392
|
+
data: entry.bytes,
|
|
393
|
+
mediaType: detectPackageMediaType(entry.path),
|
|
394
|
+
}));
|
|
363
395
|
}
|
|
364
396
|
|
|
365
397
|
function partFromItems(
|
|
@@ -370,10 +402,6 @@ function partFromItems(
|
|
|
370
402
|
return { identifier, title, itemHrefs: items.map((item) => item.href) };
|
|
371
403
|
}
|
|
372
404
|
|
|
373
|
-
function pathIdentifier(path: string): string {
|
|
374
|
-
return path.replace(/\.[^.]+$/, "").replace(/[^A-Za-z0-9_]/g, "_") || "ITEM";
|
|
375
|
-
}
|
|
376
|
-
|
|
377
405
|
function itemTitleFromXmlSafe(xml: string): string {
|
|
378
406
|
try {
|
|
379
407
|
return itemTitleFromXml(xml);
|
|
@@ -381,13 +409,3 @@ function itemTitleFromXmlSafe(xml: string): string {
|
|
|
381
409
|
return "Imported Item";
|
|
382
410
|
}
|
|
383
411
|
}
|
|
384
|
-
|
|
385
|
-
function mediaType(path: string): string | undefined {
|
|
386
|
-
if (/\.png$/i.test(path)) return "image/png";
|
|
387
|
-
if (/\.jpe?g$/i.test(path)) return "image/jpeg";
|
|
388
|
-
if (/\.gif$/i.test(path)) return "image/gif";
|
|
389
|
-
if (/\.svg$/i.test(path)) return "image/svg+xml";
|
|
390
|
-
if (/\.mp3$/i.test(path)) return "audio/mpeg";
|
|
391
|
-
if (/\.mp4$/i.test(path)) return "video/mp4";
|
|
392
|
-
return undefined;
|
|
393
|
-
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import type { Qti3PackageAsset, Qti3PackageItem } from "@longsightgroup/qti3-writer";
|
|
2
|
+
|
|
3
|
+
import { diagnostic, hasErrors } from "./diagnostics.js";
|
|
4
|
+
import { migrationPackageIdentifier } from "./identifiers.js";
|
|
5
|
+
import type {
|
|
6
|
+
QtiMigrationAsset,
|
|
7
|
+
QtiMigrationDiagnostic,
|
|
8
|
+
QtiMigrationResult,
|
|
9
|
+
QtiPackageMigrationResult,
|
|
10
|
+
} from "./types.js";
|
|
11
|
+
|
|
12
|
+
export function migrationResultToPackage(result: QtiMigrationResult): QtiPackageMigrationResult {
|
|
13
|
+
const itemDiagnostics = result.items.flatMap((item) => item.diagnostics);
|
|
14
|
+
const assetDiagnostics: QtiMigrationDiagnostic[] = [];
|
|
15
|
+
const assetsByPath = migrationAssetsByPath(result.assets, assetDiagnostics);
|
|
16
|
+
const itemBuildDiagnostics: QtiMigrationDiagnostic[] = [];
|
|
17
|
+
const items = buildPackageItems(result, assetsByPath, itemBuildDiagnostics);
|
|
18
|
+
const diagnostics = [
|
|
19
|
+
...result.diagnostics,
|
|
20
|
+
...itemDiagnostics,
|
|
21
|
+
...assetDiagnostics,
|
|
22
|
+
...itemBuildDiagnostics,
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
if (hasErrors(diagnostics)) return { ok: false, diagnostics };
|
|
26
|
+
return {
|
|
27
|
+
ok: true,
|
|
28
|
+
package: {
|
|
29
|
+
identifier: migrationPackageIdentifier(result.title),
|
|
30
|
+
title: result.title,
|
|
31
|
+
items,
|
|
32
|
+
},
|
|
33
|
+
diagnostics,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function buildPackageItems(
|
|
38
|
+
result: QtiMigrationResult,
|
|
39
|
+
assetsByPath: ReadonlyMap<string, Qti3PackageAsset>,
|
|
40
|
+
diagnostics: QtiMigrationDiagnostic[],
|
|
41
|
+
): Qti3PackageItem[] {
|
|
42
|
+
const items: Qti3PackageItem[] = [];
|
|
43
|
+
for (const item of result.items) {
|
|
44
|
+
if (!item.xml) {
|
|
45
|
+
diagnostics.push(
|
|
46
|
+
diagnostic("package_item_xml_missing", "error", "Migrated item has no QTI 3 XML.", {
|
|
47
|
+
path: item.href,
|
|
48
|
+
sourceFormat: result.sourceFormat,
|
|
49
|
+
}),
|
|
50
|
+
);
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
items.push({
|
|
55
|
+
kind: "xml",
|
|
56
|
+
path: item.href,
|
|
57
|
+
identifier: item.identifier,
|
|
58
|
+
xml: item.xml,
|
|
59
|
+
assets: packageItemAssets(item.assetHrefs ?? [], assetsByPath, diagnostics),
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
return items;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function migrationAssetsByPath(
|
|
66
|
+
assets: readonly QtiMigrationAsset[],
|
|
67
|
+
diagnostics: QtiMigrationDiagnostic[],
|
|
68
|
+
): ReadonlyMap<string, Qti3PackageAsset> {
|
|
69
|
+
const assetsByPath = new Map<string, Qti3PackageAsset>();
|
|
70
|
+
for (const asset of assets) {
|
|
71
|
+
if (!asset.data) {
|
|
72
|
+
diagnostics.push(
|
|
73
|
+
diagnostic("package_asset_data_missing", "error", "Migrated package asset has no data.", {
|
|
74
|
+
path: asset.path,
|
|
75
|
+
}),
|
|
76
|
+
);
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
assetsByPath.set(asset.path, {
|
|
80
|
+
path: asset.path,
|
|
81
|
+
data: asset.data,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
return assetsByPath;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function packageItemAssets(
|
|
88
|
+
hrefs: readonly string[],
|
|
89
|
+
assetsByPath: ReadonlyMap<string, Qti3PackageAsset>,
|
|
90
|
+
diagnostics: QtiMigrationDiagnostic[],
|
|
91
|
+
): readonly Qti3PackageAsset[] {
|
|
92
|
+
const assets: Qti3PackageAsset[] = [];
|
|
93
|
+
for (const href of hrefs) {
|
|
94
|
+
const asset = assetsByPath.get(href);
|
|
95
|
+
if (!asset) {
|
|
96
|
+
diagnostics.push(
|
|
97
|
+
diagnostic(
|
|
98
|
+
"package_asset_missing",
|
|
99
|
+
"error",
|
|
100
|
+
"Migrated package item references missing asset.",
|
|
101
|
+
{
|
|
102
|
+
path: href,
|
|
103
|
+
},
|
|
104
|
+
),
|
|
105
|
+
);
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
assets.push(asset);
|
|
109
|
+
}
|
|
110
|
+
return assets;
|
|
111
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
Qti3AuthoringItem,
|
|
3
|
+
Qti3PackageAuthoringInput,
|
|
4
|
+
Qti3WriterDiagnostic,
|
|
5
|
+
} from "@longsightgroup/qti3-writer";
|
|
2
6
|
|
|
3
7
|
export type QtiMigrationSourceFormat = "qti12" | "qti21" | "qti22";
|
|
4
8
|
|
|
@@ -58,6 +62,7 @@ export interface QtiMigrationItemResult {
|
|
|
58
62
|
readonly identifier: string;
|
|
59
63
|
readonly title: string;
|
|
60
64
|
readonly href: string;
|
|
65
|
+
readonly assetHrefs?: readonly string[] | undefined;
|
|
61
66
|
readonly authoringItem?: Qti3AuthoringItem | undefined;
|
|
62
67
|
readonly xml?: string | undefined;
|
|
63
68
|
readonly diagnostics: readonly QtiMigrationDiagnostic[];
|
|
@@ -71,3 +76,11 @@ export interface QtiMigrationResult {
|
|
|
71
76
|
readonly assets: readonly QtiMigrationAsset[];
|
|
72
77
|
readonly diagnostics: readonly QtiMigrationDiagnostic[];
|
|
73
78
|
}
|
|
79
|
+
|
|
80
|
+
export type QtiPackageMigrationResult =
|
|
81
|
+
| {
|
|
82
|
+
readonly ok: true;
|
|
83
|
+
readonly package: Qti3PackageAuthoringInput;
|
|
84
|
+
readonly diagnostics: readonly QtiMigrationDiagnostic[];
|
|
85
|
+
}
|
|
86
|
+
| { readonly ok: false; readonly diagnostics: readonly QtiMigrationDiagnostic[] };
|