@qti-editor/core 1.3.1 → 1.4.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 +5 -1
- package/dist/composer/index.d.ts.map +1 -1
- package/dist/composer/index.js +79 -83
- package/package.json +14 -14
package/dist/composer/index.d.ts
CHANGED
|
@@ -10,12 +10,16 @@ export interface ComposerItemContext {
|
|
|
10
10
|
lang?: string;
|
|
11
11
|
title?: string;
|
|
12
12
|
itemBody?: Document;
|
|
13
|
+
items?: Array<{
|
|
14
|
+
identifier?: string;
|
|
15
|
+
title?: string;
|
|
16
|
+
}>;
|
|
13
17
|
}
|
|
14
18
|
export interface ResponseDeclaration {
|
|
15
19
|
identifier: string;
|
|
16
20
|
cardinality: 'single' | 'multiple' | 'ordered';
|
|
17
21
|
baseType: 'identifier' | 'directedPair' | 'point' | 'string';
|
|
18
|
-
correctResponse?: string;
|
|
22
|
+
correctResponse?: string | string[];
|
|
19
23
|
stringMapping?: {
|
|
20
24
|
defaultValue: number;
|
|
21
25
|
entries: Array<{
|
|
@@ -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,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,QAAQ,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;IACpB,KAAK,CAAC,EAAE,KAAK,CAAC;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACxD;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,QAAQ,GAAG,UAAU,GAAG,SAAS,CAAC;IAC/C,QAAQ,EAAE,YAAY,GAAG,cAAc,GAAG,OAAO,GAAG,QAAQ,CAAC;IAC7D,eAAe,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACpC,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;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAiED,wBAAgB,2BAA2B,CAAC,YAAY,CAAC,EAAE,OAAO,GAAG,IAAI,GAAG,mBAAmB,EAAE,CAOhG;AAkFD,wBAAgB,sBAAsB,CAAC,WAAW,CAAC,EAAE,mBAAmB,GAAG,MAAM,CAyHhF;AAED;;;;;;;;GAQG;AACH,wBAAgB,+BAA+B,CAAC,WAAW,CAAC,EAAE,mBAAmB,GAAG,MAAM,CAmCzF;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,WAAW,CAAC,EAAE,mBAAmB,GAAG,MAAM,CAUtF;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,CAAC,EAAE,mBAAmB,GAAG,MAAM,CAK5E;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,CAAC,EAAE,mBAAmB,GAAG,KAAK,CAAC;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,CAiChI;AAoKD,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CA4B7C"}
|
package/dist/composer/index.js
CHANGED
|
@@ -10,27 +10,52 @@ 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
|
+
const TEXT_ENTRY_INTERACTION_TAG = 'qti-text-entry-interaction';
|
|
14
|
+
const SELECT_POINT_INTERACTION_TAG = 'qti-select-point-interaction';
|
|
15
|
+
const EDITOR_DATA_ATTRIBUTE_MAPPINGS = [
|
|
16
|
+
{ source: 'correct-response', target: 'data-correct-response' },
|
|
17
|
+
{ source: 'correctResponse', target: 'data-correct-response' },
|
|
18
|
+
{ source: 'correctAnswer', target: 'data-correct-response' },
|
|
19
|
+
{ source: 'score', target: 'data-score' },
|
|
20
|
+
];
|
|
21
|
+
const TEXT_ENTRY_DATA_ATTRIBUTE_MAPPINGS = [
|
|
22
|
+
{ source: 'case-sensitive', target: 'data-case-sensitive' },
|
|
23
|
+
];
|
|
24
|
+
const SELECT_POINT_DATA_ATTRIBUTE_MAPPINGS = [
|
|
25
|
+
{ source: 'area-mappings', target: 'data-area-mappings' },
|
|
26
|
+
];
|
|
13
27
|
function parseCorrectResponseValues(declaration) {
|
|
14
|
-
|
|
28
|
+
const value = declaration.correctResponse;
|
|
29
|
+
if (value == null)
|
|
15
30
|
return [];
|
|
31
|
+
if (Array.isArray(value)) {
|
|
32
|
+
return value.map(v => v.trim()).filter(Boolean);
|
|
33
|
+
}
|
|
16
34
|
if (declaration.cardinality === 'single') {
|
|
17
|
-
return [
|
|
35
|
+
return value.length > 0 ? [value] : [];
|
|
18
36
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
37
|
+
return value.split(',').map(v => v.trim()).filter(Boolean);
|
|
38
|
+
}
|
|
39
|
+
function copyEditorDataAttribute(sourceElement, targetElement, source, target) {
|
|
40
|
+
const value = sourceElement.getAttribute(source);
|
|
41
|
+
if (value == null || value.length === 0 || targetElement.hasAttribute(target))
|
|
42
|
+
return;
|
|
43
|
+
targetElement.setAttribute(target, value);
|
|
44
|
+
}
|
|
45
|
+
function preserveEditorDataAttributes(sourceElement, targetElement, tagName) {
|
|
46
|
+
EDITOR_DATA_ATTRIBUTE_MAPPINGS.forEach(({ source, target }) => {
|
|
47
|
+
copyEditorDataAttribute(sourceElement, targetElement, source, target);
|
|
48
|
+
});
|
|
49
|
+
if (tagName === TEXT_ENTRY_INTERACTION_TAG) {
|
|
50
|
+
TEXT_ENTRY_DATA_ATTRIBUTE_MAPPINGS.forEach(({ source, target }) => {
|
|
51
|
+
copyEditorDataAttribute(sourceElement, targetElement, source, target);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
if (tagName === SELECT_POINT_INTERACTION_TAG) {
|
|
55
|
+
SELECT_POINT_DATA_ATTRIBUTE_MAPPINGS.forEach(({ source, target }) => {
|
|
56
|
+
copyEditorDataAttribute(sourceElement, targetElement, source, target);
|
|
57
|
+
});
|
|
32
58
|
}
|
|
33
|
-
return declaration.correctResponse.split(',').map(v => v.trim()).filter(Boolean);
|
|
34
59
|
}
|
|
35
60
|
export function extractResponseDeclarations(itemBodyRoot) {
|
|
36
61
|
if (!itemBodyRoot)
|
|
@@ -128,7 +153,7 @@ export function buildAssessmentItemXml(itemContext) {
|
|
|
128
153
|
const composedItemBody = sourceBodyRoot != null
|
|
129
154
|
? xmlDoc.importNode(sourceBodyRoot, true)
|
|
130
155
|
: xmlDoc.createElementNS(QTI_NS, 'qti-item-body');
|
|
131
|
-
const { declarations, responseTemplate, maxScore } = composeAndNormalizeItemBody(composedItemBody, xmlDoc);
|
|
156
|
+
const { declarations, responseTemplate, maxScore, hasAutomatedProcessing } = composeAndNormalizeItemBody(composedItemBody, xmlDoc);
|
|
132
157
|
declarations.forEach(declaration => {
|
|
133
158
|
const responseDeclaration = xmlDoc.createElementNS(QTI_NS, 'qti-response-declaration');
|
|
134
159
|
responseDeclaration.setAttribute('identifier', declaration.identifier);
|
|
@@ -182,7 +207,7 @@ export function buildAssessmentItemXml(itemContext) {
|
|
|
182
207
|
outcomeDeclaration.appendChild(scoreDefaultValue);
|
|
183
208
|
root.appendChild(outcomeDeclaration);
|
|
184
209
|
const maxScoreOutcomeDeclaration = xmlDoc.createElementNS(QTI_NS, 'qti-outcome-declaration');
|
|
185
|
-
maxScoreOutcomeDeclaration.setAttribute('identifier', '
|
|
210
|
+
maxScoreOutcomeDeclaration.setAttribute('identifier', 'MAXSCORE');
|
|
186
211
|
maxScoreOutcomeDeclaration.setAttribute('cardinality', 'single');
|
|
187
212
|
maxScoreOutcomeDeclaration.setAttribute('base-type', 'float');
|
|
188
213
|
const maxScoreDefaultValue = xmlDoc.createElementNS(QTI_NS, 'qti-default-value');
|
|
@@ -193,17 +218,20 @@ export function buildAssessmentItemXml(itemContext) {
|
|
|
193
218
|
root.appendChild(maxScoreOutcomeDeclaration);
|
|
194
219
|
}
|
|
195
220
|
root.appendChild(composedItemBody);
|
|
196
|
-
if (maxScore > 0) {
|
|
197
|
-
|
|
221
|
+
if (maxScore > 0 && hasAutomatedProcessing) {
|
|
222
|
+
const single = declarations.length === 1 ? declarations[0] : null;
|
|
223
|
+
const canUseTemplate = single !== null &&
|
|
224
|
+
!(single.responseProcessingKind === 'match_correct' && (single.score ?? 1) !== 1);
|
|
225
|
+
if (canUseTemplate) {
|
|
198
226
|
const responseProcessing = xmlDoc.createElementNS(QTI_NS, 'qti-response-processing');
|
|
199
227
|
responseProcessing.setAttribute('template', responseTemplate);
|
|
200
228
|
root.appendChild(responseProcessing);
|
|
201
229
|
}
|
|
202
|
-
else
|
|
230
|
+
else {
|
|
203
231
|
root.appendChild(buildMultiInteractionResponseProcessing(xmlDoc, declarations));
|
|
204
232
|
}
|
|
205
233
|
}
|
|
206
|
-
return new XMLSerializer().serializeToString(xmlDoc);
|
|
234
|
+
return new XMLSerializer().serializeToString(xmlDoc).replace(/\s+xmlns=""/g, '');
|
|
207
235
|
}
|
|
208
236
|
/**
|
|
209
237
|
* Build multiple QTI assessment items from a single editor document.
|
|
@@ -228,12 +256,13 @@ export function buildMultipleAssessmentItemsXml(itemContext) {
|
|
|
228
256
|
const lang = itemContext.lang?.trim() || 'en';
|
|
229
257
|
const itemXmls = fragments.map((fragmentBody, index) => {
|
|
230
258
|
const itemNumber = index + 1;
|
|
259
|
+
const perItem = itemContext.items?.[index];
|
|
231
260
|
const fragmentDoc = document.implementation.createDocument(QTI_NS, 'qti-item-body', null);
|
|
232
261
|
const importedFragment = fragmentDoc.importNode(fragmentBody, true);
|
|
233
262
|
fragmentDoc.replaceChild(importedFragment, fragmentDoc.documentElement);
|
|
234
263
|
const fragmentContext = {
|
|
235
|
-
identifier: `${baseIdentifier}-${itemNumber}`,
|
|
236
|
-
title: `${baseTitle} ${itemNumber}`,
|
|
264
|
+
identifier: perItem?.identifier?.trim() || `${baseIdentifier}-${itemNumber}`,
|
|
265
|
+
title: perItem?.title?.trim() || `${baseTitle} ${itemNumber}`,
|
|
237
266
|
lang,
|
|
238
267
|
itemBody: fragmentDoc,
|
|
239
268
|
};
|
|
@@ -278,33 +307,27 @@ export function getItemFragmentXmls(itemContext) {
|
|
|
278
307
|
const fragments = splitItemBodyAtDividers(itemContext.itemBody);
|
|
279
308
|
// If only one fragment (no dividers), return single item
|
|
280
309
|
if (fragments.length <= 1) {
|
|
281
|
-
const
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
}];
|
|
310
|
+
const perItem = itemContext.items?.[0];
|
|
311
|
+
const identifier = perItem?.identifier?.trim() || itemContext.identifier?.trim() || 'item-1';
|
|
312
|
+
const title = perItem?.title?.trim() || itemContext.title?.trim() || 'Untitled Item';
|
|
313
|
+
const xml = buildAssessmentItemXml({ ...itemContext, identifier, title });
|
|
314
|
+
return [{ identifier, title, xml }];
|
|
287
315
|
}
|
|
288
316
|
const baseIdentifier = itemContext.identifier?.trim() || 'item';
|
|
289
317
|
const baseTitle = itemContext.title?.trim() || 'Untitled Item';
|
|
290
318
|
const lang = itemContext.lang?.trim() || 'en';
|
|
291
319
|
return fragments.map((fragmentBody, index) => {
|
|
292
320
|
const itemNumber = index + 1;
|
|
321
|
+
const perItem = itemContext.items?.[index];
|
|
322
|
+
const identifier = perItem?.identifier?.trim() || `${baseIdentifier}-${itemNumber}`;
|
|
323
|
+
const title = perItem?.title?.trim() || `${baseTitle} ${itemNumber}`;
|
|
293
324
|
const fragmentDoc = document.implementation.createDocument(QTI_NS, 'qti-item-body', null);
|
|
294
325
|
const importedFragment = fragmentDoc.importNode(fragmentBody, true);
|
|
295
326
|
fragmentDoc.replaceChild(importedFragment, fragmentDoc.documentElement);
|
|
296
|
-
const identifier = `${baseIdentifier}-${itemNumber}`;
|
|
297
|
-
const title = `${baseTitle} ${itemNumber}`;
|
|
298
|
-
const fragmentContext = {
|
|
299
|
-
identifier,
|
|
300
|
-
title,
|
|
301
|
-
lang,
|
|
302
|
-
itemBody: fragmentDoc,
|
|
303
|
-
};
|
|
304
327
|
return {
|
|
305
328
|
identifier,
|
|
306
329
|
title,
|
|
307
|
-
xml: buildAssessmentItemXml(
|
|
330
|
+
xml: buildAssessmentItemXml({ identifier, title, lang, itemBody: fragmentDoc }),
|
|
308
331
|
};
|
|
309
332
|
});
|
|
310
333
|
}
|
|
@@ -320,6 +343,7 @@ function composeAndNormalizeItemBody(itemBody, xmlDoc) {
|
|
|
320
343
|
const isInteractionCandidate = tagName.endsWith('-interaction') || element.hasAttribute('response-identifier');
|
|
321
344
|
if (handler) {
|
|
322
345
|
const composeResult = handler.compose(element, xmlDoc);
|
|
346
|
+
preserveEditorDataAttributes(element, composeResult.normalizedElement, tagName);
|
|
323
347
|
composeResult.warnings.forEach(warning => {
|
|
324
348
|
console.warn(`[QTI Composer] ${warning.message}`);
|
|
325
349
|
});
|
|
@@ -342,14 +366,17 @@ function composeAndNormalizeItemBody(itemBody, xmlDoc) {
|
|
|
342
366
|
if (composeResult.responseDeclaration) {
|
|
343
367
|
maxScore += composeResult.responseDeclaration.score ?? 1;
|
|
344
368
|
}
|
|
345
|
-
if (composeResult.responseDeclaration
|
|
369
|
+
if (composeResult.responseDeclaration) {
|
|
370
|
+
const declaration = composeResult.responseDeclaration;
|
|
371
|
+
if (seenIdentifiers.has(declaration.identifier)) {
|
|
372
|
+
const freshId = `RESPONSE_${crypto.randomUUID()}`;
|
|
373
|
+
composeResult.normalizedElement.setAttribute('response-identifier', freshId);
|
|
374
|
+
declaration.identifier = freshId;
|
|
375
|
+
}
|
|
346
376
|
const responseProcessingKind = composeResult
|
|
347
377
|
.responseProcessingKind;
|
|
348
|
-
declarations.push({
|
|
349
|
-
|
|
350
|
-
responseProcessingKind,
|
|
351
|
-
});
|
|
352
|
-
seenIdentifiers.add(composeResult.responseDeclaration.identifier);
|
|
378
|
+
declarations.push({ ...declaration, responseProcessingKind });
|
|
379
|
+
seenIdentifiers.add(declaration.identifier);
|
|
353
380
|
}
|
|
354
381
|
if (composeResult.responseProcessingTemplate && composeResult.responseDeclaration) {
|
|
355
382
|
templateCandidates.add(composeResult.responseProcessingTemplate);
|
|
@@ -366,16 +393,17 @@ function composeAndNormalizeItemBody(itemBody, xmlDoc) {
|
|
|
366
393
|
itemBody.querySelectorAll('[score]').forEach(element => {
|
|
367
394
|
element.removeAttribute('score');
|
|
368
395
|
});
|
|
369
|
-
normalizeResponseIdentifiers(itemBody, declarations);
|
|
370
396
|
if (declarations.length === 1 && templateCandidates.size === 1) {
|
|
371
|
-
return { declarations, responseTemplate: Array.from(templateCandidates)[0], maxScore };
|
|
397
|
+
return { declarations, responseTemplate: Array.from(templateCandidates)[0], maxScore, hasAutomatedProcessing: true };
|
|
372
398
|
}
|
|
373
|
-
return { declarations, responseTemplate: MATCH_CORRECT_TEMPLATE, maxScore };
|
|
399
|
+
return { declarations, responseTemplate: MATCH_CORRECT_TEMPLATE, maxScore, hasAutomatedProcessing: templateCandidates.size > 0 };
|
|
374
400
|
}
|
|
375
401
|
function buildMultiInteractionResponseProcessing(xmlDoc, declarations) {
|
|
376
402
|
const responseProcessing = xmlDoc.createElementNS(QTI_NS, 'qti-response-processing');
|
|
377
403
|
declarations.forEach(declaration => {
|
|
378
|
-
|
|
404
|
+
if (declaration.responseProcessingKind === undefined)
|
|
405
|
+
return;
|
|
406
|
+
const kind = declaration.responseProcessingKind;
|
|
379
407
|
if (kind === 'match_correct') {
|
|
380
408
|
responseProcessing.appendChild(createMatchCorrectContribution(xmlDoc, declaration.identifier, declaration.score ?? 1));
|
|
381
409
|
return;
|
|
@@ -408,16 +436,12 @@ function createMatchCorrectContribution(xmlDoc, responseIdentifier, score = 1) {
|
|
|
408
436
|
}
|
|
409
437
|
function createMapResponseContribution(xmlDoc, responseIdentifier) {
|
|
410
438
|
const mapResponse = xmlDoc.createElementNS(QTI_NS, 'qti-map-response');
|
|
411
|
-
|
|
412
|
-
variable.setAttribute('identifier', responseIdentifier);
|
|
413
|
-
mapResponse.appendChild(variable);
|
|
439
|
+
mapResponse.setAttribute('identifier', responseIdentifier);
|
|
414
440
|
return createScoreIncrement(xmlDoc, mapResponse);
|
|
415
441
|
}
|
|
416
442
|
function createMapResponsePointContribution(xmlDoc, responseIdentifier) {
|
|
417
443
|
const mapResponsePoint = xmlDoc.createElementNS(QTI_NS, 'qti-map-response-point');
|
|
418
|
-
|
|
419
|
-
variable.setAttribute('identifier', responseIdentifier);
|
|
420
|
-
mapResponsePoint.appendChild(variable);
|
|
444
|
+
mapResponsePoint.setAttribute('identifier', responseIdentifier);
|
|
421
445
|
return createScoreIncrement(xmlDoc, mapResponsePoint);
|
|
422
446
|
}
|
|
423
447
|
function createScoreIncrement(xmlDoc, contribution) {
|
|
@@ -431,34 +455,6 @@ function createScoreIncrement(xmlDoc, contribution) {
|
|
|
431
455
|
setOutcomeValue.appendChild(sum);
|
|
432
456
|
return setOutcomeValue;
|
|
433
457
|
}
|
|
434
|
-
function normalizeResponseIdentifiers(itemBody, declarations) {
|
|
435
|
-
if (declarations.length === 0)
|
|
436
|
-
return;
|
|
437
|
-
const identifierMap = new Map();
|
|
438
|
-
if (declarations.length === 1) {
|
|
439
|
-
identifierMap.set(declarations[0].identifier, 'RESPONSE');
|
|
440
|
-
}
|
|
441
|
-
else {
|
|
442
|
-
declarations.forEach((declaration, index) => {
|
|
443
|
-
identifierMap.set(declaration.identifier, `RESPONSE${index + 1}`);
|
|
444
|
-
});
|
|
445
|
-
}
|
|
446
|
-
itemBody.querySelectorAll('[response-identifier]').forEach(interaction => {
|
|
447
|
-
const currentIdentifier = interaction.getAttribute('response-identifier')?.trim();
|
|
448
|
-
if (!currentIdentifier)
|
|
449
|
-
return;
|
|
450
|
-
const mappedIdentifier = identifierMap.get(currentIdentifier);
|
|
451
|
-
if (mappedIdentifier) {
|
|
452
|
-
interaction.setAttribute('response-identifier', mappedIdentifier);
|
|
453
|
-
}
|
|
454
|
-
});
|
|
455
|
-
declarations.forEach(declaration => {
|
|
456
|
-
const mappedIdentifier = identifierMap.get(declaration.identifier);
|
|
457
|
-
if (mappedIdentifier) {
|
|
458
|
-
declaration.identifier = mappedIdentifier;
|
|
459
|
-
}
|
|
460
|
-
});
|
|
461
|
-
}
|
|
462
458
|
export function formatXml(xml) {
|
|
463
459
|
const PADDING = ' ';
|
|
464
460
|
const reg = /(>)(<)(\/*)/g;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qti-editor/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "QTI semantics, composer registry, and XML export orchestration for QTI Editor",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -24,19 +24,19 @@
|
|
|
24
24
|
}
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@qti-editor/interfaces": "1.2.
|
|
28
|
-
"@qti-editor/interaction-associate": "1.2.
|
|
29
|
-
"@qti-editor/interaction-choice": "1.2.
|
|
30
|
-
"@qti-editor/interaction-extended-text": "1.
|
|
31
|
-
"@qti-editor/interaction-gap-match": "1.1.
|
|
32
|
-
"@qti-editor/interaction-hottext": "1.2.
|
|
33
|
-
"@qti-editor/interaction-inline-choice": "1.
|
|
34
|
-
"@qti-editor/interaction-match": "1.2.
|
|
35
|
-
"@qti-editor/interaction-order": "0.6.
|
|
36
|
-
"@qti-editor/interaction-select-point": "1.2.
|
|
37
|
-
"@qti-editor/interaction-shared": "1.3.
|
|
38
|
-
"@qti-editor/interaction-text-entry": "1.2.
|
|
39
|
-
"@qti-editor/qti-item-divider": "1.1.
|
|
27
|
+
"@qti-editor/interfaces": "1.2.1",
|
|
28
|
+
"@qti-editor/interaction-associate": "1.2.3",
|
|
29
|
+
"@qti-editor/interaction-choice": "1.2.2",
|
|
30
|
+
"@qti-editor/interaction-extended-text": "1.3.0",
|
|
31
|
+
"@qti-editor/interaction-gap-match": "1.1.1",
|
|
32
|
+
"@qti-editor/interaction-hottext": "1.2.3",
|
|
33
|
+
"@qti-editor/interaction-inline-choice": "1.3.0",
|
|
34
|
+
"@qti-editor/interaction-match": "1.2.1",
|
|
35
|
+
"@qti-editor/interaction-order": "0.6.1",
|
|
36
|
+
"@qti-editor/interaction-select-point": "1.2.1",
|
|
37
|
+
"@qti-editor/interaction-shared": "1.3.1",
|
|
38
|
+
"@qti-editor/interaction-text-entry": "1.2.1",
|
|
39
|
+
"@qti-editor/qti-item-divider": "1.1.2"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@types/node": "^20.0.0",
|