@qti-editor/core 1.1.1 → 1.3.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.
@@ -34,8 +34,39 @@ export interface ResponseDeclaration {
34
34
  }>;
35
35
  };
36
36
  sourceTag: string;
37
+ score?: number;
37
38
  }
38
39
  export declare function extractResponseDeclarations(itemBodyRoot?: Element | null): ResponseDeclaration[];
39
40
  export declare function buildAssessmentItemXml(itemContext?: ComposerItemContext): string;
41
+ /**
42
+ * Build multiple QTI assessment items from a single editor document.
43
+ *
44
+ * Splits the item body at qti-item-divider elements and generates
45
+ * a separate <qti-assessment-item> for each segment.
46
+ *
47
+ * @returns XML string containing multiple assessment items wrapped in a container,
48
+ * or a single assessment item if no dividers are found.
49
+ */
50
+ export declare function buildMultipleAssessmentItemsXml(itemContext?: ComposerItemContext): string;
51
+ /**
52
+ * Build a single QTI assessment item, converting any dividers to <hr /> elements.
53
+ * Use this when you want to export the entire editor content as one item.
54
+ */
55
+ export declare function buildSingleAssessmentItemXml(itemContext?: ComposerItemContext): string;
56
+ /**
57
+ * Count how many items would be generated from an item body document.
58
+ * Returns 1 if no dividers, or dividers.length + 1 otherwise.
59
+ */
60
+ export declare function countItemFragments(itemContext?: ComposerItemContext): number;
61
+ /**
62
+ * Get an array of individual assessment item XMLs.
63
+ * Each item is generated from a segment between dividers.
64
+ * Returns an array with identifier and XML for each item.
65
+ */
66
+ export declare function getItemFragmentXmls(itemContext?: ComposerItemContext): Array<{
67
+ identifier: string;
68
+ title: string;
69
+ xml: string;
70
+ }>;
40
71
  export declare function formatXml(xml: string): string;
41
72
  //# sourceMappingURL=index.d.ts.map
@@ -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;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,cAAc,GAAG,OAAO,GAAG,QAAQ,CAAC;IAC7D,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"}
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,cAAc,GAAG,OAAO,GAAG,QAAQ,CAAC;IAC7D,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;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAoCD,wBAAgB,2BAA2B,CAAC,YAAY,CAAC,EAAE,OAAO,GAAG,IAAI,GAAG,mBAAmB,EAAE,CAOhG;AAkFD,wBAAgB,sBAAsB,CAAC,WAAW,CAAC,EAAE,mBAAmB,GAAG,MAAM,CAqHhF;AAED;;;;;;;;GAQG;AACH,wBAAgB,+BAA+B,CAAC,WAAW,CAAC,EAAE,mBAAmB,GAAG,MAAM,CAkCzF;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,CAyChI;AAgMD,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CA4B7C"}
@@ -40,6 +40,74 @@ export function extractResponseDeclarations(itemBodyRoot) {
40
40
  const { declarations } = composeAndNormalizeItemBody(tempRoot, tempDoc);
41
41
  return declarations;
42
42
  }
