@patch-adams/core 1.5.19 → 1.5.21
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/dist/cli.cjs +135 -2
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +135 -2
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +135 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +135 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -1932,6 +1932,129 @@ function generateLrsBridgeCode(options) {
|
|
|
1932
1932
|
return hasValidMbox || hasValidAccount;
|
|
1933
1933
|
}
|
|
1934
1934
|
|
|
1935
|
+
// ========================================================================
|
|
1936
|
+
// CROSS-FRAME ACTOR SHARING
|
|
1937
|
+
// PA-Patcher injects the bridge into ALL HTML files in a SCORM package.
|
|
1938
|
+
// Rise courses have multiple HTML files (index.html, scormcontent/index.html),
|
|
1939
|
+
// each getting their own bridge instance with its own LRS.actor.
|
|
1940
|
+
// The skin overlay (email gate) only runs in one frame and sets the actor there.
|
|
1941
|
+
// Without sharing, other bridge instances keep the Anonymous Learner actor.
|
|
1942
|
+
// Solution: persist actor to localStorage so all bridge instances can use it.
|
|
1943
|
+
// ========================================================================
|
|
1944
|
+
var ACTOR_STORAGE_KEY = 'pa_lrs_shared_actor';
|
|
1945
|
+
|
|
1946
|
+
function isAnonymousActor(actor) {
|
|
1947
|
+
if (!actor) return true;
|
|
1948
|
+
if (!actor.name) return true;
|
|
1949
|
+
var n = actor.name.toLowerCase();
|
|
1950
|
+
return n === 'anonymous learner' || n === 'unknown learner' || n === 'anonymous' || n === 'unknown';
|
|
1951
|
+
}
|
|
1952
|
+
|
|
1953
|
+
/**
|
|
1954
|
+
* Persist actor to localStorage for cross-frame sharing.
|
|
1955
|
+
* Only stores non-anonymous actors.
|
|
1956
|
+
*/
|
|
1957
|
+
function persistActor(actor) {
|
|
1958
|
+
if (!actor || isAnonymousActor(actor)) return;
|
|
1959
|
+
try {
|
|
1960
|
+
localStorage.setItem(ACTOR_STORAGE_KEY, JSON.stringify(actor));
|
|
1961
|
+
log('Actor persisted to localStorage:', actor.name);
|
|
1962
|
+
} catch (e) { /* localStorage unavailable */ }
|
|
1963
|
+
}
|
|
1964
|
+
|
|
1965
|
+
/**
|
|
1966
|
+
* Load shared actor from localStorage.
|
|
1967
|
+
* Returns the stored actor or null.
|
|
1968
|
+
*/
|
|
1969
|
+
function loadSharedActor() {
|
|
1970
|
+
try {
|
|
1971
|
+
var stored = localStorage.getItem(ACTOR_STORAGE_KEY);
|
|
1972
|
+
if (stored) {
|
|
1973
|
+
var actor = JSON.parse(stored);
|
|
1974
|
+
if (actor && !isAnonymousActor(actor)) {
|
|
1975
|
+
return actor;
|
|
1976
|
+
}
|
|
1977
|
+
}
|
|
1978
|
+
} catch (e) { /* localStorage unavailable or parse error */ }
|
|
1979
|
+
return null;
|
|
1980
|
+
}
|
|
1981
|
+
|
|
1982
|
+
/**
|
|
1983
|
+
* Get the best available actor for statement building.
|
|
1984
|
+
* ALWAYS checks localStorage because the skin overlay in another frame
|
|
1985
|
+
* may have updated the actor AFTER this bridge instance initialized.
|
|
1986
|
+
* (e.g., user enters email in skin overlay \u2192 actor persisted to localStorage,
|
|
1987
|
+
* but the bridge in scormcontent/index.html already loaded a stale actor at init)
|
|
1988
|
+
*/
|
|
1989
|
+
function getActor() {
|
|
1990
|
+
// Always check localStorage for the freshest actor \u2014 it may have been
|
|
1991
|
+
// updated by the skin overlay in another frame since our init
|
|
1992
|
+
var shared = loadSharedActor();
|
|
1993
|
+
if (shared) {
|
|
1994
|
+
// Only update if different from current (avoid unnecessary log spam)
|
|
1995
|
+
if (!LRS.actor || LRS.actor.name !== shared.name ||
|
|
1996
|
+
(LRS.actor.account && shared.account && LRS.actor.account.name !== shared.account.name)) {
|
|
1997
|
+
log('Actor updated from cross-frame storage:', shared.name);
|
|
1998
|
+
}
|
|
1999
|
+
LRS.actor = shared;
|
|
2000
|
+
return shared;
|
|
2001
|
+
}
|
|
2002
|
+
// Fallback to current actor or re-extract
|
|
2003
|
+
if (LRS.actor && !isAnonymousActor(LRS.actor)) {
|
|
2004
|
+
return LRS.actor;
|
|
2005
|
+
}
|
|
2006
|
+
return LRS.actor || extractActor();
|
|
2007
|
+
}
|
|
2008
|
+
|
|
2009
|
+
/**
|
|
2010
|
+
* Set actor on the bridge with cross-frame persistence.
|
|
2011
|
+
* Called by skins and external code via window.pa_patcher.lrs.setActor(actor)
|
|
2012
|
+
*/
|
|
2013
|
+
LRS.setActor = function(actor) {
|
|
2014
|
+
LRS.actor = actor;
|
|
2015
|
+
persistActor(actor);
|
|
2016
|
+
|
|
2017
|
+
// Propagate to ALL frames: walk UP parent chain AND DOWN into child iframes
|
|
2018
|
+
// UP: parent frames (e.g., if skin is in a child iframe)
|
|
2019
|
+
try {
|
|
2020
|
+
var w = window;
|
|
2021
|
+
for (var i = 0; i < 10; i++) {
|
|
2022
|
+
try {
|
|
2023
|
+
if (w !== window && w.pa_patcher && w.pa_patcher.lrs) {
|
|
2024
|
+
w.pa_patcher.lrs.actor = actor;
|
|
2025
|
+
}
|
|
2026
|
+
} catch (e) { /* cross-origin */ }
|
|
2027
|
+
if (w === w.parent) break;
|
|
2028
|
+
w = w.parent;
|
|
2029
|
+
}
|
|
2030
|
+
} catch (e) {}
|
|
2031
|
+
|
|
2032
|
+
// DOWN: child iframes (e.g., scormcontent/index.html has its own bridge)
|
|
2033
|
+
function setActorInChildren(win) {
|
|
2034
|
+
try {
|
|
2035
|
+
var frames = win.frames;
|
|
2036
|
+
for (var j = 0; j < frames.length; j++) {
|
|
2037
|
+
try {
|
|
2038
|
+
if (frames[j].pa_patcher && frames[j].pa_patcher.lrs) {
|
|
2039
|
+
frames[j].pa_patcher.lrs.actor = actor;
|
|
2040
|
+
log('Actor propagated to child frame', j);
|
|
2041
|
+
}
|
|
2042
|
+
// Recurse into nested iframes
|
|
2043
|
+
setActorInChildren(frames[j]);
|
|
2044
|
+
} catch (e) { /* cross-origin child */ }
|
|
2045
|
+
}
|
|
2046
|
+
} catch (e) {}
|
|
2047
|
+
}
|
|
2048
|
+
setActorInChildren(window);
|
|
2049
|
+
|
|
2050
|
+
if (window.console && window.console.info) {
|
|
2051
|
+
console.info('[PA-LRS] Actor set:', actor.name,
|
|
2052
|
+
actor.mbox ? '(' + actor.mbox + ')' : '',
|
|
2053
|
+
actor.account ? '(account: ' + actor.account.name + ')' : '',
|
|
2054
|
+
'\u2014 shared across frames');
|
|
2055
|
+
}
|
|
2056
|
+
};
|
|
2057
|
+
|
|
1935
2058
|
/**
|
|
1936
2059
|
* Async version that fetches Bravais session if needed
|
|
1937
2060
|
* Also re-checks all sources in case they became available
|
|
@@ -1943,6 +2066,7 @@ function generateLrsBridgeCode(options) {
|
|
|
1943
2066
|
// Try to enhance actor with email if missing
|
|
1944
2067
|
enhanceActorWithEmail(actor, function(enhancedActor) {
|
|
1945
2068
|
LRS.actor = enhancedActor;
|
|
2069
|
+
persistActor(enhancedActor);
|
|
1946
2070
|
callback(enhancedActor);
|
|
1947
2071
|
});
|
|
1948
2072
|
}
|
|
@@ -2949,7 +3073,7 @@ function generateLrsBridgeCode(options) {
|
|
|
2949
3073
|
|
|
2950
3074
|
var statement = {
|
|
2951
3075
|
id: generateUUID(),
|
|
2952
|
-
actor:
|
|
3076
|
+
actor: getActor(),
|
|
2953
3077
|
verb: typeof verb === 'string' ? (VERBS[verb] || { id: verb, display: { 'en-US': verb } }) : verb,
|
|
2954
3078
|
object: courseObj,
|
|
2955
3079
|
timestamp: new Date().toISOString()
|
|
@@ -3371,7 +3495,7 @@ function generateLrsBridgeCode(options) {
|
|
|
3371
3495
|
function buildStatementXyleme(verb, activityObject, result, additionalContext) {
|
|
3372
3496
|
var statement = {
|
|
3373
3497
|
id: generateUUID(),
|
|
3374
|
-
actor:
|
|
3498
|
+
actor: getActor(),
|
|
3375
3499
|
verb: typeof verb === 'string' ? (VERBS[verb] || { id: verb, display: { 'en-US': verb } }) : verb,
|
|
3376
3500
|
object: activityObject,
|
|
3377
3501
|
timestamp: new Date().toISOString()
|
|
@@ -5100,6 +5224,15 @@ function generateLrsBridgeCode(options) {
|
|
|
5100
5224
|
// Extract actor (sync first for immediate use)
|
|
5101
5225
|
extractActor();
|
|
5102
5226
|
|
|
5227
|
+
// Check localStorage for actor set by another frame (e.g., skin overlay in a different HTML file)
|
|
5228
|
+
if (isAnonymousActor(LRS.actor)) {
|
|
5229
|
+
var sharedActor = loadSharedActor();
|
|
5230
|
+
if (sharedActor) {
|
|
5231
|
+
LRS.actor = sharedActor;
|
|
5232
|
+
log('Loaded actor from cross-frame storage at init:', sharedActor.name);
|
|
5233
|
+
}
|
|
5234
|
+
}
|
|
5235
|
+
|
|
5103
5236
|
log('Bridge initialized in mode:', LRS.mode);
|
|
5104
5237
|
log('Actor:', LRS.actor);
|
|
5105
5238
|
log('Course:', LRS.courseInfo);
|