@unhingged/vizu-core 0.1.10 → 0.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auto.cjs +29 -6
- package/dist/auto.cjs.map +1 -1
- package/dist/auto.js +29 -6
- package/dist/auto.js.map +1 -1
- package/dist/index.cjs +29 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +29 -6
- package/dist/index.js.map +1 -1
- package/dist/vizu.min.js +10 -10
- package/dist/vizu.min.js.map +1 -1
- package/package.json +1 -1
package/dist/vizu.min.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var VIZU=(()=>{var X=Object.defineProperty;var be=Object.getOwnPropertyDescriptor;var ze=Object.getOwnPropertyNames;var xe=Object.prototype.hasOwnProperty;var ye=(o,e)=>{for(var t in e)X(o,t,{get:e[t],enumerable:!0})},we=(o,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of ze(e))!xe.call(o,i)&&i!==t&&X(o,i,{get:()=>e[i],enumerable:!(n=be(e,i))||n.enumerable});return o};var Ce=o=>we(X({},"__esModule",{value:!0}),o);var We={};ye(We,{Vizu:()=>E});function F(){return typeof crypto<"u"&&"randomUUID"in crypto?crypto.randomUUID():Math.random().toString(36).slice(2)+Date.now().toString(36)}function Y(o,e){return!!o.closest(e)}function d(o){return o.replace(/[&<>"']/g,e=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[e])}function T(o){let e=new Date(o),n=Date.now()-o;return n<6e4?"just now":n<36e5?Math.floor(n/6e4)+"m ago":n<864e5?Math.floor(n/36e5)+"h ago":e.toLocaleDateString()+" "+e.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})}function ke(o){return o.split(/\s+/).filter(Boolean).slice(0,2).map(e=>e[0].toUpperCase()).join("")}function z(o,e="vz-comment-author-avatar"){return o
|
|
1
|
+
"use strict";var VIZU=(()=>{var X=Object.defineProperty;var be=Object.getOwnPropertyDescriptor;var ze=Object.getOwnPropertyNames;var xe=Object.prototype.hasOwnProperty;var ye=(o,e)=>{for(var t in e)X(o,t,{get:e[t],enumerable:!0})},we=(o,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of ze(e))!xe.call(o,i)&&i!==t&&X(o,i,{get:()=>e[i],enumerable:!(n=be(e,i))||n.enumerable});return o};var Ce=o=>we(X({},"__esModule",{value:!0}),o);var We={};ye(We,{Vizu:()=>E});function F(){return typeof crypto<"u"&&"randomUUID"in crypto?crypto.randomUUID():Math.random().toString(36).slice(2)+Date.now().toString(36)}function Y(o,e){return!!o.closest(e)}function d(o){return o==null?"":String(o).replace(/[&<>"']/g,e=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[e])}function T(o){let e=new Date(o),n=Date.now()-o;return n<6e4?"just now":n<36e5?Math.floor(n/6e4)+"m ago":n<864e5?Math.floor(n/36e5)+"h ago":e.toLocaleDateString()+" "+e.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})}function ke(o){return o?String(o).split(/\s+/).filter(Boolean).slice(0,2).map(e=>e[0].toUpperCase()).join(""):""}function z(o,e="vz-comment-author-avatar"){if(!o)return`<span class="${e}">\xB7</span>`;let t=o.name||o.id||"User";return o.avatarUrl?`<span class="${e}"><img src="${d(o.avatarUrl)}" alt="${d(t)}" /></span>`:`<span class="${e}">${d(ke(t)||"?")}</span>`}function ne(){return Math.random().toString(36).slice(2,10)}var Ae=/\[@([^\]]+)\]\(vizu-mention:([a-zA-Z0-9_-]+)\)/g,Ee=/(\[#[^\]]+\]\(vizu-ref:[a-zA-Z0-9_-]+\)|\[@[^\]]+\]\(vizu-mention:[a-zA-Z0-9_-]+\))/g;function U(o,e){return o.split(Ee).map(n=>{let i=n.match(/^\[#([^\]]+)\]\(vizu-ref:([a-zA-Z0-9_-]+)\)$/);if(i)return`<a class="vz-ref" data-vz="ref" data-comment-id="${d(e)}" data-ref-id="${d(i[2])}" role="button" tabindex="0">${d(i[1])}</a>`;let r=n.match(/^\[@([^\]]+)\]\(vizu-mention:([a-zA-Z0-9_-]+)\)$/);return r?`<span class="vz-mention" data-vz="mention" data-mention-id="${d(r[2])}">@${d(r[1])}</span>`:d(n)}).join("")}function ie(o){let e=[];for(let t of o.matchAll(Ae))e.includes(t[2])||e.push(t[2]);return e}function H(o){return!Array.isArray(o)||o.length===0?"":`<div class="vz-attachment-grid">${o.map(t=>{let n=t.mimeType?.startsWith("image/"),i=t.filename??t.url.split("/").pop()??"file";return n?`
|
|
2
2
|
<a class="vz-attachment-display" href="${d(t.url)}" target="_blank" rel="noreferrer" title="${d(i)}">
|
|
3
3
|
<img src="${d(t.url)}" alt="${d(i)}" loading="lazy" />
|
|
4
4
|
</a>
|
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
<span class="vz-attachment-icon" aria-hidden="true">\u{1F4C4}</span>
|
|
8
8
|
<span class="vz-attachment-filename">${d(i)}</span>
|
|
9
9
|
</a>
|
|
10
|
-
`}).join("")}</div>`}function C(o){if(!o||typeof o!="object")return o;let e={...o};return(!Array.isArray(e.fingerprints)||e.fingerprints.length===0)&&e.fingerprint&&(e.fingerprints=[e.fingerprint]),delete e.fingerprint,e.url&&!e.pageUrl&&(e.pageUrl=e.url),(!("status"in e)||!Se(e.status))&&(e.status="open"),Array.isArray(e.replies)||(e.replies=[]),Array.isArray(e.attachments)||(e.attachments=[]),Array.isArray(e.mentions)||(e.mentions=[]),"fingerprintsRefreshedAt"in e||(e.fingerprintsRefreshedAt=null),e.schemaVersion=2,e}function Se(o){return o==="open"||o==="resolved"||o==="wontfix"}function k(o){if(!Array.isArray(o))return[];let e=[];for(let t of o)!t||typeof t!="object"||e.push(C(t));return e}function re(o){if(!Array.isArray(o))return!1;for(let e of o){if(!e||typeof e!="object")continue;let t=e;if(t.schemaVersion!==2||"fingerprint"in t||!Array.isArray(t.replies)||!Array.isArray(t.attachments)||!Array.isArray(t.mentions))return!0}return!1}var Z=o=>`vizu:comments:${o}`,I=class{async load(e){return M(e)}async addComment(e,t){let n=M(e);n.push(t),V(e,n)}async updateComment(e,t,n){let i=M(e),r=i.findIndex(a=>a.id===t);if(r===-1)return null;let s={...i[r],...n,id:i[r].id};return i[r]=s,V(e,i),s}async removeComment(e,t){let n=M(e);V(e,n.filter(i=>i.id!==t))}async setAll(e,t){V(e,t)}async clear(e){typeof localStorage>"u"||localStorage.removeItem(Z(e))}async addReply(e,t,n){let i=M(e),r=i.findIndex(a=>a.id===t);if(r===-1)return null;let s={...i[r],replies:[...i[r].replies??[],n]};return i[r]=s,V(e,i),s}async removeReply(e,t,n){let i=M(e),r=i.findIndex(a=>a.id===t);if(r===-1)return null;let s={...i[r],replies:(i[r].replies??[]).filter(a=>a.id!==n)};return i[r]=s,V(e,i),s}};function M(o){if(typeof localStorage>"u")return[];let e=localStorage.getItem(Z(o));if(!e)return[];try{let t=JSON.parse(e);return Array.isArray(t)?k(t):[]}catch{return[]}}function V(o,e){typeof localStorage>"u"||localStorage.setItem(Z(o),JSON.stringify(e))}var O=class{constructor(){this.store=new Map}async load(e){return[...this.store.get(e)||[]]}async addComment(e,t){let n=this.store.get(e)??[];this.store.set(e,[...n,t])}async updateComment(e,t,n){let i=this.store.get(e)??[],r=i.findIndex(l=>l.id===t);if(r===-1)return null;let s={...i[r],...n,id:i[r].id},a=[...i];return a[r]=s,this.store.set(e,a),s}async removeComment(e,t){let n=this.store.get(e)??[];this.store.set(e,n.filter(i=>i.id!==t))}async setAll(e,t){this.store.set(e,[...t])}async clear(e){this.store.delete(e)}async addReply(e,t,n){let i=this.store.get(e)??[],r=i.findIndex(l=>l.id===t);if(r===-1)return null;let s={...i[r],replies:[...i[r].replies??[],n]},a=[...i];return a[r]=s,this.store.set(e,a),s}async removeReply(e,t,n){let i=this.store.get(e)??[],r=i.findIndex(l=>l.id===t);if(r===-1)return null;let s={...i[r],replies:(i[r].replies??[]).filter(l=>l.id!==n)},a=[...i];return a[r]=s,this.store.set(e,a),s}},N=class{async load(){return[]}async addComment(){}async updateComment(){return null}async removeComment(){}async setAll(){}async clear(){}};function G(o){if(!o||typeof o!="object")return!1;let e=o;return typeof e.load=="function"&&typeof e.save=="function"&&typeof e.clear=="function"&&typeof e.addComment!="function"}function se(o){if(!G(o))return o;let e=!1,t=()=>{e||(e=!0,typeof console<"u"&&console.warn("[vizu] StorageAdapter v1 detected. Per-comment ops are emulated via full-array rewrites \u2014 upgrade your adapter to the v2 interface (addComment / updateComment / removeComment / setAll / load / clear) when you can."))};return{async load(n){return t(),o.load(n)},async addComment(n,i){t();let r=await o.load(n);r.push(i),await o.save(n,r)},async updateComment(n,i,r){t();let s=await o.load(n),a=s.findIndex(c=>c.id===i);if(a===-1)return null;let l={...s[a],...r,id:s[a].id};return s[a]=l,await o.save(n,s),l},async removeComment(n,i){t();let r=await o.load(n);await o.save(n,r.filter(s=>s.id!==i))},async setAll(n,i){t(),await o.save(n,i)},async clear(n){await o.clear(n)}}}var Te="https://vizu.unhingged.com",oe=480,ae=640,A=class{constructor(e){this.cachedToken=null;this.pendingAuth=null;this.lastNotifiedTokenId=null;this.accessDenied=!1;this.accessDeniedReason=null;this.workspace=e.workspace,this.apiUrl=(e.apiUrl??Te).replace(/\/$/,""),this.autoSignIn=e.autoSignIn!==!1,this.onAuthChanged=e.onAuthChanged;let t=this.readHashToken();t?(this.cachedToken=t,this.writeStoredToken(t)):this.cachedToken=this.readStoredToken(),this.cachedToken&&!this.isExpired(this.cachedToken)&&this.fireAuthChanged(this.cachedToken)}readHashToken(){if(typeof window>"u")return null;let e=window.location.hash;if(!e||e.length<2)return null;let t=new URLSearchParams(e.slice(1)),n=t.get("vizu_auth");if(!n)return null;try{let i=Uint8Array.from(atob(n),p=>p.charCodeAt(0)),r=new TextDecoder("utf-8").decode(i),s=JSON.parse(r);if(!s.t||!s.e||!s.u||!s.w||s.w!==this.workspace)return null;let a={token:s.t,expiresAt:s.e,userId:s.u,user:typeof s.n=="string"?{id:s.u,name:s.n,avatarUrl:typeof s.a=="string"?s.a:void 0}:null};t.delete("vizu_auth");let l=t.toString(),c=l?`#${l}`:"";try{let p=window.location.pathname+window.location.search+c;window.history.replaceState(null,"",p)}catch{}return a}catch{return null}}async preflightAuth(){await this.resolveToken()}isAccessDenied(){return this.accessDenied}accessDenialReason(){return this.accessDeniedReason}async load(e){if(!this.cachedToken||this.isExpired(this.cachedToken)){let i=this.readStoredToken();if(!i||this.isExpired(i))return[];this.cachedToken=i}let t=[],n=null;do{let i=new URL(this.apiUrl+"/api/comments");i.searchParams.set("workspace",this.workspace),i.searchParams.set("limit","100"),n&&i.searchParams.set("cursor",n);let r=await this.fetchAuthed(i.toString(),{method:"GET"}),s=await this.parseJson(r);if(!r.ok)throw x(r.status,s);let a=Array.isArray(s.comments)?s.comments:[];t.push(...k(a)),n=typeof s.nextCursor=="string"?s.nextCursor:null}while(n);return t}async addComment(e,t){let n=await this.fetchAuthed(this.apiUrl+"/api/comments",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({workspace:this.workspace,comment:t})}),i=await this.parseJson(n);if(!n.ok)throw x(n.status,i)}async updateComment(e,t,n){let i=new URL(this.apiUrl+"/api/comments/"+encodeURIComponent(t));i.searchParams.set("workspace",this.workspace);let r=await this.fetchAuthed(i.toString(),{method:"PATCH",headers:{"content-type":"application/json"},body:JSON.stringify(n)});if(r.status===404)return null;let s=await this.parseJson(r);if(!r.ok)throw x(r.status,s);return C(s.comment)}async removeComment(e,t){let n=new URL(this.apiUrl+"/api/comments/"+encodeURIComponent(t));n.searchParams.set("workspace",this.workspace);let i=await this.fetchAuthed(n.toString(),{method:"DELETE"});if(i.status!==404&&!i.ok){let r=await this.parseJson(i);throw x(i.status,r)}}async setAll(e,t){await this.clear(e);for(let n of t)await this.addComment(e,n)}async clear(e){let t=new URL(this.apiUrl+"/api/comments");t.searchParams.set("workspace",this.workspace),t.searchParams.set("all","true");let n=await this.fetchAuthed(t.toString(),{method:"DELETE"});if(n.status!==404&&!n.ok){let i=await this.parseJson(n);throw x(n.status,i)}}async addReply(e,t,n){let i=new URL(this.apiUrl+"/api/comments/"+encodeURIComponent(t)+"/replies");i.searchParams.set("workspace",this.workspace);let r=await this.fetchAuthed(i.toString(),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(n)});if(r.status===404)return null;let s=await this.parseJson(r);if(!r.ok)throw x(r.status,s);return s?.comment?C(s.comment):null}async removeReply(e,t,n){let i=new URL(this.apiUrl+"/api/comments/"+encodeURIComponent(t)+"/replies/"+encodeURIComponent(n));i.searchParams.set("workspace",this.workspace);let r=await this.fetchAuthed(i.toString(),{method:"DELETE"});if(r.status===404)return null;if(!r.ok){let s=await this.parseJson(r);throw x(r.status,s)}return null}async uploadAttachment(e,t){let n=new FormData;n.append("file",t,t.name);let i=new URL(this.apiUrl+"/api/uploads");i.searchParams.set("workspace",this.workspace);let r=await this.fetchAuthed(i.toString(),{method:"POST",body:n}),s=await this.parseJson(r);if(!r.ok)throw x(r.status,s);if(!s?.url||typeof s.url!="string")throw x(500,{error:"upload_failed",message:"Backend did not return a URL."});return{id:F(),url:s.url,mimeType:t.type||"application/octet-stream",sizeBytes:t.size,uploadedAt:Date.now(),filename:t.name}}getAuthContext(){return this.cachedToken?{userId:this.cachedToken.userId,token:this.cachedToken.token,expiresAt:this.cachedToken.expiresAt}:null}isExpired(e){if(!e)return!0;let t=new Date(e.expiresAt).getTime();return!Number.isFinite(t)||t-Date.now()<3e4}readStoredToken(){if(typeof sessionStorage>"u")return null;let e=sessionStorage.getItem(this.sessionKey());if(!e)return null;try{let t=JSON.parse(e);return this.isExpired(t)?(sessionStorage.removeItem(this.sessionKey()),null):t}catch{return null}}writeStoredToken(e){this.cachedToken=e,typeof sessionStorage<"u"&&sessionStorage.setItem(this.sessionKey(),JSON.stringify(e))}clearStoredToken(){this.cachedToken=null,typeof sessionStorage<"u"&&sessionStorage.removeItem(this.sessionKey())}sessionKey(){return`vizu:cloud-token:v2:${this.workspace}`}async resolveToken(){if(this.cachedToken&&!this.isExpired(this.cachedToken))return this.cachedToken;let e=this.readStoredToken();if(e)return this.cachedToken=e,this.fireAuthChanged(e),e;if(this.accessDenied)throw L("access_denied",`No access to workspace "${this.workspace}" (${this.accessDeniedReason??"no_access"}).`);if(!this.autoSignIn)throw L("auth_required","Sign-in required; autoSignIn is disabled.");return this.pendingAuth||(this.pendingAuth=this.openSignInPopup().then(t=>(this.writeStoredToken(t),this.fireAuthChanged(t),t)).finally(()=>{this.pendingAuth=null})),this.pendingAuth}fireAuthChanged(e){if(this.lastNotifiedTokenId!==e.token){this.lastNotifiedTokenId=e.token;try{this.onAuthChanged?.({userId:e.userId,user:e.user})}catch(t){typeof console<"u"&&console.warn("[vizu/cloud] onAuthChanged callback threw",t)}}}openSignInPopup(){return new Promise((e,t)=>{if(typeof window>"u")return t(L("auth_unavailable","Sign-in requires a browser environment."));let n=new URL(this.apiUrl).origin,i=window.location.origin,r=this.apiUrl+"/connect?workspace="+encodeURIComponent(this.workspace)+"&origin="+encodeURIComponent(i),s=Math.max(0,Math.round((window.screen.width-oe)/2)),a=Math.max(0,Math.round((window.screen.height-ae)/2)),l=window.open(r,"vizu-connect",`width=${oe},height=${ae},left=${s},top=${a},noopener=no,popup=yes`);if(!l)try{let v=window.location.href,f=this.apiUrl+"/connect?workspace="+encodeURIComponent(this.workspace)+"&origin="+encodeURIComponent(i)+"&return_to="+encodeURIComponent(v);window.location.assign(f);return}catch(v){return t(L("popup_blocked","Sign-in popup was blocked and redirect fallback failed: "+(v instanceof Error?v.message:String(v))))}let c=!1,p=v=>{if(v.origin!==n)return;let f=v.data;if(!f)return;if(f.type==="vizu:auth-denied"&&f.workspace===this.workspace){c=!0,$(),this.accessDenied=!0,this.accessDeniedReason=typeof f.reason=="string"?f.reason:"no_access",t(L("access_denied",`No access to workspace "${this.workspace}" (${this.accessDeniedReason}).`));return}if(f.type!=="vizu:auth"||f.workspace!==this.workspace||typeof f.token!="string"||typeof f.expiresAt!="string"||typeof f.userId!="string")return;c=!0,$();let b=f.user,u=b&&typeof b.name=="string"?{id:typeof b.id=="string"?b.id:f.userId,name:b.name,avatarUrl:typeof b.avatarUrl=="string"?b.avatarUrl:void 0}:null;e({token:f.token,expiresAt:f.expiresAt,userId:f.userId,user:u})},m=window.setInterval(()=>{l.closed&&(c||($(),t(L("auth_canceled","Sign-in popup was closed before completing."))))},500);function $(){window.clearInterval(m),window.removeEventListener("message",p)}window.addEventListener("message",p)})}async fetchAuthed(e,t,n=!1){let i=await this.resolveToken(),r=new Headers(t.headers);r.set("authorization",`Bearer ${i.token}`);let s=await fetch(e,{...t,headers:r,credentials:"omit"});return s.status===401&&!n?(this.clearStoredToken(),this.fetchAuthed(e,t,!0)):s}async parseJson(e){try{let t=await e.text();return t?JSON.parse(t):null}catch{return null}}};function L(o,e){let t=new Error(e);return t.code=o,t}function x(o,e){let t=e?.error==="origin_not_allowed"?"origin_not_allowed":e?.error==="not_found"?"workspace_not_found":"http_error",n=new Error(e?.message??`HTTP ${o}`);return n.code=t,n.status=o,n.body=e,n}function le(o){let e=[],t=o,n=0;for(;t&&t!==document.documentElement&&n<8;){let i=t.tagName.toLowerCase();if(t.id){e.unshift("#"+CSS.escape(t.id));break}let r=Array.from(t.classList).filter(a=>!a.startsWith("vz-")&&!a.startsWith("vizu-")).slice(0,2);r.length&&(i+="."+r.map(a=>CSS.escape(a)).join("."));let s=t.parentElement;if(s){let a=Array.from(s.children).filter(l=>l.tagName===t.tagName);if(a.length>1){let l=a.indexOf(t);i+=":nth-of-type("+(l+1)+")"}}e.unshift(i),t=s,n++}return e.join(" > ")}function _(o){let e=o.innerText||o.textContent||"",t=o.parentElement,n=0;return t&&(n=Array.from(t.children).indexOf(o)),{selector:le(o),parentSelector:t?le(t):"",tagName:o.tagName,textSnippet:e.trim().slice(0,80),siblingIndex:n,attributes:{id:o.id||void 0,classList:Array.from(o.classList).filter(i=>!i.startsWith("vz-")&&!i.startsWith("vizu-")),role:o.getAttribute("role")||void 0,ariaLabel:o.getAttribute("aria-label")||void 0,dataKey:o.getAttribute("data-vizu-key")||void 0},ancestorChain:Me(o,4),algorithmVersion:2}}function Me(o,e){let t=[],n=o.parentElement;for(;n&&t.length<e;){let i=n.parentElement,r=1;i&&(r=Array.from(i.children).filter(a=>a.tagName===n.tagName).indexOf(n)+1),t.push({tag:n.tagName,nthOfType:r}),n=i}return t.length>0?{steps:t}:void 0}function j(o,e=document){if(o.attributes.dataKey){try{let s=e.querySelector(`[data-vizu-key="${CSS.escape(o.attributes.dataKey)}"]`);if(s)return{element:s,confidence:"exact"}}catch{}return{element:null,confidence:"orphaned"}}if(o.attributes.id)try{let s=e.querySelector("#"+CSS.escape(o.attributes.id));if(s)return{element:s,confidence:"exact"}}catch{}let t=[],n=o.attributes.classList;if(n&&n.length>0){let s=Ve(e,o.tagName,n);s?.element&&t.push({el:s.element,rung:"class"})}try{let s=e.querySelector(o.selector);s&&t.push({el:s,rung:"selector"})}catch{}if(o.ancestorChain&&o.ancestorChain.steps.length>0){let s=Le(e,o.tagName,o.ancestorChain.steps);s?.element&&t.push({el:s.element,rung:"chain"})}else try{let s=o.parentSelector?e.querySelector(o.parentSelector):e;if(s){let a=s.children[o.siblingIndex];a&&a.tagName===o.tagName&&t.push({el:a,rung:"chain"})}}catch{}if(o.textSnippet){let s=Pe(e,o.tagName,o.textSnippet);s?.element&&t.push({el:s.element,rung:"text"})}if(t.length===0)return{element:null,confidence:"orphaned"};let i=new Map;for(let s of t){let a=i.get(s.el);a||(a=new Set,i.set(s.el,a)),a.add(s.rung)}let r=null;for(let[s,a]of i)(!r||a.size>r.rungs.size)&&(r={el:s,rungs:a});return r?r.rungs.size>=3?{element:r.el,confidence:"likely"}:r.rungs.size>=2?{element:r.el,confidence:"drifted"}:r.rungs.has("class")||r.rungs.has("chain")?{element:r.el,confidence:"drifted"}:{element:null,confidence:"orphaned"}:{element:null,confidence:"orphaned"}}function Ve(o,e,t){let n=new Set(t.filter(a=>!a.startsWith("vz-")&&!a.startsWith("vizu-")));if(n.size===0)return null;let i=o.querySelectorAll(e.toLowerCase()),r=null,s=0;for(let a of i){let l=new Set(Array.from(a.classList).filter(p=>!p.startsWith("vz-")&&!p.startsWith("vizu-")));if(l.size===0)continue;let c=Ue(n,l);c<.6||(!r||c>r.score?(s=r?.score??0,r={el:a,score:c}):c>s&&(s=c))}return!r||r.score-s<.1?null:{element:r.el,confidence:"likely"}}function Le(o,e,t){let n=o.querySelectorAll(e.toLowerCase()),i=null;for(let r of n){let s=Re(r,t.length+3),a=He(s,t,3);a<2||(!i||a>i.score)&&(i={el:r,score:a})}return i?{element:i.el,confidence:i.score===t.length?"likely":"drifted"}:null}function Re(o,e){let t=[],n=o.parentElement;for(;n&&t.length<e;){let i=n.parentElement,r=1;i&&(r=Array.from(i.children).filter(a=>a.tagName===n.tagName).indexOf(n)+1),t.push({tag:n.tagName,nthOfType:r}),n=i}return t}function Pe(o,e,t){let n=ce(t);if(!n)return null;let i=o.querySelectorAll(e.toLowerCase()),r=null;for(let s of i){let a=s.innerText||s.textContent||"",l=ce(a.slice(0,160));if(!l)continue;let c=$e(n,l);c<.75||(!r||c>r.score)&&(r={el:s,score:c})}return r?{element:r.el,confidence:"drifted"}:null}function ce(o){return o.toLowerCase().replace(/\s+/g," ").trim()}function $e(o,e){if(o===e)return 1;if(o.length===0||e.length===0)return o.length===e.length?1:0;let t=Math.max(o.length,e.length);return 1-Fe(o,e)/t}function Fe(o,e){if(o.length>e.length){let i=o;o=e,e=i}let t=new Array(o.length+1),n=new Array(o.length+1);for(let i=0;i<=o.length;i++)t[i]=i;for(let i=1;i<=e.length;i++){n[0]=i;for(let r=1;r<=o.length;r++){let s=o.charCodeAt(r-1)===e.charCodeAt(i-1)?0:1;n[r]=Math.min(n[r-1]+1,t[r]+1,t[r-1]+s)}for(let r=0;r<=o.length;r++)t[r]=n[r]}return t[o.length]}function He(o,e,t){let n=0;for(let i=0;i<=t;i++){let r=0;for(let s=0;s<e.length;s++){let a=o[s+i];if(!a)break;a.tag===e[s].tag&&a.nthOfType===e[s].nthOfType&&r++}r>n&&(n=r)}return n}function Ue(o,e){if(o.size===0&&e.size===0)return 1;let t=0;for(let i of o)e.has(i)&&t++;let n=o.size+e.size-t;return n===0?0:t/n}function R(o,e){return j(o,e).element}function h(o){return o.selector+"|"+o.textSnippet}function P(o){let e=o.tagName.toLowerCase();if(o.textSnippet){let t=o.textSnippet.length>24?o.textSnippet.slice(0,24)+"\u2026":o.textSnippet;return e+": "+t}return o.attributes.id?e+"#"+o.attributes.id:o.attributes.classList&&o.attributes.classList.length?e+"."+o.attributes.classList[0]:e}var Ie="[data-vizu-root], [data-vizu-ignore], script, style, link, meta, head",q=class{constructor(e,t,n){this.current=null;this.active=!1;this.paused=!1;this.handleMove=e=>{if(this.paused){this.setCurrent(null),this.overlay.style.display="none";return}let t=document.elementFromPoint(e.clientX,e.clientY);if(!(!t||t===this.current)){if(this.shouldIgnore(t)){this.setCurrent(null),this.overlay.style.display="none";return}this.setCurrent(t),this.updateOverlay()}};this.handleClick=e=>{let t=document.elementFromPoint(e.clientX,e.clientY);t&&(this.shouldIgnore(t)||(e.preventDefault(),e.stopPropagation(),this.onClick(t,e)))};this.handleScroll=()=>{this.current&&this.updateOverlay()};this.root=e,this.extraIgnore=t,this.onClick=n,this.overlay=document.createElement("div"),this.overlay.className="vz-highlight",this.overlay.style.display="none",this.root.appendChild(this.overlay)}setCurrent(e){this.current!==e&&(this.current=e)}start(){this.active||(this.active=!0,document.addEventListener("mousemove",this.handleMove,!0),document.addEventListener("click",this.handleClick,!0),document.addEventListener("scroll",this.handleScroll,!0),window.addEventListener("resize",this.handleScroll))}stop(){this.active&&(this.active=!1,document.removeEventListener("mousemove",this.handleMove,!0),document.removeEventListener("click",this.handleClick,!0),document.removeEventListener("scroll",this.handleScroll,!0),window.removeEventListener("resize",this.handleScroll),this.overlay.style.display="none",this.setCurrent(null))}shouldIgnore(e){if(e===document.documentElement||e===document.body||Y(e,Ie))return!0;for(let t of this.extraIgnore)try{if(Y(e,t))return!0}catch{}return!1}setPaused(e){this.paused=e,e&&(this.setCurrent(null),this.overlay.style.display="none")}isPaused(){return this.paused}updateOverlay(){if(!this.current)return;let e=this.current.getBoundingClientRect();if(e.width===0||e.height===0){this.overlay.style.display="none";return}this.overlay.style.display="block",this.overlay.style.left=e.left+"px",this.overlay.style.top=e.top+"px",this.overlay.style.width=e.width+"px",this.overlay.style.height=e.height+"px"}destroy(){this.stop(),this.overlay.remove()}};function de(o){return typeof CSS<"u"&&typeof CSS.escape=="function"?CSS.escape(o):o.replace(/["\\]/g,"\\$&")}function Oe(o){let t=(o.replies??[]).map(n=>`
|
|
10
|
+
`}).join("")}</div>`}function C(o){if(!o||typeof o!="object")return o;let e={...o};return(!Array.isArray(e.fingerprints)||e.fingerprints.length===0)&&e.fingerprint&&(e.fingerprints=[e.fingerprint]),delete e.fingerprint,e.url&&!e.pageUrl&&(e.pageUrl=e.url),(!("status"in e)||!Se(e.status))&&(e.status="open"),Array.isArray(e.replies)||(e.replies=[]),Array.isArray(e.attachments)||(e.attachments=[]),Array.isArray(e.mentions)||(e.mentions=[]),"fingerprintsRefreshedAt"in e||(e.fingerprintsRefreshedAt=null),e.schemaVersion=2,e}function Se(o){return o==="open"||o==="resolved"||o==="wontfix"}function k(o){if(!Array.isArray(o))return[];let e=[];for(let t of o)!t||typeof t!="object"||e.push(C(t));return e}function re(o){if(!Array.isArray(o))return!1;for(let e of o){if(!e||typeof e!="object")continue;let t=e;if(t.schemaVersion!==2||"fingerprint"in t||!Array.isArray(t.replies)||!Array.isArray(t.attachments)||!Array.isArray(t.mentions))return!0}return!1}var Z=o=>`vizu:comments:${o}`,I=class{async load(e){return M(e)}async addComment(e,t){let n=M(e);n.push(t),V(e,n)}async updateComment(e,t,n){let i=M(e),r=i.findIndex(a=>a.id===t);if(r===-1)return null;let s={...i[r],...n,id:i[r].id};return i[r]=s,V(e,i),s}async removeComment(e,t){let n=M(e);V(e,n.filter(i=>i.id!==t))}async setAll(e,t){V(e,t)}async clear(e){typeof localStorage>"u"||localStorage.removeItem(Z(e))}async addReply(e,t,n){let i=M(e),r=i.findIndex(a=>a.id===t);if(r===-1)return null;let s={...i[r],replies:[...i[r].replies??[],n]};return i[r]=s,V(e,i),s}async removeReply(e,t,n){let i=M(e),r=i.findIndex(a=>a.id===t);if(r===-1)return null;let s={...i[r],replies:(i[r].replies??[]).filter(a=>a.id!==n)};return i[r]=s,V(e,i),s}};function M(o){if(typeof localStorage>"u")return[];let e=localStorage.getItem(Z(o));if(!e)return[];try{let t=JSON.parse(e);return Array.isArray(t)?k(t):[]}catch{return[]}}function V(o,e){typeof localStorage>"u"||localStorage.setItem(Z(o),JSON.stringify(e))}var O=class{constructor(){this.store=new Map}async load(e){return[...this.store.get(e)||[]]}async addComment(e,t){let n=this.store.get(e)??[];this.store.set(e,[...n,t])}async updateComment(e,t,n){let i=this.store.get(e)??[],r=i.findIndex(l=>l.id===t);if(r===-1)return null;let s={...i[r],...n,id:i[r].id},a=[...i];return a[r]=s,this.store.set(e,a),s}async removeComment(e,t){let n=this.store.get(e)??[];this.store.set(e,n.filter(i=>i.id!==t))}async setAll(e,t){this.store.set(e,[...t])}async clear(e){this.store.delete(e)}async addReply(e,t,n){let i=this.store.get(e)??[],r=i.findIndex(l=>l.id===t);if(r===-1)return null;let s={...i[r],replies:[...i[r].replies??[],n]},a=[...i];return a[r]=s,this.store.set(e,a),s}async removeReply(e,t,n){let i=this.store.get(e)??[],r=i.findIndex(l=>l.id===t);if(r===-1)return null;let s={...i[r],replies:(i[r].replies??[]).filter(l=>l.id!==n)},a=[...i];return a[r]=s,this.store.set(e,a),s}},N=class{async load(){return[]}async addComment(){}async updateComment(){return null}async removeComment(){}async setAll(){}async clear(){}};function G(o){if(!o||typeof o!="object")return!1;let e=o;return typeof e.load=="function"&&typeof e.save=="function"&&typeof e.clear=="function"&&typeof e.addComment!="function"}function se(o){if(!G(o))return o;let e=!1,t=()=>{e||(e=!0,typeof console<"u"&&console.warn("[vizu] StorageAdapter v1 detected. Per-comment ops are emulated via full-array rewrites \u2014 upgrade your adapter to the v2 interface (addComment / updateComment / removeComment / setAll / load / clear) when you can."))};return{async load(n){return t(),o.load(n)},async addComment(n,i){t();let r=await o.load(n);r.push(i),await o.save(n,r)},async updateComment(n,i,r){t();let s=await o.load(n),a=s.findIndex(c=>c.id===i);if(a===-1)return null;let l={...s[a],...r,id:s[a].id};return s[a]=l,await o.save(n,s),l},async removeComment(n,i){t();let r=await o.load(n);await o.save(n,r.filter(s=>s.id!==i))},async setAll(n,i){t(),await o.save(n,i)},async clear(n){await o.clear(n)}}}var Te="https://vizu.unhingged.com",oe=480,ae=640,A=class{constructor(e){this.cachedToken=null;this.pendingAuth=null;this.lastNotifiedTokenId=null;this.accessDenied=!1;this.accessDeniedReason=null;this.workspace=e.workspace,this.apiUrl=(e.apiUrl??Te).replace(/\/$/,""),this.autoSignIn=e.autoSignIn!==!1,this.onAuthChanged=e.onAuthChanged;let t=this.readHashToken();t?(this.cachedToken=t,this.writeStoredToken(t)):this.cachedToken=this.readStoredToken(),this.cachedToken&&!this.isExpired(this.cachedToken)&&this.fireAuthChanged(this.cachedToken)}readHashToken(){if(typeof window>"u")return null;let e=window.location.hash;if(!e||e.length<2)return null;let t=new URLSearchParams(e.slice(1)),n=t.get("vizu_auth");if(!n)return null;try{let i=Uint8Array.from(atob(n),p=>p.charCodeAt(0)),r=new TextDecoder("utf-8").decode(i),s=JSON.parse(r);if(!s.t||!s.e||!s.u||!s.w||s.w!==this.workspace)return null;let a={token:s.t,expiresAt:s.e,userId:s.u,user:typeof s.n=="string"?{id:s.u,name:s.n,avatarUrl:typeof s.a=="string"?s.a:void 0}:null};t.delete("vizu_auth");let l=t.toString(),c=l?`#${l}`:"";try{let p=window.location.pathname+window.location.search+c;window.history.replaceState(null,"",p)}catch{}return a}catch{return null}}async preflightAuth(){await this.resolveToken()}isAccessDenied(){return this.accessDenied}accessDenialReason(){return this.accessDeniedReason}async searchMentionable(){if(!this.cachedToken||this.isExpired(this.cachedToken))return[];try{let e=await this.fetchAuthed(this.apiUrl+"/api/workspaces/"+encodeURIComponent(this.workspace)+"/mentionable",{method:"GET"});if(!e.ok)return[];let t=await this.parseJson(e);return Array.isArray(t?.users)?t.users:[]}catch{return[]}}async load(e){if(!this.cachedToken||this.isExpired(this.cachedToken)){let i=this.readStoredToken();if(!i||this.isExpired(i))return[];this.cachedToken=i}let t=[],n=null;do{let i=new URL(this.apiUrl+"/api/comments");i.searchParams.set("workspace",this.workspace),i.searchParams.set("limit","100"),n&&i.searchParams.set("cursor",n);let r=await this.fetchAuthed(i.toString(),{method:"GET"}),s=await this.parseJson(r);if(!r.ok)throw x(r.status,s);let a=Array.isArray(s.comments)?s.comments:[];t.push(...k(a)),n=typeof s.nextCursor=="string"?s.nextCursor:null}while(n);return t}async addComment(e,t){let n=await this.fetchAuthed(this.apiUrl+"/api/comments",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({workspace:this.workspace,comment:t})}),i=await this.parseJson(n);if(!n.ok)throw x(n.status,i)}async updateComment(e,t,n){let i=new URL(this.apiUrl+"/api/comments/"+encodeURIComponent(t));i.searchParams.set("workspace",this.workspace);let r=await this.fetchAuthed(i.toString(),{method:"PATCH",headers:{"content-type":"application/json"},body:JSON.stringify(n)});if(r.status===404)return null;let s=await this.parseJson(r);if(!r.ok)throw x(r.status,s);return C(s.comment)}async removeComment(e,t){let n=new URL(this.apiUrl+"/api/comments/"+encodeURIComponent(t));n.searchParams.set("workspace",this.workspace);let i=await this.fetchAuthed(n.toString(),{method:"DELETE"});if(i.status!==404&&!i.ok){let r=await this.parseJson(i);throw x(i.status,r)}}async setAll(e,t){await this.clear(e);for(let n of t)await this.addComment(e,n)}async clear(e){let t=new URL(this.apiUrl+"/api/comments");t.searchParams.set("workspace",this.workspace),t.searchParams.set("all","true");let n=await this.fetchAuthed(t.toString(),{method:"DELETE"});if(n.status!==404&&!n.ok){let i=await this.parseJson(n);throw x(n.status,i)}}async addReply(e,t,n){let i=new URL(this.apiUrl+"/api/comments/"+encodeURIComponent(t)+"/replies");i.searchParams.set("workspace",this.workspace);let r=await this.fetchAuthed(i.toString(),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(n)});if(r.status===404)return null;let s=await this.parseJson(r);if(!r.ok)throw x(r.status,s);return s?.comment?C(s.comment):null}async removeReply(e,t,n){let i=new URL(this.apiUrl+"/api/comments/"+encodeURIComponent(t)+"/replies/"+encodeURIComponent(n));i.searchParams.set("workspace",this.workspace);let r=await this.fetchAuthed(i.toString(),{method:"DELETE"});if(r.status===404)return null;if(!r.ok){let s=await this.parseJson(r);throw x(r.status,s)}return null}async uploadAttachment(e,t){let n=new FormData;n.append("file",t,t.name);let i=new URL(this.apiUrl+"/api/uploads");i.searchParams.set("workspace",this.workspace);let r=await this.fetchAuthed(i.toString(),{method:"POST",body:n}),s=await this.parseJson(r);if(!r.ok)throw x(r.status,s);if(!s?.url||typeof s.url!="string")throw x(500,{error:"upload_failed",message:"Backend did not return a URL."});return{id:F(),url:s.url,mimeType:t.type||"application/octet-stream",sizeBytes:t.size,uploadedAt:Date.now(),filename:t.name}}getAuthContext(){return this.cachedToken?{userId:this.cachedToken.userId,token:this.cachedToken.token,expiresAt:this.cachedToken.expiresAt}:null}isExpired(e){if(!e)return!0;let t=new Date(e.expiresAt).getTime();return!Number.isFinite(t)||t-Date.now()<3e4}readStoredToken(){if(typeof sessionStorage>"u")return null;let e=sessionStorage.getItem(this.sessionKey());if(!e)return null;try{let t=JSON.parse(e);return this.isExpired(t)?(sessionStorage.removeItem(this.sessionKey()),null):t}catch{return null}}writeStoredToken(e){this.cachedToken=e,typeof sessionStorage<"u"&&sessionStorage.setItem(this.sessionKey(),JSON.stringify(e))}clearStoredToken(){this.cachedToken=null,typeof sessionStorage<"u"&&sessionStorage.removeItem(this.sessionKey())}sessionKey(){return`vizu:cloud-token:v2:${this.workspace}`}async resolveToken(){if(this.cachedToken&&!this.isExpired(this.cachedToken))return this.cachedToken;let e=this.readStoredToken();if(e)return this.cachedToken=e,this.fireAuthChanged(e),e;if(this.accessDenied)throw L("access_denied",`No access to workspace "${this.workspace}" (${this.accessDeniedReason??"no_access"}).`);if(!this.autoSignIn)throw L("auth_required","Sign-in required; autoSignIn is disabled.");return this.pendingAuth||(this.pendingAuth=this.openSignInPopup().then(t=>(this.writeStoredToken(t),this.fireAuthChanged(t),t)).finally(()=>{this.pendingAuth=null})),this.pendingAuth}fireAuthChanged(e){if(this.lastNotifiedTokenId!==e.token){this.lastNotifiedTokenId=e.token;try{this.onAuthChanged?.({userId:e.userId,user:e.user})}catch(t){typeof console<"u"&&console.warn("[vizu/cloud] onAuthChanged callback threw",t)}}}openSignInPopup(){return new Promise((e,t)=>{if(typeof window>"u")return t(L("auth_unavailable","Sign-in requires a browser environment."));let n=new URL(this.apiUrl).origin,i=window.location.origin,r=this.apiUrl+"/connect?workspace="+encodeURIComponent(this.workspace)+"&origin="+encodeURIComponent(i),s=Math.max(0,Math.round((window.screen.width-oe)/2)),a=Math.max(0,Math.round((window.screen.height-ae)/2)),l=window.open(r,"vizu-connect",`width=${oe},height=${ae},left=${s},top=${a},noopener=no,popup=yes`);if(!l)try{let v=window.location.href,f=this.apiUrl+"/connect?workspace="+encodeURIComponent(this.workspace)+"&origin="+encodeURIComponent(i)+"&return_to="+encodeURIComponent(v);window.location.assign(f);return}catch(v){return t(L("popup_blocked","Sign-in popup was blocked and redirect fallback failed: "+(v instanceof Error?v.message:String(v))))}let c=!1,p=v=>{if(v.origin!==n)return;let f=v.data;if(!f)return;if(f.type==="vizu:auth-denied"&&f.workspace===this.workspace){c=!0,$(),this.accessDenied=!0,this.accessDeniedReason=typeof f.reason=="string"?f.reason:"no_access",t(L("access_denied",`No access to workspace "${this.workspace}" (${this.accessDeniedReason}).`));return}if(f.type!=="vizu:auth"||f.workspace!==this.workspace||typeof f.token!="string"||typeof f.expiresAt!="string"||typeof f.userId!="string")return;c=!0,$();let b=f.user,u=b&&typeof b.name=="string"?{id:typeof b.id=="string"?b.id:f.userId,name:b.name,avatarUrl:typeof b.avatarUrl=="string"?b.avatarUrl:void 0}:null;e({token:f.token,expiresAt:f.expiresAt,userId:f.userId,user:u})},m=window.setInterval(()=>{l.closed&&(c||($(),t(L("auth_canceled","Sign-in popup was closed before completing."))))},500);function $(){window.clearInterval(m),window.removeEventListener("message",p)}window.addEventListener("message",p)})}async fetchAuthed(e,t,n=!1){let i=await this.resolveToken(),r=new Headers(t.headers);r.set("authorization",`Bearer ${i.token}`);let s=await fetch(e,{...t,headers:r,credentials:"omit"});return s.status===401&&!n?(this.clearStoredToken(),this.fetchAuthed(e,t,!0)):s}async parseJson(e){try{let t=await e.text();return t?JSON.parse(t):null}catch{return null}}};function L(o,e){let t=new Error(e);return t.code=o,t}function x(o,e){let t=e?.error==="origin_not_allowed"?"origin_not_allowed":e?.error==="not_found"?"workspace_not_found":"http_error",n=new Error(e?.message??`HTTP ${o}`);return n.code=t,n.status=o,n.body=e,n}function le(o){let e=[],t=o,n=0;for(;t&&t!==document.documentElement&&n<8;){let i=t.tagName.toLowerCase();if(t.id){e.unshift("#"+CSS.escape(t.id));break}let r=Array.from(t.classList).filter(a=>!a.startsWith("vz-")&&!a.startsWith("vizu-")).slice(0,2);r.length&&(i+="."+r.map(a=>CSS.escape(a)).join("."));let s=t.parentElement;if(s){let a=Array.from(s.children).filter(l=>l.tagName===t.tagName);if(a.length>1){let l=a.indexOf(t);i+=":nth-of-type("+(l+1)+")"}}e.unshift(i),t=s,n++}return e.join(" > ")}function _(o){let e=o.innerText||o.textContent||"",t=o.parentElement,n=0;return t&&(n=Array.from(t.children).indexOf(o)),{selector:le(o),parentSelector:t?le(t):"",tagName:o.tagName,textSnippet:e.trim().slice(0,80),siblingIndex:n,attributes:{id:o.id||void 0,classList:Array.from(o.classList).filter(i=>!i.startsWith("vz-")&&!i.startsWith("vizu-")),role:o.getAttribute("role")||void 0,ariaLabel:o.getAttribute("aria-label")||void 0,dataKey:o.getAttribute("data-vizu-key")||void 0},ancestorChain:Me(o,4),algorithmVersion:2}}function Me(o,e){let t=[],n=o.parentElement;for(;n&&t.length<e;){let i=n.parentElement,r=1;i&&(r=Array.from(i.children).filter(a=>a.tagName===n.tagName).indexOf(n)+1),t.push({tag:n.tagName,nthOfType:r}),n=i}return t.length>0?{steps:t}:void 0}function j(o,e=document){if(o.attributes.dataKey){try{let s=e.querySelector(`[data-vizu-key="${CSS.escape(o.attributes.dataKey)}"]`);if(s)return{element:s,confidence:"exact"}}catch{}return{element:null,confidence:"orphaned"}}if(o.attributes.id)try{let s=e.querySelector("#"+CSS.escape(o.attributes.id));if(s)return{element:s,confidence:"exact"}}catch{}let t=[],n=o.attributes.classList;if(n&&n.length>0){let s=Ve(e,o.tagName,n);s?.element&&t.push({el:s.element,rung:"class"})}try{let s=e.querySelector(o.selector);s&&t.push({el:s,rung:"selector"})}catch{}if(o.ancestorChain&&o.ancestorChain.steps.length>0){let s=Le(e,o.tagName,o.ancestorChain.steps);s?.element&&t.push({el:s.element,rung:"chain"})}else try{let s=o.parentSelector?e.querySelector(o.parentSelector):e;if(s){let a=s.children[o.siblingIndex];a&&a.tagName===o.tagName&&t.push({el:a,rung:"chain"})}}catch{}if(o.textSnippet){let s=Pe(e,o.tagName,o.textSnippet);s?.element&&t.push({el:s.element,rung:"text"})}if(t.length===0)return{element:null,confidence:"orphaned"};let i=new Map;for(let s of t){let a=i.get(s.el);a||(a=new Set,i.set(s.el,a)),a.add(s.rung)}let r=null;for(let[s,a]of i)(!r||a.size>r.rungs.size)&&(r={el:s,rungs:a});return r?r.rungs.size>=3?{element:r.el,confidence:"likely"}:r.rungs.size>=2?{element:r.el,confidence:"drifted"}:r.rungs.has("class")||r.rungs.has("chain")?{element:r.el,confidence:"drifted"}:{element:null,confidence:"orphaned"}:{element:null,confidence:"orphaned"}}function Ve(o,e,t){let n=new Set(t.filter(a=>!a.startsWith("vz-")&&!a.startsWith("vizu-")));if(n.size===0)return null;let i=o.querySelectorAll(e.toLowerCase()),r=null,s=0;for(let a of i){let l=new Set(Array.from(a.classList).filter(p=>!p.startsWith("vz-")&&!p.startsWith("vizu-")));if(l.size===0)continue;let c=He(n,l);c<.6||(!r||c>r.score?(s=r?.score??0,r={el:a,score:c}):c>s&&(s=c))}return!r||r.score-s<.1?null:{element:r.el,confidence:"likely"}}function Le(o,e,t){let n=o.querySelectorAll(e.toLowerCase()),i=null;for(let r of n){let s=Re(r,t.length+3),a=Ue(s,t,3);a<2||(!i||a>i.score)&&(i={el:r,score:a})}return i?{element:i.el,confidence:i.score===t.length?"likely":"drifted"}:null}function Re(o,e){let t=[],n=o.parentElement;for(;n&&t.length<e;){let i=n.parentElement,r=1;i&&(r=Array.from(i.children).filter(a=>a.tagName===n.tagName).indexOf(n)+1),t.push({tag:n.tagName,nthOfType:r}),n=i}return t}function Pe(o,e,t){let n=ce(t);if(!n)return null;let i=o.querySelectorAll(e.toLowerCase()),r=null;for(let s of i){let a=s.innerText||s.textContent||"",l=ce(a.slice(0,160));if(!l)continue;let c=$e(n,l);c<.75||(!r||c>r.score)&&(r={el:s,score:c})}return r?{element:r.el,confidence:"drifted"}:null}function ce(o){return o.toLowerCase().replace(/\s+/g," ").trim()}function $e(o,e){if(o===e)return 1;if(o.length===0||e.length===0)return o.length===e.length?1:0;let t=Math.max(o.length,e.length);return 1-Fe(o,e)/t}function Fe(o,e){if(o.length>e.length){let i=o;o=e,e=i}let t=new Array(o.length+1),n=new Array(o.length+1);for(let i=0;i<=o.length;i++)t[i]=i;for(let i=1;i<=e.length;i++){n[0]=i;for(let r=1;r<=o.length;r++){let s=o.charCodeAt(r-1)===e.charCodeAt(i-1)?0:1;n[r]=Math.min(n[r-1]+1,t[r]+1,t[r-1]+s)}for(let r=0;r<=o.length;r++)t[r]=n[r]}return t[o.length]}function Ue(o,e,t){let n=0;for(let i=0;i<=t;i++){let r=0;for(let s=0;s<e.length;s++){let a=o[s+i];if(!a)break;a.tag===e[s].tag&&a.nthOfType===e[s].nthOfType&&r++}r>n&&(n=r)}return n}function He(o,e){if(o.size===0&&e.size===0)return 1;let t=0;for(let i of o)e.has(i)&&t++;let n=o.size+e.size-t;return n===0?0:t/n}function R(o,e){return j(o,e).element}function h(o){return o.selector+"|"+o.textSnippet}function P(o){let e=o.tagName.toLowerCase();if(o.textSnippet){let t=o.textSnippet.length>24?o.textSnippet.slice(0,24)+"\u2026":o.textSnippet;return e+": "+t}return o.attributes.id?e+"#"+o.attributes.id:o.attributes.classList&&o.attributes.classList.length?e+"."+o.attributes.classList[0]:e}var Ie="[data-vizu-root], [data-vizu-ignore], script, style, link, meta, head",q=class{constructor(e,t,n){this.current=null;this.active=!1;this.paused=!1;this.handleMove=e=>{if(this.paused){this.setCurrent(null),this.overlay.style.display="none";return}let t=document.elementFromPoint(e.clientX,e.clientY);if(!(!t||t===this.current)){if(this.shouldIgnore(t)){this.setCurrent(null),this.overlay.style.display="none";return}this.setCurrent(t),this.updateOverlay()}};this.handleClick=e=>{let t=document.elementFromPoint(e.clientX,e.clientY);t&&(this.shouldIgnore(t)||(e.preventDefault(),e.stopPropagation(),this.onClick(t,e)))};this.handleScroll=()=>{this.current&&this.updateOverlay()};this.root=e,this.extraIgnore=t,this.onClick=n,this.overlay=document.createElement("div"),this.overlay.className="vz-highlight",this.overlay.style.display="none",this.root.appendChild(this.overlay)}setCurrent(e){this.current!==e&&(this.current=e)}start(){this.active||(this.active=!0,document.addEventListener("mousemove",this.handleMove,!0),document.addEventListener("click",this.handleClick,!0),document.addEventListener("scroll",this.handleScroll,!0),window.addEventListener("resize",this.handleScroll))}stop(){this.active&&(this.active=!1,document.removeEventListener("mousemove",this.handleMove,!0),document.removeEventListener("click",this.handleClick,!0),document.removeEventListener("scroll",this.handleScroll,!0),window.removeEventListener("resize",this.handleScroll),this.overlay.style.display="none",this.setCurrent(null))}shouldIgnore(e){if(e===document.documentElement||e===document.body||Y(e,Ie))return!0;for(let t of this.extraIgnore)try{if(Y(e,t))return!0}catch{}return!1}setPaused(e){this.paused=e,e&&(this.setCurrent(null),this.overlay.style.display="none")}isPaused(){return this.paused}updateOverlay(){if(!this.current)return;let e=this.current.getBoundingClientRect();if(e.width===0||e.height===0){this.overlay.style.display="none";return}this.overlay.style.display="block",this.overlay.style.left=e.left+"px",this.overlay.style.top=e.top+"px",this.overlay.style.width=e.width+"px",this.overlay.style.height=e.height+"px"}destroy(){this.stop(),this.overlay.remove()}};function de(o){return typeof CSS<"u"&&typeof CSS.escape=="function"?CSS.escape(o):o.replace(/["\\]/g,"\\$&")}function Oe(o){let t=(o.replies??[]).map(n=>`
|
|
11
11
|
<div class="vz-reply" data-reply-id="${d(n.id)}">
|
|
12
|
-
${n.author?`<div class="vz-comment-author">${z(n.author)} <span class="vz-comment-author-name">${d(n.author.name)}</span></div>`:""}
|
|
12
|
+
${n.author?`<div class="vz-comment-author">${z(n.author)} <span class="vz-comment-author-name">${d(n.author.name||n.author.id||"User")}</span></div>`:""}
|
|
13
13
|
<div class="vz-reply-text">${d(n.text)}</div>
|
|
14
14
|
<div class="vz-comment-meta">
|
|
15
15
|
<span>${d(T(typeof n.createdAt=="number"?n.createdAt:new Date(n.createdAt).getTime()))}</span>
|
|
@@ -34,9 +34,9 @@
|
|
|
34
34
|
<div class="vz-comment-list">
|
|
35
35
|
${e.length===0?'<div class="vz-empty">No comments yet.</div>':e.map(m=>`
|
|
36
36
|
<div class="vz-comment" data-comment-id="${d(m.id)}">
|
|
37
|
-
${m.author?`<div class="vz-comment-author">${z(m.author)} <span class="vz-comment-author-name">${d(m.author.name)}</span></div>`:""}
|
|
38
|
-
<div>${
|
|
39
|
-
${
|
|
37
|
+
${m.author?`<div class="vz-comment-author">${z(m.author)} <span class="vz-comment-author-name">${d(m.author.name||m.author.id||"User")}</span></div>`:""}
|
|
38
|
+
<div>${U(m.text,m.id)}</div>
|
|
39
|
+
${H(m.attachments)}
|
|
40
40
|
<div class="vz-comment-meta">
|
|
41
41
|
<span>${d(T(m.createdAt))}</span>
|
|
42
42
|
<span class="vz-comment-actions">
|
|
@@ -108,8 +108,8 @@
|
|
|
108
108
|
${fe}
|
|
109
109
|
${w!=="open"?`<span class="vz-status-pill vz-status-${w}">${w}</span>`:""}
|
|
110
110
|
</div>
|
|
111
|
-
<span class="vz-sidebar-item-text">${
|
|
112
|
-
${
|
|
111
|
+
<span class="vz-sidebar-item-text">${U(g.text,g.id)}</span>
|
|
112
|
+
${H(g.attachments)}
|
|
113
113
|
${ge}
|
|
114
114
|
<div class="vz-sidebar-item-meta">
|
|
115
115
|
<span>${d(T(g.createdAt))}${(g.fingerprints||[]).length>1?` \xB7 grouped (${(g.fingerprints||[]).length})`:""}${(g.replies?.length??0)>0?` \xB7 ${g.replies.length} ${g.replies.length===1?"reply":"replies"}`:""}</span>
|
|
@@ -155,8 +155,8 @@
|
|
|
155
155
|
<div class="vz-sidebar-orphan-anchor">
|
|
156
156
|
was on <code>${d(r)}</code>${s?` “${d(s)}${(i?.textSnippet?.length??0)>60?"\u2026":""}”`:""}
|
|
157
157
|
</div>
|
|
158
|
-
<span class="vz-sidebar-item-text">${
|
|
159
|
-
${
|
|
158
|
+
<span class="vz-sidebar-item-text">${U(t.text,t.id)}</span>
|
|
159
|
+
${H(t.attachments)}
|
|
160
160
|
<div class="vz-sidebar-item-meta">
|
|
161
161
|
<span>${d(T(t.createdAt))}${n!=="open"?` \xB7 ${n}`:""}</span>
|
|
162
162
|
<span class="vz-sidebar-item-actions">
|