@pie-players/pie-players-shared 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.
Files changed (86) hide show
  1. package/README.md +88 -75
  2. package/dist/components/vendor/nds/README.md +4 -5
  3. package/dist/config/profile.d.ts +1 -1
  4. package/dist/config/profile.js +1 -1
  5. package/dist/i18n/index.d.ts +1 -1
  6. package/dist/i18n/index.js +1 -1
  7. package/dist/i18n/language-tags.d.ts +9 -1
  8. package/dist/i18n/language-tags.js +11 -1
  9. package/dist/i18n/messages/en-US.d.ts +33 -28
  10. package/dist/i18n/messages/en-US.js +34 -29
  11. package/dist/i18n/messages/nl-NL.d.ts +33 -28
  12. package/dist/i18n/messages/nl-NL.js +34 -29
  13. package/dist/i18n/provider.d.ts +14 -7
  14. package/dist/i18n/provider.js +26 -29
  15. package/dist/i18n/types.d.ts +4 -5
  16. package/dist/index.d.ts +1 -1
  17. package/dist/index.js +0 -1
  18. package/dist/instrumentation/providers/BaseInstrumentationProvider.js +0 -14
  19. package/dist/loader-config.d.ts +0 -2
  20. package/dist/loader-config.js +0 -2
  21. package/dist/loaders/element-loader.js +13 -6
  22. package/dist/loaders/esm-adapter.d.ts +11 -0
  23. package/dist/loaders/esm-adapter.js +74 -45
  24. package/dist/loaders/iife-adapter.d.ts +3 -3
  25. package/dist/loaders/iife-adapter.js +36 -35
  26. package/dist/loaders/index.d.ts +4 -2
  27. package/dist/loaders/index.js +2 -1
  28. package/dist/loaders/mathjax-events.d.ts +22 -0
  29. package/dist/loaders/mathjax-events.js +65 -0
  30. package/dist/loaders/preloaded-registration.d.ts +18 -2
  31. package/dist/loaders/preloaded-registration.js +14 -2
  32. package/dist/media/index.d.ts +4 -6
  33. package/dist/media/index.js +6 -8
  34. package/dist/object/index.d.ts +8 -3
  35. package/dist/object/index.js +8 -6
  36. package/dist/pie/asset-handler.d.ts +0 -17
  37. package/dist/pie/asset-handler.js +1 -1
  38. package/dist/pie/authoring.js +5 -7
  39. package/dist/pie/elements-rendered.d.ts +23 -0
  40. package/dist/pie/elements-rendered.js +96 -0
  41. package/dist/pie/index.d.ts +4 -6
  42. package/dist/pie/index.js +4 -7
  43. package/dist/pie/initialization.d.ts +13 -14
  44. package/dist/pie/initialization.js +61 -75
  45. package/dist/pie/instrumentation-event-bridge.js +23 -1
  46. package/dist/pie/instrumentation-event-map.js +11 -18
  47. package/dist/pie/item-controller.js +4 -0
  48. package/dist/pie/item-session-contract.js +7 -9
  49. package/dist/pie/logger.d.ts +6 -0
  50. package/dist/pie/logger.js +10 -0
  51. package/dist/pie/math-assets.d.ts +48 -0
  52. package/dist/pie/math-assets.js +81 -0
  53. package/dist/pie/resource-monitor.d.ts +34 -32
  54. package/dist/pie/resource-monitor.js +152 -231
  55. package/dist/pie/scoring.d.ts +1 -6
  56. package/dist/pie/scoring.js +3 -8
  57. package/dist/pie/session-commit.js +1 -1
  58. package/dist/pie/stages.d.ts +11 -47
  59. package/dist/pie/stages.js +11 -47
  60. package/dist/pie/updates.js +5 -4
  61. package/dist/pie/utils.d.ts +0 -2
  62. package/dist/pie/utils.js +0 -2
  63. package/dist/security/sanitize-item-markup.d.ts +8 -4
  64. package/dist/security/sanitize-item-markup.js +52 -6
  65. package/dist/security/sanitize-svg-icon.js +2 -2
  66. package/dist/security/wrap-overwide-images.d.ts +1 -1
  67. package/dist/security/wrap-overwide-images.js +20 -1
  68. package/dist/security/wrap-overwide.d.ts +8 -0
  69. package/dist/security/wrap-overwide.js +47 -3
  70. package/dist/timed-media/media-element-source.js +1 -2
  71. package/dist/types/index.d.ts +88 -153
  72. package/dist/types/index.js +2 -2
  73. package/dist/ui/attribute-coercion.d.ts +5 -0
  74. package/dist/ui/attribute-coercion.js +6 -4
  75. package/dist/ui/content-styles.d.ts +6 -10
  76. package/dist/ui/content-styles.js +8 -13
  77. package/dist/ui/first-focusable.d.ts +0 -1
  78. package/dist/ui/first-focusable.js +0 -1
  79. package/dist/ui/focus-trap.js +2 -3
  80. package/dist/ui/scope-css.d.ts +23 -26
  81. package/dist/ui/scope-css.js +23 -26
  82. package/package.json +6 -4
  83. package/dist/loaders/mathjax-version-conflict.d.ts +0 -17
  84. package/dist/loaders/mathjax-version-conflict.js +0 -51
  85. package/dist/pie/stage-tracker.d.ts +0 -50
  86. package/dist/pie/stage-tracker.js +0 -105
