@longsightgroup/qti3-migrator 0.9.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +21 -0
- package/README.md +13 -0
- package/dist/diagnostics.d.ts +7 -0
- package/dist/diagnostics.d.ts.map +1 -0
- package/dist/diagnostics.js +7 -0
- package/dist/diagnostics.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +262 -0
- package/dist/index.js.map +1 -0
- package/dist/options.d.ts +3 -0
- package/dist/options.d.ts.map +1 -0
- package/dist/options.js +7 -0
- package/dist/options.js.map +1 -0
- package/dist/qti12-item.d.ts +7 -0
- package/dist/qti12-item.d.ts.map +1 -0
- package/dist/qti12-item.js +393 -0
- package/dist/qti12-item.js.map +1 -0
- package/dist/qti2-body.d.ts +11 -0
- package/dist/qti2-body.d.ts.map +1 -0
- package/dist/qti2-body.js +90 -0
- package/dist/qti2-body.js.map +1 -0
- package/dist/qti2-choices.d.ts +7 -0
- package/dist/qti2-choices.d.ts.map +1 -0
- package/dist/qti2-choices.js +74 -0
- package/dist/qti2-choices.js.map +1 -0
- package/dist/qti2-graphic.d.ts +10 -0
- package/dist/qti2-graphic.d.ts.map +1 -0
- package/dist/qti2-graphic.js +30 -0
- package/dist/qti2-graphic.js.map +1 -0
- package/dist/qti2-item.d.ts +8 -0
- package/dist/qti2-item.d.ts.map +1 -0
- package/dist/qti2-item.js +494 -0
- package/dist/qti2-item.js.map +1 -0
- package/dist/qti2-response.d.ts +9 -0
- package/dist/qti2-response.d.ts.map +1 -0
- package/dist/qti2-response.js +32 -0
- package/dist/qti2-response.js.map +1 -0
- package/dist/source.d.ts +30 -0
- package/dist/source.d.ts.map +1 -0
- package/dist/source.js +197 -0
- package/dist/source.js.map +1 -0
- package/dist/text.d.ts +5 -0
- package/dist/text.d.ts.map +1 -0
- package/dist/text.js +19 -0
- package/dist/text.js.map +1 -0
- package/dist/types.d.ts +61 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/xml.d.ts +16 -0
- package/dist/xml.d.ts.map +1 -0
- package/dist/xml.js +101 -0
- package/dist/xml.js.map +1 -0
- package/package.json +56 -0
- package/src/diagnostics.ts +21 -0
- package/src/index.ts +393 -0
- package/src/options.ts +8 -0
- package/src/qti12-item.ts +507 -0
- package/src/qti2-body.ts +138 -0
- package/src/qti2-choices.ts +96 -0
- package/src/qti2-graphic.ts +32 -0
- package/src/qti2-item.ts +650 -0
- package/src/qti2-response.ts +41 -0
- package/src/source.ts +251 -0
- package/src/text.ts +21 -0
- package/src/types.ts +73 -0
- package/src/xml.ts +119 -0
package/dist/source.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { QtiMigrationDetectionResult, QtiMigrationDiagnostic, QtiMigrationSourceInput } from "./types.js";
|
|
2
|
+
export interface MigrationEntry {
|
|
3
|
+
readonly path: string;
|
|
4
|
+
readonly bytes: Uint8Array;
|
|
5
|
+
readonly text?: string | undefined;
|
|
6
|
+
}
|
|
7
|
+
export interface MigrationSource {
|
|
8
|
+
readonly filename?: string | undefined;
|
|
9
|
+
readonly isPackage: boolean;
|
|
10
|
+
readonly entries: readonly MigrationEntry[];
|
|
11
|
+
readonly xml?: string | undefined;
|
|
12
|
+
}
|
|
13
|
+
export declare function readMigrationSource(input: QtiMigrationSourceInput): MigrationSource;
|
|
14
|
+
export declare function detectQtiMigrationSource(input: QtiMigrationSourceInput): QtiMigrationDetectionResult;
|
|
15
|
+
export declare function detectMigrationSource(source: MigrationSource): QtiMigrationDetectionResult;
|
|
16
|
+
export interface LegacyManifest {
|
|
17
|
+
readonly title: string;
|
|
18
|
+
readonly resources: readonly LegacyManifestResource[];
|
|
19
|
+
readonly itemHrefs: readonly string[];
|
|
20
|
+
readonly testHrefs: readonly string[];
|
|
21
|
+
readonly diagnostics: readonly QtiMigrationDiagnostic[];
|
|
22
|
+
}
|
|
23
|
+
export interface LegacyManifestResource {
|
|
24
|
+
readonly identifier: string;
|
|
25
|
+
readonly type: string;
|
|
26
|
+
readonly href?: string | undefined;
|
|
27
|
+
readonly files: readonly string[];
|
|
28
|
+
}
|
|
29
|
+
export declare function parseLegacyManifest(xml: string): LegacyManifest;
|
|
30
|
+
//# sourceMappingURL=source.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source.d.ts","sourceRoot":"","sources":["../src/source.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,2BAA2B,EAC3B,sBAAsB,EACtB,uBAAuB,EACxB,MAAM,YAAY,CAAC;AAGpB,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACpC;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,SAAS,cAAc,EAAE,CAAC;IAC5C,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACnC;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,uBAAuB,GAAG,eAAe,CAwBnF;AAED,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,uBAAuB,GAC7B,2BAA2B,CAY7B;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,eAAe,GAAG,2BAA2B,CAiB1F;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,SAAS,sBAAsB,EAAE,CAAC;IACtD,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,WAAW,EAAE,SAAS,sBAAsB,EAAE,CAAC;CACzD;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,CAuC/D"}
|
package/dist/source.js
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { unzipSync } from "fflate";
|
|
2
|
+
import { decodeUtf8 } from "@longsightgroup/qti3-core";
|
|
3
|
+
import { diagnostic } from "./diagnostics.js";
|
|
4
|
+
import { attr, findAllDescendantsByLocalName, localName, parseXml, textOf } from "./xml.js";
|
|
5
|
+
export function readMigrationSource(input) {
|
|
6
|
+
if (input.xml !== undefined) {
|
|
7
|
+
return { filename: input.filename, isPackage: false, entries: [], xml: input.xml };
|
|
8
|
+
}
|
|
9
|
+
if (!input.bytes) {
|
|
10
|
+
throw new Error("QTI migration input must include xml or bytes.");
|
|
11
|
+
}
|
|
12
|
+
if (isZip(input.bytes)) {
|
|
13
|
+
const unzipped = unzipSync(input.bytes);
|
|
14
|
+
const entries = Object.entries(unzipped)
|
|
15
|
+
.filter(([path]) => !path.endsWith("/"))
|
|
16
|
+
.map(([path, bytes]) => ({
|
|
17
|
+
path: path.replaceAll("\\", "/"),
|
|
18
|
+
bytes,
|
|
19
|
+
text: isTextPath(path) ? decodeUtf8(bytes) : undefined,
|
|
20
|
+
}));
|
|
21
|
+
return { filename: input.filename, isPackage: true, entries };
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
filename: input.filename,
|
|
25
|
+
isPackage: false,
|
|
26
|
+
entries: [],
|
|
27
|
+
xml: decodeUtf8(input.bytes),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export function detectQtiMigrationSource(input) {
|
|
31
|
+
try {
|
|
32
|
+
const source = readMigrationSource(input);
|
|
33
|
+
return detectMigrationSource(source);
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
return {
|
|
37
|
+
supported: false,
|
|
38
|
+
confidence: 0,
|
|
39
|
+
reason: error instanceof Error ? error.message : "source-read-failed",
|
|
40
|
+
isPackage: false,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
export function detectMigrationSource(source) {
|
|
45
|
+
if (source.isPackage) {
|
|
46
|
+
const manifest = source.entries.find((entry) => entry.path.toLowerCase() === "imsmanifest.xml");
|
|
47
|
+
if (!manifest?.text) {
|
|
48
|
+
return {
|
|
49
|
+
supported: false,
|
|
50
|
+
confidence: 0.2,
|
|
51
|
+
reason: "package-manifest-missing",
|
|
52
|
+
isPackage: true,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
return detectManifest(manifest.text);
|
|
56
|
+
}
|
|
57
|
+
if (!source.xml) {
|
|
58
|
+
return { supported: false, confidence: 0, reason: "xml-missing", isPackage: false };
|
|
59
|
+
}
|
|
60
|
+
return detectItemXml(source.xml);
|
|
61
|
+
}
|
|
62
|
+
export function parseLegacyManifest(xml) {
|
|
63
|
+
const diagnostics = [];
|
|
64
|
+
const doc = parseXml(xml, "imsmanifest.xml");
|
|
65
|
+
const root = doc.documentElement;
|
|
66
|
+
const title = textOf(findAllDescendantsByLocalName(root, "title")[0]) ||
|
|
67
|
+
attr(root, "identifier") ||
|
|
68
|
+
"Imported QTI Package";
|
|
69
|
+
const resourceNodes = findAllDescendantsByLocalName(root, "resource");
|
|
70
|
+
const resources = resourceNodes.map((resource, index) => {
|
|
71
|
+
const files = findAllDescendantsByLocalName(resource, "file")
|
|
72
|
+
.map((file) => attr(file, "href"))
|
|
73
|
+
.filter((href) => Boolean(href));
|
|
74
|
+
return {
|
|
75
|
+
identifier: attr(resource, "identifier") ?? `RESOURCE_${index + 1}`,
|
|
76
|
+
type: attr(resource, "type") ?? "",
|
|
77
|
+
href: attr(resource, "href") ?? files.find((file) => file.toLowerCase().endsWith(".xml")),
|
|
78
|
+
files,
|
|
79
|
+
};
|
|
80
|
+
});
|
|
81
|
+
const itemHrefs = resources
|
|
82
|
+
.filter((resource) => isLegacyItemResource(resource.type))
|
|
83
|
+
.map((resource) => resource.href)
|
|
84
|
+
.filter((href) => Boolean(href));
|
|
85
|
+
const testHrefs = resources
|
|
86
|
+
.filter((resource) => isLegacyTestResource(resource.type))
|
|
87
|
+
.map((resource) => resource.href)
|
|
88
|
+
.filter((href) => Boolean(href));
|
|
89
|
+
if (!itemHrefs.length && !testHrefs.length) {
|
|
90
|
+
diagnostics.push(diagnostic("manifest_items_missing", "error", "Manifest does not contain supported QTI 1.2 or QTI 2.x item/test resources.", { path: "imsmanifest.xml" }));
|
|
91
|
+
}
|
|
92
|
+
return { title, resources, itemHrefs, testHrefs, diagnostics };
|
|
93
|
+
}
|
|
94
|
+
function detectManifest(xml) {
|
|
95
|
+
const manifest = parseLegacyManifest(xml);
|
|
96
|
+
const typeText = manifest.resources.map((resource) => resource.type.toLowerCase()).join(" ");
|
|
97
|
+
if (typeText.includes("v2p2")) {
|
|
98
|
+
return {
|
|
99
|
+
supported: true,
|
|
100
|
+
sourceFormat: "qti22",
|
|
101
|
+
confidence: 0.9,
|
|
102
|
+
reason: "manifest-qti22",
|
|
103
|
+
isPackage: true,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
if (typeText.includes("v2p1") || typeText.includes("imsqti_item_xmlv2")) {
|
|
107
|
+
return {
|
|
108
|
+
supported: true,
|
|
109
|
+
sourceFormat: "qti21",
|
|
110
|
+
confidence: 0.85,
|
|
111
|
+
reason: "manifest-qti2x",
|
|
112
|
+
isPackage: true,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
if (typeText.includes("qti_xmlv1p2") || typeText.includes("imsqti_xmlv1p2")) {
|
|
116
|
+
return {
|
|
117
|
+
supported: true,
|
|
118
|
+
sourceFormat: "qti12",
|
|
119
|
+
confidence: 0.85,
|
|
120
|
+
reason: "manifest-qti12",
|
|
121
|
+
isPackage: true,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
return {
|
|
125
|
+
supported: manifest.itemHrefs.length > 0,
|
|
126
|
+
sourceFormat: manifest.itemHrefs.length > 0 ? "qti21" : undefined,
|
|
127
|
+
confidence: manifest.itemHrefs.length > 0 ? 0.45 : 0.1,
|
|
128
|
+
reason: manifest.itemHrefs.length > 0 ? "manifest-legacy-item-resource" : "manifest-unsupported",
|
|
129
|
+
isPackage: true,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
function detectItemXml(xml) {
|
|
133
|
+
const doc = parseXml(xml, "item");
|
|
134
|
+
const root = doc.documentElement;
|
|
135
|
+
const rootName = localName(root);
|
|
136
|
+
const serializedRoot = root.nodeName.toLowerCase();
|
|
137
|
+
const namespaceText = [
|
|
138
|
+
attr(root, "xmlns"),
|
|
139
|
+
attr(root, "xmlns:qti"),
|
|
140
|
+
attr(root, "xsi:schemaLocation"),
|
|
141
|
+
attr(root, "schemaLocation"),
|
|
142
|
+
serializedRoot,
|
|
143
|
+
]
|
|
144
|
+
.join(" ")
|
|
145
|
+
.toLowerCase();
|
|
146
|
+
if (rootName === "assessmentitem") {
|
|
147
|
+
if (namespaceText.includes("v2p2")) {
|
|
148
|
+
return {
|
|
149
|
+
supported: true,
|
|
150
|
+
sourceFormat: "qti22",
|
|
151
|
+
confidence: 0.9,
|
|
152
|
+
reason: "assessmentitem-qti22",
|
|
153
|
+
isPackage: false,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
return {
|
|
157
|
+
supported: true,
|
|
158
|
+
sourceFormat: "qti21",
|
|
159
|
+
confidence: 0.85,
|
|
160
|
+
reason: "assessmentitem-qti2x",
|
|
161
|
+
isPackage: false,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
if (rootName === "questestinterop" || rootName === "item") {
|
|
165
|
+
return {
|
|
166
|
+
supported: true,
|
|
167
|
+
sourceFormat: "qti12",
|
|
168
|
+
confidence: 0.75,
|
|
169
|
+
reason: "qti12-root",
|
|
170
|
+
isPackage: false,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
return {
|
|
174
|
+
supported: false,
|
|
175
|
+
confidence: 0,
|
|
176
|
+
reason: `unsupported-root-${rootName}`,
|
|
177
|
+
isPackage: false,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
function isLegacyItemResource(type) {
|
|
181
|
+
const value = type.toLowerCase();
|
|
182
|
+
return (value.includes("imsqti_item_xmlv2") ||
|
|
183
|
+
value.includes("imsqti_item_xmlv1p2") ||
|
|
184
|
+
value.includes("imsqti_xmlv1p2") ||
|
|
185
|
+
value.includes("qti_xmlv1p2"));
|
|
186
|
+
}
|
|
187
|
+
function isLegacyTestResource(type) {
|
|
188
|
+
const value = type.toLowerCase();
|
|
189
|
+
return value.includes("imsqti_test_xmlv2");
|
|
190
|
+
}
|
|
191
|
+
function isZip(bytes) {
|
|
192
|
+
return bytes.length >= 4 && bytes[0] === 0x50 && bytes[1] === 0x4b;
|
|
193
|
+
}
|
|
194
|
+
function isTextPath(path) {
|
|
195
|
+
return /\.(xml|html?|txt|json|css|js)$/i.test(path);
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=source.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source.js","sourceRoot":"","sources":["../src/source.ts"],"names":[],"mappings":"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"}
|
package/dist/text.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function normalizeIdentifier(value: string | null | undefined, fallback?: string): string;
|
|
2
|
+
export declare function stripTags(html: string): string;
|
|
3
|
+
export declare function trustedFragment(html: string): string;
|
|
4
|
+
export declare function escapeText(value: string): string;
|
|
5
|
+
//# sourceMappingURL=text.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../src/text.ts"],"names":[],"mappings":"AAAA,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,QAAQ,SAAO,GAAG,MAAM,CAI7F;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMhD"}
|
package/dist/text.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export function normalizeIdentifier(value, fallback = "ID") {
|
|
2
|
+
const source = (value ?? "").trim() || fallback;
|
|
3
|
+
const normalized = source.replace(/[^A-Za-z0-9_]/g, "_").replace(/^[^A-Za-z_]+/, "");
|
|
4
|
+
return normalized || fallback;
|
|
5
|
+
}
|
|
6
|
+
export function stripTags(html) {
|
|
7
|
+
return html.replace(/<[^>]*>/g, "").trim();
|
|
8
|
+
}
|
|
9
|
+
export function trustedFragment(html) {
|
|
10
|
+
return html.trim();
|
|
11
|
+
}
|
|
12
|
+
export function escapeText(value) {
|
|
13
|
+
return value
|
|
14
|
+
.replaceAll("&", "&")
|
|
15
|
+
.replaceAll("<", "<")
|
|
16
|
+
.replaceAll(">", ">")
|
|
17
|
+
.replaceAll('"', """);
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=text.js.map
|
package/dist/text.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.js","sourceRoot":"","sources":["../src/text.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,mBAAmB,CAAC,KAAgC,EAAE,QAAQ,GAAG,IAAI;IACnF,MAAM,MAAM,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,QAAQ,CAAC;IAChD,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,gBAAgB,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;IACrF,OAAO,UAAU,IAAI,QAAQ,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,OAAO,KAAK;SACT,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC;SACxB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC;SACvB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC;SACvB,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;AAC/B,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { Qti3AuthoringItem, Qti3WriterDiagnostic } from "@longsightgroup/qti3-writer";
|
|
2
|
+
export type QtiMigrationSourceFormat = "qti12" | "qti21" | "qti22";
|
|
3
|
+
export type QtiMigrationRepairPolicy = "none" | "safe";
|
|
4
|
+
export type QtiMigrationUnsupportedPolicy = "diagnostic" | "stub" | "skip";
|
|
5
|
+
export interface QtiMigrationSourceInput {
|
|
6
|
+
readonly filename?: string | undefined;
|
|
7
|
+
readonly bytes?: Uint8Array | undefined;
|
|
8
|
+
readonly xml?: string | undefined;
|
|
9
|
+
readonly mime?: string | undefined;
|
|
10
|
+
}
|
|
11
|
+
export interface QtiMigrationOptions {
|
|
12
|
+
readonly repairPolicy?: QtiMigrationRepairPolicy | undefined;
|
|
13
|
+
readonly unsupportedPolicy?: QtiMigrationUnsupportedPolicy | undefined;
|
|
14
|
+
}
|
|
15
|
+
export interface ResolvedQtiMigrationOptions {
|
|
16
|
+
readonly repairPolicy: QtiMigrationRepairPolicy;
|
|
17
|
+
readonly unsupportedPolicy: QtiMigrationUnsupportedPolicy;
|
|
18
|
+
}
|
|
19
|
+
export interface QtiMigrationDetectionResult {
|
|
20
|
+
readonly supported: boolean;
|
|
21
|
+
readonly sourceFormat?: QtiMigrationSourceFormat | undefined;
|
|
22
|
+
readonly confidence: number;
|
|
23
|
+
readonly reason: string;
|
|
24
|
+
readonly isPackage: boolean;
|
|
25
|
+
}
|
|
26
|
+
export type QtiMigrationDiagnosticSeverity = "info" | "warning" | "error";
|
|
27
|
+
export interface QtiMigrationDiagnostic {
|
|
28
|
+
readonly code: string;
|
|
29
|
+
readonly severity: QtiMigrationDiagnosticSeverity;
|
|
30
|
+
readonly message: string;
|
|
31
|
+
readonly path?: string | undefined;
|
|
32
|
+
readonly sourceFormat?: QtiMigrationSourceFormat | undefined;
|
|
33
|
+
readonly writerDiagnostics?: readonly Qti3WriterDiagnostic[] | undefined;
|
|
34
|
+
}
|
|
35
|
+
export interface QtiMigrationPart {
|
|
36
|
+
readonly identifier: string;
|
|
37
|
+
readonly title: string;
|
|
38
|
+
readonly itemHrefs: readonly string[];
|
|
39
|
+
}
|
|
40
|
+
export interface QtiMigrationAsset {
|
|
41
|
+
readonly path: string;
|
|
42
|
+
readonly data?: Uint8Array | undefined;
|
|
43
|
+
readonly mediaType?: string | undefined;
|
|
44
|
+
}
|
|
45
|
+
export interface QtiMigrationItemResult {
|
|
46
|
+
readonly identifier: string;
|
|
47
|
+
readonly title: string;
|
|
48
|
+
readonly href: string;
|
|
49
|
+
readonly authoringItem?: Qti3AuthoringItem | undefined;
|
|
50
|
+
readonly xml?: string | undefined;
|
|
51
|
+
readonly diagnostics: readonly QtiMigrationDiagnostic[];
|
|
52
|
+
}
|
|
53
|
+
export interface QtiMigrationResult {
|
|
54
|
+
readonly title: string;
|
|
55
|
+
readonly sourceFormat?: QtiMigrationSourceFormat | undefined;
|
|
56
|
+
readonly parts: readonly QtiMigrationPart[];
|
|
57
|
+
readonly items: readonly QtiMigrationItemResult[];
|
|
58
|
+
readonly assets: readonly QtiMigrationAsset[];
|
|
59
|
+
readonly diagnostics: readonly QtiMigrationDiagnostic[];
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/dist/xml.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type XmlDocument = Document;
|
|
2
|
+
export type XmlElement = Element;
|
|
3
|
+
export type XmlNode = Node;
|
|
4
|
+
export declare function parseXml(xml: string, context: string): XmlDocument;
|
|
5
|
+
export declare function serializeNode(node: XmlNode): string;
|
|
6
|
+
export declare function serializeChildren(element: XmlElement): string;
|
|
7
|
+
export declare function attr(element: XmlElement | null | undefined, key: string): string | null;
|
|
8
|
+
export declare function localName(element: XmlElement | null | undefined): string;
|
|
9
|
+
export declare function childElements(node: XmlElement): XmlElement[];
|
|
10
|
+
export declare function findDescendantByLocalName(root: XmlElement | null | undefined, tag: string): XmlElement | null;
|
|
11
|
+
export declare function findAllDescendantsByLocalName(root: XmlElement | null | undefined, tag: string): XmlElement[];
|
|
12
|
+
export declare function findAllDescendantsByAnyLocalName(root: XmlElement | null | undefined, tags: readonly string[]): XmlElement[];
|
|
13
|
+
export declare function toNumber(value: string | null | undefined): number | undefined;
|
|
14
|
+
export declare function textOf(element: XmlElement | null | undefined): string;
|
|
15
|
+
export declare function isXmlElement(node: XmlNode | null): node is XmlElement;
|
|
16
|
+
//# sourceMappingURL=xml.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"xml.d.ts","sourceRoot":"","sources":["../src/xml.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,WAAW,GAAG,QAAQ,CAAC;AACnC,MAAM,MAAM,UAAU,GAAG,OAAO,CAAC;AACjC,MAAM,MAAM,OAAO,GAAG,IAAI,CAAC;AAK3B,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,WAAW,CAMlE;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAEnD;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,UAAU,GAAG,MAAM,CAO7D;AAED,wBAAgB,IAAI,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkBvF;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAGxE;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,UAAU,EAAE,CAO5D;AAED,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS,EACnC,GAAG,EAAE,MAAM,GACV,UAAU,GAAG,IAAI,CASnB;AAED,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS,EACnC,GAAG,EAAE,MAAM,GACV,UAAU,EAAE,CAEd;AAED,wBAAgB,gCAAgC,CAC9C,IAAI,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS,EACnC,IAAI,EAAE,SAAS,MAAM,EAAE,GACtB,UAAU,EAAE,CAYd;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAI7E;AAED,wBAAgB,MAAM,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAErE;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,GAAG,IAAI,IAAI,UAAU,CAErE"}
|
package/dist/xml.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { DOMParser, XMLSerializer } from "@xmldom/xmldom";
|
|
2
|
+
const parser = new DOMParser();
|
|
3
|
+
const serializer = new XMLSerializer();
|
|
4
|
+
export function parseXml(xml, context) {
|
|
5
|
+
const doc = parser.parseFromString(normalizeXml(xml), "text/xml");
|
|
6
|
+
if (doc.documentElement.nodeName === "parsererror") {
|
|
7
|
+
throw new Error(`Failed to parse XML (${context}).`);
|
|
8
|
+
}
|
|
9
|
+
return doc;
|
|
10
|
+
}
|
|
11
|
+
export function serializeNode(node) {
|
|
12
|
+
return serializer.serializeToString(node);
|
|
13
|
+
}
|
|
14
|
+
export function serializeChildren(element) {
|
|
15
|
+
let out = "";
|
|
16
|
+
for (let index = 0; index < element.childNodes.length; index += 1) {
|
|
17
|
+
const child = element.childNodes.item(index);
|
|
18
|
+
out += serializeNode(child);
|
|
19
|
+
}
|
|
20
|
+
return out;
|
|
21
|
+
}
|
|
22
|
+
export function attr(element, key) {
|
|
23
|
+
if (!element)
|
|
24
|
+
return null;
|
|
25
|
+
const alternate = key.includes("-")
|
|
26
|
+
? key.replace(/-([a-z])/g, (_match, char) => char.toUpperCase())
|
|
27
|
+
: key.replace(/[A-Z]/g, (char) => `-${char.toLowerCase()}`);
|
|
28
|
+
const target = key.toLowerCase();
|
|
29
|
+
for (let index = 0; index < element.attributes.length; index += 1) {
|
|
30
|
+
const attribute = element.attributes.item(index);
|
|
31
|
+
if (!attribute)
|
|
32
|
+
continue;
|
|
33
|
+
if (attribute.name === key ||
|
|
34
|
+
attribute.name === alternate ||
|
|
35
|
+
attribute.name.toLowerCase() === target) {
|
|
36
|
+
return attribute.value;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
export function localName(element) {
|
|
42
|
+
const raw = element?.localName ?? element?.nodeName ?? "";
|
|
43
|
+
return (raw.includes(":") ? (raw.split(":").pop() ?? raw) : raw).toLowerCase();
|
|
44
|
+
}
|
|
45
|
+
export function childElements(node) {
|
|
46
|
+
const out = [];
|
|
47
|
+
for (let index = 0; index < node.childNodes.length; index += 1) {
|
|
48
|
+
const child = node.childNodes.item(index);
|
|
49
|
+
if (isXmlElement(child))
|
|
50
|
+
out.push(child);
|
|
51
|
+
}
|
|
52
|
+
return out;
|
|
53
|
+
}
|
|
54
|
+
export function findDescendantByLocalName(root, tag) {
|
|
55
|
+
if (!root)
|
|
56
|
+
return null;
|
|
57
|
+
const target = tag.toLowerCase();
|
|
58
|
+
for (const child of childElements(root)) {
|
|
59
|
+
if (localName(child) === target)
|
|
60
|
+
return child;
|
|
61
|
+
const nested = findDescendantByLocalName(child, target);
|
|
62
|
+
if (nested)
|
|
63
|
+
return nested;
|
|
64
|
+
}
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
export function findAllDescendantsByLocalName(root, tag) {
|
|
68
|
+
return findAllDescendantsByAnyLocalName(root, [tag]);
|
|
69
|
+
}
|
|
70
|
+
export function findAllDescendantsByAnyLocalName(root, tags) {
|
|
71
|
+
if (!root)
|
|
72
|
+
return [];
|
|
73
|
+
const tagSet = new Set(tags.map((tag) => tag.toLowerCase()));
|
|
74
|
+
const matches = [];
|
|
75
|
+
const walk = (node) => {
|
|
76
|
+
for (const child of childElements(node)) {
|
|
77
|
+
if (tagSet.has(localName(child)))
|
|
78
|
+
matches.push(child);
|
|
79
|
+
if (child.childNodes.length)
|
|
80
|
+
walk(child);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
walk(root);
|
|
84
|
+
return matches;
|
|
85
|
+
}
|
|
86
|
+
export function toNumber(value) {
|
|
87
|
+
if (value == null || value.trim() === "")
|
|
88
|
+
return undefined;
|
|
89
|
+
const num = Number(value);
|
|
90
|
+
return Number.isFinite(num) ? num : undefined;
|
|
91
|
+
}
|
|
92
|
+
export function textOf(element) {
|
|
93
|
+
return (element?.textContent ?? "").trim();
|
|
94
|
+
}
|
|
95
|
+
export function isXmlElement(node) {
|
|
96
|
+
return node?.nodeType === 1;
|
|
97
|
+
}
|
|
98
|
+
function normalizeXml(xml) {
|
|
99
|
+
return xml.replace(/^\uFEFF/, "").trimStart();
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=xml.js.map
|
package/dist/xml.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"xml.js","sourceRoot":"","sources":["../src/xml.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAM1D,MAAM,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;AAC/B,MAAM,UAAU,GAAG,IAAI,aAAa,EAAE,CAAC;AAEvC,MAAM,UAAU,QAAQ,CAAC,GAAW,EAAE,OAAe;IACnD,MAAM,GAAG,GAAG,MAAM,CAAC,eAAe,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,UAAU,CAAC,CAAC;IAClE,IAAI,GAAG,CAAC,eAAe,CAAC,QAAQ,KAAK,aAAa,EAAE,CAAC;QACnD,MAAM,IAAI,KAAK,CAAC,wBAAwB,OAAO,IAAI,CAAC,CAAC;IACvD,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAa;IACzC,OAAO,UAAU,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,OAAmB;IACnD,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC,UAAU,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QAClE,MAAM,KAAK,GAAG,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC7C,GAAG,IAAI,aAAa,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,OAAsC,EAAE,GAAW;IACtE,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,MAAM,SAAS,GAAG,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC;QACjC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,MAAM,EAAE,IAAY,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QACxE,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IAC9D,MAAM,MAAM,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;IACjC,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC,UAAU,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QAClE,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACjD,IAAI,CAAC,SAAS;YAAE,SAAS;QACzB,IACE,SAAS,CAAC,IAAI,KAAK,GAAG;YACtB,SAAS,CAAC,IAAI,KAAK,SAAS;YAC5B,SAAS,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,MAAM,EACvC,CAAC;YACD,OAAO,SAAS,CAAC,KAAK,CAAC;QACzB,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,OAAsC;IAC9D,MAAM,GAAG,GAAG,OAAO,EAAE,SAAS,IAAI,OAAO,EAAE,QAAQ,IAAI,EAAE,CAAC;IAC1D,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;AACjF,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAgB;IAC5C,MAAM,GAAG,GAAiB,EAAE,CAAC;IAC7B,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QAC/D,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1C,IAAI,YAAY,CAAC,KAAK,CAAC;YAAE,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC3C,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,yBAAyB,CACvC,IAAmC,EACnC,GAAW;IAEX,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,MAAM,MAAM,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;IACjC,KAAK,MAAM,KAAK,IAAI,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;QACxC,IAAI,SAAS,CAAC,KAAK,CAAC,KAAK,MAAM;YAAE,OAAO,KAAK,CAAC;QAC9C,MAAM,MAAM,GAAG,yBAAyB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QACxD,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC;IAC5B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,6BAA6B,CAC3C,IAAmC,EACnC,GAAW;IAEX,OAAO,gCAAgC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,gCAAgC,CAC9C,IAAmC,EACnC,IAAuB;IAEvB,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,CAAC;IACrB,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IAC7D,MAAM,OAAO,GAAiB,EAAE,CAAC;IACjC,MAAM,IAAI,GAAG,CAAC,IAAgB,EAAQ,EAAE;QACtC,KAAK,MAAM,KAAK,IAAI,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;YACxC,IAAI,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;gBAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACtD,IAAI,KAAK,CAAC,UAAU,CAAC,MAAM;gBAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC,CAAC;IACF,IAAI,CAAC,IAAI,CAAC,CAAC;IACX,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,KAAgC;IACvD,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,SAAS,CAAC;IAC3D,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC1B,OAAO,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,OAAsC;IAC3D,OAAO,CAAC,OAAO,EAAE,WAAW,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAoB;IAC/C,OAAO,IAAI,EAAE,QAAQ,KAAK,CAAC,CAAC;AAC9B,CAAC;AAED,SAAS,YAAY,CAAC,GAAW;IAC/B,OAAO,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC;AAChD,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@longsightgroup/qti3-migrator",
|
|
3
|
+
"version": "0.9.5",
|
|
4
|
+
"description": "Framework-neutral QTI 1.2 and QTI 2.x to QTI 3 migration utilities.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"assessment",
|
|
7
|
+
"migration",
|
|
8
|
+
"qti",
|
|
9
|
+
"qti3",
|
|
10
|
+
"typescript",
|
|
11
|
+
"xml"
|
|
12
|
+
],
|
|
13
|
+
"homepage": "https://github.com/LongsightGroup/qti3/tree/main/packages/migrator#readme",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/LongsightGroup/qti3/issues"
|
|
16
|
+
},
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"author": {
|
|
19
|
+
"name": "Sam Ottenhoff",
|
|
20
|
+
"url": "https://github.com/ottenhoff"
|
|
21
|
+
},
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "git+https://github.com/LongsightGroup/qti3.git",
|
|
25
|
+
"directory": "packages/migrator"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"dist/**/*.d.ts",
|
|
29
|
+
"dist/**/*.d.ts.map",
|
|
30
|
+
"dist/**/*.js",
|
|
31
|
+
"dist/**/*.js.map",
|
|
32
|
+
"!dist/**/*.test.*",
|
|
33
|
+
"!dist/test-helpers.*",
|
|
34
|
+
"src/**/*.ts",
|
|
35
|
+
"!src/**/*.test.ts",
|
|
36
|
+
"!src/test-helpers.ts"
|
|
37
|
+
],
|
|
38
|
+
"type": "module",
|
|
39
|
+
"exports": {
|
|
40
|
+
".": {
|
|
41
|
+
"types": "./dist/index.d.ts",
|
|
42
|
+
"import": "./dist/index.js"
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public",
|
|
47
|
+
"registry": "https://registry.npmjs.org"
|
|
48
|
+
},
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"@xmldom/xmldom": "^0.8.11",
|
|
51
|
+
"fflate": "^0.8.2",
|
|
52
|
+
"@longsightgroup/qti3-core": "0.9.5",
|
|
53
|
+
"@longsightgroup/qti3-writer": "0.9.5"
|
|
54
|
+
},
|
|
55
|
+
"scripts": {}
|
|
56
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
QtiMigrationDiagnostic,
|
|
3
|
+
QtiMigrationDiagnosticSeverity,
|
|
4
|
+
QtiMigrationSourceFormat,
|
|
5
|
+
} from "./types.js";
|
|
6
|
+
|
|
7
|
+
export function diagnostic(
|
|
8
|
+
code: string,
|
|
9
|
+
severity: QtiMigrationDiagnosticSeverity,
|
|
10
|
+
message: string,
|
|
11
|
+
options: {
|
|
12
|
+
readonly path?: string | undefined;
|
|
13
|
+
readonly sourceFormat?: QtiMigrationSourceFormat | undefined;
|
|
14
|
+
} = {},
|
|
15
|
+
): QtiMigrationDiagnostic {
|
|
16
|
+
return { code, severity, message, ...options };
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function hasErrors(diagnostics: readonly QtiMigrationDiagnostic[]): boolean {
|
|
20
|
+
return diagnostics.some((entry) => entry.severity === "error");
|
|
21
|
+
}
|