43
+ /**
44
+ * Convert qti-item-divider elements to <hr /> elements.
45
+ * Used when composing a single item that should preserve dividers as visual separators.
46
+ */
47
+ function convertDividersToHr(itemBodyDoc) {
48
+ const itemBodyRoot = itemBodyDoc.querySelector('qti-item-body') ??
49
+ (itemBodyDoc.documentElement?.tagName.toLowerCase() === 'qti-item-body'
50
+ ? itemBodyDoc.documentElement
51
+ : null);
52
+ if (!itemBodyRoot)
53
+ return itemBodyDoc;
54
+ // Clone the document to avoid mutating the original
55
+ const clonedDoc = document.implementation.createDocument(QTI_NS, 'qti-item-body', null);
56
+ const clonedRoot = clonedDoc.importNode(itemBodyRoot, true);
57
+ clonedDoc.replaceChild(clonedRoot, clonedDoc.documentElement);
58
+ // Find and replace all dividers with <hr />
59
+ const dividers = Array.from(clonedRoot.querySelectorAll('qti-item-divider'));
60
+ for (const divider of dividers) {
61
+ const hr = clonedDoc.createElementNS(QTI_NS, 'hr');
62
+ divider.parentNode?.replaceChild(hr, divider);
63
+ }
64
+ return clonedDoc;
65
+ }
66
+ /**
67
+ * Split an item body document at qti-item-divider elements.
68
+ * Returns an array of item body fragments, one for each item.
69
+ */
70
+ function splitItemBodyAtDividers(itemBodyDoc) {
71
+ const itemBodyRoot = itemBodyDoc.querySelector('qti-item-body') ??
72
+ (itemBodyDoc.documentElement?.tagName.toLowerCase() === 'qti-item-body'
73
+ ? itemBodyDoc.documentElement
74
+ : null);
75
+ if (!itemBodyRoot)
76
+ return [];
77
+ // Find all dividers
78
+ const dividers = Array.from(itemBodyRoot.querySelectorAll('qti-item-divider'));
79
+ // If no dividers, return the whole body as a single item
80
+ if (dividers.length === 0) {
81
+ return [itemBodyRoot];
82
+ }
83
+ const fragments = [];
84
+ const children = Array.from(itemBodyRoot.childNodes);
85
+ let currentFragment = [];
86
+ for (const child of children) {
87
+ // Check if this child is a divider
88
+ if (child.nodeType === Node.ELEMENT_NODE &&
89
+ child.tagName.toLowerCase() === 'qti-item-divider') {
90
+ // Save the current fragment if it has content
91
+ if (currentFragment.length > 0) {
92
+ const fragmentBody = itemBodyDoc.createElementNS(QTI_NS, 'qti-item-body');
93
+ currentFragment.forEach(node => fragmentBody.appendChild(node.cloneNode(true)));
94
+ fragments.push(fragmentBody);
95
+ currentFragment = [];
96
+ }
97
+ // Skip the divider itself - it doesn't go into any fragment
98
+ }
99
+ else {
100
+ currentFragment.push(child);
101
+ }
102
+ }
103
+ // Add the last fragment if it has content
104
+ if (currentFragment.length > 0) {
105
+ const fragmentBody = itemBodyDoc.createElementNS(QTI_NS, 'qti-item-body');
106
+ currentFragment.forEach(node => fragmentBody.appendChild(node.cloneNode(true)));
107
+ fragments.push(fragmentBody);
108
+ }
109
+ return fragments;
110
+ }
43
111
  export function buildAssessmentItemXml(itemContext) {
44
112
  if (!itemContext)
45
113
  return '';
@@ -137,6 +205,109 @@ export function buildAssessmentItemXml(itemContext) {
137
205
  }
138
206
  return new XMLSerializer().serializeToString(xmlDoc);
139
207
  }
