@longsightgroup/qti3-player 0.4.0 → 0.5.4
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 +146 -13
- package/dist/content/content-dom.d.ts +11 -0
- package/dist/content/content-dom.d.ts.map +1 -0
- package/dist/content/content-dom.js +262 -0
- package/dist/content/content-dom.js.map +1 -0
- package/dist/content/content-renderer.d.ts +17 -0
- package/dist/content/content-renderer.d.ts.map +1 -0
- package/dist/content/content-renderer.js +82 -0
- package/dist/content/content-renderer.js.map +1 -0
- package/dist/controls/remove-button.d.ts +3 -0
- package/dist/controls/remove-button.d.ts.map +1 -0
- package/dist/controls/remove-button.js +12 -0
- package/dist/controls/remove-button.js.map +1 -0
- package/dist/index.d.ts +13 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/interactions/choice-interaction.d.ts +4 -0
- package/dist/interactions/choice-interaction.d.ts.map +1 -0
- package/dist/interactions/choice-interaction.js +81 -0
- package/dist/interactions/choice-interaction.js.map +1 -0
- package/dist/interactions/drawing-interaction.d.ts +6 -0
- package/dist/interactions/drawing-interaction.d.ts.map +1 -0
- package/dist/interactions/drawing-interaction.js +401 -0
- package/dist/interactions/drawing-interaction.js.map +1 -0
- package/dist/interactions/end-attempt-interaction.d.ts +4 -0
- package/dist/interactions/end-attempt-interaction.d.ts.map +1 -0
- package/dist/interactions/end-attempt-interaction.js +13 -0
- package/dist/interactions/end-attempt-interaction.js.map +1 -0
- package/dist/interactions/gap-match-interaction.d.ts +4 -0
- package/dist/interactions/gap-match-interaction.d.ts.map +1 -0
- package/dist/interactions/gap-match-interaction.js +277 -0
- package/dist/interactions/gap-match-interaction.js.map +1 -0
- package/dist/interactions/graphic-associate-interaction.d.ts +4 -0
- package/dist/interactions/graphic-associate-interaction.d.ts.map +1 -0
- package/dist/interactions/graphic-associate-interaction.js +297 -0
- package/dist/interactions/graphic-associate-interaction.js.map +1 -0
- package/dist/interactions/graphic-context.d.ts +3 -0
- package/dist/interactions/graphic-context.d.ts.map +1 -0
- package/dist/interactions/graphic-context.js +35 -0
- package/dist/interactions/graphic-context.js.map +1 -0
- package/dist/interactions/hotspot-interaction.d.ts +4 -0
- package/dist/interactions/hotspot-interaction.d.ts.map +1 -0
- package/dist/interactions/hotspot-interaction.js +68 -0
- package/dist/interactions/hotspot-interaction.js.map +1 -0
- package/dist/interactions/hottext-interaction.d.ts +3 -0
- package/dist/interactions/hottext-interaction.d.ts.map +1 -0
- package/dist/interactions/hottext-interaction.js +66 -0
- package/dist/interactions/hottext-interaction.js.map +1 -0
- package/dist/interactions/inline-choice-interaction.d.ts +4 -0
- package/dist/interactions/inline-choice-interaction.d.ts.map +1 -0
- package/dist/interactions/inline-choice-interaction.js +31 -0
- package/dist/interactions/inline-choice-interaction.js.map +1 -0
- package/dist/interactions/inline-controls.d.ts +6 -0
- package/dist/interactions/inline-controls.d.ts.map +1 -0
- package/dist/interactions/inline-controls.js +15 -0
- package/dist/interactions/inline-controls.js.map +1 -0
- package/dist/interactions/interaction-diagnostics.d.ts +7 -0
- package/dist/interactions/interaction-diagnostics.d.ts.map +1 -0
- package/dist/interactions/interaction-diagnostics.js +137 -0
- package/dist/interactions/interaction-diagnostics.js.map +1 -0
- package/dist/interactions/interaction-dispatch.d.ts +2 -0
- package/dist/interactions/interaction-dispatch.d.ts.map +1 -0
- package/dist/interactions/interaction-dispatch.js +2 -0
- package/dist/interactions/interaction-dispatch.js.map +1 -0
- package/dist/interactions/interaction-label.d.ts +4 -0
- package/dist/interactions/interaction-label.d.ts.map +1 -0
- package/dist/interactions/interaction-label.js +8 -0
- package/dist/interactions/interaction-label.js.map +1 -0
- package/dist/interactions/interaction-registry.d.ts +24 -0
- package/dist/interactions/interaction-registry.d.ts.map +1 -0
- package/dist/interactions/interaction-registry.js +138 -0
- package/dist/interactions/interaction-registry.js.map +1 -0
- package/dist/interactions/match-interaction.d.ts +4 -0
- package/dist/interactions/match-interaction.d.ts.map +1 -0
- package/dist/interactions/match-interaction.js +188 -0
- package/dist/interactions/match-interaction.js.map +1 -0
- package/dist/interactions/object-asset.d.ts +8 -0
- package/dist/interactions/object-asset.d.ts.map +1 -0
- package/dist/interactions/object-asset.js +182 -0
- package/dist/interactions/object-asset.js.map +1 -0
- package/dist/interactions/pair-interaction.d.ts +4 -0
- package/dist/interactions/pair-interaction.d.ts.map +1 -0
- package/dist/interactions/pair-interaction.js +125 -0
- package/dist/interactions/pair-interaction.js.map +1 -0
- package/dist/interactions/point-value.d.ts +16 -0
- package/dist/interactions/point-value.d.ts.map +1 -0
- package/dist/interactions/point-value.js +37 -0
- package/dist/interactions/point-value.js.map +1 -0
- package/dist/interactions/portable-custom-interaction.d.ts +16 -0
- package/dist/interactions/portable-custom-interaction.d.ts.map +1 -0
- package/dist/interactions/portable-custom-interaction.js +97 -0
- package/dist/interactions/portable-custom-interaction.js.map +1 -0
- package/dist/interactions/position-object-interaction.d.ts +4 -0
- package/dist/interactions/position-object-interaction.d.ts.map +1 -0
- package/dist/interactions/position-object-interaction.js +177 -0
- package/dist/interactions/position-object-interaction.js.map +1 -0
- package/dist/interactions/routing.d.ts +5 -0
- package/dist/interactions/routing.d.ts.map +1 -0
- package/dist/interactions/routing.js +24 -0
- package/dist/interactions/routing.js.map +1 -0
- package/dist/interactions/select-point-interaction.d.ts +4 -0
- package/dist/interactions/select-point-interaction.d.ts.map +1 -0
- package/dist/interactions/select-point-interaction.js +166 -0
- package/dist/interactions/select-point-interaction.js.map +1 -0
- package/dist/interactions/shared.d.ts +12 -0
- package/dist/interactions/shared.d.ts.map +1 -0
- package/dist/interactions/shared.js +65 -0
- package/dist/interactions/shared.js.map +1 -0
- package/dist/interactions/text-interaction.d.ts +6 -0
- package/dist/interactions/text-interaction.d.ts.map +1 -0
- package/dist/interactions/text-interaction.js +110 -0
- package/dist/interactions/text-interaction.js.map +1 -0
- package/dist/interactions/unsupported-interaction.d.ts +4 -0
- package/dist/interactions/unsupported-interaction.d.ts.map +1 -0
- package/dist/interactions/unsupported-interaction.js +23 -0
- package/dist/interactions/unsupported-interaction.js.map +1 -0
- package/dist/interactions/upload-interaction.d.ts +4 -0
- package/dist/interactions/upload-interaction.d.ts.map +1 -0
- package/dist/interactions/upload-interaction.js +10 -0
- package/dist/interactions/upload-interaction.js.map +1 -0
- package/dist/player/attempt-availability.d.ts +6 -0
- package/dist/player/attempt-availability.d.ts.map +1 -0
- package/dist/player/attempt-availability.js +27 -0
- package/dist/player/attempt-availability.js.map +1 -0
- package/dist/player/content-state.d.ts +19 -0
- package/dist/player/content-state.d.ts.map +1 -0
- package/dist/player/content-state.js +39 -0
- package/dist/player/content-state.js.map +1 -0
- package/dist/player/dynamic-body.d.ts +7 -0
- package/dist/player/dynamic-body.d.ts.map +1 -0
- package/dist/player/dynamic-body.js +28 -0
- package/dist/player/dynamic-body.js.map +1 -0
- package/dist/player/feedback-panel.d.ts +3 -0
- package/dist/player/feedback-panel.d.ts.map +1 -0
- package/dist/player/feedback-panel.js +14 -0
- package/dist/player/feedback-panel.js.map +1 -0
- package/dist/player/fetch-xml.d.ts +2 -0
- package/dist/player/fetch-xml.d.ts.map +1 -0
- package/dist/player/fetch-xml.js +10 -0
- package/dist/player/fetch-xml.js.map +1 -0
- package/dist/player/interaction-render.d.ts +14 -0
- package/dist/player/interaction-render.d.ts.map +1 -0
- package/dist/player/interaction-render.js +51 -0
- package/dist/player/interaction-render.js.map +1 -0
- package/dist/player/render-shell.d.ts +8 -0
- package/dist/player/render-shell.d.ts.map +1 -0
- package/dist/player/render-shell.js +37 -0
- package/dist/player/render-shell.js.map +1 -0
- package/dist/player/resolve-assets.d.ts +3 -0
- package/dist/player/resolve-assets.d.ts.map +1 -0
- package/dist/player/resolve-assets.js +12 -0
- package/dist/player/resolve-assets.js.map +1 -0
- package/dist/player/validation-messages.d.ts +17 -0
- package/dist/player/validation-messages.d.ts.map +1 -0
- package/dist/player/validation-messages.js +33 -0
- package/dist/player/validation-messages.js.map +1 -0
- package/dist/player-adapter.d.ts +62 -0
- package/dist/player-adapter.d.ts.map +1 -0
- package/dist/player-adapter.js +119 -0
- package/dist/player-adapter.js.map +1 -0
- package/dist/player-dev.d.ts +4 -0
- package/dist/player-dev.d.ts.map +1 -0
- package/dist/player-dev.js +14 -0
- package/dist/player-dev.js.map +1 -0
- package/dist/player-element.d.ts +14 -1
- package/dist/player-element.d.ts.map +1 -1
- package/dist/player-element.js +57 -5
- package/dist/player-element.js.map +1 -1
- package/dist/player-locale.d.ts +8 -3
- package/dist/player-locale.d.ts.map +1 -1
- package/dist/player-locale.js +16 -175
- package/dist/player-locale.js.map +1 -1
- package/dist/player-message-catalog-default.d.ts +4 -0
- package/dist/player-message-catalog-default.d.ts.map +1 -0
- package/dist/player-message-catalog-default.js +118 -0
- package/dist/player-message-catalog-default.js.map +1 -0
- package/dist/player-message-catalog-validate.d.ts +31 -0
- package/dist/player-message-catalog-validate.d.ts.map +1 -0
- package/dist/player-message-catalog-validate.js +327 -0
- package/dist/player-message-catalog-validate.js.map +1 -0
- package/dist/player-message-catalog.d.ts +18 -0
- package/dist/player-message-catalog.d.ts.map +1 -0
- package/dist/player-message-catalog.js +40 -0
- package/dist/player-message-catalog.js.map +1 -0
- package/dist/player-message-keys.d.ts +6 -0
- package/dist/player-message-keys.d.ts.map +1 -0
- package/dist/player-message-keys.js +7 -0
- package/dist/player-message-keys.js.map +1 -0
- package/dist/player-message-manifest.d.ts +272 -0
- package/dist/player-message-manifest.d.ts.map +1 -0
- package/dist/player-message-manifest.js +83 -0
- package/dist/player-message-manifest.js.map +1 -0
- package/dist/player-message-overrides.d.ts +3 -0
- package/dist/player-message-overrides.d.ts.map +1 -0
- package/dist/player-message-overrides.js +28 -0
- package/dist/player-message-overrides.js.map +1 -0
- package/dist/player-message-resolver.d.ts +31 -0
- package/dist/player-message-resolver.d.ts.map +1 -0
- package/dist/player-message-resolver.js +110 -0
- package/dist/player-message-resolver.js.map +1 -0
- package/dist/player-messages.d.ts +0 -38
- package/dist/player-messages.d.ts.map +1 -1
- package/dist/player-types.d.ts +12 -2
- package/dist/player-types.d.ts.map +1 -1
- package/dist/reorder/a11y.d.ts +7 -0
- package/dist/reorder/a11y.d.ts.map +1 -0
- package/dist/reorder/a11y.js +34 -0
- package/dist/reorder/a11y.js.map +1 -0
- package/dist/reorder/graphic-order-interaction.d.ts +4 -0
- package/dist/reorder/graphic-order-interaction.d.ts.map +1 -0
- package/dist/reorder/graphic-order-interaction.js +205 -0
- package/dist/reorder/graphic-order-interaction.js.map +1 -0
- package/dist/reorder/list-controls.d.ts +22 -0
- package/dist/reorder/list-controls.d.ts.map +1 -0
- package/dist/reorder/list-controls.js +75 -0
- package/dist/reorder/list-controls.js.map +1 -0
- package/dist/reorder/order-interaction.d.ts +4 -0
- package/dist/reorder/order-interaction.d.ts.map +1 -0
- package/dist/reorder/order-interaction.js +54 -0
- package/dist/reorder/order-interaction.js.map +1 -0
- package/dist/styles/base-styles.d.ts +2 -0
- package/dist/styles/base-styles.d.ts.map +1 -0
- package/dist/styles/base-styles.js +133 -0
- package/dist/styles/base-styles.js.map +1 -0
- package/dist/styles/choice-hottext-styles.d.ts +2 -0
- package/dist/styles/choice-hottext-styles.d.ts.map +1 -0
- package/dist/styles/choice-hottext-styles.js +76 -0
- package/dist/styles/choice-hottext-styles.js.map +1 -0
- package/dist/styles/control-styles.d.ts +2 -0
- package/dist/styles/control-styles.d.ts.map +1 -0
- package/dist/styles/control-styles.js +114 -0
- package/dist/styles/control-styles.js.map +1 -0
- package/dist/styles/drawing-styles.d.ts +2 -0
- package/dist/styles/drawing-styles.d.ts.map +1 -0
- package/dist/styles/drawing-styles.js +30 -0
- package/dist/styles/drawing-styles.js.map +1 -0
- package/dist/styles/gap-match-styles.d.ts +2 -0
- package/dist/styles/gap-match-styles.d.ts.map +1 -0
- package/dist/styles/gap-match-styles.js +33 -0
- package/dist/styles/gap-match-styles.js.map +1 -0
- package/dist/styles/graphic-styles.d.ts +2 -0
- package/dist/styles/graphic-styles.d.ts.map +1 -0
- package/dist/styles/graphic-styles.js +289 -0
- package/dist/styles/graphic-styles.js.map +1 -0
- package/dist/styles/match-pair-styles.d.ts +2 -0
- package/dist/styles/match-pair-styles.d.ts.map +1 -0
- package/dist/styles/match-pair-styles.js +62 -0
- package/dist/styles/match-pair-styles.js.map +1 -0
- package/dist/styles/text-slider-styles.d.ts +2 -0
- package/dist/styles/text-slider-styles.d.ts.map +1 -0
- package/dist/styles/text-slider-styles.js +35 -0
- package/dist/styles/text-slider-styles.js.map +1 -0
- package/package.json +8 -8
- package/src/controls/remove-button.ts +8 -5
- package/src/index.ts +61 -5
- package/src/interactions/choice-interaction.ts +6 -2
- package/src/interactions/drawing-interaction.ts +14 -9
- package/src/interactions/end-attempt-interaction.ts +3 -3
- package/src/interactions/gap-match-interaction.ts +32 -13
- package/src/interactions/graphic-associate-interaction.ts +15 -10
- package/src/interactions/hotspot-interaction.ts +10 -6
- package/src/interactions/inline-choice-interaction.ts +4 -4
- package/src/interactions/interaction-registry.ts +12 -12
- package/src/interactions/match-interaction.ts +9 -6
- package/src/interactions/pair-interaction.ts +22 -14
- package/src/interactions/position-object-interaction.ts +22 -13
- package/src/interactions/select-point-interaction.ts +25 -13
- package/src/interactions/shared.ts +21 -4
- package/src/interactions/text-interaction.ts +14 -4
- package/src/interactions/upload-interaction.ts +6 -3
- package/src/player/interaction-render.ts +4 -4
- package/src/player-adapter.ts +253 -0
- package/src/player-dev.ts +14 -0
- package/src/player-element.ts +78 -8
- package/src/player-locale.ts +28 -199
- package/src/player-message-catalog-default.ts +119 -0
- package/src/player-message-catalog-validate.ts +425 -0
- package/src/player-message-catalog.ts +72 -0
- package/src/player-message-keys.ts +12 -0
- package/src/player-message-manifest.ts +103 -0
- package/src/player-message-overrides.ts +38 -0
- package/src/player-message-resolver.ts +205 -0
- package/src/player-messages.ts +0 -30
- package/src/player-types.ts +15 -4
- package/src/reorder/a11y.ts +22 -7
- package/src/reorder/graphic-order-interaction.ts +23 -16
- package/src/reorder/list-controls.ts +8 -6
- package/src/reorder/order-interaction.ts +7 -5
- package/src/styles/base-styles.ts +20 -5
- package/src/styles/graphic-styles.ts +0 -6
package/README.md
CHANGED
|
@@ -46,25 +46,126 @@ scoring is a convenience for validation, feedback, previews, and response snapsh
|
|
|
46
46
|
High-stakes assessment systems must treat browser outcomes as untrusted and recompute
|
|
47
47
|
scores server-side from authoritative QTI XML and trusted response variables.
|
|
48
48
|
|
|
49
|
-
## Player Chrome Messages
|
|
49
|
+
## Player Chrome Messages (host-owned i18n)
|
|
50
50
|
|
|
51
|
-
The player keeps authored QTI content
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
English. Hosts can override it when delivery settings require a fixed interface language.
|
|
51
|
+
The player keeps **authored QTI content** (prompts, choice labels, `title` on
|
|
52
|
+
end-attempt) separate from **player chrome** (remove buttons, aria labels, live-region
|
|
53
|
+
status, gap labels).
|
|
55
54
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
Only **English** ships in the package. `language-of-interface="sv-SE"` does **not**
|
|
56
|
+
change chrome by itself; the host loads a locale file.
|
|
57
|
+
|
|
58
|
+
### Locale files (recommended)
|
|
59
|
+
|
|
60
|
+
Harbor or an LMS maintains JSON (or ICU/Fluent exported to JSON) with the shape
|
|
61
|
+
`PlayerMessageCatalog`: a flat `strings` map, optional `interactionTypes`, and
|
|
62
|
+
`directions`. Copy `defaultPlayerMessageCatalog` from the package as the template; omit
|
|
63
|
+
keys you do not need to translate (missing keys fall back to English).
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
import type { PlayerMessageCatalog } from "@longsightgroup/qti3-player";
|
|
67
|
+
|
|
68
|
+
const sv = (await fetch("/locales/player/sv-SE.json")).json() as PlayerMessageCatalog;
|
|
69
|
+
|
|
70
|
+
player.languageOfInterface = "sv-SE";
|
|
71
|
+
player.messageCatalog = sv;
|
|
72
|
+
await player.loadXml(xml);
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Example entries:
|
|
76
|
+
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"locale": "sv-SE",
|
|
80
|
+
"strings": {
|
|
81
|
+
"remove": "Ta bort",
|
|
82
|
+
"removePair": "Ta bort {label}",
|
|
83
|
+
"associationPairLabel": "{source} med {target}",
|
|
84
|
+
"extendedTextCounter": "{characters} tecken, {words} ord",
|
|
85
|
+
"associationsMade.one": "{count} koppling skapad.",
|
|
86
|
+
"associationsMade.other": "{count} kopplingar skapade."
|
|
87
|
+
},
|
|
88
|
+
"interactionTypes": {
|
|
89
|
+
"graphicOrder": "Grafisk ordning"
|
|
90
|
+
},
|
|
91
|
+
"directions": { "up": "upp", "down": "ner", "left": "vänster", "right": "höger" }
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Templates use `{placeholder}` names. For English-style singular/plural, use
|
|
96
|
+
`messageKey.one` and `messageKey.other` (for example `associationsMade.one`). Languages
|
|
97
|
+
that do not inflect by count can use a single key (for example one `extendedTextCounter`
|
|
98
|
+
string for all counts).
|
|
99
|
+
|
|
100
|
+
Validate locale files in CI with `validatePlayerMessageCatalog()` — pass `JSON.parse` output
|
|
101
|
+
directly (`unknown`). Shape errors (non-object root, missing `strings`, numeric templates, bad
|
|
102
|
+
`directions` / `interactionTypes`) return diagnostics instead of throwing:
|
|
59
103
|
|
|
60
104
|
```ts
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
105
|
+
import { validatePlayerMessageCatalog } from "@longsightgroup/qti3-player";
|
|
106
|
+
|
|
107
|
+
const raw = JSON.parse(await readFile("locales/player/sv-SE.json", "utf8"));
|
|
108
|
+
const result = validatePlayerMessageCatalog(raw);
|
|
109
|
+
if (!result.valid) {
|
|
110
|
+
for (const issue of result.diagnostics) {
|
|
111
|
+
console.error(`${issue.code} ${issue.key}: ${issue.message}`);
|
|
112
|
+
}
|
|
113
|
+
process.exit(1);
|
|
114
|
+
}
|
|
66
115
|
```
|
|
67
116
|
|
|
117
|
+
Use `requireAllKeys: true` only for complete locale files forked from `defaultPlayerMessageCatalog`.
|
|
118
|
+
Partial delivery catalogs should omit that flag.
|
|
119
|
+
|
|
120
|
+
Reference exports:
|
|
121
|
+
|
|
122
|
+
- `PLAYER_MESSAGE_KEYS` — message ids from `PLAYER_MESSAGE_MANIFEST`
|
|
123
|
+
- `PLAYER_MESSAGE_STRING_KEYS` — all keys in `defaultPlayerMessageCatalog.strings`
|
|
124
|
+
- `defaultPlayerMessageCatalog` — English template to fork
|
|
125
|
+
- `allowedCatalogPlaceholders(entry)` — placeholders a template may use
|
|
126
|
+
- `requiredCatalogPlaceholders(catalogKey)` — placeholders required for that key per English default
|
|
127
|
+
- `createPlayerMessageResolver(catalog)` — canonical key-driven runtime API
|
|
128
|
+
- `PlayerMessageParams<K>` — typed params for `message(key, params)`
|
|
129
|
+
|
|
130
|
+
Resolver kinds in the manifest (hosts only edit `strings`; behavior is fixed):
|
|
131
|
+
|
|
132
|
+
| Resolver | Meaning |
|
|
133
|
+
| --------------------- | ---------------------------------------------------- |
|
|
134
|
+
| `plain` | Static string |
|
|
135
|
+
| `template` | `{placeholder}` interpolation from params |
|
|
136
|
+
| `plural` | Uses `key.one` / `key.other` when `count` is present |
|
|
137
|
+
| `typeLabel` | Interaction type short name from `interactionTypes` |
|
|
138
|
+
| `typeTemplate` | Template with `{typeName}` derived from `type` |
|
|
139
|
+
| `directionTemplate` | Template with localized `{direction}` |
|
|
140
|
+
| `extendedTextCounter` | `{characters}`, `{words}`, and unit plural helpers |
|
|
141
|
+
|
|
142
|
+
### Runtime API
|
|
143
|
+
|
|
144
|
+
Chrome resolves to a key-driven `PlayerMessageResolver`:
|
|
145
|
+
|
|
146
|
+
```ts
|
|
147
|
+
const messages = resolvePlayerMessages(locale, {}, catalog);
|
|
148
|
+
|
|
149
|
+
messages.message("remove");
|
|
150
|
+
messages.message("removePair", { label: pairLabel });
|
|
151
|
+
messages.message("associationsMade", { count: 2 });
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
`createPlayerMessageResolver(catalog)` builds the same resolver directly from a locale file.
|
|
155
|
+
|
|
156
|
+
### Per-message overrides
|
|
157
|
+
|
|
158
|
+
`player.messages` accepts `QtiPlayerMessageOverrides` — each key uses the same param types as
|
|
159
|
+
`message(key, params)` (for example `removePair: ({ label }) => ...`). Use only when a catalog
|
|
160
|
+
entry is not enough; composed strings (for example `removePair` using `associationPairLabel`
|
|
161
|
+
text) are easy to break.
|
|
162
|
+
|
|
163
|
+
### Item language vs interface language
|
|
164
|
+
|
|
165
|
+
Do not copy item `xml:lang` onto `<qti-assessment-item-player lang="...">` unless you
|
|
166
|
+
intentionally want the player element's `lang` attribute to influence
|
|
167
|
+
`defaultPlayerLocale()`. Prefer `player.messageCatalog` for UI chrome.
|
|
168
|
+
|
|
68
169
|
## Portable Custom Interactions
|
|
69
170
|
|
|
70
171
|
For `qti-portable-custom-interaction`, the player renders a
|
|
@@ -75,11 +176,43 @@ definition. Host code can attach a PCI runtime and send response/state updates b
|
|
|
75
176
|
Production sandboxing, CSP, origin policy, and audit logging belong to the host delivery
|
|
76
177
|
system.
|
|
77
178
|
|
|
179
|
+
## Framework adapters
|
|
180
|
+
|
|
181
|
+
Optional React and Preact TSX wrappers ship as separate packages. They keep the web component as
|
|
182
|
+
the rendering primitive and only handle framework lifecycle wiring:
|
|
183
|
+
|
|
184
|
+
- `@longsightgroup/qti3-player-react`
|
|
185
|
+
- `@longsightgroup/qti3-player-preact`
|
|
186
|
+
|
|
187
|
+
Use the native element directly when you do not need React or Preact integration.
|
|
188
|
+
|
|
189
|
+
Local manual proof for the React adapter: from the repo root run
|
|
190
|
+
`pnpm dev:adapter-react` and open `/adapter-react.html` (linked from the main manual harness).
|
|
191
|
+
|
|
192
|
+
## Clearing a loaded item
|
|
193
|
+
|
|
194
|
+
`clearItem()` (or omitting declarative `xml` on the adapters) removes rendered content and in-memory
|
|
195
|
+
session state. It does not emit `qti-statechange` or other player events because no item is loaded.
|
|
196
|
+
Hosts should treat the prop transition or imperative call as the source of truth.
|
|
197
|
+
|
|
198
|
+
Framework adapters treat `xml={undefined}` as a clear and `xml=""` as a load attempt. An empty
|
|
199
|
+
string shows the parse error view when the XML is invalid.
|
|
200
|
+
|
|
201
|
+
Restored `loadOptions.state` reload keys use JSON serialization: equivalent content with different
|
|
202
|
+
object references does not reload, but key order follows construction order and in-place mutation
|
|
203
|
+
without a reload key change is not detected.
|
|
204
|
+
|
|
78
205
|
## Styling
|
|
79
206
|
|
|
80
207
|
The player uses light DOM and is style-neutral by design. Host applications can style
|
|
81
208
|
the rendered `qti3-*` classes directly while preserving the item author's QTI shared
|
|
82
209
|
vocabulary classes.
|
|
83
210
|
|
|
211
|
+
Screen-reader status lines (`.qti3-selection-summary`, `aria-live="polite"`) are
|
|
212
|
+
visually hidden by default so LMS shells do not show reorder or selection announcements
|
|
213
|
+
to sighted users. They remain available to assistive technology. Set
|
|
214
|
+
`data-show-live-regions` on `qti-assessment-item-player` only in local debug or harness
|
|
215
|
+
pages when you want those messages visible on screen.
|
|
216
|
+
|
|
84
217
|
See the main repository README for the support matrix and release notes:
|
|
85
218
|
https://github.com/LongsightGroup/qti3
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { QtiContentNode, QtiValue } from "@longsightgroup/qti3-core";
|
|
2
|
+
export declare const unsafeContentElements: Set<string>;
|
|
3
|
+
export declare function contentElementName(qtiName: string): string | undefined;
|
|
4
|
+
export declare function createContentElement(name: string): HTMLElement | MathMLElement;
|
|
5
|
+
export declare function copySafeAttributes(element: Element, attributes: Record<string, string>): void;
|
|
6
|
+
export declare function applySharedAccessibilityVocabulary(element: Element, attributes: Record<string, string>): void;
|
|
7
|
+
export declare function isSafeUrl(value: string): boolean;
|
|
8
|
+
export declare function isResolvableAssetUrl(value: string): boolean;
|
|
9
|
+
export declare function formatPrintedValue(value: QtiValue, format?: string): string;
|
|
10
|
+
export declare function contentNodeText(node: QtiContentNode): string;
|
|
11
|
+
//# sourceMappingURL=content-dom.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content-dom.d.ts","sourceRoot":"","sources":["../../src/content/content-dom.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AA2D1E,eAAO,MAAM,qBAAqB,aAA+B,CAAC;AA6ClE,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAQtE;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,aAAa,CAK9E;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAS7F;AAED,wBAAgB,kCAAkC,CAChD,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACjC,IAAI,CAeN;AAiFD,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAYhD;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAQ3D;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAY3E;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM,CAI5D"}
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
const htmlContentElements = new Set([
|
|
2
|
+
"a",
|
|
3
|
+
"abbr",
|
|
4
|
+
"b",
|
|
5
|
+
"bdi",
|
|
6
|
+
"bdo",
|
|
7
|
+
"blockquote",
|
|
8
|
+
"br",
|
|
9
|
+
"caption",
|
|
10
|
+
"cite",
|
|
11
|
+
"code",
|
|
12
|
+
"dd",
|
|
13
|
+
"dfn",
|
|
14
|
+
"div",
|
|
15
|
+
"dl",
|
|
16
|
+
"dt",
|
|
17
|
+
"em",
|
|
18
|
+
"figcaption",
|
|
19
|
+
"figure",
|
|
20
|
+
"h1",
|
|
21
|
+
"h2",
|
|
22
|
+
"h3",
|
|
23
|
+
"h4",
|
|
24
|
+
"h5",
|
|
25
|
+
"h6",
|
|
26
|
+
"hr",
|
|
27
|
+
"i",
|
|
28
|
+
"img",
|
|
29
|
+
"kbd",
|
|
30
|
+
"li",
|
|
31
|
+
"ol",
|
|
32
|
+
"p",
|
|
33
|
+
"pre",
|
|
34
|
+
"q",
|
|
35
|
+
"rb",
|
|
36
|
+
"rbc",
|
|
37
|
+
"rp",
|
|
38
|
+
"rt",
|
|
39
|
+
"rtc",
|
|
40
|
+
"ruby",
|
|
41
|
+
"samp",
|
|
42
|
+
"small",
|
|
43
|
+
"span",
|
|
44
|
+
"strong",
|
|
45
|
+
"sub",
|
|
46
|
+
"sup",
|
|
47
|
+
"table",
|
|
48
|
+
"tbody",
|
|
49
|
+
"td",
|
|
50
|
+
"tfoot",
|
|
51
|
+
"th",
|
|
52
|
+
"thead",
|
|
53
|
+
"tr",
|
|
54
|
+
"ul",
|
|
55
|
+
"var",
|
|
56
|
+
]);
|
|
57
|
+
export const unsafeContentElements = new Set(["script", "style"]);
|
|
58
|
+
const mathMlElements = new Set([
|
|
59
|
+
"math",
|
|
60
|
+
"maction",
|
|
61
|
+
"maligngroup",
|
|
62
|
+
"malignmark",
|
|
63
|
+
"menclose",
|
|
64
|
+
"merror",
|
|
65
|
+
"mfenced",
|
|
66
|
+
"mfrac",
|
|
67
|
+
"mglyph",
|
|
68
|
+
"mi",
|
|
69
|
+
"mlabeledtr",
|
|
70
|
+
"mlongdiv",
|
|
71
|
+
"mmultiscripts",
|
|
72
|
+
"mn",
|
|
73
|
+
"mo",
|
|
74
|
+
"mover",
|
|
75
|
+
"mpadded",
|
|
76
|
+
"mphantom",
|
|
77
|
+
"mroot",
|
|
78
|
+
"mrow",
|
|
79
|
+
"ms",
|
|
80
|
+
"mscarries",
|
|
81
|
+
"mscarry",
|
|
82
|
+
"msgroup",
|
|
83
|
+
"msline",
|
|
84
|
+
"mspace",
|
|
85
|
+
"msqrt",
|
|
86
|
+
"msrow",
|
|
87
|
+
"mstack",
|
|
88
|
+
"mstyle",
|
|
89
|
+
"msub",
|
|
90
|
+
"msubsup",
|
|
91
|
+
"msup",
|
|
92
|
+
"mtable",
|
|
93
|
+
"mtd",
|
|
94
|
+
"mtext",
|
|
95
|
+
"mtr",
|
|
96
|
+
"munder",
|
|
97
|
+
"munderover",
|
|
98
|
+
"semantics",
|
|
99
|
+
]);
|
|
100
|
+
export function contentElementName(qtiName) {
|
|
101
|
+
if (qtiName === "qti-content-body" || qtiName === "qti-prompt")
|
|
102
|
+
return undefined;
|
|
103
|
+
if (htmlContentElements.has(qtiName) || mathMlElements.has(qtiName))
|
|
104
|
+
return qtiName;
|
|
105
|
+
if (qtiName === "object")
|
|
106
|
+
return "object";
|
|
107
|
+
if (qtiName === "qti-rubric-block")
|
|
108
|
+
return "section";
|
|
109
|
+
if (qtiName === "qti-template-block")
|
|
110
|
+
return "div";
|
|
111
|
+
if (qtiName === "qti-template-inline")
|
|
112
|
+
return "span";
|
|
113
|
+
return undefined;
|
|
114
|
+
}
|
|
115
|
+
export function createContentElement(name) {
|
|
116
|
+
if (mathMlElements.has(name)) {
|
|
117
|
+
return document.createElementNS("http://www.w3.org/1998/Math/MathML", name);
|
|
118
|
+
}
|
|
119
|
+
return document.createElement(name);
|
|
120
|
+
}
|
|
121
|
+
export function copySafeAttributes(element, attributes) {
|
|
122
|
+
for (const [name, value] of Object.entries(attributes)) {
|
|
123
|
+
if (!isSafeContentAttribute(name, value))
|
|
124
|
+
continue;
|
|
125
|
+
element.setAttribute(name, value);
|
|
126
|
+
if (name === "xml:lang" && !Object.hasOwn(attributes, "lang")) {
|
|
127
|
+
element.setAttribute("lang", value);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
applySharedAccessibilityVocabulary(element, attributes);
|
|
131
|
+
}
|
|
132
|
+
export function applySharedAccessibilityVocabulary(element, attributes) {
|
|
133
|
+
for (const [name, value] of Object.entries(attributes)) {
|
|
134
|
+
const ariaName = qtiAriaAttributeName(name);
|
|
135
|
+
if (!ariaName || hasAttributeName(attributes, ariaName))
|
|
136
|
+
continue;
|
|
137
|
+
element.setAttribute(ariaName, value);
|
|
138
|
+
}
|
|
139
|
+
const suppressTts = attributeValue(attributes, "data-qti-suppress-tts");
|
|
140
|
+
if (suppressesScreenReaderSpeech(suppressTts) &&
|
|
141
|
+
!hasAttributeName(attributes, "aria-hidden") &&
|
|
142
|
+
!hasAttributeName(attributes, "data-qti-aria-hidden")) {
|
|
143
|
+
element.setAttribute("aria-hidden", "true");
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
function qtiAriaAttributeName(name) {
|
|
147
|
+
const normalizedName = name.toLowerCase();
|
|
148
|
+
const prefix = "data-qti-aria-";
|
|
149
|
+
if (!normalizedName.startsWith(prefix))
|
|
150
|
+
return undefined;
|
|
151
|
+
const suffix = normalizedName.slice(prefix.length);
|
|
152
|
+
if (!/^[a-z0-9][a-z0-9-]*$/.test(suffix))
|
|
153
|
+
return undefined;
|
|
154
|
+
return `aria-${suffix}`;
|
|
155
|
+
}
|
|
156
|
+
function attributeValue(attributes, name) {
|
|
157
|
+
const normalizedName = name.toLowerCase();
|
|
158
|
+
const entry = Object.entries(attributes).find(([attributeName]) => attributeName.toLowerCase() === normalizedName);
|
|
159
|
+
return entry?.[1];
|
|
160
|
+
}
|
|
161
|
+
function hasAttributeName(attributes, name) {
|
|
162
|
+
return attributeValue(attributes, name) !== undefined;
|
|
163
|
+
}
|
|
164
|
+
function suppressesScreenReaderSpeech(value) {
|
|
165
|
+
if (!value)
|
|
166
|
+
return false;
|
|
167
|
+
const tokens = value
|
|
168
|
+
.toLowerCase()
|
|
169
|
+
.split(/[\s,]+/)
|
|
170
|
+
.filter(Boolean);
|
|
171
|
+
return tokens.includes("all") || tokens.includes("screen-reader");
|
|
172
|
+
}
|
|
173
|
+
function isSafeContentAttribute(name, value) {
|
|
174
|
+
const normalizedName = name.toLowerCase();
|
|
175
|
+
if (normalizedName.startsWith("on"))
|
|
176
|
+
return false;
|
|
177
|
+
if (normalizedName === "style")
|
|
178
|
+
return false;
|
|
179
|
+
if (normalizedName === "href" || normalizedName === "src" || normalizedName === "data") {
|
|
180
|
+
return isSafeUrl(value);
|
|
181
|
+
}
|
|
182
|
+
return (normalizedName === "alt" ||
|
|
183
|
+
normalizedName === "class" ||
|
|
184
|
+
normalizedName === "colspan" ||
|
|
185
|
+
normalizedName === "dir" ||
|
|
186
|
+
normalizedName === "headers" ||
|
|
187
|
+
normalizedName === "height" ||
|
|
188
|
+
normalizedName === "id" ||
|
|
189
|
+
normalizedName === "lang" ||
|
|
190
|
+
normalizedName === "role" ||
|
|
191
|
+
normalizedName === "rowspan" ||
|
|
192
|
+
normalizedName === "scope" ||
|
|
193
|
+
normalizedName === "title" ||
|
|
194
|
+
normalizedName === "type" ||
|
|
195
|
+
normalizedName === "width" ||
|
|
196
|
+
normalizedName === "xml:lang" ||
|
|
197
|
+
mathMlAttributeNames.has(normalizedName) ||
|
|
198
|
+
normalizedName.startsWith("aria-") ||
|
|
199
|
+
normalizedName.startsWith("data-"));
|
|
200
|
+
}
|
|
201
|
+
const mathMlAttributeNames = new Set([
|
|
202
|
+
"accent",
|
|
203
|
+
"accentunder",
|
|
204
|
+
"align",
|
|
205
|
+
"columnalign",
|
|
206
|
+
"display",
|
|
207
|
+
"fence",
|
|
208
|
+
"largeop",
|
|
209
|
+
"lspace",
|
|
210
|
+
"mathbackground",
|
|
211
|
+
"mathcolor",
|
|
212
|
+
"mathsize",
|
|
213
|
+
"mathvariant",
|
|
214
|
+
"movablelimits",
|
|
215
|
+
"rowalign",
|
|
216
|
+
"rspace",
|
|
217
|
+
"separator",
|
|
218
|
+
"stretchy",
|
|
219
|
+
]);
|
|
220
|
+
export function isSafeUrl(value) {
|
|
221
|
+
return (value.startsWith("#") ||
|
|
222
|
+
value.startsWith("/") ||
|
|
223
|
+
value.startsWith("./") ||
|
|
224
|
+
value.startsWith("../") ||
|
|
225
|
+
value.startsWith("http://") ||
|
|
226
|
+
value.startsWith("https://") ||
|
|
227
|
+
value.startsWith("data:image/") ||
|
|
228
|
+
value.startsWith("data:audio/") ||
|
|
229
|
+
value.startsWith("data:video/"));
|
|
230
|
+
}
|
|
231
|
+
export function isResolvableAssetUrl(value) {
|
|
232
|
+
return (!value.startsWith("#") &&
|
|
233
|
+
!value.startsWith("data:") &&
|
|
234
|
+
!value.startsWith("blob:") &&
|
|
235
|
+
!value.startsWith("http://") &&
|
|
236
|
+
!value.startsWith("https://"));
|
|
237
|
+
}
|
|
238
|
+
export function formatPrintedValue(value, format) {
|
|
239
|
+
if (value === null || value === undefined)
|
|
240
|
+
return "";
|
|
241
|
+
const numericValue = typeof value === "number" ? value : typeof value === "string" ? Number(value) : Number.NaN;
|
|
242
|
+
if (Number.isFinite(numericValue) && format) {
|
|
243
|
+
const fixed = /^%\.(\d+)f$/.exec(format);
|
|
244
|
+
if (fixed)
|
|
245
|
+
return numericValue.toFixed(Number(fixed[1]));
|
|
246
|
+
if (format === "%d" || format === "%i")
|
|
247
|
+
return String(Math.trunc(numericValue));
|
|
248
|
+
}
|
|
249
|
+
if (Array.isArray(value))
|
|
250
|
+
return value.map((item) => String(item)).join(", ");
|
|
251
|
+
if (typeof value === "object")
|
|
252
|
+
return JSON.stringify(value);
|
|
253
|
+
return String(value);
|
|
254
|
+
}
|
|
255
|
+
export function contentNodeText(node) {
|
|
256
|
+
if (node.kind === "text")
|
|
257
|
+
return node.text;
|
|
258
|
+
if ("children" in node)
|
|
259
|
+
return node.children.map(contentNodeText).join("");
|
|
260
|
+
return "";
|
|
261
|
+
}
|
|
262
|
+
//# sourceMappingURL=content-dom.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content-dom.js","sourceRoot":"","sources":["../../src/content/content-dom.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { QtiContentNode, QtiInteraction, QtiValue } from "@longsightgroup/qti3-core";
|
|
2
|
+
export interface PlayerContentContext {
|
|
3
|
+
interactionAt(index: number): QtiInteraction | undefined;
|
|
4
|
+
renderBlockInteraction(interaction: QtiInteraction): HTMLElement;
|
|
5
|
+
renderEmbeddedInteraction(interaction: QtiInteraction): HTMLElement;
|
|
6
|
+
currentVariableValue(identifier: string): QtiValue;
|
|
7
|
+
mathTemplateValue(node: Extract<QtiContentNode, {
|
|
8
|
+
kind: "element";
|
|
9
|
+
}>): string | undefined;
|
|
10
|
+
isFeedbackVisible(node: Extract<QtiContentNode, {
|
|
11
|
+
kind: "feedback";
|
|
12
|
+
}>): boolean;
|
|
13
|
+
isTemplateContentVisible(element: HTMLElement): boolean;
|
|
14
|
+
}
|
|
15
|
+
export declare function renderContentNodes(nodes: QtiContentNode[], context: PlayerContentContext): Node[];
|
|
16
|
+
export declare function renderContentNode(node: QtiContentNode, context: PlayerContentContext): Node[];
|
|
17
|
+
//# sourceMappingURL=content-renderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content-renderer.d.ts","sourceRoot":"","sources":["../../src/content/content-renderer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAS1F,MAAM,WAAW,oBAAoB;IACnC,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAAC;IACzD,sBAAsB,CAAC,WAAW,EAAE,cAAc,GAAG,WAAW,CAAC;IACjE,yBAAyB,CAAC,WAAW,EAAE,cAAc,GAAG,WAAW,CAAC;IACpE,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,QAAQ,CAAC;IACnD,iBAAiB,CAAC,IAAI,EAAE,OAAO,CAAC,cAAc,EAAE;QAAE,IAAI,EAAE,SAAS,CAAA;KAAE,CAAC,GAAG,MAAM,GAAG,SAAS,CAAC;IAC1F,iBAAiB,CAAC,IAAI,EAAE,OAAO,CAAC,cAAc,EAAE;QAAE,IAAI,EAAE,UAAU,CAAA;KAAE,CAAC,GAAG,OAAO,CAAC;IAChF,wBAAwB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC;CACzD;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,cAAc,EAAE,EAAE,OAAO,EAAE,oBAAoB,GAAG,IAAI,EAAE,CAEjG;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,oBAAoB,GAAG,IAAI,EAAE,CA6C7F"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { contentElementName, copySafeAttributes, createContentElement, formatPrintedValue, unsafeContentElements, } from "./content-dom.js";
|
|
2
|
+
export function renderContentNodes(nodes, context) {
|
|
3
|
+
return nodes.flatMap((node) => renderContentNode(node, context));
|
|
4
|
+
}
|
|
5
|
+
export function renderContentNode(node, context) {
|
|
6
|
+
if (node.kind === "text")
|
|
7
|
+
return [document.createTextNode(node.text)];
|
|
8
|
+
if (node.kind === "interaction") {
|
|
9
|
+
const interaction = context.interactionAt(node.interactionIndex);
|
|
10
|
+
if (!interaction)
|
|
11
|
+
return [];
|
|
12
|
+
if (interaction.type === "inlineChoice" || interaction.type === "textEntry") {
|
|
13
|
+
return [context.renderEmbeddedInteraction(interaction)];
|
|
14
|
+
}
|
|
15
|
+
return [context.renderBlockInteraction(interaction)];
|
|
16
|
+
}
|
|
17
|
+
if (node.kind === "printedVariable") {
|
|
18
|
+
return [renderPrintedVariable(node.identifier, node.format, context)];
|
|
19
|
+
}
|
|
20
|
+
if (node.kind === "feedback")
|
|
21
|
+
return renderFeedbackContent(node, context);
|
|
22
|
+
if (node.qtiName === "qti-template-block" || node.qtiName === "qti-template-inline") {
|
|
23
|
+
return [renderTemplateContent(node, context)];
|
|
24
|
+
}
|
|
25
|
+
if (node.qtiName === "qti-position-object-stage") {
|
|
26
|
+
return renderContentNodes(node.children.filter((child) => !("qtiName" in child) || (child.qtiName !== "object" && child.qtiName !== "img")), context);
|
|
27
|
+
}
|
|
28
|
+
if (node.qtiName === "qti-prompt") {
|
|
29
|
+
const prompt = document.createElement("p");
|
|
30
|
+
copySafeAttributes(prompt, node.attributes);
|
|
31
|
+
prompt.classList.add("qti3-item-prompt");
|
|
32
|
+
prompt.append(...renderContentNodes(node.children, context));
|
|
33
|
+
return [prompt];
|
|
34
|
+
}
|
|
35
|
+
if (unsafeContentElements.has(node.qtiName))
|
|
36
|
+
return [];
|
|
37
|
+
const elementName = contentElementName(node.qtiName);
|
|
38
|
+
if (!elementName)
|
|
39
|
+
return renderContentNodes(node.children, context);
|
|
40
|
+
const element = createContentElement(elementName);
|
|
41
|
+
copySafeAttributes(element, node.attributes);
|
|
42
|
+
const mathTemplateValue = context.mathTemplateValue(node);
|
|
43
|
+
if (mathTemplateValue === undefined) {
|
|
44
|
+
element.append(...renderContentNodes(node.children, context));
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
element.textContent = mathTemplateValue;
|
|
48
|
+
}
|
|
49
|
+
return [element];
|
|
50
|
+
}
|
|
51
|
+
function renderTemplateContent(node, context) {
|
|
52
|
+
const element = document.createElement(node.qtiName === "qti-template-block" ? "div" : "span");
|
|
53
|
+
copySafeAttributes(element, node.attributes);
|
|
54
|
+
element.classList.add(node.qtiName === "qti-template-block" ? "qti3-template-block" : "qti3-template-inline");
|
|
55
|
+
element.dataset.templateIdentifier = node.attributes["template-identifier"] ?? "";
|
|
56
|
+
element.dataset.templateValueIdentifier = node.attributes.identifier ?? "";
|
|
57
|
+
element.dataset.showHide = node.attributes["show-hide"] === "hide" ? "hide" : "show";
|
|
58
|
+
element.hidden = !context.isTemplateContentVisible(element);
|
|
59
|
+
element.append(...renderContentNodes(node.children, context));
|
|
60
|
+
return element;
|
|
61
|
+
}
|
|
62
|
+
function renderPrintedVariable(identifier, format, context) {
|
|
63
|
+
const output = document.createElement("output");
|
|
64
|
+
output.className = "qti3-printed-variable";
|
|
65
|
+
output.dataset.identifier = identifier;
|
|
66
|
+
if (format)
|
|
67
|
+
output.dataset.format = format;
|
|
68
|
+
output.value = formatPrintedValue(context.currentVariableValue(identifier), format);
|
|
69
|
+
output.textContent = output.value;
|
|
70
|
+
return output;
|
|
71
|
+
}
|
|
72
|
+
function renderFeedbackContent(node, context) {
|
|
73
|
+
const element = document.createElement(node.feedbackType === "block" ? "section" : "span");
|
|
74
|
+
element.className = `qti3-feedback-${node.feedbackType}`;
|
|
75
|
+
element.dataset.feedbackIdentifier = node.identifier;
|
|
76
|
+
element.dataset.outcomeIdentifier = node.outcomeIdentifier;
|
|
77
|
+
element.dataset.showHide = node.showHide;
|
|
78
|
+
element.hidden = !context.isFeedbackVisible(node);
|
|
79
|
+
element.append(...renderContentNodes(node.children, context));
|
|
80
|
+
return [element];
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=content-renderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content-renderer.js","sourceRoot":"","sources":["../../src/content/content-renderer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remove-button.d.ts","sourceRoot":"","sources":["../../src/controls/remove-button.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAE3E,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,QAAQ,EAAE,qBAAqB,GAC9B,iBAAiB,CASnB"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { trashIcon } from "../icons.js";
|
|
2
|
+
export function removeButton(label, messages) {
|
|
3
|
+
const safeLabel = label?.trim() || messages.message("remove");
|
|
4
|
+
const button = document.createElement("button");
|
|
5
|
+
button.type = "button";
|
|
6
|
+
button.className = "qti3-icon-button qti3-remove-button";
|
|
7
|
+
button.title = messages.message("remove");
|
|
8
|
+
button.setAttribute("aria-label", messages.message("removePair", { label: safeLabel }));
|
|
9
|
+
button.append(trashIcon());
|
|
10
|
+
return button;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=remove-button.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remove-button.js","sourceRoot":"","sources":["../../src/controls/remove-button.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAGxC,MAAM,UAAU,YAAY,CAC1B,KAAoB,EACpB,QAA+B;IAE/B,MAAM,SAAS,GAAG,KAAK,EAAE,IAAI,EAAE,IAAI,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC9D,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IAChD,MAAM,CAAC,IAAI,GAAG,QAAQ,CAAC;IACvB,MAAM,CAAC,SAAS,GAAG,qCAAqC,CAAC;IACzD,MAAM,CAAC,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC1C,MAAM,CAAC,YAAY,CAAC,YAAY,EAAE,QAAQ,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;IACxF,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;IAC3B,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,15 @@
|
|
|
1
|
-
export type {
|
|
2
|
-
export type {
|
|
1
|
+
export type { QtiPlayerMovementDirection } from "./player-messages.js";
|
|
2
|
+
export type { QtiAttemptStateV1, QtiCatalogSupportResolution, QtiCatalogSupportResolutionOptions, QtiScoreResult, QtiTextToSpeechTraversal, } from "@longsightgroup/qti3-core";
|
|
3
|
+
export type { QtiAssessmentItemPlayerCustomEventMap, QtiAssessmentItemPlayerEvent, QtiAssessmentItemPlayerEventDetailMap, QtiAssessmentItemPlayerEventName, QtiDiagnosticsEventDetail, QtiEndAttemptEventDetail, QtiPlayerFetchXml, QtiPlayerLoadOptions, QtiPlayerResolveAsset, QtiPlayerSessionControl, QtiPortableCustomMountEventDetail, QtiReadyEventDetail, QtiResponseChangeEventDetail, QtiResetEventDetail, QtiRestoreEventDetail, QtiScoreAttemptOptions, QtiScoreEventDetail, QtiStateChangeEventDetail, QtiSuspendEventDetail, QtiValidationEventDetail, } from "./player-types.js";
|
|
4
|
+
export type { QtiAssessmentItemPlayerAdapterEventCallback, QtiAssessmentItemPlayerAdapterEventHandlerProps, QtiAssessmentItemPlayerAdapterEventPropName, QtiAssessmentItemPlayerAdapterLoadSyncInput, QtiAssessmentItemPlayerAdapterProps, QtiAssessmentItemPlayerAdapterPropName, QtiAssessmentItemPlayerHandle, QtiAssessmentItemPlayerLoadDependencies, } from "./player-adapter.js";
|
|
5
|
+
export { bindQtiAssessmentItemPlayerAdapterEvents, createQtiAssessmentItemPlayerAdapterLoadSync, createQtiAssessmentItemPlayerHandle, isQtiAssessmentItemPlayerAdapterPropName, normalizeQtiAssessmentItemPlayerLoadError, qtiAssessmentItemPlayerAdapterEventEntries, qtiAssessmentItemPlayerAdapterPropNames, qtiAssessmentItemPlayerLoadDependencies, qtiAssessmentItemPlayerLoadStateKey, syncQtiAssessmentItemPlayerAdapterChrome, syncQtiAssessmentItemPlayerAdapterMessages, } from "./player-adapter.js";
|
|
6
|
+
export type { PlayerMessageCatalog } from "./player-message-catalog.js";
|
|
7
|
+
export type { PlayerMessageKey, PlayerMessageResolverKind } from "./player-message-manifest.js";
|
|
8
|
+
export { PLAYER_MESSAGE_MANIFEST } from "./player-message-manifest.js";
|
|
9
|
+
export { createPlayerMessageResolver, defaultPlayerMessageCatalog, defaultPlayerMessageResolver, extractMessagePlaceholders, formatPlayerMessage, mergePlayerMessageCatalogs, type PlayerMessageOverride, type PlayerMessageParams, type PlayerMessageResolver, type QtiPlayerMessageOverrides, } from "./player-message-catalog.js";
|
|
10
|
+
export { PLAYER_MESSAGE_KEYS, PLAYER_MESSAGE_STRING_KEYS } from "./player-message-keys.js";
|
|
11
|
+
export type { PlayerMessageCatalogDiagnostic, PlayerMessageCatalogDiagnosticCode, PlayerMessageCatalogValidationResult, ValidatePlayerMessageCatalogOptions, } from "./player-message-catalog-validate.js";
|
|
12
|
+
export { allowedCatalogPlaceholders, requiredCatalogPlaceholders, validatePlayerMessageCatalog, } from "./player-message-catalog-validate.js";
|
|
13
|
+
export { resolvePlayerMessages } from "./player-locale.js";
|
|
3
14
|
export { QtiAssessmentItemPlayer, defineQtiAssessmentItemPlayer } from "./player-element.js";
|
|
4
15
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AACvE,YAAY,EACV,iBAAiB,EACjB,2BAA2B,EAC3B,kCAAkC,EAClC,cAAc,EACd,wBAAwB,GACzB,MAAM,2BAA2B,CAAC;AACnC,YAAY,EACV,qCAAqC,EACrC,4BAA4B,EAC5B,qCAAqC,EACrC,gCAAgC,EAChC,yBAAyB,EACzB,wBAAwB,EACxB,iBAAiB,EACjB,oBAAoB,EACpB,qBAAqB,EACrB,uBAAuB,EACvB,iCAAiC,EACjC,mBAAmB,EACnB,4BAA4B,EAC5B,mBAAmB,EACnB,qBAAqB,EACrB,sBAAsB,EACtB,mBAAmB,EACnB,yBAAyB,EACzB,qBAAqB,EACrB,wBAAwB,GACzB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,2CAA2C,EAC3C,+CAA+C,EAC/C,2CAA2C,EAC3C,2CAA2C,EAC3C,mCAAmC,EACnC,sCAAsC,EACtC,6BAA6B,EAC7B,uCAAuC,GACxC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,wCAAwC,EACxC,4CAA4C,EAC5C,mCAAmC,EACnC,wCAAwC,EACxC,yCAAyC,EACzC,0CAA0C,EAC1C,uCAAuC,EACvC,uCAAuC,EACvC,mCAAmC,EACnC,wCAAwC,EACxC,0CAA0C,GAC3C,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACxE,YAAY,EAAE,gBAAgB,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAC;AAChG,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EACL,2BAA2B,EAC3B,2BAA2B,EAC3B,4BAA4B,EAC5B,0BAA0B,EAC1B,mBAAmB,EACnB,0BAA0B,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,GAC/B,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AAC3F,YAAY,EACV,8BAA8B,EAC9B,kCAAkC,EAClC,oCAAoC,EACpC,mCAAmC,GACpC,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EACL,0BAA0B,EAC1B,2BAA2B,EAC3B,4BAA4B,GAC7B,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,uBAAuB,EAAE,6BAA6B,EAAE,MAAM,qBAAqB,CAAC"}
|