@qti-editor/core 1.3.0 → 1.3.2

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.
@@ -15,7 +15,7 @@ export interface ResponseDeclaration {
15
15
  identifier: string;
16
16
  cardinality: 'single' | 'multiple' | 'ordered';
17
17
  baseType: 'identifier' | 'directedPair' | 'point' | 'string';
18
- correctResponse?: string;
18
+ correctResponse?: string | string[];
19
19
  stringMapping?: {
20
20
  defaultValue: number;
21
21
  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;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"}
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,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,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;AAiMD,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CA4B7C"}
@@ -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
- if (!declaration.correctResponse)
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 [declaration.correctResponse];
35
+ return value.length > 0 ? [value] : [];
18
36
  }
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
- }
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)
@@ -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', 'MAX_SCORE');
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');
@@ -320,6 +345,7 @@ function composeAndNormalizeItemBody(itemBody, xmlDoc) {
320
345
  const isInteractionCandidate = tagName.endsWith('-interaction') || element.hasAttribute('response-identifier');
321
346
  if (handler) {
322
347
  const composeResult = handler.compose(element, xmlDoc);
348
+ preserveEditorDataAttributes(element, composeResult.normalizedElement, tagName);
323
349
  composeResult.warnings.forEach(warning => {
324
350
  console.warn(`[QTI Composer] ${warning.message}`);
325
351
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qti-editor/core",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
4
4
  "description": "QTI semantics, composer registry, and XML export orchestration for QTI Editor",
5
5
  "repository": {
6
6
  "type": "git",
@@ -29,7 +29,7 @@
29
29
  "@qti-editor/interaction-choice": "1.2.1",
30
30
  "@qti-editor/interaction-extended-text": "1.2.1",
31
31
  "@qti-editor/interaction-gap-match": "1.1.0",
32
- "@qti-editor/interaction-hottext": "1.2.1",
32
+ "@qti-editor/interaction-hottext": "1.2.2",
33
33
  "@qti-editor/interaction-inline-choice": "1.2.1",
34
34
  "@qti-editor/interaction-match": "1.2.0",
35
35
  "@qti-editor/interaction-order": "0.6.0",