@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.
- package/README.md +30 -2
- package/dist/components/vendor/nds/README.md +7 -5
- package/dist/config/profile.d.ts +0 -2
- package/dist/config/profile.js +2 -8
- package/dist/i18n/index.d.ts +2 -3
- package/dist/i18n/index.js +2 -3
- package/dist/i18n/messages/en-US.d.ts +11 -24
- package/dist/i18n/messages/en-US.js +13 -26
- package/dist/i18n/messages/nl-NL.d.ts +7 -24
- package/dist/i18n/messages/nl-NL.js +9 -26
- package/dist/i18n/provider.d.ts +4 -5
- package/dist/i18n/provider.js +4 -5
- package/dist/i18n/types.d.ts +4 -5
- package/dist/index.d.ts +4 -2
- package/dist/index.js +3 -1
- package/dist/instrumentation/index.d.ts +5 -4
- package/dist/instrumentation/index.js +5 -4
- package/dist/instrumentation/new-relic-agent.d.ts +20 -0
- package/dist/instrumentation/new-relic-agent.js +24 -0
- package/dist/instrumentation/providers/BaseInstrumentationProvider.d.ts +5 -4
- package/dist/instrumentation/providers/NewRelicInstrumentationProvider.d.ts +7 -7
- package/dist/instrumentation/providers/NewRelicInstrumentationProvider.js +21 -32
- package/dist/instrumentation/types.d.ts +7 -3
- package/dist/loader-config.d.ts +16 -6
- package/dist/loaders/controller-loading.d.ts +14 -0
- package/dist/loaders/controller-loading.js +12 -0
- package/dist/loaders/defaults.d.ts +10 -0
- package/dist/loaders/defaults.js +10 -0
- package/dist/loaders/element-loader.d.ts +20 -8
- package/dist/loaders/element-loader.js +102 -36
- package/dist/loaders/element-package-policy.d.ts +2 -0
- package/dist/loaders/element-package-policy.js +2 -1
- package/dist/loaders/esm-adapter.d.ts +29 -0
- package/dist/loaders/esm-adapter.js +635 -102
- package/dist/loaders/iife-adapter.d.ts +0 -5
- package/dist/loaders/iife-adapter.js +3 -9
- package/dist/loaders/index.d.ts +12 -3
- package/dist/loaders/index.js +9 -3
- package/dist/loaders/mathjax-events.d.ts +22 -0
- package/dist/loaders/mathjax-events.js +65 -0
- package/dist/loaders/module-shim.d.ts +12 -0
- package/dist/loaders/module-shim.js +12 -0
- package/dist/loaders/preloaded-alignment.d.ts +24 -0
- package/dist/loaders/preloaded-alignment.js +57 -0
- package/dist/loaders/preloaded-authored-tags.d.ts +26 -0
- package/dist/loaders/preloaded-authored-tags.js +69 -0
- package/dist/loaders/preloaded-registration.d.ts +72 -0
- package/dist/loaders/preloaded-registration.js +141 -0
- package/dist/media/index.d.ts +69 -0
- package/dist/media/index.js +194 -0
- package/dist/pie/authoring.d.ts +1 -1
- package/dist/pie/authoring.js +25 -18
- package/dist/pie/element-announcements.d.ts +39 -0
- package/dist/pie/element-announcements.js +67 -0
- package/dist/pie/element-observer.d.ts +3 -1
- package/dist/pie/element-observer.js +1 -0
- package/dist/pie/elements-rendered.d.ts +25 -0
- package/dist/pie/elements-rendered.js +96 -0
- package/dist/pie/index.d.ts +8 -10
- package/dist/pie/index.js +9 -10
- package/dist/pie/initialization.js +13 -22
- package/dist/pie/initialize-element.d.ts +3 -0
- package/dist/pie/initialize-element.js +3 -4
- package/dist/pie/instrumentation-event-bridge.js +23 -1
- package/dist/pie/instrumentation-event-map.js +11 -25
- package/dist/pie/instrumentation-provider-resolution.d.ts +2 -1
- package/dist/pie/instrumentation-provider-resolution.js +0 -1
- package/dist/pie/item-controller.js +4 -0
- package/dist/pie/item-session-contract.d.ts +8 -0
- package/dist/pie/item-session-contract.js +30 -9
- package/dist/pie/logger.d.ts +6 -0
- package/dist/pie/logger.js +10 -0
- package/dist/pie/markup-math.d.ts +20 -0
- package/dist/pie/markup-math.js +118 -0
- package/dist/pie/math-assets.d.ts +48 -0
- package/dist/pie/math-assets.js +81 -0
- package/dist/pie/math-rendering.d.ts +10 -21
- package/dist/pie/math-rendering.js +50 -35
- package/dist/pie/registry.d.ts +13 -1
- package/dist/pie/registry.js +39 -1
- package/dist/pie/resource-monitor.d.ts +6 -33
- package/dist/pie/resource-monitor.js +14 -213
- package/dist/pie/scoring.d.ts +12 -8
- package/dist/pie/scoring.js +21 -24
- package/dist/pie/session-commit.d.ts +16 -0
- package/dist/pie/session-commit.js +34 -6
- package/dist/pie/session-snapshot.d.ts +80 -0
- package/dist/pie/session-snapshot.js +166 -0
- package/dist/pie/stages.d.ts +10 -47
- package/dist/pie/stages.js +10 -47
- package/dist/pie/tag-names.d.ts +1 -0
- package/dist/pie/tag-names.js +1 -0
- package/dist/pie/types.d.ts +4 -5
- package/dist/pie/types.js +1 -0
- package/dist/pie/updates.d.ts +2 -2
- package/dist/pie/updates.js +33 -15
- package/dist/pie/versioned-tag.d.ts +4 -0
- package/dist/pie/versioned-tag.js +4 -0
- package/dist/security/index.d.ts +2 -3
- package/dist/security/index.js +2 -3
- package/dist/security/sanitize-item-markup.d.ts +4 -2
- package/dist/security/sanitize-item-markup.js +48 -6
- package/dist/security/sanitize-svg-icon.d.ts +0 -2
- package/dist/security/sanitize-svg-icon.js +0 -5
- package/dist/security/wrap-overwide-images.js +19 -0
- package/dist/security/wrap-overwide.d.ts +13 -0
- package/dist/security/wrap-overwide.js +63 -3
- package/dist/timed-media/policy.js +5 -16
- package/dist/types/index.d.ts +67 -423
- package/dist/types/index.js +0 -68
- package/dist/ui/attribute-coercion.d.ts +12 -0
- package/dist/ui/attribute-coercion.js +33 -0
- package/dist/ui/content-styles.d.ts +18 -16
- package/dist/ui/content-styles.js +67 -36
- package/dist/ui/overlay-containment.d.ts +31 -0
- package/dist/ui/overlay-containment.js +63 -0
- package/dist/ui/overlay-placement.d.ts +110 -0
- package/dist/ui/overlay-placement.js +222 -0
- package/dist/ui/pointer-gesture.d.ts +32 -0
- package/dist/ui/pointer-gesture.js +56 -0
- package/dist/ui/pointer-rotate.d.ts +29 -0
- package/dist/ui/pointer-rotate.js +39 -0
- package/package.json +23 -18
- package/dist/pie/component-context.d.ts +0 -21
- package/dist/pie/component-context.js +0 -29
- package/dist/pie/player-initializer.d.ts +0 -54
- package/dist/pie/player-initializer.js +0 -122
- package/dist/pie/stage-tracker.d.ts +0 -50
- package/dist/pie/stage-tracker.js +0 -105
- package/dist/security/wrap-model-rich-content.d.ts +0 -1
- package/dist/security/wrap-model-rich-content.js +0 -40
- package/dist/server/npm-auth-env.d.ts +0 -13
- package/dist/server/npm-auth-env.js +0 -64
- package/dist/server/npm-registry.d.ts +0 -7
- package/dist/server/npm-registry.js +0 -59
- package/dist/ui/debug-panel-persistence.d.ts +0 -17
- package/dist/ui/debug-panel-persistence.js +0 -37
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Device-local snapshot of a committed session.
|
|
3
|
+
*
|
|
4
|
+
* A crash or an OS kill fires no lifecycle event, so the only state that
|
|
5
|
+
* survives it is state already written. The snapshot writes each committed
|
|
6
|
+
* session to device storage and offers it back on the next load.
|
|
7
|
+
*
|
|
8
|
+
* It is offered, never applied. School devices are shared, and a player cannot
|
|
9
|
+
* tell a legitimate recovery from a previous student's draft, so the host
|
|
10
|
+
* decides.
|
|
11
|
+
*
|
|
12
|
+
* `sessionStorage` is the default, matching the annotation toolbar's existing
|
|
13
|
+
* use of it for learner annotations: it is tab-scoped and cleared when the tab
|
|
14
|
+
* closes, so a response does not outlive the sitting, and browser session
|
|
15
|
+
* restore brings it back after a crash. A host that wants recovery across a
|
|
16
|
+
* full browser restart injects a `localStorage`-backed store and owns the
|
|
17
|
+
* retention consequences.
|
|
18
|
+
*/
|
|
19
|
+
const KEY_PREFIX = "pie-session-snapshot";
|
|
20
|
+
/**
|
|
21
|
+
* Whether an identity names one sitting.
|
|
22
|
+
*
|
|
23
|
+
* `sessionId` is the only field that distinguishes one learner's attempt from
|
|
24
|
+
* another's. Keyed on the item alone, a shared device offers the previous
|
|
25
|
+
* student's draft to the next one - and the offer is itself a disclosure, before
|
|
26
|
+
* the host ever decides whether to apply it. So without a `sessionId` there is
|
|
27
|
+
* no snapshot, and a host driving the player by props alone opts in by passing
|
|
28
|
+
* an explicit `key`.
|
|
29
|
+
*/
|
|
30
|
+
export function isSnapshotIdentitySpecific(identity) {
|
|
31
|
+
return Boolean(identity.sessionId);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Key built from the delivery identity, so a snapshot is only offered back to
|
|
35
|
+
* the sitting that wrote it.
|
|
36
|
+
*/
|
|
37
|
+
export function sessionSnapshotKey(identity) {
|
|
38
|
+
const parts = [
|
|
39
|
+
identity.assignmentId || "",
|
|
40
|
+
identity.sessionId || "",
|
|
41
|
+
identity.itemId || "",
|
|
42
|
+
];
|
|
43
|
+
return `${KEY_PREFIX}:${parts.join("|")}`;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* `sessionStorage`-backed store. Every access is guarded: private mode and
|
|
47
|
+
* blocked site data make the accessor throw, and a player must keep working
|
|
48
|
+
* without a snapshot rather than fail.
|
|
49
|
+
*/
|
|
50
|
+
export function sessionStorageSnapshotStore() {
|
|
51
|
+
return {
|
|
52
|
+
read(key) {
|
|
53
|
+
try {
|
|
54
|
+
if (typeof sessionStorage === "undefined")
|
|
55
|
+
return null;
|
|
56
|
+
return sessionStorage.getItem(key);
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
write(key, value) {
|
|
63
|
+
try {
|
|
64
|
+
if (typeof sessionStorage === "undefined")
|
|
65
|
+
return;
|
|
66
|
+
sessionStorage.setItem(key, value);
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
// Quota, private mode, blocked site data: no snapshot this sitting.
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
clear(key) {
|
|
73
|
+
try {
|
|
74
|
+
if (typeof sessionStorage === "undefined")
|
|
75
|
+
return;
|
|
76
|
+
sessionStorage.removeItem(key);
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
// ignore
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
export function isSessionSnapshotEnabled(config) {
|
|
85
|
+
if (typeof config === "boolean")
|
|
86
|
+
return config;
|
|
87
|
+
if (!config)
|
|
88
|
+
return false;
|
|
89
|
+
return config.enabled !== false;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Returns `null` when the host has not enabled a snapshot, and when the
|
|
93
|
+
* identity does not name one sitting. PIE writes learner responses to the
|
|
94
|
+
* device only on an explicit opt-in, and only under a key no other learner
|
|
95
|
+
* shares.
|
|
96
|
+
*/
|
|
97
|
+
export function createSessionSnapshot(args) {
|
|
98
|
+
if (!isSessionSnapshotEnabled(args.config))
|
|
99
|
+
return null;
|
|
100
|
+
const settings = typeof args.config === "object" && args.config ? args.config : {};
|
|
101
|
+
if (!settings.key && !isSnapshotIdentitySpecific(args.identity))
|
|
102
|
+
return null;
|
|
103
|
+
const key = settings.key || sessionSnapshotKey(args.identity);
|
|
104
|
+
const store = settings.store || sessionStorageSnapshotStore();
|
|
105
|
+
// A host-injected store is guarded the same way the default one is: a player
|
|
106
|
+
// keeps working without a snapshot rather than failing on storage.
|
|
107
|
+
const safeRead = () => {
|
|
108
|
+
try {
|
|
109
|
+
return store.read(key);
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
const safeWrite = (value) => {
|
|
116
|
+
try {
|
|
117
|
+
store.write(key, value);
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
// no snapshot this sitting
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
const safeClear = () => {
|
|
124
|
+
try {
|
|
125
|
+
store.clear(key);
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
// no snapshot this sitting
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
return {
|
|
132
|
+
key,
|
|
133
|
+
write(session) {
|
|
134
|
+
let payload;
|
|
135
|
+
try {
|
|
136
|
+
payload = JSON.stringify({ session, timestamp: Date.now() });
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
safeWrite(payload);
|
|
142
|
+
},
|
|
143
|
+
read() {
|
|
144
|
+
const raw = safeRead();
|
|
145
|
+
if (!raw)
|
|
146
|
+
return null;
|
|
147
|
+
try {
|
|
148
|
+
const parsed = JSON.parse(raw);
|
|
149
|
+
if (!parsed || typeof parsed !== "object" || !("session" in parsed)) {
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
return {
|
|
153
|
+
key,
|
|
154
|
+
session: parsed.session,
|
|
155
|
+
timestamp: typeof parsed.timestamp === "number" ? parsed.timestamp : 0,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
},
|
|
162
|
+
clear() {
|
|
163
|
+
safeClear();
|
|
164
|
+
},
|
|
165
|
+
};
|
|
166
|
+
}
|
package/dist/pie/stages.d.ts
CHANGED
|
@@ -1,56 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Stage vocabulary of the section player's `pie-stage-change` event.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
4
|
+
* A cohort (one section and attempt) moves through `composed`,
|
|
5
|
+
* `engine-ready`, `interactive` and `disposed`, in that order. The section
|
|
6
|
+
* runtime engine in `@pie-players/pie-assessment-toolkit` is the only emitter;
|
|
7
|
+
* it dispatches the event on the layout element. `pie-loading-complete`
|
|
8
|
+
* reports that every item loaded and is not a stage. `readiness.mode =
|
|
9
|
+
* "strict"` only delays `interactive`.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* `runtime-bound`, and `ui-rendered` stages. The retro keeps the same
|
|
15
|
-
* shape for both the toolkit CE and the layout CEs — every CE iterates
|
|
16
|
-
* through the same list so subscribers don't need to special-case shape.
|
|
17
|
-
*
|
|
18
|
-
* Locked decisions (see `m6_ready_vocab_canonical_followup.plan.md`):
|
|
19
|
-
* - **A1** Stage machine model with one canonical event family.
|
|
20
|
-
* - **B1** "All items loaded" is reclassified as `pie-loading-complete`,
|
|
21
|
-
* not a stage. (The previous `ready` DOM event alias was removed in
|
|
22
|
-
* the broad architecture review compat sweep.)
|
|
23
|
-
* - **C1** `readiness.mode = "strict"` only delays the `interactive`
|
|
24
|
-
* transition; every earlier stage fires identically across modes.
|
|
25
|
-
* - **D1** One DOM event family `pie-stage-change` with the stage in the
|
|
26
|
-
* payload, mirroring the M3 `framework-error` idiom.
|
|
27
|
-
*
|
|
28
|
-
* Failure semantics deliberately stay in the M3 framework-error contract —
|
|
29
|
-
* `status: "failed"` records the position; the framework error records the
|
|
30
|
-
* cause.
|
|
11
|
+
* `status` is `entered`, or `failed` for the stage a non-recoverable
|
|
12
|
+
* framework error stopped the chain at, with `skipped` for each later stage
|
|
13
|
+
* up to `interactive`. The `framework-error` event carries the cause.
|
|
31
14
|
*/
|
|
32
15
|
export declare const STAGES: readonly ["composed", "engine-ready", "interactive", "disposed"];
|
|
33
16
|
export type Stage = (typeof STAGES)[number];
|
|
34
17
|
export type StageStatus = "entered" | "skipped" | "failed";
|
|
35
|
-
/**
|
|
36
|
-
* Subset of the source CE shape used by stage subscribers. Both shapes
|
|
37
|
-
* apply every canonical stage post-retro — the distinction stays in the
|
|
38
|
-
* type so future shape-specific stages (e.g. layout-only `paginated`) can
|
|
39
|
-
* be added without churn at the call sites.
|
|
40
|
-
*/
|
|
41
|
-
export type StageSourceCe = "toolkit" | "layout";
|
|
42
|
-
/**
|
|
43
|
-
* Stages that apply to a given CE shape. Post-retro the toolkit and the
|
|
44
|
-
* layout CEs share the same canonical list; `applicableStages` is kept as
|
|
45
|
-
* an indirection so the tracker, telemetry, and tests don't have to be
|
|
46
|
-
* rewritten when a future stage diverges between shapes.
|
|
47
|
-
*/
|
|
48
|
-
export declare function applicableStages(_sourceCe: StageSourceCe): readonly Stage[];
|
|
49
|
-
/**
|
|
50
|
-
* Strict ordering index used by the tracker to detect monotonic
|
|
51
|
-
* violations. `disposed` is last; `composed` is first.
|
|
52
|
-
*/
|
|
53
|
-
export declare function stageOrdinal(stage: Stage): number;
|
|
54
18
|
export type StageChangeDetail = {
|
|
55
19
|
stage: Stage;
|
|
56
20
|
status: StageStatus;
|
|
@@ -68,7 +32,6 @@ export type LoadingCompleteDetail = {
|
|
|
68
32
|
sectionId: string;
|
|
69
33
|
attemptId?: string;
|
|
70
34
|
itemCount: number;
|
|
71
|
-
loadedCount: number;
|
|
72
35
|
timestamp: string;
|
|
73
36
|
sourceCe: string;
|
|
74
37
|
};
|
package/dist/pie/stages.js
CHANGED
|
@@ -1,33 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Stage vocabulary of the section player's `pie-stage-change` event.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
4
|
+
* A cohort (one section and attempt) moves through `composed`,
|
|
5
|
+
* `engine-ready`, `interactive` and `disposed`, in that order. The section
|
|
6
|
+
* runtime engine in `@pie-players/pie-assessment-toolkit` is the only emitter;
|
|
7
|
+
* it dispatches the event on the layout element. `pie-loading-complete`
|
|
8
|
+
* reports that every item loaded and is not a stage. `readiness.mode =
|
|
9
|
+
* "strict"` only delays `interactive`.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* `runtime-bound`, and `ui-rendered` stages. The retro keeps the same
|
|
15
|
-
* shape for both the toolkit CE and the layout CEs — every CE iterates
|
|
16
|
-
* through the same list so subscribers don't need to special-case shape.
|
|
17
|
-
*
|
|
18
|
-
* Locked decisions (see `m6_ready_vocab_canonical_followup.plan.md`):
|
|
19
|
-
* - **A1** Stage machine model with one canonical event family.
|
|
20
|
-
* - **B1** "All items loaded" is reclassified as `pie-loading-complete`,
|
|
21
|
-
* not a stage. (The previous `ready` DOM event alias was removed in
|
|
22
|
-
* the broad architecture review compat sweep.)
|
|
23
|
-
* - **C1** `readiness.mode = "strict"` only delays the `interactive`
|
|
24
|
-
* transition; every earlier stage fires identically across modes.
|
|
25
|
-
* - **D1** One DOM event family `pie-stage-change` with the stage in the
|
|
26
|
-
* payload, mirroring the M3 `framework-error` idiom.
|
|
27
|
-
*
|
|
28
|
-
* Failure semantics deliberately stay in the M3 framework-error contract —
|
|
29
|
-
* `status: "failed"` records the position; the framework error records the
|
|
30
|
-
* cause.
|
|
11
|
+
* `status` is `entered`, or `failed` for the stage a non-recoverable
|
|
12
|
+
* framework error stopped the chain at, with `skipped` for each later stage
|
|
13
|
+
* up to `interactive`. The `framework-error` event carries the cause.
|
|
31
14
|
*/
|
|
32
15
|
export const STAGES = Object.freeze([
|
|
33
16
|
"composed",
|
|
@@ -35,23 +18,3 @@ export const STAGES = Object.freeze([
|
|
|
35
18
|
"interactive",
|
|
36
19
|
"disposed",
|
|
37
20
|
]);
|
|
38
|
-
/**
|
|
39
|
-
* Stages that apply to a given CE shape. Post-retro the toolkit and the
|
|
40
|
-
* layout CEs share the same canonical list; `applicableStages` is kept as
|
|
41
|
-
* an indirection so the tracker, telemetry, and tests don't have to be
|
|
42
|
-
* rewritten when a future stage diverges between shapes.
|
|
43
|
-
*/
|
|
44
|
-
export function applicableStages(_sourceCe) {
|
|
45
|
-
return STAGES;
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Strict ordering index used by the tracker to detect monotonic
|
|
49
|
-
* violations. `disposed` is last; `composed` is first.
|
|
50
|
-
*/
|
|
51
|
-
export function stageOrdinal(stage) {
|
|
52
|
-
const idx = STAGES.indexOf(stage);
|
|
53
|
-
if (idx === -1) {
|
|
54
|
-
throw new Error(`Unknown stage \`${stage}\``);
|
|
55
|
-
}
|
|
56
|
-
return idx;
|
|
57
|
-
}
|
package/dist/pie/tag-names.d.ts
CHANGED
|
@@ -15,3 +15,4 @@ export declare const toViewTag: (baseTag: string, view: PieViewMode | string, cu
|
|
|
15
15
|
* Build a safe print tag by appending a deterministic, positive hash suffix.
|
|
16
16
|
*/
|
|
17
17
|
export declare const toPrintHashedTag: (baseTag: string, hashSource: string, hashFn: (value: string) => number) => string;
|
|
18
|
+
export { parseVersionedTagName } from "./versioned-tag.js";
|
package/dist/pie/tag-names.js
CHANGED
package/dist/pie/types.d.ts
CHANGED
|
@@ -5,10 +5,6 @@
|
|
|
5
5
|
* This module has NO runtime dependencies on other PIE modules.
|
|
6
6
|
*/
|
|
7
7
|
import type { ConfigEntity, Env, PieController, PieModel } from "../types/index.js";
|
|
8
|
-
/**
|
|
9
|
-
* Player modes
|
|
10
|
-
*/
|
|
11
|
-
export type PlayerMode = "gather" | "view" | "evaluate" | "author";
|
|
12
8
|
/**
|
|
13
9
|
* PIE custom element interface
|
|
14
10
|
*/
|
|
@@ -52,7 +48,8 @@ export interface AssetHandler {
|
|
|
52
48
|
export declare enum BundleType {
|
|
53
49
|
player = "player.js",// Elements only (no controllers)
|
|
54
50
|
clientPlayer = "client-player.js",// Elements + controllers
|
|
55
|
-
editor = "editor.js"
|
|
51
|
+
editor = "editor.js",// Editor UI
|
|
52
|
+
esm = "esm"
|
|
56
53
|
}
|
|
57
54
|
/**
|
|
58
55
|
* Internal PIE registry entry status
|
|
@@ -93,6 +90,8 @@ export interface UpdatePieElementOptions {
|
|
|
93
90
|
session: any[];
|
|
94
91
|
env?: Env;
|
|
95
92
|
invokeControllerForModel?: boolean;
|
|
93
|
+
/** The delivering player's bundle type, see `findPieController`. */
|
|
94
|
+
bundleType?: BundleType;
|
|
96
95
|
eventListeners?: EventListeners;
|
|
97
96
|
container?: Element | Document;
|
|
98
97
|
/**
|
package/dist/pie/types.js
CHANGED
|
@@ -12,6 +12,7 @@ export var BundleType;
|
|
|
12
12
|
BundleType["player"] = "player.js";
|
|
13
13
|
BundleType["clientPlayer"] = "client-player.js";
|
|
14
14
|
BundleType["editor"] = "editor.js";
|
|
15
|
+
BundleType["esm"] = "esm";
|
|
15
16
|
})(BundleType || (BundleType = {}));
|
|
16
17
|
/**
|
|
17
18
|
* Internal PIE registry entry status
|
package/dist/pie/updates.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Functions for updating PIE elements with new models, sessions, and env.
|
|
5
5
|
*/
|
|
6
6
|
import type { ConfigEntity, Env } from "../types/index.js";
|
|
7
|
-
import type { UpdatePieElementOptions } from "./types.js";
|
|
7
|
+
import type { BundleType, UpdatePieElementOptions } from "./types.js";
|
|
8
8
|
/**
|
|
9
9
|
* Update a PIE element by ref (direct Element reference)
|
|
10
10
|
*/
|
|
@@ -16,4 +16,4 @@ export declare const updatePieElement: (elName: string, opts: UpdatePieElementOp
|
|
|
16
16
|
/**
|
|
17
17
|
* Update all PIE elements in a config
|
|
18
18
|
*/
|
|
19
|
-
export declare const updatePieElements: (config: ConfigEntity, session: any[], env: Env, container?: Element | Document, onElementSessionUpdate?: UpdatePieElementOptions["onElementSessionUpdate"]) => Promise<void>;
|
|
19
|
+
export declare const updatePieElements: (config: ConfigEntity, session: any[], env: Env, container?: Element | Document, onElementSessionUpdate?: UpdatePieElementOptions["onElementSessionUpdate"], bundleType?: BundleType) => Promise<void>;
|
package/dist/pie/updates.js
CHANGED
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
* Functions for updating PIE elements with new models, sessions, and env.
|
|
5
5
|
*/
|
|
6
6
|
import { mergeObjectsIgnoringNullUndefined } from "../object/index.js";
|
|
7
|
-
import { wrapModelRichContent } from "../security/wrap-model-rich-content.js";
|
|
8
7
|
import { createPieLogger, isGlobalDebugEnabled } from "./logger.js";
|
|
9
8
|
import { findPieController } from "./scoring.js";
|
|
10
9
|
import { defaultPieElementOptions } from "./types.js";
|
|
@@ -55,11 +54,23 @@ const emitControllerError = (pieElement, detail) => {
|
|
|
55
54
|
composed: true,
|
|
56
55
|
}));
|
|
57
56
|
};
|
|
57
|
+
/**
|
|
58
|
+
* Reports whether an element has left the document since its update started.
|
|
59
|
+
* A legacy element unmounts its React root when it is disconnected, and a
|
|
60
|
+
* write after that throws React error #409 in releases before PIE-703, or
|
|
61
|
+
* renders a tree nothing unmounts in later ones. The controller call is when a
|
|
62
|
+
* host can remove the player. An element that was never inserted still takes
|
|
63
|
+
* the update, so a caller can set one up before inserting it.
|
|
64
|
+
*/
|
|
65
|
+
const trackRemoval = (element) => {
|
|
66
|
+
const wasConnected = element.isConnected;
|
|
67
|
+
return () => wasConnected && !element.isConnected;
|
|
68
|
+
};
|
|
58
69
|
/**
|
|
59
70
|
* Helper function to apply controller to element
|
|
60
71
|
* Extracted to eliminate duplication and ensure consistent controller invocation
|
|
61
72
|
*/
|
|
62
|
-
const applyControllerToElement = async (element, model, elementSession, controller, env, logPrefix, onElementSessionUpdate) => {
|
|
73
|
+
const applyControllerToElement = async (element, model, elementSession, controller, env, logPrefix, wasRemoved, onElementSessionUpdate) => {
|
|
63
74
|
logger.debug(`${logPrefix} Using controller, env:`, env);
|
|
64
75
|
logger.debug(`${logPrefix} Model before filter:`, {
|
|
65
76
|
id: model.id,
|
|
@@ -93,15 +104,16 @@ const applyControllerToElement = async (element, model, elementSession, controll
|
|
|
93
104
|
element: model.element,
|
|
94
105
|
...controllerResultObject,
|
|
95
106
|
};
|
|
96
|
-
const wrappedModel = wrapModelRichContent(filteredModel);
|
|
97
107
|
logger.debug(`${logPrefix} ✅ Controller filtered model:`, {
|
|
98
|
-
id:
|
|
99
|
-
element:
|
|
100
|
-
hasCorrectResponse: "correctResponse" in
|
|
108
|
+
id: filteredModel.id,
|
|
109
|
+
element: filteredModel.element,
|
|
110
|
+
hasCorrectResponse: "correctResponse" in filteredModel,
|
|
101
111
|
mode: env.mode,
|
|
102
112
|
role: env.role,
|
|
103
113
|
});
|
|
104
|
-
|
|
114
|
+
if (wasRemoved())
|
|
115
|
+
return;
|
|
116
|
+
element.model = filteredModel;
|
|
105
117
|
element.session = elementSession;
|
|
106
118
|
}
|
|
107
119
|
catch (err) {
|
|
@@ -110,7 +122,7 @@ const applyControllerToElement = async (element, model, elementSession, controll
|
|
|
110
122
|
}
|
|
111
123
|
};
|
|
112
124
|
const resolveAndValidateUpdateOptions = (opts) => {
|
|
113
|
-
const { config, session, env, eventListeners, invokeControllerForModel, onElementSessionUpdate, } = mergeObjectsIgnoringNullUndefined(defaultPieElementOptions, opts);
|
|
125
|
+
const { config, session, env, eventListeners, invokeControllerForModel, bundleType, onElementSessionUpdate, } = mergeObjectsIgnoringNullUndefined(defaultPieElementOptions, opts);
|
|
114
126
|
if (!env) {
|
|
115
127
|
throw new Error("env is required");
|
|
116
128
|
}
|
|
@@ -126,11 +138,12 @@ const resolveAndValidateUpdateOptions = (opts) => {
|
|
|
126
138
|
env,
|
|
127
139
|
eventListeners,
|
|
128
140
|
invokeControllerForModel,
|
|
141
|
+
bundleType,
|
|
129
142
|
onElementSessionUpdate,
|
|
130
143
|
};
|
|
131
144
|
};
|
|
132
145
|
const updateSinglePieElement = async (pieElement, controllerLookupTag, options, logContext) => {
|
|
133
|
-
const { config, session, env, eventListeners, invokeControllerForModel, onElementSessionUpdate, } = options;
|
|
146
|
+
const { config, session, env, eventListeners, invokeControllerForModel, bundleType, onElementSessionUpdate, } = options;
|
|
134
147
|
const model = config.models?.find((m) => m.id === pieElement.id);
|
|
135
148
|
if (!model) {
|
|
136
149
|
logger.error(`${logContext} Model not found for`, controllerLookupTag);
|
|
@@ -144,10 +157,10 @@ const updateSinglePieElement = async (pieElement, controllerLookupTag, options,
|
|
|
144
157
|
});
|
|
145
158
|
}
|
|
146
159
|
if (env && invokeControllerForModel) {
|
|
147
|
-
const controller = findPieController(controllerLookupTag);
|
|
160
|
+
const controller = findPieController(controllerLookupTag, bundleType);
|
|
148
161
|
if (!controller) {
|
|
149
162
|
logger.debug(`${logContext} ℹ️ No controller for ${controllerLookupTag}, using server-processed model`);
|
|
150
|
-
pieElement.model =
|
|
163
|
+
pieElement.model = model;
|
|
151
164
|
pieElement.session = elementSession;
|
|
152
165
|
return;
|
|
153
166
|
}
|
|
@@ -160,8 +173,9 @@ const updateSinglePieElement = async (pieElement, controllerLookupTag, options,
|
|
|
160
173
|
// caller computes/emits the session signature; otherwise a late, async
|
|
161
174
|
// shuffle write lands after the cycle that read the session and the order
|
|
162
175
|
// never round-trips (PIE-631).
|
|
176
|
+
const wasRemoved = trackRemoval(pieElement);
|
|
163
177
|
try {
|
|
164
|
-
await applyControllerToElement(pieElement, model, elementSession, controller, env, `${logContext}(${controllerLookupTag}#${pieElement.id})`, onElementSessionUpdate);
|
|
178
|
+
await applyControllerToElement(pieElement, model, elementSession, controller, env, `${logContext}(${controllerLookupTag}#${pieElement.id})`, wasRemoved, onElementSessionUpdate);
|
|
165
179
|
}
|
|
166
180
|
catch (err) {
|
|
167
181
|
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
@@ -172,19 +186,22 @@ const updateSinglePieElement = async (pieElement, controllerLookupTag, options,
|
|
|
172
186
|
? "PIE_CONTROLLER_CONTRACT_ERROR"
|
|
173
187
|
: "PIE_CONTROLLER_RUNTIME_ERROR",
|
|
174
188
|
message: `${controllerLookupTag} controller failed while applying model for ${pieElement.id}. ${errorMessage}`,
|
|
189
|
+
recoverable: true,
|
|
175
190
|
elementName: controllerLookupTag,
|
|
176
191
|
elementId: pieElement.id,
|
|
177
192
|
controllerShape: describeControllerShape(controller),
|
|
178
193
|
cause: errorMessage,
|
|
179
194
|
});
|
|
180
195
|
// Fall back to raw model on controller error
|
|
181
|
-
|
|
196
|
+
if (wasRemoved())
|
|
197
|
+
return;
|
|
198
|
+
pieElement.model = model;
|
|
182
199
|
pieElement.session = elementSession;
|
|
183
200
|
}
|
|
184
201
|
}
|
|
185
202
|
else {
|
|
186
203
|
logger.debug(`${logContext} Direct model assignment for ${controllerLookupTag}#${pieElement.id} (no controller invocation requested)`);
|
|
187
|
-
pieElement.model =
|
|
204
|
+
pieElement.model = model;
|
|
188
205
|
pieElement.session = elementSession;
|
|
189
206
|
}
|
|
190
207
|
};
|
|
@@ -215,7 +232,7 @@ export const updatePieElement = (elName, opts) => {
|
|
|
215
232
|
/**
|
|
216
233
|
* Update all PIE elements in a config
|
|
217
234
|
*/
|
|
218
|
-
export const updatePieElements = (config, session, env, container, onElementSessionUpdate) => {
|
|
235
|
+
export const updatePieElements = (config, session, env, container, onElementSessionUpdate, bundleType) => {
|
|
219
236
|
logger.debug("[updatePieElements] Updating all elements with env:", env);
|
|
220
237
|
return Promise.all(Object.entries(config.elements).map(([elName, _pkg]) => updatePieElement(elName, {
|
|
221
238
|
config,
|
|
@@ -223,5 +240,6 @@ export const updatePieElements = (config, session, env, container, onElementSess
|
|
|
223
240
|
env,
|
|
224
241
|
container,
|
|
225
242
|
onElementSessionUpdate,
|
|
243
|
+
bundleType,
|
|
226
244
|
}))).then(() => undefined);
|
|
227
245
|
};
|
|
@@ -6,6 +6,10 @@ const encodeVersionForTag = (version) => version
|
|
|
6
6
|
.replace(/[.+]/g, "-")
|
|
7
7
|
.replace(/[^0-9A-Za-z-]/g, "-")
|
|
8
8
|
.replace(/-{2,}/g, "-");
|
|
9
|
+
/**
|
|
10
|
+
* Split a runtime tag into its base name and the encoded version that follows
|
|
11
|
+
* `--version-`, when it has one.
|
|
12
|
+
*/
|
|
9
13
|
export function parseVersionedTagName(tagName) {
|
|
10
14
|
const versionMatch = tagName.match(new RegExp(`${VERSION_DELIMITER}(${TAG_VERSION_PATTERN})$`));
|
|
11
15
|
if (!versionMatch || versionMatch.index === undefined) {
|
package/dist/security/index.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
export { buildAuthoringAllowList, createDefaultItemMarkupSanitizer,
|
|
1
|
+
export { buildAuthoringAllowList, createDefaultItemMarkupSanitizer, sanitizeItemMarkup, type ItemMarkupSanitizer, type SanitizeItemMarkupOptions, } from "./sanitize-item-markup.js";
|
|
2
2
|
export { parseAllowedStyleOrigins, validateExternalStyleUrl, type StyleUrlValidationError, type StyleUrlValidationOk, type StyleUrlValidationOptions, type StyleUrlValidationResult, } from "./validate-style-url.js";
|
|
3
|
-
export {
|
|
3
|
+
export { sanitizeSvgIcon } from "./sanitize-svg-icon.js";
|
|
4
4
|
export { sanitizeStyleAttribute } from "./sanitize-style-attribute.js";
|
|
5
5
|
export { isOverwideImageWrapMutation, wrapOverwideImages, wrapOverwideImagesInElement, } from "./wrap-overwide-images.js";
|
|
6
|
-
export { wrapModelRichContent } from "./wrap-model-rich-content.js";
|
|
7
6
|
export { isOverwideTableWrapMutation, wrapOverwideTables, wrapOverwideTablesInElement, } from "./wrap-overwide-tables.js";
|
package/dist/security/index.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
export { buildAuthoringAllowList, createDefaultItemMarkupSanitizer,
|
|
1
|
+
export { buildAuthoringAllowList, createDefaultItemMarkupSanitizer, sanitizeItemMarkup, } from "./sanitize-item-markup.js";
|
|
2
2
|
export { parseAllowedStyleOrigins, validateExternalStyleUrl, } from "./validate-style-url.js";
|
|
3
|
-
export {
|
|
3
|
+
export { sanitizeSvgIcon } from "./sanitize-svg-icon.js";
|
|
4
4
|
export { sanitizeStyleAttribute } from "./sanitize-style-attribute.js";
|
|
5
5
|
export { isOverwideImageWrapMutation, wrapOverwideImages, wrapOverwideImagesInElement, } from "./wrap-overwide-images.js";
|
|
6
|
-
export { wrapModelRichContent } from "./wrap-model-rich-content.js";
|
|
7
6
|
export { isOverwideTableWrapMutation, wrapOverwideTables, wrapOverwideTablesInElement, } from "./wrap-overwide-tables.js";
|
|
@@ -35,6 +35,10 @@ export interface SanitizeItemMarkupOptions {
|
|
|
35
35
|
* `form`, `meta`, `link`).
|
|
36
36
|
* - Preserves PIE custom elements (`pie-*`) and any extra tags listed in
|
|
37
37
|
* `allowedCustomElements`.
|
|
38
|
+
* - Marks elements that carry an authored color, as `markAuthoredColors`
|
|
39
|
+
* in `@pie-element/shared-utils` describes, so a color scheme can override
|
|
40
|
+
* it. A host that opts out with `trust-markup` or supplies its own
|
|
41
|
+
* sanitizer gets no markers.
|
|
38
42
|
* - During SSR (no `window`) returns an empty string so untrusted markup
|
|
39
43
|
* never reaches the prerender output; the live renderer will re-run the
|
|
40
44
|
* sanitizer on hydrate.
|
|
@@ -52,5 +56,3 @@ export declare function createDefaultItemMarkupSanitizer(options?: SanitizeItemM
|
|
|
52
56
|
* keeps the rewritten `-config` tags instead of stripping them.
|
|
53
57
|
*/
|
|
54
58
|
export declare function buildAuthoringAllowList(elementTagNames: Iterable<string>): string[];
|
|
55
|
-
/** Reset the memoised DOMPurify instance. Only intended for tests. */
|
|
56
|
-
export declare function resetPurifierForTesting(): void;
|