@pie-players/pie-assessment-toolkit 0.3.74 → 1.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +658 -714
- package/custom-elements.json +1315 -0
- package/dist/attempt/TestSession.d.ts +1 -21
- package/dist/attempt/TestSession.js +16 -102
- 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-3zrc4p3d.js +4 -0
- package/dist/components/chunks/ItemToolBar-66hcwmfw.js +2 -0
- package/dist/components/chunks/ItemToolBar-9gqhfxtn.js +40 -0
- package/dist/components/chunks/ItemToolBar-hzc5wyjp.js +2 -0
- package/dist/components/chunks/{ItemToolBar-gmrryv2v.js → ItemToolBar-kkj69ptr.js} +1 -1
- package/dist/components/chunks/ItemToolBar-vdkyn9f3.js +2 -0
- package/dist/components/chunks/sre-engine-bj997w4b.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 +33 -6
- package/dist/index.d.ts +25 -50
- package/dist/index.js +15 -45
- package/dist/policy/core/PolicySource.d.ts +2 -2
- package/dist/policy/core/ToolPolicyEngine.d.ts +118 -34
- package/dist/policy/core/ToolPolicyEngine.js +203 -56
- package/dist/policy/core/compose-decision.d.ts +28 -7
- package/dist/policy/core/compose-decision.js +95 -74
- package/dist/policy/core/decision-types.d.ts +98 -55
- package/dist/policy/core/feature-decision.d.ts +28 -19
- package/dist/policy/core/feature-decision.js +15 -11
- package/dist/policy/core/pnp-policy-inputs.d.ts +29 -35
- package/dist/policy/core/pnp-policy-inputs.js +40 -88
- package/dist/policy/core/provenance.d.ts +10 -5
- package/dist/policy/core/provenance.js +1 -1
- package/dist/policy/core/tool-parameters.d.ts +11 -0
- package/dist/policy/core/tool-parameters.js +15 -0
- package/dist/policy/engine.d.ts +7 -23
- package/dist/policy/engine.js +5 -20
- package/dist/policy/sources/PnpPolicySource.d.ts +43 -68
- package/dist/policy/sources/PnpPolicySource.js +133 -132
- package/dist/runtime/SectionControllerBinding.d.ts +283 -0
- package/dist/runtime/SectionControllerBinding.js +456 -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 -3
- package/dist/runtime/adapter/subscriber-fanout.js +2 -6
- 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 +12 -18
- package/dist/runtime/composition-emit-scheduler.js +10 -16
- package/dist/runtime/content-language.d.ts +32 -0
- package/dist/runtime/content-language.js +46 -0
- package/dist/runtime/content-region.d.ts +13 -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 -4
- package/dist/runtime/core/SectionEngineCore.js +2 -6
- package/dist/runtime/core/cohort.d.ts +1 -6
- package/dist/runtime/core/cohort.js +1 -10
- 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 +17 -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 +74 -53
- 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 +22 -14
- package/dist/runtime/runtime-event-claim.d.ts +8 -0
- package/dist/runtime/runtime-event-claim.js +15 -0
- package/dist/runtime/runtime-id.d.ts +1 -1
- package/dist/runtime/runtime-id.js +1 -1
- 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 +194 -0
- package/dist/runtime/tool-host-contract.d.ts +8 -14
- package/dist/runtime/tool-host-contract.js +12 -12
- package/dist/runtime/unclaimed-registration-watch.d.ts +7 -0
- package/dist/runtime/unclaimed-registration-watch.js +23 -0
- package/dist/services/AccessibilityCatalogResolver.d.ts +21 -31
- package/dist/services/AccessibilityCatalogResolver.js +29 -42
- package/dist/services/ElementToolStateStore.d.ts +42 -67
- package/dist/services/ElementToolStateStore.js +65 -71
- package/dist/services/HighlightCoordinator.d.ts +28 -40
- package/dist/services/HighlightCoordinator.js +459 -381
- package/dist/services/RangeSerializer.d.ts +11 -33
- package/dist/services/RangeSerializer.js +88 -59
- package/dist/services/SSMLExtractor.d.ts +8 -31
- package/dist/services/SSMLExtractor.js +18 -40
- package/dist/services/TTSService.d.ts +159 -119
- package/dist/services/TTSService.js +937 -822
- package/dist/services/ToolCoordinator.d.ts +42 -102
- package/dist/services/ToolCoordinator.js +178 -256
- package/dist/services/ToolRegistry.d.ts +152 -133
- package/dist/services/ToolRegistry.js +192 -178
- package/dist/services/ToolkitCoordinator.d.ts +233 -237
- package/dist/services/ToolkitCoordinator.js +615 -557
- 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 +51 -13
- package/dist/services/framework-error.js +19 -20
- package/dist/services/interfaces.d.ts +189 -184
- package/dist/services/section-controller-types.d.ts +7 -7
- package/dist/services/section-session-assignment.d.ts +21 -0
- package/dist/services/section-session-assignment.js +80 -0
- package/dist/services/spoken-audio-cards.d.ts +2 -6
- package/dist/services/spoken-audio-cards.js +2 -6
- 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 +9 -12
- package/dist/services/tool-config-validation.js +47 -87
- package/dist/services/tool-context.d.ts +7 -31
- package/dist/services/tool-context.js +99 -65
- package/dist/services/tool-failure.d.ts +30 -0
- package/dist/services/tool-failure.js +11 -0
- package/dist/services/tool-icons.d.ts +5 -5
- package/dist/services/tool-icons.js +6 -5
- package/dist/services/tool-instance-id.d.ts +8 -7
- package/dist/services/tool-instance-id.js +12 -24
- package/dist/services/tool-providers/TTSToolProvider.d.ts +20 -58
- package/dist/services/tool-providers/TTSToolProvider.js +32 -85
- package/dist/services/tool-providers/ToolProviderApi.d.ts +10 -11
- package/dist/services/tool-providers/ToolProviderRegistry.d.ts +29 -60
- package/dist/services/tool-providers/ToolProviderRegistry.js +128 -144
- package/dist/services/tool-request.d.ts +31 -12
- package/dist/services/tool-request.js +31 -16
- package/dist/services/toolbar-decided-tools.d.ts +16 -0
- package/dist/services/toolbar-decided-tools.js +29 -0
- package/dist/services/toolbar-items.js +2 -5
- package/dist/services/tools-config-normalizer.d.ts +33 -29
- package/dist/services/tools-config-normalizer.js +26 -28
- package/dist/services/tts/browser-provider.d.ts +39 -6
- package/dist/services/tts/browser-provider.js +280 -160
- package/dist/services/tts/catalog-span-alignment.js +14 -7
- package/dist/services/tts/flat-tree.d.ts +64 -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/dom/to-chunk-inputs.d.ts +2 -2
- package/dist/services/tts/generated-speech/index.d.ts +1 -1
- package/dist/services/tts/generated-speech/index.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/generated-speech/types.d.ts +1 -1
- package/dist/services/tts/generated-speech/types.js +1 -1
- package/dist/services/tts/highlight-pipeline/create-highlight-plan.js +22 -16
- 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/highlight-target-resolver.d.ts +12 -0
- package/dist/services/tts/math-aware-text-processing.d.ts +5 -1
- package/dist/services/tts/math-aware-text-processing.js +42 -47
- 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 +12 -1
- package/dist/services/tts/math-speech.js +54 -18
- package/dist/services/tts/mathml-sanitization.d.ts +7 -0
- package/dist/services/tts/mathml-sanitization.js +9 -1
- package/dist/services/tts/provider-options.d.ts +52 -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 +4 -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 +12 -0
- package/dist/services/tts/text-segmentation.js +60 -10
- package/dist/services/tts-runtime-config.d.ts +54 -26
- package/dist/services/tts-runtime-config.js +27 -112
- package/dist/tools/content-capability-resolution.d.ts +9 -11
- package/dist/tools/content-capability-resolution.js +8 -45
- package/dist/tools/registration.d.ts +59 -0
- package/dist/tools/registration.js +55 -0
- package/dist/tools/registrations/toolbar-registration-helpers.d.ts +6 -0
- package/dist/tools/registrations/toolbar-registration-helpers.js +8 -2
- package/dist/tools/tool-surface-host.d.ts +6 -10
- package/dist/tools/tool-surface-host.js +45 -50
- 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 +15 -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/ContextVariableStore.d.ts +0 -113
- package/dist/services/ContextVariableStore.js +0 -206
- 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/services/tts-control-events.d.ts +0 -13
- package/dist/services/tts-control-events.js +0 -7
- 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
- package/dist/utils/logger.d.ts +0 -6
- package/dist/utils/logger.js +0 -10
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { composedClosest, composedContains } from "../flat-tree.js";
|
|
1
2
|
const READABLE_REGION_SELECTOR = [
|
|
2
3
|
"[data-pie-tts-region]",
|
|
3
4
|
"[data-catalog-region]",
|
|
@@ -10,8 +11,8 @@ const READABLE_REGION_SELECTOR = [
|
|
|
10
11
|
"div",
|
|
11
12
|
].join(",");
|
|
12
13
|
export const resolveReadableRegion = (sourceElement, contentRoot) => {
|
|
13
|
-
const region = sourceElement
|
|
14
|
-
if (region && contentRoot
|
|
14
|
+
const region = composedClosest(sourceElement, READABLE_REGION_SELECTOR);
|
|
15
|
+
if (region && composedContains(contentRoot, region)) {
|
|
15
16
|
return region;
|
|
16
17
|
}
|
|
17
18
|
return sourceElement;
|
|
@@ -44,6 +44,11 @@ export type RenderableHighlightTarget = {
|
|
|
44
44
|
type: "range";
|
|
45
45
|
quality: "exact-word" | "semantic-token" | "expression" | "region";
|
|
46
46
|
range: Range;
|
|
47
|
+
/**
|
|
48
|
+
* Every range to paint when the target crosses shadow boundaries, one per
|
|
49
|
+
* tree, `range` among them; absent when `range` covers the target.
|
|
50
|
+
*/
|
|
51
|
+
ranges?: Range[];
|
|
47
52
|
} | {
|
|
48
53
|
type: "element";
|
|
49
54
|
quality: "semantic-token" | "expression" | "region";
|
|
@@ -1,2 +1,14 @@
|
|
|
1
1
|
import type { NormalizedTextMap } from "../text-processing.js";
|
|
2
|
+
/**
|
|
3
|
+
* The range over visible characters `start` to `end` (exclusive). A live range
|
|
4
|
+
* holds one tree, so when the span runs into a shadow tree, or out of one, the
|
|
5
|
+
* range ends at the last character in the tree it starts in.
|
|
6
|
+
*/
|
|
2
7
|
export declare const createRangeFromVisibleMap: (visibleMap: NormalizedTextMap | undefined, start: number, end: number) => Range | null;
|
|
8
|
+
/**
|
|
9
|
+
* The ranges over visible characters `start` to `end` (exclusive), one per run of
|
|
10
|
+
* characters in the same tree, so a span crossing shadow boundaries paints in
|
|
11
|
+
* each tree it covers. A span within one tree gives exactly
|
|
12
|
+
* {@link createRangeFromVisibleMap}'s range.
|
|
13
|
+
*/
|
|
14
|
+
export declare const createRangesFromVisibleMap: (visibleMap: NormalizedTextMap | undefined, start: number, end: number) => Range[];
|
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
const treeOf = (mapping) => mapping.node.getRootNode?.() ?? mapping.node;
|
|
2
|
+
const rangeBetween = (start, end) => {
|
|
3
|
+
try {
|
|
4
|
+
const range = document.createRange();
|
|
5
|
+
range.setStart(start.node, start.offset);
|
|
6
|
+
range.setEnd(end.node, end.offset + 1);
|
|
7
|
+
return range;
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* The range over visible characters `start` to `end` (exclusive). A live range
|
|
15
|
+
* holds one tree, so when the span runs into a shadow tree, or out of one, the
|
|
16
|
+
* range ends at the last character in the tree it starts in.
|
|
17
|
+
*/
|
|
1
18
|
export const createRangeFromVisibleMap = (visibleMap, start, end) => {
|
|
2
19
|
if (!visibleMap || typeof document === "undefined")
|
|
3
20
|
return null;
|
|
@@ -9,13 +26,62 @@ export const createRangeFromVisibleMap = (visibleMap, start, end) => {
|
|
|
9
26
|
return null;
|
|
10
27
|
if (!endMapping)
|
|
11
28
|
endMapping = startMapping;
|
|
12
|
-
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
29
|
+
if (treeOf(endMapping) !== treeOf(startMapping)) {
|
|
30
|
+
const tree = treeOf(startMapping);
|
|
31
|
+
endMapping = startMapping;
|
|
32
|
+
for (let index = start + 1; index < end; index++) {
|
|
33
|
+
const mapping = visibleMap.get(index);
|
|
34
|
+
if (mapping && treeOf(mapping) === tree)
|
|
35
|
+
endMapping = mapping;
|
|
36
|
+
}
|
|
17
37
|
}
|
|
18
|
-
|
|
19
|
-
|
|
38
|
+
return rangeBetween(startMapping, endMapping);
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* The ranges over visible characters `start` to `end` (exclusive), one per run of
|
|
42
|
+
* characters in the same tree, so a span crossing shadow boundaries paints in
|
|
43
|
+
* each tree it covers. A span within one tree gives exactly
|
|
44
|
+
* {@link createRangeFromVisibleMap}'s range.
|
|
45
|
+
*/
|
|
46
|
+
export const createRangesFromVisibleMap = (visibleMap, start, end) => {
|
|
47
|
+
if (!visibleMap || typeof document === "undefined" || end <= start)
|
|
48
|
+
return [];
|
|
49
|
+
const startMapping = visibleMap.get(start);
|
|
50
|
+
if (!startMapping)
|
|
51
|
+
return [];
|
|
52
|
+
const tree = treeOf(startMapping);
|
|
53
|
+
let crossesTrees = false;
|
|
54
|
+
for (let index = start + 1; index < end && !crossesTrees; index++) {
|
|
55
|
+
const mapping = visibleMap.get(index);
|
|
56
|
+
if (mapping && treeOf(mapping) !== tree)
|
|
57
|
+
crossesTrees = true;
|
|
58
|
+
}
|
|
59
|
+
if (!crossesTrees) {
|
|
60
|
+
const range = createRangeFromVisibleMap(visibleMap, start, end);
|
|
61
|
+
return range ? [range] : [];
|
|
62
|
+
}
|
|
63
|
+
const ranges = [];
|
|
64
|
+
let runStart = null;
|
|
65
|
+
let runEnd = null;
|
|
66
|
+
const closeRun = () => {
|
|
67
|
+
if (runStart && runEnd) {
|
|
68
|
+
const range = rangeBetween(runStart, runEnd);
|
|
69
|
+
if (range)
|
|
70
|
+
ranges.push(range);
|
|
71
|
+
}
|
|
72
|
+
runStart = null;
|
|
73
|
+
runEnd = null;
|
|
74
|
+
};
|
|
75
|
+
for (let index = start; index < end; index++) {
|
|
76
|
+
const mapping = visibleMap.get(index);
|
|
77
|
+
if (!mapping)
|
|
78
|
+
continue;
|
|
79
|
+
if (runStart && treeOf(runStart) !== treeOf(mapping))
|
|
80
|
+
closeRun();
|
|
81
|
+
if (!runStart)
|
|
82
|
+
runStart = mapping;
|
|
83
|
+
runEnd = mapping;
|
|
20
84
|
}
|
|
85
|
+
closeRun();
|
|
86
|
+
return ranges;
|
|
21
87
|
};
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the host knows about the content being highlighted. `scopeElement`
|
|
3
|
+
* falls back to the content element being read.
|
|
4
|
+
*/
|
|
1
5
|
export interface TTSHighlightContext {
|
|
2
6
|
scopeElement?: HTMLElement | null;
|
|
3
7
|
itemId?: string;
|
|
@@ -6,12 +10,20 @@ export interface TTSHighlightContext {
|
|
|
6
10
|
contentKind?: string;
|
|
7
11
|
regionPolicy?: string;
|
|
8
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* Host remap of TTS highlight targets. A null or undefined result keeps the
|
|
15
|
+
* native targets, and so does a result outside `scopeElement` or a throw. For
|
|
16
|
+
* sentences, one out-of-scope or non-Range/Element entry keeps all native
|
|
17
|
+
* ranges.
|
|
18
|
+
*/
|
|
9
19
|
export interface TTSHighlightTargetResolver {
|
|
10
20
|
resolveWordRange?(range: Range, context: TTSHighlightContext): Range | null | undefined;
|
|
11
21
|
resolveSentenceRanges?(ranges: Range[], context: TTSHighlightContext): Array<Range | HTMLElement> | null | undefined;
|
|
12
22
|
}
|
|
23
|
+
/** A resolver with the context it is called with. */
|
|
13
24
|
export interface TTSHighlightTargetResolverRuntime {
|
|
14
25
|
context: TTSHighlightContext;
|
|
15
26
|
resolver?: TTSHighlightTargetResolver | null;
|
|
16
27
|
}
|
|
28
|
+
/** Read at every highlight; a throw counts as no resolver. */
|
|
17
29
|
export type TTSHighlightTargetResolverProvider = () => TTSHighlightTargetResolverRuntime | null | undefined;
|
|
@@ -15,4 +15,8 @@ export interface MathAwareTextResult {
|
|
|
15
15
|
chunks: MathAwareSpeechChunk[];
|
|
16
16
|
containsMathMarkup: boolean;
|
|
17
17
|
}
|
|
18
|
-
|
|
18
|
+
/**
|
|
19
|
+
* With `range`, only the part of `element` the range selects: text it selects
|
|
20
|
+
* and equations it holds whole.
|
|
21
|
+
*/
|
|
22
|
+
export declare const collectMathAwareTextAndMap: (element: Element, options?: TextProcessingOptions, range?: Range) => MathAwareTextResult;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { flatQuerySelector, flatTreeChildNodes, flatTreeParentElement, rangeIntersectsComposedNode, } from "./flat-tree.js";
|
|
1
2
|
import { canonicalizeMathML } from "./mathml-sanitization.js";
|
|
2
|
-
import { collectVisibleTextAndMap, isNodeExcludedFromSpeech, normalizeTextForSpeech, shouldInsertWordBoundarySpace, } from "./text-processing.js";
|
|
3
|
+
import { collectVisibleTextAndMap, isNodeExcludedFromSpeech, normalizeTextForSpeech, rangeHoldsSpeakableElement, shouldInsertWordBoundarySpace, } from "./text-processing.js";
|
|
3
4
|
const createAccumulator = (options) => ({
|
|
4
5
|
chars: [],
|
|
5
6
|
map: new Map(),
|
|
@@ -21,7 +22,7 @@ const getDataMathML = (element) => {
|
|
|
21
22
|
return value && value.trim() ? value : null;
|
|
22
23
|
};
|
|
23
24
|
const findAssistiveMathML = (element) => {
|
|
24
|
-
const assistive = element
|
|
25
|
+
const assistive = flatQuerySelector(element, "mjx-assistive-mml math");
|
|
25
26
|
return assistive?.outerHTML || null;
|
|
26
27
|
};
|
|
27
28
|
const findCanonicalMathML = (element) => {
|
|
@@ -72,22 +73,20 @@ const TEXT_CHUNK_SOURCE_ROLES = new Set([
|
|
|
72
73
|
"rowheader",
|
|
73
74
|
]);
|
|
74
75
|
const resolveTextChunkSourceElement = (textNode, root) => {
|
|
75
|
-
let current = textNode
|
|
76
|
-
let best = null;
|
|
76
|
+
let current = flatTreeParentElement(textNode);
|
|
77
77
|
while (current && current !== root) {
|
|
78
78
|
const role = (current.getAttribute("role") || "").toLowerCase();
|
|
79
79
|
const tagName = current.tagName.toUpperCase();
|
|
80
80
|
if (TEXT_CHUNK_SOURCE_TAGS.has(tagName) ||
|
|
81
81
|
TEXT_CHUNK_SOURCE_ROLES.has(role)) {
|
|
82
|
-
|
|
83
|
-
break;
|
|
82
|
+
return current;
|
|
84
83
|
}
|
|
85
|
-
current = current
|
|
84
|
+
current = flatTreeParentElement(current);
|
|
86
85
|
}
|
|
87
|
-
return
|
|
86
|
+
return root;
|
|
88
87
|
};
|
|
89
88
|
const hasMathCandidate = (element) => Boolean(typeof element.querySelector === "function" &&
|
|
90
|
-
element
|
|
89
|
+
flatQuerySelector(element, "math, [data-mathml], .MathJax, mjx-container, mjx-assistive-mml")) ||
|
|
91
90
|
element.tagName?.toLowerCase() === "math" ||
|
|
92
91
|
element.hasAttribute?.("data-mathml") ||
|
|
93
92
|
isMathJaxElement(element);
|
|
@@ -121,10 +120,11 @@ const shouldInsertBoundarySpace = (acc, nextCharacter) => {
|
|
|
121
120
|
// visible-text collector, instead of an ASCII-only heuristic.
|
|
122
121
|
return shouldInsertWordBoundarySpace(previous, nextCharacter, acc.options);
|
|
123
122
|
};
|
|
124
|
-
|
|
123
|
+
/** `start` and `end` bound the part of the node appended, for a selection. */
|
|
124
|
+
const appendTextNode = (acc, textNode, start = 0, end = (textNode.textContent || "").length) => {
|
|
125
125
|
const raw = textNode.textContent || "";
|
|
126
126
|
let appendedNonWhitespaceInNode = false;
|
|
127
|
-
for (let i =
|
|
127
|
+
for (let i = start; i < end; i++) {
|
|
128
128
|
const character = raw[i];
|
|
129
129
|
const isWhitespace = /\s/.test(character);
|
|
130
130
|
if (acc.inLeadingWhitespace) {
|
|
@@ -156,13 +156,12 @@ const appendCollectedText = (acc, collected) => {
|
|
|
156
156
|
for (let i = 0; i < collected.text.length; i++) {
|
|
157
157
|
const character = collected.text[i];
|
|
158
158
|
const isWhitespace = /\s/.test(character);
|
|
159
|
-
const mapping = collected.map.get(i)
|
|
160
|
-
|
|
161
|
-
const
|
|
162
|
-
const normalizedMapping = mapping
|
|
159
|
+
const mapping = collected.map.get(i);
|
|
160
|
+
// An unmapped character borrows the last mapped position.
|
|
161
|
+
const characterMapping = mapping
|
|
163
162
|
? { node: mapping.node, offset: mapping.offset }
|
|
164
|
-
:
|
|
165
|
-
? { node:
|
|
163
|
+
: acc.lastMapped
|
|
164
|
+
? { node: acc.lastMapped.node, offset: acc.lastMapped.offset }
|
|
166
165
|
: null;
|
|
167
166
|
if (acc.inLeadingWhitespace) {
|
|
168
167
|
if (isWhitespace)
|
|
@@ -171,29 +170,16 @@ const appendCollectedText = (acc, collected) => {
|
|
|
171
170
|
}
|
|
172
171
|
if (isWhitespace) {
|
|
173
172
|
if (!acc.lastCharWasWhitespace) {
|
|
174
|
-
appendCharacter(acc, " ",
|
|
173
|
+
appendCharacter(acc, " ", characterMapping);
|
|
175
174
|
}
|
|
176
175
|
acc.lastCharWasWhitespace = true;
|
|
177
176
|
continue;
|
|
178
177
|
}
|
|
179
178
|
if (i === 0 && shouldInsertBoundarySpace(acc, character)) {
|
|
180
|
-
appendCharacter(acc, " ",
|
|
179
|
+
appendCharacter(acc, " ", characterMapping);
|
|
181
180
|
}
|
|
182
|
-
appendCharacter(acc, character,
|
|
181
|
+
appendCharacter(acc, character, characterMapping);
|
|
183
182
|
acc.lastCharWasWhitespace = false;
|
|
184
|
-
if (mapping) {
|
|
185
|
-
acc.map.set(acc.position - 1, {
|
|
186
|
-
node: mapping.node,
|
|
187
|
-
offset: mapping.offset,
|
|
188
|
-
});
|
|
189
|
-
acc.lastMapped = { node: mapping.node, offset: mapping.offset };
|
|
190
|
-
}
|
|
191
|
-
else if (syntheticNode) {
|
|
192
|
-
acc.map.set(acc.position - 1, {
|
|
193
|
-
node: syntheticNode,
|
|
194
|
-
offset: syntheticOffset,
|
|
195
|
-
});
|
|
196
|
-
}
|
|
197
183
|
}
|
|
198
184
|
};
|
|
199
185
|
const textFallbackFromMathML = (mathml) => {
|
|
@@ -230,7 +216,7 @@ const textFallbackFromMathML = (mathml) => {
|
|
|
230
216
|
const mapFallbackToAssistiveMath = (element, fallbackText) => {
|
|
231
217
|
const map = new Map();
|
|
232
218
|
const sourceMath = isMathJaxElement(element)
|
|
233
|
-
? element
|
|
219
|
+
? flatQuerySelector(element, "mjx-assistive-mml math")
|
|
234
220
|
: null;
|
|
235
221
|
if (!sourceMath)
|
|
236
222
|
return map;
|
|
@@ -247,7 +233,7 @@ const mapFallbackToAssistiveMath = (element, fallbackText) => {
|
|
|
247
233
|
}
|
|
248
234
|
if (node.nodeType !== 1 || isAnnotationElement(node))
|
|
249
235
|
return;
|
|
250
|
-
for (const child of
|
|
236
|
+
for (const child of flatTreeChildNodes(node)) {
|
|
251
237
|
visit(child);
|
|
252
238
|
}
|
|
253
239
|
};
|
|
@@ -281,7 +267,7 @@ const collectVisibleMathFallback = (element, canonicalMathML, options) => {
|
|
|
281
267
|
isAnnotationElement(childElement)) {
|
|
282
268
|
return;
|
|
283
269
|
}
|
|
284
|
-
for (const child of
|
|
270
|
+
for (const child of flatTreeChildNodes(childElement)) {
|
|
285
271
|
visit(child);
|
|
286
272
|
}
|
|
287
273
|
};
|
|
@@ -307,7 +293,7 @@ const trimTrailingWhitespace = (acc) => {
|
|
|
307
293
|
acc.map.delete(acc.position);
|
|
308
294
|
}
|
|
309
295
|
};
|
|
310
|
-
const collectMathAware = (root, options) => {
|
|
296
|
+
const collectMathAware = (root, options, range) => {
|
|
311
297
|
const acc = createAccumulator(options);
|
|
312
298
|
const chunks = [];
|
|
313
299
|
let textChunkStart = 0;
|
|
@@ -328,22 +314,28 @@ const collectMathAware = (root, options) => {
|
|
|
328
314
|
const processNode = (node) => {
|
|
329
315
|
if (isNodeExcludedFromSpeech(node, root))
|
|
330
316
|
return;
|
|
331
|
-
if (
|
|
317
|
+
if (range && !rangeIntersectsComposedNode(range, node))
|
|
318
|
+
return;
|
|
319
|
+
if (node.nodeType === 3) {
|
|
332
320
|
const sourceElement = resolveTextChunkSourceElement(node, root);
|
|
333
321
|
if (textChunkSourceElement && sourceElement !== textChunkSourceElement) {
|
|
334
322
|
flushTextChunk();
|
|
335
323
|
}
|
|
336
324
|
textChunkSourceElement = sourceElement;
|
|
337
|
-
|
|
325
|
+
const textNode = node;
|
|
326
|
+
appendTextNode(acc, textNode, range?.startContainer === textNode ? range.startOffset : undefined, range?.endContainer === textNode ? range.endOffset : undefined);
|
|
338
327
|
return;
|
|
339
328
|
}
|
|
340
|
-
if (node.nodeType !==
|
|
329
|
+
if (node.nodeType !== 1)
|
|
341
330
|
return;
|
|
342
331
|
const element = node;
|
|
343
332
|
if (isAssistiveMathElement(element))
|
|
344
333
|
return;
|
|
345
334
|
const canonicalMathML = findCanonicalMathML(element);
|
|
346
|
-
|
|
335
|
+
// An equation is spoken as math only when the selection holds all of it;
|
|
336
|
+
// a part of one reads as the text selected.
|
|
337
|
+
if (canonicalMathML &&
|
|
338
|
+
(!range || rangeHoldsSpeakableElement(range, element, root))) {
|
|
347
339
|
flushTextChunk();
|
|
348
340
|
const collected = collectVisibleMathFallback(element, canonicalMathML, options);
|
|
349
341
|
appendCollectedText(acc, collected);
|
|
@@ -358,19 +350,16 @@ const collectMathAware = (root, options) => {
|
|
|
358
350
|
containsMathMarkup = true;
|
|
359
351
|
return;
|
|
360
352
|
}
|
|
361
|
-
for (const child of
|
|
353
|
+
for (const child of flatTreeChildNodes(element)) {
|
|
362
354
|
processNode(child);
|
|
363
355
|
}
|
|
364
356
|
};
|
|
365
|
-
for (const child of
|
|
357
|
+
for (const child of flatTreeChildNodes(root)) {
|
|
366
358
|
processNode(child);
|
|
367
359
|
}
|
|
368
360
|
trimTrailingWhitespace(acc);
|
|
369
361
|
flushTextChunk();
|
|
370
362
|
const visibleText = acc.chars.join("");
|
|
371
|
-
while (acc.map.has(visibleText.length)) {
|
|
372
|
-
acc.map.delete(visibleText.length);
|
|
373
|
-
}
|
|
374
363
|
return {
|
|
375
364
|
visibleText,
|
|
376
365
|
map: acc.map,
|
|
@@ -378,7 +367,13 @@ const collectMathAware = (root, options) => {
|
|
|
378
367
|
containsMathMarkup,
|
|
379
368
|
};
|
|
380
369
|
};
|
|
381
|
-
|
|
370
|
+
/**
|
|
371
|
+
* With `range`, only the part of `element` the range selects: text it selects
|
|
372
|
+
* and equations it holds whole.
|
|
373
|
+
*/
|
|
374
|
+
export const collectMathAwareTextAndMap = (element, options, range) => {
|
|
375
|
+
if (range)
|
|
376
|
+
return collectMathAware(element, options, range);
|
|
382
377
|
if (!hasMathCandidate(element)) {
|
|
383
378
|
const { text, map } = collectVisibleTextAndMap(element, options);
|
|
384
379
|
return {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type ResolveMathSpeechOptions, type SREMathSpeechOptions } from "./math-speech.js";
|
|
2
|
+
export interface MathControlNamesOptions {
|
|
3
|
+
/**
|
|
4
|
+
* The host's math speech options. Names take only `engineOptions`, where
|
|
5
|
+
* SRE's locale tables load from: their domain and style are fixed.
|
|
6
|
+
*/
|
|
7
|
+
getMathSpeech?: () => SREMathSpeechOptions | undefined;
|
|
8
|
+
/** The host's `content-language`, read when an expression is named. */
|
|
9
|
+
getContentLanguage?: () => string | null | undefined;
|
|
10
|
+
loadSre?: ResolveMathSpeechOptions["loadSre"];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Labels each typeset expression inside a control under `root`, open shadow
|
|
14
|
+
* roots included, with SRE's speech, as MathJax adds it and again whenever
|
|
15
|
+
* MathJax replaces it. An `aria-label` on the role-less `mjx-container` puts
|
|
16
|
+
* that speech in the name of the control around it, among the control's other
|
|
17
|
+
* text. English reads ClearSpeak, other languages MathSpeak, in the language of
|
|
18
|
+
* the content. The label replaces the elements' own; it stays when SRE cannot
|
|
19
|
+
* speak the math. Returns the function that stops observing.
|
|
20
|
+
*/
|
|
21
|
+
export declare function observeMathControlNames(root: Element, options?: MathControlNamesOptions): () => void;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { resolveContentLanguage } from "../../runtime/content-language.js";
|
|
2
|
+
import { flatQuerySelector, flatTreeClosest, walkFlatTree, } from "./flat-tree.js";
|
|
3
|
+
import { resolveMathSpeechFromChunks, } from "./math-speech.js";
|
|
4
|
+
import { canonicalizeMathML } from "./mathml-sanitization.js";
|
|
5
|
+
/**
|
|
6
|
+
* Elements that take their accessible name from their content. Browsers leave
|
|
7
|
+
* MathML out of that name, so a choice labelled with math is named from its
|
|
8
|
+
* bare symbols ("4 12" for 4 over 12). The elements' renderer labels the math
|
|
9
|
+
* in the same set of controls with its own English speech.
|
|
10
|
+
*/
|
|
11
|
+
const CONTROLS = [
|
|
12
|
+
"a[href]",
|
|
13
|
+
"button",
|
|
14
|
+
"label",
|
|
15
|
+
"summary",
|
|
16
|
+
...[
|
|
17
|
+
"button",
|
|
18
|
+
"checkbox",
|
|
19
|
+
"combobox",
|
|
20
|
+
"link",
|
|
21
|
+
"menuitem",
|
|
22
|
+
"menuitemcheckbox",
|
|
23
|
+
"menuitemradio",
|
|
24
|
+
"option",
|
|
25
|
+
"radio",
|
|
26
|
+
"switch",
|
|
27
|
+
"tab",
|
|
28
|
+
"treeitem",
|
|
29
|
+
].map((role) => `[role="${role}"]`),
|
|
30
|
+
].join(", ");
|
|
31
|
+
const TOKENS = new Set(["mi", "mn", "mtext"]);
|
|
32
|
+
const isToken = (element) => TOKENS.has(element.localName) ||
|
|
33
|
+
(element.localName === "mrow" &&
|
|
34
|
+
element.children.length === 1 &&
|
|
35
|
+
TOKENS.has(element.children[0].localName));
|
|
36
|
+
/**
|
|
37
|
+
* ClearSpeak's fraction preference for a name. "4 over 12" keeps the numerals
|
|
38
|
+
* as written, where the default says "four fourths" for 4 over 4 (WCAG 2.5.3:
|
|
39
|
+
* a name does not put words in place of the formula). "Over" between longer
|
|
40
|
+
* parts is ambiguous, so an expression holding such a fraction reads every
|
|
41
|
+
* fraction by numerator and denominator.
|
|
42
|
+
*/
|
|
43
|
+
const fractionStyle = (math) => Array.from(math.getElementsByTagName("mfrac")).every((fraction) => Array.from(fraction.children).every(isToken))
|
|
44
|
+
? "Fraction_Over"
|
|
45
|
+
: "Fraction_General";
|
|
46
|
+
const isEnglish = (language) => !language || language.toLowerCase().split("-")[0] === "en";
|
|
47
|
+
/**
|
|
48
|
+
* Labels each typeset expression inside a control under `root`, open shadow
|
|
49
|
+
* roots included, with SRE's speech, as MathJax adds it and again whenever
|
|
50
|
+
* MathJax replaces it. An `aria-label` on the role-less `mjx-container` puts
|
|
51
|
+
* that speech in the name of the control around it, among the control's other
|
|
52
|
+
* text. English reads ClearSpeak, other languages MathSpeak, in the language of
|
|
53
|
+
* the content. The label replaces the elements' own; it stays when SRE cannot
|
|
54
|
+
* speak the math. Returns the function that stops observing.
|
|
55
|
+
*/
|
|
56
|
+
export function observeMathControlNames(root, options = {}) {
|
|
57
|
+
if (typeof MutationObserver === "undefined")
|
|
58
|
+
return () => { };
|
|
59
|
+
const speech = new Map();
|
|
60
|
+
let stopped = false;
|
|
61
|
+
const speak = async (mathml, math, language) => {
|
|
62
|
+
const result = await resolveMathSpeechFromChunks([{ type: "math", mathml, fallbackText: "" }], {
|
|
63
|
+
language,
|
|
64
|
+
loadSre: options.loadSre,
|
|
65
|
+
mathSpeech: {
|
|
66
|
+
...(isEnglish(language) ? { style: fractionStyle(math) } : {}),
|
|
67
|
+
engineOptions: options.getMathSpeech?.()?.engineOptions,
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
return result.usedMathSpeech ? result.speechText : null;
|
|
71
|
+
};
|
|
72
|
+
const name = (container) => {
|
|
73
|
+
if (!flatTreeClosest(container, CONTROLS))
|
|
74
|
+
return;
|
|
75
|
+
const math = flatQuerySelector(container, "math");
|
|
76
|
+
const mathml = math && canonicalizeMathML(math.outerHTML);
|
|
77
|
+
if (!math || !mathml)
|
|
78
|
+
return;
|
|
79
|
+
const language = resolveContentLanguage(container, {
|
|
80
|
+
contentLanguage: options.getContentLanguage?.(),
|
|
81
|
+
});
|
|
82
|
+
const key = `${language ?? ""}\u0000${mathml}`;
|
|
83
|
+
let pending = speech.get(key);
|
|
84
|
+
if (!pending) {
|
|
85
|
+
pending = speak(mathml, math, language);
|
|
86
|
+
speech.set(key, pending);
|
|
87
|
+
}
|
|
88
|
+
void pending.then((label) => {
|
|
89
|
+
if (stopped || !label || !container.isConnected)
|
|
90
|
+
return;
|
|
91
|
+
if (container.getAttribute("aria-label") !== label) {
|
|
92
|
+
container.setAttribute("aria-label", label);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
};
|
|
96
|
+
// A shadow root is a tree of its own, which an observer on `root` does not
|
|
97
|
+
// see into, so each one found is observed as well. One attached after its
|
|
98
|
+
// host was visited is not found until something is added around the host.
|
|
99
|
+
const observed = new WeakSet();
|
|
100
|
+
const observeTree = (tree) => {
|
|
101
|
+
if (observed.has(tree))
|
|
102
|
+
return;
|
|
103
|
+
observed.add(tree);
|
|
104
|
+
observer.observe(tree, { childList: true, subtree: true });
|
|
105
|
+
};
|
|
106
|
+
const visit = (node) => {
|
|
107
|
+
if (node.nodeType !== 1)
|
|
108
|
+
return;
|
|
109
|
+
const element = node;
|
|
110
|
+
const container = flatTreeClosest(element, "mjx-container");
|
|
111
|
+
if (container) {
|
|
112
|
+
name(container);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
if (element.shadowRoot)
|
|
116
|
+
observeTree(element.shadowRoot);
|
|
117
|
+
walkFlatTree(element, (descendant) => {
|
|
118
|
+
if (descendant.nodeType !== 1)
|
|
119
|
+
return "skip";
|
|
120
|
+
const found = descendant;
|
|
121
|
+
if (found.localName === "mjx-container") {
|
|
122
|
+
name(found);
|
|
123
|
+
return "skip";
|
|
124
|
+
}
|
|
125
|
+
if (found.shadowRoot)
|
|
126
|
+
observeTree(found.shadowRoot);
|
|
127
|
+
return undefined;
|
|
128
|
+
});
|
|
129
|
+
};
|
|
130
|
+
const observer = new MutationObserver((records) => {
|
|
131
|
+
for (const record of records) {
|
|
132
|
+
for (const node of record.addedNodes)
|
|
133
|
+
visit(node);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
observeTree(root);
|
|
137
|
+
visit(root);
|
|
138
|
+
return () => {
|
|
139
|
+
stopped = true;
|
|
140
|
+
observer.disconnect();
|
|
141
|
+
};
|
|
142
|
+
}
|
|
@@ -14,7 +14,7 @@ export interface ResolveMathSpeechOptions {
|
|
|
14
14
|
mathSpeech?: SREMathSpeechOptions;
|
|
15
15
|
/**
|
|
16
16
|
* Also produce SRE's SSML rendering (markup: "ssml") for the equation, for
|
|
17
|
-
* the runtime generated-SSML path
|
|
17
|
+
* the runtime generated-SSML path. Only populated when the input
|
|
18
18
|
* is a single math chunk and SRE succeeds. The plain `speechText` is always
|
|
19
19
|
* computed with markup: "none" so the plain path is unaffected.
|
|
20
20
|
*/
|
|
@@ -43,6 +43,17 @@ export interface ResolvedMathSpeech {
|
|
|
43
43
|
*/
|
|
44
44
|
ssml?: string;
|
|
45
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* Loads the speech-rule-engine once per page. A failed load is dropped, so the
|
|
48
|
+
* next call tries again; meanwhile math reads as its visible text. The first
|
|
49
|
+
* failure warns, later ones log at debug.
|
|
50
|
+
*/
|
|
51
|
+
export declare const createSreLoader: (importEngine: () => Promise<SpeechRuleEngineApi>) => ((engineOptions?: Record<string, unknown>) => Promise<SpeechRuleEngineApi>);
|
|
52
|
+
/**
|
|
53
|
+
* One speech-rule-engine load for a whole read: its equations share the
|
|
54
|
+
* attempt, so a failed load costs a read one attempt.
|
|
55
|
+
*/
|
|
56
|
+
export declare const createReadSreLoad: (mathSpeech?: SREMathSpeechOptions) => (() => Promise<SpeechRuleEngineApi>);
|
|
46
57
|
export declare const normalizeSREMathSpeechOptions: (options: unknown) => SREMathSpeechOptions | undefined;
|
|
47
58
|
export declare const resolveMathSpeechFromChunks: (chunks: MathAwareSpeechChunk[], options?: ResolveMathSpeechOptions) => Promise<ResolvedMathSpeech>;
|
|
48
59
|
export {};
|