@pie-players/pie-assessment-toolkit 0.3.74 → 0.3.75
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 +349 -313
- package/dist/attempt/TestSession.d.ts +1 -20
- package/dist/attempt/TestSession.js +8 -99
- package/dist/components/ItemScope.custom-element.d.ts +1 -0
- package/dist/components/ItemScope.custom-element.js +1 -0
- package/dist/components/ItemToolBar.custom-element.js +1 -1
- package/dist/components/PieAssessmentToolkit.custom-element.js +14 -14
- package/dist/components/SectionToolBar.custom-element.js +1 -1
- package/dist/components/chunks/ItemToolBar-7tt7v2xp.js +4 -0
- package/dist/components/chunks/{ItemToolBar-gmrryv2v.js → ItemToolBar-97hx60z4.js} +1 -1
- package/dist/components/chunks/ItemToolBar-bxwyhr5p.js +2 -0
- package/dist/components/chunks/ItemToolBar-jx38w99s.js +2 -0
- package/dist/components/chunks/ItemToolBar-rd2bb4p6.js +40 -0
- package/dist/components/chunks/ItemToolBar-vdkyn9f3.js +2 -0
- package/dist/components/chunks/sre-engine-jd8cc08x.js +1 -0
- package/dist/components/item-scope-element.d.ts +2 -0
- package/dist/components/item-scope-element.js +2 -0
- package/dist/context/assessment-toolkit-context.d.ts +27 -6
- package/dist/index.d.ts +22 -47
- package/dist/index.js +12 -36
- package/dist/policy/core/PolicySource.d.ts +1 -1
- package/dist/policy/core/ToolPolicyEngine.d.ts +77 -32
- package/dist/policy/core/ToolPolicyEngine.js +136 -46
- package/dist/policy/core/compose-decision.d.ts +28 -7
- package/dist/policy/core/compose-decision.js +75 -54
- package/dist/policy/core/decision-types.d.ts +65 -34
- package/dist/policy/core/feature-decision.d.ts +16 -9
- package/dist/policy/core/feature-decision.js +14 -8
- package/dist/policy/core/pnp-policy-inputs.d.ts +24 -33
- package/dist/policy/core/pnp-policy-inputs.js +28 -56
- package/dist/policy/core/provenance.d.ts +9 -4
- package/dist/policy/core/provenance.js +1 -1
- package/dist/policy/engine.d.ts +7 -23
- package/dist/policy/engine.js +5 -20
- package/dist/policy/sources/PnpPolicySource.d.ts +44 -61
- package/dist/policy/sources/PnpPolicySource.js +117 -118
- package/dist/runtime/SectionControllerBinding.d.ts +279 -0
- package/dist/runtime/SectionControllerBinding.js +450 -0
- package/dist/runtime/SectionRuntimeEngine.d.ts +26 -289
- package/dist/runtime/SectionRuntimeEngine.js +30 -372
- package/dist/runtime/adapter/SectionEngineAdapter.d.ts +19 -80
- package/dist/runtime/adapter/SectionEngineAdapter.js +19 -92
- package/dist/runtime/adapter/dom-event-bridge.d.ts +15 -30
- package/dist/runtime/adapter/dom-event-bridge.js +17 -44
- package/dist/runtime/adapter/subscriber-fanout.d.ts +1 -2
- package/dist/runtime/adapter/subscriber-fanout.js +1 -2
- package/dist/runtime/catalog-context.d.ts +19 -0
- package/dist/runtime/catalog-context.js +28 -0
- package/dist/runtime/composition-emit-scheduler.d.ts +9 -15
- package/dist/runtime/composition-emit-scheduler.js +9 -15
- package/dist/runtime/content-language.d.ts +32 -0
- package/dist/runtime/content-language.js +46 -0
- package/dist/runtime/content-region.d.ts +17 -0
- package/dist/runtime/content-region.js +29 -0
- package/dist/runtime/content-registration.d.ts +13 -0
- package/dist/runtime/content-registration.js +25 -0
- package/dist/runtime/core/SectionEngineCore.d.ts +2 -2
- package/dist/runtime/core/SectionEngineCore.js +2 -2
- package/dist/runtime/core/cohort.d.ts +1 -1
- package/dist/runtime/core/cohort.js +1 -1
- package/dist/runtime/core/engine-input.d.ts +18 -30
- package/dist/runtime/core/engine-input.js +11 -12
- package/dist/runtime/core/engine-output.d.ts +16 -40
- package/dist/runtime/core/engine-output.js +9 -21
- package/dist/runtime/core/engine-readiness.d.ts +5 -37
- package/dist/runtime/core/engine-readiness.js +8 -41
- package/dist/runtime/core/engine-resolver.d.ts +46 -74
- package/dist/runtime/core/engine-resolver.js +18 -43
- package/dist/runtime/core/engine-state.d.ts +28 -36
- package/dist/runtime/core/engine-state.js +18 -21
- package/dist/runtime/core/engine-transition.d.ts +14 -19
- package/dist/runtime/core/engine-transition.js +71 -51
- package/dist/runtime/engine.d.ts +16 -19
- package/dist/runtime/engine.js +12 -19
- package/dist/runtime/page-warnings.d.ts +13 -0
- package/dist/runtime/page-warnings.js +22 -0
- package/dist/runtime/policy-input-forwarding.d.ts +25 -0
- package/dist/runtime/policy-input-forwarding.js +25 -0
- package/dist/runtime/registration-events.d.ts +11 -0
- package/dist/runtime/runtime-event-claim.d.ts +8 -0
- package/dist/runtime/runtime-event-claim.js +15 -0
- package/dist/runtime/shell-event-bridge.d.ts +45 -0
- package/dist/runtime/shell-event-bridge.js +127 -0
- package/dist/runtime/shell-registration.d.ts +73 -0
- package/dist/runtime/shell-registration.js +95 -0
- package/dist/runtime/shell-scope.d.ts +68 -0
- package/dist/runtime/shell-scope.js +188 -0
- package/dist/runtime/tool-host-contract.d.ts +8 -10
- package/dist/runtime/tool-host-contract.js +11 -11
- package/dist/runtime/unclaimed-registration-watch.d.ts +7 -0
- package/dist/runtime/unclaimed-registration-watch.js +23 -0
- package/dist/services/ElementToolStateStore.d.ts +14 -10
- package/dist/services/ElementToolStateStore.js +37 -13
- package/dist/services/HighlightCoordinator.d.ts +21 -21
- package/dist/services/HighlightCoordinator.js +431 -325
- package/dist/services/RangeSerializer.d.ts +10 -1
- package/dist/services/RangeSerializer.js +87 -14
- package/dist/services/TTSService.d.ts +117 -70
- package/dist/services/TTSService.js +668 -578
- package/dist/services/ToolCoordinator.d.ts +43 -60
- package/dist/services/ToolCoordinator.js +164 -206
- package/dist/services/ToolRegistry.d.ts +74 -57
- package/dist/services/ToolRegistry.js +104 -114
- package/dist/services/ToolkitCoordinator.d.ts +183 -189
- package/dist/services/ToolkitCoordinator.js +477 -431
- package/dist/services/audio-handoff.d.ts +6 -7
- package/dist/services/audio-handoff.js +20 -14
- package/dist/services/catalog-owner.d.ts +0 -1
- package/dist/services/framework-error-bus.d.ts +3 -6
- package/dist/services/framework-error-bus.js +3 -6
- package/dist/services/framework-error.d.ts +22 -7
- package/dist/services/framework-error.js +9 -7
- package/dist/services/interfaces.d.ts +158 -129
- package/dist/services/section-session-assignment.d.ts +21 -0
- package/dist/services/section-session-assignment.js +82 -0
- package/dist/services/spoken-audio-cards.d.ts +0 -2
- package/dist/services/spoken-audio-cards.js +0 -2
- package/dist/services/tool-config-defaults.d.ts +3 -3
- package/dist/services/tool-config-defaults.js +3 -3
- package/dist/services/tool-config-validation.d.ts +4 -5
- package/dist/services/tool-config-validation.js +36 -61
- package/dist/services/tool-context.d.ts +0 -8
- package/dist/services/tool-context.js +0 -12
- package/dist/services/tool-icons.d.ts +4 -3
- package/dist/services/tool-icons.js +4 -3
- package/dist/services/tool-instance-id.d.ts +0 -1
- package/dist/services/tool-instance-id.js +0 -6
- package/dist/services/tool-providers/TTSToolProvider.d.ts +18 -19
- package/dist/services/tool-providers/TTSToolProvider.js +37 -34
- package/dist/services/tool-providers/ToolProviderApi.d.ts +10 -4
- package/dist/services/tool-providers/ToolProviderRegistry.d.ts +30 -26
- package/dist/services/tool-providers/ToolProviderRegistry.js +119 -93
- package/dist/services/tool-request.d.ts +27 -12
- package/dist/services/tool-request.js +24 -14
- package/dist/services/toolbar-decided-tools.d.ts +15 -0
- package/dist/services/toolbar-decided-tools.js +28 -0
- package/dist/services/tools-config-normalizer.d.ts +17 -22
- package/dist/services/tools-config-normalizer.js +2 -10
- package/dist/services/tts/browser-provider.d.ts +38 -2
- package/dist/services/tts/browser-provider.js +276 -140
- package/dist/services/tts/flat-tree.d.ts +71 -0
- package/dist/services/tts/flat-tree.js +269 -0
- package/dist/services/tts/generated-speech/assemble-plan.d.ts +3 -1
- package/dist/services/tts/generated-speech/assemble-plan.js +3 -1
- package/dist/services/tts/generated-speech/dom/build-dom-plan.d.ts +2 -0
- package/dist/services/tts/generated-speech/dom/build-dom-plan.js +1 -1
- package/dist/services/tts/generated-speech/math-speech-cache.d.ts +3 -1
- package/dist/services/tts/generated-speech/math-speech-cache.js +5 -1
- package/dist/services/tts/highlight-pipeline/create-highlight-plan.js +12 -4
- package/dist/services/tts/highlight-pipeline/prose-boundary-resolver.js +6 -4
- package/dist/services/tts/highlight-pipeline/readable-region.js +3 -2
- package/dist/services/tts/highlight-pipeline/types.d.ts +5 -0
- package/dist/services/tts/highlight-pipeline/visible-map-range.d.ts +12 -0
- package/dist/services/tts/highlight-pipeline/visible-map-range.js +73 -7
- package/dist/services/tts/math-aware-text-processing.d.ts +5 -1
- package/dist/services/tts/math-aware-text-processing.js +32 -18
- package/dist/services/tts/math-control-names.d.ts +21 -0
- package/dist/services/tts/math-control-names.js +142 -0
- package/dist/services/tts/math-speech.d.ts +11 -0
- package/dist/services/tts/math-speech.js +51 -18
- package/dist/services/tts/provider-options.d.ts +41 -0
- package/dist/services/tts/provider-options.js +1 -0
- package/dist/services/tts/ssml/spoken-text.d.ts +2 -26
- package/dist/services/tts/ssml/spoken-text.js +29 -0
- package/dist/services/tts/start-failure.d.ts +11 -0
- package/dist/services/tts/start-failure.js +19 -0
- package/dist/services/tts/text-processing.d.ts +9 -0
- package/dist/services/tts/text-processing.js +46 -33
- package/dist/services/tts/text-segmentation.d.ts +7 -0
- package/dist/services/tts/text-segmentation.js +47 -0
- package/dist/services/tts-runtime-config.d.ts +25 -17
- package/dist/services/tts-runtime-config.js +16 -95
- package/dist/tools/content-capability-resolution.d.ts +7 -9
- package/dist/tools/content-capability-resolution.js +8 -45
- package/dist/tools/registration.d.ts +58 -0
- package/dist/tools/registration.js +54 -0
- package/dist/tools/registrations/toolbar-registration-helpers.js +2 -2
- package/dist/tools/tool-surface-host.d.ts +6 -10
- package/dist/tools/tool-surface-host.js +44 -42
- package/dist/tools/tool-tag-map.d.ts +5 -15
- package/dist/tools/tool-tag-map.js +6 -20
- package/dist/utils/structural-equality.d.ts +11 -0
- package/dist/utils/structural-equality.js +47 -0
- package/package.json +13 -29
- package/dist/attempt/adapters/activity-to-test-attempt-session.d.ts +0 -49
- package/dist/attempt/adapters/activity-to-test-attempt-session.js +0 -138
- package/dist/components/chunks/ItemToolBar-b9dz5jvd.js +0 -40
- package/dist/components/chunks/ItemToolBar-h4xap0t0.js +0 -4
- package/dist/components/chunks/ItemToolBar-wr2myaah.js +0 -2
- package/dist/components/chunks/sre-engine-wf9s43gg.js +0 -1
- package/dist/context/runtime-context-consumer.d.ts +0 -13
- package/dist/context/runtime-context-consumer.js +0 -18
- package/dist/item-loader.d.ts +0 -44
- package/dist/item-loader.js +0 -61
- package/dist/policy/core/engine-context.d.ts +0 -29
- package/dist/policy/core/engine-context.js +0 -27
- package/dist/policy/core/policy-source-tag.d.ts +0 -31
- package/dist/policy/core/policy-source-tag.js +0 -28
- package/dist/policy/internal.d.ts +0 -25
- package/dist/policy/internal.js +0 -25
- package/dist/runtime/adapter/coordinator-bridge.d.ts +0 -92
- package/dist/runtime/adapter/coordinator-bridge.js +0 -126
- package/dist/runtime/adapter/framework-error-bridge.d.ts +0 -36
- package/dist/runtime/adapter/framework-error-bridge.js +0 -46
- package/dist/runtime/adapter/instrumentation-bridge.d.ts +0 -31
- package/dist/runtime/adapter/instrumentation-bridge.js +0 -38
- package/dist/runtime/core/engine-stage-derivation.d.ts +0 -18
- package/dist/runtime/core/engine-stage-derivation.js +0 -29
- package/dist/runtime/engine-context.d.ts +0 -39
- package/dist/runtime/engine-context.js +0 -31
- package/dist/runtime/internal.d.ts +0 -43
- package/dist/runtime/internal.js +0 -45
- package/dist/runtime/section-runtime-engine-host-context.d.ts +0 -74
- package/dist/runtime/section-runtime-engine-host-context.js +0 -57
- package/dist/runtime/stage-emit-gate.d.ts +0 -92
- package/dist/runtime/stage-emit-gate.js +0 -82
- package/dist/services/I18nService.d.ts +0 -47
- package/dist/services/I18nService.js +0 -84
- package/dist/services/ThemeProvider.d.ts +0 -95
- package/dist/services/ThemeProvider.js +0 -334
- package/dist/services/defaultPersonalNeedsProfile.d.ts +0 -21
- package/dist/services/defaultPersonalNeedsProfile.js +0 -26
- package/dist/services/pnp-standard-features.d.ts +0 -238
- package/dist/services/pnp-standard-features.js +0 -338
- package/dist/tools/client.d.ts +0 -10
- package/dist/tools/client.js +0 -10
- package/dist/tools/internal.d.ts +0 -44
- package/dist/tools/internal.js +0 -39
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
* Used by both TTS (for timing data) and annotations (for persistence).
|
|
6
6
|
*
|
|
7
7
|
* Uses CSS selector paths and node indices for robust serialization that
|
|
8
|
-
* survives content changes when possible.
|
|
8
|
+
* survives content changes when possible. A path into an open shadow root names
|
|
9
|
+
* its host, then ` >>> `, then the path inside the root, so ranges in content
|
|
10
|
+
* that renders into shadow roots round-trip; paths without one read as before.
|
|
9
11
|
*/
|
|
10
12
|
/**
|
|
11
13
|
* Serialized form of a Range suitable for storage.
|
|
@@ -91,6 +93,13 @@ export declare class RangeSerializer {
|
|
|
91
93
|
* @returns CSS selector path
|
|
92
94
|
*/
|
|
93
95
|
private getElementPath;
|
|
96
|
+
/** The path to `shadowRoot` itself: its host's path and an empty step into it. */
|
|
97
|
+
private getShadowRootPath;
|
|
98
|
+
/**
|
|
99
|
+
* The element, or shadow root, an element path names: each step after a
|
|
100
|
+
* {@link SHADOW_STEP} continues in the shadow root of what the step before named.
|
|
101
|
+
*/
|
|
102
|
+
private resolveElementPath;
|
|
94
103
|
/**
|
|
95
104
|
* Find a node by its path from root.
|
|
96
105
|
*
|
|
@@ -5,8 +5,13 @@
|
|
|
5
5
|
* Used by both TTS (for timing data) and annotations (for persistence).
|
|
6
6
|
*
|
|
7
7
|
* Uses CSS selector paths and node indices for robust serialization that
|
|
8
|
-
* survives content changes when possible.
|
|
8
|
+
* survives content changes when possible. A path into an open shadow root names
|
|
9
|
+
* its host, then ` >>> `, then the path inside the root, so ranges in content
|
|
10
|
+
* that renders into shadow roots round-trip; paths without one read as before.
|
|
9
11
|
*/
|
|
12
|
+
import { isShadowRootNode } from "./tts/flat-tree.js";
|
|
13
|
+
/** Separates a shadow host's path from the path inside its shadow root. */
|
|
14
|
+
const SHADOW_STEP = " >>> ";
|
|
10
15
|
/**
|
|
11
16
|
* RangeSerializer - Serialize and deserialize Range objects.
|
|
12
17
|
*/
|
|
@@ -94,20 +99,25 @@ export class RangeSerializer {
|
|
|
94
99
|
}
|
|
95
100
|
// Handle text nodes
|
|
96
101
|
if (node.nodeType === Node.TEXT_NODE) {
|
|
97
|
-
const parent = node.
|
|
102
|
+
const parent = node.parentNode;
|
|
98
103
|
if (!parent) {
|
|
99
104
|
throw new Error("Text node has no parent");
|
|
100
105
|
}
|
|
101
106
|
// Get index of this text node among its siblings
|
|
102
107
|
const textNodes = Array.from(parent.childNodes).filter((n) => n.nodeType === Node.TEXT_NODE);
|
|
103
108
|
const index = textNodes.indexOf(node);
|
|
104
|
-
const parentPath =
|
|
109
|
+
const parentPath = isShadowRootNode(parent)
|
|
110
|
+
? this.getShadowRootPath(parent, root)
|
|
111
|
+
: this.getElementPath(parent, root);
|
|
105
112
|
return `${parentPath}::text[${index}]`;
|
|
106
113
|
}
|
|
107
114
|
// Handle element nodes
|
|
108
115
|
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
109
116
|
return this.getElementPath(node, root);
|
|
110
117
|
}
|
|
118
|
+
if (isShadowRootNode(node)) {
|
|
119
|
+
return this.getShadowRootPath(node, root);
|
|
120
|
+
}
|
|
111
121
|
throw new Error(`Unsupported node type: ${node.nodeType}`);
|
|
112
122
|
}
|
|
113
123
|
/**
|
|
@@ -121,27 +131,81 @@ export class RangeSerializer {
|
|
|
121
131
|
if (element === root) {
|
|
122
132
|
return "";
|
|
123
133
|
}
|
|
124
|
-
const
|
|
134
|
+
const rootTree = root.getRootNode?.();
|
|
135
|
+
// One path per tree, outermost first.
|
|
136
|
+
const trees = [];
|
|
137
|
+
let path = [];
|
|
125
138
|
let current = element;
|
|
139
|
+
// Ends `current`'s tree at the shadow root holding it, continuing at the host.
|
|
140
|
+
const leaveShadowRoot = (shadowRoot) => {
|
|
141
|
+
trees.unshift(path.join(" > "));
|
|
142
|
+
path = [];
|
|
143
|
+
current = shadowRoot.host;
|
|
144
|
+
};
|
|
126
145
|
while (current && current !== root) {
|
|
127
|
-
// Use ID if available (more stable)
|
|
146
|
+
// Use ID if available (more stable). An id is unique within its tree, so
|
|
147
|
+
// the path still names the shadow host above it.
|
|
128
148
|
if (current.id) {
|
|
129
149
|
path.unshift(`#${current.id}`);
|
|
150
|
+
const tree = current.getRootNode?.();
|
|
151
|
+
if (isShadowRootNode(tree) && tree !== rootTree) {
|
|
152
|
+
leaveShadowRoot(tree);
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
130
155
|
break;
|
|
131
156
|
}
|
|
132
157
|
// Otherwise use tag + nth-of-type
|
|
133
158
|
const parent = current.parentElement;
|
|
134
|
-
|
|
159
|
+
const parentNode = current.parentNode;
|
|
160
|
+
const siblingsParent = parent ?? (isShadowRootNode(parentNode) ? parentNode : null);
|
|
161
|
+
if (!siblingsParent)
|
|
135
162
|
break;
|
|
136
|
-
const
|
|
163
|
+
const tagName = current.tagName;
|
|
164
|
+
const siblings = Array.from(siblingsParent.children).filter((el) => el.tagName === tagName);
|
|
137
165
|
const index = siblings.indexOf(current);
|
|
138
166
|
const selector = siblings.length > 1
|
|
139
|
-
? `${
|
|
140
|
-
:
|
|
167
|
+
? `${tagName.toLowerCase()}:nth-of-type(${index + 1})`
|
|
168
|
+
: tagName.toLowerCase();
|
|
141
169
|
path.unshift(selector);
|
|
142
|
-
|
|
170
|
+
if (parent) {
|
|
171
|
+
current = parent;
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
leaveShadowRoot(siblingsParent);
|
|
175
|
+
}
|
|
143
176
|
}
|
|
144
|
-
|
|
177
|
+
trees.unshift(path.join(" > "));
|
|
178
|
+
return trees.join(SHADOW_STEP);
|
|
179
|
+
}
|
|
180
|
+
/** The path to `shadowRoot` itself: its host's path and an empty step into it. */
|
|
181
|
+
getShadowRootPath(shadowRoot, root) {
|
|
182
|
+
return `${this.getElementPath(shadowRoot.host, root)}${SHADOW_STEP}`;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* The element, or shadow root, an element path names: each step after a
|
|
186
|
+
* {@link SHADOW_STEP} continues in the shadow root of what the step before named.
|
|
187
|
+
*/
|
|
188
|
+
resolveElementPath(path, root) {
|
|
189
|
+
let scope = root;
|
|
190
|
+
const steps = path.split(SHADOW_STEP);
|
|
191
|
+
for (let index = 0; index < steps.length; index++) {
|
|
192
|
+
if (index > 0) {
|
|
193
|
+
const shadowRoot = isShadowRootNode(scope)
|
|
194
|
+
? null
|
|
195
|
+
: scope.shadowRoot;
|
|
196
|
+
if (!shadowRoot)
|
|
197
|
+
return null;
|
|
198
|
+
scope = shadowRoot;
|
|
199
|
+
}
|
|
200
|
+
const selector = steps[index].trim();
|
|
201
|
+
if (!selector)
|
|
202
|
+
continue;
|
|
203
|
+
const found = scope.querySelector(selector);
|
|
204
|
+
if (!found)
|
|
205
|
+
return null;
|
|
206
|
+
scope = found;
|
|
207
|
+
}
|
|
208
|
+
return scope;
|
|
145
209
|
}
|
|
146
210
|
/**
|
|
147
211
|
* Find a node by its path from root.
|
|
@@ -156,10 +220,19 @@ export class RangeSerializer {
|
|
|
156
220
|
}
|
|
157
221
|
// Handle text node paths
|
|
158
222
|
if (path.includes("::text[")) {
|
|
159
|
-
const
|
|
223
|
+
const marker = path.lastIndexOf("::text[");
|
|
224
|
+
const elementPath = path.slice(0, marker);
|
|
225
|
+
const textPart = path.slice(marker + "::text[".length);
|
|
160
226
|
const textIndex = Number.parseInt(textPart.replace("]", ""), 10);
|
|
161
227
|
// Find parent element
|
|
162
|
-
|
|
228
|
+
let parent;
|
|
229
|
+
try {
|
|
230
|
+
parent = this.resolveElementPath(elementPath, root);
|
|
231
|
+
}
|
|
232
|
+
catch (error) {
|
|
233
|
+
console.warn("Invalid selector path:", path, error);
|
|
234
|
+
return null;
|
|
235
|
+
}
|
|
163
236
|
if (!parent)
|
|
164
237
|
return null;
|
|
165
238
|
// Find text node by index
|
|
@@ -168,7 +241,7 @@ export class RangeSerializer {
|
|
|
168
241
|
}
|
|
169
242
|
// Handle element paths
|
|
170
243
|
try {
|
|
171
|
-
return
|
|
244
|
+
return this.resolveElementPath(path, root);
|
|
172
245
|
}
|
|
173
246
|
catch (error) {
|
|
174
247
|
console.warn("Invalid selector path:", path, error);
|
|
@@ -16,10 +16,11 @@
|
|
|
16
16
|
* Part of PIE Assessment Toolkit.
|
|
17
17
|
*/
|
|
18
18
|
import type { ITTSProvider, TTSConfig, TTSProviderCapabilities } from "@pie-players/pie-tts";
|
|
19
|
-
import type { AccessibilityCatalogResolver
|
|
20
|
-
import type { HighlightCoordinatorApi } from "./interfaces.js";
|
|
19
|
+
import type { AccessibilityCatalogResolver } from "./AccessibilityCatalogResolver.js";
|
|
20
|
+
import type { HighlightCoordinatorApi, SpeakOptions } from "./interfaces.js";
|
|
21
21
|
import type { TTSHighlightTargetResolverProvider } from "./tts/highlight-target-resolver.js";
|
|
22
|
-
|
|
22
|
+
import { type SREMathSpeechOptions } from "./tts/math-speech.js";
|
|
23
|
+
export type { ITTSProvider, ITTSProviderImplementation, TTSConfig, TTSProviderCapabilities, } from "@pie-players/pie-tts";
|
|
23
24
|
/**
|
|
24
25
|
* Playback state
|
|
25
26
|
*/
|
|
@@ -30,16 +31,6 @@ export declare enum PlaybackState {
|
|
|
30
31
|
PAUSED = "paused",
|
|
31
32
|
ERROR = "error"
|
|
32
33
|
}
|
|
33
|
-
type HighlightMode = "word" | "sentence";
|
|
34
|
-
interface SpeakOptions {
|
|
35
|
-
catalogId?: string;
|
|
36
|
-
catalogContext?: CatalogLookupContext;
|
|
37
|
-
ignoreCatalogs?: boolean;
|
|
38
|
-
language?: string;
|
|
39
|
-
contentElement?: Element;
|
|
40
|
-
wordBoundaryOffset?: number;
|
|
41
|
-
highlightModeOverride?: HighlightMode;
|
|
42
|
-
}
|
|
43
34
|
/**
|
|
44
35
|
* TTSService
|
|
45
36
|
*
|
|
@@ -53,7 +44,13 @@ export declare class TTSService {
|
|
|
53
44
|
private highlightTargetResolverProvider;
|
|
54
45
|
private catalogResolver;
|
|
55
46
|
private state;
|
|
47
|
+
private resumeState;
|
|
56
48
|
private ttsConfig;
|
|
49
|
+
private hostLocales;
|
|
50
|
+
private readLocale;
|
|
51
|
+
private disposed;
|
|
52
|
+
private readinessGate;
|
|
53
|
+
private mathSpeechSource;
|
|
57
54
|
private currentText;
|
|
58
55
|
private currentContentElement;
|
|
59
56
|
private normalizedToDOM;
|
|
@@ -70,6 +67,8 @@ export declare class TTSService {
|
|
|
70
67
|
private playbackStartDeferredRunId;
|
|
71
68
|
private pendingPlaybackStartHighlights;
|
|
72
69
|
private playbackStartBarrierCleanup;
|
|
70
|
+
private pauseHold;
|
|
71
|
+
private structuralPause;
|
|
73
72
|
private playbackRateWriteQueue;
|
|
74
73
|
private playbackRateRequestId;
|
|
75
74
|
private pendingPlaybackRateRequest;
|
|
@@ -78,13 +77,31 @@ export declare class TTSService {
|
|
|
78
77
|
private lastRenderedRegionTarget;
|
|
79
78
|
private telemetryReporter;
|
|
80
79
|
private readonly generatedMathSpeechResolver;
|
|
81
|
-
private static readonly debugEnabled;
|
|
82
80
|
constructor();
|
|
83
|
-
private debugLog;
|
|
84
81
|
private clearPlaybackStartBarrier;
|
|
85
82
|
private notifyPlaybackStarted;
|
|
86
83
|
private installPlaybackStartBarrier;
|
|
87
84
|
private runWhenPlaybackStarts;
|
|
85
|
+
/** Resolves when run `runId` may start its next part: at once unless paused. */
|
|
86
|
+
private waitWhilePaused;
|
|
87
|
+
private releasePauseHold;
|
|
88
|
+
private waitStructuralPause;
|
|
89
|
+
private cancelStructuralPause;
|
|
90
|
+
/**
|
|
91
|
+
* Release what a superseded run still holds: its start barrier, a recorded
|
|
92
|
+
* clip still playing, a structural gap and a pause hold. Its loops then see
|
|
93
|
+
* the new run id and return.
|
|
94
|
+
*/
|
|
95
|
+
private abandonRun;
|
|
96
|
+
/**
|
|
97
|
+
* Start a run and enter loading. From here a pause or stop applies to the
|
|
98
|
+
* run, whatever it is still waiting for: the provider, its content or the
|
|
99
|
+
* provider's audio.
|
|
100
|
+
*/
|
|
101
|
+
private beginRun;
|
|
102
|
+
/** The run's audio is sounding; under a pause, it sounds again on resume. */
|
|
103
|
+
private markPlaying;
|
|
104
|
+
private assertNotDisposed;
|
|
88
105
|
private emitTelemetry;
|
|
89
106
|
/**
|
|
90
107
|
* Initialize TTS service with a provider
|
|
@@ -94,18 +111,27 @@ export declare class TTSService {
|
|
|
94
111
|
*/
|
|
95
112
|
initialize(provider: ITTSProvider, config?: Partial<TTSConfig>): Promise<void>;
|
|
96
113
|
/**
|
|
97
|
-
* Update
|
|
98
|
-
*
|
|
99
|
-
* This allows changing rate, pitch, and voice on the fly.
|
|
100
|
-
* Note: Some providers may require reinitialization for voice changes.
|
|
101
|
-
*
|
|
102
|
-
* @param settings Partial settings to update (rate, pitch, voice)
|
|
114
|
+
* Update rate, pitch, voice or provider options without reinitializing.
|
|
115
|
+
* `providerOptions` merge over the ones already configured.
|
|
103
116
|
*/
|
|
104
117
|
updateSettings(settings: Partial<TTSConfig>): Promise<void>;
|
|
105
118
|
/**
|
|
106
119
|
* Set highlight coordinator for word highlighting
|
|
107
120
|
*/
|
|
108
121
|
setHighlightCoordinator(coordinator: HighlightCoordinatorApi): void;
|
|
122
|
+
/**
|
|
123
|
+
* Starts the service when a caller speaks before it is initialized; a gate
|
|
124
|
+
* that rejects fails the speak with its error. The coordinator installs one
|
|
125
|
+
* that runs its own text-to-speech start.
|
|
126
|
+
*/
|
|
127
|
+
setReadinessGate(gate: (() => Promise<void>) | null): void;
|
|
128
|
+
/**
|
|
129
|
+
* Where the configured math speech options come from before, and apart from,
|
|
130
|
+
* initialization, so math names do not depend on when speech started.
|
|
131
|
+
*/
|
|
132
|
+
setMathSpeechSource(source: (() => unknown) | null): void;
|
|
133
|
+
/** The start a speak must wait for, or null when it can speak now without yielding. */
|
|
134
|
+
private pendingReadiness;
|
|
109
135
|
/**
|
|
110
136
|
* Set a late-bound provider for optional host TTS highlight target remapping.
|
|
111
137
|
*
|
|
@@ -131,18 +157,6 @@ export declare class TTSService {
|
|
|
131
157
|
* @param resolver AccessibilityCatalogResolver instance
|
|
132
158
|
*/
|
|
133
159
|
setCatalogResolver(resolver: AccessibilityCatalogResolver): void;
|
|
134
|
-
/**
|
|
135
|
-
* Whether a catalog holds spoken content this service could actually speak.
|
|
136
|
-
*
|
|
137
|
-
* Exists because `data-catalog-idref` is one attribute with several readers:
|
|
138
|
-
* a node can be docked to a catalog that carries only a signing card, and the
|
|
139
|
-
* nearest docked ancestor of a selection is therefore not necessarily the one
|
|
140
|
-
* holding its authored SSML. A caller resolving a selection climbs ancestors
|
|
141
|
-
* and asks this before settling on an id — see the TTS tool's
|
|
142
|
-
* `findSpokenCatalogId`. Without it, a signing card docked on an inner node
|
|
143
|
-
* silently shadows authored speech on an outer one.
|
|
144
|
-
*/
|
|
145
|
-
hasSpokenAlternate(catalogId: string, language?: string): boolean;
|
|
146
160
|
private getHighlightResolverRuntime;
|
|
147
161
|
private getNodeElement;
|
|
148
162
|
private isElementWithinScope;
|
|
@@ -150,18 +164,45 @@ export declare class TTSService {
|
|
|
150
164
|
private resolveWordHighlightRange;
|
|
151
165
|
private resolveSentenceHighlightTargets;
|
|
152
166
|
private createTextRange;
|
|
153
|
-
|
|
167
|
+
/**
|
|
168
|
+
* Paint the spoken word, each range offered to the host's resolver. A word
|
|
169
|
+
* split across inline elements is one range over its text nodes; across
|
|
170
|
+
* shadow trees, one range per tree.
|
|
171
|
+
*/
|
|
172
|
+
private paintTTSWord;
|
|
154
173
|
private paintTTSSentenceRanges;
|
|
155
174
|
/**
|
|
156
175
|
* Get provider capabilities
|
|
157
176
|
*/
|
|
158
177
|
getCapabilities(): TTSProviderCapabilities | null;
|
|
178
|
+
private providerOptions;
|
|
179
|
+
/** The longest text the provider accepts in one speak, when it declares one. */
|
|
180
|
+
private maxTextLength;
|
|
181
|
+
/**
|
|
182
|
+
* Speak `text`, in pieces when it exceeds the provider's `maxTextLength`. Word
|
|
183
|
+
* boundaries keep indexing the whole text. An SSML document cannot be cut, so
|
|
184
|
+
* one over the limit fails and the chunk's plain fallback reads instead.
|
|
185
|
+
*/
|
|
186
|
+
private speakWithinLimit;
|
|
187
|
+
/** Segments no longer than the provider's `maxTextLength`, offsets kept. */
|
|
188
|
+
private segmentsWithinLimit;
|
|
159
189
|
/**
|
|
160
190
|
* Build a character-by-character map from normalized text positions to DOM positions
|
|
161
191
|
* This handles the complexity of whitespace normalization
|
|
162
192
|
*/
|
|
163
193
|
private getTextProcessingOptions;
|
|
164
|
-
|
|
194
|
+
/**
|
|
195
|
+
* The language a read of `node` is in. Its content language is the nearest
|
|
196
|
+
* `lang` between it and its shell, else the language the speak names, else a
|
|
197
|
+
* pinned `lang_id`. Its locale is that content language, else the host's
|
|
198
|
+
* configured locale, else en-US.
|
|
199
|
+
*/
|
|
200
|
+
private resolveReadLanguage;
|
|
201
|
+
/**
|
|
202
|
+
* The host's SRE options for math speech: from the installed source, else as
|
|
203
|
+
* this service was initialized with.
|
|
204
|
+
*/
|
|
205
|
+
getMathSpeechOptions(): SREMathSpeechOptions | undefined;
|
|
165
206
|
private buildPositionMap;
|
|
166
207
|
private getStructuralPauseProfile;
|
|
167
208
|
private resolvePauseMsFromUnits;
|
|
@@ -195,22 +236,30 @@ export declare class TTSService {
|
|
|
195
236
|
private getSegmentIndexForOffset;
|
|
196
237
|
private highlightSentenceForOffset;
|
|
197
238
|
/**
|
|
198
|
-
*
|
|
239
|
+
* Read `target` aloud: a range reads the text it selects, an element its
|
|
240
|
+
* content. A node with a spoken card that the target holds whole reads its
|
|
241
|
+
* card, `catalogId` names the card of the content root, and math reads as
|
|
242
|
+
* math speech.
|
|
199
243
|
*
|
|
200
|
-
*
|
|
201
|
-
*
|
|
202
|
-
*
|
|
244
|
+
* Content marked not-to-be-spoken is never read, a named card included. When
|
|
245
|
+
* the target holds nothing speakable, nothing is spoken and playback already
|
|
246
|
+
* running continues.
|
|
203
247
|
*/
|
|
204
|
-
|
|
248
|
+
speak(target: Range | Element, options?: SpeakOptions): Promise<void>;
|
|
205
249
|
/**
|
|
206
|
-
*
|
|
207
|
-
*
|
|
208
|
-
|
|
209
|
-
|
|
250
|
+
* Suppression is read from the live ancestors of what is read, because the
|
|
251
|
+
* element carrying it may sit above the content root.
|
|
252
|
+
*/
|
|
253
|
+
private isSuppressedTarget;
|
|
254
|
+
private resolveElementTarget;
|
|
255
|
+
private resolveRangeTarget;
|
|
256
|
+
private speakContent;
|
|
257
|
+
/**
|
|
258
|
+
* Hand the read's language to the provider. A read in a named content language
|
|
259
|
+
* sets the provider's locales and `contentLanguage` to it, so a browser voice
|
|
260
|
+
* follows it; a read naming none restores the host's locales and clears
|
|
261
|
+
* `contentLanguage`, so the browser voice follows the browser's language.
|
|
210
262
|
*/
|
|
211
|
-
speak(text: string, options?: SpeakOptions): Promise<void>;
|
|
212
|
-
private switchProviderToBrowser;
|
|
213
|
-
private isBrowserSpeechFallbackAvailable;
|
|
214
263
|
private applyLanguageSettings;
|
|
215
264
|
private resolveSpeechContent;
|
|
216
265
|
private resolveCatalogComposedSpeechContent;
|
|
@@ -226,6 +275,10 @@ export declare class TTSService {
|
|
|
226
275
|
* defensive net if a capable provider still rejects a given SSML payload.
|
|
227
276
|
*/
|
|
228
277
|
private resolveGeneratedPlaybackFormat;
|
|
278
|
+
/**
|
|
279
|
+
* With `range`, the selection only: an equation it holds whole reads as math
|
|
280
|
+
* speech, and a selection without one reads the selected text, `normalizedInputText`.
|
|
281
|
+
*/
|
|
229
282
|
private resolveGeneratedSpeechContent;
|
|
230
283
|
private logResolvedSpeechContent;
|
|
231
284
|
private initializeSpeakTracking;
|
|
@@ -233,7 +286,6 @@ export declare class TTSService {
|
|
|
233
286
|
private configureWordBoundaryHighlighting;
|
|
234
287
|
private clearWordBoundaryHighlighting;
|
|
235
288
|
private highlightCatalogRegion;
|
|
236
|
-
private highlightCatalogActiveRange;
|
|
237
289
|
private highlightRenderableRegionTarget;
|
|
238
290
|
private highlightRenderableActiveTarget;
|
|
239
291
|
private renderHighlightDecision;
|
|
@@ -253,28 +305,19 @@ export declare class TTSService {
|
|
|
253
305
|
private speakCatalogChunkOnce;
|
|
254
306
|
private executeSpeakPlayback;
|
|
255
307
|
private clearHighlightsAndTracking;
|
|
256
|
-
/**
|
|
257
|
-
* Speak a text range with accurate word highlighting
|
|
258
|
-
*
|
|
259
|
-
* This calculates the offset of the range within its parent element
|
|
260
|
-
* to ensure word highlighting aligns correctly with the selected text.
|
|
261
|
-
*
|
|
262
|
-
* @param range DOM Range to speak
|
|
263
|
-
*/
|
|
264
308
|
/**
|
|
265
309
|
* The selected part of `root`'s normalized visible text and where it starts, or
|
|
266
310
|
* null when the map is unavailable or holds no selected character.
|
|
267
311
|
*/
|
|
268
312
|
private selectMappedRangeText;
|
|
269
|
-
speakRange(range: Range, options?: {
|
|
270
|
-
contentRoot?: Element | null;
|
|
271
|
-
}): Promise<void>;
|
|
272
313
|
/**
|
|
273
|
-
* Pause playback
|
|
314
|
+
* Pause playback. A pause while the read is loading holds it: its audio does
|
|
315
|
+
* not start until {@link resume}.
|
|
274
316
|
*/
|
|
275
317
|
pause(): void;
|
|
276
318
|
/**
|
|
277
|
-
* Resume playback
|
|
319
|
+
* Resume playback, back to loading when the pause came before the audio
|
|
320
|
+
* started.
|
|
278
321
|
*/
|
|
279
322
|
resume(): void;
|
|
280
323
|
private normalizePlaybackRate;
|
|
@@ -287,6 +330,16 @@ export declare class TTSService {
|
|
|
287
330
|
* Stop playback
|
|
288
331
|
*/
|
|
289
332
|
stop(): void;
|
|
333
|
+
/**
|
|
334
|
+
* Stop playback and drop the provider, whose owner destroys it. A later speak
|
|
335
|
+
* waits on the readiness gate, as before the first {@link initialize}.
|
|
336
|
+
*/
|
|
337
|
+
releaseProvider(): void;
|
|
338
|
+
/**
|
|
339
|
+
* Stop, release the provider and drop every listener, hook and pending timer.
|
|
340
|
+
* A disposed service cannot speak or be initialized again.
|
|
341
|
+
*/
|
|
342
|
+
dispose(): void;
|
|
290
343
|
/**
|
|
291
344
|
* Request UI-level TTS controls to hand off/deactivate.
|
|
292
345
|
*
|
|
@@ -316,16 +369,10 @@ export declare class TTSService {
|
|
|
316
369
|
*/
|
|
317
370
|
getLastError(): string | null;
|
|
318
371
|
/**
|
|
319
|
-
* Subscribe to state changes
|
|
320
|
-
*
|
|
321
|
-
* @param id Unique listener ID
|
|
322
|
-
* @param callback Function to call on state change
|
|
323
|
-
*/
|
|
324
|
-
onStateChange(id: string, callback: (state: PlaybackState) => void): void;
|
|
325
|
-
/**
|
|
326
|
-
* Unsubscribe from state changes
|
|
372
|
+
* Subscribe to playback state changes. The returned function unsubscribes;
|
|
373
|
+
* each subscription is its own, so the same callback can be subscribed twice.
|
|
327
374
|
*/
|
|
328
|
-
|
|
375
|
+
onStateChange(callback: (state: PlaybackState) => void): () => void;
|
|
329
376
|
/**
|
|
330
377
|
* Set state and notify listeners
|
|
331
378
|
*/
|