@qti-editor/core 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/composer/index.d.ts
CHANGED
|
@@ -7,12 +7,13 @@
|
|
|
7
7
|
import type { ResponseProcessingKind } from '@qti-editor/interfaces';
|
|
8
8
|
export interface ComposerItemContext {
|
|
9
9
|
identifier?: string;
|
|
10
|
+
lang?: string;
|
|
10
11
|
title?: string;
|
|
11
12
|
itemBody?: Document;
|
|
12
13
|
}
|
|
13
14
|
export interface ResponseDeclaration {
|
|
14
15
|
identifier: string;
|
|
15
|
-
cardinality: 'single' | 'multiple';
|
|
16
|
+
cardinality: 'single' | 'multiple' | 'ordered';
|
|
16
17
|
baseType: 'identifier' | 'point' | 'string';
|
|
17
18
|
correctResponse?: string;
|
|
18
19
|
stringMapping?: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/composer/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAErE,MAAM,WAAW,mBAAmB;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,QAAQ,GAAG,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/composer/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAErE,MAAM,WAAW,mBAAmB;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,QAAQ,GAAG,UAAU,GAAG,SAAS,CAAC;IAC/C,QAAQ,EAAE,YAAY,GAAG,OAAO,GAAG,QAAQ,CAAC;IAC5C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE;QACd,YAAY,EAAE,MAAM,CAAC;QACrB,OAAO,EAAE,KAAK,CAAC;YACb,MAAM,EAAE,MAAM,CAAC;YACf,WAAW,EAAE,MAAM,CAAC;YACpB,aAAa,EAAE,OAAO,CAAC;SACxB,CAAC,CAAC;KACJ,CAAC;IACF,sBAAsB,CAAC,EAAE,sBAAsB,CAAC;IAChD,WAAW,CAAC,EAAE;QACZ,YAAY,EAAE,MAAM,CAAC;QACrB,OAAO,EAAE,KAAK,CAAC;YACb,KAAK,EAAE,QAAQ,GAAG,MAAM,CAAC;YACzB,MAAM,EAAE,MAAM,CAAC;YACf,WAAW,EAAE,MAAM,CAAC;SACrB,CAAC,CAAC;KACJ,CAAC;IACF,SAAS,EAAE,MAAM,CAAC;CACnB;AAoCD,wBAAgB,2BAA2B,CAAC,YAAY,CAAC,EAAE,OAAO,GAAG,IAAI,GAAG,mBAAmB,EAAE,CAOhG;AAED,wBAAgB,sBAAsB,CAAC,WAAW,CAAC,EAAE,mBAAmB,GAAG,MAAM,CAqHhF;AAgLD,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CA4B7C"}
|
package/dist/composer/index.js
CHANGED
|
@@ -10,6 +10,28 @@ const XSI_NS = 'http://www.w3.org/2001/XMLSchema-instance';
|
|
|
10
10
|
const XML_NS = 'http://www.w3.org/XML/1998/namespace';
|
|
11
11
|
const SCHEMA_LOCATION = 'http://www.imsglobal.org/xsd/imsqtiasi_v3p0 https://purl.imsglobal.org/spec/qti/v3p0/schema/xsd/imsqti_asiv3p0p1_v1p0.xsd';
|
|
12
12
|
const MATCH_CORRECT_TEMPLATE = 'https://purl.imsglobal.org/spec/qti/v3p0/rptemplates/match_correct';
|
|
13
|
+
function parseCorrectResponseValues(declaration) {
|
|
14
|
+
if (!declaration.correctResponse)
|
|
15
|
+
return [];
|
|
16
|
+
if (declaration.cardinality === 'single') {
|
|
17
|
+
return [declaration.correctResponse];
|
|
18
|
+
}
|
|
19
|
+
if (declaration.cardinality === 'ordered') {
|
|
20
|
+
try {
|
|
21
|
+
const parsed = JSON.parse(declaration.correctResponse);
|
|
22
|
+
if (Array.isArray(parsed)) {
|
|
23
|
+
return parsed
|
|
24
|
+
.filter((value) => typeof value === 'string')
|
|
25
|
+
.map(value => value.trim())
|
|
26
|
+
.filter(Boolean);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
// Fall back to comma-separated parsing for malformed or legacy values.
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return declaration.correctResponse.split(',').map(v => v.trim()).filter(Boolean);
|
|
34
|
+
}
|
|
13
35
|
export function extractResponseDeclarations(itemBodyRoot) {
|
|
14
36
|
if (!itemBodyRoot)
|
|
15
37
|
return [];
|
|
@@ -29,7 +51,7 @@ export function buildAssessmentItemXml(itemContext) {
|
|
|
29
51
|
root.setAttribute('title', itemContext.title?.trim() || 'Untitled Item');
|
|
30
52
|
root.setAttribute('adaptive', 'false');
|
|
31
53
|
root.setAttribute('time-dependent', 'false');
|
|
32
|
-
root.setAttributeNS(XML_NS, 'xml:lang', 'en');
|
|
54
|
+
root.setAttributeNS(XML_NS, 'xml:lang', itemContext.lang?.trim() || 'en');
|
|
33
55
|
const sourceBodyDoc = itemContext.itemBody;
|
|
34
56
|
const sourceBodyRoot = sourceBodyDoc?.querySelector('qti-item-body') ??
|
|
35
57
|
(sourceBodyDoc?.documentElement?.tagName.toLowerCase() === 'qti-item-body'
|
|
@@ -46,9 +68,7 @@ export function buildAssessmentItemXml(itemContext) {
|
|
|
46
68
|
responseDeclaration.setAttribute('base-type', declaration.baseType);
|
|
47
69
|
if (declaration.correctResponse) {
|
|
48
70
|
const correctResponse = xmlDoc.createElementNS(QTI_NS, 'qti-correct-response');
|
|
49
|
-
const values = declaration
|
|
50
|
-
? declaration.correctResponse.split(',').map(v => v.trim()).filter(Boolean)
|
|
51
|
-
: [declaration.correctResponse];
|
|
71
|
+
const values = parseCorrectResponseValues(declaration);
|
|
52
72
|
values.forEach(v => {
|
|
53
73
|
const value = xmlDoc.createElementNS(QTI_NS, 'qti-value');
|
|
54
74
|
value.textContent = v;
|
|
@@ -126,6 +146,7 @@ function composeAndNormalizeItemBody(itemBody, xmlDoc) {
|
|
|
126
146
|
elements.forEach(element => {
|
|
127
147
|
const tagName = element.tagName.toLowerCase();
|
|
128
148
|
const handler = getInteractionComposerHandler(tagName);
|
|
149
|
+
const isInteractionCandidate = tagName.endsWith('-interaction') || element.hasAttribute('response-identifier');
|
|
129
150
|
if (handler) {
|
|
130
151
|
const composeResult = handler.compose(element, xmlDoc);
|
|
131
152
|
composeResult.warnings.forEach(warning => {
|
|
@@ -152,7 +173,9 @@ function composeAndNormalizeItemBody(itemBody, xmlDoc) {
|
|
|
152
173
|
}
|
|
153
174
|
return;
|
|
154
175
|
}
|
|
155
|
-
|
|
176
|
+
if (isInteractionCandidate) {
|
|
177
|
+
console.warn(`[QTI Composer] Missing interaction composer handler for ${tagName}; keeping element as-is during compose.`);
|
|
178
|
+
}
|
|
156
179
|
});
|
|
157
180
|
itemBody.querySelectorAll('[correct-response]').forEach(interaction => {
|
|
158
181
|
interaction.removeAttribute('correct-response');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qti-editor/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "QTI semantics, composer registry, and XML export orchestration for QTI Editor",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -19,14 +19,14 @@
|
|
|
19
19
|
}
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@qti-editor/interfaces": "0.
|
|
23
|
-
"@qti-editor/interaction-choice": "0.
|
|
24
|
-
"@qti-editor/interaction-
|
|
25
|
-
"@qti-editor/interaction-
|
|
26
|
-
"@qti-editor/interaction-
|
|
27
|
-
"@qti-editor/interaction-
|
|
28
|
-
"@qti-editor/interaction-text
|
|
29
|
-
"@qti-editor/interaction-
|
|
22
|
+
"@qti-editor/interfaces": "0.2.0",
|
|
23
|
+
"@qti-editor/interaction-choice": "0.2.0",
|
|
24
|
+
"@qti-editor/interaction-inline-choice": "0.2.0",
|
|
25
|
+
"@qti-editor/interaction-match": "0.2.0",
|
|
26
|
+
"@qti-editor/interaction-shared": "0.2.0",
|
|
27
|
+
"@qti-editor/interaction-text-entry": "0.2.0",
|
|
28
|
+
"@qti-editor/interaction-extended-text": "0.2.0",
|
|
29
|
+
"@qti-editor/interaction-select-point": "0.2.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@types/node": "^20.0.0",
|