hyperclayjs 1.26.4 → 1.27.1

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 CHANGED
@@ -86,7 +86,7 @@ import 'hyperclayjs/presets/standard.js';
86
86
 
87
87
  | Module | Size | Description |
88
88
  |--------|------|-------------|
89
- | dialogs | 8.1KB | ask(), consent(), tell(), snippet() dialog functions |
89
+ | dialogs | 8.5KB | ask(), consent(), tell(), snippet() dialog functions |
90
90
  | the-modal | 22.5KB | Full modal window creation system - window.theModal |
91
91
  | toast | 15.8KB | Success/error message notifications, toast(msg, msgType) |
92
92
 
@@ -123,7 +123,7 @@ import 'hyperclayjs/presets/standard.js';
123
123
  | Module | Size | Description |
124
124
  |--------|------|-------------|
125
125
  | file-upload | 11.3KB | File upload with progress |
126
- | live-sync | 11.6KB | Real-time DOM sync across browsers |
126
+ | live-sync | 15.5KB | Real-time DOM sync across browsers |
127
127
  | send-message | 1.3KB | Message sending utility |
128
128
 
129
129
  ### Vendor Libraries (Third-party libraries)
@@ -144,7 +144,7 @@ Standard feature set for most use cases
144
144
 
145
145
  **Modules:** `save-core`, `snapshot`, `save-system`, `unsaved-warning`, `edit-mode-helpers`, `persist`, `option-visibility`, `event-attrs`, `dom-helpers`, `toast`, `save-toast`, `export-to-window`, `view-mode-excludes-edit-modules`
146
146
 
147
- ### Everything (~231.8KB)
147
+ ### Everything (~236.1KB)
148
148
  All available features
149
149
 
150
150
  Includes all available modules across all categories.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hyperclayjs",
3
- "version": "1.26.4",
3
+ "version": "1.27.1",
4
4
  "description": "Modular JavaScript library for building interactive malleable HTML files with Hyperclay",
5
5
  "type": "module",
6
6
  "main": "src/hyperclay.js",