package/README.md CHANGED
@@ -1,8 +1,9 @@
1
1
  # PIE Players Shared
2
2
 
3
- Shared runtime utilities for the `@pie-players/*` player suite. This package is
4
- for framework code and host integrations that need the same loader, PIE config,
5
- security, object, i18n, or type helpers used by the player packages.
3
+ Shared runtime utilities for the `@pie-players/*` player suite: the element
4
+ loader, PIE config and session helpers, markup security, i18n, and the
5
+ formative, timed-media and media contracts. For framework code and host
6
+ integrations that need the helpers the player packages use.
6
7
 
7
8
  ## Public Exports
8
9
 
@@ -12,28 +13,38 @@ import { makeUniqueTags } from "@pie-players/pie-players-shared/pie";
12
13
  import { normalizeItemPlayerStrategy } from "@pie-players/pie-players-shared";
13
14
  ```
14
15
 
15
- Supported subpaths are declared in `package.json`:
16
-
17
- - `@pie-players/pie-players-shared`
18
- - `@pie-players/pie-players-shared/loader-config`
19
- - `@pie-players/pie-players-shared/security`
20
- - `@pie-players/pie-players-shared/object`
21
- - `@pie-players/pie-players-shared/types`
22
- - `@pie-players/pie-players-shared/formative`
23
- - `@pie-players/pie-players-shared/timed-media`
24
- - `@pie-players/pie-players-shared/media`
25
- - `@pie-players/pie-players-shared/pie`
26
- - `@pie-players/pie-players-shared/pie/tag-names`
27
- - `@pie-players/pie-players-shared/loaders`
28
- - `@pie-players/pie-players-shared/i18n`
16
+ The subpaths below are the package's `exports`; nothing else is importable.
17
+
18
+ | Subpath | Contents |
19
+ | --- | --- |
20
+ | `@pie-players/pie-players-shared` | The root: the loader, PIE, security and object helpers, loader config, instrumentation providers, the item-player strategy helpers, the default bundle host URL (`BUILDER_BUNDLE_URL`), a subset of the shared types, and the UI helpers (attribute coercion, content styles, pointer gestures, overlay placement, focus trap, safe storage, scoped CSS) |
21
+ | `/loader-config` | `LoaderConfig` and its defaults: instrumentation (`trackPageActions`, `instrumentationProvider`), resource retry, and IIFE bundle retry |
22
+ | `/security` | The item-markup sanitizer (`sanitizeItemMarkup`, `createDefaultItemMarkupSanitizer`, `buildAuthoringAllowList`), external-stylesheet URL validation, the SVG icon and `style` attribute sanitizers, and the wrappers that put overwide images and tables in a scrollable region |
23
+ | `/object` | `mergeObjectsIgnoringNullUndefined`, `cloneDeep`, `isPlainRecord` |
24
+ | `/types` | The shared types: item, passage, section and session entities, PIE models and controllers, accessibility catalogs, and the [media vocabulary](#media-validation) |
25
+ | `/formative` | [Formative delivery](#formative-delivery) |
26
+ | `/timed-media` | [Timed media](#timed-media) |
27
+ | `/media` | [Media validation](#media-validation) |
28
+ | `/pie` | PIE runtime utilities: config helpers, bundle initialization, `ItemController` and the item session contract, session commit and snapshots, authoring helpers, math renderer setup, instrumentation event maps ([PIE utilities](src/pie/README.md)) |
29
+ | `/pie/tag-names` | Custom element tag helpers: `validateCustomElementTag`, `toViewTag`, `toPrintHashedTag`, `parseVersionedTagName` |
30
+ | `/loaders` | The `ElementLoader` primitive and its IIFE and ESM adapters, `registerPreloadedElements`, the element package policy, and the MathJax event names ([Element loading](#element-loading)) |
31
+ | `/i18n` | `createPieI18n`, a provider for every bundled locale ([i18n](src/i18n/README.md)) |
32
+ | `/i18n/types` | The i18n contract, types only |
33
+ | `/i18n/provider` | `SimpleI18n`, `getDefaultI18n` and `resolveInterfaceI18n`, with the English catalog only |
34
+ | `/i18n/catalogs` | `BUNDLED_LOCALES` and lazy loaders for the bundled locales other than English |
35
+ | `/i18n/language-tags` | BCP 47 language tag normalization and matching |
36
+ | `/nds-icon-button` | `<nds-icon-button>`, an icon button vendored as a prebuilt bundle with Lit inlined; importing it registers the tag. The assessment toolkit and `@pie-players/pie-tool-tts-inline` render it |
37
+ | `/ui/attribute-coercion` | Boolean attribute coercion for custom elements |
38
+ | `/ui/content-styles` | `installContentStyles`, `auditContentStyles` and the opt-out checks behind the item player's content styles |
39
+ | `/tools/term-lookup` | Term normalization and the lookup session the dictionary tools share; the host supplies the endpoint or a resolver |
29
40
 
30
41
  ## Formative Delivery
31
42
 
32
43
  `@pie-players/pie-players-shared/formative` holds the policy resolution, outcome
33
44
  aggregation, Try-state reducer, item view, and mastery rollup that
34
- `pie-section-player` drives. It is pure — no DOM, no timers, no element registry
35
- — so it is testable without a browser and importable by an adapter that has no
36
- player.
45
+ `pie-section-player` drives. It is pure (no DOM, no timers, no element
46
+ registry), so it is testable without a browser and importable by an adapter that
47
+ has no player.
37
48
 
38
49
  ```ts
