@timeback/core 0.2.1-beta.20260313023436 → 0.2.1-beta.20260314020510

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/README.md CHANGED
@@ -31,6 +31,8 @@ const analytics = await timeback.edubridge.analytics.summary()
31
31
 
32
32
  // Caliper - learning analytics events
33
33
  await timeback.caliper.events.send(event)
34
+
35
+ // Also available: case, clr, masterytrack, powerpath, qti, webhooks
34
36
  ```
35
37
 
36
38
  ## Managing Multiple Clients
@@ -194,6 +196,12 @@ For standalone usage, install individual packages:
194
196
  bun add @timeback/oneroster
195
197
  bun add @timeback/edubridge
196
198
  bun add @timeback/caliper
199
+ bun add @timeback/case
200
+ bun add @timeback/clr
201
+ bun add @timeback/masterytrack
202
+ bun add @timeback/powerpath
203
+ bun add @timeback/qti
204
+ bun add @timeback/webhooks
197
205
  ```
198
206
 
199
207
  ```typescript
package/dist/qti.d.ts ADDED
@@ -0,0 +1,11 @@
1
+ /**
2
+ * QTI XML parsing utilities, re-exported from `@timeback/qti/parse`.
3
+ *
4
+ * @example
5
+ * ```typescript
6
+ * import { parseQtiXml, extractPrompt } from '@timeback/core/qti'
7
+ * ```
8
+ */
9
+ export { extractChoices, extractCorrectResponse, extractFeedback, extractInteractionAttributes, extractModalFeedback, extractPrompt, extractResponseDeclaration, parseQtiXml, } from '@timeback/qti/parse';
10
+ export type { ParsedQtiItem, QtiChoice, QtiInlineFeedback, QtiInteractionAttributes, QtiModalFeedback, QtiResponseDeclaration, } from '@timeback/qti/parse';
11
+ //# sourceMappingURL=qti.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qti.d.ts","sourceRoot":"","sources":["../src/qti.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EACN,cAAc,EACd,sBAAsB,EACtB,eAAe,EACf,4BAA4B,EAC5B,oBAAoB,EACpB,aAAa,EACb,0BAA0B,EAC1B,WAAW,GACX,MAAM,qBAAqB,CAAA;AAE5B,YAAY,EACX,aAAa,EACb,SAAS,EACT,iBAAiB,EACjB,wBAAwB,EACxB,gBAAgB,EAChB,sBAAsB,GACtB,MAAM,qBAAqB,CAAA"}
package/dist/qti.js ADDED
@@ -0,0 +1,126 @@
1
+ import"./chunk-3j7jywnx.js";
2
+
3
+ // ../qti/src/parse.ts
4
+ function extractPrompt(xml) {
5
+ if (!xml)
6
+ return "";
7
+ const match = xml.match(/<qti-prompt[^>]*>([\s\S]*?)<\/qti-prompt>/i);
8
+ return match?.[1]?.trim() ?? "";
9
+ }
10
+ function extractChoices(xml) {
11
+ if (!xml)
12
+ return [];
13
+ const choices = [];
14
+ const regex = /<qti-simple-choice[^>]*identifier="([^"]+)"[^>]*>([\s\S]*?)<\/qti-simple-choice>/gi;
15
+ let match;
16
+ while ((match = regex.exec(xml)) !== null) {
17
+ let text = match[2] ?? "";
18
+ text = text.replace(/<qti-feedback-inline[\s\S]*?<\/qti-feedback-inline>/gi, "").trim();
19
+ choices.push({ identifier: match[1] ?? "", text });
20
+ }
21
+ return choices;
22
+ }
23
+ function extractCorrectResponse(xml) {
24
+ if (!xml)
25
+ return null;
26
+ const match = xml.match(/<qti-correct-response>\s*<qti-value>([^<]+)<\/qti-value>/i);
27
+ return match?.[1]?.trim() ?? null;
28
+ }
29
+ function extractFeedback(xml) {
30
+ if (!xml)
31
+ return [];
32
+ const feedback = [];
33
+ const regex = /<qti-feedback-inline([^>]*)>([\s\S]*?)<\/qti-feedback-inline>/gi;
34
+ let match;
35
+ while ((match = regex.exec(xml)) !== null) {
36
+ const attrs = match[1] ?? "";
37
+ const outcomeId = attrs.match(/outcome-identifier="([^"]*)"/);
38
+ const id = attrs.match(/(?:^|\s)identifier="([^"]*)"/);
39
+ const showHide = attrs.match(/show-hide="([^"]*)"/);
40
+ feedback.push({
41
+ outcomeIdentifier: outcomeId?.[1] ?? "",
42
+ identifier: id?.[1] ?? "",
43
+ showHide: showHide?.[1] ?? "show",
44
+ content: (match[2] ?? "").trim()
45
+ });
46
+ }
47
+ return feedback;
48
+ }
49
+ function extractModalFeedback(xml) {
50
+ if (!xml)
51
+ return [];
52
+ const modalFeedback = [];
53
+ const regex = /<qti-modal-feedback([^>]*)>([\s\S]*?)<\/qti-modal-feedback>/gi;
54
+ let match;
55
+ while ((match = regex.exec(xml)) !== null) {
56
+ const attrs = match[1] ?? "";
57
+ const outcomeId = attrs.match(/outcome-identifier="([^"]*)"/);
58
+ const id = attrs.match(/(?:^|\s)identifier="([^"]*)"/);
59
+ const showHide = attrs.match(/show-hide="([^"]*)"/);
60
+ let content = match[2] ?? "";
61
+ const bodyMatch = content.match(/<qti-content-body>([\s\S]*?)<\/qti-content-body>/i);
62
+ if (bodyMatch) {
63
+ content = bodyMatch[1] ?? "";
64
+ }
65
+ modalFeedback.push({
66
+ outcomeIdentifier: outcomeId?.[1] ?? "",
67
+ identifier: id?.[1] ?? "",
68
+ showHide: showHide?.[1] ?? "show",
69
+ content: content.trim()
70
+ });
71
+ }
72
+ return modalFeedback;
73
+ }
74
+ function extractInteractionAttributes(xml) {
75
+ if (!xml)
76
+ return null;
77
+ const match = xml.match(/<qti-choice-interaction([^>]*)>/i);
78
+ if (!match)
79
+ return null;
80
+ const attrs = match[1] ?? "";
81
+ const responseId = attrs.match(/response-identifier="([^"]*)"/);
82
+ const shuffle = attrs.match(/shuffle="([^"]*)"/);
83
+ const maxChoices = attrs.match(/max-choices="([^"]*)"/);
84
+ return {
85
+ responseIdentifier: responseId?.[1] ?? "",
86
+ shuffle: shuffle?.[1]?.toLowerCase() === "true",
87
+ maxChoices: maxChoices?.[1] ? parseInt(maxChoices[1], 10) : 1
88
+ };
89
+ }
90
+ function extractResponseDeclaration(xml) {
91
+ if (!xml)
92
+ return null;
93
+ const match = xml.match(/<qti-response-declaration([^>]*)>/i);
94
+ if (!match)
95
+ return null;
96
+ const attrs = match[1] ?? "";
97
+ const identifier = attrs.match(/identifier="([^"]*)"/);
98
+ const cardinality = attrs.match(/cardinality="([^"]*)"/);
99
+ const baseType = attrs.match(/base-type="([^"]*)"/);
100
+ return {
101
+ identifier: identifier?.[1] ?? "",
102
+ cardinality: cardinality?.[1] ?? "",
103
+ baseType: baseType?.[1] ?? null
104
+ };
105
+ }
106
+ function parseQtiXml(xml) {
107
+ return {
108
+ prompt: extractPrompt(xml),
109
+ choices: extractChoices(xml),
110
+ correctAnswer: extractCorrectResponse(xml),
111
+ feedback: extractFeedback(xml),
112
+ modalFeedback: extractModalFeedback(xml),
113
+ interaction: extractInteractionAttributes(xml),
114
+ responseDeclaration: extractResponseDeclaration(xml)
115
+ };
116
+ }
117
+ export {
118
+ parseQtiXml,
119
+ extractResponseDeclaration,
120
+ extractPrompt,
121
+ extractModalFeedback,
122
+ extractInteractionAttributes,
123
+ extractFeedback,
124
+ extractCorrectResponse,
125
+ extractChoices
126
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@timeback/core",
3
- "version": "0.2.1-beta.20260313023436",
3
+ "version": "0.2.1-beta.20260314020510",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -18,6 +18,10 @@
18
18
  "./utils": {
19
19
  "types": "./dist/utils.d.ts",
20
20
  "import": "./dist/utils.js"
21
+ },
22
+ "./qti": {
23
+ "types": "./dist/qti.d.ts",
24
+ "import": "./dist/qti.js"
21
25
  }
22
26
  },
23
27
  "main": "dist/index.js",