208
+ /**
209
+ * Build multiple QTI assessment items from a single editor document.
210
+ *
211
+ * Splits the item body at qti-item-divider elements and generates
212
+ * a separate <qti-assessment-item> for each segment.
213
+ *
214
+ * @returns XML string containing multiple assessment items wrapped in a container,
215
+ * or a single assessment item if no dividers are found.
216
+ */
217
+ export function buildMultipleAssessmentItemsXml(itemContext) {
218
+ if (!itemContext?.itemBody)
219
+ return '';
220
+ const fragments = splitItemBodyAtDividers(itemContext.itemBody);
221
+ // If only one fragment (no dividers), use the regular single-item builder
222
+ if (fragments.length <= 1) {
223
+ return buildAssessmentItemXml(itemContext);
224
+ }
225
+ // Build multiple items
226
+ const baseIdentifier = itemContext.identifier?.trim() || 'item';
227
+ const baseTitle = itemContext.title?.trim() || 'Untitled Item';
228
+ const lang = itemContext.lang?.trim() || 'en';
229
+ const itemXmls = fragments.map((fragmentBody, index) => {
230
+ const itemNumber = index + 1;
231
+ const fragmentDoc = document.implementation.createDocument(QTI_NS, 'qti-item-body', null);
232
+ const importedFragment = fragmentDoc.importNode(fragmentBody, true);
233
+ fragmentDoc.replaceChild(importedFragment, fragmentDoc.documentElement);
234
+ const fragmentContext = {
235
+ identifier: `${baseIdentifier}-${itemNumber}`,
236
+ title: `${baseTitle} ${itemNumber}`,
237
+ lang,
238
+ itemBody: fragmentDoc,
239
+ };
240
+ return buildAssessmentItemXml(fragmentContext);
241
+ });
242
+ // Join multiple items with a comment separator for clarity
243
+ const separator = '\n\n<!-- Next Assessment Item -->\n\n';
244
+ return itemXmls.join(separator);
245
+ }
246
+ /**
247
+ * Build a single QTI assessment item, converting any dividers to <hr /> elements.
248
+ * Use this when you want to export the entire editor content as one item.
249
+ */
250
+ export function buildSingleAssessmentItemXml(itemContext) {
251
+ if (!itemContext?.itemBody)
252
+ return '';
253
+ // Convert dividers to <hr /> elements
254
+ const convertedDoc = convertDividersToHr(itemContext.itemBody);
255
+ return buildAssessmentItemXml({
256
+ ...itemContext,
257
+ itemBody: convertedDoc,
258
+ });
259
+ }
260
+ /**
261
+ * Count how many items would be generated from an item body document.
262
+ * Returns 1 if no dividers, or dividers.length + 1 otherwise.
263
+ */
264
+ export function countItemFragments(itemContext) {
265
+ if (!itemContext?.itemBody)
266
+ return 0;
267
+ const fragments = splitItemBodyAtDividers(itemContext.itemBody);
268
+ return fragments.length;
269
+ }
270
+ /**
271
+ * Get an array of individual assessment item XMLs.
272
+ * Each item is generated from a segment between dividers.
273
+ * Returns an array with identifier and XML for each item.
274
+ */
275
+ export function getItemFragmentXmls(itemContext) {
276
+ if (!itemContext?.itemBody)
277
+ return [];
278
+ const fragments = splitItemBodyAtDividers(itemContext.itemBody);
279
+ // If only one fragment (no dividers), return single item
280
+ if (fragments.length <= 1) {
281
+ const xml = buildAssessmentItemXml(itemContext);
282
+ return [{
283
+ identifier: itemContext.identifier?.trim() || 'item-1',
284
+ title: itemContext.title?.trim() || 'Untitled Item',
285
+ xml,
286
+ }];
287
+ }
288
+ const baseIdentifier = itemContext.identifier?.trim() || 'item';
289
+ const baseTitle = itemContext.title?.trim() || 'Untitled Item';
290
+ const lang = itemContext.lang?.trim() || 'en';
291
+ return fragments.map((fragmentBody, index) => {
292
+ const itemNumber = index + 1;
293
+ const fragmentDoc = document.implementation.createDocument(QTI_NS, 'qti-item-body', null);
294
+ const importedFragment = fragmentDoc.importNode(fragmentBody, true);
295
+ 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
+ return {
305
+ identifier,
306
+ title,
307
+ xml: buildAssessmentItemXml(fragmentContext),
308
+ };
309
+ });
310
+ }
140
311
  function composeAndNormalizeItemBody(itemBody, xmlDoc) {
141
312
  const declarations = [];
142
313
  const seenIdentifiers = new Set();
@@ -155,9 +326,21 @@ function composeAndNormalizeItemBody(itemBody, xmlDoc) {
155
326
  const parent = element.parentNode;
156
327
  if (parent) {
157
328
  parent.replaceChild(composeResult.normalizedElement, element);
329
+ // Insert any additional elements (like rubric blocks) after the interaction
330
+ if (composeResult.additionalElements?.length) {
331
+ const nextSibling = composeResult.normalizedElement.nextSibling;
332
+ for (const additionalElement of composeResult.additionalElements) {
333
+ if (nextSibling) {
334
+ parent.insertBefore(additionalElement, nextSibling);
335
+ }
336
+ else {
337
+ parent.appendChild(additionalElement);
338
+ }
339
+ }
340
+ }
158
341
  }
159
342
  if (composeResult.responseDeclaration) {
160
- maxScore += 1;
343
+ maxScore += composeResult.responseDeclaration.score ?? 1;
161
344
  }
162
345
  if (composeResult.responseDeclaration && !seenIdentifiers.has(composeResult.responseDeclaration.identifier)) {
163
346
  const responseProcessingKind = composeResult
@@ -180,6 +363,9 @@ function composeAndNormalizeItemBody(itemBody, xmlDoc) {
180
363
  itemBody.querySelectorAll('[correct-response]').forEach(interaction => {
181
364
  interaction.removeAttribute('correct-response');
182
365
  });
366
+ itemBody.querySelectorAll('[score]').forEach(element => {
367
+ element.removeAttribute('score');
368
+ });
183
369
  normalizeResponseIdentifiers(itemBody, declarations);
184
370
  if (declarations.length === 1 && templateCandidates.size === 1) {
185
371
  return { declarations, responseTemplate: Array.from(templateCandidates)[0], maxScore };
@@ -191,7 +377,7 @@ function buildMultiInteractionResponseProcessing(xmlDoc, declarations) {
191
377
  declarations.forEach(declaration => {
192
378
  const kind = declaration.responseProcessingKind ?? 'match_correct';
193
379
  if (kind === 'match_correct') {
194
- responseProcessing.appendChild(createMatchCorrectContribution(xmlDoc, declaration.identifier));
380
+ responseProcessing.appendChild(createMatchCorrectContribution(xmlDoc, declaration.identifier, declaration.score ?? 1));
195
381
  return;
196
382
  }
197
383
  if (kind === 'map_response') {
@@ -202,7 +388,7 @@ function buildMultiInteractionResponseProcessing(xmlDoc, declarations) {
202
388
  });
203
389
  return responseProcessing;
204
390
  }
205
- function createMatchCorrectContribution(xmlDoc, responseIdentifier) {
391
+ function createMatchCorrectContribution(xmlDoc, responseIdentifier, score = 1) {
206
392
  const responseCondition = xmlDoc.createElementNS(QTI_NS, 'qti-response-condition');
207
393
  const responseIf = xmlDoc.createElementNS(QTI_NS, 'qti-response-if');
208
394
  const match = xmlDoc.createElementNS(QTI_NS, 'qti-match');
@@ -215,7 +401,7 @@ function createMatchCorrectContribution(xmlDoc, responseIdentifier) {
215
401
  responseIf.appendChild(match);
216
402
  const incrementValue = xmlDoc.createElementNS(QTI_NS, 'qti-base-value');
217
403
  incrementValue.setAttribute('base-type', 'float');
218
- incrementValue.textContent = '1';
404
+ incrementValue.textContent = String(score);
219
405
  responseIf.appendChild(createScoreIncrement(xmlDoc, incrementValue));
220
406
  responseCondition.appendChild(responseIf);
221
407
  return responseCondition;
@@ -1 +1 @@
1
- {"version":3,"file":"composer.d.ts","sourceRoot":"","sources":["../../src/interactions/composer.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EACV,0BAA0B,EAC1B,2BAA2B,EAC3B,qBAAqB,EACrB,0BAA0B,EAC3B,MAAM,wBAAwB,CAAC;AAkChC,wBAAgB,8BAA8B,CAAC,OAAO,EAAE,MAAM,GAAG,2BAA2B,GAAG,SAAS,CAEvG;AAED,wBAAgB,4CAA4C,CAC1D,YAAY,EAAE,MAAM,GACnB,2BAA2B,GAAG,SAAS,CAEzC;AAED,wBAAgB,2CAA2C,CACzD,YAAY,EAAE,MAAM,GACnB,0BAA0B,GAAG,SAAS,CAExC;AAED,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,MAAM,GAAG,0BAA0B,GAAG,SAAS,CAErG;AAED,wBAAgB,+BAA+B,IAAI,aAAa,CAAC,0BAA0B,CAAC,CAE3F;AAED,wBAAgB,0BAA0B,IAAI,aAAa,CAAC,qBAAqB,CAAC,CAEjF;AAED,wBAAgB,8BAA8B,IAAI,aAAa,CAC7D,WAAW,CAAC,qBAAqB,CAAC,iBAAiB,CAAC,CAAC,CAAC,MAAM,CAAC,CAC9D,CAEA"}
1
+ {"version":3,"file":"composer.d.ts","sourceRoot":"","sources":["../../src/interactions/composer.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EACV,0BAA0B,EAC1B,2BAA2B,EAC3B,qBAAqB,EACrB,0BAA0B,EAC3B,MAAM,wBAAwB,CAAC;AAoChC,wBAAgB,8BAA8B,CAAC,OAAO,EAAE,MAAM,GAAG,2BAA2B,GAAG,SAAS,CAEvG;AAED,wBAAgB,4CAA4C,CAC1D,YAAY,EAAE,MAAM,GACnB,2BAA2B,GAAG,SAAS,CAEzC;AAED,wBAAgB,2CAA2C,CACzD,YAAY,EAAE,MAAM,GACnB,0BAA0B,GAAG,SAAS,CAExC;AAED,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,MAAM,GAAG,0BAA0B,GAAG,SAAS,CAErG;AAED,wBAAgB,+BAA+B,IAAI,aAAa,CAAC,0BAA0B,CAAC,CAE3F;AAED,wBAAgB,0BAA0B,IAAI,aAAa,CAAC,qBAAqB,CAAC,CAEjF;AAED,wBAAgB,8BAA8B,IAAI,aAAa,CAC7D,WAAW,CAAC,qBAAqB,CAAC,iBAAiB,CAAC,CAAC,CAAC,MAAM,CAAC,CAC9D,CAEA"}
@@ -1,22 +1,26 @@
1
1
  import { associateInteractionDescriptor } from '@qti-editor/interaction-associate';
2
2
  import { choiceInteractionDescriptor } from '@qti-editor/interaction-choice';
3
3
  import { extendedTextInteractionDescriptor } from '@qti-editor/interaction-extended-text';
4
+ import { gapMatchInteractionDescriptor } from '@qti-editor/interaction-gap-match';
4
5
  import { hottextInteractionDescriptor } from '@qti-editor/interaction-hottext';
5
6
  import { inlineChoiceInteractionDescriptor } from '@qti-editor/interaction-inline-choice';
6
7
  import { matchInteractionDescriptor } from '@qti-editor/interaction-match';
7
8
  import { orderInteractionDescriptor } from '@qti-editor/interaction-order';
8
9
  import { selectPointInteractionDescriptor } from '@qti-editor/interaction-select-point';
9
10
  import { textEntryInteractionDescriptor } from '@qti-editor/interaction-text-entry';
11
+ import { qtiItemDividerDescriptor } from '@qti-editor/qti-item-divider';
10
12
  const registeredDescriptors = [
11
13
  associateInteractionDescriptor,
12
14
  choiceInteractionDescriptor,
13
15
  extendedTextInteractionDescriptor,
16
+ gapMatchInteractionDescriptor,
14
17
  hottextInteractionDescriptor,
15
18
  inlineChoiceInteractionDescriptor,
16
19
  matchInteractionDescriptor,
17
20
  orderInteractionDescriptor,
18
21
  selectPointInteractionDescriptor,
19
22
  textEntryInteractionDescriptor,
23
+ qtiItemDividerDescriptor,
20
24
  ];
21
25
  const metadataByTagName = new Map(registeredDescriptors.map(d => [d.tagName, d.composerMetadata]));
22
26
  const metadataByNodeTypeName = new Map(registeredDescriptors.map(d => [d.nodeTypeName.toLowerCase(), d.composerMetadata]));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qti-editor/core",
3
- "version": "1.1.1",
3
+ "version": "1.3.0",
4
4
  "description": "QTI semantics, composer registry, and XML export orchestration for QTI Editor",
5
5
  "repository": {
6
6
  "type": "git",
@@ -24,17 +24,19 @@
24
24
  }
25
25
  },
26
26
  "dependencies": {
27
- "@qti-editor/interfaces": "1.1.0",
28
- "@qti-editor/interaction-associate": "1.1.2",
29
- "@qti-editor/interaction-choice": "1.1.2",
30
- "@qti-editor/interaction-extended-text": "1.1.2",
31
- "@qti-editor/interaction-hottext": "1.1.2",
32
- "@qti-editor/interaction-inline-choice": "1.1.0",
33
- "@qti-editor/interaction-match": "1.1.0",
34
- "@qti-editor/interaction-order": "0.5.0",
35
- "@qti-editor/interaction-select-point": "1.1.0",
36
- "@qti-editor/interaction-shared": "1.1.0",
37
- "@qti-editor/interaction-text-entry": "1.1.1"
27
+ "@qti-editor/interfaces": "1.2.0",
28
+ "@qti-editor/interaction-associate": "1.2.1",
29
+ "@qti-editor/interaction-choice": "1.2.1",
30
+ "@qti-editor/interaction-extended-text": "1.2.1",
31
+ "@qti-editor/interaction-gap-match": "1.1.0",
32
+ "@qti-editor/interaction-hottext": "1.2.1",
33
+ "@qti-editor/interaction-inline-choice": "1.2.1",
34
+ "@qti-editor/interaction-match": "1.2.0",
35
+ "@qti-editor/interaction-order": "0.6.0",
36
+ "@qti-editor/interaction-select-point": "1.2.0",
37
+ "@qti-editor/interaction-shared": "1.3.0",
38
+ "@qti-editor/interaction-text-entry": "1.2.0",
39
+ "@qti-editor/qti-item-divider": "1.1.0"
38
40
  },
39
41
  "devDependencies": {
40
42
  "@types/node": "^20.0.0",