39
50
  import {
@@ -44,8 +55,8 @@ import {
44
55
  } from "@pie-players/pie-players-shared/formative";
45
56
  ```
46
57
 
47
- The authored half — `FormativeDeliveryPolicy` on `AssessmentSection` and
48
- `FormativeItemPolicy` on `AssessmentItemRef` — is re-exported from the package
58
+ The authored half, `FormativeDeliveryPolicy` on `AssessmentSection` and
59
+ `FormativeItemPolicy` on `AssessmentItemRef`, is re-exported from the package
49
60
  root and from `/types`, beside the section types it annotates.
50
61
 
51
62
  The contract is [`docs/prds/formative-delivery-contract.md`](../../docs/prds/formative-delivery-contract.md),
@@ -55,9 +66,9 @@ including the QTI 3 mapping and why PIE says **Try** rather than "attempt".
55
66
 
56
67
  `@pie-players/pie-players-shared/timed-media` holds the timed-media section
57
68
  vocabulary, its validation, the cue reduction, the session slice, and the **Media
58
- Time Source** port that a section reaches media through. Pure apart from
59
- `createMediaElementTimeSource`, which is inert until called, so the contract stays
60
- importable in Node beside the rest.
69
+ Time Source** port that a section reaches media through. It is pure apart from
70
+ `createMediaElementTimeSource`, which is inert until called, so the contract
71
+ imports in Node.js beside the rest.
61
72
 
62
73
  ```ts
63
74
  import {
@@ -69,14 +80,14 @@ import {
69
80
  } from "@pie-players/pie-players-shared/timed-media";
70
81
  ```
71
82
 
72
- The port is shaped after `HTMLMediaElement` on purpose — a native `<video>`
73
- satisfies it through the adapter above — with two departures: seeking is
74
- `seekTo(seconds)` rather than a writable `currentTime`, and `capabilities` declares
75
- `canPause` / `canRestrictSeeking`, because a source that cannot control playback
76
- needs a way to say so. A host implementing the port directly needs no PIE element to
77
- deliver timed media.
83
+ The port is shaped after `HTMLMediaElement`, so a native `<video>` satisfies it
84
+ through `createMediaElementTimeSource`, with two departures: seeking is
85
+ `seekTo(seconds)` in place of a writable `currentTime`, and `capabilities`
86
+ declares `canPause` and `canRestrictSeeking`, because a source that cannot
87
+ control playback needs a way to say so. A host implementing the port directly
88
+ needs no PIE element to deliver timed media.
78
89
 
79
- The authored half — `sectionType` and `timedMedia` on `AssessmentSection` — is
90
+ The authored half, `sectionType` and `timedMedia` on `AssessmentSection`, is
80
91
  re-exported from the package root and from `/types`, beside the section types it
81
92
  annotates.
82
93
 
@@ -87,14 +98,22 @@ unenforceable policy degrades to advisory rather than failing closed.
87
98
  ## Media Validation
88
99
 
89
100
  `@pie-players/pie-players-shared/media` validates authored, wire-facing media
90
- references before they reach a media element: the source-scheme allow-list
91
- (`isSafeMediaSrc`), source normalization with dedupe by `src`
92
- (`normalizeMediaSources`), fragment-range normalization, and
93
- unknown-`MediaAssetRef.version` rejection. `applyMediaFragment` writes a
94
- fragment range as a Media Fragments URI, and `enforceMediaFragment` holds a
95
- media element to that range because browsers honour the URI inconsistently.
101
+ references before they reach a media element:
102
+
103
+ - `isSafeMediaSrc` is the source-scheme allow-list: relative and
104
+ protocol-relative URLs, `http:`, `https:`, `data:` and `blob:`.
105
+ - `normalizeMediaSources` drops unsafe and malformed sources and deduplicates by
106
+ `src`, keeping the first.
107
+ - `normalizeMediaFragment` normalizes a fragment range; an end at or before the
108
+ start becomes an open end.
109
+ - `isUnsupportedMediaAssetVersion` rejects a `MediaAssetRef.version` other than
110
+ `SUPPORTED_MEDIA_ASSET_VERSION` (1); an absent version passes.
111
+ - `applyMediaFragment` writes a fragment range as a Media Fragments URI (`#t=`),
112
+ and `enforceMediaFragment` holds a media element to that range, because
113
+ browsers honor the URI inconsistently.
114
+
96
115
  Nothing runs at import time, so an element imports it without the assessment
97
- toolkit; the toolkit root re-exports the same names.
116
+ toolkit.
98
117
 
99
118
  ```ts
100
119
  import {
@@ -104,44 +123,38 @@ import {
104
123
  } from "@pie-players/pie-players-shared/media";
105
124
  ```
106
125
 
107
- The media vocabulary it validates is [`docs/prds/shared-contracts/media-asset-contract.md`](../../docs/prds/shared-contracts/media-asset-contract.md).
108
-
109
- ## Browser ESM Element Contract
110
-
111
- The canonical producer-side contract lives with the `pie-elements-ng` package
112
- contract. The loader assumptions here must stay aligned with that producer
113
- surface.
114
-
115
- The ESM element loader consumes static `@pie-element/*` browser entries such as
116
- `dist/browser/delivery/index.js`; it does not transform element packages through
117
- CDN `+esm` entry points. Browser ESM elements must publish exact shared runtime
118
- metadata in `package.json` under `pie.browserSharedDependencies`.
119
- Under URL resolution it loads the variant an element declares in
120
- `pie.browserEditorRuntime` and maps that runtime's `pie.browserModules`, one
121
- runtime version per page; see
122
- [Shared editor runtime](../../docs/item-player/loading-strategies.md#shared-editor-runtime).
123
-
124
- jsDelivr is the default npm CDN provider. Hosts can opt into `esm.sh` with
125
- `loaderOptions.esmCdnProvider = "esm.sh"` and `loaderOptions.esmCdnUrl =
126
- "https://esm.sh"`. For `esm.sh`, PIE package artifacts are loaded from
127
- `raw.esm.sh` while shared browser dependencies are loaded from `esm.sh`.
128
- Provider names are open-ended: custom/internal providers can pass their own name
129
- when they follow the jsDelivr-compatible package-file URL layout, or pass a
130
- provider object when package artifacts and shared dependencies need different
131
- route builders.
132
-
133
- `dependencies` and `peerDependencies` are not used as fallback runtime contracts.
134
- If multiple elements request different minor or patch versions of a shared
135
- singleton such as React, the loader chooses the highest same-major version and
136
- emits console plus instrumentation warnings. Different major versions fail the
137
- load and are also reported through console and instrumentation.
138
-
139
- Preloaded mode means the host has already registered the expected custom element
140
- tag; it is not a separate package format. IIFE mode remains supported through the
141
- same package exports and controller compatibility shim used by legacy builders.
126
+ The media vocabulary it validates ships in `/types`:
127
+
128
+ | Type | Shape |
129
+ | --- | --- |
130
+ | `MediaAssetRef` | `{ version: 1, id, kind, sources, poster?, thumbnail?, durationSeconds?, tracks?, transcript?, label?, description?, lang? }` |
131
+ | `MediaKind` | `"image" \| "audio" \| "video" \| "other"` |
132
+ | `MediaSource` | `{ src, type?, width?, height?, bitrate? }` |
133
+ | `TextTrackRef` | `{ src, kind, lang, label, default? }`, where `kind` is `captions`, `subtitles`, `descriptions`, `chapters` or `metadata` |
134
+ | `TranscriptRef` | `{ src?, html?, plainText?, lang? }` |
135
+ | `MediaFragmentRange` | `{ startSeconds, endSeconds? }`: a slice of a longer recording, so one file serves several content nodes |
136
+ | `SignLanguageCardPayload` | `{ signLang?, media, fragment? }`, the payload of a `sign-language` catalog card |
137
+ | `SpokenAudioCardPayload` | `{ media, fragment? }`, the payload of a recorded `spoken` catalog card |
138
+ | `CatalogCardPayload` | Either payload; the card's `catalog` decides which |
139
+
140
+ The design record is [`docs/prds/shared-contracts/media-asset-contract.md`](../../docs/prds/shared-contracts/media-asset-contract.md).
141
+
142
+ ## Element Loading
143
+
144
+ `@pie-players/pie-players-shared/loaders` holds the `ElementLoader` primitive and
145
+ the IIFE and ESM adapters `<pie-item-player>` loads elements through.
146
+ [Loading strategies](../../docs/item-player/loading-strategies.md) documents
147
+ their behavior, including the ESM adapter's file layout and CDN providers
148
+ ([`strategy="esm"`](../../docs/item-player/loading-strategies.md#strategyesm))
149
+ and the one-version rule for page singletons such as React
150
+ ([Shared dependencies](../../docs/item-player/loading-strategies.md#shared-dependencies)).
151
+ The producer side is the
152
+ [PIE element contract](https://github.com/pie-framework/pie-elements-ng/blob/develop/docs/PIE_ELEMENT_CONTRACT.md)
153
+ in pie-elements-ng.
142
154
 
143
155
  ## Related Documentation
144
156
 
145
157
  - [PIE utilities README](src/pie/README.md)
146
158
  - [i18n README](src/i18n/README.md)
147
- - [PIE element tag/id contract](../../docs/architecture/types-and-utilities-contract.md)
159
+ - [Loading strategies](../../docs/item-player/loading-strategies.md)
160
+ - [Internationalization](../../docs/architecture/internationalization.md)
@@ -22,9 +22,9 @@ lands, so it never leaks into a consumer's own dependency set.
22
22
 
23
23
  | Field | Value |
24
24
  | --- | --- |
25
- | Upstream repo | `git@github.com:RenaissancePlace/nextComponentLibrary.git` |
25
+ | Upstream | NDS component library |
26
26
  | Source file | `web-components/src/components/icon-button/nds-icon-button.ts` |
27
- | Last sync commit | `1c728d3` (`feat(UX-2319): add new components…`) |
27
+ | Last sync commit | `1c728d3` |
28
28
  | Bundler | Vite 7 in lib mode, ES output, single-file (Lit inlined) |
29
29
 
30
30
  ## Why a vendored bundle, not an npm dep
@@ -79,9 +79,8 @@ Consuming bundlers treat this module per their own externals config:
79
79
 
80
80
  When a newer `nds-icon-button` is needed:
81
81
 
82
- 1. Pull the latest `nextComponentLibrary` next to this repo (sibling checkout:
83
- `../../nextComponentLibrary`).
84
- 2. From `nextComponentLibrary/web-components/`, `bun install`.
82
+ 1. Check out the latest NDS component library source.
83
+ 2. From its `web-components/` directory, `bun install`.
85
84
  3. Build a self-contained ESM bundle (no shared chunks) — the upstream
86
85
  `vite.bundle.config.js` splits Lit into a `property.js` chunk, which would
87
86
  break the single-file copy here. Use this one-shot config instead:
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Minimal, frontend-safe defaults for PIE build service URLs.
3
3
  *
4
- * In PIEOneer, these come from `$env/dynamic/public`. In `pie-players` we avoid
4
+ * A SvelteKit host reads these from `$env/dynamic/public`. `pie-players` avoids
5
5
  * SvelteKit env dependencies so this can be consumed by any bundler.
6
6
  */
7
7
  declare global {
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Minimal, frontend-safe defaults for PIE build service URLs.
3
3
  *
4
- * In PIEOneer, these come from `$env/dynamic/public`. In `pie-players` we avoid
4
+ * A SvelteKit host reads these from `$env/dynamic/public`. `pie-players` avoids
5
5
  * SvelteKit env dependencies so this can be consumed by any bundler.
6
6
  */
7
7
  import { DEFAULT_BUNDLE_HOST } from "../loaders/defaults.js";
@@ -28,6 +28,6 @@ import type { I18nConfig, I18nServiceApi } from "./types.js";
28
28
  */
29
29
  export declare function createPieI18n(config?: I18nConfig): I18nServiceApi;
30
30
  export { BUNDLED_LOCALES, loadBundledCatalog } from "./catalogs.js";
31
- export { findBestLanguageMatch, languageTagLookupSequence, languageTagsEqual, normalizeLanguageTag, } from "./language-tags.js";
31
+ export { findBestLanguageMatch, languageTagLookupSequence, languageTagsEqual, normalizeLanguageTag, toLanguageTag, } from "./language-tags.js";
32
32
  export { DEFAULT_LOCALE, detectBrowserLocale, dynamicMessageKey, getDefaultI18n, localeDirection, resolveInterfaceI18n, SimpleI18n, } from "./provider.js";
33
33
  export type { BundledLocaleCode, DynamicMessageKey, I18nConfig, I18nProvider, I18nServiceApi, InterpolationValues, LocaleCode, MessageCatalog, MessageKey, MessageKeyInput, MessageNode, PluralOptions, PluralTranslation, TextDirection, TranslationBundle, } from "./types.js";
@@ -35,5 +35,5 @@ export function createPieI18n(config = {}) {
35
35
  });
36
36
  }
37
37
  export { BUNDLED_LOCALES, loadBundledCatalog } from "./catalogs.js";
38
- export { findBestLanguageMatch, languageTagLookupSequence, languageTagsEqual, normalizeLanguageTag, } from "./language-tags.js";
38
+ export { findBestLanguageMatch, languageTagLookupSequence, languageTagsEqual, normalizeLanguageTag, toLanguageTag, } from "./language-tags.js";
39
39
  export { DEFAULT_LOCALE, detectBrowserLocale, dynamicMessageKey, getDefaultI18n, localeDirection, resolveInterfaceI18n, SimpleI18n, } from "./provider.js";
@@ -22,12 +22,20 @@
22
22
  * Converts POSIX underscores to hyphens, strips a POSIX charset or modifier
23
23
  * suffix (`es_ES.UTF-8`, `es_ES@euro`), and lowercases. Lowercasing rather than
24
24
  * applying BCP-47 display casing is intentional — this output is a comparison
25
- * key, not something to render.
25
+ * key, not something to render. `toLanguageTag` is the form to render.
26
26
  *
27
27
  * Returns an empty string for nullish or blank input, which callers read as
28
28
  * "this card declares no language".
29
29
  */
30
30
  export declare function normalizeLanguageTag(tag: string | null | undefined): string;
31
+ /**
32
+ * A tag in BCP-47 syntax with its authored casing kept: POSIX underscores become
33
+ * hyphens, so `es_ES` renders as `es-ES`. The form for a `lang` attribute or a
34
+ * platform locale API.
35
+ *
36
+ * Returns an empty string for nullish or blank input.
37
+ */
38
+ export declare function toLanguageTag(tag: string | null | undefined): string;
31
39
  /**
32
40
  * Whether two language tags denote the same locale, ignoring separator style and
33
41
  * case. Two tags that both declare no language are not a match.
@@ -22,7 +22,7 @@
22
22
  * Converts POSIX underscores to hyphens, strips a POSIX charset or modifier
23
23
  * suffix (`es_ES.UTF-8`, `es_ES@euro`), and lowercases. Lowercasing rather than
24
24
  * applying BCP-47 display casing is intentional — this output is a comparison
25
- * key, not something to render.
25
+ * key, not something to render. `toLanguageTag` is the form to render.
26
26
  *
27
27
  * Returns an empty string for nullish or blank input, which callers read as
28
28
  * "this card declares no language".
@@ -34,6 +34,16 @@ export function normalizeLanguageTag(tag) {
34
34
  const withoutPosixSuffix = separatorsUnified.split(/[.@]/)[0];
35
35
  return withoutPosixSuffix.toLowerCase();
36
36
  }
37
+ /**
38
+ * A tag in BCP-47 syntax with its authored casing kept: POSIX underscores become
39
+ * hyphens, so `es_ES` renders as `es-ES`. The form for a `lang` attribute or a
40
+ * platform locale API.
41
+ *
42
+ * Returns an empty string for nullish or blank input.
43
+ */
44
+ export function toLanguageTag(tag) {
45
+ return tag ? tag.trim().replace(/_/g, "-") : "";
46
+ }
37
47
  /**
38
48
  * Whether two language tags denote the same locale, ignoring separator style and
39
49
  * case. Two tags that both declare no language are not a match.
@@ -393,30 +393,7 @@ declare const enUS: {
393
393
  textToSpeech: {
394
394
  name: string;
395
395
  description: string;
396
- toolA11y: string;
397
- title: string;
398
- initializing: string;
399
396
  initFailed: string;
400
- selectText: string;
401
- speed: string;
402
- play: string;
403
- pause: string;
404
- resume: string;
405
- stop: string;
406
- speaking: string;
407
- paused: string;
408
- charactersSelected: {
409
- one: string;
410
- other: string;
411
- };
412
- rate: {
413
- slow: string;
414
- slower: string;
415
- normal: string;
416
- faster: string;
417
- fast: string;
418
- veryFast: string;
419
- };
420
397
  /** Inline reading controls and their live-region announcements. */
421
398
  inline: {
422
399
  controlsA11y: string;
@@ -424,14 +401,13 @@ declare const enUS: {
424
401
  rewindA11y: string;
425
402
  fastForwardA11y: string;
426
403
  stopA11y: string;
427
- initializing: string;
428
- initFailed: string;
429
404
  starting: string;
430
405
  started: string;
431
406
  resumed: string;
432
407
  pausedAnnouncement: string;
433
408
  stopped: string;
434
409
  switchedSection: string;
410
+ nothingToRead: string;
435
411
  startFailed: string;
436
412
  skippedForward: string;
437
413
  skipForwardFailed: string;
@@ -526,6 +502,7 @@ declare const enUS: {
526
502
  pnp: {
527
503
  title: string;
528
504
  noAssessmentBound: string;
505
+ noAssessmentBoundBody: string;
529
506
  determinationReadOnly: string;
530
507
  toolsEditor: string;
531
508
  enforcement: string;
@@ -538,6 +515,7 @@ declare const enUS: {
538
515
  resolvedTools: string;
539
516
  provenanceSummary: string;
540
517
  perToolDecisions: string;
518
+ policyDiagnostics: string;
541
519
  profileReadOnly: string;
542
520
  };
543
521
  /** TTS settings panel. */
@@ -601,12 +579,39 @@ declare const enUS: {
601
579
  previewEnterText: string;
602
580
  previewUnavailable: string;
603
581
  browserSynthesisUnavailable: string;
604
- browserSynthesisEndedEarly: string;
605
- browserSynthesisQueueFailed: string;
606
- browserPreviewFailed: string;
607
582
  ssmlWordTrackingDisabled: string;
608
583
  applyUnavailable: string;
609
584
  coordinatorUnavailable: string;
585
+ customProviderNotRegistered: string;
586
+ customProviderNoConfig: string;
587
+ httpError: string;
588
+ unknownError: string;
589
+ previewRequestFailed: string;
590
+ notAvailable: string;
591
+ voiceLocal: string;
592
+ voiceRemote: string;
593
+ voiceBrowserDefault: string;
594
+ browserAvailable: {
595
+ one: string;
596
+ other: string;
597
+ };
598
+ pollyAvailable: {
599
+ one: string;
600
+ other: string;
601
+ };
602
+ googleAvailable: {
603
+ one: string;
604
+ other: string;
605
+ };
606
+ headerRowReservation: string;
607
+ speedOptionsHelp: string;
608
+ usingSelectedVoice: string;
609
+ autoVoice: string;
610
+ autoVoiceWaiting: string;
611
+ previewHintBrowserSsml: string;
612
+ previewHintGoogleSsml: string;
613
+ previewHintCustom: string;
614
+ previewHintTracking: string;
610
615
  };
611
616
  };
612
617
  };
@@ -407,30 +407,7 @@ const enUS = {
407
407
  textToSpeech: {
408
408
  name: "Text to Speech",
409
409
  description: "Read content aloud",
410
- toolA11y: "Text-to-speech tool",
411
- title: "Text-to-Speech",
412
- initializing: "Initializing…",
413
- initFailed: "Failed to initialize text-to-speech.",
414
- selectText: "Select text on the page to read it aloud.",
415
- speed: "Speed:",
416
- play: "Play",
417
- pause: "Pause",
418
- resume: "Resume",
419
- stop: "Stop",
420
- speaking: "Speaking…",
421
- paused: "Paused",
422
- charactersSelected: {
423
- one: "{count} character selected",
424
- other: "{count} characters selected",
425
- },
426
- rate: {
427
- slow: "Slow",
428
- slower: "Slower",
429
- normal: "Normal",
430
- faster: "Faster",
431
- fast: "Fast",
432
- veryFast: "Very Fast",
433
- },
410
+ initFailed: "Unable to initialize text-to-speech. Try again.",
434
411
  /** Inline reading controls and their live-region announcements. */
435
412
  inline: {
436
413
  controlsA11y: "Reading controls",
@@ -438,14 +415,13 @@ const enUS = {
438
415
  rewindA11y: "Rewind",
439
416
  fastForwardA11y: "Fast-forward",
440
417
  stopA11y: "Stop reading",
441
- initializing: "Initializing text-to-speech",
442
- initFailed: "Unable to initialize text-to-speech. Try again.",
443
418
  starting: "Starting reading",
444
419
  started: "Reading started",
445
420
  resumed: "Reading resumed",
446
421
  pausedAnnouncement: "Reading paused",
447
422
  stopped: "Reading stopped",
448
423
  switchedSection: "Reading switched to another section",
424
+ nothingToRead: "Nothing to read aloud here",
449
425
  startFailed: "Unable to start reading",
450
426
  skippedForward: "Skipped forward",
451
427
  skipForwardFailed: "Unable to skip forward",
@@ -540,6 +516,7 @@ const enUS = {
540
516
  pnp: {
541
517
  title: "PNP Profile",
542
518
  noAssessmentBound: "No assessment bound",
519
+ noAssessmentBoundBody: "Profile, district and test-administration policy have nothing to read, so only an item's requiredTools can grant an accommodation. Pass the assessment to the toolkit's assessment property, or call updateAssessment(...) on the toolkit coordinator.",
543
520
  determinationReadOnly: "Determination (read-only)",
544
521
  toolsEditor: "Tools Editor",
545
522
  enforcement: "PNP enforcement",
@@ -552,6 +529,7 @@ const enUS = {
552
529
  resolvedTools: "Resolved Tools (toolkit)",
553
530
  provenanceSummary: "Tool Policy Provenance Summary",
554
531
  perToolDecisions: "Per-Tool Decisions",
532
+ policyDiagnostics: "Policy Diagnostics",
555
533
  profileReadOnly: "PNP Profile (read-only)",
556
534
  },
557
535
  /** TTS settings panel. */
@@ -617,12 +595,39 @@ const enUS = {
617
595
  previewEnterText: "Enter preview text before starting playback.",
618
596
  previewUnavailable: "Cannot preview while this service is unavailable.",
619
597
  browserSynthesisUnavailable: "Browser speech synthesis is unavailable.",
620
- browserSynthesisEndedEarly: "Browser speech synthesis ended before audio started. Restart the browser and try again.",
621
- browserSynthesisQueueFailed: "Browser speech synthesis failed to queue preview audio.",
622
- browserPreviewFailed: "Failed to play browser voice preview.",
623
598
  ssmlWordTrackingDisabled: "Google SSML preview preserves authored SSML, so word tracking is disabled.",
624
599
  applyUnavailable: "Cannot apply settings while this service is unavailable.",
625
600
  coordinatorUnavailable: "Toolkit coordinator is not available for text-to-speech updates.",
601
+ customProviderNotRegistered: "Custom provider '{id}' is not registered.",
602
+ customProviderNoConfig: "Custom provider '{id}' did not return an apply config.",
603
+ httpError: "HTTP {status}: {message}",
604
+ unknownError: "Unknown error",
605
+ previewRequestFailed: "Preview request failed ({status}).",
606
+ notAvailable: "n/a",
607
+ voiceLocal: "local",
608
+ voiceRemote: "remote",
609
+ voiceBrowserDefault: "browser default",
610
+ browserAvailable: {
611
+ one: "Browser TTS available ({count} voice detected).",
612
+ other: "Browser TTS available ({count} voices detected).",
613
+ },
614
+ pollyAvailable: {
615
+ one: "AWS Polly available ({count} matching voice, {engine} engine).",
616
+ other: "AWS Polly available ({count} matching voices, {engine} engine).",
617
+ },
618
+ googleAvailable: {
619
+ one: "Google Cloud TTS available ({count} matching voice).",
620
+ other: "Google Cloud TTS available ({count} matching voices).",
621
+ },
622
+ headerRowReservation: "Item header row reservation: {state}",
623
+ speedOptionsHelp: "Comma or semicolon-separated multipliers. Include 1 for Normal; leave empty to hide speed controls.",
624
+ usingSelectedVoice: "Using selected voice: {voice}",
625
+ autoVoice: "Best available voice (auto): {voice}",
626
+ autoVoiceWaiting: "Best available voice (auto): waiting for browser voices.",
627
+ previewHintBrowserSsml: "SSML is unsupported in Browser preview.",
628
+ previewHintGoogleSsml: "SSML preserved. Tracking disabled.",
629
+ previewHintCustom: "Tracking enabled when provider returns speech marks.",
630
+ previewHintTracking: "Tracking enabled while preview plays.",
626
631
  },
627
632
  },
628
633
  };
@@ -321,44 +321,20 @@ declare const nlNL: {
321
321
  textToSpeech: {
322
322
  name: string;
323
323
  description: string;
324
- toolA11y: string;
325
- title: string;
326
- initializing: string;
327
324
  initFailed: string;
328
- selectText: string;
329
- speed: string;
330
- play: string;
331
- pause: string;
332
- resume: string;
333
- stop: string;
334
- speaking: string;
335
- paused: string;
336
- charactersSelected: {
337
- one: string;
338
- other: string;
339
- };
340
- rate: {
341
- slow: string;
342
- slower: string;
343
- normal: string;
344
- faster: string;
345
- fast: string;
346
- veryFast: string;
347
- };
348
325
  inline: {
349
326
  controlsA11y: string;
350
327
  playbackSpeedA11y: string;
351
328
  rewindA11y: string;
352
329
  fastForwardA11y: string;
353
330
  stopA11y: string;
354
- initializing: string;
355
- initFailed: string;
356
331
  starting: string;
357
332
  started: string;
358
333
  resumed: string;
359
334
  pausedAnnouncement: string;
360
335
  stopped: string;
361
336
  switchedSection: string;
337
+ nothingToRead: string;
362
338
  startFailed: string;
363
339
  skippedForward: string;
364
340
  skipForwardFailed: string;
@@ -438,6 +414,7 @@ declare const nlNL: {
438
414
  pnp: {
439
415
  title: string;
440
416
  noAssessmentBound: string;
417
+ noAssessmentBoundBody: string;
441
418
  determinationReadOnly: string;
442
419
  toolsEditor: string;
443
420
  enforcement: string;
@@ -450,6 +427,7 @@ declare const nlNL: {
450
427
  resolvedTools: string;
451
428
  provenanceSummary: string;
452
429
  perToolDecisions: string;
430
+ policyDiagnostics: string;
453
431
  profileReadOnly: string;
454
432
  };
455
433
  tts: {
@@ -512,12 +490,39 @@ declare const nlNL: {
512
490
  previewEnterText: string;
513
491
  previewUnavailable: string;
514
492
  browserSynthesisUnavailable: string;
515
- browserSynthesisEndedEarly: string;
516
- browserSynthesisQueueFailed: string;
517
- browserPreviewFailed: string;
518
493
  ssmlWordTrackingDisabled: string;
519
494
  applyUnavailable: string;
520
495
  coordinatorUnavailable: string;
496
+ customProviderNotRegistered: string;
497
+ customProviderNoConfig: string;
498
+ httpError: string;
499
+ unknownError: string;
500
+ previewRequestFailed: string;
501
+ notAvailable: string;
502
+ voiceLocal: string;
503
+ voiceRemote: string;
504
+ voiceBrowserDefault: string;
505
+ browserAvailable: {
506
+ one: string;
507
+ other: string;
508
+ };
509
+ pollyAvailable: {
510
+ one: string;
511
+ other: string;
512
+ };
513
+ googleAvailable: {
514
+ one: string;
515
+ other: string;
516
+ };
517
+ headerRowReservation: string;
518
+ speedOptionsHelp: string;
519
+ usingSelectedVoice: string;
520
+ autoVoice: string;
521
+ autoVoiceWaiting: string;
522
+ previewHintBrowserSsml: string;
523
+ previewHintGoogleSsml: string;
524
+ previewHintCustom: string;
525
+ previewHintTracking: string;
521
526
  };
522
527
  };
523
528
  };