@@ -47,6 +47,20 @@ class LiveSync {
47
47
  // Store handler reference for cleanup
48
48
  this._snapshotHandler = null;
49
49
 
50
+ // High-water mark of server seqs we've seen on this channel (own echoes
51
+ // count too). Server-broadcast payloads carry a monotonic seq
52
+ // (Date.now()-based). We drop anything <= this to guard against rare
53
+ // cases where a stale message lands after a newer one — e.g. buffered
54
+ // replay, alt backend after reconnect, or an own-save echo arriving
55
+ // after a peer's newer broadcast.
56
+ this.lastSeenSeq = 0;
57
+
58
+ // Promise chain used to serialize overlapping applyUpdate() calls.
59
+ // A morph with external scripts returns a Promise; without chaining, two
60
+ // SSE events arriving back-to-back would interleave their morphs on the
61
+ // same DOM.
62
+ this._applyChain = Promise.resolve();
63
+
50
64
  // Callbacks
51
65
  this.onConnect = null;
52
66
  this.onDisconnect = null;
@@ -112,6 +126,8 @@ class LiveSync {
112
126
 
113
127
  // Reset state for new connection
114
128
  this.lastHtml = null;
129
+ this.lastSeenSeq = 0;
130
+ this._applyChain = Promise.resolve();
115
131
 
116
132
  console.log('[LiveSync] Starting for:', this.currentFile);
117
133
  this.connect();
@@ -194,9 +210,24 @@ class LiveSync {
194
210
  return;
195
211
  }
196
212
 
197
- const { html, sender } = data;
213
+ const { html, sender, seq } = data;
198
214
 
199
- // Ignore own changes
215
+ // Staleness check runs FIRST — compared against the high-water mark of
216
+ // seqs we've seen (own echoes count too, see below). `seq` is optional
217
+ // for back-compat with older server builds that don't stamp it.
218
+ if (typeof seq === 'number' && seq <= this.lastSeenSeq) {
219
+ this._log(`Dropping stale message: seq=${seq}, lastSeen=${this.lastSeenSeq}`);
220
+ return;
221
+ }
222
+
223
+ // Advance the watermark before the sender filter so that our own save
224
+ // echoes count toward "seen". Without this, a later buffered/replayed
225
+ // peer message with a smaller seq could rewind us past our local edit.
226
+ if (typeof seq === 'number') {
227
+ this.lastSeenSeq = seq;
228
+ }
229
+
230
+ // Ignore own changes — already reflected in the DOM, nothing to morph
200
231
  if (sender === this.clientId) {
201
232
  this._log('Ignoring own message (sender matches clientId)');
202
233
  return;
@@ -208,9 +239,9 @@ class LiveSync {
208
239
  return;
209
240
  }
210
241
 
211
- this._log(`Received update from: ${sender} (my clientId: ${this.clientId})`);
212
- this.applyUpdate(html);
213
- if (this.onUpdate) this.onUpdate({ html, sender });
242
+ this._log(`Received update from: ${sender} (my clientId: ${this.clientId}, seq=${seq})`);
243
+ this.applyUpdate(html, seq);
244
+ if (this.onUpdate) this.onUpdate({ html, sender, seq });
214
245
  };
215
246
 
216
247
  // Native EventSource auto-reconnects on transient errors
@@ -285,13 +316,48 @@ class LiveSync {
285
316
  }
286
317
 
287
318
  /**
288
- * Apply an update received from the server
289
- * Morphs the entire document (head and body)
319
+ * Apply an update received from the server.
320
+ * Morphs the entire document (head and body).
321
+ *
322
+ * Serialized via a promise chain so concurrent SSE events don't produce
323
+ * overlapping morphs (morph can return a Promise when external scripts load).
324
+ *
325
+ * @param {string} html - Full document HTML
326
+ * @param {number} [seq] - Optional monotonic seq from the server
327
+ * @returns {Promise<void>}
328
+ */
329
+ applyUpdate(html, seq) {
330
+ // Serialize concurrent updates onto a single promise chain. `.catch` on
331
+ // the combined result both logs the failure (so it isn't a silent
332
+ // unhandled rejection) AND heals the chain so subsequent updates aren't
333
+ // blocked by it. `_applyChain` and the returned promise are the same
334
+ // caught promise — callers that fire-and-forget are safe.
335
+ const result = this._applyChain
336
+ .then(() => this._doApplyUpdate(html, seq))
337
+ .catch((err) => {
338
+ console.error('[LiveSync] applyUpdate failed:', err);
339
+ });
340
+ this._applyChain = result;
341
+ return result;
342
+ }
343
+
344
+ /**
345
+ * Actual morph work. Do not call directly — use applyUpdate() so calls
346
+ * serialize.
347
+ * @param {string} html
348
+ * @param {number} [seq]
349
+ * @returns {Promise<void>}
290
350
  */
291
- applyUpdate(html) {
351
+ async _doApplyUpdate(html, seq) {
292
352
  this._log('applyUpdate - pausing mutations and morphing');
293
353
  this.isPaused = true;
294
- this.lastHtml = html;
354
+
355
+ // Preserve scroll position: a remote edit that inserts or removes content
356
+ // above the viewport would otherwise cause a visible jump. Capturing here
357
+ // and restoring after the morph keeps the viewport stable. Browser
358
+ // scroll-clamping handles the case where the document is now shorter.
359
+ const scrollX = window.scrollX;
360
+ const scrollY = window.scrollY;
295
361
 
296
362
  // Pause mutation observer so morph doesn't trigger autosave
297
363
  Mutation.pause();
@@ -300,19 +366,36 @@ class LiveSync {
300
366
  const parser = new DOMParser();
301
367
  const newDoc = parser.parseFromString(html, 'text/html');
302
368
 
303
- // Morph entire document (html element)
304
- HyperMorph.morph(document.documentElement, newDoc.documentElement, {
305
- morphStyle: 'outerHTML',
306
- ignoreActiveValue: true,
307
- head: { style: 'merge' },
308
- scripts: { handle: true, matchMode: 'smart' }
309
- });
310
-
311
- this._log('applyUpdate - morph complete, resuming mutations');
312
- Mutation.resume();
313
- // Defer past microtask boundary MutationObserver callbacks and any async
314
- // morph side-effects fire before this, so isPaused catches stray snapshots
315
- setTimeout(() => { this.isPaused = false; }, 0);
369
+ try {
370
+ // Morph entire document. We MUST await — HyperMorph.morph returns a
371
+ // Promise when `scripts: { handle: true }` needs to wait for external
372
+ // scripts to load. If we don't await, Mutation.resume() fires before
373
+ // late-loading scripts execute, and any DOM mutations they trigger look
374
+ // like user edits the receiving tab rebroadcasts them (feedback loop).
375
+ await HyperMorph.morph(document.documentElement, newDoc.documentElement, {
376
+ morphStyle: 'outerHTML',
377
+ ignoreActiveValue: true,
378
+ head: { style: 'merge' },
379
+ scripts: { handle: true, matchMode: 'smart' }
380
+ });
381
+
382
+ // Restore viewport. Done after morph so layout has settled.
383
+ window.scrollTo(scrollX, scrollY);
384
+
385
+ // Only mark lastHtml after a successful morph so that a failed apply
386
+ // doesn't desync our state and cause the next outbound save to be
387
+ // mistakenly skipped as "unchanged". Note: lastSeenSeq is advanced at
388
+ // receive time (in onmessage) so the staleness check covers own-save
389
+ // echoes even when they don't reach this point.
390
+ this.lastHtml = html;
391
+ } finally {
392
+ this._log('applyUpdate - morph complete, resuming mutations');
393
+ Mutation.resume();
394
+ // Defer past microtask boundary — MutationObserver callbacks fire before
395
+ // this, so isPaused catches any stray snapshots from the morph itself.
396
+ await new Promise((resolve) => setTimeout(resolve, 0));
397
+ this.isPaused = false;
398
+ }
316
399
  }
317
400
 
318
401
  /**
package/src/hyperclay.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * DO NOT EDIT THIS FILE DIRECTLY — it is generated from build/hyperclay.template.js
3
3
  *
4
- * HyperclayJS v1.26.4 - Minimal Browser-Native Loader
4
+ * HyperclayJS v1.27.1 - Minimal Browser-Native Loader
5
5
  *
6
6
  * Modules auto-init when imported (no separate init call needed).
7
7
  * Include `export-to-window` feature to export to window.hyperclay.
package/src/ui/prompts.js CHANGED
@@ -21,30 +21,31 @@ function createModal(promptText, yesCallback, extraContent = "", includeInput =
21
21
 
22
22
  const promise = new Promise((resolve, reject) => {
23
23
  themodal.onYes(() => {
24
- try {
25
- if (includeInput) {
26
- const promptResult = document.querySelector(".micromodal__input").value;
27
- if (promptResult) {
28
- if (yesCallback) yesCallback(promptResult);
29
- resolve(promptResult);
30
- return true; // Allow modal to close
31
- }
32
- } else {
33
- if (yesCallback) yesCallback();
34
- resolve();
35
- return true; // Allow modal to close
24
+ let promptResult;
25
+ if (includeInput) {
26
+ promptResult = document.querySelector(".micromodal__input").value;
27
+ if (!promptResult) return false; // keep modal open on empty input
28
+ }
29
+ // Run the validation callback synchronously so a throw can keep the
30
+ // modal open (callers rely on this — e.g. delete-site confirms by
31
+ // throwing when the typed name doesn't match).
32
+ if (yesCallback) {
33
+ try {
34
+ yesCallback(promptResult);
35
+ } catch (err) {
36
+ toast(err.message || 'An error occurred', 'error');
37
+ return false; // keep modal open, user can retry
36
38
  }
37
- } catch (error) {
38
- // Show error message as toast
39
- toast(error.message || 'An error occurred', 'error');
40
- // Keep modal open - don't reject or resolve
41
- // User can try again
42
- return false; // Prevent modal from closing
43
39
  }
40
+ // Defer resolve so downstream .then() handlers don't fire inside this
41
+ // modal's onYes loop — themodal is a singleton, and chained ask()/
42
+ // consent() calls need a clean themodal to set up their state.
43
+ setTimeout(() => resolve(promptResult), 0);
44
+ return true; // allow modal to close
44
45
  });
45
46
 
46
47
  themodal.onNo = () => {
47
- reject();
48
+ setTimeout(reject, 0);
48
49
  };
49
50
  });
50
51
 
@@ -95,12 +96,12 @@ export function tell(promptText, ...content) {
95
96
 
96
97
  const promise = new Promise((resolve, reject) => {
97
98
  themodal.onYes(() => {
98
- resolve();
99
+ setTimeout(resolve, 0);
99
100
  return true;
100
101
  });
101
102
 
102
103
  themodal.onNo = () => {
103
- reject();
104
+ setTimeout(reject, 0);
104
105
  };
105
106
  });
106
107
 
@@ -159,22 +160,22 @@ export function snippet(title, content, extraContent = '') {
159
160
  }, 0);
160
161
 
161
162
  themodal.onYes(() => {
162
- // Clean up the event listener
163
+ // Clean up the event listener synchronously — the DOM may be torn down
164
+ // before our deferred resolve fires otherwise.
163
165
  const modalContainer = document.querySelector('.micromodal-parent');
164
166
  if (modalContainer) {
165
167
  modalContainer.removeEventListener('click', handleCopy);
166
168
  }
167
- resolve();
169
+ setTimeout(resolve, 0);
168
170
  return true;
169
171
  });
170
172
 
171
173
  themodal.onNo = () => {
172
- // Clean up the event listener
173
174
  const modalContainer = document.querySelector('.micromodal-parent');
174
175
  if (modalContainer) {
175
176
  modalContainer.removeEventListener('click', handleCopy);
176
177
  }
177
- resolve();
178
+ setTimeout(resolve, 0);
178
179
  };
179
180
  });
180
181
 
@@ -1,4 +1,4 @@
1
- var HyperMorph=(()=>{var V=Object.defineProperty;var K=Object.getOwnPropertyDescriptor;var G=Object.getOwnPropertyNames;var Y=Object.prototype.hasOwnProperty;var J=(s,o)=>{for(var u in o)V(s,u,{get:o[u],enumerable:!0})},Q=(s,o,u,d)=>{if(o&&typeof o=="object"||typeof o=="function")for(let h of G(o))!Y.call(s,h)&&h!==u&&V(s,h,{get:()=>o[h],enumerable:!(d=K(o,h))||d.enumerable});return s};var X=s=>Q(V({},"__esModule",{value:!0}),s);var pe={};J(pe,{HyperMorph:()=>$,default:()=>he,defaults:()=>fe,morph:()=>de});var F={includeClasses:!0,includeAttributes:["href","src","name","type","role","aria-label","alt","title"],excludeAttributePrefixes:["data-morph-","data-hyper-","data-im-"],textHintLength:64,excludeIds:!0,maxPathDepth:4,landmarks:["HEADER","NAV","MAIN","ASIDE","FOOTER","SECTION","ARTICLE"],weights:{signature:100,pathSegment:10,textMatch:20,textMismatch:25,uniqueCandidate:50,positionPenalty:1},minConfidence:101};function Z(s){let o=5381;for(let u=0;u<s.length;u++)o=(o<<5)+o^s.charCodeAt(u);return Math.abs(o).toString(36)}function ee(s){if(s.classList&&s.classList.length>0)return Array.from(s.classList).sort().join(" ");let o=s.getAttribute?.("class");return o?o.split(/\s+/).filter(Boolean).sort().join(" "):""}function te(s,o){let u=[];for(let d of s.attributes||[]){let h=d.name;h==="id"||h==="class"||o.excludeAttributePrefixes.some(y=>h.startsWith(y))||o.includeAttributes.includes(h)&&u.push(`${h}=${d.value}`)}return u.sort().join("|")}function ne(s,o){return(s.textContent||"").replace(/\s+/g," ").trim().slice(0,o.textHintLength)}function re(s,o){let u=[s.tagName];return o.includeClasses&&u.push(ee(s)),u.push(te(s,o)),Z(u.join("|"))}function se(s){let o=s.tagName,u=1,d=s.previousElementSibling;for(;d;)d.tagName===o&&u++,d=d.previousElementSibling;return u}function ie(s,o){return s.id||s.getAttribute?.("role")?!0:o.landmarks.includes(s.tagName)}function ae(s){if(s.id)return`#${s.id}`;let o=s.getAttribute?.("role");return o?`@${o}`:s.tagName}function oe(s,o){let u=[],d=s;for(;d&&d.tagName&&u.length<o.maxPathDepth;){let h=`${d.tagName}:${se(d)}`;if(u.unshift(h),d!==s&&ie(d,o)){u.unshift(ae(d));break}d=d.parentElement}return u}function ue(s,o){let u=0,d=s.length-1,h=o.length-1;for(;d>=0&&h>=0&&s[d]===o[h];)u++,d--,h--;return u}function C(s,o,u){if(u.has(s))return u.get(s);let d={signature:re(s,o),path:oe(s,o),textHint:ne(s,o)};return u.set(s,d),d}function z(s,o,u,d){if(d.has(s))return d.get(s);let h=new Map,y=s.querySelectorAll("*"),H=0;for(let S of y){let I=C(S,o,u);I.domIndex=H++,h.has(I.signature)||h.set(I.signature,[]),h.get(I.signature).push(S)}return d.set(s,h),h}function ce(s,o,u){u.delete(s),o.delete(s);let d=s.querySelectorAll("*");for(let h of d)o.delete(h)}function q(s,o,u,d,h){let y=C(s,u,d),H=C(o,u,d),S=u.weights,I={},E=0;if(y.signature!==H.signature)return{score:0,breakdown:{rejected:"signature mismatch"}};E+=S.signature,I.signature=S.signature;let T=ue(y.path,H.path)*S.pathSegment;E+=T,I.path=T;let k=!0;if(y.textHint&&H.textHint?y.textHint===H.textHint?(E+=S.textMatch,I.text=S.textMatch):(E-=S.textMismatch,I.text=-S.textMismatch,k=!1):y.textHint!==H.textHint&&(E-=S.textMismatch,I.text=-S.textMismatch,k=!1),h.candidateCount===1&&k&&(E+=S.uniqueCandidate,I.unique=S.uniqueCandidate),typeof y.domIndex=="number"&&typeof H.domIndex=="number"){let N=Math.abs(y.domIndex-H.domIndex),R=Math.min(N*S.positionPenalty,20);E-=R,I.drift=-R}return{score:E,breakdown:I}}function D(s,o,u,d,h){if(u.excludeIds&&s.id)return null;let y=z(o,u,d,h),H=C(s,u,d);if(typeof H.domIndex!="number"){let k=0,N=s.previousElementSibling;for(;N;)k++,N=N.previousElementSibling;H.domIndex=k}let S=y.get(H.signature)||[],I=u.excludeIds?S.filter(k=>!k.id):S;if(I.length===0)return null;let E=null,x=0,T=null;for(let k of I){let{score:N,breakdown:R}=q(s,k,u,d,{candidateCount:I.length});N>x&&(x=N,E=k,T=R)}return x<u.minConfidence?null:{element:E,confidence:x,breakdown:T}}function W(s,o,u,d,h){let y=o.querySelectorAll("*"),H=z(s,u,d,h),S=0;for(let T of y){let k=C(T,u,d);k.domIndex=S++}let I=[];for(let T of y){if(u.excludeIds&&T.id)continue;let k=C(T,u,d),N=H.get(k.signature)||[],R=u.excludeIds?N.filter(B=>!B.id):N;for(let B of R){let{score:l,breakdown:A}=q(T,B,u,d,{candidateCount:R.length});l>=u.minConfidence&&I.push({newEl:T,oldEl:B,score:l,breakdown:A})}}I.sort((T,k)=>k.score-T.score);let E=new Map,x=new Set;for(let{newEl:T,oldEl:k}of I)E.has(T)||x.has(k)||(E.set(T,k),x.add(k));return E}function P(s,o,u,d){let h=C(s,u,d),y=C(o,u,d),{score:H,breakdown:S}=q(s,o,u,d,{candidateCount:1});return{matches:H>=u.minConfidence,score:H,breakdown:S,newMeta:{signature:h.signature,path:h.path,textHint:h.textHint},oldMeta:{signature:y.signature,path:y.path,textHint:y.textHint}}}function U(s={}){let o={...F,...s,weights:{...F.weights,...s.weights}},u=new WeakMap,d=new WeakMap;return{findMatch:(h,y)=>D(h,y,o,u,d),computeMatches:(h,y)=>W(h,y,o,u,d),explain:(h,y)=>P(h,y,o,u),invalidate:h=>ce(h,u,d),session:()=>{let h=new WeakMap,y=new WeakMap;return{findMatch:(H,S)=>D(H,S,o,h,y),computeMatches:(H,S)=>W(H,S,o,h,y),explain:(H,S)=>P(H,S,o,h)}},getConfig:()=>({...o})}}var le=U(),$=(function(){"use strict";let s=()=>{};function o(l){if(!(l instanceof Element))return!1;if(l.hasAttribute("save-ignore"))return!0;if(l.tagName==="LINK"||l.tagName==="SCRIPT"){let A=l.getAttribute("src")||l.getAttribute("href")||"";if(A.startsWith("chrome-extension://")||A.startsWith("moz-extension://")||A.startsWith("safari-web-extension://"))return!0}return!1}function u(l,A){if(A!=="smart")return l.outerHTML;let p=l.getAttribute("src"),v=l.getAttribute("type")||"text/javascript";if(p)try{let b=new URL(p,window.location.href);return`ext:${v}:${b.origin}${b.pathname}`}catch{return`ext:${v}:${p}`}else{let b=l.textContent.trim(),g=5381;for(let r=0;r<b.length;r++)g=(g<<5)+g^b.charCodeAt(r);return`inline:${v}:${Math.abs(g).toString(36)}`}}let d={morphStyle:"outerHTML",callbacks:{beforeNodeAdded:s,afterNodeAdded:s,beforeNodeMorphed:s,afterNodeMorphed:s,beforeNodeRemoved:s,afterNodeRemoved:s,beforeAttributeUpdated:s},head:{style:"merge",shouldPreserve:l=>l.getAttribute("im-preserve")==="true",shouldReAppend:l=>l.getAttribute("im-re-append")==="true",shouldRemove:s,afterHeadMorphed:s},scripts:{handle:!1,matchMode:"outerHTML",shouldPreserve:l=>l.getAttribute("im-preserve")==="true",shouldReAppend:l=>l.getAttribute("im-re-append")==="true",shouldRemove:s,afterScriptsHandled:s},restoreFocus:!0},h={computeMatches(l,A){let{computeMatches:p}=le.session();return p(l,A)}};function y(l,A,p={}){l=R(l);let v=B(A),b=N(l,v,p),g=b.scripts.matchMode,r=new Set(Array.from(l.querySelectorAll("script")).map(n=>u(n,g))),c=S(b,()=>x(b,l,v,n=>n.morphStyle==="innerHTML"?(I(n,l,v),Array.from(l.childNodes)):H(n,l,v)));b.pantry.remove();let e=k(l,r,b);return e.length>0?c instanceof Promise?c.then(n=>Promise.all(e).then(()=>n)):Promise.all(e).then(()=>c):c}function H(l,A,p){let v=B(A);return I(l,v,p,A,A.nextSibling),Array.from(v.childNodes)}function S(l,A){if(!l.config.restoreFocus)return A();let p=document.activeElement;if(!(p instanceof HTMLInputElement||p instanceof HTMLTextAreaElement))return A();let{id:v,selectionStart:b,selectionEnd:g}=p,r=A();return v&&v!==document.activeElement?.getAttribute("id")&&(p=l.target.querySelector(`[id="${v}"]`),p?.focus()),p&&!p.selectionEnd&&g!=null&&p.setSelectionRange(b,g),r}let I=(function(){function l(e,n,i,t=null,a=null){n instanceof HTMLTemplateElement&&i instanceof HTMLTemplateElement&&(n=n.content,i=i.content),t||=n.firstChild;for(let f of i.childNodes){if(o(f))continue;if(t&&t!=a){let M=p(e,f,t,a);if(M){M!==t&&b(e,t,M),E(M,f,e),t=M.nextSibling;continue}}if(f instanceof Element){let M=f.getAttribute("id");if(e.persistentIds.has(M)){let w=g(n,M,t,e);E(w,f,e),t=w.nextSibling;continue}if(!e.idMap.has(f)){let w=e.hyperMatches.get(f);if(w&&!e.idMap.has(w)){c(n,w,t),E(w,f,e),t=w.nextSibling;continue}}}let m=A(n,f,t,e);m&&(t=m.nextSibling)}for(;t&&t!=a;){let f=t;t=t.nextSibling,o(f)||v(e,f)}}function A(e,n,i,t){if(t.callbacks.beforeNodeAdded(n)===!1)return null;if(t.idMap.has(n)){let a=document.createElement(n.tagName);return e.insertBefore(a,i),E(a,n,t),t.callbacks.afterNodeAdded(a),a}else{let a=document.importNode(n,!0);return e.insertBefore(a,i),t.callbacks.afterNodeAdded(a),a}}let p=(function(){function e(t,a,f,m){let M=a instanceof Element&&!t.idMap.has(a)?t.hyperMatches.get(a):null,w=null,O=a.nextSibling,j=0,L=f;for(;L&&L!=m;){if(i(L,a)){if(n(t,L,a)||L===M&&!t.idMap.has(L))return L;if(w===null){let _=L instanceof Element&&t.hyperMatchedOldElements.has(L);!t.idMap.has(L)&&!_&&(w=L)}}if(w===null&&O&&i(L,O)&&(j++,O=O.nextSibling,j>=2&&(w=void 0)),t.activeElementAndParents.includes(L))break;L=L.nextSibling}return w||null}function n(t,a,f){let m=t.idMap.get(a),M=t.idMap.get(f);if(!M||!m)return!1;for(let w of m)if(M.has(w))return!0;return!1}function i(t,a){let f=t,m=a;return f.nodeType===m.nodeType&&f.tagName===m.tagName&&(!f.getAttribute?.("id")||f.getAttribute?.("id")===m.getAttribute?.("id"))}return e})();function v(e,n){let i=n instanceof Element&&e.hyperMatchedOldElements.has(n)&&!e.idMap.has(n);if(e.idMap.has(n)||i)c(e.pantry,n,null);else{if(e.callbacks.beforeNodeRemoved(n)===!1)return;n.parentNode?.removeChild(n),e.callbacks.afterNodeRemoved(n)}}function b(e,n,i){let t=n;for(;t&&t!==i;){let a=t;t=t.nextSibling,o(a)||v(e,a)}return t}function g(e,n,i,t){let a=t.target.getAttribute?.("id")===n&&t.target||t.target.querySelector(`[id="${n}"]`)||t.pantry.querySelector(`[id="${n}"]`);return r(a,t),c(e,a,i),a}function r(e,n){let i=e.getAttribute("id");for(;e=e.parentNode;){let t=n.idMap.get(e);t&&(t.delete(i),t.size||n.idMap.delete(e))}}function c(e,n,i){if(e.moveBefore)try{e.moveBefore(n,i)}catch{e.insertBefore(n,i)}else e.insertBefore(n,i)}return l})(),E=(function(){function l(r,c,e){return e.ignoreActive&&r===document.activeElement?null:(e.callbacks.beforeNodeMorphed(r,c)===!1||(r instanceof HTMLHeadElement&&e.head.ignore||(r instanceof HTMLHeadElement&&e.head.style!=="morph"?T(r,c,e):(A(r,c,e),g(r,e)||I(e,r,c))),e.callbacks.afterNodeMorphed(r,c)),r)}function A(r,c,e){let n=c.nodeType;if(n===1){let i=r,t=c,a=i.attributes,f=t.attributes;for(let m of f)b(m.name,i,"update",e)||i.getAttribute(m.name)!==m.value&&i.setAttribute(m.name,m.value);for(let m=a.length-1;0<=m;m--){let M=a[m];if(M&&!t.hasAttribute(M.name)){if(b(M.name,i,"remove",e))continue;i.removeAttribute(M.name)}}g(i,e)||p(i,t,e)}(n===8||n===3)&&r.nodeValue!==c.nodeValue&&(r.nodeValue=c.nodeValue)}function p(r,c,e){if(r instanceof HTMLInputElement&&c instanceof HTMLInputElement&&c.type!=="file"){let n=c.value,i=r.value;v(r,c,"checked",e),v(r,c,"disabled",e),c.hasAttribute("value")?i!==n&&(b("value",r,"update",e)||(r.setAttribute("value",n),r.value=n)):b("value",r,"remove",e)||(r.value="",r.removeAttribute("value"))}else if(r instanceof HTMLOptionElement&&c instanceof HTMLOptionElement)v(r,c,"selected",e);else if(r instanceof HTMLTextAreaElement&&c instanceof HTMLTextAreaElement){let n=c.value,i=r.value;if(b("value",r,"update",e))return;n!==i&&(r.value=n),r.firstChild&&r.firstChild.nodeValue!==n&&(r.firstChild.nodeValue=n)}}function v(r,c,e,n){let i=c[e],t=r[e];if(i!==t){let a=b(e,r,"update",n);a||(r[e]=c[e]),i?a||r.setAttribute(e,""):b(e,r,"remove",n)||r.removeAttribute(e)}}function b(r,c,e,n){return r==="value"&&n.ignoreActiveValue&&c===document.activeElement?!0:n.callbacks.beforeAttributeUpdated(r,c,e)===!1}function g(r,c){return!!c.ignoreActiveValue&&r===document.activeElement&&r!==document.body}return l})();function x(l,A,p,v){if(l.head.block){let b=A.querySelector("head"),g=p.querySelector("head");if(b&&g){let r=T(b,g,l);return Promise.all(r).then(()=>{let c=Object.assign(l,{head:{block:!1,ignore:!0}});return v(c)})}}return v(l)}function T(l,A,p){let v=[],b=[],g=[],r=[],c=p.scripts.matchMode,e=t=>{if(t.tagName==="SCRIPT")return u(t,c);if(t.tagName==="LINK"&&c==="smart"){let a=t.getAttribute("href");if(a)try{let f=new URL(a,window.location.href);return`link:${t.getAttribute("rel")||""}:${f.origin}${f.pathname}`}catch{}}return t.outerHTML},n=new Map;for(let t of A.children)o(t)||n.set(e(t),t);for(let t of l.children){let a=e(t),f=n.has(a),m=p.head.shouldReAppend(t),M=p.head.shouldPreserve(t);f||M?m?b.push(t):(n.delete(a),g.push(t)):p.head.style==="append"?m&&(b.push(t),r.push(t)):p.head.shouldRemove(t)!==!1&&!o(t)&&b.push(t)}r.push(...n.values());let i=[];for(let t of r){let a=document.createRange().createContextualFragment(t.outerHTML).firstChild;if(p.callbacks.beforeNodeAdded(a)!==!1){if("href"in a&&a.href||"src"in a&&a.src){let f,m=new Promise(function(M){f=M});a.addEventListener("load",function(){f()}),i.push(m)}l.appendChild(a),p.callbacks.afterNodeAdded(a),v.push(a)}}for(let t of b)p.callbacks.beforeNodeRemoved(t)!==!1&&(l.removeChild(t),p.callbacks.afterNodeRemoved(t));return p.head.afterHeadMorphed(l,{added:v,kept:g,removed:b}),i}function k(l,A,p){if(!p.scripts.handle)return[];let v=[],b=[],g=[],r=[],c=p.scripts.matchMode,e=Array.from(l.querySelectorAll("script"));for(let i of e){let t=u(i,c),a=A.has(t),f=p.scripts.shouldPreserve(i),m=p.scripts.shouldReAppend(i);a||f?m?(b.push(i),r.push(i)):g.push(i):r.push(i)}for(let i of A){let t=e.some(a=>a.outerHTML===i)}let n=[];for(let i of r){if(p.callbacks.beforeNodeAdded(i)===!1)continue;let t=document.createRange().createContextualFragment(i.outerHTML).firstChild;if(t.src){let a,f=new Promise(function(m){a=m});t.addEventListener("load",function(){a()}),t.addEventListener("error",function(){a()}),n.push(f)}i.replaceWith(t),p.callbacks.afterNodeAdded(t),v.push(t)}return p.scripts.afterScriptsHandled(l,{added:v,kept:g,removed:b}),n}let N=(function(){function l(e,n,i){let{persistentIds:t,idMap:a}=r(e,n),f=h.computeMatches(e,n),m=new Set;for(let O of f.values())m.add(O);let M=A(i),w=M.morphStyle||"outerHTML";if(!["innerHTML","outerHTML"].includes(w))throw`Do not understand how to morph style ${w}`;return{target:e,newContent:n,config:M,morphStyle:w,ignoreActive:M.ignoreActive,ignoreActiveValue:M.ignoreActiveValue,restoreFocus:M.restoreFocus,idMap:a,persistentIds:t,hyperMatches:f,hyperMatchedOldElements:m,pantry:p(),activeElementAndParents:v(e),callbacks:M.callbacks,head:M.head,scripts:M.scripts}}function A(e){let n=Object.assign({},d);return Object.assign(n,e),n.callbacks=Object.assign({},d.callbacks,e.callbacks),n.head=Object.assign({},d.head,e.head),n.scripts=Object.assign({},d.scripts,e.scripts),n}function p(){let e=document.createElement("div");return e.hidden=!0,document.body.insertAdjacentElement("afterend",e),e}function v(e){let n=[],i=document.activeElement;if(i?.tagName!=="BODY"&&e.contains(i))for(;i&&(n.push(i),i!==e);)i=i.parentElement;return n}function b(e){let n=Array.from(e.querySelectorAll("[id]"));return e.getAttribute?.("id")&&n.push(e),n}function g(e,n,i,t){for(let a of t){let f=a.getAttribute("id");if(n.has(f)){let m=a;for(;m;){let M=e.get(m);if(M==null&&(M=new Set,e.set(m,M)),M.add(f),m===i)break;m=m.parentElement}}}}function r(e,n){let i=b(e),t=b(n),a=c(i,t),f=new Map;g(f,a,e,i);let m=n.__hyperMorphRoot||n;return g(f,a,m,t),{persistentIds:a,idMap:f}}function c(e,n){let i=new Set,t=new Map;for(let{id:f,tagName:m}of e)t.has(f)?i.add(f):t.set(f,m);let a=new Set;for(let{id:f,tagName:m}of n)a.has(f)?i.add(f):t.get(f)===m&&a.add(f);for(let f of i)a.delete(f);return a}return l})(),{normalizeElement:R,normalizeParent:B}=(function(){let l=new WeakSet;function A(g){return g instanceof Document?g.documentElement:g}function p(g){if(g==null)return document.createElement("div");if(typeof g=="string")return p(b(g));if(l.has(g))return g;if(g instanceof Node){if(g.parentNode)return new v(g);{let r=document.createElement("div");return r.append(g),r}}else{let r=document.createElement("div");for(let c of[...g])r.append(c);return r}}class v{constructor(r){this.originalNode=r,this.realParentNode=r.parentNode,this.previousSibling=r.previousSibling,this.nextSibling=r.nextSibling}get childNodes(){let r=[],c=this.previousSibling?this.previousSibling.nextSibling:this.realParentNode.firstChild;for(;c&&c!=this.nextSibling;)r.push(c),c=c.nextSibling;return r}querySelectorAll(r){return this.childNodes.reduce((c,e)=>{if(e instanceof Element){e.matches(r)&&c.push(e);let n=e.querySelectorAll(r);for(let i=0;i<n.length;i++)c.push(n[i])}return c},[])}insertBefore(r,c){return this.realParentNode.insertBefore(r,c)}moveBefore(r,c){return this.realParentNode.moveBefore(r,c)}get __hyperMorphRoot(){return this.originalNode}}function b(g){let r=new DOMParser,c=g.replace(/<svg(\s[^>]*>|>)([\s\S]*?)<\/svg>/gim,"");if(c.match(/<\/html>/)||c.match(/<\/head>/)||c.match(/<\/body>/)){let e=r.parseFromString(g,"text/html");if(c.match(/<\/html>/))return l.add(e),e;{let n=e.firstChild;return n&&l.add(n),n}}else{let n=r.parseFromString("<body><template>"+g+"</template></body>","text/html").body.querySelector("template").content;return l.add(n),n}}return{normalizeElement:A,normalizeParent:p}})();return{morph:y,defaults:d}})();var de=$.morph,fe=$.defaults,he=$;return X(pe);})();
1
+ var HyperMorph=(()=>{var V=Object.defineProperty;var K=Object.getOwnPropertyDescriptor;var G=Object.getOwnPropertyNames;var Y=Object.prototype.hasOwnProperty;var J=(s,o)=>{for(var u in o)V(s,u,{get:o[u],enumerable:!0})},Q=(s,o,u,d)=>{if(o&&typeof o=="object"||typeof o=="function")for(let h of G(o))!Y.call(s,h)&&h!==u&&V(s,h,{get:()=>o[h],enumerable:!(d=K(o,h))||d.enumerable});return s};var X=s=>Q(V({},"__esModule",{value:!0}),s);var pe={};J(pe,{HyperMorph:()=>$,default:()=>he,defaults:()=>fe,morph:()=>de});var F={includeClasses:!0,includeAttributes:["href","src","name","type","role","aria-label","alt","title"],excludeAttributePrefixes:["data-morph-","data-hyper-","data-im-"],textHintLength:64,excludeIds:!0,maxPathDepth:4,landmarks:["HEADER","NAV","MAIN","ASIDE","FOOTER","SECTION","ARTICLE"],weights:{signature:100,pathSegment:10,textMatch:20,textMismatch:25,uniqueCandidate:50,positionPenalty:1},minConfidence:101};function Z(s){let o=5381;for(let u=0;u<s.length;u++)o=(o<<5)+o^s.charCodeAt(u);return Math.abs(o).toString(36)}function ee(s){if(s.classList&&s.classList.length>0)return Array.from(s.classList).sort().join(" ");let o=s.getAttribute?.("class");return o?o.split(/\s+/).filter(Boolean).sort().join(" "):""}function te(s,o){let u=[];for(let d of s.attributes||[]){let h=d.name;h==="id"||h==="class"||o.excludeAttributePrefixes.some(y=>h.startsWith(y))||o.includeAttributes.includes(h)&&u.push(`${h}=${d.value}`)}return u.sort().join("|")}function ne(s,o){return(s.textContent||"").replace(/\s+/g," ").trim().slice(0,o.textHintLength)}function re(s,o){let u=[s.tagName];return o.includeClasses&&u.push(ee(s)),u.push(te(s,o)),Z(u.join("|"))}function se(s){let o=s.tagName,u=1,d=s.previousElementSibling;for(;d;)d.tagName===o&&u++,d=d.previousElementSibling;return u}function ie(s,o){return s.id||s.getAttribute?.("role")?!0:o.landmarks.includes(s.tagName)}function ae(s){if(s.id)return`#${s.id}`;let o=s.getAttribute?.("role");return o?`@${o}`:s.tagName}function oe(s,o){let u=[],d=s;for(;d&&d.tagName&&u.length<o.maxPathDepth;){let h=`${d.tagName}:${se(d)}`;if(u.unshift(h),d!==s&&ie(d,o)){u.unshift(ae(d));break}d=d.parentElement}return u}function ue(s,o){let u=0,d=s.length-1,h=o.length-1;for(;d>=0&&h>=0&&s[d]===o[h];)u++,d--,h--;return u}function C(s,o,u){if(u.has(s))return u.get(s);let d={signature:re(s,o),path:oe(s,o),textHint:ne(s,o)};return u.set(s,d),d}function z(s,o,u,d){if(d.has(s))return d.get(s);let h=new Map,y=s.querySelectorAll("*"),H=0;for(let S of y){let I=C(S,o,u);I.domIndex=H++,h.has(I.signature)||h.set(I.signature,[]),h.get(I.signature).push(S)}return d.set(s,h),h}function ce(s,o,u){u.delete(s),o.delete(s);let d=s.querySelectorAll("*");for(let h of d)o.delete(h)}function q(s,o,u,d,h){let y=C(s,u,d),H=C(o,u,d),S=u.weights,I={},E=0;if(y.signature!==H.signature)return{score:0,breakdown:{rejected:"signature mismatch"}};E+=S.signature,I.signature=S.signature;let T=ue(y.path,H.path)*S.pathSegment;E+=T,I.path=T;let k=!0;if(y.textHint&&H.textHint?y.textHint===H.textHint?(E+=S.textMatch,I.text=S.textMatch):(E-=S.textMismatch,I.text=-S.textMismatch,k=!1):y.textHint!==H.textHint&&(E-=S.textMismatch,I.text=-S.textMismatch,k=!1),h.candidateCount===1&&k&&(E+=S.uniqueCandidate,I.unique=S.uniqueCandidate),typeof y.domIndex=="number"&&typeof H.domIndex=="number"){let N=Math.abs(y.domIndex-H.domIndex),R=Math.min(N*S.positionPenalty,20);E-=R,I.drift=-R}return{score:E,breakdown:I}}function D(s,o,u,d,h){if(u.excludeIds&&s.id)return null;let y=z(o,u,d,h),H=C(s,u,d);if(typeof H.domIndex!="number"){let k=0,N=s.previousElementSibling;for(;N;)k++,N=N.previousElementSibling;H.domIndex=k}let S=y.get(H.signature)||[],I=u.excludeIds?S.filter(k=>!k.id):S;if(I.length===0)return null;let E=null,x=0,T=null;for(let k of I){let{score:N,breakdown:R}=q(s,k,u,d,{candidateCount:I.length});N>x&&(x=N,E=k,T=R)}return x<u.minConfidence?null:{element:E,confidence:x,breakdown:T}}function W(s,o,u,d,h){let y=o.querySelectorAll("*"),H=z(s,u,d,h),S=0;for(let T of y){let k=C(T,u,d);k.domIndex=S++}let I=[];for(let T of y){if(u.excludeIds&&T.id)continue;let k=C(T,u,d),N=H.get(k.signature)||[],R=u.excludeIds?N.filter(B=>!B.id):N;for(let B of R){let{score:l,breakdown:A}=q(T,B,u,d,{candidateCount:R.length});l>=u.minConfidence&&I.push({newEl:T,oldEl:B,score:l,breakdown:A})}}I.sort((T,k)=>k.score-T.score);let E=new Map,x=new Set;for(let{newEl:T,oldEl:k}of I)E.has(T)||x.has(k)||(E.set(T,k),x.add(k));return E}function P(s,o,u,d){let h=C(s,u,d),y=C(o,u,d),{score:H,breakdown:S}=q(s,o,u,d,{candidateCount:1});return{matches:H>=u.minConfidence,score:H,breakdown:S,newMeta:{signature:h.signature,path:h.path,textHint:h.textHint},oldMeta:{signature:y.signature,path:y.path,textHint:y.textHint}}}function U(s={}){let o={...F,...s,weights:{...F.weights,...s.weights}},u=new WeakMap,d=new WeakMap;return{findMatch:(h,y)=>D(h,y,o,u,d),computeMatches:(h,y)=>W(h,y,o,u,d),explain:(h,y)=>P(h,y,o,u),invalidate:h=>ce(h,u,d),session:()=>{let h=new WeakMap,y=new WeakMap;return{findMatch:(H,S)=>D(H,S,o,h,y),computeMatches:(H,S)=>W(H,S,o,h,y),explain:(H,S)=>P(H,S,o,h)}},getConfig:()=>({...o})}}var le=U(),$=(function(){"use strict";let s=()=>{};function o(l){if(!(l instanceof Element))return!1;if(l.hasAttribute("save-ignore"))return!0;if(l.tagName==="LINK"||l.tagName==="SCRIPT"){let A=l.getAttribute("src")||l.getAttribute("href")||"";if(A.startsWith("chrome-extension://")||A.startsWith("moz-extension://")||A.startsWith("safari-web-extension://"))return!0}return!1}function u(l,A){if(A!=="smart")return l.outerHTML;let p=l.getAttribute("src"),v=l.getAttribute("type")||"text/javascript";if(p)try{let b=new URL(p,window.location.href);return`ext:${v}:${b.origin}${b.pathname}${b.search}`}catch{return`ext:${v}:${p}`}else{let b=l.textContent.trim(),g=5381;for(let r=0;r<b.length;r++)g=(g<<5)+g^b.charCodeAt(r);return`inline:${v}:${Math.abs(g).toString(36)}`}}let d={morphStyle:"outerHTML",callbacks:{beforeNodeAdded:s,afterNodeAdded:s,beforeNodeMorphed:s,afterNodeMorphed:s,beforeNodeRemoved:s,afterNodeRemoved:s,beforeAttributeUpdated:s},head:{style:"merge",shouldPreserve:l=>l.getAttribute("im-preserve")==="true",shouldReAppend:l=>l.getAttribute("im-re-append")==="true",shouldRemove:s,afterHeadMorphed:s},scripts:{handle:!1,matchMode:"outerHTML",shouldPreserve:l=>l.getAttribute("im-preserve")==="true",shouldReAppend:l=>l.getAttribute("im-re-append")==="true",shouldRemove:s,afterScriptsHandled:s},restoreFocus:!0},h={computeMatches(l,A){let{computeMatches:p}=le.session();return p(l,A)}};function y(l,A,p={}){l=R(l);let v=B(A),b=N(l,v,p),g=b.scripts.matchMode,r=new Set(Array.from(l.querySelectorAll("script")).map(n=>u(n,g))),c=S(b,()=>x(b,l,v,n=>n.morphStyle==="innerHTML"?(I(n,l,v),Array.from(l.childNodes)):H(n,l,v)));b.pantry.remove();let e=k(l,r,b);return e.length>0?c instanceof Promise?c.then(n=>Promise.all(e).then(()=>n)):Promise.all(e).then(()=>c):c}function H(l,A,p){let v=B(A);return I(l,v,p,A,A.nextSibling),Array.from(v.childNodes)}function S(l,A){if(!l.config.restoreFocus)return A();let p=document.activeElement;if(!(p instanceof HTMLInputElement||p instanceof HTMLTextAreaElement))return A();let{id:v,selectionStart:b,selectionEnd:g}=p,r=A();return v&&v!==document.activeElement?.getAttribute("id")&&(p=l.target.querySelector(`[id="${v}"]`),p?.focus()),p&&!p.selectionEnd&&g!=null&&p.setSelectionRange(b,g),r}let I=(function(){function l(e,n,i,t=null,a=null){n instanceof HTMLTemplateElement&&i instanceof HTMLTemplateElement&&(n=n.content,i=i.content),t||=n.firstChild;for(let f of i.childNodes){if(o(f))continue;if(t&&t!=a){let M=p(e,f,t,a);if(M){M!==t&&b(e,t,M),E(M,f,e),t=M.nextSibling;continue}}if(f instanceof Element){let M=f.getAttribute("id");if(e.persistentIds.has(M)){let w=g(n,M,t,e);E(w,f,e),t=w.nextSibling;continue}if(!e.idMap.has(f)){let w=e.hyperMatches.get(f);if(w&&!e.idMap.has(w)){c(n,w,t),E(w,f,e),t=w.nextSibling;continue}}}let m=A(n,f,t,e);m&&(t=m.nextSibling)}for(;t&&t!=a;){let f=t;t=t.nextSibling,o(f)||v(e,f)}}function A(e,n,i,t){if(t.callbacks.beforeNodeAdded(n)===!1)return null;if(t.idMap.has(n)){let a=document.createElement(n.tagName);return e.insertBefore(a,i),E(a,n,t),t.callbacks.afterNodeAdded(a),a}else{let a=document.importNode(n,!0);return e.insertBefore(a,i),t.callbacks.afterNodeAdded(a),a}}let p=(function(){function e(t,a,f,m){let M=a instanceof Element&&!t.idMap.has(a)?t.hyperMatches.get(a):null,w=null,O=a.nextSibling,j=0,L=f;for(;L&&L!=m;){if(i(L,a)){if(n(t,L,a)||L===M&&!t.idMap.has(L))return L;if(w===null){let _=L instanceof Element&&t.hyperMatchedOldElements.has(L);!t.idMap.has(L)&&!_&&(w=L)}}if(w===null&&O&&i(L,O)&&(j++,O=O.nextSibling,j>=2&&(w=void 0)),t.activeElementAndParents.includes(L))break;L=L.nextSibling}return w||null}function n(t,a,f){let m=t.idMap.get(a),M=t.idMap.get(f);if(!M||!m)return!1;for(let w of m)if(M.has(w))return!0;return!1}function i(t,a){let f=t,m=a;return f.nodeType===m.nodeType&&f.tagName===m.tagName&&(!f.getAttribute?.("id")||f.getAttribute?.("id")===m.getAttribute?.("id"))}return e})();function v(e,n){let i=n instanceof Element&&e.hyperMatchedOldElements.has(n)&&!e.idMap.has(n);if(e.idMap.has(n)||i)c(e.pantry,n,null);else{if(e.callbacks.beforeNodeRemoved(n)===!1)return;n.parentNode?.removeChild(n),e.callbacks.afterNodeRemoved(n)}}function b(e,n,i){let t=n;for(;t&&t!==i;){let a=t;t=t.nextSibling,o(a)||v(e,a)}return t}function g(e,n,i,t){let a=t.target.getAttribute?.("id")===n&&t.target||t.target.querySelector(`[id="${n}"]`)||t.pantry.querySelector(`[id="${n}"]`);return r(a,t),c(e,a,i),a}function r(e,n){let i=e.getAttribute("id");for(;e=e.parentNode;){let t=n.idMap.get(e);t&&(t.delete(i),t.size||n.idMap.delete(e))}}function c(e,n,i){if(e.moveBefore)try{e.moveBefore(n,i)}catch{e.insertBefore(n,i)}else e.insertBefore(n,i)}return l})(),E=(function(){function l(r,c,e){return e.ignoreActive&&r===document.activeElement?null:(e.callbacks.beforeNodeMorphed(r,c)===!1||(r instanceof HTMLHeadElement&&e.head.ignore||(r instanceof HTMLHeadElement&&e.head.style!=="morph"?T(r,c,e):(A(r,c,e),g(r,e)||I(e,r,c))),e.callbacks.afterNodeMorphed(r,c)),r)}function A(r,c,e){let n=c.nodeType;if(n===1){let i=r,t=c,a=i.attributes,f=t.attributes;for(let m of f)b(m.name,i,"update",e)||i.getAttribute(m.name)!==m.value&&i.setAttribute(m.name,m.value);for(let m=a.length-1;0<=m;m--){let M=a[m];if(M&&!t.hasAttribute(M.name)){if(b(M.name,i,"remove",e))continue;i.removeAttribute(M.name)}}g(i,e)||p(i,t,e)}(n===8||n===3)&&r.nodeValue!==c.nodeValue&&(r.nodeValue=c.nodeValue)}function p(r,c,e){if(r instanceof HTMLInputElement&&c instanceof HTMLInputElement&&c.type!=="file"){let n=c.value,i=r.value;v(r,c,"checked",e),v(r,c,"disabled",e),c.hasAttribute("value")?i!==n&&(b("value",r,"update",e)||(r.setAttribute("value",n),r.value=n)):b("value",r,"remove",e)||(r.value="",r.removeAttribute("value"))}else if(r instanceof HTMLOptionElement&&c instanceof HTMLOptionElement)v(r,c,"selected",e);else if(r instanceof HTMLTextAreaElement&&c instanceof HTMLTextAreaElement){let n=c.value,i=r.value;if(b("value",r,"update",e))return;n!==i&&(r.value=n),r.firstChild&&r.firstChild.nodeValue!==n&&(r.firstChild.nodeValue=n)}}function v(r,c,e,n){let i=c[e],t=r[e];if(i!==t){let a=b(e,r,"update",n);a||(r[e]=c[e]),i?a||r.setAttribute(e,""):b(e,r,"remove",n)||r.removeAttribute(e)}}function b(r,c,e,n){return r==="value"&&n.ignoreActiveValue&&c===document.activeElement?!0:n.callbacks.beforeAttributeUpdated(r,c,e)===!1}function g(r,c){return!!c.ignoreActiveValue&&r===document.activeElement&&r!==document.body}return l})();function x(l,A,p,v){if(l.head.block){let b=A.querySelector("head"),g=p.querySelector("head");if(b&&g){let r=T(b,g,l);return Promise.all(r).then(()=>{let c=Object.assign(l,{head:{block:!1,ignore:!0}});return v(c)})}}return v(l)}function T(l,A,p){let v=[],b=[],g=[],r=[],c=p.scripts.matchMode,e=t=>{if(t.tagName==="SCRIPT")return u(t,c);if(t.tagName==="LINK"&&c==="smart"){let a=t.getAttribute("href");if(a)try{let f=new URL(a,window.location.href);return`link:${t.getAttribute("rel")||""}:${f.origin}${f.pathname}${f.search}`}catch{}}return t.outerHTML},n=new Map;for(let t of A.children)o(t)||n.set(e(t),t);for(let t of l.children){let a=e(t),f=n.has(a),m=p.head.shouldReAppend(t),M=p.head.shouldPreserve(t);f||M?m?b.push(t):(n.delete(a),g.push(t)):p.head.style==="append"?m&&(b.push(t),r.push(t)):p.head.shouldRemove(t)!==!1&&!o(t)&&b.push(t)}r.push(...n.values());let i=[];for(let t of r){let a=document.createRange().createContextualFragment(t.outerHTML).firstChild;if(p.callbacks.beforeNodeAdded(a)!==!1){if("href"in a&&a.href||"src"in a&&a.src){let f,m=new Promise(function(M){f=M});a.addEventListener("load",function(){f()}),i.push(m)}l.appendChild(a),p.callbacks.afterNodeAdded(a),v.push(a)}}for(let t of b)p.callbacks.beforeNodeRemoved(t)!==!1&&(l.removeChild(t),p.callbacks.afterNodeRemoved(t));return p.head.afterHeadMorphed(l,{added:v,kept:g,removed:b}),i}function k(l,A,p){if(!p.scripts.handle)return[];let v=[],b=[],g=[],r=[],c=p.scripts.matchMode,e=Array.from(l.querySelectorAll("script"));for(let i of e){let t=u(i,c),a=A.has(t),f=p.scripts.shouldPreserve(i),m=p.scripts.shouldReAppend(i);a||f?m?(b.push(i),r.push(i)):g.push(i):r.push(i)}for(let i of A){let t=e.some(a=>a.outerHTML===i)}let n=[];for(let i of r){if(p.callbacks.beforeNodeAdded(i)===!1)continue;let t=document.createRange().createContextualFragment(i.outerHTML).firstChild;if(t.src){let a,f=new Promise(function(m){a=m});t.addEventListener("load",function(){a()}),t.addEventListener("error",function(){a()}),n.push(f)}i.replaceWith(t),p.callbacks.afterNodeAdded(t),v.push(t)}return p.scripts.afterScriptsHandled(l,{added:v,kept:g,removed:b}),n}let N=(function(){function l(e,n,i){let{persistentIds:t,idMap:a}=r(e,n),f=h.computeMatches(e,n),m=new Set;for(let O of f.values())m.add(O);let M=A(i),w=M.morphStyle||"outerHTML";if(!["innerHTML","outerHTML"].includes(w))throw`Do not understand how to morph style ${w}`;return{target:e,newContent:n,config:M,morphStyle:w,ignoreActive:M.ignoreActive,ignoreActiveValue:M.ignoreActiveValue,restoreFocus:M.restoreFocus,idMap:a,persistentIds:t,hyperMatches:f,hyperMatchedOldElements:m,pantry:p(),activeElementAndParents:v(e),callbacks:M.callbacks,head:M.head,scripts:M.scripts}}function A(e){let n=Object.assign({},d);return Object.assign(n,e),n.callbacks=Object.assign({},d.callbacks,e.callbacks),n.head=Object.assign({},d.head,e.head),n.scripts=Object.assign({},d.scripts,e.scripts),n}function p(){let e=document.createElement("div");return e.hidden=!0,document.body.insertAdjacentElement("afterend",e),e}function v(e){let n=[],i=document.activeElement;if(i?.tagName!=="BODY"&&e.contains(i))for(;i&&(n.push(i),i!==e);)i=i.parentElement;return n}function b(e){let n=Array.from(e.querySelectorAll("[id]"));return e.getAttribute?.("id")&&n.push(e),n}function g(e,n,i,t){for(let a of t){let f=a.getAttribute("id");if(n.has(f)){let m=a;for(;m;){let M=e.get(m);if(M==null&&(M=new Set,e.set(m,M)),M.add(f),m===i)break;m=m.parentElement}}}}function r(e,n){let i=b(e),t=b(n),a=c(i,t),f=new Map;g(f,a,e,i);let m=n.__hyperMorphRoot||n;return g(f,a,m,t),{persistentIds:a,idMap:f}}function c(e,n){let i=new Set,t=new Map;for(let{id:f,tagName:m}of e)t.has(f)?i.add(f):t.set(f,m);let a=new Set;for(let{id:f,tagName:m}of n)a.has(f)?i.add(f):t.get(f)===m&&a.add(f);for(let f of i)a.delete(f);return a}return l})(),{normalizeElement:R,normalizeParent:B}=(function(){let l=new WeakSet;function A(g){return g instanceof Document?g.documentElement:g}function p(g){if(g==null)return document.createElement("div");if(typeof g=="string")return p(b(g));if(l.has(g))return g;if(g instanceof Node){if(g.parentNode)return new v(g);{let r=document.createElement("div");return r.append(g),r}}else{let r=document.createElement("div");for(let c of[...g])r.append(c);return r}}class v{constructor(r){this.originalNode=r,this.realParentNode=r.parentNode,this.previousSibling=r.previousSibling,this.nextSibling=r.nextSibling}get childNodes(){let r=[],c=this.previousSibling?this.previousSibling.nextSibling:this.realParentNode.firstChild;for(;c&&c!=this.nextSibling;)r.push(c),c=c.nextSibling;return r}querySelectorAll(r){return this.childNodes.reduce((c,e)=>{if(e instanceof Element){e.matches(r)&&c.push(e);let n=e.querySelectorAll(r);for(let i=0;i<n.length;i++)c.push(n[i])}return c},[])}insertBefore(r,c){return this.realParentNode.insertBefore(r,c)}moveBefore(r,c){return this.realParentNode.moveBefore(r,c)}get __hyperMorphRoot(){return this.originalNode}}function b(g){let r=new DOMParser,c=g.replace(/<svg(\s[^>]*>|>)([\s\S]*?)<\/svg>/gim,"");if(c.match(/<\/html>/)||c.match(/<\/head>/)||c.match(/<\/body>/)){let e=r.parseFromString(g,"text/html");if(c.match(/<\/html>/))return l.add(e),e;{let n=e.firstChild;return n&&l.add(n),n}}else{let n=r.parseFromString("<body><template>"+g+"</template></body>","text/html").body.querySelector("template").content;return l.add(n),n}}return{normalizeElement:A,normalizeParent:p}})();return{morph:y,defaults:d}})();var de=$.morph,fe=$.defaults,he=$;return X(pe);})();
2
2
 
3
3
  // Convenience morph wrapper with data-id support
4
4
  var morph = function(oldEl, newEl, options = {}) {