@pie-players/pie-players-shared 0.3.73 → 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.
Files changed (137) hide show
  1. package/README.md +30 -2
  2. package/dist/components/vendor/nds/README.md +7 -5
  3. package/dist/config/profile.d.ts +0 -2
  4. package/dist/config/profile.js +2 -8
  5. package/dist/i18n/index.d.ts +2 -3
  6. package/dist/i18n/index.js +2 -3
  7. package/dist/i18n/messages/en-US.d.ts +11 -24
  8. package/dist/i18n/messages/en-US.js +13 -26
  9. package/dist/i18n/messages/nl-NL.d.ts +7 -24
  10. package/dist/i18n/messages/nl-NL.js +9 -26
  11. package/dist/i18n/provider.d.ts +4 -5
  12. package/dist/i18n/provider.js +4 -5
  13. package/dist/i18n/types.d.ts +4 -5
  14. package/dist/index.d.ts +4 -2
  15. package/dist/index.js +3 -1
  16. package/dist/instrumentation/index.d.ts +5 -4
  17. package/dist/instrumentation/index.js +5 -4
  18. package/dist/instrumentation/new-relic-agent.d.ts +20 -0
  19. package/dist/instrumentation/new-relic-agent.js +24 -0
  20. package/dist/instrumentation/providers/BaseInstrumentationProvider.d.ts +5 -4
  21. package/dist/instrumentation/providers/NewRelicInstrumentationProvider.d.ts +7 -7
  22. package/dist/instrumentation/providers/NewRelicInstrumentationProvider.js +21 -32
  23. package/dist/instrumentation/types.d.ts +7 -3
  24. package/dist/loader-config.d.ts +16 -6
  25. package/dist/loaders/controller-loading.d.ts +14 -0
  26. package/dist/loaders/controller-loading.js +12 -0
  27. package/dist/loaders/defaults.d.ts +10 -0
  28. package/dist/loaders/defaults.js +10 -0
  29. package/dist/loaders/element-loader.d.ts +20 -8
  30. package/dist/loaders/element-loader.js +102 -36
  31. package/dist/loaders/element-package-policy.d.ts +2 -0
  32. package/dist/loaders/element-package-policy.js +2 -1
  33. package/dist/loaders/esm-adapter.d.ts +29 -0
  34. package/dist/loaders/esm-adapter.js +635 -102
  35. package/dist/loaders/iife-adapter.d.ts +0 -5
  36. package/dist/loaders/iife-adapter.js +3 -9
  37. package/dist/loaders/index.d.ts +12 -3
  38. package/dist/loaders/index.js +9 -3
  39. package/dist/loaders/mathjax-events.d.ts +22 -0
  40. package/dist/loaders/mathjax-events.js +65 -0
  41. package/dist/loaders/module-shim.d.ts +12 -0
  42. package/dist/loaders/module-shim.js +12 -0
  43. package/dist/loaders/preloaded-alignment.d.ts +24 -0
  44. package/dist/loaders/preloaded-alignment.js +57 -0
  45. package/dist/loaders/preloaded-authored-tags.d.ts +26 -0
  46. package/dist/loaders/preloaded-authored-tags.js +69 -0
  47. package/dist/loaders/preloaded-registration.d.ts +72 -0
  48. package/dist/loaders/preloaded-registration.js +141 -0
  49. package/dist/media/index.d.ts +69 -0
  50. package/dist/media/index.js +194 -0
  51. package/dist/pie/authoring.d.ts +1 -1
  52. package/dist/pie/authoring.js +25 -18
  53. package/dist/pie/element-announcements.d.ts +39 -0
  54. package/dist/pie/element-announcements.js +67 -0
  55. package/dist/pie/element-observer.d.ts +3 -1
  56. package/dist/pie/element-observer.js +1 -0
  57. package/dist/pie/elements-rendered.d.ts +25 -0
  58. package/dist/pie/elements-rendered.js +96 -0
  59. package/dist/pie/index.d.ts +8 -10
  60. package/dist/pie/index.js +9 -10
  61. package/dist/pie/initialization.js +13 -22
  62. package/dist/pie/initialize-element.d.ts +3 -0
  63. package/dist/pie/initialize-element.js +3 -4
  64. package/dist/pie/instrumentation-event-bridge.js +23 -1
  65. package/dist/pie/instrumentation-event-map.js +11 -25
  66. package/dist/pie/instrumentation-provider-resolution.d.ts +2 -1
  67. package/dist/pie/instrumentation-provider-resolution.js +0 -1
  68. package/dist/pie/item-controller.js +4 -0
  69. package/dist/pie/item-session-contract.d.ts +8 -0
  70. package/dist/pie/item-session-contract.js +30 -9
  71. package/dist/pie/logger.d.ts +6 -0
  72. package/dist/pie/logger.js +10 -0
  73. package/dist/pie/markup-math.d.ts +20 -0
  74. package/dist/pie/markup-math.js +118 -0
  75. package/dist/pie/math-assets.d.ts +48 -0
  76. package/dist/pie/math-assets.js +81 -0
  77. package/dist/pie/math-rendering.d.ts +10 -21
  78. package/dist/pie/math-rendering.js +50 -35
  79. package/dist/pie/registry.d.ts +13 -1
  80. package/dist/pie/registry.js +39 -1
  81. package/dist/pie/resource-monitor.d.ts +6 -33
  82. package/dist/pie/resource-monitor.js +14 -213
  83. package/dist/pie/scoring.d.ts +12 -8
  84. package/dist/pie/scoring.js +21 -24
  85. package/dist/pie/session-commit.d.ts +16 -0
  86. package/dist/pie/session-commit.js +34 -6
  87. package/dist/pie/session-snapshot.d.ts +80 -0
  88. package/dist/pie/session-snapshot.js +166 -0
  89. package/dist/pie/stages.d.ts +10 -47
  90. package/dist/pie/stages.js +10 -47
  91. package/dist/pie/tag-names.d.ts +1 -0
  92. package/dist/pie/tag-names.js +1 -0
  93. package/dist/pie/types.d.ts +4 -5
  94. package/dist/pie/types.js +1 -0
  95. package/dist/pie/updates.d.ts +2 -2
  96. package/dist/pie/updates.js +33 -15
  97. package/dist/pie/versioned-tag.d.ts +4 -0
  98. package/dist/pie/versioned-tag.js +4 -0
  99. package/dist/security/index.d.ts +2 -3
  100. package/dist/security/index.js +2 -3
  101. package/dist/security/sanitize-item-markup.d.ts +4 -2
  102. package/dist/security/sanitize-item-markup.js +48 -6
  103. package/dist/security/sanitize-svg-icon.d.ts +0 -2
  104. package/dist/security/sanitize-svg-icon.js +0 -5
  105. package/dist/security/wrap-overwide-images.js +19 -0
  106. package/dist/security/wrap-overwide.d.ts +13 -0
  107. package/dist/security/wrap-overwide.js +63 -3
  108. package/dist/timed-media/policy.js +5 -16
  109. package/dist/types/index.d.ts +67 -423
  110. package/dist/types/index.js +0 -68
  111. package/dist/ui/attribute-coercion.d.ts +12 -0
  112. package/dist/ui/attribute-coercion.js +33 -0
  113. package/dist/ui/content-styles.d.ts +18 -16
  114. package/dist/ui/content-styles.js +67 -36
  115. package/dist/ui/overlay-containment.d.ts +31 -0
  116. package/dist/ui/overlay-containment.js +63 -0
  117. package/dist/ui/overlay-placement.d.ts +110 -0
  118. package/dist/ui/overlay-placement.js +222 -0
  119. package/dist/ui/pointer-gesture.d.ts +32 -0
  120. package/dist/ui/pointer-gesture.js +56 -0
  121. package/dist/ui/pointer-rotate.d.ts +29 -0
  122. package/dist/ui/pointer-rotate.js +39 -0
  123. package/package.json +23 -18
  124. package/dist/pie/component-context.d.ts +0 -21
  125. package/dist/pie/component-context.js +0 -29
  126. package/dist/pie/player-initializer.d.ts +0 -54
  127. package/dist/pie/player-initializer.js +0 -122
  128. package/dist/pie/stage-tracker.d.ts +0 -50
  129. package/dist/pie/stage-tracker.js +0 -105
  130. package/dist/security/wrap-model-rich-content.d.ts +0 -1
  131. package/dist/security/wrap-model-rich-content.js +0 -40
  132. package/dist/server/npm-auth-env.d.ts +0 -13
  133. package/dist/server/npm-auth-env.js +0 -64
  134. package/dist/server/npm-registry.d.ts +0 -7
  135. package/dist/server/npm-registry.js +0 -59
  136. package/dist/ui/debug-panel-persistence.d.ts +0 -17
  137. package/dist/ui/debug-panel-persistence.js +0 -37
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Math in an item's own markup: what the item and passage markup carry outside
3
+ * every PIE element.
4
+ *
5
+ * Each element typesets its own subtree, so the player hands its renderer only
6
+ * the markup around them. A renderer finds math below the element it is given,
7
+ * so no root holds a PIE element: the markup splits into the elements that hold
8
+ * none, and math sharing a parent with one is wrapped in a span of its own.
9
+ */
10
+ /** TeX as `@pie-element/shared-math-rendering-mathjax` detects it. */
11
+ const TEX = /\\\(|\\\[|\$\$|\\\$|\\begin\{|\\(?:eq)?ref\{/;
12
+ /** The same, with `$…$` inline math turned on by the legacy opt-in. */
13
+ const TEX_WITH_SINGLE_DOLLAR = /\\\(|\\\[|\$|\\begin\{|\\(?:eq)?ref\{/;
14
+ /** Elements whose content MathJax leaves alone, as both PIE configurations list them. */
15
+ const SKIPPED_ELEMENTS = new Set([
16
+ "script",
17
+ "noscript",
18
+ "style",
19
+ "textarea",
20
+ "pre",
21
+ "code",
22
+ "annotation",
23
+ "annotation-xml",
24
+ "mjx-container",
25
+ "mjx-assistive-mml",
26
+ ]);
27
+ /** The class an author marks content with to keep MathJax out of it. */
28
+ const IGNORED_CLASS = /(?:^|\s)mathjax_ignore(?:\s|$)/;
29
+ const HTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
30
+ function texPattern() {
31
+ const legacy = globalThis["@pie-lib/math-rendering@2"];
32
+ return legacy?.opts?.useSingleDollar ? TEX_WITH_SINGLE_DOLLAR : TEX;
33
+ }
34
+ function isSkipped(element) {
35
+ return (SKIPPED_ELEMENTS.has(element.localName) ||
36
+ IGNORED_CLASS.test(element.getAttribute("class") ?? ""));
37
+ }
38
+ /** Math a renderer would only find on `element` itself, never below it. */
39
+ function holdsOwnMath(element) {
40
+ return (element.localName === "math" ||
41
+ (element.hasAttribute("data-latex") &&
42
+ !element.hasAttribute("data-math-handled")));
43
+ }
44
+ function holdsMath(element, tex) {
45
+ if (holdsOwnMath(element) ||
46
+ element.querySelector("[data-latex]:not([data-math-handled])")) {
47
+ return true;
48
+ }
49
+ for (const math of element.getElementsByTagName("math")) {
50
+ if (!math.closest("mjx-assistive-mml"))
51
+ return true;
52
+ }
53
+ return tex.test(element.textContent ?? "");
54
+ }
55
+ function wrapInSpan(node) {
56
+ const span = (node.ownerDocument ?? document).createElement("span");
57
+ node.replaceWith(span);
58
+ span.append(node);
59
+ return span;
60
+ }
61
+ /**
62
+ * The parts of `container` holding math and no PIE element, each one a root to
63
+ * typeset. `pieTags` are the tag names of the PIE elements its markup places.
64
+ */
65
+ export function collectMarkupMathRoots(container, pieTags) {
66
+ const tex = texPattern();
67
+ const holdsPie = new Set();
68
+ for (const tag of pieTags) {
69
+ for (const element of container.getElementsByTagName(tag)) {
70
+ for (let ancestor = element.parentElement; ancestor && !holdsPie.has(ancestor); ancestor = ancestor.parentElement) {
71
+ holdsPie.add(ancestor);
72
+ if (ancestor === container)
73
+ break;
74
+ }
75
+ }
76
+ }
77
+ if (!holdsPie.has(container)) {
78
+ return holdsMath(container, tex) ? [container] : [];
79
+ }
80
+ const roots = [];
81
+ const visit = (parent) => {
82
+ for (const child of [...parent.childNodes]) {
83
+ if (child.nodeType === Node.TEXT_NODE) {
84
+ if (tex.test(child.data))
85
+ roots.push(wrapInSpan(child));
86
+ continue;
87
+ }
88
+ if (child.nodeType !== Node.ELEMENT_NODE)
89
+ continue;
90
+ const element = child;
91
+ if (pieTags.has(element.localName) || isSkipped(element))
92
+ continue;
93
+ if (holdsPie.has(element)) {
94
+ visit(element);
95
+ }
96
+ else if (holdsMath(element, tex)) {
97
+ if (holdsOwnMath(element)) {
98
+ roots.push(wrapInSpan(element));
99
+ }
100
+ else if (element.namespaceURI === HTML_NAMESPACE) {
101
+ roots.push(element);
102
+ }
103
+ }
104
+ }
105
+ };
106
+ visit(container);
107
+ return roots;
108
+ }
109
+ /**
110
+ * Typesets the math in `containers` outside every PIE element with `render`,
111
+ * one root at a time.
112
+ */
113
+ export async function typesetMarkupMath(containers, pieTags, render) {
114
+ const roots = [...containers].flatMap((container) => collectMarkupMathRoots(container, pieTags));
115
+ for (const root of roots) {
116
+ await render(root);
117
+ }
118
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Where the MathJax adapter's copies load MathJax's fonts, speech worker and,
3
+ * on its npm build, MathJax itself from, and whether math is in the tab order.
4
+ * Every copy of `@pie-element/shared-math-rendering-mathjax` reads these from
5
+ * the legacy renderer's page options as it starts MathJax, on its first render,
6
+ * so they are set before any element renders. See
7
+ * https://github.com/pie-framework/pie-elements-ng/blob/develop/docs/MATH-RENDERING.md#assets
8
+ */
9
+ export interface MathAssetOptions {
10
+ /**
11
+ * An npm root: a URL under which `<package>@<version>/<path>` serves that
12
+ * file of the package, such as `https://cdn.jsdelivr.net/npm`. A relative URL
13
+ * resolves against the page.
14
+ */
15
+ assetRoot?: string | URL;
16
+ /**
17
+ * The directory of `speech-worker.js` and its `mathmaps/`, by default
18
+ * `mathjax@<version>/sre` under the asset root.
19
+ */
20
+ speechPath?: string | URL;
21
+ /**
22
+ * The URL of individual files by npm path, `<package>@<version>/<path>`: a
23
+ * listed file loads from its URL, the rest from the asset root. A bundle lists
24
+ * each file it ships as `new URL("./…", import.meta.url)`, which its host's
25
+ * bundler emits, and needs no root. Read by the adapter's browser build, for
26
+ * its fonts, speech worker and speech rules.
27
+ */
28
+ assetUrls?: Readonly<Record<string, string | URL>>;
29
+ /**
30
+ * The speech locales the MathJax menu lists, by id (`["en", "es"]`), or by id
31
+ * with the label it shows. Unset, it lists every locale SRE ships.
32
+ */
33
+ speechLocales?: readonly string[] | Readonly<Record<string, string>>;
34
+ /**
35
+ * Puts typeset math in the keyboard tab order, for the MathJax menu and its
36
+ * explorer. Off by default.
37
+ */
38
+ inTabOrder?: boolean;
39
+ }
40
+ /** Why `options` is not a `MathAssetOptions`, or `undefined` when it is. */
41
+ export declare function mathAssetOptionsError(options: unknown): string | undefined;
42
+ /**
43
+ * Writes `options` to the page options, keeping the ones it leaves unset and
44
+ * the files of `assetUrls` it does not list.
45
+ */
46
+ export declare function setMathAssetOptions(options: MathAssetOptions): void;
47
+ /** The asset root the page options set, if any. */
48
+ export declare function pageMathAssetRoot(): string | undefined;
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Where the MathJax adapter's copies load MathJax's fonts, speech worker and,
3
+ * on its npm build, MathJax itself from, and whether math is in the tab order.
4
+ * Every copy of `@pie-element/shared-math-rendering-mathjax` reads these from
5
+ * the legacy renderer's page options as it starts MathJax, on its first render,
6
+ * so they are set before any element renders. See
7
+ * https://github.com/pie-framework/pie-elements-ng/blob/develop/docs/MATH-RENDERING.md#assets
8
+ */
9
+ /** The legacy renderer's page options, which the adapter reads as well. */
10
+ const PAGE_OPTIONS_KEY = "@pie-lib/math-rendering@2";
11
+ const isUrl = (value) => (typeof value === "string" && value !== "") || value instanceof URL;
12
+ /** Why `options` is not a `MathAssetOptions`, or `undefined` when it is. */
13
+ export function mathAssetOptionsError(options) {
14
+ if (!options || typeof options !== "object" || Array.isArray(options)) {
15
+ return "must be an object";
16
+ }
17
+ const { assetRoot, speechPath, assetUrls, speechLocales, inTabOrder } = options;
18
+ if (assetRoot !== undefined && !isUrl(assetRoot)) {
19
+ return `assetRoot must be a URL, got ${JSON.stringify(assetRoot)}`;
20
+ }
21
+ if (speechPath !== undefined && !isUrl(speechPath)) {
22
+ return `speechPath must be a URL, got ${JSON.stringify(speechPath)}`;
23
+ }
24
+ if (assetUrls !== undefined &&
25
+ (!assetUrls ||
26
+ typeof assetUrls !== "object" ||
27
+ Array.isArray(assetUrls) ||
28
+ !Object.values(assetUrls).every(isUrl))) {
29
+ return "assetUrls must map npm paths to URLs";
30
+ }
31
+ if (speechLocales !== undefined) {
32
+ const listed = Array.isArray(speechLocales)
33
+ ? speechLocales
34
+ : speechLocales && typeof speechLocales === "object"
35
+ ? Object.values(speechLocales)
36
+ : null;
37
+ if (!listed || listed.some((entry) => typeof entry !== "string" || !entry)) {
38
+ return "speechLocales must be locale ids, or locale ids mapped to their labels";
39
+ }
40
+ }
41
+ if (inTabOrder !== undefined && typeof inTabOrder !== "boolean") {
42
+ return `inTabOrder must be a boolean, got ${JSON.stringify(inTabOrder)}`;
43
+ }
44
+ return undefined;
45
+ }
46
+ /**
47
+ * Writes `options` to the page options, keeping the ones it leaves unset and
48
+ * the files of `assetUrls` it does not list.
49
+ */
50
+ export function setMathAssetOptions(options) {
51
+ if (typeof window === "undefined")
52
+ return;
53
+ const host = window;
54
+ const page = (host[PAGE_OPTIONS_KEY] ??= {});
55
+ const opts = (page.opts ??= {});
56
+ if (options.assetRoot !== undefined)
57
+ opts.assetRoot = String(options.assetRoot);
58
+ if (options.speechPath !== undefined)
59
+ opts.speechPath = String(options.speechPath);
60
+ if (options.assetUrls !== undefined) {
61
+ const listed = opts.assetUrls && typeof opts.assetUrls === "object" ? opts.assetUrls : {};
62
+ opts.assetUrls = {
63
+ ...listed,
64
+ ...Object.fromEntries(Object.entries(options.assetUrls).map(([path, url]) => [path, String(url)])),
65
+ };
66
+ }
67
+ if (options.speechLocales !== undefined) {
68
+ opts.speechLocales = Array.isArray(options.speechLocales)
69
+ ? [...options.speechLocales]
70
+ : { ...options.speechLocales };
71
+ }
72
+ if (options.inTabOrder !== undefined)
73
+ opts.inTabOrder = options.inTabOrder;
74
+ }
75
+ /** The asset root the page options set, if any. */
76
+ export function pageMathAssetRoot() {
77
+ if (typeof window === "undefined")
78
+ return undefined;
79
+ const root = window[PAGE_OPTIONS_KEY]?.opts?.assetRoot;
80
+ return typeof root === "string" && root ? root : undefined;
81
+ }
@@ -4,7 +4,7 @@
4
4
  * PIE elements expect @pie-lib/math-rendering to be available on window.
5
5
  * This module ensures required globals are populated from the upstream
6
6
  * @pie-lib/math-rendering-module package, and also supports overriding with
7
- * a custom renderer object when needed.
7
+ * a custom renderer object through setMathRenderer().
8
8
  */
9
9
  export type MathRenderer = (element: HTMLElement) => void | Promise<void>;
10
10
  export interface MathRenderingAPI {
@@ -14,32 +14,30 @@ export interface MathRenderingAPI {
14
14
  mmlToLatex?: (mathml: string) => string;
15
15
  }
16
16
  /**
17
- * Initialize math rendering with optional custom renderer
18
- *
19
- * If no custom renderer is provided, defaults to MathJax.
17
+ * The page's renderer: the one `initializeMathRendering` installed, or a
18
+ * host's. IIFE elements render with it, and so do ESM elements when the page
19
+ * has one.
20
+ */
21
+ export declare const getMathRenderer: () => MathRenderingAPI | null;
22
+ /**
23
+ * Initialize math rendering, defaulting to MathJax.
20
24
  * For custom renderers, use setMathRenderer() before calling this function.
21
25
  *
22
26
  * Sets TWO window globals that PIE elements expect:
23
27
  * - window["@pie-lib/math-rendering"] (standard key)
24
28
  * - window["_dll_pie_lib__math_rendering"] (SystemJS/DLL key for IIFE bundles)
25
29
  *
26
- * @param customRenderer - Optional custom renderer to use instead of default MathJax
27
- *
28
30
  * @example
29
31
  * ```typescript
30
32
  * // Default MathJax
31
33
  * await initializeMathRendering();
32
34
  *
33
- * // Custom renderer instance implementing MathRenderingAPI
34
- * const customRenderer = await createCustomRenderer();
35
- * await initializeMathRendering(customRenderer);
36
- *
37
- * // Or use setMathRenderer first
35
+ * // Custom renderer: install it first
38
36
  * setMathRenderer(katexRenderer);
39
37
  * await initializeMathRendering();
40
38
  * ```
41
39
  */
42
- export declare function initializeMathRendering(customRenderer?: MathRenderingAPI): Promise<void>;
40
+ export declare function initializeMathRendering(): Promise<void>;
43
41
  /**
44
42
  * Set custom math renderer programmatically
45
43
  *
@@ -60,12 +58,3 @@ export declare function initializeMathRendering(customRenderer?: MathRenderingAP
60
58
  * ```
61
59
  */
62
60
  export declare function setMathRenderer(renderer: MathRenderingAPI): void;
63
- /**
64
- * Render math in the given element
65
- *
66
- * Convenience wrapper that calls the active renderer's renderMath() function.
67
- * Typically called after PIE elements are rendered.
68
- *
69
- * @param element - The element to render math within
70
- */
71
- export declare function renderMath(element: HTMLElement): void;
@@ -4,15 +4,23 @@
4
4
  * PIE elements expect @pie-lib/math-rendering to be available on window.
5
5
  * This module ensures required globals are populated from the upstream
6
6
  * @pie-lib/math-rendering-module package, and also supports overriding with
7
- * a custom renderer object when needed.
7
+ * a custom renderer object through setMathRenderer().
8
8
  */
9
9
  /// <reference path="../shims.d.ts" />
10
10
  import { createPieLogger, isGlobalDebugEnabled } from "./logger.js";
11
11
  const GLOBAL_KEY = "@pie-lib/math-rendering";
12
12
  const GLOBAL_DLL_KEY = "_dll_pie_lib__math_rendering";
13
+ // Every copy of @pie-lib/math-rendering on a page typesets through the MathJax
14
+ // instance kept here, and the first copy to typeset creates it.
15
+ const SHARED_INSTANCE_KEY = "@pie-lib/math-rendering@2";
13
16
  let initPromise = null;
14
17
  const logger = createPieLogger("math-rendering", () => isGlobalDebugEnabled());
15
- const getWindowRenderer = () => {
18
+ /**
19
+ * The page's renderer: the one `initializeMathRendering` installed, or a
20
+ * host's. IIFE elements render with it, and so do ESM elements when the page
21
+ * has one.
22
+ */
23
+ export const getMathRenderer = () => {
16
24
  if (typeof window === "undefined") {
17
25
  return null;
18
26
  }
@@ -26,43 +34,55 @@ const setWindowRenderer = (renderer) => {
26
34
  window[GLOBAL_DLL_KEY] = renderer;
27
35
  };
28
36
  /**
29
- * Initialize math rendering with optional custom renderer
37
+ * Creates the shared MathJax instance from `renderer`, unless the page already
38
+ * holds one.
30
39
  *
31
- * If no custom renderer is provided, defaults to MathJax.
40
+ * Legacy element bundles carry their own copy of math-rendering. A copy that
41
+ * predates the assistive-MathML guard, such as the one in multiple-choice
42
+ * 9.9.1, re-typesets the hidden `<math>` inside `mjx-assistive-mml` on every
43
+ * pass, so if it creates the instance, each re-render nests the expression
44
+ * again for every element on the page. Typesetting a detached element makes the
45
+ * guarded module create it first. Failure leaves the instance to the first
46
+ * element, as before, so it is logged and never fails initialization.
47
+ */
48
+ const createSharedInstance = (renderer) => {
49
+ if (window[SHARED_INSTANCE_KEY]?.instance)
50
+ return;
51
+ if (typeof document === "undefined" || !document.body)
52
+ return;
53
+ const warn = (error) => logger.warn("Could not create the shared MathJax instance:", error);
54
+ try {
55
+ Promise.resolve(renderer.renderMath(document.createElement("div"))).catch(warn);
56
+ }
57
+ catch (error) {
58
+ warn(error);
59
+ }
60
+ };
61
+ /**
62
+ * Initialize math rendering, defaulting to MathJax.
32
63
  * For custom renderers, use setMathRenderer() before calling this function.
33
64
  *
34
65
  * Sets TWO window globals that PIE elements expect:
35
66
  * - window["@pie-lib/math-rendering"] (standard key)
36
67
  * - window["_dll_pie_lib__math_rendering"] (SystemJS/DLL key for IIFE bundles)
37
68
  *
38
- * @param customRenderer - Optional custom renderer to use instead of default MathJax
39
- *
40
69
  * @example
41
70
  * ```typescript
42
71
  * // Default MathJax
43
72
  * await initializeMathRendering();
44
73
  *
45
- * // Custom renderer instance implementing MathRenderingAPI
46
- * const customRenderer = await createCustomRenderer();
47
- * await initializeMathRendering(customRenderer);
48
- *
49
- * // Or use setMathRenderer first
74
+ * // Custom renderer: install it first
50
75
  * setMathRenderer(katexRenderer);
51
76
  * await initializeMathRendering();
52
77
  * ```
53
78
  */
54
- export async function initializeMathRendering(customRenderer) {
79
+ export async function initializeMathRendering() {
55
80
  // Only run in browser
56
81
  if (typeof window === "undefined") {
57
82
  return;
58
83
  }
59
- // Explicit override always wins.
60
- if (customRenderer) {
61
- setWindowRenderer(customRenderer);
62
- return;
63
- }
64
84
  // Already initialized - skip.
65
- if (getWindowRenderer()) {
85
+ if (getMathRenderer()) {
66
86
  return;
67
87
  }
68
88
  if (initPromise) {
@@ -71,11 +91,20 @@ export async function initializeMathRendering(customRenderer) {
71
91
  }
72
92
  initPromise = (async () => {
73
93
  try {
74
- const { _dll_pie_lib__math_rendering } = await import("@pie-lib/math-rendering-module/module");
94
+ // The package has no exports map, so the file is named in full for
95
+ // resolvers that do not complete a directory, such as webpack's
96
+ // fully-specified ESM resolution.
97
+ const mathRenderingModule = await import("@pie-lib/math-rendering-module/module/index.js");
98
+ // The player builds defer the module's evaluation to this call (see
99
+ // math-rendering-module-deferral.mjs); unbundled, it evaluated on import.
100
+ const renderer = mathRenderingModule.evaluateMathRenderingModule
101
+ ? mathRenderingModule.evaluateMathRenderingModule()
102
+ : mathRenderingModule._dll_pie_lib__math_rendering;
75
103
  // A host may install its renderer while the default module is in flight.
76
104
  // The explicit renderer remains authoritative when that happens.
77
- if (!getWindowRenderer()) {
78
- setWindowRenderer(_dll_pie_lib__math_rendering);
105
+ if (!getMathRenderer()) {
106
+ setWindowRenderer(renderer);
107
+ createSharedInstance(renderer);
79
108
  logger.debug("Math rendering module initialized (both globals set)");
80
109
  }
81
110
  }
@@ -113,17 +142,3 @@ export async function initializeMathRendering(customRenderer) {
113
142
  export function setMathRenderer(renderer) {
114
143
  setWindowRenderer(renderer);
115
144
  }
116
- /**
117
- * Render math in the given element
118
- *
119
- * Convenience wrapper that calls the active renderer's renderMath() function.
120
- * Typically called after PIE elements are rendered.
121
- *
122
- * @param element - The element to render math within
123
- */
124
- export function renderMath(element) {
125
- const renderer = getWindowRenderer();
126
- if (renderer && typeof renderer.renderMath === "function") {
127
- renderer.renderMath(element);
128
- }
129
- }
@@ -3,8 +3,20 @@
3
3
  *
4
4
  * Manages the global PIE registry that tracks loaded elements.
5
5
  */
6
- import type { PieRegistry } from "./types.js";
6
+ import type { Entry, PieRegistry } from "./types.js";
7
7
  /**
8
8
  * Get or create the global PIE registry
9
9
  */
10
10
  export declare const pieRegistry: () => PieRegistry;
11
+ /**
12
+ * Record a tag in `window.PIE_REGISTRY`. Every registration path writes through
13
+ * here: the IIFE and ESM loaders, bundle initialization, and
14
+ * `registerPreloadedElements`.
15
+ *
16
+ * The first loaded entry for a tag `customElements` holds describes that
17
+ * definition, which no later load replaces, so it keeps its package and
18
+ * element. A later write fills only what it left empty: a controller, with the
19
+ * bundle type that supplied it, and a config. Any other entry is replaced.
20
+ * Returns the entry the registry holds afterwards.
21
+ */
22
+ export declare function writeRegistryEntry(entry: Entry): Entry;
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Manages the global PIE registry that tracks loaded elements.
5
5
  */
6
- import { isPieRegistryAvailable } from "./types.js";
6
+ import { isPieRegistryAvailable, Status } from "./types.js";
7
7
  /**
8
8
  * Get or create the global PIE registry
9
9
  */
@@ -18,3 +18,41 @@ export const pieRegistry = () => {
18
18
  }
19
19
  return registry;
20
20
  };
21
+ /**
22
+ * Record a tag in `window.PIE_REGISTRY`. Every registration path writes through
23
+ * here: the IIFE and ESM loaders, bundle initialization, and
24
+ * `registerPreloadedElements`.
25
+ *
26
+ * The first loaded entry for a tag `customElements` holds describes that
27
+ * definition, which no later load replaces, so it keeps its package and
28
+ * element. A later write fills only what it left empty: a controller, with the
29
+ * bundle type that supplied it, and a config. Any other entry is replaced.
30
+ * Returns the entry the registry holds afterwards.
31
+ */
32
+ export function writeRegistryEntry(entry) {
33
+ const registry = pieRegistry();
34
+ const existing = registry[entry.tagName];
35
+ if (!existing ||
36
+ existing.status !== Status.loaded ||
37
+ !isDefinedTag(entry.tagName)) {
38
+ registry[entry.tagName] = entry;
39
+ return entry;
40
+ }
41
+ const fillsController = !existing.controller && !!entry.controller;
42
+ const fillsConfig = existing.config == null && entry.config != null;
43
+ if (!fillsController && !fillsConfig)
44
+ return existing;
45
+ const filled = { ...existing };
46
+ if (fillsController) {
47
+ filled.controller = entry.controller;
48
+ filled.bundleType = entry.bundleType;
49
+ }
50
+ if (fillsConfig)
51
+ filled.config = entry.config;
52
+ registry[entry.tagName] = filled;
53
+ return filled;
54
+ }
55
+ function isDefinedTag(tagName) {
56
+ return (typeof customElements !== "undefined" &&
57
+ customElements.get(tagName) !== undefined);
58
+ }
@@ -7,11 +7,11 @@
7
7
  * Features:
8
8
  * - Tracks resource load timing with PerformanceObserver
9
9
  * - Detects and retries failed resource loads
10
- * - Sends instrumentation to New Relic
10
+ * - With `trackPageActions`, reports loads, retries and failures to the
11
+ * instrumentation provider it is given
11
12
  * - Works with all resource types (audio, video, img, link)
12
13
  */
13
14
  import type { InstrumentationProvider } from "../instrumentation/types.js";
14
- import type { ComponentContext } from "./component-context.js";
15
15
  export type ResourceMonitorConfig = {
16
16
  /**
17
17
  * Enable tracking page actions/events
@@ -22,29 +22,15 @@ export type ResourceMonitorConfig = {
22
22
  /**
23
23
  * Instrumentation provider for tracking events and errors
24
24
  *
25
- * Optional. If not provided, defaults to NewRelicInstrumentationProvider.
26
- * The provider handles instrumentation gracefully - if New Relic is not available,
27
- * it will simply not track events (no errors thrown).
28
- *
29
- * To use a different provider, pass it here:
30
- *
31
- * @example
32
- * ```typescript
33
- * const provider = new ConsoleInstrumentationProvider();
34
- * await provider.initialize({ debug: true });
35
- *
36
- * const monitor = new ResourceMonitor({
37
- * trackPageActions: true,
38
- * instrumentationProvider: provider
39
- * });
40
- * ```
25
+ * The monitor constructs no provider of its own: without one it only
26
+ * retries. Players pass what `resolveInstrumentationProvider` resolves from
27
+ * their `loaderConfig`.
41
28
  */
42
29
  instrumentationProvider?: InstrumentationProvider;
43
30
  /**
44
31
  * Whether ResourceMonitor should initialize/destroy the instrumentation provider.
45
32
  *
46
- * Defaults to `true` when ResourceMonitor creates the provider internally, and
47
- * `false` when a provider is injected by the host.
33
+ * Defaults to `false`: the provider belongs to whoever passed it in.
48
34
  */
49
35
  manageProviderLifecycle?: boolean;
50
36
  /**
@@ -97,8 +83,6 @@ export declare class ResourceMonitor {
97
83
  private isBrowser;
98
84
  private containerResources;
99
85
  private provider;
100
- private readonly ownsProvider;
101
- private readonly manageProviderLifecycle;
102
86
  private started;
103
87
  private lifecycleVersion;
104
88
  private pendingRetryTimers;
@@ -229,14 +213,3 @@ export declare class ResourceMonitor {
229
213
  }>;
230
214
  };
231
215
  }
232
- /**
233
- * Create and start a resource monitor for a container
234
- */
235
- export declare function createResourceMonitor(container: HTMLElement, config?: ResourceMonitorConfig): ResourceMonitor;
236
- /**
237
- * Initialize global resource request tracking (404s for fonts/images/etc.)
238
- * Call this once when the app loads (client-side only).
239
- */
240
- export declare function initializeResourceRequestTracking(): void;
241
- export declare function getTrackedResourceRequests(): Map<string, ComponentContext[]>;
242
- export declare function clearTrackedResourceRequests(): void;