@rathnasgala/theme 2.0.16 → 2.0.18
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rathnasgala/theme",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.18",
|
|
4
4
|
"description": "Managed Gala static-site theme payload",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"url": "git+https://github.com/rathnasgala/site-template.git"
|
|
9
9
|
},
|
|
10
10
|
"gala": {
|
|
11
|
-
"sourceCommit": "
|
|
11
|
+
"sourceCommit": "1416a9c31af41c6f4634e84c67e9fbf20fa541ed"
|
|
12
12
|
},
|
|
13
13
|
"files": [
|
|
14
14
|
"payload"
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"themePackage": {
|
|
4
4
|
"name": "@rathnasgala/theme",
|
|
5
|
-
"version": "2.0.
|
|
5
|
+
"version": "2.0.18",
|
|
6
6
|
"availableDesignThemes": [
|
|
7
7
|
"editorial",
|
|
8
8
|
"modern",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"securityAdvisories": []
|
|
12
12
|
},
|
|
13
13
|
"requiredBudgets": {
|
|
14
|
-
"managedJavaScriptBytes":
|
|
14
|
+
"managedJavaScriptBytes": 70973,
|
|
15
15
|
"managedCssBytes": 34816
|
|
16
16
|
},
|
|
17
17
|
"files": {
|
|
@@ -53,10 +53,10 @@
|
|
|
53
53
|
"src/assets/engagement-comments.js": "eda0fee471c7e42ee01a25b8aa14ed6ae9690d52b3fbb34027d97534ab62998b",
|
|
54
54
|
"src/assets/engagement-transport.js": "7f69815c4eb4fc0e127a5c09702da4189130d47b73b4598fce4196d7d6f5cbe8",
|
|
55
55
|
"src/assets/favicon.svg": "8615e3d96fe37ae9ed14afb1886e7c0e690eef5b10be66ca91cccfd085a74bb6",
|
|
56
|
-
"src/assets/interactions.js": "
|
|
56
|
+
"src/assets/interactions.js": "7b907aa0c05f0b5eb2e58cb410214a2129dcbdddc8c530d81f1d340fd90177db",
|
|
57
57
|
"src/assets/preferences.js": "789127bee013ed6a1bbf8cefd7b9109291c16220e7a6e09314e3c93c54731d1d",
|
|
58
58
|
"src/assets/prism-session.js": "1fab23725b843006c3f589af7669ef3ad6ad01f3264a3b00564e64b56738d2cd",
|
|
59
|
-
"src/assets/reader.js": "
|
|
59
|
+
"src/assets/reader.js": "3afa06aea16d7b3883e34adb367dd73646b42459eab62dc9f6c3940b169c0064",
|
|
60
60
|
"src/assets/search.js": "df425f0239277792ad39f2138bc89cb66cc4ecda5ed59042d46abc2f05372088",
|
|
61
61
|
"src/assets/theme-mode.js": "d81af8317b59f6d94dc8154c1dcba9d3e16accb37348bc3fce127712141d6c63",
|
|
62
62
|
"src/assets/theme.css": "7391086efd6f61791c47bbdf3523d7452e17b1cdb1fc91339861fe2f0a2c884b",
|
|
@@ -121,6 +121,15 @@ document.addEventListener('click', async (event) => {
|
|
|
121
121
|
return;
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
+
// FedCM requires the relying party to call navigator.credentials.get synchronously from a
|
|
125
|
+
// top-level user gesture. A click inside the cross-origin session frame followed by postMessage
|
|
126
|
+
// loses that activation before it reaches this page, so the account control owns sign-in.
|
|
127
|
+
const accountControl = event.target.closest('[data-user-control]');
|
|
128
|
+
if (accountControl && !sessionUser && sessionFrameToken) {
|
|
129
|
+
fedCmSession('active');
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
|
|
124
133
|
const dialogControl = event.target.closest('[data-open-dialog]');
|
|
125
134
|
if (dialogControl) {
|
|
126
135
|
const dialog = document.getElementById(dialogControl.dataset.openDialog);
|
|
@@ -327,6 +336,34 @@ const sessionFrame = document.querySelector('[data-gala-session-frame]');
|
|
|
327
336
|
const sessionOrigin = sessionFrame ? new URL(sessionFrame.src).origin : null;
|
|
328
337
|
let sessionFrameReady = false;
|
|
329
338
|
let pendingSessionTransferCode = null;
|
|
339
|
+
let sessionFrameToken = null;
|
|
340
|
+
let fedCmController = null;
|
|
341
|
+
const FEDCM_GRANT_COOKIE = 'gala-fedcm-grant=1';
|
|
342
|
+
|
|
343
|
+
function hasFedCmGrant() {
|
|
344
|
+
try {
|
|
345
|
+
return document.cookie.split(';').some((value) => value.trim() === FEDCM_GRANT_COOKIE);
|
|
346
|
+
} catch (error) {
|
|
347
|
+
console.warn('Gala could not read this publication\'s FedCM grant marker.', error);
|
|
348
|
+
return false;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
function rememberFedCmGrant() {
|
|
353
|
+
try {
|
|
354
|
+
document.cookie = 'gala-fedcm-grant=1; Max-Age=31536000; Path=/; SameSite=Strict; Secure';
|
|
355
|
+
} catch (error) {
|
|
356
|
+
console.warn('Gala could not remember this publication\'s FedCM grant.', error);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
function forgetFedCmGrant() {
|
|
361
|
+
try {
|
|
362
|
+
document.cookie = 'gala-fedcm-grant=; Max-Age=0; Path=/; SameSite=Strict; Secure';
|
|
363
|
+
} catch (error) {
|
|
364
|
+
console.warn('Gala could not clear this publication\'s FedCM grant.', error);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
330
367
|
|
|
331
368
|
function deliverSessionTransfer() {
|
|
332
369
|
if (!sessionFrameReady || !sessionFrame || !pendingSessionTransferCode) return;
|
|
@@ -347,6 +384,50 @@ if (sessionFrame) {
|
|
|
347
384
|
requestSessionState();
|
|
348
385
|
}
|
|
349
386
|
|
|
387
|
+
async function fedCmSession(mode) {
|
|
388
|
+
const status = document.querySelector('[data-engagement-status]');
|
|
389
|
+
if (!sessionFrameToken) return false;
|
|
390
|
+
if (!globalThis.IdentityCredential || typeof navigator.credentials?.get !== 'function') {
|
|
391
|
+
if (status) status.textContent = 'FedCM is not available in this browser. Use a current browser to sign in.';
|
|
392
|
+
return false;
|
|
393
|
+
}
|
|
394
|
+
if (fedCmController) {
|
|
395
|
+
if (mode === 'passive') return false;
|
|
396
|
+
fedCmController.abort();
|
|
397
|
+
}
|
|
398
|
+
const controller = new AbortController();
|
|
399
|
+
fedCmController = controller;
|
|
400
|
+
try {
|
|
401
|
+
const siteId = new URL(sessionFrame.src).searchParams.get('siteId') ?? '';
|
|
402
|
+
const provider = {
|
|
403
|
+
configURL: 'https://api.gala67.com/v1/fedcm/config.json',
|
|
404
|
+
clientId: siteId,
|
|
405
|
+
fields: ['name', 'email'],
|
|
406
|
+
params: { nonce: sessionFrameToken }
|
|
407
|
+
};
|
|
408
|
+
const identity = { providers: [provider] };
|
|
409
|
+
if (mode === 'active') identity.mode = 'active';
|
|
410
|
+
const credential = await navigator.credentials.get({
|
|
411
|
+
identity,
|
|
412
|
+
mediation: mode === 'active' ? 'required' : 'silent',
|
|
413
|
+
signal: controller.signal
|
|
414
|
+
});
|
|
415
|
+
if (typeof credential?.token !== 'string') return false;
|
|
416
|
+
if (mode === 'active') rememberFedCmGrant();
|
|
417
|
+
pendingSessionTransferCode = credential.token;
|
|
418
|
+
deliverSessionTransfer();
|
|
419
|
+
return true;
|
|
420
|
+
} catch (error) {
|
|
421
|
+
if (mode === 'active' && error?.name !== 'NotAllowedError' && error?.name !== 'AbortError') {
|
|
422
|
+
console.error('Gala FedCM sign-in failed.', error);
|
|
423
|
+
}
|
|
424
|
+
if (mode === 'active' && status) status.textContent = 'Sign-in did not finish. Try again.';
|
|
425
|
+
return false;
|
|
426
|
+
} finally {
|
|
427
|
+
if (fedCmController === controller) fedCmController = null;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
350
431
|
function requestSession(intent) {
|
|
351
432
|
const field = intent.field;
|
|
352
433
|
pendingIntent = {
|
|
@@ -357,20 +438,10 @@ function requestSession(intent) {
|
|
|
357
438
|
draft: field ? field.value : null,
|
|
358
439
|
caret: field ? field.selectionStart : null
|
|
359
440
|
};
|
|
360
|
-
// One window, not three. Asking used to open a modal, containing a frame, containing a
|
|
361
|
-
// button, that opened a popup. The popup is the only part that has to exist, because it is
|
|
362
|
-
// the only one running at the top level on the origin the identity providers accept.
|
|
363
|
-
const frame = document.querySelector('[data-gala-session-frame]');
|
|
364
|
-
const status = document.querySelector('[data-engagement-status]');
|
|
365
|
-
if (!frame) return;
|
|
366
|
-
const source = new URL(frame.getAttribute('src'), window.location.href);
|
|
367
|
-
const signIn = new URL('/v1/widget/session/sign-in', source.origin);
|
|
368
|
-
signIn.searchParams.set('siteId', source.searchParams.get('siteId') ?? '');
|
|
369
441
|
if (field) field.blur();
|
|
370
|
-
|
|
371
|
-
pendingIntent = null;
|
|
372
|
-
|
|
373
|
-
}
|
|
442
|
+
fedCmSession('active').then((started) => {
|
|
443
|
+
if (!started) pendingIntent = null;
|
|
444
|
+
});
|
|
374
445
|
}
|
|
375
446
|
|
|
376
447
|
/** Puts the reader back exactly where the sign-in interrupted them. */
|
|
@@ -398,29 +469,6 @@ function resumeIntent() {
|
|
|
398
469
|
element.click();
|
|
399
470
|
}
|
|
400
471
|
|
|
401
|
-
// Signing in happens in another window, so the moment this one is focused again is the moment
|
|
402
|
-
// the reader is back and the interrupted action can be finished.
|
|
403
|
-
window.addEventListener('focus', () => {
|
|
404
|
-
if (sessionUser && pendingIntent) resumeIntent();
|
|
405
|
-
});
|
|
406
|
-
|
|
407
|
-
/*
|
|
408
|
-
* The sign-in window reports success to this page rather than to the account frame.
|
|
409
|
-
*
|
|
410
|
-
* It cannot reach the frame directly: a frame embedded in a publication has its storage - and its
|
|
411
|
-
* BroadcastChannel - partitioned away from a window running at the top level on the API's origin,
|
|
412
|
-
* so the session it wrote is invisible there. The signal carries only an opaque, one-time transfer
|
|
413
|
-
* code. This page waits for the frame's readiness message before relaying that code; otherwise a
|
|
414
|
-
* fast popup can return before the frame is listening and every later click asks the reader to sign
|
|
415
|
-
* in once more.
|
|
416
|
-
*/
|
|
417
|
-
window.addEventListener('message', (event) => {
|
|
418
|
-
if (!sessionFrame || event.data?.type !== 'gala-session-established') return;
|
|
419
|
-
if (event.origin !== sessionOrigin || typeof event.data.transferCode !== 'string') return;
|
|
420
|
-
pendingSessionTransferCode = event.data.transferCode;
|
|
421
|
-
deliverSessionTransfer();
|
|
422
|
-
});
|
|
423
|
-
|
|
424
472
|
document.querySelectorAll('[data-engagement-url]').forEach((region) => {
|
|
425
473
|
refreshEngagement(region);
|
|
426
474
|
recordView(region);
|
|
@@ -501,6 +549,13 @@ async function mutateEngagement(region, operation, payload) {
|
|
|
501
549
|
if (sessionFrame) {
|
|
502
550
|
window.addEventListener('message', (event) => {
|
|
503
551
|
if (event.origin !== sessionOrigin || event.source !== sessionFrame.contentWindow) return;
|
|
552
|
+
if (event.data?.type === 'gala-fedcm-sign-out') {
|
|
553
|
+
forgetFedCmGrant();
|
|
554
|
+
navigator.credentials?.preventSilentAccess?.().catch((error) => {
|
|
555
|
+
console.error('Gala could not disable silent FedCM access after sign-out.', error);
|
|
556
|
+
});
|
|
557
|
+
return;
|
|
558
|
+
}
|
|
504
559
|
if (event.data?.type === 'gala-engagement-result') {
|
|
505
560
|
const pending = pendingEngagementWrites.get(event.data.requestId);
|
|
506
561
|
if (!pending) return;
|
|
@@ -534,6 +589,10 @@ if (sessionFrame) {
|
|
|
534
589
|
}
|
|
535
590
|
if (event.data?.type !== 'gala-session') return;
|
|
536
591
|
sessionFrameReady = true;
|
|
592
|
+
if (typeof event.data.frameToken === 'string') {
|
|
593
|
+
sessionFrameToken = event.data.frameToken;
|
|
594
|
+
document.querySelector('[data-user-control]')?.setAttribute('data-fedcm-ready', 'true');
|
|
595
|
+
}
|
|
537
596
|
if (pendingSessionTransferCode) deliverSessionTransfer();
|
|
538
597
|
sessionUser = event.data.user && typeof event.data.user.id === 'string' ? event.data.user : null;
|
|
539
598
|
const control = document.querySelector('[data-user-control]');
|
|
@@ -565,5 +624,6 @@ if (sessionFrame) {
|
|
|
565
624
|
});
|
|
566
625
|
// Signed in on the back of an interrupted action: finish what they were doing.
|
|
567
626
|
if (sessionUser && pendingIntent) resumeIntent();
|
|
627
|
+
if (!sessionUser && sessionFrameToken && hasFedCmGrant()) fedCmSession('passive');
|
|
568
628
|
});
|
|
569
629
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
(()=>{var I=["system","light","dark"],P="gala-color-mode";function O(){let e=document.documentElement.dataset.mode;return I.includes(e)?e:"system"}function re(){try{let e=localStorage.getItem(P);if(I.includes(e))return e}catch{return O()}return O()}function F(e){document.documentElement.dataset.mode=e;let n=I[(I.indexOf(e)+1)%I.length];document.querySelectorAll("[data-theme-mode-toggle]").forEach(t=>{let a=t.querySelector?.("[data-theme-mode-label]");a?a.textContent=`Theme: ${e}`:t.textContent=`Theme: ${e}`,t.setAttribute("aria-label",`Color mode: ${e}. Activate for ${n}.`)})}document.addEventListener("DOMContentLoaded",()=>{F(re()),document.querySelectorAll("[data-theme-mode-toggle]").forEach(e=>{e.addEventListener("click",()=>{let n=I[(I.indexOf(document.documentElement.dataset.mode)+1)%I.length];try{localStorage.setItem(P,n)}catch{}F(n)})})});var G="gala-language-preference";function oe(){try{return localStorage.getItem(G)}catch{return null}}function H(e,n){return[...e.options].find(t=>t.value===n)}document.addEventListener("DOMContentLoaded",()=>{let e=oe();document.querySelectorAll("[data-language-preference]").forEach(n=>{e!=null&&H(n,e)!=null&&(n.value=e),n.addEventListener("change",()=>{try{localStorage.setItem(G,n.value)}catch{}if(!n.hasAttribute("data-navigate-on-selection"))return;let t=H(n,n.value);t?.dataset.url&&window.location.assign(t.dataset.url)})})});var $="gala.prism.session.v1";document.addEventListener("click",e=>{if(e.target.closest("[data-prism-restore]")){try{sessionStorage.removeItem($)}catch{}return}let t=e.target.closest("[data-prism-select]");if(t)try{sessionStorage.setItem($,JSON.stringify({articleId:t.dataset.prismArticleId,language:t.dataset.prismLanguage,configurationId:t.dataset.prismConfigurationId,sourceRevisionHash:t.dataset.prismSourceHash,selectedAt:new Date().toISOString()}))}catch{}});function L(e){let n=e.closest(".gala-share"),t=n?.querySelector(".gala-share__fallback");t?.classList.add("gala-share__fallback--visible"),t?.focus(),t?.select();let a=n?.querySelector(".gala-share__status");a&&(a.textContent="Select and copy the URL shown.")}var j=document.querySelector("[data-reading-progress]"),x=document.querySelector(".gala-markdown");if(j&&x){let e=null,n=()=>{e=null;let a=x.offsetTop,r=Math.max(1,x.offsetHeight-window.innerHeight),c=Math.min(1,Math.max(0,(window.scrollY-a)/r));j.value=c},t=()=>{e==null&&(e=requestAnimationFrame(n))};addEventListener("scroll",t,{passive:!0}),addEventListener("resize",t,{passive:!0}),t()}var C=document.querySelector(".gala-toc");if(C?.tagName==="DETAILS"){let e=C.querySelector("nav"),n=[...C.querySelectorAll('a[href^="#"]')],t=n.map(m=>document.getElementById(m.hash.slice(1))).filter(Boolean),a=null,r=()=>{if(a=null,C.classList.toggle("gala-toc--floating",C.getBoundingClientRect().top<=96),!t.length)return;let m=window.innerHeight*.42,f=t[0];for(let s of t)if(s.getBoundingClientRect().top<=m)f=s;else break;let E=n.find(s=>s.hash===`#${f.id}`);for(let s of n)s===E?s.setAttribute("aria-current","location"):s.removeAttribute("aria-current");if(e&&n.length){let s=n[0].getBoundingClientRect(),o=n[n.length-1].getBoundingClientRect();C.classList.toggle("gala-toc--overflowing",o.bottom-s.top>e.clientHeight)}if(E&&e&&e.scrollHeight>e.clientHeight){let s=e.getBoundingClientRect(),o=E.getBoundingClientRect(),i=e.scrollTop+o.top-s.top-(e.clientHeight-o.height)/2;e.scrollTo({top:Math.max(0,i),behavior:"auto"})}},c=()=>{a==null&&(a=requestAnimationFrame(r))};addEventListener("scroll",c,{passive:!0}),addEventListener("resize",c,{passive:!0}),c()}var B=document.querySelector(".gala-action-rail"),W=document.querySelector("[data-action-dock]");if(B&&W){let e=n=>{B.classList.toggle("gala-action-rail--integrated",n[0].isIntersecting)};new IntersectionObserver(e,{rootMargin:"0px 0px 18% 0px",threshold:0}).observe(W)}function K(e,n){let t=n?"Unfollow article":"Follow article";e.setAttribute("aria-pressed",String(n)),e.setAttribute("aria-label",t),e.title=t;let a=e.querySelector("[data-follow-label]");a&&(a.textContent=t)}document.addEventListener("click",async e=>{if(e.target instanceof HTMLDialogElement&&e.target.open){let s=e.target.getBoundingClientRect();if(e.clientX<s.left||e.clientX>s.right||e.clientY<s.top||e.clientY>s.bottom){e.target.close();return}}let n=e.target.closest("[data-gala-embed-load]");if(n){let s=n.closest("[data-gala-embed]"),o=n.dataset.galaEmbedSrc,i=n.dataset.galaEmbedLoad;if(!s||!o||!["youtube","codepen"].includes(i))return;let d=document.createElement("iframe");d.src=o,d.title=i==="youtube"?"YouTube video":"CodePen example",d.loading="eager",d.referrerPolicy="strict-origin-when-cross-origin",d.setAttribute("sandbox","allow-forms allow-popups allow-presentation allow-same-origin allow-scripts"),d.setAttribute("allow",i==="youtube"?"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture; web-share":"fullscreen"),d.setAttribute("allowfullscreen",""),s.replaceChildren(d);return}let t=e.target.closest("[data-open-dialog]");if(t){let s=document.getElementById(t.dataset.openDialog);s instanceof HTMLDialogElement&&s.showModal();return}let a=e.target.closest("[data-reaction]");if(a){let s=a.closest("[data-engagement-url]");if(!s)return;if(!w)return U({kind:"reaction",region:s,selector:`[data-reaction="${a.dataset.reaction}"]`});let o=a.getAttribute("aria-pressed")!=="true";if(!await Q(s,o?"reaction.add":"reaction.remove",{articleId:s.dataset.articleId,reaction:a.dataset.reaction}))return;a.setAttribute("aria-pressed",String(o));return}let r=e.target.closest("[data-follow-article]");if(r){let s=r.closest("[data-engagement-url]");if(!s)return;if(!w)return U({kind:"follow",region:s,selector:"[data-follow-article]"});let o=r.getAttribute("aria-pressed")!=="true";if(!await Q(s,o?"follow.add":"follow.remove",{targetType:"articles",targetId:s.dataset.articleId}))return;K(r,o);return}let c=e.target.closest("[data-copy-url]");if(c){let s=c.dataset.copyUrl;if(!window.isSecureContext||!navigator.clipboard?.writeText){L(c);return}try{await navigator.clipboard.writeText(s);let o=c.closest(".gala-share")?.querySelector(".gala-share__status");o&&(o.textContent="Link copied.")}catch{L(c)}return}let m=e.target.closest("[data-native-share]");if(m){if(navigator.share)try{await navigator.share({title:document.title,url:m.dataset.nativeShare})}catch(s){s.name!=="AbortError"&&L(m)}else L(m);return}let f=e.target.closest("[data-copy-code]");if(!f)return;let E=f.closest(".gala-code-block")?.querySelector("code");if(!(!E||!navigator.clipboard?.writeText||!window.isSecureContext))try{await navigator.clipboard.writeText(E.textContent),f.textContent="Copied"}catch{f.textContent="Select code to copy"}});var se=new Set([...document.querySelectorAll("pre code")].map(e=>e.closest("pre")).filter(Boolean));se.forEach(e=>{let n=document.createElement("div");n.className="gala-code-block",e.before(n),n.append(e);let t=document.createElement("button");t.type="button",t.dataset.copyCode="",t.textContent="Copy code",t.setAttribute("aria-label","Copy code block"),n.prepend(t)});function ie(e){return[["Reactions",Object.values(e.reactions??{}).reduce((t,a)=>t+(Number.isSafeInteger(a)?a:0),0)],["Comments",Number.isSafeInteger(e.comments?.totalCount)?e.comments.totalCount:0],["Views",Number.isSafeInteger(e.views?.count)?e.views.count:0]]}function ce(e){return e<1e3?"<1K":new Intl.NumberFormat("en",{notation:"compact",maximumFractionDigits:1}).format(e)}function le(e,n){let t=n?.data;if(!t||typeof t!="object")throw new TypeError("Engagement data is invalid");for(let[a,r]of ie(t))e.querySelectorAll(`[data-engagement-stat="${a.toLowerCase()}"]`).forEach(c=>{c.textContent=ce(r),c.closest("div")?.setAttribute("title",`${r} ${a.toLowerCase()}`)});e.querySelector("[data-engagement-snapshot]")?.remove(),e.querySelector(".gala-engagement__placeholder")?.remove()}async function k(e,n="",t=!1,a=!1){let r=e.querySelector("[data-engagement-status]"),c=!!e.querySelector("[data-gala-comments]");try{let m=new URL(e.dataset.engagementUrl);n&&m.searchParams.set("commentsCursor",n);let f=await fetch(m,{headers:{Accept:"application/json"},credentials:"omit",cache:a?"no-store":"default"});if(!f.ok)throw new Error(`Engagement returned HTTP ${f.status}`);let E=await f.json();le(e,E),r&&!c&&(r.textContent=E.errors?.length?"Some engagement data is temporarily unavailable.":"")}catch{r&&!c&&(r.textContent="Engagement is temporarily unavailable.")}}function de(){let e=new URL(window.location.href).searchParams,n={};for(let t of["utm_source","utm_medium","utm_campaign","utm_content","utm_term"]){let a=e.get(t);a&&[...a].length<=128&&(n[t]=a)}return n}function ue(e){let n=new URL(e.dataset.engagementUrl);n.pathname=n.pathname.replace(/\/engagement$/,"/views"),fetch(n,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({language:document.documentElement.lang||void 0,referrer:document.referrer||void 0,campaign:de()}),credentials:"omit",keepalive:!0}).catch(()=>{})}document.addEventListener("gala-request-sign-in",e=>{w||S||U({kind:e.detail?.kind??"comment"})});var w=null,Y=null,N=null,q=new Map,S=null,y=document.querySelector("[data-gala-session-frame]"),_=y?new URL(y.src).origin:null,z=!1,v=null;function X(){!z||!y||!v||(y.contentWindow?.postMessage({type:"gala-session-transfer",transferCode:v},_),v=null)}function V(){y?.contentWindow?.postMessage({type:"gala-session-request"},_)}y&&(y.addEventListener("load",V),V());function U(e){let n=e.field;S={kind:e.kind,region:e.region,selector:e.selector,draft:n?n.value:null,caret:n?n.selectionStart:null};let t=document.querySelector("[data-gala-session-frame]"),a=document.querySelector("[data-engagement-status]");if(!t)return;let r=new URL(t.getAttribute("src"),window.location.href),c=new URL("/v1/widget/session/sign-in",r.origin);c.searchParams.set("siteId",r.searchParams.get("siteId")??""),n&&n.blur(),window.open(c,"gala-sign-in","popup,width=520,height=680")||(S=null,a&&(a.textContent="Allow pop-ups for this site to sign in, then try again."))}function J(){let e=S;if(!e||!document.hasFocus())return;let n=e.region?.querySelector(e.selector);if(n){if(S=null,e.kind==="comment"){e.draft!=null&&n.value===""&&(n.value=e.draft),n.focus(),e.caret!=null&&typeof n.setSelectionRange=="function"&&n.setSelectionRange(e.caret,e.caret);return}n.click()}}window.addEventListener("focus",()=>{w&&S&&J()});window.addEventListener("message",e=>{!y||e.data?.type!=="gala-session-established"||e.origin!==_||typeof e.data.transferCode!="string"||(v=e.data.transferCode,X())});document.querySelectorAll("[data-engagement-url]").forEach(e=>{k(e),ue(e)});function Z(e){return e==="AUTHENTICATION_REQUIRED"||e==="INVALID_BEARER_TOKEN"||e==="REAUTHENTICATION_REQUIRED"?"Sign in again to continue.":e==="ENGAGEMENT_RATE_LIMITED"?"You are posting too quickly; try again shortly.":e==="CONTACT_RATE_LIMITED"?"You are sending too quickly; try again later.":e==="RESOURCE_NOT_FOUND"?"That item is no longer available.":e==="INVALID_ENGAGEMENT_WRITE"||e==="INVALID_CONTACT_SUBMISSION"||e==="INVALID_REQUEST"?"Check your entry and try again.":e==="ACCESS_DENIED"?"That action is not available for this account.":e==="IDEMPOTENCY_CONFLICT"||e==="ENGAGEMENT_STATE_CONFLICT"?"The item changed; reload and try again.":"The action could not be completed. Try again."}function ee(e,n){if(!y||!w)return Promise.reject(new Error("AUTHENTICATION_REQUIRED"));let t=crypto.randomUUID();return new Promise((a,r)=>{let c=setTimeout(()=>{q.delete(t),r(new Error("REQUEST_TIMEOUT"))},1e4);q.set(t,{resolve:m=>{clearTimeout(c),a(m)},reject:m=>{clearTimeout(c),r(m)}}),y.contentWindow.postMessage({type:"gala-engagement-write",requestId:t,operation:e,payload:n},new URL(y.src).origin)})}document.addEventListener("submit",async e=>{let n=e.target.closest("[data-contact-form] form");if(!n)return;e.preventDefault();let t=n.closest("[data-contact-form]"),a=t.querySelector("[data-contact-status]");if(!w){a.textContent="Sign in with the account button before sending.";return}let r=new FormData(n);try{a.textContent="Sending\u2026",await ee("contact.submit",{siteId:t.dataset.siteId,subject:r.get("subject"),message:r.get("message"),website:r.get("website")||null,phone:r.get("phone")||null}),n.reset(),a.textContent="Message sent."}catch(c){a.textContent=Z(c.message)}});async function Q(e,n,t){let a=e.querySelector("[data-engagement-status]");try{return a&&(a.textContent="Saving\u2026"),await ee(n,t),a&&(a.textContent="Saved."),await k(e,"",!1,!0),!0}catch(r){return a&&(a.textContent=Z(r.message)),!1}}y&&window.addEventListener("message",e=>{if(e.origin!==_||e.source!==y.contentWindow)return;if(e.data?.type==="gala-engagement-result"){let r=q.get(e.data.requestId);if(!r)return;q.delete(e.data.requestId),e.data.ok===!0?r.resolve(e.data.result):r.reject(new Error(e.data.error?.code||"ENGAGEMENT_WRITE_FAILED"));return}if(e.data?.type==="gala-reader-state-result"){if(e.data.requestId!==N||e.data.ok!==!0)return;N=null;let r=new Set(Array.isArray(e.data.state?.reactions)?e.data.state.reactions:[]);document.querySelectorAll("[data-reaction]").forEach(c=>{c.setAttribute("aria-pressed",String(r.has(c.dataset.reaction)))}),document.querySelectorAll("[data-follow-article]").forEach(c=>{let m=e.data.state?.following===!0;K(c,m)});return}if(e.data?.type==="gala-session-height"){let r=Number(e.data.height);Number.isFinite(r)&&r>0&&r<2e3&&(y.height=String(Math.ceil(r)));return}if(e.data?.type!=="gala-session")return;z=!0,v&&X(),w=e.data.user&&typeof e.data.user.id=="string"?e.data.user:null;let n=document.querySelector("[data-user-control]"),t=w?.displayName;if(n){n.setAttribute("aria-label",t?`Account: ${t}`:"Sign in or view account"),n.title=t?`Account: ${t}`:"Account";let r=n.querySelector("[data-user-label]");r&&(r.textContent=t||"Sign in")}let a=Y!==(w?.id??null);if(Y=w?.id??null,w){let r=document.querySelector("[data-article-id]");r&&(N=crypto.randomUUID(),y.contentWindow.postMessage({type:"gala-reader-state-request",requestId:N,articleId:r.dataset.articleId},_))}document.querySelectorAll("[data-engagement-url]").forEach(r=>{a&&k(r)}),w&&S&&J()});document.querySelectorAll("[data-gala-search]").forEach(e=>{let n=e.querySelector("form"),t=n?.elements.namedItem("q"),a=e.querySelector("[data-search-status]"),r=e.querySelector("[data-search-results]"),c=e.dataset.indexUrl,m,f=i=>String(i??"").normalize("NFKC").toLocaleLowerCase();function E(i,d){r.replaceChildren();for(let u of i){let p=document.createElement("li"),l=document.createElement("article"),h=document.createElement("h2"),b=document.createElement("a");if(b.href=u.url,b.lang=u.language,b.textContent=u.title,h.append(b),l.append(h),u.description){let M=document.createElement("p");M.textContent=u.description,l.append(M)}p.append(l),r.append(p)}a.textContent=`${i.length} result${i.length===1?"":"s"} for \u201C${d}\u201D.`}async function s(i){let d=i.trim();if(d===""){r.replaceChildren(),a.textContent="Enter a search term.";return}a.textContent="Searching\u2026";try{m??=fetch(c,{headers:{Accept:"application/json"}}).then(async l=>{if(!l.ok)throw new Error(`Search index returned HTTP ${l.status}`);let h=await l.json();if(h?.schemaVersion!==1||!Array.isArray(h.entries))throw new TypeError("Search index schema is unsupported");return h.entries});let u=f(d),p=(await m).filter(l=>f([l.title,l.description,l.language,...Array.isArray(l.tags)?l.tags:[],l.body].join(`
|
|
2
|
-
`)).includes(
|
|
1
|
+
(()=>{var S=["system","light","dark"],$="gala-color-mode";function P(){let e=document.documentElement.dataset.mode;return S.includes(e)?e:"system"}function se(){try{let e=localStorage.getItem($);if(S.includes(e))return e}catch{return P()}return P()}function H(e){document.documentElement.dataset.mode=e;let a=S[(S.indexOf(e)+1)%S.length];document.querySelectorAll("[data-theme-mode-toggle]").forEach(t=>{let r=t.querySelector?.("[data-theme-mode-label]");r?r.textContent=`Theme: ${e}`:t.textContent=`Theme: ${e}`,t.setAttribute("aria-label",`Color mode: ${e}. Activate for ${a}.`)})}document.addEventListener("DOMContentLoaded",()=>{H(se()),document.querySelectorAll("[data-theme-mode-toggle]").forEach(e=>{e.addEventListener("click",()=>{let a=S[(S.indexOf(document.documentElement.dataset.mode)+1)%S.length];try{localStorage.setItem($,a)}catch{}H(a)})})});var B="gala-language-preference";function ie(){try{return localStorage.getItem(B)}catch{return null}}function j(e,a){return[...e.options].find(t=>t.value===a)}document.addEventListener("DOMContentLoaded",()=>{let e=ie();document.querySelectorAll("[data-language-preference]").forEach(a=>{e!=null&&j(a,e)!=null&&(a.value=e),a.addEventListener("change",()=>{try{localStorage.setItem(B,a.value)}catch{}if(!a.hasAttribute("data-navigate-on-selection"))return;let t=j(a,a.value);t?.dataset.url&&window.location.assign(t.dataset.url)})})});var W="gala.prism.session.v1";document.addEventListener("click",e=>{if(e.target.closest("[data-prism-restore]")){try{sessionStorage.removeItem(W)}catch{}return}let t=e.target.closest("[data-prism-select]");if(t)try{sessionStorage.setItem(W,JSON.stringify({articleId:t.dataset.prismArticleId,language:t.dataset.prismLanguage,configurationId:t.dataset.prismConfigurationId,sourceRevisionHash:t.dataset.prismSourceHash,selectedAt:new Date().toISOString()}))}catch{}});function L(e){let a=e.closest(".gala-share"),t=a?.querySelector(".gala-share__fallback");t?.classList.add("gala-share__fallback--visible"),t?.focus(),t?.select();let r=a?.querySelector(".gala-share__status");r&&(r.textContent="Select and copy the URL shown.")}var Y=document.querySelector("[data-reading-progress]"),U=document.querySelector(".gala-markdown");if(Y&&U){let e=null,a=()=>{e=null;let r=U.offsetTop,o=Math.max(1,U.offsetHeight-window.innerHeight),i=Math.min(1,Math.max(0,(window.scrollY-r)/o));Y.value=i},t=()=>{e==null&&(e=requestAnimationFrame(a))};addEventListener("scroll",t,{passive:!0}),addEventListener("resize",t,{passive:!0}),t()}var I=document.querySelector(".gala-toc");if(I?.tagName==="DETAILS"){let e=I.querySelector("nav"),a=[...I.querySelectorAll('a[href^="#"]')],t=a.map(d=>document.getElementById(d.hash.slice(1))).filter(Boolean),r=null,o=()=>{if(r=null,I.classList.toggle("gala-toc--floating",I.getBoundingClientRect().top<=96),!t.length)return;let d=window.innerHeight*.42,f=t[0];for(let m of t)if(m.getBoundingClientRect().top<=d)f=m;else break;let h=a.find(m=>m.hash===`#${f.id}`);for(let m of a)m===h?m.setAttribute("aria-current","location"):m.removeAttribute("aria-current");if(e&&a.length){let m=a[0].getBoundingClientRect(),n=a[a.length-1].getBoundingClientRect();I.classList.toggle("gala-toc--overflowing",n.bottom-m.top>e.clientHeight)}if(h&&e&&e.scrollHeight>e.clientHeight){let m=e.getBoundingClientRect(),n=h.getBoundingClientRect(),s=e.scrollTop+n.top-m.top-(e.clientHeight-n.height)/2;e.scrollTo({top:Math.max(0,s),behavior:"auto"})}},i=()=>{r==null&&(r=requestAnimationFrame(o))};addEventListener("scroll",i,{passive:!0}),addEventListener("resize",i,{passive:!0}),i()}var V=document.querySelector(".gala-action-rail"),Q=document.querySelector("[data-action-dock]");if(V&&Q){let e=a=>{V.classList.toggle("gala-action-rail--integrated",a[0].isIntersecting)};new IntersectionObserver(e,{rootMargin:"0px 0px 18% 0px",threshold:0}).observe(Q)}function J(e,a){let t=a?"Unfollow article":"Follow article";e.setAttribute("aria-pressed",String(a)),e.setAttribute("aria-label",t),e.title=t;let r=e.querySelector("[data-follow-label]");r&&(r.textContent=t)}document.addEventListener("click",async e=>{if(e.target instanceof HTMLDialogElement&&e.target.open){let n=e.target.getBoundingClientRect();if(e.clientX<n.left||e.clientX>n.right||e.clientY<n.top||e.clientY>n.bottom){e.target.close();return}}let a=e.target.closest("[data-gala-embed-load]");if(a){let n=a.closest("[data-gala-embed]"),s=a.dataset.galaEmbedSrc,u=a.dataset.galaEmbedLoad;if(!n||!s||!["youtube","codepen"].includes(u))return;let l=document.createElement("iframe");l.src=s,l.title=u==="youtube"?"YouTube video":"CodePen example",l.loading="eager",l.referrerPolicy="strict-origin-when-cross-origin",l.setAttribute("sandbox","allow-forms allow-popups allow-presentation allow-same-origin allow-scripts"),l.setAttribute("allow",u==="youtube"?"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture; web-share":"fullscreen"),l.setAttribute("allowfullscreen",""),n.replaceChildren(l);return}if(e.target.closest("[data-user-control]")&&!w&&N){O("active");return}let r=e.target.closest("[data-open-dialog]");if(r){let n=document.getElementById(r.dataset.openDialog);n instanceof HTMLDialogElement&&n.showModal();return}let o=e.target.closest("[data-reaction]");if(o){let n=o.closest("[data-engagement-url]");if(!n)return;if(!w)return M({kind:"reaction",region:n,selector:`[data-reaction="${o.dataset.reaction}"]`});let s=o.getAttribute("aria-pressed")!=="true";if(!await X(n,s?"reaction.add":"reaction.remove",{articleId:n.dataset.articleId,reaction:o.dataset.reaction}))return;o.setAttribute("aria-pressed",String(s));return}let i=e.target.closest("[data-follow-article]");if(i){let n=i.closest("[data-engagement-url]");if(!n)return;if(!w)return M({kind:"follow",region:n,selector:"[data-follow-article]"});let s=i.getAttribute("aria-pressed")!=="true";if(!await X(n,s?"follow.add":"follow.remove",{targetType:"articles",targetId:n.dataset.articleId}))return;J(i,s);return}let d=e.target.closest("[data-copy-url]");if(d){let n=d.dataset.copyUrl;if(!window.isSecureContext||!navigator.clipboard?.writeText){L(d);return}try{await navigator.clipboard.writeText(n);let s=d.closest(".gala-share")?.querySelector(".gala-share__status");s&&(s.textContent="Link copied.")}catch{L(d)}return}let f=e.target.closest("[data-native-share]");if(f){if(navigator.share)try{await navigator.share({title:document.title,url:f.dataset.nativeShare})}catch(n){n.name!=="AbortError"&&L(f)}else L(f);return}let h=e.target.closest("[data-copy-code]");if(!h)return;let m=h.closest(".gala-code-block")?.querySelector("code");if(!(!m||!navigator.clipboard?.writeText||!window.isSecureContext))try{await navigator.clipboard.writeText(m.textContent),h.textContent="Copied"}catch{h.textContent="Select code to copy"}});var ce=new Set([...document.querySelectorAll("pre code")].map(e=>e.closest("pre")).filter(Boolean));ce.forEach(e=>{let a=document.createElement("div");a.className="gala-code-block",e.before(a),a.append(e);let t=document.createElement("button");t.type="button",t.dataset.copyCode="",t.textContent="Copy code",t.setAttribute("aria-label","Copy code block"),a.prepend(t)});function le(e){return[["Reactions",Object.values(e.reactions??{}).reduce((t,r)=>t+(Number.isSafeInteger(r)?r:0),0)],["Comments",Number.isSafeInteger(e.comments?.totalCount)?e.comments.totalCount:0],["Views",Number.isSafeInteger(e.views?.count)?e.views.count:0]]}function de(e){return e<1e3?"<1K":new Intl.NumberFormat("en",{notation:"compact",maximumFractionDigits:1}).format(e)}function ue(e,a){let t=a?.data;if(!t||typeof t!="object")throw new TypeError("Engagement data is invalid");for(let[r,o]of le(t))e.querySelectorAll(`[data-engagement-stat="${r.toLowerCase()}"]`).forEach(i=>{i.textContent=de(o),i.closest("div")?.setAttribute("title",`${o} ${r.toLowerCase()}`)});e.querySelector("[data-engagement-snapshot]")?.remove(),e.querySelector(".gala-engagement__placeholder")?.remove()}async function D(e,a="",t=!1,r=!1){let o=e.querySelector("[data-engagement-status]"),i=!!e.querySelector("[data-gala-comments]");try{let d=new URL(e.dataset.engagementUrl);a&&d.searchParams.set("commentsCursor",a);let f=await fetch(d,{headers:{Accept:"application/json"},credentials:"omit",cache:r?"no-store":"default"});if(!f.ok)throw new Error(`Engagement returned HTTP ${f.status}`);let h=await f.json();ue(e,h),o&&!i&&(o.textContent=h.errors?.length?"Some engagement data is temporarily unavailable.":"")}catch{o&&!i&&(o.textContent="Engagement is temporarily unavailable.")}}function me(){let e=new URL(window.location.href).searchParams,a={};for(let t of["utm_source","utm_medium","utm_campaign","utm_content","utm_term"]){let r=e.get(t);r&&[...r].length<=128&&(a[t]=r)}return a}function ge(e){let a=new URL(e.dataset.engagementUrl);a.pathname=a.pathname.replace(/\/engagement$/,"/views"),fetch(a,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({language:document.documentElement.lang||void 0,referrer:document.referrer||void 0,campaign:me()}),credentials:"omit",keepalive:!0}).catch(()=>{})}document.addEventListener("gala-request-sign-in",e=>{w||T||M({kind:e.detail?.kind??"comment"})});var w=null,K=null,q=null,R=new Map,T=null,E=document.querySelector("[data-gala-session-frame]"),x=E?new URL(E.src).origin:null,Z=!1,_=null,N=null,v=null,fe="gala-fedcm-grant=1";function pe(){try{return document.cookie.split(";").some(e=>e.trim()===fe)}catch(e){return console.warn("Gala could not read this publication's FedCM grant marker.",e),!1}}function he(){try{document.cookie="gala-fedcm-grant=1; Max-Age=31536000; Path=/; SameSite=Strict; Secure"}catch(e){console.warn("Gala could not remember this publication's FedCM grant.",e)}}function ye(){try{document.cookie="gala-fedcm-grant=; Max-Age=0; Path=/; SameSite=Strict; Secure"}catch(e){console.warn("Gala could not clear this publication's FedCM grant.",e)}}function ee(){!Z||!E||!_||(E.contentWindow?.postMessage({type:"gala-session-transfer",transferCode:_},x),_=null)}function z(){E?.contentWindow?.postMessage({type:"gala-session-request"},x)}E&&(E.addEventListener("load",z),z());async function O(e){let a=document.querySelector("[data-engagement-status]");if(!N)return!1;if(!globalThis.IdentityCredential||typeof navigator.credentials?.get!="function")return a&&(a.textContent="FedCM is not available in this browser. Use a current browser to sign in."),!1;if(v){if(e==="passive")return!1;v.abort()}let t=new AbortController;v=t;try{let i={providers:[{configURL:"https://api.gala67.com/v1/fedcm/config.json",clientId:new URL(E.src).searchParams.get("siteId")??"",fields:["name","email"],params:{nonce:N}}]};e==="active"&&(i.mode="active");let d=await navigator.credentials.get({identity:i,mediation:e==="active"?"required":"silent",signal:t.signal});return typeof d?.token!="string"?!1:(e==="active"&&he(),_=d.token,ee(),!0)}catch(r){return e==="active"&&r?.name!=="NotAllowedError"&&r?.name!=="AbortError"&&console.error("Gala FedCM sign-in failed.",r),e==="active"&&a&&(a.textContent="Sign-in did not finish. Try again."),!1}finally{v===t&&(v=null)}}function M(e){let a=e.field;T={kind:e.kind,region:e.region,selector:e.selector,draft:a?a.value:null,caret:a?a.selectionStart:null},a&&a.blur(),O("active").then(t=>{t||(T=null)})}function Ee(){let e=T;if(!e||!document.hasFocus())return;let a=e.region?.querySelector(e.selector);if(a){if(T=null,e.kind==="comment"){e.draft!=null&&a.value===""&&(a.value=e.draft),a.focus(),e.caret!=null&&typeof a.setSelectionRange=="function"&&a.setSelectionRange(e.caret,e.caret);return}a.click()}}document.querySelectorAll("[data-engagement-url]").forEach(e=>{D(e),ge(e)});function te(e){return e==="AUTHENTICATION_REQUIRED"||e==="INVALID_BEARER_TOKEN"||e==="REAUTHENTICATION_REQUIRED"?"Sign in again to continue.":e==="ENGAGEMENT_RATE_LIMITED"?"You are posting too quickly; try again shortly.":e==="CONTACT_RATE_LIMITED"?"You are sending too quickly; try again later.":e==="RESOURCE_NOT_FOUND"?"That item is no longer available.":e==="INVALID_ENGAGEMENT_WRITE"||e==="INVALID_CONTACT_SUBMISSION"||e==="INVALID_REQUEST"?"Check your entry and try again.":e==="ACCESS_DENIED"?"That action is not available for this account.":e==="IDEMPOTENCY_CONFLICT"||e==="ENGAGEMENT_STATE_CONFLICT"?"The item changed; reload and try again.":"The action could not be completed. Try again."}function ae(e,a){if(!E||!w)return Promise.reject(new Error("AUTHENTICATION_REQUIRED"));let t=crypto.randomUUID();return new Promise((r,o)=>{let i=setTimeout(()=>{R.delete(t),o(new Error("REQUEST_TIMEOUT"))},1e4);R.set(t,{resolve:d=>{clearTimeout(i),r(d)},reject:d=>{clearTimeout(i),o(d)}}),E.contentWindow.postMessage({type:"gala-engagement-write",requestId:t,operation:e,payload:a},new URL(E.src).origin)})}document.addEventListener("submit",async e=>{let a=e.target.closest("[data-contact-form] form");if(!a)return;e.preventDefault();let t=a.closest("[data-contact-form]"),r=t.querySelector("[data-contact-status]");if(!w){r.textContent="Sign in with the account button before sending.";return}let o=new FormData(a);try{r.textContent="Sending\u2026",await ae("contact.submit",{siteId:t.dataset.siteId,subject:o.get("subject"),message:o.get("message"),website:o.get("website")||null,phone:o.get("phone")||null}),a.reset(),r.textContent="Message sent."}catch(i){r.textContent=te(i.message)}});async function X(e,a,t){let r=e.querySelector("[data-engagement-status]");try{return r&&(r.textContent="Saving\u2026"),await ae(a,t),r&&(r.textContent="Saved."),await D(e,"",!1,!0),!0}catch(o){return r&&(r.textContent=te(o.message)),!1}}E&&window.addEventListener("message",e=>{if(e.origin!==x||e.source!==E.contentWindow)return;if(e.data?.type==="gala-fedcm-sign-out"){ye(),navigator.credentials?.preventSilentAccess?.().catch(o=>{console.error("Gala could not disable silent FedCM access after sign-out.",o)});return}if(e.data?.type==="gala-engagement-result"){let o=R.get(e.data.requestId);if(!o)return;R.delete(e.data.requestId),e.data.ok===!0?o.resolve(e.data.result):o.reject(new Error(e.data.error?.code||"ENGAGEMENT_WRITE_FAILED"));return}if(e.data?.type==="gala-reader-state-result"){if(e.data.requestId!==q||e.data.ok!==!0)return;q=null;let o=new Set(Array.isArray(e.data.state?.reactions)?e.data.state.reactions:[]);document.querySelectorAll("[data-reaction]").forEach(i=>{i.setAttribute("aria-pressed",String(o.has(i.dataset.reaction)))}),document.querySelectorAll("[data-follow-article]").forEach(i=>{let d=e.data.state?.following===!0;J(i,d)});return}if(e.data?.type==="gala-session-height"){let o=Number(e.data.height);Number.isFinite(o)&&o>0&&o<2e3&&(E.height=String(Math.ceil(o)));return}if(e.data?.type!=="gala-session")return;Z=!0,typeof e.data.frameToken=="string"&&(N=e.data.frameToken,document.querySelector("[data-user-control]")?.setAttribute("data-fedcm-ready","true")),_&&ee(),w=e.data.user&&typeof e.data.user.id=="string"?e.data.user:null;let a=document.querySelector("[data-user-control]"),t=w?.displayName;if(a){a.setAttribute("aria-label",t?`Account: ${t}`:"Sign in or view account"),a.title=t?`Account: ${t}`:"Account";let o=a.querySelector("[data-user-label]");o&&(o.textContent=t||"Sign in")}let r=K!==(w?.id??null);if(K=w?.id??null,w){let o=document.querySelector("[data-article-id]");o&&(q=crypto.randomUUID(),E.contentWindow.postMessage({type:"gala-reader-state-request",requestId:q,articleId:o.dataset.articleId},x))}document.querySelectorAll("[data-engagement-url]").forEach(o=>{r&&D(o)}),w&&T&&Ee(),!w&&N&&pe()&&O("passive")});document.querySelectorAll("[data-gala-search]").forEach(e=>{let a=e.querySelector("form"),t=a?.elements.namedItem("q"),r=e.querySelector("[data-search-status]"),o=e.querySelector("[data-search-results]"),i=e.dataset.indexUrl,d,f=s=>String(s??"").normalize("NFKC").toLocaleLowerCase();function h(s,u){o.replaceChildren();for(let l of s){let p=document.createElement("li"),c=document.createElement("article"),y=document.createElement("h2"),b=document.createElement("a");if(b.href=l.url,b.lang=l.language,b.textContent=l.title,y.append(b),c.append(y),l.description){let G=document.createElement("p");G.textContent=l.description,c.append(G)}p.append(c),o.append(p)}r.textContent=`${s.length} result${s.length===1?"":"s"} for \u201C${u}\u201D.`}async function m(s){let u=s.trim();if(u===""){o.replaceChildren(),r.textContent="Enter a search term.";return}r.textContent="Searching\u2026";try{d??=fetch(i,{headers:{Accept:"application/json"}}).then(async c=>{if(!c.ok)throw new Error(`Search index returned HTTP ${c.status}`);let y=await c.json();if(y?.schemaVersion!==1||!Array.isArray(y.entries))throw new TypeError("Search index schema is unsupported");return y.entries});let l=f(u),p=(await d).filter(c=>f([c.title,c.description,c.language,...Array.isArray(c.tags)?c.tags:[],c.body].join(`
|
|
2
|
+
`)).includes(l));h(p,u)}catch{o.replaceChildren(),r.textContent="Search is temporarily unavailable."}}a?.addEventListener("submit",s=>{s.preventDefault();let u=t.value,l=new URL(window.location.href);u.trim()===""?l.searchParams.delete("q"):l.searchParams.set("q",u),window.history.replaceState(null,"",l),m(u)});let n=new URLSearchParams(window.location.search).get("q")??"";t&&(t.value=n),m(n)});var C={value:null},A=document.querySelector("[data-gala-session-frame]"),ne=A?new URL(A.src).origin:null,k=new Map;function re(e){return e==="AUTHENTICATION_REQUIRED"||e==="INVALID_BEARER_TOKEN"||e==="REAUTHENTICATION_REQUIRED"?"Sign in again to continue.":e==="ENGAGEMENT_RATE_LIMITED"?"You are posting too quickly; try again shortly.":e==="CONTACT_RATE_LIMITED"?"You are sending too quickly; try again later.":e==="RESOURCE_NOT_FOUND"?"That item is no longer available.":e==="INVALID_ENGAGEMENT_WRITE"||e==="INVALID_CONTACT_SUBMISSION"||e==="INVALID_REQUEST"?"Check your entry and try again.":e==="ACCESS_DENIED"?"That action is not available for this account.":e==="IDEMPOTENCY_CONFLICT"||e==="ENGAGEMENT_STATE_CONFLICT"?"The item changed; reload and try again.":"The action could not be completed. Try again."}function oe(e,a){if(!A||!C.value)return Promise.reject(new Error("AUTHENTICATION_REQUIRED"));let t=crypto.randomUUID();return new Promise((r,o)=>{let i=setTimeout(()=>{k.delete(t),o(new Error("REQUEST_TIMEOUT"))},1e4);k.set(t,{resolve:d=>{clearTimeout(i),r(d)},reject:d=>{clearTimeout(i),o(d)}}),A.contentWindow.postMessage({type:"gala-engagement-write",requestId:t,operation:e,payload:a},ne)})}function F(e){document.dispatchEvent(new CustomEvent("gala-request-sign-in",{detail:e}))}A&&window.addEventListener("message",e=>{if(e.origin!==ne||e.source!==A.contentWindow)return;if(e.data?.type==="gala-engagement-result"){let t=k.get(e.data.requestId);if(!t)return;k.delete(e.data.requestId),e.data.ok===!0?t.resolve(e.data.result):t.reject(new Error(e.data.error?.code||"ENGAGEMENT_WRITE_FAILED"));return}if(e.data?.type!=="gala-session")return;let a=e.data.user;C.value=a&&typeof a.id=="string"?a:null,window.dispatchEvent(new CustomEvent("gala-session-change"))});var we=5,g=(e,a,t)=>{let r=document.createElement(e);return a&&(r.className=a),t!==void 0&&(r.textContent=t),r};function be(e){let a=new Map;for(let r of e){let o=r.parentCommentId??"";a.has(o)||a.set(o,[]),a.get(o).push(r)}let t=(r,o)=>(a.get(r)??[]).map(i=>({...i,depth:o,replies:t(i.commentId,o+1)}));return t("",0)}function Se(e,a){let t={items:[],cursor:null,total:0,busy:!1,status:"",phase:"loading"},r=/\/v1\/articles\/([^/]+)\/engagement/.exec(a)?.[1]??"",o=e.closest(".gala-conversation")?.querySelector("[data-engagement-status]");async function i(n="",{append:s=!1,fresh:u=!1}={}){let l=new URL(a);n&&l.searchParams.set("commentsCursor",n);let p=await fetch(l,{headers:{Accept:"application/json"},credentials:"omit",cache:u?"no-store":"default"});if(!p.ok)throw new Error(`Comments returned HTTP ${p.status}`);let c=(await p.json())?.data?.comments;if(!c||!Array.isArray(c.items))throw new TypeError("Comment page is invalid");t.items=s?[...t.items,...c.items]:c.items,t.cursor=c.nextCursor??null,Number.isSafeInteger(c.totalCount)&&(t.total=c.totalCount)}async function d(n,s){if(!C.value)return F({kind:"comment"}),!1;t.busy=!0,t.status="",m();try{return await oe(n,s),await i("",{fresh:!0}),!0}catch(u){return t.status=re(u.message),!1}finally{t.busy=!1,m()}}function f(n,s,u){let l=g("form","gala-comment__form"),p=g("textarea");p.rows=3,p.value=s,p.placeholder=n,p.setAttribute("aria-label",n);let c=g("button","","Post");return c.type="submit",c.disabled=t.busy,l.append(p,c),l.addEventListener("submit",async y=>{y.preventDefault();let b=p.value.trim();b&&await u(b)&&(p.value="")}),l}function h(n){let s=g("li","gala-comment");s.dataset.commentId=n.commentId,s.dataset.depth=n.depth;let u=g("p","gala-comment__meta");if(u.append(g("strong","",n.author?.displayName??"[deleted]")),n.createdAt){let l=g("time","",new Date(n.createdAt).toLocaleDateString());l.dateTime=n.createdAt,u.append(l)}if(s.append(u,g("p","gala-comment__body",n.deleted?"[deleted]":n.body)),!n.deleted){let l=g("div","gala-comment-actions");if(n.depth<we){let c=g("button","","Reply");c.type="button",c.dataset.replyComment=n.commentId,c.addEventListener("click",()=>{let y=s.querySelector(":scope > .gala-comment__form");if(y){y.remove();return}l.after(f(`Reply to ${n.author?.displayName??"this comment"}`,"",b=>d("comment.create",{articleId:r,parentCommentId:n.commentId,body:b})))}),l.append(c)}if(C.value&&n.author?.userId===C.value.id){let c=g("button","","Edit");c.type="button",c.dataset.editComment=n.commentId,c.addEventListener("click",()=>l.after(f("Edit your comment",n.body??"",b=>d("comment.edit",{articleId:r,commentId:n.commentId,body:b}))));let y=g("button","","Delete");y.type="button",y.dataset.deleteComment=n.commentId,y.addEventListener("click",()=>d("comment.delete",{articleId:r,commentId:n.commentId})),l.append(c,y)}else{let c=g("button","","Report");c.type="button",c.dataset.reportComment=n.commentId,c.addEventListener("click",()=>d("comment.report",{articleId:r,commentId:n.commentId,reason:"OTHER"})),l.append(c)}s.append(l)}if(n.replies.length){let l=g("ol","gala-comment-replies");l.append(...n.replies.map(h)),s.append(l)}return s}function m(){if(o&&(o.textContent=t.phase==="loading"?"Loading comments\u2026":t.phase==="unavailable"?"Comments are temporarily unavailable.":t.status),t.phase!=="ready"){e.replaceChildren();return}let n=g("section","gala-comments-island");if(n.setAttribute("aria-label","Comments"),n.append(g("p","gala-comments__heading",t.total===1?"1 comment":`${t.total} comments`)),C.value)n.append(f("Add a comment","",s=>d("comment.create",{articleId:r,body:s})));else{let s=g("p","gala-comments__prompt"),u=g("button","","Sign in to join the conversation");u.type="button",u.addEventListener("click",()=>F({kind:"comment"})),s.append(u),n.append(s)}if(!t.items.length)n.append(g("p","gala-comments__empty","No comments yet."));else{let s=g("ol","gala-comments");s.append(...be(t.items).map(h)),n.append(s)}if(t.cursor){let s=g("button","gala-comments__more","Show more comments");s.type="button",s.disabled=t.busy,s.addEventListener("click",async()=>{t.busy=!0,t.status="Loading more comments\u2026",m();try{await i(t.cursor,{append:!0}),t.status=""}catch{t.status="More comments couldn\u2019t be loaded. Try again."}t.busy=!1,m()}),n.append(s)}e.replaceChildren(n)}window.addEventListener("gala-session-change",m),m(),i().then(()=>{t.phase="ready"}).catch(()=>{t.phase="unavailable"}).finally(m)}document.querySelectorAll("[data-gala-comments]").forEach(e=>{let a=e.closest("[data-engagement-url]")?.dataset.engagementUrl;a&&Se(e,a)});})();
|