collabmd 0.1.19 → 0.1.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -11
- package/docker-compose.yml +1 -1
- package/package.json +1 -1
- package/public/assets/css/style.css +1 -1
- package/public/assets/js/chunks/chunk-GFDM7YCF.js +1 -0
- package/public/assets/js/chunks/editor-session-EAUBJCHH.js +22 -0
- package/public/assets/js/chunks/{preview-render-compiler-UZ4SZDQQ.js → preview-render-compiler-6Y7TKXFJ.js} +1 -1
- package/public/assets/js/chunks/{quick-switcher-controller-J7I3CUET.js → quick-switcher-controller-A6SKH5HI.js} +1 -1
- package/public/assets/js/{excalidraw-editor-ZDYKMZOL.js → excalidraw-editor-TCIH6GJL.js} +1 -1
- package/public/assets/js/excalidraw-editor.js +1 -1
- package/public/assets/js/main.js +102 -75
- package/public/assets/js/preview-render-worker.js +15 -15
- package/public/index.html +14 -4
- package/src/client/application/app-shell/git-feature.js +86 -19
- package/src/client/application/app-shell/ui-feature.js +4 -0
- package/src/client/application/app-shell-elements.js +1 -0
- package/src/client/bootstrap/collabmd-app-shell.js +16 -0
- package/src/client/domain/vault-utils.js +2 -2
- package/src/client/excalidraw-editor.js +2 -1
- package/src/client/infrastructure/editor-session.js +4 -0
- package/src/client/infrastructure/editor-view-adapter.js +245 -7
- package/src/client/infrastructure/workspace-sync-client.js +324 -0
- package/src/client/presentation/backlinks-panel.js +157 -101
- package/src/client/presentation/comment-ui-controller.js +233 -10
- package/src/client/presentation/file-explorer-controller.js +15 -3
- package/src/client/presentation/file-explorer-view.js +152 -11
- package/src/client/presentation/git-panel-controller.js +73 -0
- package/src/client/presentation/outline-controller.js +25 -0
- package/src/client/styles/style.css +184 -9
- package/src/domain/wiki-link-resolver.js +16 -5
- package/src/domain/workspace-change.js +68 -0
- package/src/domain/workspace-room.js +3 -0
- package/src/server/create-app-server.js +41 -10
- package/src/server/domain/backlink-index.js +94 -1
- package/src/server/domain/collaboration/collaboration-room.js +191 -22
- package/src/server/domain/collaboration/room-registry.js +64 -10
- package/src/server/infrastructure/git/errors.js +4 -1
- package/src/server/infrastructure/git/git-service.js +215 -1
- package/src/server/infrastructure/git/responses.js +12 -19
- package/src/server/infrastructure/http/create-git-api-command-handler.js +58 -43
- package/src/server/infrastructure/http/create-git-api-handler.js +2 -0
- package/src/server/infrastructure/http/create-git-api-query-handler.js +16 -1
- package/src/server/infrastructure/http/create-request-handler.js +7 -0
- package/src/server/infrastructure/http/create-vault-api-command-handler.js +58 -14
- package/src/server/infrastructure/http/create-vault-api-handler.js +3 -0
- package/src/server/infrastructure/http/create-vault-api-query-handler.js +3 -1
- package/src/server/infrastructure/http/http-response.js +65 -28
- package/src/server/infrastructure/persistence/pull-backup-store.js +283 -0
- package/src/server/infrastructure/persistence/vault-file-store.js +179 -52
- package/src/server/infrastructure/workspace/file-system-sync-service.js +488 -0
- package/src/server/infrastructure/workspace/workspace-mutation-coordinator.js +551 -0
- package/public/assets/js/chunks/chunk-R3DDMJHH.js +0 -1
- package/public/assets/js/chunks/editor-session-AH6Z3MXW.js +0 -22
package/public/assets/js/main.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{C as
|
|
1
|
+
import{C as Xt,a as _t,b as C,c as pe,d as Kt,e as jt,k as Ce,t as Ee,u as Se,v as Qt,w as Yt,x as Zt,y as ke,z as vt}from"./chunks/chunk-HEWVH67U.js";import{a as zt,b as fe,d as Vt,e as be}from"./chunks/chunk-5QRWYPYT.js";import{a as g,b as Ht,c as x,e as Ut,f as $t,g as Ot,h as Z,i as qt,j as ge,k as we,l as ye,m as Wt,n as Gt,o as ve,p as q}from"./chunks/chunk-GFDM7YCF.js";import"./chunks/chunk-775E65SU.js";var en={edit:`
|
|
2
2
|
<svg viewBox="0 0 16 16" aria-hidden="true" focusable="false">
|
|
3
3
|
<path d="M11.8 1.8a1.5 1.5 0 0 1 2.1 2.1l-7.2 7.2-3.2.9.9-3.2z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.4"/>
|
|
4
4
|
<path d="M10.7 2.9l2.4 2.4" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.4"/>
|
|
@@ -17,50 +17,50 @@ import{C as qt,a as kt,b,c as xt,d as Nt,e as Ht,k as Dt,t as _t,u as be,v as zt
|
|
|
17
17
|
<path d="M6 5V2H2M10 5V2h4M10 11v3h4M6 11v3H2" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.4"/>
|
|
18
18
|
<path d="M4.5 4.5h7v7h-7z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.4"/>
|
|
19
19
|
</svg>
|
|
20
|
-
`};function T(n,e){if(!(n instanceof HTMLElement))return;let t=Ui[e];if(!t){n.classList.remove("is-icon-only");return}n.classList.add("is-icon-only"),n.dataset.icon=e,n.innerHTML=t.trim()}var L={default:1,animationDurationMs:160,max:3,min:.5,step:.1},k={default:1,animationDurationMs:160,max:3,min:.1,step:.1},W=500,Wt=2,Vt=2;function te(n,e){return typeof window.requestIdleCallback=="function"?window.requestIdleCallback(n,{timeout:e}):window.setTimeout(()=>{n({didTimeout:!1,timeRemaining:()=>0})},1)}function ie(n){if(n!==null){if(typeof window.cancelIdleCallback=="function"){window.cancelIdleCallback(n);return}window.clearTimeout(n)}}function X(n,e,t){let i=e.getAttribute(t);if(i===null){n.removeAttribute(t);return}n.setAttribute(t,i)}function ce(n){let e=n.viewBox?.baseVal,t=Number.parseFloat(n.getAttribute("width")||""),i=Number.parseFloat(n.getAttribute("height")||""),s=n.getBoundingClientRect(),r=typeof n.getBBox=="function"?n.getBBox():null;return{height:e?.height||r?.height||i||s.height||480,width:e?.width||r?.width||t||s.width||640}}function Kt(n){if(!n||typeof n.getBBox!="function")return ce(n);try{let e=n.getBBox();if(!Number.isFinite(e.width)||!Number.isFinite(e.height)||e.width<=0||e.height<=0)return ce(n);let t=16,i=e.x-t,s=e.y-t,r=e.width+t*2,a=e.height+t*2;return n.setAttribute("viewBox",`${i} ${s} ${r} ${a}`),n.setAttribute("width",String(r)),n.setAttribute("height",String(a)),n.setAttribute("preserveAspectRatio","xMinYMin meet"),{width:r,height:a}}catch{return ce(n)}}function j(n){let e=window.getComputedStyle(n),t=Number.parseFloat(e.paddingLeft||"0")+Number.parseFloat(e.paddingRight||"0"),i=Number.parseFloat(e.paddingTop||"0")+Number.parseFloat(e.paddingBottom||"0");return{height:Math.max(n.clientHeight-i,0),width:Math.max(n.clientWidth-t,0)}}function Ce(n){return 1-(1-n)**3}function Gt(n){return mt(n,{label:"Mermaid diagram",message:"Loads when visible"})}function mt(n,{label:e="Mermaid diagram",message:t="Loads when visible"}={}){let i=document.createElement("div");i.className="mermaid-placeholder-card";let s=document.createElement("div");s.className="mermaid-placeholder-copy";let r=document.createElement("strong");r.textContent=e;let a=document.createElement("span");a.textContent=t;let o=document.createElement("button");return o.type="button",o.className="mermaid-placeholder-btn",o.dataset.mermaidKey=n,o.textContent="Render",s.append(r,a),i.append(s,o),i}function pt(n,e="Renders server-side when visible"){let t=document.createElement("div");t.className="plantuml-placeholder-card";let i=document.createElement("div");i.className="plantuml-placeholder-copy";let s=document.createElement("strong");s.textContent="PlantUML diagram";let r=document.createElement("span");r.textContent=e;let a=document.createElement("button");return a.type="button",a.className="plantuml-placeholder-btn",a.dataset.plantumlKey=n,a.textContent="Render",i.append(s,r),t.append(i,a),t}function jt(n){let t=new DOMParser().parseFromString(n,"image/svg+xml"),i=t.documentElement;if(!i||i.nodeName.toLowerCase()!=="svg")throw new Error("Renderer returned invalid SVG");return t.querySelectorAll("script, foreignObject").forEach(s=>{s.remove()}),Array.from(t.querySelectorAll("*")).forEach(s=>{Array.from(s.attributes).forEach(r=>{let a=r.name.toLowerCase(),o=r.value||"";if(a.startsWith("on")){s.removeAttribute(r.name);return}(a==="href"||a==="xlink:href")&&/^\s*javascript:/i.test(o)&&s.removeAttribute(r.name)})}),i.outerHTML}function Qt({nextSource:n="",nextTarget:e="",preservedSource:t="",preservedTarget:i=""}={}){return n?n===t:e?e===i:!1}function Zt(n,e,t){if(!n||!e)return!1;let i=e.getBoundingClientRect(),s=n.getBoundingClientRect();return s.bottom>=i.top-t&&s.top<=i.bottom+t}function $i(n){return`data-${n.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`)}`}var ne=class{constructor(e,{batchSize:t,datasetKeys:i,fetchFn:s=(...d)=>fetch(...d),filePathLabel:r,requestIdleRenderFn:a=te,cancelIdleRenderFn:o=ie,intersectionObserverFactory:l=(d,g)=>new IntersectionObserver(d,g),isNearViewportFn:h=Zt,requestAnimationFrameFn:c=d=>requestAnimationFrame(d),shellClassName:u,sourceClassName:f}){this.renderer=e,this.batchSize=t,this.datasetKeys=i,this.fetchFn=s,this.filePathLabel=r,this.requestIdleRenderFn=a,this.cancelIdleRenderFn=o,this.intersectionObserverFactory=l,this.isNearViewportFn=h,this.requestAnimationFrameFn=c,this.shellClassName=u,this.sourceClassName=f,this.shellSelector=`.${u}`,this.sourceSelector=`.${f}`,this.attributeNames=Object.fromEntries(Object.entries(i).map(([d,g])=>[d,$i(g)])),this.observer=null,this.idleId=null,this.pendingShells=[],this.hydrationInProgress=!1,this.instanceCounter=0,this.preservedShells=new Map,this.fileInflightRequests=new Map}destroy(){this.cancelHydration(),this.preservedShells.clear()}cancelHydration(){this.observer&&(this.observer.disconnect(),this.observer=null),this.cancelIdleRenderFn(this.idleId),this.idleId=null,this.pendingShells=[],this.hydrationInProgress=!1}cancelPendingIdleWork(){this.cancelIdleRenderFn(this.idleId),this.idleId=null}clearPreservedShells(){this.preservedShells.clear()}hasPendingWork(){return this.hydrationInProgress||this.pendingShells.length>0}preserveHydratedShellsForCommit(){this.preservedShells.clear();let e=this.renderer.previewElement;e&&Array.from(e.querySelectorAll(`${this.shellSelector}[${this.attributeNames.hydrated}="true"][${this.attributeNames.key}]`)).forEach(t=>{let i=t.dataset[this.datasetKeys.key],s=t.querySelector(this.sourceSelector)?.textContent??"",r=t.dataset[this.datasetKeys.target]??"";!i||!s&&!r||(t.isConnected&&t.remove(),this.preservedShells.set(i,{key:i,shell:t,source:s,target:r}))})}reconcileHydratedShells(){let e=this.renderer.previewElement;if(!e||this.preservedShells.size===0){this.preservedShells.clear();return}let t=!1;Array.from(e.querySelectorAll(`${this.shellSelector}[${this.attributeNames.key}]`)).forEach(i=>{let s=i.dataset[this.datasetKeys.key],r=s?this.preservedShells.get(s):null;if(!r)return;let a=i.querySelector(this.sourceSelector)?.textContent??"",o=i.dataset[this.datasetKeys.target]??"";Qt({nextSource:a,nextTarget:o,preservedSource:r.source,preservedTarget:r.target})&&(this.syncPreservedShell(r.shell,i),i.replaceWith(r.shell),t=t||r.shell.classList.contains("is-maximized"),this.preservedShells.delete(s))}),this.preservedShells.clear(),this.handleReconcile({restoredMaximizedShell:t})}handleReconcile(){}syncPreservedShell(e,t){X(e,t,this.attributeNames.sourceLine),X(e,t,this.attributeNames.sourceLineEnd),X(e,t,this.attributeNames.key),X(e,t,this.attributeNames.target),X(e,t,this.attributeNames.label),X(e,t,this.attributeNames.sourceHash),e.classList.add(this.shellClassName),e.dataset[this.datasetKeys.hydrated]="true",this.removeDatasetValue(e,"queued");let i=t.querySelector(this.sourceSelector),s=e.querySelector(this.sourceSelector);if(!s&&i&&(s=i.cloneNode(!0),e.prepend(s)),s&&i){let r=i.textContent??"";(r||!t.dataset[this.datasetKeys.target])&&(s.textContent=r),s.hidden=!0}}setupHydration(e){let t=this.renderer.previewElement,i=this.renderer.previewContainer;if(!t||!i)return 0;let s=Array.from(t.querySelectorAll(this.shellSelector));return s.length===0?0:(this.observer=this.intersectionObserverFactory(r=>{r.forEach(a=>{a.isIntersecting&&this.enqueueShell(a.target)})},{root:i,rootMargin:this.renderer.isLargeDocument?"180px 0px":"420px 0px"}),s.forEach(r=>this.observer.observe(r)),this.requestAnimationFrameFn(()=>{e===this.renderer.activeRenderVersion&&(this.hydrateVisibleShells(),this.renderer.updateHydrationPhase())}),s.length)}hydrateVisibleShells(){let e=this.renderer.previewElement,t=this.renderer.previewContainer;if(this.renderer.hydrationPaused||!e||!t)return;let i=this.renderer.isLargeDocument?180:420;Array.from(e.querySelectorAll(this.shellSelector)).forEach(s=>{this.isNearViewportFn(s,t,i)&&this.enqueueShell(s,{prioritize:!0})})}enqueueShell(e,{prioritize:t=!1}={}){!e?.isConnected||this.isShellHydrated(e)||this.isShellQueued(e)||(e.dataset[this.datasetKeys.queued]="true",t?this.pendingShells.unshift(e):this.pendingShells.push(e),!this.renderer.hydrationPaused&&(this.renderer.updateHydrationPhase(),this.scheduleHydration()))}scheduleHydration(){this.renderer.hydrationPaused||this.hydrationInProgress||this.idleId!==null||(this.idleId=this.requestIdleRenderFn(()=>{this.idleId=null,this.flushHydrationQueue()},W))}async flushHydrationQueue(){if(this.renderer.hydrationPaused||this.hydrationInProgress)return;let e=[];for(;this.pendingShells.length>0&&e.length<this.batchSize;){let i=this.pendingShells.shift();!i?.isConnected||this.isShellHydrated(i)||(this.removeDatasetValue(i,"queued"),e.push(i))}if(e.length===0){this.renderer.updateHydrationPhase();return}this.hydrationInProgress=!0,this.renderer.setPhase("hydrating");let t=null;try{t=await this.prepareHydrationBatch(e)}catch(i){this.handlePrepareHydrationBatchError(e,i),this.hydrationInProgress=!1,this.renderer.updateHydrationPhase();return}for(let i of e)await this.hydrateShell(i,t);this.hydrationInProgress=!1,this.pendingShells.length>0&&this.scheduleHydration(),this.renderer.updateHydrationPhase()}async prepareHydrationBatch(){return null}handlePrepareHydrationBatchError(e,t){}async hydrateShell(){throw new Error("hydrateShell must be implemented by subclasses")}markShellHydrated(e){e.dataset[this.datasetKeys.hydrated]="true",e.dataset[this.datasetKeys.instanceId]=String(++this.instanceCounter)}isShellHydrated(e){return e?.dataset?.[this.datasetKeys.hydrated]==="true"}removeDatasetValue(e,t){let i=this.datasetKeys[t];!i||!e||(e.removeAttribute?.(this.attributeNames[t]),e.dataset&&delete e.dataset[i])}isShellQueued(e){return e?.dataset?.[this.datasetKeys.queued]==="true"}async fetchSource(e){let t=String(e??"").trim();if(!t)throw new Error(`Missing ${this.filePathLabel} file path`);if(this.fileInflightRequests.has(t))return this.fileInflightRequests.get(t);let i=this.fetchFn(b(`/file?path=${encodeURIComponent(t)}`),{headers:{Accept:"application/json"}}).then(async s=>{let r=await s.json().catch(()=>null);if(!s.ok||typeof r?.content!="string")throw new Error(r?.error||`Failed to load ${t}`);return r.content}).finally(()=>{this.fileInflightRequests.delete(t)});return this.fileInflightRequests.set(t,i),i}};var Ee=class extends ne{constructor(e){super(e,{batchSize:Wt,datasetKeys:{hydrated:"mermaidHydrated",instanceId:"mermaidInstanceId",key:"mermaidKey",label:"mermaidLabel",queued:"mermaidQueued",sourceHash:"mermaidSourceHash",sourceLine:"sourceLine",sourceLineEnd:"sourceLineEnd",target:"mermaidTarget"},filePathLabel:"Mermaid",shellClassName:"mermaid-shell",sourceClassName:"mermaid-source"}),this.renderer=e,this.currentTheme=document.documentElement?.dataset.theme==="light"?"light":"dark",this.loader=null,this.runtime=null,this.shellRefits=new WeakMap}applyTheme(e){this.currentTheme=e;let t=this.runtime;t&&(this.configureMermaid(t),this.resetHydratedShells())}configureMermaid(e){e.initialize({startOnLoad:!1,flowchart:{defaultRenderer:"dagre-wrapper",useMaxWidth:!0},class:{defaultRenderer:"dagre-wrapper",useMaxWidth:!0},theme:this.currentTheme==="dark"?"dark":"default",themeVariables:this.currentTheme==="dark"?{background:"#161822",clusterBkg:"#1a1c28",edgeLabelBackground:"#161822",lineColor:"#8b8ba0",mainBkg:"#1c1e2c",nodeBorder:"#383a50",primaryBorderColor:"#383a50",primaryColor:"#818cf8",primaryTextColor:"#e2e2ea",secondaryColor:"#1c1e2c",tertiaryColor:"#161822",titleColor:"#e2e2ea"}:{}})}ensureMermaid(){return this.runtime?(this.configureMermaid(this.runtime),Promise.resolve(this.runtime)):this.loader?this.loader:(this.loader=import("./chunks/mermaid-runtime-BIFNJ2CT.js").then(e=>{let t=e?.default;if(!t)throw new Error("Mermaid runtime failed to initialize");return this.runtime=t,this.configureMermaid(t),t}).catch(e=>{throw this.loader=null,this.runtime=null,new Error(e instanceof Error?e.message:"Failed to load Mermaid runtime")}),this.loader)}handleReconcile({restoredMaximizedShell:e}){e&&document.body.classList.add("mermaid-maximized-open")}async prepareHydrationBatch(){return this.ensureMermaid()}handlePrepareHydrationBatchError(e,t){console.warn("[preview] Mermaid runtime failed to load:",t)}async hydrateShell(e,t){if(!t||!e?.isConnected||this.isShellHydrated(e))return;let i=e.querySelector(".mermaid-source");i||(i=document.createElement("span"),i.className="mermaid-source",i.hidden=!0,e.appendChild(i));let s=i.textContent??"";try{if(!s.trim()&&e.dataset.mermaidTarget){if(s=await this.fetchSource(e.dataset.mermaidTarget),!e.isConnected)return;i.textContent=s}if(!s.trim())throw new Error(e.dataset.mermaidTarget?"Mermaid file is empty":"Mermaid source is empty");s=this.prepareSource(s),e.querySelector(".mermaid-placeholder-card")?.remove();let r=document.createElement("div");r.className="mermaid mermaid-render-node",r.id=e.dataset.mermaidKey||`mermaid-${Date.now()}`;let a=e.getAttribute("data-source-line"),o=e.getAttribute("data-source-line-end");if(a&&r.setAttribute("data-source-line",a),o&&r.setAttribute("data-source-line-end",o),r.textContent=s,e.appendChild(r),await t.run({nodes:[r]}),!r.isConnected||e!==r.parentElement)return;this.enhanceDiagram(e,r),this.markShellHydrated(e)}catch(r){console.warn("[preview] Mermaid render failed:",r),e.querySelector(":scope > .mermaid-toolbar")?.remove(),e.querySelector(":scope > .mermaid-frame")?.remove(),e.querySelector(":scope > .mermaid-render-node")?.remove(),e.querySelector(".mermaid-placeholder-card")||i?.after(mt(e.dataset.mermaidKey||"mermaid",{label:e.dataset.mermaidLabel||"Mermaid diagram",message:r instanceof Error?r.message:"Render failed"}))}}prepareSource(e){let t=String(e??"");if(!/%%\{[\s\S]*?\binit\s*:/m.test(t)){let r=this.getPreviewInitConfig(t);r&&(t=`%%{init: ${JSON.stringify(r)}}%%
|
|
20
|
+
`};function T(n,e){if(!(n instanceof HTMLElement))return;let t=en[e];if(!t){n.classList.remove("is-icon-only");return}n.classList.add("is-icon-only"),n.dataset.icon=e,n.innerHTML=t.trim()}var k={default:1,animationDurationMs:160,max:3,min:.5,step:.1},P={default:1,animationDurationMs:160,max:3,min:.1,step:.1},W=500,Jt=2,ei=2;function ie(n,e){return typeof window.requestIdleCallback=="function"?window.requestIdleCallback(n,{timeout:e}):window.setTimeout(()=>{n({didTimeout:!1,timeRemaining:()=>0})},1)}function ne(n){if(n!==null){if(typeof window.cancelIdleCallback=="function"){window.cancelIdleCallback(n);return}window.clearTimeout(n)}}function X(n,e,t){let i=e.getAttribute(t);if(i===null){n.removeAttribute(t);return}n.setAttribute(t,i)}function ce(n){let e=n.viewBox?.baseVal,t=Number.parseFloat(n.getAttribute("width")||""),i=Number.parseFloat(n.getAttribute("height")||""),s=n.getBoundingClientRect(),r=typeof n.getBBox=="function"?n.getBBox():null;return{height:e?.height||r?.height||i||s.height||480,width:e?.width||r?.width||t||s.width||640}}function ti(n){if(!n||typeof n.getBBox!="function")return ce(n);try{let e=n.getBBox();if(!Number.isFinite(e.width)||!Number.isFinite(e.height)||e.width<=0||e.height<=0)return ce(n);let t=16,i=e.x-t,s=e.y-t,r=e.width+t*2,a=e.height+t*2;return n.setAttribute("viewBox",`${i} ${s} ${r} ${a}`),n.setAttribute("width",String(r)),n.setAttribute("height",String(a)),n.setAttribute("preserveAspectRatio","xMinYMin meet"),{width:r,height:a}}catch{return ce(n)}}function j(n){let e=window.getComputedStyle(n),t=Number.parseFloat(e.paddingLeft||"0")+Number.parseFloat(e.paddingRight||"0"),i=Number.parseFloat(e.paddingTop||"0")+Number.parseFloat(e.paddingBottom||"0");return{height:Math.max(n.clientHeight-i,0),width:Math.max(n.clientWidth-t,0)}}function Pe(n){return 1-(1-n)**3}function ii(n){return bt(n,{label:"Mermaid diagram",message:"Loads when visible"})}function bt(n,{label:e="Mermaid diagram",message:t="Loads when visible"}={}){let i=document.createElement("div");i.className="mermaid-placeholder-card";let s=document.createElement("div");s.className="mermaid-placeholder-copy";let r=document.createElement("strong");r.textContent=e;let a=document.createElement("span");a.textContent=t;let o=document.createElement("button");return o.type="button",o.className="mermaid-placeholder-btn",o.dataset.mermaidKey=n,o.textContent="Render",s.append(r,a),i.append(s,o),i}function Ct(n,e="Renders server-side when visible"){let t=document.createElement("div");t.className="plantuml-placeholder-card";let i=document.createElement("div");i.className="plantuml-placeholder-copy";let s=document.createElement("strong");s.textContent="PlantUML diagram";let r=document.createElement("span");r.textContent=e;let a=document.createElement("button");return a.type="button",a.className="plantuml-placeholder-btn",a.dataset.plantumlKey=n,a.textContent="Render",i.append(s,r),t.append(i,a),t}function ni(n){let t=new DOMParser().parseFromString(n,"image/svg+xml"),i=t.documentElement;if(!i||i.nodeName.toLowerCase()!=="svg")throw new Error("Renderer returned invalid SVG");return t.querySelectorAll("script, foreignObject").forEach(s=>{s.remove()}),Array.from(t.querySelectorAll("*")).forEach(s=>{Array.from(s.attributes).forEach(r=>{let a=r.name.toLowerCase(),o=r.value||"";if(a.startsWith("on")){s.removeAttribute(r.name);return}(a==="href"||a==="xlink:href")&&/^\s*javascript:/i.test(o)&&s.removeAttribute(r.name)})}),i.outerHTML}function si({nextSource:n="",nextTarget:e="",preservedSource:t="",preservedTarget:i=""}={}){return n?n===t:e?e===i:!1}function ri(n,e,t){if(!n||!e)return!1;let i=e.getBoundingClientRect(),s=n.getBoundingClientRect();return s.bottom>=i.top-t&&s.top<=i.bottom+t}function tn(n){return`data-${n.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`)}`}var se=class{constructor(e,{batchSize:t,datasetKeys:i,fetchFn:s=(...d)=>fetch(...d),filePathLabel:r,requestIdleRenderFn:a=ie,cancelIdleRenderFn:o=ne,intersectionObserverFactory:l=(d,w)=>new IntersectionObserver(d,w),isNearViewportFn:h=ri,requestAnimationFrameFn:c=d=>requestAnimationFrame(d),shellClassName:u,sourceClassName:p}){this.renderer=e,this.batchSize=t,this.datasetKeys=i,this.fetchFn=s,this.filePathLabel=r,this.requestIdleRenderFn=a,this.cancelIdleRenderFn=o,this.intersectionObserverFactory=l,this.isNearViewportFn=h,this.requestAnimationFrameFn=c,this.shellClassName=u,this.sourceClassName=p,this.shellSelector=`.${u}`,this.sourceSelector=`.${p}`,this.attributeNames=Object.fromEntries(Object.entries(i).map(([d,w])=>[d,tn(w)])),this.observer=null,this.idleId=null,this.pendingShells=[],this.hydrationInProgress=!1,this.instanceCounter=0,this.preservedShells=new Map,this.fileInflightRequests=new Map}destroy(){this.cancelHydration(),this.preservedShells.clear()}cancelHydration(){this.observer&&(this.observer.disconnect(),this.observer=null),this.cancelIdleRenderFn(this.idleId),this.idleId=null,this.pendingShells=[],this.hydrationInProgress=!1}cancelPendingIdleWork(){this.cancelIdleRenderFn(this.idleId),this.idleId=null}clearPreservedShells(){this.preservedShells.clear()}hasPendingWork(){return this.hydrationInProgress||this.pendingShells.length>0}preserveHydratedShellsForCommit(){this.preservedShells.clear();let e=this.renderer.previewElement;e&&Array.from(e.querySelectorAll(`${this.shellSelector}[${this.attributeNames.hydrated}="true"][${this.attributeNames.key}]`)).forEach(t=>{let i=t.dataset[this.datasetKeys.key],s=t.querySelector(this.sourceSelector)?.textContent??"",r=t.dataset[this.datasetKeys.target]??"";!i||!s&&!r||(t.isConnected&&t.remove(),this.preservedShells.set(i,{key:i,shell:t,source:s,target:r}))})}reconcileHydratedShells(){let e=this.renderer.previewElement;if(!e||this.preservedShells.size===0){this.preservedShells.clear();return}let t=!1;Array.from(e.querySelectorAll(`${this.shellSelector}[${this.attributeNames.key}]`)).forEach(i=>{let s=i.dataset[this.datasetKeys.key],r=s?this.preservedShells.get(s):null;if(!r)return;let a=i.querySelector(this.sourceSelector)?.textContent??"",o=i.dataset[this.datasetKeys.target]??"";si({nextSource:a,nextTarget:o,preservedSource:r.source,preservedTarget:r.target})&&(this.syncPreservedShell(r.shell,i),i.replaceWith(r.shell),t=t||r.shell.classList.contains("is-maximized"),this.preservedShells.delete(s))}),this.preservedShells.clear(),this.handleReconcile({restoredMaximizedShell:t})}handleReconcile(){}syncPreservedShell(e,t){X(e,t,this.attributeNames.sourceLine),X(e,t,this.attributeNames.sourceLineEnd),X(e,t,this.attributeNames.key),X(e,t,this.attributeNames.target),X(e,t,this.attributeNames.label),X(e,t,this.attributeNames.sourceHash),e.classList.add(this.shellClassName),e.dataset[this.datasetKeys.hydrated]="true",this.removeDatasetValue(e,"queued");let i=t.querySelector(this.sourceSelector),s=e.querySelector(this.sourceSelector);if(!s&&i&&(s=i.cloneNode(!0),e.prepend(s)),s&&i){let r=i.textContent??"";(r||!t.dataset[this.datasetKeys.target])&&(s.textContent=r),s.hidden=!0}}setupHydration(e){let t=this.renderer.previewElement,i=this.renderer.previewContainer;if(!t||!i)return 0;let s=Array.from(t.querySelectorAll(this.shellSelector));return s.length===0?0:(this.observer=this.intersectionObserverFactory(r=>{r.forEach(a=>{a.isIntersecting&&this.enqueueShell(a.target)})},{root:i,rootMargin:this.renderer.isLargeDocument?"180px 0px":"420px 0px"}),s.forEach(r=>this.observer.observe(r)),this.requestAnimationFrameFn(()=>{e===this.renderer.activeRenderVersion&&(this.hydrateVisibleShells(),this.renderer.updateHydrationPhase())}),s.length)}hydrateVisibleShells(){let e=this.renderer.previewElement,t=this.renderer.previewContainer;if(this.renderer.hydrationPaused||!e||!t)return;let i=this.renderer.isLargeDocument?180:420;Array.from(e.querySelectorAll(this.shellSelector)).forEach(s=>{this.isNearViewportFn(s,t,i)&&this.enqueueShell(s,{prioritize:!0})})}enqueueShell(e,{prioritize:t=!1}={}){!e?.isConnected||this.isShellHydrated(e)||this.isShellQueued(e)||(e.dataset[this.datasetKeys.queued]="true",t?this.pendingShells.unshift(e):this.pendingShells.push(e),!this.renderer.hydrationPaused&&(this.renderer.updateHydrationPhase(),this.scheduleHydration()))}scheduleHydration(){this.renderer.hydrationPaused||this.hydrationInProgress||this.idleId!==null||(this.idleId=this.requestIdleRenderFn(()=>{this.idleId=null,this.flushHydrationQueue()},W))}async flushHydrationQueue(){if(this.renderer.hydrationPaused||this.hydrationInProgress)return;let e=[];for(;this.pendingShells.length>0&&e.length<this.batchSize;){let i=this.pendingShells.shift();!i?.isConnected||this.isShellHydrated(i)||(this.removeDatasetValue(i,"queued"),e.push(i))}if(e.length===0){this.renderer.updateHydrationPhase();return}this.hydrationInProgress=!0,this.renderer.setPhase("hydrating");let t=null;try{t=await this.prepareHydrationBatch(e)}catch(i){this.handlePrepareHydrationBatchError(e,i),this.hydrationInProgress=!1,this.renderer.updateHydrationPhase();return}for(let i of e)await this.hydrateShell(i,t);this.hydrationInProgress=!1,this.pendingShells.length>0&&this.scheduleHydration(),this.renderer.updateHydrationPhase()}async prepareHydrationBatch(){return null}handlePrepareHydrationBatchError(e,t){}async hydrateShell(){throw new Error("hydrateShell must be implemented by subclasses")}markShellHydrated(e){e.dataset[this.datasetKeys.hydrated]="true",e.dataset[this.datasetKeys.instanceId]=String(++this.instanceCounter)}isShellHydrated(e){return e?.dataset?.[this.datasetKeys.hydrated]==="true"}removeDatasetValue(e,t){let i=this.datasetKeys[t];!i||!e||(e.removeAttribute?.(this.attributeNames[t]),e.dataset&&delete e.dataset[i])}isShellQueued(e){return e?.dataset?.[this.datasetKeys.queued]==="true"}async fetchSource(e){let t=String(e??"").trim();if(!t)throw new Error(`Missing ${this.filePathLabel} file path`);if(this.fileInflightRequests.has(t))return this.fileInflightRequests.get(t);let i=this.fetchFn(C(`/file?path=${encodeURIComponent(t)}`),{headers:{Accept:"application/json"}}).then(async s=>{let r=await s.json().catch(()=>null);if(!s.ok||typeof r?.content!="string")throw new Error(r?.error||`Failed to load ${t}`);return r.content}).finally(()=>{this.fileInflightRequests.delete(t)});return this.fileInflightRequests.set(t,i),i}};var Le=class extends se{constructor(e){super(e,{batchSize:Jt,datasetKeys:{hydrated:"mermaidHydrated",instanceId:"mermaidInstanceId",key:"mermaidKey",label:"mermaidLabel",queued:"mermaidQueued",sourceHash:"mermaidSourceHash",sourceLine:"sourceLine",sourceLineEnd:"sourceLineEnd",target:"mermaidTarget"},filePathLabel:"Mermaid",shellClassName:"mermaid-shell",sourceClassName:"mermaid-source"}),this.renderer=e,this.currentTheme=document.documentElement?.dataset.theme==="light"?"light":"dark",this.loader=null,this.runtime=null,this.shellRefits=new WeakMap}applyTheme(e){this.currentTheme=e;let t=this.runtime;t&&(this.configureMermaid(t),this.resetHydratedShells())}configureMermaid(e){e.initialize({startOnLoad:!1,flowchart:{defaultRenderer:"dagre-wrapper",useMaxWidth:!0},class:{defaultRenderer:"dagre-wrapper",useMaxWidth:!0},theme:this.currentTheme==="dark"?"dark":"default",themeVariables:this.currentTheme==="dark"?{background:"#161822",clusterBkg:"#1a1c28",edgeLabelBackground:"#161822",lineColor:"#8b8ba0",mainBkg:"#1c1e2c",nodeBorder:"#383a50",primaryBorderColor:"#383a50",primaryColor:"#818cf8",primaryTextColor:"#e2e2ea",secondaryColor:"#1c1e2c",tertiaryColor:"#161822",titleColor:"#e2e2ea"}:{}})}ensureMermaid(){return this.runtime?(this.configureMermaid(this.runtime),Promise.resolve(this.runtime)):this.loader?this.loader:(this.loader=import("./chunks/mermaid-runtime-BIFNJ2CT.js").then(e=>{let t=e?.default;if(!t)throw new Error("Mermaid runtime failed to initialize");return this.runtime=t,this.configureMermaid(t),t}).catch(e=>{throw this.loader=null,this.runtime=null,new Error(e instanceof Error?e.message:"Failed to load Mermaid runtime")}),this.loader)}handleReconcile({restoredMaximizedShell:e}){e&&document.body.classList.add("mermaid-maximized-open")}async prepareHydrationBatch(){return this.ensureMermaid()}handlePrepareHydrationBatchError(e,t){console.warn("[preview] Mermaid runtime failed to load:",t)}async hydrateShell(e,t){if(!t||!e?.isConnected||this.isShellHydrated(e))return;let i=e.querySelector(".mermaid-source");i||(i=document.createElement("span"),i.className="mermaid-source",i.hidden=!0,e.appendChild(i));let s=i.textContent??"";try{if(!s.trim()&&e.dataset.mermaidTarget){if(s=await this.fetchSource(e.dataset.mermaidTarget),!e.isConnected)return;i.textContent=s}if(!s.trim())throw new Error(e.dataset.mermaidTarget?"Mermaid file is empty":"Mermaid source is empty");s=this.prepareSource(s),e.querySelector(".mermaid-placeholder-card")?.remove();let r=document.createElement("div");r.className="mermaid mermaid-render-node",r.id=e.dataset.mermaidKey||`mermaid-${Date.now()}`;let a=e.getAttribute("data-source-line"),o=e.getAttribute("data-source-line-end");if(a&&r.setAttribute("data-source-line",a),o&&r.setAttribute("data-source-line-end",o),r.textContent=s,e.appendChild(r),await t.run({nodes:[r]}),!r.isConnected||e!==r.parentElement)return;this.enhanceDiagram(e,r),this.markShellHydrated(e)}catch(r){console.warn("[preview] Mermaid render failed:",r),e.querySelector(":scope > .mermaid-toolbar")?.remove(),e.querySelector(":scope > .mermaid-frame")?.remove(),e.querySelector(":scope > .mermaid-render-node")?.remove(),e.querySelector(".mermaid-placeholder-card")||i?.after(bt(e.dataset.mermaidKey||"mermaid",{label:e.dataset.mermaidLabel||"Mermaid diagram",message:r instanceof Error?r.message:"Render failed"}))}}prepareSource(e){let t=String(e??"");if(!/%%\{[\s\S]*?\binit\s*:/m.test(t)){let r=this.getPreviewInitConfig(t);r&&(t=`%%{init: ${JSON.stringify(r)}}%%
|
|
21
21
|
${t}`)}if(!/^\s*gantt\b/m.test(t)||/\btodayMarker\b/.test(t))return t;let i=t.split(`
|
|
22
22
|
`),s=i.findIndex(r=>/^\s*gantt\b/.test(r));return s===-1?t:(i.splice(s+1,0," todayMarker off"),i.join(`
|
|
23
|
-
`))}getPreviewInitConfig(e){return/^\s*stateDiagram(?:-v2)?\b/m.test(e)?{htmlLabels:!1}:/^\s*classDiagram\b/m.test(e)?{htmlLabels:!1}:/^\s*gantt\b/m.test(e)?{htmlLabels:!1}:null}resetHydratedShells(){let e=this.renderer.previewElement;if(!e)return;let t=Array.from(e.querySelectorAll('.mermaid-shell[data-mermaid-hydrated="true"]'));t.length!==0&&t.forEach(i=>{this.shellRefits.delete(i),i.removeAttribute("data-mermaid-hydrated"),i.querySelector(":scope > .mermaid-toolbar")?.remove(),i.querySelector(":scope > .mermaid-frame")?.remove(),i.querySelector(":scope > .mermaid-render-node")?.remove(),i.querySelector(".mermaid-placeholder-card")||i.querySelector(".mermaid-source")?.after(Gt(i.dataset.mermaidKey||"mermaid")),this.enqueueShell(i,{prioritize:!0})})}enhanceDiagram(e,t){let i=t.querySelector("svg");if(!i){t.remove();return}let s=document.createElement("div");s.className="mermaid-toolbar diagram-preview-toolbar";let r=this.createZoomButton("\u2212","Zoom out"),a=this.createZoomButton("+","Zoom in"),o=this.createZoomButton("Reset","Reset zoom"),l=this.createZoomButton("Max","Maximize diagram");l.classList.add("mermaid-maximize-btn"),T(l,"maximize");let h=document.createElement("span");h.className="mermaid-zoom-label diagram-preview-zoom-label",h.setAttribute("aria-live","polite"),s.append(r,h,o,a,l);let c=document.createElement("div");c.className="mermaid-frame diagram-preview-frame";let{width:u,height:f}=Kt(i),d=L.default,g=1,w=null,E=null,C=!1,P=0,I=!1,A=null,z=0,U=0,R=0,B=0;i.style.display="block",i.style.margin="0 auto",i.style.maxWidth="none";let N=()=>{let m=j(c);if(!Number.isFinite(u)||u<=0||m.width<=0)return L.default;let y=m.width/u;return!Number.isFinite(y)||y<=0?L.default:F(y,L.min,L.max)},$=m=>{d=F(m,L.min,L.max),i.style.width=`${u*d}px`,i.style.height=`${f*d}px`,h.textContent=`${Math.round(d*100)}%`,r.disabled=d<=L.min,a.disabled=d>=L.max;let y=j(c),v=u*d>y.width||f*d>y.height;c.classList.toggle("is-pannable",v),i.style.margin=v?"0":"0 auto"},V=()=>({x:c.scrollLeft+c.clientWidth/2,y:c.scrollTop+c.clientHeight/2}),K=(m,y,v)=>{if(m===0)return;let S=y/m;c.scrollLeft=v.x*S-c.clientWidth/2,c.scrollTop=v.y*S-c.clientHeight/2},Z=m=>{let y=F(m,L.min,L.max),v=d;if(y===v)return;let S=V(),ct=performance.now();w&&cancelAnimationFrame(w);let ae=ht=>{let oe=F((ht-ct)/L.animationDurationMs,0,1),dt=Ce(oe),le=v+(y-v)*dt;if($(le),K(v,le,S),oe<1){w=requestAnimationFrame(ae);return}w=null,$(y),K(v,y,S)};w=requestAnimationFrame(ae)},G=m=>{C=!0,Z(d+m)},H=({animate:m=!1}={})=>{if(g=N(),C=!1,P=j(c).width,m&&Math.abs(g-d)>.001){Z(g);return}w&&(cancelAnimationFrame(w),w=null),$(g),c.scrollLeft=0,c.scrollTop=0},M=({force:m=!1}={})=>{E&&cancelAnimationFrame(E),E=requestAnimationFrame(()=>{if(E=null,!e.isConnected)return;let y=j(c).width,v=Math.abs(y-P)>1;!m&&C||!m&&P>0&&!v||H()})};this.shellRefits.set(e,M),r.addEventListener("click",()=>G(-L.step)),a.addEventListener("click",()=>G(L.step)),o.addEventListener("click",()=>{H({animate:!0})});let D=()=>{let m=e.classList.contains("is-maximized");T(l,m?"restore":"maximize");let y=m?"Restore diagram size":"Maximize diagram";l.setAttribute("aria-label",y),l.title=y},ee=m=>{let y=this.renderer.previewElement;if(m){let v=y.querySelector(".mermaid-shell.is-maximized");if(v&&v!==e){v.classList.remove("is-maximized"),this.shellRefits.get(v)?.();let S=v.querySelector(".mermaid-maximize-btn");S&&(T(S,"maximize"),S.setAttribute("aria-label","Maximize diagram"),S.title="Maximize diagram")}e.classList.add("is-maximized"),document.body.classList.add("mermaid-maximized-open"),D(),M({force:!0});return}e.classList.remove("is-maximized"),y.querySelector(".mermaid-shell.is-maximized")||document.body.classList.remove("mermaid-maximized-open"),D(),M({force:!0})};D(),l.addEventListener("click",()=>{ee(!e.classList.contains("is-maximized"))});let O=()=>{if(I){if(I=!1,c.classList.remove("is-dragging"),A!==null&&typeof c.releasePointerCapture=="function")try{c.releasePointerCapture(A)}catch{}A=null}};c.addEventListener("pointerdown",m=>{m.button!==0||!c.classList.contains("is-pannable")||(w&&(cancelAnimationFrame(w),w=null),I=!0,A=m.pointerId,z=m.clientX,U=m.clientY,R=c.scrollLeft,B=c.scrollTop,c.classList.add("is-dragging"),c.setPointerCapture?.(m.pointerId),m.preventDefault())}),c.addEventListener("pointermove",m=>{I&&(c.scrollLeft=R-(m.clientX-z),c.scrollTop=B-(m.clientY-U))}),c.addEventListener("pointerup",O),c.addEventListener("pointercancel",O),c.addEventListener("lostpointercapture",O),c.appendChild(i);let _=e.querySelector(".mermaid-source");t.remove(),e.replaceChildren(),_&&(_.hidden=!0,e.appendChild(_)),e.append(s,c),M({force:!0})}scheduleActiveRefit(){let e=this.renderer.previewElement;e&&Array.from(e.querySelectorAll('.mermaid-shell[data-mermaid-hydrated="true"]')).forEach(t=>{this.shellRefits.get(t)?.()})}createZoomButton(e,t){let i=document.createElement("button");return i.type="button",i.className="mermaid-zoom-btn diagram-preview-action-btn",i.setAttribute("aria-label",t),i.title=t,i.textContent=e,i}};var Se=class extends ne{constructor(e){super(e,{batchSize:Vt,datasetKeys:{hydrated:"plantumlHydrated",instanceId:"plantumlInstanceId",key:"plantumlKey",label:"plantumlLabel",queued:"plantumlQueued",sourceHash:"plantumlSourceHash",sourceLine:"sourceLine",sourceLineEnd:"sourceLineEnd",target:"plantumlTarget"},filePathLabel:"PlantUML",shellClassName:"plantuml-shell",sourceClassName:"plantuml-source"}),this.renderer=e,this.svgCache=new Map,this.svgInflightRequests=new Map,this.shellRefits=new WeakMap,this.activeMaximizedShell=null,this.maximizedRoot=null,this.resizeFrameId=null}destroy(){this.cancelHydration(),this.preservedShells.clear(),this.clearActiveShell(),this.resizeFrameId&&(cancelAnimationFrame(this.resizeFrameId),this.resizeFrameId=null),this.maximizedRoot?.remove(),this.maximizedRoot=null}clearActiveShell(){this.activeMaximizedShell=null,this.maximizedRoot&&this.maximizedRoot.childElementCount===0&&(this.maximizedRoot.hidden=!0)}syncActiveShell(){return this.activeMaximizedShell?.isConnected&&this.activeMaximizedShell.classList.contains("is-maximized")?this.activeMaximizedShell:(this.clearActiveShell(),null)}scheduleActiveRefit(){this.resizeFrameId&&cancelAnimationFrame(this.resizeFrameId),this.resizeFrameId=requestAnimationFrame(()=>{this.resizeFrameId=null;let e=this.syncActiveShell();e&&this.shellRefits.get(e)?.()})}handleReconcile({restoredMaximizedShell:e}){e&&document.body.classList.add("plantuml-maximized-open"),this.syncActiveShell()}ensureMaximizedRoot(){if(this.maximizedRoot?.isConnected&&this.maximizedRoot.parentElement===document.body)return this.maximizedRoot;let e=document.body.querySelector('[data-plantuml-maximized-root="true"]');return e||(e=document.createElement("div"),e.dataset.plantumlMaximizedRoot="true",e.className="plantuml-maximized-root",document.body.appendChild(e)),this.maximizedRoot=e,e}mountShellInMaximizedRoot(e){if(!e)return;let t=this.ensureMaximizedRoot();t.hidden=!1,e._plantumlRestoreParent=e.parentElement||null,e._plantumlRestoreNextSibling=e.nextSibling||null,t.appendChild(e)}restoreShellMount(e){if(!e)return;let t=e._plantumlRestoreParent,i=e._plantumlRestoreNextSibling;t?.isConnected&&(i?.parentElement===t?t.insertBefore(e,i):t.appendChild(e)),e._plantumlRestoreParent=null,e._plantumlRestoreNextSibling=null,this.maximizedRoot&&this.maximizedRoot.childElementCount===0&&(this.maximizedRoot.hidden=!0)}async hydrateShell(e){if(!e?.isConnected||this.isShellHydrated(e))return;let t=e.querySelector(".plantuml-source");t||(t=document.createElement("span"),t.className="plantuml-source",t.hidden=!0,e.appendChild(t)),e.querySelector(".plantuml-placeholder-card")?.remove();try{let i=t.textContent??"";if(!i.trim()&&e.dataset.plantumlTarget){if(i=await this.fetchSource(e.dataset.plantumlTarget),!e.isConnected)return;t.textContent=i}if(!i.trim())throw new Error(e.dataset.plantumlTarget?"PlantUML file is empty":"PlantUML source is empty");let s=await this.fetchSvg(i);if(!e.isConnected)return;this.enhanceDiagram(e,s),this.markShellHydrated(e)}catch(i){console.warn("[preview] PlantUML render failed:",i),e.querySelector(":scope > .plantuml-toolbar")?.remove(),e.querySelector(":scope > .plantuml-frame")?.remove(),e.querySelector(".plantuml-placeholder-card")||t?.after(pt(e.dataset.plantumlKey||"plantuml",i instanceof Error?i.message:"Render failed"))}}async fetchSvg(e){let t=e;if(this.svgCache.has(t))return this.svgCache.get(t);if(this.svgInflightRequests.has(t))return this.svgInflightRequests.get(t);let i=fetch(b("/plantuml/render"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({source:e})}).then(async s=>{let r=await s.json().catch(()=>null);if(!s.ok||!r?.ok||typeof r.svg!="string")throw new Error(r?.error||"Failed to render PlantUML");let a=jt(r.svg);return this.svgCache.set(t,a),a}).finally(()=>{this.svgInflightRequests.delete(t)});return this.svgInflightRequests.set(t,i),i}resetShell(e,{clearCache:t=!1,message:i="Renders server-side when visible"}={}){let s=e.querySelector(".plantuml-source")?.textContent??"";t&&s&&(this.svgCache.delete(s),this.svgInflightRequests.delete(s)),this.shellRefits.delete(e),this.activeMaximizedShell===e&&(this.restoreShellMount(e),this.clearActiveShell()),e.removeAttribute("data-plantuml-hydrated"),e.removeAttribute("data-plantuml-instance-id"),e.removeAttribute("data-plantuml-queued"),e.classList.remove("is-maximized"),this.syncActiveShell()||document.body.classList.remove("plantuml-maximized-open"),e.querySelector(":scope > .plantuml-toolbar")?.remove(),e.querySelector(":scope > .plantuml-frame")?.remove(),e.querySelector(".plantuml-placeholder-card")||e.querySelector(".plantuml-source")?.after(pt(e.dataset.plantumlKey||"plantuml",i))}enhanceDiagram(e,t){let i=document.createElement("div");i.innerHTML=t;let s=i.querySelector("svg");if(!s)throw new Error("Renderer returned invalid SVG");let r=document.createElement("div");r.className="plantuml-toolbar diagram-preview-toolbar";let a=document.createElement("div");a.className="plantuml-frame diagram-preview-frame";let o=this.createToolButton("\u2212","Zoom out"),l=this.createToolButton("+","Zoom in"),h=this.createToolButton("Reset","Reset zoom"),c=this.createToolButton("Reload","Reload diagram"),u=this.createToolButton("Max","Maximize diagram");u.classList.add("plantuml-maximize-btn"),T(c,"refresh"),T(u,"maximize");let f=document.createElement("span");f.className="plantuml-zoom-label diagram-preview-zoom-label",f.setAttribute("aria-live","polite"),r.append(o,f,h,l,c,u);let{width:d,height:g}=ce(s),w=k.default,E=1,C=null,P=!1,I=null,A=0,z=0,U=0,R=0;s.style.display="block",s.style.margin="0 auto",s.style.maxWidth="none";let B=()=>{let m=j(a);return!Number.isFinite(d)||d<=0||m.width<=0?k.default:F(Math.min(k.default,m.width/d),k.min,k.max)},N=m=>{w=F(m,k.min,k.max),s.style.width=`${d*w}px`,s.style.height=`${g*w}px`,f.textContent=`${Math.round(w*100)}%`,o.disabled=w<=k.min,l.disabled=w>=k.max;let y=j(a),v=d*w>y.width||g*w>y.height;a.classList.toggle("is-pannable",v)},$=()=>({x:a.scrollLeft+a.clientWidth/2,y:a.scrollTop+a.clientHeight/2}),V=(m,y,v)=>{if(m===0)return;let S=y/m;a.scrollLeft=v.x*S-a.clientWidth/2,a.scrollTop=v.y*S-a.clientHeight/2},K=m=>{let y=F(m,k.min,k.max),v=w;if(y===v)return;let S=$(),ct=performance.now();C&&cancelAnimationFrame(C);let ae=ht=>{let oe=F((ht-ct)/k.animationDurationMs,0,1),dt=Ce(oe),le=v+(y-v)*dt;if(N(le),V(v,le,S),oe<1){C=requestAnimationFrame(ae);return}C=null,N(y),V(v,y,S)};C=requestAnimationFrame(ae)},Z=m=>{K(w+m)},G=({animate:m=!1}={})=>{if(E=B(),m&&Math.abs(E-w)>.001){K(E);return}C&&(cancelAnimationFrame(C),C=null),N(E),a.scrollLeft=0,a.scrollTop=0},H=null,M=()=>{H&&cancelAnimationFrame(H),H=requestAnimationFrame(()=>{H=null,e.isConnected&&G()})};this.shellRefits.set(e,M),o.addEventListener("click",()=>Z(-k.step)),l.addEventListener("click",()=>Z(k.step)),h.addEventListener("click",()=>{G({animate:!0})});let D=()=>{let m=e.classList.contains("is-maximized");T(u,m?"restore":"maximize");let y=m?"Restore diagram size":"Maximize diagram";u.setAttribute("aria-label",y),u.title=y},ee=m=>{if(m){let y=this.syncActiveShell();if(y&&y!==e){this.restoreShellMount(y),y.classList.remove("is-maximized"),this.activeMaximizedShell===y&&this.clearActiveShell(),this.shellRefits.get(y)?.();let v=y.querySelector(".plantuml-maximize-btn");v&&(T(v,"maximize"),v.setAttribute("aria-label","Maximize diagram"),v.title="Maximize diagram")}this.mountShellInMaximizedRoot(e),e.classList.add("is-maximized"),this.activeMaximizedShell=e,document.body.classList.add("plantuml-maximized-open"),D(),M();return}this.restoreShellMount(e),e.classList.remove("is-maximized"),this.activeMaximizedShell===e&&this.clearActiveShell(),this.syncActiveShell()||document.body.classList.remove("plantuml-maximized-open"),D(),M()};c.addEventListener("click",()=>{this.resetShell(e,{clearCache:!0,message:"Refreshing\u2026"}),this.enqueueShell(e,{prioritize:!0})}),D(),u.addEventListener("click",()=>{ee(!e.classList.contains("is-maximized"))});let O=()=>{if(P){if(P=!1,a.classList.remove("is-dragging"),I!==null&&typeof a.releasePointerCapture=="function")try{a.releasePointerCapture(I)}catch{}I=null}};a.addEventListener("pointerdown",m=>{m.button!==0||!a.classList.contains("is-pannable")||(C&&(cancelAnimationFrame(C),C=null),P=!0,I=m.pointerId,A=m.clientX,z=m.clientY,U=a.scrollLeft,R=a.scrollTop,a.classList.add("is-dragging"),a.setPointerCapture?.(m.pointerId),m.preventDefault())}),a.addEventListener("pointermove",m=>{P&&(a.scrollLeft=U-(m.clientX-A),a.scrollTop=R-(m.clientY-z))}),a.addEventListener("pointerup",O),a.addEventListener("pointercancel",O),a.addEventListener("lostpointercapture",O),a.appendChild(s);let _=e.querySelector(".plantuml-source");e.replaceChildren(),_&&(_.hidden=!0,e.appendChild(_)),e.append(r,a),E=B(),N(E)}createToolButton(e,t){let i=document.createElement("button");return i.type="button",i.className="plantuml-tool-btn diagram-preview-action-btn",i.setAttribute("aria-label",t),i.title=t,i.textContent=e,i}};function Oi(){return new Worker(new URL("./preview-render-worker.js",import.meta.url),{type:"module"})}var Le=class{constructor({attachmentApiPath:e="/api/attachment",cancelIdleRenderFn:t=ie,compilePreviewDocumentLoader:i=()=>import("./chunks/preview-render-compiler-UZ4SZDQQ.js"),createWorkerFn:s=Oi,getFileList:r,getSourceFilePath:a=null,idleTimeoutMs:o=W,requestIdleRenderFn:l=te}={}){this.attachmentApiPath=e,this.cancelIdleRenderFn=t,this.compilePreviewDocumentLoader=i,this.createWorkerFn=s,this.getFileList=r,this.getSourceFilePath=a,this.idleTimeoutMs=o,this.requestIdleRenderFn=l,this.worker=null,this.workerDisabled=!1,this.workerJob=null,this.workerPrewarmId=null,this.handleWorkerMessage=h=>{if(!this.workerJob||h.data?.renderVersion!==this.workerJob.renderVersion)return;let c=this.workerJob;if(this.workerJob=null,h.data?.error){c.reject(new Error(h.data.error));return}c.resolve({html:h.data.html,stats:h.data.stats})},this.handleWorkerError=h=>{let c=new Error(h.message||"Preview worker failed");this.workerJob&&(this.workerJob.reject(c),this.workerJob=null),this.reset("Preview worker failed",{disable:!0})}}hasPendingJob(){return this.workerJob!==null}schedulePrewarm({timeout:e=this.idleTimeoutMs}={}){this.workerDisabled||this.worker||this.workerPrewarmId!==null||(this.workerPrewarmId=this.requestIdleRenderFn(()=>{this.workerPrewarmId=null,this.ensureWorker()},e))}ensureWorker(){if(this.workerDisabled)return null;if(this.worker)return this.worker;try{return this.worker=this.createWorkerFn(),this.worker.addEventListener("message",this.handleWorkerMessage),this.worker.addEventListener("error",this.handleWorkerError),this.worker}catch{return this.workerDisabled=!0,null}}async compile(e,t){if(this.ensureWorker()){this.workerJob&&this.reset("Superseded preview render");let r=this.ensureWorker();return new Promise((a,o)=>{this.workerJob={reject:o,renderVersion:t,resolve:a},r.postMessage({attachmentApiPath:this.attachmentApiPath,fileList:this.getFileList?.()??[],markdownText:e,renderVersion:t,sourceFilePath:this.getSourceFilePath?.()??""})})}let{compilePreviewDocument:s}=await this.compilePreviewDocumentLoader();return s({attachmentApiPath:this.attachmentApiPath,fileList:this.getFileList?.()??[],markdownText:e,sourceFilePath:this.getSourceFilePath?.()??""})}cancelWorkerJob(e){this.workerJob&&(this.workerJob.reject(new Error(e)),this.workerJob=null)}reset(e,{disable:t=!1}={}){this.cancelWorkerJob(e),this.worker&&(this.worker.removeEventListener("message",this.handleWorkerMessage),this.worker.removeEventListener("error",this.handleWorkerError),this.worker.terminate(),this.worker=null),t&&(this.workerDisabled=!0)}destroy(e="Preview renderer destroyed"){this.workerPrewarmId!==null&&this.cancelIdleRenderFn(this.workerPrewarmId),this.workerPrewarmId=null,this.reset(e)}};var ke=class{constructor({cancelAnimationFrameFn:e=h=>cancelAnimationFrame(h),cancelIdleRenderFn:t=ie,clearTimeoutFn:i=h=>clearTimeout(h),getRenderProfileFn:s=ve,idleTimeoutMs:r=W,requestAnimationFrameFn:a=h=>requestAnimationFrame(h),requestIdleRenderFn:o=te,setTimeoutFn:l=(h,c)=>setTimeout(h,c)}={}){this.cancelAnimationFrameFn=e,this.cancelIdleRenderFn=t,this.clearTimeoutFn=i,this.getRenderProfileFn=s,this.idleTimeoutMs=r,this.requestAnimationFrameFn=a,this.requestIdleRenderFn=o,this.setTimeoutFn=l,this.frameId=null,this.idleId=null,this.timeoutId=null}queue({markdownText:e,onRenderRequested:t,renderVersion:i}){let s=this.getRenderProfileFn(e);this.cancel();let r=()=>{this.frameId=this.requestAnimationFrameFn(()=>{this.frameId=null,this.timeoutId=null,t?.(e,i)})},a=()=>{if(s.deferUntilIdle){this.idleId=this.requestIdleRenderFn(()=>{this.idleId=null,r()},this.idleTimeoutMs);return}r()};this.timeoutId=this.setTimeoutFn(a,s.debounceMs)}cancel(){this.clearTimeoutFn(this.timeoutId),this.frameId&&this.cancelAnimationFrameFn(this.frameId),this.cancelIdleRenderFn(this.idleId),this.frameId=null,this.idleId=null,this.timeoutId=null}destroy(){this.cancel()}};var xe=class{constructor({getContent:e,getFileList:t,getSourceFilePath:i,onAfterRenderCommit:s,onBeforeRenderCommit:r,onRenderComplete:a,outlineController:o,previewContainer:l,previewElement:h}){this.getContent=e,this.getFileList=t,this.getSourceFilePath=i,this.onAfterRenderCommit=s,this.onBeforeRenderCommit=r,this.onRenderComplete=a,this.outlineController=o,this.previewContainer=l,this.previewElement=h,this.renderHost=null,this.pendingRenderVersion=0,this.activeRenderVersion=0,this.readyRenderVersion=0,this.currentStats=null,this.isLargeDocument=!1,this.hydrationPaused=!1,this.handlePreviewClick=c=>{let u=c.target.closest(".mermaid-placeholder-btn");if(u){let d=u.closest(".mermaid-shell");if(!d)return;c.preventDefault(),this.enqueueMermaidShell(d,{prioritize:!0});return}let f=c.target.closest(".plantuml-placeholder-btn");if(f){let d=f.closest(".plantuml-shell");if(!d)return;c.preventDefault(),this.enqueuePlantUmlShell(d,{prioritize:!0})}},this.handleWindowResize=()=>{this.mermaidHydrator.scheduleActiveRefit(),this.plantUmlHydrator.scheduleActiveRefit()},this.mermaidHydrator=new Ee(this),this.plantUmlHydrator=new Se(this),this.renderScheduler=new ke({getRenderProfileFn:ve}),this.renderExecutor=new Le({attachmentApiPath:b("/attachment"),getFileList:()=>this.getFileList?.()??[],getSourceFilePath:()=>this.getSourceFilePath?.()??"",idleTimeoutMs:W}),this.previewElement?.addEventListener("click",this.handlePreviewClick),window.addEventListener("resize",this.handleWindowResize),this.setPhase("ready")}ensureRenderHost(){if(!this.previewElement)return null;if(this.renderHost?.isConnected&&this.renderHost.parentElement===this.previewElement)return this.renderHost;let e=this.previewElement.querySelector('[data-preview-render-host="true"]');return e||(e=document.createElement("div"),e.dataset.previewRenderHost="true",this.previewElement.appendChild(e)),this.renderHost=e,this.renderHost}normalizePreviewChildren(e=this.renderHost){this.previewElement&&Array.from(this.previewElement.children).forEach(t=>{t===e||t.dataset.excalidrawOverlayRoot==="true"||t.dataset.videoOverlayRoot==="true"||t.remove()})}getReservedPreviewHeight(){let e=this.renderHost?.getBoundingClientRect?.().height??0,t=this.previewContainer?.clientHeight??0;return Math.max(Math.round(e),Math.round(t),320)}beginDocumentLoad(){this.cancelScheduledRender(),this.cancelMermaidHydration(),this.cancelPlantUmlHydration(),this.mermaidHydrator.clearPreservedShells(),this.plantUmlHydrator.clearPreservedShells(),this.clearActivePlantUmlShell(),this.onBeforeRenderCommit?.(this.previewElement),this.pendingRenderVersion+=1,this.activeRenderVersion=this.pendingRenderVersion,this.readyRenderVersion=0,this.currentStats=null,this.isLargeDocument=!1,this.renderExecutor.hasPendingJob()&&this.resetWorker("Document changed");let e=this.ensureRenderHost();this.normalizePreviewChildren(e);let t=this.getReservedPreviewHeight();e&&(e.replaceChildren(),e.style.minHeight=`${t}px`);let i=document.createElement("div");i.className="preview-shell",i.style.minHeight=`${t}px`,i.textContent="Rendering preview\u2026",e?.append(i),this.setPhase("shell")}applyTheme(e){let t=document.getElementById("hljs-theme");if(t){let{darkHref:i,lightHref:s}=t.dataset;t.href=e==="dark"?i:s}this.mermaidHydrator.applyTheme(e)}configureMermaid(e){this.mermaidHydrator.configureMermaid(e)}ensureMermaid(){return this.mermaidHydrator.ensureMermaid()}queueRender(){let e=this.getContent();this.cancelScheduledRender(),this.pendingRenderVersion+=1;let t=this.pendingRenderVersion;this.renderScheduler.queue({markdownText:e,onRenderRequested:(i,s)=>{this.render(i,s)},renderVersion:t})}async render(e=this.getContent(),t=this.pendingRenderVersion){if(this.previewElement)try{let i=await this.compilePreview(e,t);if(t!==this.pendingRenderVersion)return;this.commitBaseRender(i,t)}catch(i){if(t!==this.pendingRenderVersion)return;console.warn("[preview] Failed to render preview:",i)}}destroy(){this.renderScheduler.destroy(),this.mermaidHydrator.destroy(),this.plantUmlHydrator.destroy(),this.renderExecutor.destroy(),this.previewElement?.removeEventListener("click",this.handlePreviewClick),window.removeEventListener("resize",this.handleWindowResize)}setPhase(e){this.previewElement&&(this.previewElement.dataset.renderPhase=e)}cancelScheduledRender(){this.renderScheduler.cancel()}cancelMermaidHydration(){this.mermaidHydrator.cancelHydration()}cancelPlantUmlHydration(){this.plantUmlHydrator.cancelHydration()}clearActivePlantUmlShell(){this.plantUmlHydrator.clearActiveShell()}scheduleActiveMermaidRefit(){this.mermaidHydrator.scheduleActiveRefit()}syncActivePlantUmlShell(){return this.plantUmlHydrator.syncActiveShell()}scheduleActivePlantUmlRefit(){this.plantUmlHydrator.scheduleActiveRefit()}setHydrationPaused(e){if(this.hydrationPaused=!!e,this.hydrationPaused){this.mermaidHydrator.cancelPendingIdleWork(),this.plantUmlHydrator.cancelPendingIdleWork();return}this.mermaidHydrator.hydrateVisibleShells(),this.mermaidHydrator.scheduleHydration(),this.plantUmlHydrator.hydrateVisibleShells(),this.plantUmlHydrator.scheduleHydration(),this.updateHydrationPhase()}resetWorker(e,{disable:t=!1}={}){this.renderExecutor.reset(e,{disable:t})}scheduleWorkerPrewarm({timeout:e=W}={}){this.renderExecutor.schedulePrewarm({timeout:e})}async compilePreview(e,t){return this.renderExecutor.compile(e,t)}commitBaseRender({html:e,stats:t},i){this.activeRenderVersion=i,this.readyRenderVersion=0,this.currentStats=t,this.isLargeDocument=Bt(t),this.cancelMermaidHydration(),this.cancelPlantUmlHydration(),document.body.classList.remove("mermaid-maximized-open"),document.body.classList.remove("plantuml-maximized-open"),this.preserveHydratedMermaidsForCommit(),this.preserveHydratedPlantUmlsForCommit(),this.onBeforeRenderCommit?.(this.previewElement);let s=this.ensureRenderHost();this.normalizePreviewChildren(s),s&&(s.innerHTML=e),this.reconcileHydratedMermaids(),this.reconcileHydratedPlantUmls(),this.setPhase("base"),this.outlineController.refresh(),this.onAfterRenderCommit?.(this.previewElement,{...t,isLargeDocument:this.isLargeDocument,renderVersion:i});let r=this.setupMermaidHydration(i),a=this.setupPlantUmlHydration(i);r===0&&a===0&&this.notifyReady()}preserveHydratedMermaidsForCommit(){this.mermaidHydrator.preserveHydratedShellsForCommit()}preserveHydratedPlantUmlsForCommit(){this.plantUmlHydrator.preserveHydratedShellsForCommit()}reconcileHydratedMermaids(){this.mermaidHydrator.reconcileHydratedShells()}reconcileHydratedPlantUmls(){this.plantUmlHydrator.reconcileHydratedShells()}syncPreservedMermaidShell(e,t){this.mermaidHydrator.syncPreservedShell(e,t)}syncPreservedPlantUmlShell(e,t){this.plantUmlHydrator.syncPreservedShell(e,t)}setupMermaidHydration(e){return this.mermaidHydrator.setupHydration(e)}hydrateVisibleMermaids(){this.mermaidHydrator.hydrateVisibleShells()}enqueueMermaidShell(e,{prioritize:t=!1}={}){this.mermaidHydrator.enqueueShell(e,{prioritize:t})}scheduleMermaidHydration(){this.mermaidHydrator.scheduleHydration()}async flushMermaidHydrationQueue(){await this.mermaidHydrator.flushHydrationQueue()}async hydrateMermaidShell(e,t){await this.mermaidHydrator.hydrateShell(e,t)}resetHydratedMermaids(){this.mermaidHydrator.resetHydratedShells()}setupPlantUmlHydration(e){return this.plantUmlHydrator.setupHydration(e)}hydrateVisiblePlantUmls(){this.plantUmlHydrator.hydrateVisibleShells()}enqueuePlantUmlShell(e,{prioritize:t=!1}={}){this.plantUmlHydrator.enqueueShell(e,{prioritize:t})}schedulePlantUmlHydration(){this.plantUmlHydrator.scheduleHydration()}async flushPlantUmlHydrationQueue(){await this.plantUmlHydrator.flushHydrationQueue()}async hydratePlantUmlShell(e){await this.plantUmlHydrator.hydrateShell(e)}updateHydrationPhase(){if(this.hydrationPaused&&(this.mermaidHydrator.hasPendingWork()||this.plantUmlHydrator.hasPendingWork())){this.setPhase("base");return}if(this.mermaidHydrator.hasPendingWork()||this.plantUmlHydrator.hasPendingWork()){this.setPhase("hydrating");return}this.notifyReady()}notifyReady(){this.renderHost&&(this.renderHost.style.minHeight=""),this.setPhase("ready"),this.readyRenderVersion!==this.activeRenderVersion&&(this.readyRenderVersion=this.activeRenderVersion,this.onRenderComplete?.({isLargeDocument:this.isLargeDocument,stats:this.currentStats}))}async fetchPlantUmlSvg(e){return this.plantUmlHydrator.fetchSvg(e)}async fetchPlantUmlSource(e){return this.plantUmlHydrator.fetchSource(e)}async fetchMermaidSource(e){return this.mermaidHydrator.fetchSource(e)}resetPlantUmlShell(e,{clearCache:t=!1,message:i="Renders server-side when visible"}={}){this.plantUmlHydrator.resetShell(e,{clearCache:t,message:i})}enhancePlantUmlDiagram(e,t){this.plantUmlHydrator.enhanceDiagram(e,t)}enhanceMermaidDiagram(e,t){this.mermaidHydrator.enhanceDiagram(e,t)}createMermaidZoomButton(e,t){return this.mermaidHydrator.createZoomButton(e,t)}createPlantUmlToolButton(e,t){return this.plantUmlHydrator.createToolButton(e,t)}};var Fe=class{constructor({backlinksPanel:e,clearInitialFileBootstrap:t,closeSidebarOnMobile:i,elements:s,excalidrawEmbed:r,fileExplorer:a,getIsTabActive:o,getSessionLoadToken:l,gitDiffView:h,gitPanel:c,imageLightbox:u=null,lobby:f,navigation:d,previewRenderer:g,renderAvatars:w,renderPresence:E,resetPreviewMode:C,scrollSyncController:P,setSession:I,setSessionLoadToken:A,setSidebarTab:z,setCurrentFilePath:U,showGitDiff:R,syncMainChrome:B,videoEmbed:N,workspaceCoordinator:$,layoutController:V}){this.backlinksPanel=e,this.clearInitialFileBootstrap=t,this.closeSidebarOnMobile=i,this.elements=s,this.excalidrawEmbed=r,this.fileExplorer=a,this.getIsTabActive=o,this.getSessionLoadToken=l,this.gitDiffView=h,this.gitPanel=c,this.imageLightbox=u,this.lobby=f,this.navigation=d,this.previewRenderer=g,this.renderAvatars=w,this.renderPresence=E,this.resetPreviewMode=C,this.scrollSyncController=P,this.setSession=I,this.setSessionLoadToken=A,this.setSidebarTab=z,this.setCurrentFilePath=U,this.showGitDiff=R,this.syncMainChrome=B,this.videoEmbed=N,this.workspaceCoordinator=$,this.layoutController=V}async handleHashChange(){if(!this.getIsTabActive())return;let e=this.navigation.getHashRoute();if(e.type==="empty"){this.gitPanel.setSelection(),this.showEmptyState(),this.syncMainChrome({mode:"empty",title:"CollabMD"});return}if(e.type==="git-diff"){this.setSidebarTab("git"),await this.showGitDiff(e);return}this.setSidebarTab("files"),await this.openFile(e.filePath)}showEmptyState(){this.gitDiffView.hide(),this.workspaceCoordinator.cleanupSession(),this.setSession(null),this.setSessionLoadToken(this.getSessionLoadToken()+1),this.clearInitialFileBootstrap(),this.resetPreviewMode(),this.elements.outlineToggle?.classList.remove("hidden"),this.elements.markdownToolbar?.classList.add("hidden"),this.setCurrentFilePath(null),this.lobby.setCurrentFile(null),this.fileExplorer.setActiveFile(null),this.elements.emptyState?.classList.remove("hidden"),this.elements.editorPage?.classList.add("hidden"),this.elements.diffPage?.classList.add("hidden"),this.elements.previewContent&&(this.elements.previewContent.innerHTML="",this.elements.previewContent.dataset.renderPhase="ready"),this.videoEmbed?.reconcileEmbeds(this.elements.previewContent),this.resetPreviewSurface(),this.renderAvatars(),this.renderPresence(),this.backlinksPanel.clear(),this.elements.activeFileName&&(this.elements.activeFileName.textContent="CollabMD")}showDiffState(){this.setSessionLoadToken(this.getSessionLoadToken()+1),this.clearInitialFileBootstrap(),this.workspaceCoordinator.cleanupSession(),this.setSession(null),this.resetPreviewMode(),this.layoutController.reset(),this.setCurrentFilePath(null),this.lobby.setCurrentFile(null),this.fileExplorer.setActiveFile(null),this.elements.emptyState?.classList.add("hidden"),this.elements.editorPage?.classList.add("hidden"),this.elements.diffPage?.classList.remove("hidden"),this.elements.previewContent&&(this.elements.previewContent.innerHTML="",this.elements.previewContent.dataset.renderPhase="ready"),this.videoEmbed?.reconcileEmbeds(this.elements.previewContent),this.resetPreviewSurface(),this.elements.outlineToggle?.classList.add("hidden"),this.elements.markdownToolbar?.classList.add("hidden"),this.renderAvatars(),this.renderPresence(),this.backlinksPanel.clear()}async openFile(e){this.imageLightbox?.close?.(),this.gitPanel.setSelection(),this.gitDiffView.hide(),this.syncMainChrome({mode:"editor"}),await this.workspaceCoordinator.openFile(e),this.setSession(this.workspaceCoordinator.getSession())}cleanupSession(){this.workspaceCoordinator.cleanupSession(),this.setSession(this.workspaceCoordinator.getSession())}handleFileSelection(e,{closeSidebarOnMobile:t=!1}={}){t&&this.closeSidebarOnMobile(),this.navigation.navigateToFile(e)}resetPreviewSurface(){this.imageLightbox?.close?.(),this.previewRenderer.setHydrationPaused(!1),this.excalidrawEmbed.setHydrationPaused(!1),this.videoEmbed?.detachForCommit(),this.scrollSyncController.setLargeDocumentMode(!1),this.scrollSyncController.invalidatePreviewBlocks()}};function x(n){let e=String(n??"").trim().replace(/\\/g,"/").replace(/^\/+/u,"").split("/").map(t=>t.trim()).filter(Boolean);return e.some(t=>t==="."||t==="..")?"":e.join("/")}function se(n,e){let t=x(n),i=x(e);return t?i?`${t}/${i}`:t:i}function Yt(n,e){return n.toLowerCase().endsWith(e.toLowerCase())?n:`${n}${e}`}function Pe(n){return`# ${q(String(n??"").split("/").pop()||"")||"Untitled"}
|
|
23
|
+
`))}getPreviewInitConfig(e){return/^\s*stateDiagram(?:-v2)?\b/m.test(e)?{htmlLabels:!1}:/^\s*classDiagram\b/m.test(e)?{htmlLabels:!1}:/^\s*gantt\b/m.test(e)?{htmlLabels:!1}:null}resetHydratedShells(){let e=this.renderer.previewElement;if(!e)return;let t=Array.from(e.querySelectorAll('.mermaid-shell[data-mermaid-hydrated="true"]'));t.length!==0&&t.forEach(i=>{this.shellRefits.delete(i),i.removeAttribute("data-mermaid-hydrated"),i.querySelector(":scope > .mermaid-toolbar")?.remove(),i.querySelector(":scope > .mermaid-frame")?.remove(),i.querySelector(":scope > .mermaid-render-node")?.remove(),i.querySelector(".mermaid-placeholder-card")||i.querySelector(".mermaid-source")?.after(ii(i.dataset.mermaidKey||"mermaid")),this.enqueueShell(i,{prioritize:!0})})}enhanceDiagram(e,t){let i=t.querySelector("svg");if(!i){t.remove();return}let s=document.createElement("div");s.className="mermaid-toolbar diagram-preview-toolbar";let r=this.createZoomButton("\u2212","Zoom out"),a=this.createZoomButton("+","Zoom in"),o=this.createZoomButton("Reset","Reset zoom"),l=this.createZoomButton("Max","Maximize diagram");l.classList.add("mermaid-maximize-btn"),T(l,"maximize");let h=document.createElement("span");h.className="mermaid-zoom-label diagram-preview-zoom-label",h.setAttribute("aria-live","polite"),s.append(r,h,o,a,l);let c=document.createElement("div");c.className="mermaid-frame diagram-preview-frame";let{width:u,height:p}=ti(i),d=k.default,w=1,m=null,b=null,E=!1,I=0,F=!1,A=null,z=0,U=0,R=0,B=0;i.style.display="block",i.style.margin="0 auto",i.style.maxWidth="none";let N=()=>{let f=j(c);if(!Number.isFinite(u)||u<=0||f.width<=0)return k.default;let y=f.width/u;return!Number.isFinite(y)||y<=0?k.default:x(y,k.min,k.max)},$=f=>{d=x(f,k.min,k.max),i.style.width=`${u*d}px`,i.style.height=`${p*d}px`,h.textContent=`${Math.round(d*100)}%`,r.disabled=d<=k.min,a.disabled=d>=k.max;let y=j(c),v=u*d>y.width||p*d>y.height;c.classList.toggle("is-pannable",v),i.style.margin=v?"0":"0 auto"},G=()=>({x:c.scrollLeft+c.clientWidth/2,y:c.scrollTop+c.clientHeight/2}),V=(f,y,v)=>{if(f===0)return;let S=y/f;c.scrollLeft=v.x*S-c.clientWidth/2,c.scrollTop=v.y*S-c.clientHeight/2},Y=f=>{let y=x(f,k.min,k.max),v=d;if(y===v)return;let S=G(),gt=performance.now();m&&cancelAnimationFrame(m);let ae=wt=>{let oe=x((wt-gt)/k.animationDurationMs,0,1),yt=Pe(oe),le=v+(y-v)*yt;if($(le),V(v,le,S),oe<1){m=requestAnimationFrame(ae);return}m=null,$(y),V(v,y,S)};m=requestAnimationFrame(ae)},K=f=>{E=!0,Y(d+f)},D=({animate:f=!1}={})=>{if(w=N(),E=!1,I=j(c).width,f&&Math.abs(w-d)>.001){Y(w);return}m&&(cancelAnimationFrame(m),m=null),$(w),c.scrollLeft=0,c.scrollTop=0},M=({force:f=!1}={})=>{b&&cancelAnimationFrame(b),b=requestAnimationFrame(()=>{if(b=null,!e.isConnected)return;let y=j(c).width,v=Math.abs(y-I)>1;!f&&E||!f&&I>0&&!v||D()})};this.shellRefits.set(e,M),r.addEventListener("click",()=>K(-k.step)),a.addEventListener("click",()=>K(k.step)),o.addEventListener("click",()=>{D({animate:!0})});let H=()=>{let f=e.classList.contains("is-maximized");T(l,f?"restore":"maximize");let y=f?"Restore diagram size":"Maximize diagram";l.setAttribute("aria-label",y),l.title=y},te=f=>{let y=this.renderer.previewElement;if(f){let v=y.querySelector(".mermaid-shell.is-maximized");if(v&&v!==e){v.classList.remove("is-maximized"),this.shellRefits.get(v)?.();let S=v.querySelector(".mermaid-maximize-btn");S&&(T(S,"maximize"),S.setAttribute("aria-label","Maximize diagram"),S.title="Maximize diagram")}e.classList.add("is-maximized"),document.body.classList.add("mermaid-maximized-open"),H(),M({force:!0});return}e.classList.remove("is-maximized"),y.querySelector(".mermaid-shell.is-maximized")||document.body.classList.remove("mermaid-maximized-open"),H(),M({force:!0})};H(),l.addEventListener("click",()=>{te(!e.classList.contains("is-maximized"))});let O=()=>{if(F){if(F=!1,c.classList.remove("is-dragging"),A!==null&&typeof c.releasePointerCapture=="function")try{c.releasePointerCapture(A)}catch{}A=null}};c.addEventListener("pointerdown",f=>{f.button!==0||!c.classList.contains("is-pannable")||(m&&(cancelAnimationFrame(m),m=null),F=!0,A=f.pointerId,z=f.clientX,U=f.clientY,R=c.scrollLeft,B=c.scrollTop,c.classList.add("is-dragging"),c.setPointerCapture?.(f.pointerId),f.preventDefault())}),c.addEventListener("pointermove",f=>{F&&(c.scrollLeft=R-(f.clientX-z),c.scrollTop=B-(f.clientY-U))}),c.addEventListener("pointerup",O),c.addEventListener("pointercancel",O),c.addEventListener("lostpointercapture",O),c.appendChild(i);let _=e.querySelector(".mermaid-source");t.remove(),e.replaceChildren(),_&&(_.hidden=!0,e.appendChild(_)),e.append(s,c),M({force:!0})}scheduleActiveRefit(){let e=this.renderer.previewElement;e&&Array.from(e.querySelectorAll('.mermaid-shell[data-mermaid-hydrated="true"]')).forEach(t=>{this.shellRefits.get(t)?.()})}createZoomButton(e,t){let i=document.createElement("button");return i.type="button",i.className="mermaid-zoom-btn diagram-preview-action-btn",i.setAttribute("aria-label",t),i.title=t,i.textContent=e,i}};var xe=class extends se{constructor(e){super(e,{batchSize:ei,datasetKeys:{hydrated:"plantumlHydrated",instanceId:"plantumlInstanceId",key:"plantumlKey",label:"plantumlLabel",queued:"plantumlQueued",sourceHash:"plantumlSourceHash",sourceLine:"sourceLine",sourceLineEnd:"sourceLineEnd",target:"plantumlTarget"},filePathLabel:"PlantUML",shellClassName:"plantuml-shell",sourceClassName:"plantuml-source"}),this.renderer=e,this.svgCache=new Map,this.svgInflightRequests=new Map,this.shellRefits=new WeakMap,this.activeMaximizedShell=null,this.maximizedRoot=null,this.resizeFrameId=null}destroy(){this.cancelHydration(),this.preservedShells.clear(),this.clearActiveShell(),this.resizeFrameId&&(cancelAnimationFrame(this.resizeFrameId),this.resizeFrameId=null),this.maximizedRoot?.remove(),this.maximizedRoot=null}clearActiveShell(){this.activeMaximizedShell=null,this.maximizedRoot&&this.maximizedRoot.childElementCount===0&&(this.maximizedRoot.hidden=!0)}syncActiveShell(){return this.activeMaximizedShell?.isConnected&&this.activeMaximizedShell.classList.contains("is-maximized")?this.activeMaximizedShell:(this.clearActiveShell(),null)}scheduleActiveRefit(){this.resizeFrameId&&cancelAnimationFrame(this.resizeFrameId),this.resizeFrameId=requestAnimationFrame(()=>{this.resizeFrameId=null;let e=this.syncActiveShell();e&&this.shellRefits.get(e)?.()})}handleReconcile({restoredMaximizedShell:e}){e&&document.body.classList.add("plantuml-maximized-open"),this.syncActiveShell()}ensureMaximizedRoot(){if(this.maximizedRoot?.isConnected&&this.maximizedRoot.parentElement===document.body)return this.maximizedRoot;let e=document.body.querySelector('[data-plantuml-maximized-root="true"]');return e||(e=document.createElement("div"),e.dataset.plantumlMaximizedRoot="true",e.className="plantuml-maximized-root",document.body.appendChild(e)),this.maximizedRoot=e,e}mountShellInMaximizedRoot(e){if(!e)return;let t=this.ensureMaximizedRoot();t.hidden=!1,e._plantumlRestoreParent=e.parentElement||null,e._plantumlRestoreNextSibling=e.nextSibling||null,t.appendChild(e)}restoreShellMount(e){if(!e)return;let t=e._plantumlRestoreParent,i=e._plantumlRestoreNextSibling;t?.isConnected&&(i?.parentElement===t?t.insertBefore(e,i):t.appendChild(e)),e._plantumlRestoreParent=null,e._plantumlRestoreNextSibling=null,this.maximizedRoot&&this.maximizedRoot.childElementCount===0&&(this.maximizedRoot.hidden=!0)}async hydrateShell(e){if(!e?.isConnected||this.isShellHydrated(e))return;let t=e.querySelector(".plantuml-source");t||(t=document.createElement("span"),t.className="plantuml-source",t.hidden=!0,e.appendChild(t)),e.querySelector(".plantuml-placeholder-card")?.remove();try{let i=t.textContent??"";if(!i.trim()&&e.dataset.plantumlTarget){if(i=await this.fetchSource(e.dataset.plantumlTarget),!e.isConnected)return;t.textContent=i}if(!i.trim())throw new Error(e.dataset.plantumlTarget?"PlantUML file is empty":"PlantUML source is empty");let s=await this.fetchSvg(i);if(!e.isConnected)return;this.enhanceDiagram(e,s),this.markShellHydrated(e)}catch(i){console.warn("[preview] PlantUML render failed:",i),e.querySelector(":scope > .plantuml-toolbar")?.remove(),e.querySelector(":scope > .plantuml-frame")?.remove(),e.querySelector(".plantuml-placeholder-card")||t?.after(Ct(e.dataset.plantumlKey||"plantuml",i instanceof Error?i.message:"Render failed"))}}async fetchSvg(e){let t=e;if(this.svgCache.has(t))return this.svgCache.get(t);if(this.svgInflightRequests.has(t))return this.svgInflightRequests.get(t);let i=fetch(C("/plantuml/render"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({source:e})}).then(async s=>{let r=await s.json().catch(()=>null);if(!s.ok||!r?.ok||typeof r.svg!="string")throw new Error(r?.error||"Failed to render PlantUML");let a=ni(r.svg);return this.svgCache.set(t,a),a}).finally(()=>{this.svgInflightRequests.delete(t)});return this.svgInflightRequests.set(t,i),i}resetShell(e,{clearCache:t=!1,message:i="Renders server-side when visible"}={}){let s=e.querySelector(".plantuml-source")?.textContent??"";t&&s&&(this.svgCache.delete(s),this.svgInflightRequests.delete(s)),this.shellRefits.delete(e),this.activeMaximizedShell===e&&(this.restoreShellMount(e),this.clearActiveShell()),e.removeAttribute("data-plantuml-hydrated"),e.removeAttribute("data-plantuml-instance-id"),e.removeAttribute("data-plantuml-queued"),e.classList.remove("is-maximized"),this.syncActiveShell()||document.body.classList.remove("plantuml-maximized-open"),e.querySelector(":scope > .plantuml-toolbar")?.remove(),e.querySelector(":scope > .plantuml-frame")?.remove(),e.querySelector(".plantuml-placeholder-card")||e.querySelector(".plantuml-source")?.after(Ct(e.dataset.plantumlKey||"plantuml",i))}enhanceDiagram(e,t){let i=document.createElement("div");i.innerHTML=t;let s=i.querySelector("svg");if(!s)throw new Error("Renderer returned invalid SVG");let r=document.createElement("div");r.className="plantuml-toolbar diagram-preview-toolbar";let a=document.createElement("div");a.className="plantuml-frame diagram-preview-frame";let o=this.createToolButton("\u2212","Zoom out"),l=this.createToolButton("+","Zoom in"),h=this.createToolButton("Reset","Reset zoom"),c=this.createToolButton("Reload","Reload diagram"),u=this.createToolButton("Max","Maximize diagram");u.classList.add("plantuml-maximize-btn"),T(c,"refresh"),T(u,"maximize");let p=document.createElement("span");p.className="plantuml-zoom-label diagram-preview-zoom-label",p.setAttribute("aria-live","polite"),r.append(o,p,h,l,c,u);let{width:d,height:w}=ce(s),m=P.default,b=1,E=null,I=!1,F=null,A=0,z=0,U=0,R=0;s.style.display="block",s.style.margin="0 auto",s.style.maxWidth="none";let B=()=>{let f=j(a);return!Number.isFinite(d)||d<=0||f.width<=0?P.default:x(Math.min(P.default,f.width/d),P.min,P.max)},N=f=>{m=x(f,P.min,P.max),s.style.width=`${d*m}px`,s.style.height=`${w*m}px`,p.textContent=`${Math.round(m*100)}%`,o.disabled=m<=P.min,l.disabled=m>=P.max;let y=j(a),v=d*m>y.width||w*m>y.height;a.classList.toggle("is-pannable",v)},$=()=>({x:a.scrollLeft+a.clientWidth/2,y:a.scrollTop+a.clientHeight/2}),G=(f,y,v)=>{if(f===0)return;let S=y/f;a.scrollLeft=v.x*S-a.clientWidth/2,a.scrollTop=v.y*S-a.clientHeight/2},V=f=>{let y=x(f,P.min,P.max),v=m;if(y===v)return;let S=$(),gt=performance.now();E&&cancelAnimationFrame(E);let ae=wt=>{let oe=x((wt-gt)/P.animationDurationMs,0,1),yt=Pe(oe),le=v+(y-v)*yt;if(N(le),G(v,le,S),oe<1){E=requestAnimationFrame(ae);return}E=null,N(y),G(v,y,S)};E=requestAnimationFrame(ae)},Y=f=>{V(m+f)},K=({animate:f=!1}={})=>{if(b=B(),f&&Math.abs(b-m)>.001){V(b);return}E&&(cancelAnimationFrame(E),E=null),N(b),a.scrollLeft=0,a.scrollTop=0},D=null,M=()=>{D&&cancelAnimationFrame(D),D=requestAnimationFrame(()=>{D=null,e.isConnected&&K()})};this.shellRefits.set(e,M),o.addEventListener("click",()=>Y(-P.step)),l.addEventListener("click",()=>Y(P.step)),h.addEventListener("click",()=>{K({animate:!0})});let H=()=>{let f=e.classList.contains("is-maximized");T(u,f?"restore":"maximize");let y=f?"Restore diagram size":"Maximize diagram";u.setAttribute("aria-label",y),u.title=y},te=f=>{if(f){let y=this.syncActiveShell();if(y&&y!==e){this.restoreShellMount(y),y.classList.remove("is-maximized"),this.activeMaximizedShell===y&&this.clearActiveShell(),this.shellRefits.get(y)?.();let v=y.querySelector(".plantuml-maximize-btn");v&&(T(v,"maximize"),v.setAttribute("aria-label","Maximize diagram"),v.title="Maximize diagram")}this.mountShellInMaximizedRoot(e),e.classList.add("is-maximized"),this.activeMaximizedShell=e,document.body.classList.add("plantuml-maximized-open"),H(),M();return}this.restoreShellMount(e),e.classList.remove("is-maximized"),this.activeMaximizedShell===e&&this.clearActiveShell(),this.syncActiveShell()||document.body.classList.remove("plantuml-maximized-open"),H(),M()};c.addEventListener("click",()=>{this.resetShell(e,{clearCache:!0,message:"Refreshing\u2026"}),this.enqueueShell(e,{prioritize:!0})}),H(),u.addEventListener("click",()=>{te(!e.classList.contains("is-maximized"))});let O=()=>{if(I){if(I=!1,a.classList.remove("is-dragging"),F!==null&&typeof a.releasePointerCapture=="function")try{a.releasePointerCapture(F)}catch{}F=null}};a.addEventListener("pointerdown",f=>{f.button!==0||!a.classList.contains("is-pannable")||(E&&(cancelAnimationFrame(E),E=null),I=!0,F=f.pointerId,A=f.clientX,z=f.clientY,U=a.scrollLeft,R=a.scrollTop,a.classList.add("is-dragging"),a.setPointerCapture?.(f.pointerId),f.preventDefault())}),a.addEventListener("pointermove",f=>{I&&(a.scrollLeft=U-(f.clientX-A),a.scrollTop=R-(f.clientY-z))}),a.addEventListener("pointerup",O),a.addEventListener("pointercancel",O),a.addEventListener("lostpointercapture",O),a.appendChild(s);let _=e.querySelector(".plantuml-source");e.replaceChildren(),_&&(_.hidden=!0,e.appendChild(_)),e.append(r,a),b=B(),N(b)}createToolButton(e,t){let i=document.createElement("button");return i.type="button",i.className="plantuml-tool-btn diagram-preview-action-btn",i.setAttribute("aria-label",t),i.title=t,i.textContent=e,i}};function nn(){return new Worker(new URL("./preview-render-worker.js",import.meta.url),{type:"module"})}var Ie=class{constructor({attachmentApiPath:e="/api/attachment",cancelIdleRenderFn:t=ne,compilePreviewDocumentLoader:i=()=>import("./chunks/preview-render-compiler-6Y7TKXFJ.js"),createWorkerFn:s=nn,getFileList:r,getSourceFilePath:a=null,idleTimeoutMs:o=W,requestIdleRenderFn:l=ie}={}){this.attachmentApiPath=e,this.cancelIdleRenderFn=t,this.compilePreviewDocumentLoader=i,this.createWorkerFn=s,this.getFileList=r,this.getSourceFilePath=a,this.idleTimeoutMs=o,this.requestIdleRenderFn=l,this.worker=null,this.workerDisabled=!1,this.workerJob=null,this.workerPrewarmId=null,this.handleWorkerMessage=h=>{if(!this.workerJob||h.data?.renderVersion!==this.workerJob.renderVersion)return;let c=this.workerJob;if(this.workerJob=null,h.data?.error){c.reject(new Error(h.data.error));return}c.resolve({html:h.data.html,stats:h.data.stats})},this.handleWorkerError=h=>{let c=new Error(h.message||"Preview worker failed");this.workerJob&&(this.workerJob.reject(c),this.workerJob=null),this.reset("Preview worker failed",{disable:!0})}}hasPendingJob(){return this.workerJob!==null}schedulePrewarm({timeout:e=this.idleTimeoutMs}={}){this.workerDisabled||this.worker||this.workerPrewarmId!==null||(this.workerPrewarmId=this.requestIdleRenderFn(()=>{this.workerPrewarmId=null,this.ensureWorker()},e))}ensureWorker(){if(this.workerDisabled)return null;if(this.worker)return this.worker;try{return this.worker=this.createWorkerFn(),this.worker.addEventListener("message",this.handleWorkerMessage),this.worker.addEventListener("error",this.handleWorkerError),this.worker}catch{return this.workerDisabled=!0,null}}async compile(e,t){if(this.ensureWorker()){this.workerJob&&this.reset("Superseded preview render");let r=this.ensureWorker();return new Promise((a,o)=>{this.workerJob={reject:o,renderVersion:t,resolve:a},r.postMessage({attachmentApiPath:this.attachmentApiPath,fileList:this.getFileList?.()??[],markdownText:e,renderVersion:t,sourceFilePath:this.getSourceFilePath?.()??""})})}let{compilePreviewDocument:s}=await this.compilePreviewDocumentLoader();return s({attachmentApiPath:this.attachmentApiPath,fileList:this.getFileList?.()??[],markdownText:e,sourceFilePath:this.getSourceFilePath?.()??""})}cancelWorkerJob(e){this.workerJob&&(this.workerJob.reject(new Error(e)),this.workerJob=null)}reset(e,{disable:t=!1}={}){this.cancelWorkerJob(e),this.worker&&(this.worker.removeEventListener("message",this.handleWorkerMessage),this.worker.removeEventListener("error",this.handleWorkerError),this.worker.terminate(),this.worker=null),t&&(this.workerDisabled=!0)}destroy(e="Preview renderer destroyed"){this.workerPrewarmId!==null&&this.cancelIdleRenderFn(this.workerPrewarmId),this.workerPrewarmId=null,this.reset(e)}};var Fe=class{constructor({cancelAnimationFrameFn:e=h=>cancelAnimationFrame(h),cancelIdleRenderFn:t=ne,clearTimeoutFn:i=h=>clearTimeout(h),getRenderProfileFn:s=be,idleTimeoutMs:r=W,requestAnimationFrameFn:a=h=>requestAnimationFrame(h),requestIdleRenderFn:o=ie,setTimeoutFn:l=(h,c)=>setTimeout(h,c)}={}){this.cancelAnimationFrameFn=e,this.cancelIdleRenderFn=t,this.clearTimeoutFn=i,this.getRenderProfileFn=s,this.idleTimeoutMs=r,this.requestAnimationFrameFn=a,this.requestIdleRenderFn=o,this.setTimeoutFn=l,this.frameId=null,this.idleId=null,this.timeoutId=null}queue({markdownText:e,onRenderRequested:t,renderVersion:i}){let s=this.getRenderProfileFn(e);this.cancel();let r=()=>{this.frameId=this.requestAnimationFrameFn(()=>{this.frameId=null,this.timeoutId=null,t?.(e,i)})},a=()=>{if(s.deferUntilIdle){this.idleId=this.requestIdleRenderFn(()=>{this.idleId=null,r()},this.idleTimeoutMs);return}r()};this.timeoutId=this.setTimeoutFn(a,s.debounceMs)}cancel(){this.clearTimeoutFn(this.timeoutId),this.frameId&&this.cancelAnimationFrameFn(this.frameId),this.cancelIdleRenderFn(this.idleId),this.frameId=null,this.idleId=null,this.timeoutId=null}destroy(){this.cancel()}};var Te=class{constructor({getContent:e,getFileList:t,getSourceFilePath:i,onAfterRenderCommit:s,onBeforeRenderCommit:r,onRenderComplete:a,outlineController:o,previewContainer:l,previewElement:h}){this.getContent=e,this.getFileList=t,this.getSourceFilePath=i,this.onAfterRenderCommit=s,this.onBeforeRenderCommit=r,this.onRenderComplete=a,this.outlineController=o,this.previewContainer=l,this.previewElement=h,this.renderHost=null,this.pendingRenderVersion=0,this.activeRenderVersion=0,this.readyRenderVersion=0,this.currentStats=null,this.isLargeDocument=!1,this.hydrationPaused=!1,this.handlePreviewClick=c=>{let u=c.target.closest(".mermaid-placeholder-btn");if(u){let d=u.closest(".mermaid-shell");if(!d)return;c.preventDefault(),this.enqueueMermaidShell(d,{prioritize:!0});return}let p=c.target.closest(".plantuml-placeholder-btn");if(p){let d=p.closest(".plantuml-shell");if(!d)return;c.preventDefault(),this.enqueuePlantUmlShell(d,{prioritize:!0})}},this.handleWindowResize=()=>{this.mermaidHydrator.scheduleActiveRefit(),this.plantUmlHydrator.scheduleActiveRefit()},this.mermaidHydrator=new Le(this),this.plantUmlHydrator=new xe(this),this.renderScheduler=new Fe({getRenderProfileFn:be}),this.renderExecutor=new Ie({attachmentApiPath:C("/attachment"),getFileList:()=>this.getFileList?.()??[],getSourceFilePath:()=>this.getSourceFilePath?.()??"",idleTimeoutMs:W}),this.previewElement?.addEventListener("click",this.handlePreviewClick),window.addEventListener("resize",this.handleWindowResize),this.setPhase("ready")}ensureRenderHost(){if(!this.previewElement)return null;if(this.renderHost?.isConnected&&this.renderHost.parentElement===this.previewElement)return this.renderHost;let e=this.previewElement.querySelector('[data-preview-render-host="true"]');return e||(e=document.createElement("div"),e.dataset.previewRenderHost="true",this.previewElement.appendChild(e)),this.renderHost=e,this.renderHost}normalizePreviewChildren(e=this.renderHost){this.previewElement&&Array.from(this.previewElement.children).forEach(t=>{t===e||t.dataset.excalidrawOverlayRoot==="true"||t.dataset.videoOverlayRoot==="true"||t.remove()})}getReservedPreviewHeight(){let e=this.renderHost?.getBoundingClientRect?.().height??0,t=this.previewContainer?.clientHeight??0;return Math.max(Math.round(e),Math.round(t),320)}beginDocumentLoad(){this.cancelScheduledRender(),this.cancelMermaidHydration(),this.cancelPlantUmlHydration(),this.mermaidHydrator.clearPreservedShells(),this.plantUmlHydrator.clearPreservedShells(),this.clearActivePlantUmlShell(),this.onBeforeRenderCommit?.(this.previewElement),this.pendingRenderVersion+=1,this.activeRenderVersion=this.pendingRenderVersion,this.readyRenderVersion=0,this.currentStats=null,this.isLargeDocument=!1,this.renderExecutor.hasPendingJob()&&this.resetWorker("Document changed");let e=this.ensureRenderHost();this.normalizePreviewChildren(e);let t=this.getReservedPreviewHeight();e&&(e.replaceChildren(),e.style.minHeight=`${t}px`);let i=document.createElement("div");i.className="preview-shell",i.style.minHeight=`${t}px`,i.textContent="Rendering preview\u2026",e?.append(i),this.setPhase("shell")}applyTheme(e){let t=document.getElementById("hljs-theme");if(t){let{darkHref:i,lightHref:s}=t.dataset;t.href=e==="dark"?i:s}this.mermaidHydrator.applyTheme(e)}configureMermaid(e){this.mermaidHydrator.configureMermaid(e)}ensureMermaid(){return this.mermaidHydrator.ensureMermaid()}queueRender(){let e=this.getContent();this.cancelScheduledRender(),this.pendingRenderVersion+=1;let t=this.pendingRenderVersion;this.renderScheduler.queue({markdownText:e,onRenderRequested:(i,s)=>{this.render(i,s)},renderVersion:t})}async render(e=this.getContent(),t=this.pendingRenderVersion){if(this.previewElement)try{let i=await this.compilePreview(e,t);if(t!==this.pendingRenderVersion)return;this.commitBaseRender(i,t)}catch(i){if(t!==this.pendingRenderVersion)return;console.warn("[preview] Failed to render preview:",i)}}destroy(){this.renderScheduler.destroy(),this.mermaidHydrator.destroy(),this.plantUmlHydrator.destroy(),this.renderExecutor.destroy(),this.previewElement?.removeEventListener("click",this.handlePreviewClick),window.removeEventListener("resize",this.handleWindowResize)}setPhase(e){this.previewElement&&(this.previewElement.dataset.renderPhase=e)}cancelScheduledRender(){this.renderScheduler.cancel()}cancelMermaidHydration(){this.mermaidHydrator.cancelHydration()}cancelPlantUmlHydration(){this.plantUmlHydrator.cancelHydration()}clearActivePlantUmlShell(){this.plantUmlHydrator.clearActiveShell()}scheduleActiveMermaidRefit(){this.mermaidHydrator.scheduleActiveRefit()}syncActivePlantUmlShell(){return this.plantUmlHydrator.syncActiveShell()}scheduleActivePlantUmlRefit(){this.plantUmlHydrator.scheduleActiveRefit()}setHydrationPaused(e){if(this.hydrationPaused=!!e,this.hydrationPaused){this.mermaidHydrator.cancelPendingIdleWork(),this.plantUmlHydrator.cancelPendingIdleWork();return}this.mermaidHydrator.hydrateVisibleShells(),this.mermaidHydrator.scheduleHydration(),this.plantUmlHydrator.hydrateVisibleShells(),this.plantUmlHydrator.scheduleHydration(),this.updateHydrationPhase()}resetWorker(e,{disable:t=!1}={}){this.renderExecutor.reset(e,{disable:t})}scheduleWorkerPrewarm({timeout:e=W}={}){this.renderExecutor.schedulePrewarm({timeout:e})}async compilePreview(e,t){return this.renderExecutor.compile(e,t)}commitBaseRender({html:e,stats:t},i){this.activeRenderVersion=i,this.readyRenderVersion=0,this.currentStats=t,this.isLargeDocument=Vt(t),this.cancelMermaidHydration(),this.cancelPlantUmlHydration(),document.body.classList.remove("mermaid-maximized-open"),document.body.classList.remove("plantuml-maximized-open"),this.preserveHydratedMermaidsForCommit(),this.preserveHydratedPlantUmlsForCommit(),this.onBeforeRenderCommit?.(this.previewElement);let s=this.ensureRenderHost();this.normalizePreviewChildren(s),s&&(s.innerHTML=e),this.reconcileHydratedMermaids(),this.reconcileHydratedPlantUmls(),this.setPhase("base"),this.outlineController.refresh(),this.onAfterRenderCommit?.(this.previewElement,{...t,isLargeDocument:this.isLargeDocument,renderVersion:i});let r=this.setupMermaidHydration(i),a=this.setupPlantUmlHydration(i);r===0&&a===0&&this.notifyReady()}preserveHydratedMermaidsForCommit(){this.mermaidHydrator.preserveHydratedShellsForCommit()}preserveHydratedPlantUmlsForCommit(){this.plantUmlHydrator.preserveHydratedShellsForCommit()}reconcileHydratedMermaids(){this.mermaidHydrator.reconcileHydratedShells()}reconcileHydratedPlantUmls(){this.plantUmlHydrator.reconcileHydratedShells()}syncPreservedMermaidShell(e,t){this.mermaidHydrator.syncPreservedShell(e,t)}syncPreservedPlantUmlShell(e,t){this.plantUmlHydrator.syncPreservedShell(e,t)}setupMermaidHydration(e){return this.mermaidHydrator.setupHydration(e)}hydrateVisibleMermaids(){this.mermaidHydrator.hydrateVisibleShells()}enqueueMermaidShell(e,{prioritize:t=!1}={}){this.mermaidHydrator.enqueueShell(e,{prioritize:t})}scheduleMermaidHydration(){this.mermaidHydrator.scheduleHydration()}async flushMermaidHydrationQueue(){await this.mermaidHydrator.flushHydrationQueue()}async hydrateMermaidShell(e,t){await this.mermaidHydrator.hydrateShell(e,t)}resetHydratedMermaids(){this.mermaidHydrator.resetHydratedShells()}setupPlantUmlHydration(e){return this.plantUmlHydrator.setupHydration(e)}hydrateVisiblePlantUmls(){this.plantUmlHydrator.hydrateVisibleShells()}enqueuePlantUmlShell(e,{prioritize:t=!1}={}){this.plantUmlHydrator.enqueueShell(e,{prioritize:t})}schedulePlantUmlHydration(){this.plantUmlHydrator.scheduleHydration()}async flushPlantUmlHydrationQueue(){await this.plantUmlHydrator.flushHydrationQueue()}async hydratePlantUmlShell(e){await this.plantUmlHydrator.hydrateShell(e)}updateHydrationPhase(){if(this.hydrationPaused&&(this.mermaidHydrator.hasPendingWork()||this.plantUmlHydrator.hasPendingWork())){this.setPhase("base");return}if(this.mermaidHydrator.hasPendingWork()||this.plantUmlHydrator.hasPendingWork()){this.setPhase("hydrating");return}this.notifyReady()}notifyReady(){this.renderHost&&(this.renderHost.style.minHeight=""),this.setPhase("ready"),this.readyRenderVersion!==this.activeRenderVersion&&(this.readyRenderVersion=this.activeRenderVersion,this.onRenderComplete?.({isLargeDocument:this.isLargeDocument,stats:this.currentStats}))}async fetchPlantUmlSvg(e){return this.plantUmlHydrator.fetchSvg(e)}async fetchPlantUmlSource(e){return this.plantUmlHydrator.fetchSource(e)}async fetchMermaidSource(e){return this.mermaidHydrator.fetchSource(e)}resetPlantUmlShell(e,{clearCache:t=!1,message:i="Renders server-side when visible"}={}){this.plantUmlHydrator.resetShell(e,{clearCache:t,message:i})}enhancePlantUmlDiagram(e,t){this.plantUmlHydrator.enhanceDiagram(e,t)}enhanceMermaidDiagram(e,t){this.mermaidHydrator.enhanceDiagram(e,t)}createMermaidZoomButton(e,t){return this.mermaidHydrator.createZoomButton(e,t)}createPlantUmlToolButton(e,t){return this.plantUmlHydrator.createToolButton(e,t)}};var Ae=class{constructor({backlinksPanel:e,clearInitialFileBootstrap:t,closeSidebarOnMobile:i,elements:s,excalidrawEmbed:r,fileExplorer:a,getIsTabActive:o,getSessionLoadToken:l,gitDiffView:h,gitPanel:c,imageLightbox:u=null,lobby:p,navigation:d,previewRenderer:w,renderAvatars:m,renderPresence:b,resetPreviewMode:E,scrollSyncController:I,setSession:F,setSessionLoadToken:A,setSidebarTab:z,setCurrentFilePath:U,showGitDiff:R,syncMainChrome:B,videoEmbed:N,workspaceCoordinator:$,layoutController:G}){this.backlinksPanel=e,this.clearInitialFileBootstrap=t,this.closeSidebarOnMobile=i,this.elements=s,this.excalidrawEmbed=r,this.fileExplorer=a,this.getIsTabActive=o,this.getSessionLoadToken=l,this.gitDiffView=h,this.gitPanel=c,this.imageLightbox=u,this.lobby=p,this.navigation=d,this.previewRenderer=w,this.renderAvatars=m,this.renderPresence=b,this.resetPreviewMode=E,this.scrollSyncController=I,this.setSession=F,this.setSessionLoadToken=A,this.setSidebarTab=z,this.setCurrentFilePath=U,this.showGitDiff=R,this.syncMainChrome=B,this.videoEmbed=N,this.workspaceCoordinator=$,this.layoutController=G}async handleHashChange(){if(!this.getIsTabActive())return;let e=this.navigation.getHashRoute();if(e.type==="empty"){this.gitPanel.setSelection(),this.showEmptyState(),this.syncMainChrome({mode:"empty",title:"CollabMD"});return}if(e.type==="git-diff"){this.setSidebarTab("git"),await this.showGitDiff(e);return}this.setSidebarTab("files"),await this.openFile(e.filePath)}showEmptyState(){this.gitDiffView.hide(),this.workspaceCoordinator.cleanupSession(),this.setSession(null),this.setSessionLoadToken(this.getSessionLoadToken()+1),this.clearInitialFileBootstrap(),this.resetPreviewMode(),this.elements.outlineToggle?.classList.remove("hidden"),this.elements.markdownToolbar?.classList.add("hidden"),this.setCurrentFilePath(null),this.lobby.setCurrentFile(null),this.fileExplorer.setActiveFile(null),this.elements.emptyState?.classList.remove("hidden"),this.elements.editorPage?.classList.add("hidden"),this.elements.diffPage?.classList.add("hidden"),this.elements.previewContent&&(this.elements.previewContent.innerHTML="",this.elements.previewContent.dataset.renderPhase="ready"),this.videoEmbed?.reconcileEmbeds(this.elements.previewContent),this.resetPreviewSurface(),this.renderAvatars(),this.renderPresence(),this.backlinksPanel.clear(),this.elements.activeFileName&&(this.elements.activeFileName.textContent="CollabMD")}showDiffState(){this.setSessionLoadToken(this.getSessionLoadToken()+1),this.clearInitialFileBootstrap(),this.workspaceCoordinator.cleanupSession(),this.setSession(null),this.resetPreviewMode(),this.layoutController.reset(),this.setCurrentFilePath(null),this.lobby.setCurrentFile(null),this.fileExplorer.setActiveFile(null),this.elements.emptyState?.classList.add("hidden"),this.elements.editorPage?.classList.add("hidden"),this.elements.diffPage?.classList.remove("hidden"),this.elements.previewContent&&(this.elements.previewContent.innerHTML="",this.elements.previewContent.dataset.renderPhase="ready"),this.videoEmbed?.reconcileEmbeds(this.elements.previewContent),this.resetPreviewSurface(),this.elements.outlineToggle?.classList.add("hidden"),this.elements.markdownToolbar?.classList.add("hidden"),this.renderAvatars(),this.renderPresence(),this.backlinksPanel.clear()}async openFile(e){this.imageLightbox?.close?.(),this.gitPanel.setSelection(),this.gitDiffView.hide(),this.syncMainChrome({mode:"editor"}),await this.workspaceCoordinator.openFile(e),this.setSession(this.workspaceCoordinator.getSession())}cleanupSession(){this.workspaceCoordinator.cleanupSession(),this.setSession(this.workspaceCoordinator.getSession())}handleFileSelection(e,{closeSidebarOnMobile:t=!1}={}){t&&this.closeSidebarOnMobile(),this.navigation.navigateToFile(e)}resetPreviewSurface(){this.imageLightbox?.close?.(),this.previewRenderer.setHydrationPaused(!1),this.excalidrawEmbed.setHydrationPaused(!1),this.videoEmbed?.detachForCommit(),this.scrollSyncController.setLargeDocumentMode(!1),this.scrollSyncController.invalidatePreviewBlocks()}};function L(n){let e=String(n??"").trim().replace(/\\/g,"/").replace(/^\/+/u,"").split("/").map(t=>t.trim()).filter(Boolean);return e.some(t=>t==="."||t==="..")?"":e.join("/")}function re(n,e){let t=L(n),i=L(e);return t?i?`${t}/${i}`:t:i}function ai(n,e){return n.toLowerCase().endsWith(e.toLowerCase())?n:`${n}${e}`}function Me(n){return`# ${q(String(n??"").split("/").pop()||"")||"Untitled"}
|
|
24
24
|
|
|
25
|
-
`}function
|
|
26
|
-
`),path:t}}function
|
|
27
|
-
`),path:t}}var
|
|
25
|
+
`}function oi(n){let e=L(n),t=ge(e)?e:`${e}.mmd`;return{content:["flowchart TD"," A[Start] --> B{Decide}"," B -->|Yes| C[Ship it]"," B -->|No| D[Revise]",""].join(`
|
|
26
|
+
`),path:t}}function li(n){let e=L(n),t=we(e)?e:`${e}.puml`;return{content:["@startuml","Alice -> Bob: Hello","@enduml",""].join(`
|
|
27
|
+
`),path:t}}var Re=class{constructor({getFileList:e,navigation:t,refreshExplorer:i,toastController:s,vaultApiClient:r}){this.getFileList=e,this.navigation=t,this.refreshExplorer=i,this.toastController=s,this.vaultApiClient=r}handleWikiLinkClick(e){let t=Ht(e,this.getFileList());if(t){this.navigation.navigateToFile(t);return}let i=this.normalizeNewWikiFilePath(e);if(!i){this.toastController.show("Cannot create an empty wiki-link target");return}this.createAndOpenFile(i,e)}normalizeNewWikiFilePath(e){let t=L(e);return t?t.endsWith(".md")?t:`${t}.md`:null}async createAndOpenFile(e,t){try{await this.vaultApiClient.createFile({content:Me(t||e),path:e}),await this.refreshExplorer(),this.navigation.navigateToFile(e)}catch(i){this.toastController.show(`Failed to create file: ${i.message}`)}}};var Be=class{constructor({backlinksPanel:e,elements:t,excalidrawEmbed:i,getDisplayName:s,getSession:r,isExcalidrawFile:a,isImageFile:o,isMermaidFile:l,isPlantUmlFile:h,layoutController:c,outlineController:u,previewRenderer:p,schedulePreviewLayoutSync:d,scrollSyncController:w,videoEmbed:m}){this.backlinksPanel=e,this.elements=t,this.excalidrawEmbed=i,this.getDisplayName=s,this.getSession=r,this.isExcalidrawFile=a??(()=>!1),this.isImageFile=o??(()=>!1),this.isMermaidFile=l??(()=>!1),this.isPlantUmlFile=h??(()=>!1),this.layoutController=c,this.outlineController=u,this.previewRenderer=p,this.schedulePreviewLayoutSyncCallback=d,this.scrollSyncController=w,this.videoEmbed=m}createDiagramPreviewDocument(e,t=""){let i=String(t??""),s=Math.max(...i.match(/`+/g)?.map(a=>a.length)??[0]),r="`".repeat(Math.max(3,s+1));return`${r}${e}
|
|
28
28
|
${i}
|
|
29
|
-
${r}`}getPreviewSource(e){let t=this.getSession()?.getText()??"";return this.isMermaidFile(e)?this.createDiagramPreviewDocument("mermaid",t):this.isPlantUmlFile(e)?this.createDiagramPreviewDocument("plantuml",t):t}resetPreviewMode(){this.elements.previewContent?.classList.remove("is-excalidraw-file-preview"),this.elements.previewContent?.classList.remove("is-image-file-preview"),this.elements.previewContent?.classList.remove("is-mermaid-file-preview"),this.elements.previewContent?.classList.remove("is-plantuml-file-preview")}syncFileChrome(e){let t=this.isExcalidrawFile(e),i=this.isImageFile(e),s=Y(e),r=this.isMermaidFile(e),a=this.isPlantUmlFile(e),o=Mt(e);if(this.elements.markdownToolbar?.classList.toggle("hidden",!s),this.elements.outlineToggle?.classList.toggle("hidden",o||i),this.elements.previewContent?.classList.toggle("is-mermaid-file-preview",r),this.elements.previewContent?.classList.toggle("is-plantuml-file-preview",a),t||i){this.layoutController.setView("preview",{persist:!1}),this.outlineController.close(),this.backlinksPanel.clear();return}(r||a)&&(this.outlineController.close(),this.backlinksPanel.clear())}renderExcalidrawFilePreview(e){let t=this.elements.previewContent;if(!t)return;this.videoEmbed?.detachForCommit(),this.excalidrawEmbed.detachForCommit(),this.resetPreviewMode(),t.classList.add("is-excalidraw-file-preview");let i=this.previewRenderer.ensureRenderHost();this.previewRenderer.normalizePreviewChildren(i);let s=document.createElement("div");s.className="excalidraw-embed-placeholder",s.dataset.embedKey=`${e}#file-preview`,s.dataset.embedLabel=this.getDisplayName(e),s.dataset.embedTarget=e;let r=document.createElement("div");r.className="preview-shell",r.textContent="Loading Excalidraw preview\u2026",s.appendChild(r),i&&(i.replaceChildren(s),i.style.minHeight=""),t.dataset.renderPhase="ready",this.outlineController.refresh(),this.scrollSyncController.setLargeDocumentMode(!1),this.scrollSyncController.invalidatePreviewBlocks(),this.videoEmbed?.reconcileEmbeds(t),this.excalidrawEmbed.reconcileEmbeds(t,{isLargeDocument:!1}),this.excalidrawEmbed.hydrateVisibleEmbeds(),this.schedulePreviewLayoutSyncCallback({delayMs:0})}renderImageFilePreview(e){let t=this.elements.previewContent;if(!t)return;this.videoEmbed?.detachForCommit(),this.excalidrawEmbed.detachForCommit(),this.resetPreviewMode(),t.classList.add("is-image-file-preview");let i=this.previewRenderer.ensureRenderHost();this.previewRenderer.normalizePreviewChildren(i);let s=document.createElement("figure");s.className="image-file-preview-shell";let r=document.createElement("img");r.className="image-file-preview-image",r.alt=this.getDisplayName(e),r.src=b(`/attachment?path=${encodeURIComponent(e)}`),s.appendChild(r),i&&(i.replaceChildren(s),i.style.minHeight=""),t.dataset.renderPhase="ready",this.outlineController.refresh(),this.scrollSyncController.setLargeDocumentMode(!1),this.scrollSyncController.invalidatePreviewBlocks(),this.videoEmbed?.reconcileEmbeds(t),this.schedulePreviewLayoutSyncCallback({delayMs:0})}createResizeHandler(e){let t=null;return()=>{clearTimeout(t),t=setTimeout(()=>{e?.(),this.schedulePreviewLayoutSyncCallback({delayMs:0})},100)}}initializePreviewLayoutObserver(e=()=>{}){if(typeof ResizeObserver!="function"||!this.elements.previewContent)return null;let t=new ResizeObserver(()=>{e()});return t.observe(this.elements.previewContent),t}schedulePreviewLayoutSync({hydrationPaused:e,previewLayoutSyncTimer:t,setPendingPreviewLayoutSync:i,setPreviewLayoutSyncTimer:s,delayMs:r=120}){if(e){i(!0);return}clearTimeout(t);let a=setTimeout(()=>{s(null);let o=!!this.getSession(),l=this.elements.previewContent?.classList?.contains?.("is-excalidraw-file-preview")??!1;if(!(!o&&!l||!this.elements.previewContent)&&this.elements.previewContent.dataset.renderPhase!=="shell"){if(e){i(!0);return}this.previewRenderer.scheduleActiveMermaidRefit(),this.previewRenderer.scheduleActivePlantUmlRefit(),this.videoEmbed?.syncLayout(),this.excalidrawEmbed.syncLayout(),!(l&&!o)&&(this.scrollSyncController.invalidatePreviewBlocks(),this.scrollSyncController.warmPreviewBlocks({onReady:()=>{this.getSession()&&(this.scrollSyncController.realignAfterLayoutChange(),this.outlineController.scheduleActiveHeadingUpdate())}}))}},r);s(a)}handleEditorScrollActivityChange({isActive:e,pendingPreviewLayoutSync:t,previewLayoutSyncTimer:i,setHydrationPaused:s,setPendingPreviewLayoutSync:r,setPreviewLayoutSyncTimer:a}){let o=!!e;if(s(o),this.previewRenderer.setHydrationPaused(o),this.excalidrawEmbed.setHydrationPaused(o),o){clearTimeout(i),a(null),r(!0);return}t&&(r(!1),this.schedulePreviewLayoutSync({delayMs:0,hydrationPaused:!1,previewLayoutSyncTimer:null,setPendingPreviewLayoutSync:r,setPreviewLayoutSyncTimer:a}))}};var Ae=class{constructor({attachEditorScroller:e,createEditorSession:t,loadEditorSessionClass:i,scrollContainerForSession:s}){this.attachEditorScroller=e,this.createEditorSession=t,this.loadEditorSessionClass=i,this.scrollContainerForSession=s}async createSession(e){let t=await this.loadEditorSessionClass();return this.createEditorSession(t,e)}attachSessionScroller(e){this.attachEditorScroller(this.scrollContainerForSession(e))}clearSessionScroller(){this.attachEditorScroller(null)}};var Me=class{constructor({beginDocumentLoad:e,getDisplayName:t,loadBacklinks:i,onBeforeFileOpen:s,onFileOpenError:r,onFileOpenReady:a,onRenderExcalidrawPreview:o,onRenderImagePreview:l,onSyncWrapToggle:h,onUpdateActiveFile:c,onUpdateCurrentFile:u,onUpdateLobbyCurrentFile:f,onUpdateVisibleChrome:d,onViewModeReset:g,renderPresence:w,showEditorLoading:E,stateStore:C}){this.beginDocumentLoad=e,this.getDisplayName=t,this.loadBacklinks=i,this.onBeforeFileOpen=s,this.onFileOpenError=r,this.onFileOpenReady=a,this.onRenderExcalidrawPreview=o,this.onRenderImagePreview=l,this.onSyncWrapToggle=h,this.onUpdateActiveFile=c,this.onUpdateCurrentFile=u,this.onUpdateLobbyCurrentFile=f,this.onUpdateVisibleChrome=d,this.onViewModeReset=g,this.renderPresence=w,this.showEditorLoading=E,this.stateStore=C}prepareForFileOpen(e,{resetConnectionState:t=!0}={}){return this.onViewModeReset(),this.onBeforeFileOpen(),this.stateStore.set("connectionHelpShown",!1),t&&this.stateStore.set("connectionState",{status:"connecting",unreachable:!1}),this.stateStore.set("currentFilePath",e),this.onUpdateCurrentFile(e),this.onUpdateLobbyCurrentFile(e),this.onUpdateActiveFile(e),this.onUpdateVisibleChrome(e,{displayName:this.getDisplayName(e),isMarkdown:Y(e)}),this.showEditorLoading(),this.beginDocumentLoad(),this.renderPresence(),{supportsBacklinks:ye(e)}}markFileOpenReady(e){this.onFileOpenReady(e)}finalizeFileOpen({filePath:e,isExcalidraw:t=!1,isImage:i=!1,session:s=null,supportsBacklinks:r}){t&&this.onRenderExcalidrawPreview(e),i&&this.onRenderImagePreview(e),this.onSyncWrapToggle(),r&&s&&this.loadBacklinks(e)}handleFileOpenError(){this.onFileOpenError()}};var Re=class{constructor({attachEditorScroller:e,beginDocumentLoad:t,cleanupAfterSessionDestroy:i,createEditorSession:s,getDisplayName:r,getFileList:a,getLineWrappingEnabled:o,getLocalUser:l,getStoredUserName:h,getTheme:c,isExcalidrawFile:u,isImageFile:f,isMermaidFile:d,isPlantUmlFile:g,isTabActive:w,loadEditorSessionClass:E,loadBacklinks:C,onBeforeFileOpen:P,onConnectionChange:I,onContentChange:A,onCommentsChange:z,onFileAwarenessChange:U,onFileOpenError:R,onFileOpenReady:B,onImagePaste:N,onSelectionChange:$,onSessionAssigned:V=null,onRenderExcalidrawPreview:K,onRenderImagePreview:Z,onSyncWrapToggle:G,onUpdateActiveFile:H,onUpdateCurrentFile:M,onUpdateLobbyCurrentFile:D,onUpdateVisibleChrome:ee,onViewModeReset:O,renderPresence:_,scrollContainerForSession:m,showEditorLoading:y,stateStore:v}){this.attachEditorScroller=e,this.beginDocumentLoad=t,this.cleanupAfterSessionDestroy=i,this.createEditorSession=s,this.getDisplayName=r,this.getFileList=a,this.getLineWrappingEnabled=o,this.getLocalUser=l,this.getStoredUserName=h,this.getTheme=c,this.isExcalidrawFile=u??(()=>!1),this.isImageFile=f??(()=>!1),this.isMermaidFile=d??(()=>!1),this.isPlantUmlFile=g??(()=>!1),this.isTabActive=w,this.loadEditorSessionClassPort=E,this.loadBacklinks=C,this.onBeforeFileOpen=P,this.onConnectionChange=I,this.onContentChange=A,this.onCommentsChange=z,this.onFileAwarenessChange=U,this.onFileOpenError=R,this.onFileOpenReady=B,this.onImagePaste=N,this.onSelectionChange=$,this.onSessionAssigned=V,this.onRenderExcalidrawPreview=K,this.onSyncWrapToggle=G,this.onUpdateActiveFile=H,this.onUpdateCurrentFile=M,this.onUpdateLobbyCurrentFile=D,this.onUpdateVisibleChrome=ee,this.renderPresence=_,this.stateStore=v,this.session=null,this.lifecycle=new Ae({attachEditorScroller:e,createEditorSession:s,loadEditorSessionClass:()=>this.loadEditorSessionClassPort(),scrollContainerForSession:m}),this.chromeController=new Me({beginDocumentLoad:t,getDisplayName:r,loadBacklinks:C,onBeforeFileOpen:P,onFileOpenError:R,onFileOpenReady:B,onRenderExcalidrawPreview:K,onRenderImagePreview:Z,onSyncWrapToggle:G,onUpdateActiveFile:H,onUpdateCurrentFile:M,onUpdateLobbyCurrentFile:D,onUpdateVisibleChrome:ee,onViewModeReset:O,renderPresence:_,showEditorLoading:y,stateStore:v})}getSession(){return this.session}loadEditorSessionClass(){return this.loadEditorSessionClassPort()}waitForNextPaint(){return new Promise(e=>{requestAnimationFrame(()=>{requestAnimationFrame(e)})})}cleanupSession(){this.session?.destroy(),this.session=null,this.lifecycle.clearSessionScroller(),this.cleanupAfterSessionDestroy()}async openFile(e){if(!this.isTabActive())return;let t=this.isExcalidrawFile(e),i=this.isImageFile(e),s=this.isMermaidFile(e),r=this.isPlantUmlFile(e);if(e===this.stateStore.get("currentFilePath")&&(this.session||t||i)){this.onUpdateActiveFile(e),this.onUpdateLobbyCurrentFile(e);return}let a=this.stateStore.nextSessionLoadToken();this.cleanupSession();let o=this.chromeController.prepareForFileOpen(e,{resetConnectionState:!t&&!i});if(t||i){if(this.onSessionAssigned?.(null),a!==this.stateStore.get("sessionLoadToken"))return;this.chromeController.markFileOpenReady(null),this.chromeController.finalizeFileOpen({filePath:e,isExcalidraw:t,isImage:i,session:null,supportsBacklinks:o.supportsBacklinks});return}let l=await this.lifecycle.createSession({filePath:e,getFileList:this.getFileList,lineWrappingEnabled:this.getLineWrappingEnabled(),localUser:this.getLocalUser(),onAwarenessChange:h=>this.onFileAwarenessChange(h),onConnectionChange:h=>this.onConnectionChange(h),onCommentsChange:h=>this.onCommentsChange?.(h),onContentChange:()=>{t||this.onContentChange({isMermaid:s,isPlantUml:r})},onImagePaste:h=>this.onImagePaste?.(h),preferredUserName:this.getStoredUserName(),onSelectionChange:h=>this.onSelectionChange?.(h),theme:this.getTheme()});this.session=l,this.onSessionAssigned?.(l);try{if(await l.initialize(e),a!==this.stateStore.get("sessionLoadToken")){l.destroy();return}if(this.lifecycle.attachSessionScroller(l),l.applyTheme(this.getTheme()),await l.waitForInitialSync(),l.ensureInitialContent?.(),a!==this.stateStore.get("sessionLoadToken")){l.destroy();return}if(this.chromeController.markFileOpenReady(l),l.requestMeasure(),await this.waitForNextPaint(),a!==this.stateStore.get("sessionLoadToken")){l.destroy();return}this.chromeController.finalizeFileOpen({filePath:e,isExcalidraw:t,session:l,supportsBacklinks:o.supportsBacklinks})}catch(h){if(console.error("[app] Failed to initialize editor:",h),l.destroy(),this.lifecycle.clearSessionScroller(),this.session===l&&(this.session=null),a!==this.stateStore.get("sessionLoadToken"))return;this.chromeController.handleFileOpenError()}}};var Be=class{constructor(e={}){this.state={activeSidebarTab:"files",chatInitialSyncComplete:!1,chatIsOpen:!1,chatMessageIds:new Set,chatMessages:[],chatUnreadCount:0,connectionHelpShown:!1,connectionState:{status:"disconnected",unreachable:!1},currentFilePath:null,fileExplorerReady:!1,followedCursorSignature:"",followedUserClientId:null,gitRepoAvailable:!1,globalUsers:[],isTabActive:!1,sessionLoadToken:0,...e}}get(e){return this.state[e]}set(e,t){return this.state[e]=t,t}nextSessionLoadToken(){let e=Number(this.state.sessionLoadToken||0)+1;return this.state.sessionLoadToken=e,e}replaceChatState({initialSyncComplete:e,isOpen:t,messageIds:i,messages:s,unreadCount:r}){this.state.chatMessages=Array.isArray(s)?s:[],this.state.chatMessageIds=i instanceof Set?i:new Set,this.state.chatUnreadCount=Number.isFinite(r)?r:0,this.state.chatIsOpen=!!t,this.state.chatInitialSyncComplete=!!e}};function ei(n=document){return{currentUserName:n.getElementById("currentUserName"),chatContainer:n.getElementById("chatContainer"),chatEmptyState:n.getElementById("chatEmptyState"),chatForm:n.getElementById("chatForm"),chatInput:n.getElementById("chatInput"),chatMessages:n.getElementById("chatMessages"),chatNotificationButton:n.getElementById("chatNotificationBtn"),chatPanel:n.getElementById("chatPanel"),chatStatus:n.getElementById("chatStatus"),chatToastContainer:n.getElementById("chatToastContainer"),chatToggleBadge:n.getElementById("chatToggleBadge"),chatToggleButton:n.getElementById("chatToggleBtn"),gitCommitCancel:n.getElementById("gitCommitCancel"),gitCommitCopy:n.getElementById("gitCommitCopy"),gitCommitDialog:n.getElementById("gitCommitDialog"),gitCommitForm:n.getElementById("gitCommitForm"),gitCommitInput:n.getElementById("gitCommitInput"),gitCommitSubmit:n.getElementById("gitCommitSubmit"),gitCommitTitle:n.getElementById("gitCommitTitle"),gitResetCancel:n.getElementById("gitResetCancel"),gitResetCopy:n.getElementById("gitResetCopy"),gitResetDialog:n.getElementById("gitResetDialog"),gitResetFileName:n.getElementById("gitResetFileName"),gitResetSubmit:n.getElementById("gitResetSubmit"),gitResetTitle:n.getElementById("gitResetTitle"),displayNameCancel:n.getElementById("displayNameCancel"),displayNameCopy:n.getElementById("displayNameCopy"),displayNameDialog:n.getElementById("displayNameDialog"),displayNameForm:n.getElementById("displayNameForm"),displayNameInput:n.getElementById("displayNameInput"),displayNameSubmit:n.getElementById("displayNameSubmit"),displayNameTitle:n.getElementById("displayNameTitle"),editNameButton:n.getElementById("editNameBtn"),editorContainer:n.getElementById("editorContainer"),markdownToolbar:n.getElementById("markdownToolbar"),editorPage:n.getElementById("editor-page"),diffPage:n.getElementById("diff-page"),fileSearch:n.getElementById("fileSearch"),filesSidebarTab:n.getElementById("filesSidebarTab"),gitSearch:n.getElementById("gitSearch"),gitSearchInput:n.getElementById("gitSearchInput"),gitSidebarTab:n.getElementById("gitSidebarTab"),gitOperationStatus:n.getElementById("gitOperationStatus"),lineInfo:n.getElementById("lineInfo"),mobileViewToggle:n.getElementById("mobileViewToggle"),previewContent:n.getElementById("previewContent"),previewContainer:n.getElementById("previewContainer"),shareButton:n.getElementById("shareBtn"),toastContainer:n.getElementById("toastContainer"),toggleWrapButton:n.getElementById("toggleWrapBtn"),userAvatars:n.getElementById("userAvatars"),userCount:n.getElementById("userCount"),wrapToggleLabel:n.getElementById("wrapToggleLabel"),activeFileName:n.getElementById("activeFileName"),sidebarToggle:n.getElementById("sidebarToggle"),sidebarClose:n.getElementById("sidebarClose"),sidebar:n.getElementById("sidebar"),emptyState:n.getElementById("emptyState"),emptyStateNewFileBtn:n.getElementById("emptyStateNewFileBtn"),emptyStateSearchBtn:n.getElementById("emptyStateSearchBtn"),backlinksPanel:n.getElementById("backlinksPanel"),commentSelectionButton:n.getElementById("commentSelectionBtn"),commentsDrawer:n.getElementById("commentsDrawer"),commentsDrawerEmpty:n.getElementById("commentsDrawerEmpty"),commentsDrawerList:n.getElementById("commentsDrawerList"),commentsToggleButton:n.getElementById("commentsToggle"),outlineToggle:n.getElementById("outlineToggle"),tabLockCopy:n.getElementById("tabLockCopy"),tabLockOverlay:n.getElementById("tabLockOverlay"),tabLockTakeoverButton:n.getElementById("tabLockTakeoverBtn"),tabLockTitle:n.getElementById("tabLockTitle"),toolbarCenter:n.getElementById("toolbarCenter"),toolbarDiffBadge:n.getElementById("toolbarDiffBadge"),sidebarTabs:n.getElementById("sidebarTabs")}}var ti={updateChatMessages(n,{initial:e=!1}={}){let t=new Set(this.chatMessageIds),i=this.lobby.getLocalUser()?.peerId??null;if(this.chatMessages=n,this.chatMessageIds=new Set(n.map(r=>r.id)),!this.chatInitialSyncComplete){e&&(this.chatInitialSyncComplete=!0),this.renderChat();return}let s=n.filter(r=>!t.has(r.id)&&r.peerId&&r.peerId!==i);this.chatIsOpen?this.chatUnreadCount=0:s.length>0&&(this.chatUnreadCount+=s.length);for(let r of s)this.maybeNotifyChatMessage(r);this.renderChat()},toggleChatPanel(){if(this.chatIsOpen){this.closeChatPanel();return}this.openChatPanel()},openChatPanel(){this.chatIsOpen=!0,this.chatUnreadCount=0,this.renderChat(),requestAnimationFrame(()=>{this.elements.chatInput?.focus(),this.scrollChatToBottom()})},closeChatPanel(){this.chatIsOpen&&(this.chatIsOpen=!1,this.renderChat())},handleChatSubmit(){if(!this.isTabActive)return;let n=this.elements.chatInput;if(!n)return;if(!this.lobby.sendChatMessage(n.value)){n.focus();return}if(n.value="",!this.chatIsOpen){this.openChatPanel();return}this.renderChat()},renderChat(){this.elements.chatContainer?.classList.toggle("is-open",this.chatIsOpen),this.elements.chatPanel?.classList.toggle("hidden",!this.chatIsOpen),this.syncChatToggleButton(),this.syncChatNotificationButton();let n=this.elements.chatMessages,e=this.elements.chatEmptyState;if(this.elements.chatStatus&&(this.elements.chatStatus.textContent=this.chatInitialSyncComplete?`${this.globalUsers.length} online`:"Syncing..."),!n)return;if(n.replaceChildren(),this.chatMessages.length===0){e?.classList.remove("hidden"),n.classList.add("hidden");return}e?.classList.add("hidden"),n.classList.remove("hidden");let t=document.createDocumentFragment();this.chatMessages.forEach(i=>{t.appendChild(this.createChatMessageElement(i))}),n.appendChild(t),this.chatIsOpen&&this.scrollChatToBottom()},createChatMessageElement(n){let e=document.createElement("article"),t=n.peerId===this.lobby.getLocalUser()?.peerId;e.className="chat-message",e.classList.toggle("is-local",t);let i=document.createElement("div");i.className="chat-message-avatar",i.style.backgroundColor=n.userColor||"var(--color-primary)",i.textContent=(n.userName||"?").charAt(0).toUpperCase(),i.setAttribute("aria-hidden","true");let s=document.createElement("div");s.className="chat-message-body";let r=document.createElement("div");r.className="chat-message-meta";let a=document.createElement("span");a.className="chat-message-author",a.textContent=t?`${n.userName} (you)`:n.userName;let o=document.createElement("span");o.className="chat-message-time",o.textContent=this.formatChatTimestamp(n.createdAt),r.append(a,o);let l=this.getChatMessageFileLabel(n.filePath);if(l){let c=document.createElement("span");c.className="chat-message-file",c.textContent=l,r.append(c)}let h=document.createElement("p");return h.className="chat-message-text",h.textContent=n.text,s.append(r,h),e.append(i,s),e},scrollChatToBottom(){let n=this.elements.chatMessages;n&&requestAnimationFrame(()=>{n.scrollTop=n.scrollHeight})},formatChatTimestamp(n){if(!Number.isFinite(n))return"";try{return this.chatTimeFormatter.format(new Date(n))}catch{return""}},getChatMessageFileLabel(n){return n?this.getDisplayName(n):""},formatChatToastMessage(n){let e=n?.userName||"Someone",t=String(n?.text??"").replace(/\s+/g," ").trim(),i=t.length>88?`${t.slice(0,85).trimEnd()}...`:t;return`${e}: ${i}`},syncChatToggleButton(){let n=this.elements.chatToggleButton,e=this.elements.chatToggleBadge;if(!n)return;let t=this.chatUnreadCount>0,i=t&&!this.chatIsOpen;n.classList.toggle("is-active",this.chatIsOpen),n.classList.toggle("is-unread",i),n.setAttribute("aria-expanded",String(this.chatIsOpen)),n.setAttribute("aria-label",t?`Open team chat, ${this.chatUnreadCount} unread`:"Open team chat"),n.title=this.chatUnreadCount>0?`Team chat (${this.chatUnreadCount} unread)`:"Team chat",e&&(e.classList.toggle("hidden",!t),e.textContent=this.chatUnreadCount>9?"9+":String(this.chatUnreadCount))},syncChatNotificationButton(){let n=this.elements.chatNotificationButton;if(!n)return;let e=this.notifications.getPermission();this.chatNotificationPermission=e;let t="Enable alerts",i="Enable browser notifications for new chat messages",s=!1;e==="unsupported"?(t="No alerts",i="Browser notifications are unavailable here"):e==="denied"?(t="Alerts blocked",i="Browser notifications are blocked for this site"):e==="granted"&&(s=this.chatNotificationsEnabled,t=s?"Alerts on":"Alerts off",i=s?"Disable browser notifications for chat":"Enable browser notifications for chat"),n.textContent=t,n.title=i,n.setAttribute("aria-pressed",String(s)),n.classList.toggle("is-enabled",s),n.classList.toggle("is-blocked",e==="denied")},async handleChatNotificationToggle(){let n=this.notifications.getPermission();if(this.chatNotificationPermission=n,n==="unsupported"){this.toastController.show("Browser notifications are unavailable here"),this.syncChatNotificationButton();return}if(n==="denied"){this.chatNotificationsEnabled=!1,this.preferences.setChatNotificationsEnabled(!1),this.toastController.show("Browser notifications are blocked for this site"),this.syncChatNotificationButton();return}if(n==="default"){let e=await this.notifications.requestPermission();if(this.chatNotificationPermission=e,e!=="granted"){this.chatNotificationsEnabled=!1,this.preferences.setChatNotificationsEnabled(!1),e==="denied"&&this.toastController.show("Browser notifications were blocked"),this.syncChatNotificationButton();return}this.chatNotificationsEnabled=!0,this.preferences.setChatNotificationsEnabled(!0),this.syncChatNotificationButton();return}this.chatNotificationsEnabled=!this.chatNotificationsEnabled,this.preferences.setChatNotificationsEnabled(this.chatNotificationsEnabled),this.syncChatNotificationButton()},maybeNotifyChatMessage(n){if(this.chatInitialSyncComplete){if(document.hidden){this.maybeShowBrowserChatNotification(n);return}!this.isTabActive||this.chatIsOpen||(this.chatToastController??this.toastController).show(this.formatChatToastMessage(n),4e3)}},maybeShowBrowserChatNotification(n){if(!this.chatNotificationsEnabled||this.notifications.getPermission()!=="granted")return;let e=`CollabMD chat \u2022 ${n.userName}`,t=this.getChatMessageFileLabel(n.filePath),i=t?`${t}: ${n.text}`:n.text,s=this.notifications.createNotification({body:i,onClick:()=>{n.filePath&&this.navigation.navigateToFile(n.filePath)},tag:`collabmd-chat-${n.id}`,title:e});s&&setTimeout(()=>{s.close?.()},6e3)}};var ii={getCommentFileKind(n=this.currentFilePath){return Pt(n)||"markdown"},syncCommentChrome(n=this.currentFilePath){let e=Rt(n)&&!this.isExcalidrawFile(n);this.commentUi.setCurrentFile(n,{fileKind:this.getCommentFileKind(n),supported:e}),this.handleCommentThreadsChange(this.session?.getCommentThreads?.()??[]),this.handleCommentSelectionChange(this.session?.getCurrentSelectionCommentAnchor?.()??null)},handleCommentSelectionChange(n){this.commentUi.setSelectionAnchor(n)},handleCommentThreadsChange(n=[]){this.commentUi.setThreads(n)},handleCommentEditorContentChange(){this.commentUi.handleEditorContentChange()},refreshCommentUiLayout(){this.commentUi.refreshLayout()}};function ni(n={}){return{changedPaths:Array.isArray(n.changedPaths)?n.changedPaths.filter(Boolean):[],deletedPaths:Array.isArray(n.deletedPaths)?n.deletedPaths.filter(Boolean):[],refreshExplorer:n.refreshExplorer!==!1,renamedPaths:Array.isArray(n.renamedPaths)?n.renamedPaths.filter(e=>e?.oldPath&&e?.newPath):[]}}var si={setGitOperationStatus(n=""){let e=this.elements.gitOperationStatus;if(!e)return;let t=String(n??"").trim();e.textContent=t,e.classList.toggle("hidden",!t)},async runGitActionWithStatus(n,e){this.setGitOperationStatus(n);try{return await e()}finally{this.setGitOperationStatus("")}},handleGitDiffSelection(n,{closeSidebarOnMobile:e=!1,scope:t="working-tree"}={}){e&&this.closeSidebarOnMobile(),this.navigation.navigateToGitDiff({filePath:n,scope:t})},handleGitRepoChange(n,e=null){this.gitRepoAvailable=!!n,this.elements.sidebarTabs?.classList.toggle("hidden",!this.gitRepoAvailable),this.elements.gitSidebarTab?.classList.toggle("hidden",!this.gitRepoAvailable);let t=n&&e?.summary?.changedFiles>0;if(this.elements.gitSidebarTab?.classList.toggle("has-changes",t),this.gitDiffView.setRepoStatus(this.gitRepoAvailable?e:null),!this.gitRepoAvailable&&this.activeSidebarTab==="git"){this.setSidebarTab("files");return}this.gitRepoAvailable&&this.navigation.getHashRoute().type==="git-diff"&&this.activeSidebarTab!=="git"&&this.setSidebarTab("git")},syncMainChrome({mode:n,title:e=null}={}){let t=n==="diff";this.elements.toolbarCenter?.classList.toggle("hidden",t),this.elements.mobileViewToggle?.classList.toggle("hidden",t),this.elements.userCount?.classList.toggle("hidden",t),this.elements.toolbarDiffBadge?.classList.toggle("hidden",!t),e&&this.elements.activeFileName&&(this.elements.activeFileName.textContent=e)},async showGitDiff({filePath:n=null,scope:e="all"}={}){this.gitPanel.setSelection(n?{path:n,scope:e}:{}),this.showDiffState(),this.syncMainChrome({mode:"diff",title:this.gitDiffView.getToolbarTitle({filePath:n,scope:e})}),await this.gitDiffView.open({filePath:n,scope:e})},async postGitAction(n,e){let t=await fetch(n,{body:JSON.stringify(e),headers:{"Content-Type":"application/json"},method:"POST"}),i=await t.json();if(!t.ok)throw new Error(i.error||"Git action failed");return i},async refreshWorkspaceAfterGitAction({filePath:n=null,preferredScope:e=null}={}){await this.fileExplorer.refresh(),await this.refreshGitAfterAction({filePath:n,preferredScope:e})},async refreshGitAfterAction({filePath:n=null,preferredScope:e=null}={}){await this.gitPanel.refresh({force:!0});let t=this.navigation.getHashRoute();if(t.type!=="git-diff")return;let i=n??t.filePath,s=e??t.scope;if(s!==t.scope||i!==t.filePath){this.navigation.navigateToGitDiff({filePath:i,scope:s});return}await this.showGitDiff({filePath:t.filePath,scope:t.scope})},async finalizeGitAction({action:n,filePath:e=null,preferredScope:t=null,result:i={},showLocalFileToast:s=!1}={}){let r=ni(i.workspaceChange);return await this.refreshWorkspaceAfterGitAction({filePath:e,preferredScope:t}),this.handleWorkspaceChangeForCurrentFile(r,{action:n,local:!0,showToast:s}),this.lobby.sendWorkspaceEvent({action:n,sourceRef:i.sourceRef??null,workspaceChange:r}),r},handleWorkspaceChangeForCurrentFile(n,{action:e="git",local:t=!1,showToast:i=!0}={}){let s=this.currentFilePath;if(!s)return!1;let r=n.deletedPaths.includes(s),a=n.renamedPaths.find(l=>l.oldPath===s);if(!r&&!a)return!1;if(this.navigation.navigateToFile(null),!i)return!0;let o=this.getDisplayName(s);return a?(this.toastController.show(t?`${o} was reset away from this branch path`:`${o} moved after a ${e} operation`),!0):(this.toastController.show(t?`${o} was removed by ${e}`:`${o} was removed after a ${e} operation`),!0)},async handleIncomingWorkspaceEvent(n){if(!this.isTabActive||!n)return;let e=ni(n.workspaceChange);await this.refreshWorkspaceAfterGitAction(),this.handleWorkspaceChangeForCurrentFile(e,{action:n.action||"git",local:!1,showToast:!0})},async stageGitFile(n,{scope:e="working-tree"}={}){n&&await this.runGitActionWithStatus("Staging changes...",async()=>{let t=await this.postGitAction(b("/git/stage"),{path:n});await this.finalizeGitAction({action:"stage",filePath:n,preferredScope:e==="all"?"all":"staged",result:t})})},async unstageGitFile(n,{scope:e="staged"}={}){n&&await this.runGitActionWithStatus("Unstaging changes...",async()=>{let t=await this.postGitAction(b("/git/unstage"),{path:n});await this.finalizeGitAction({action:"unstage",filePath:n,preferredScope:e==="all"?"all":"working-tree",result:t})})},async pushGitBranch(){await this.runGitActionWithStatus("Pushing branch...",async()=>{try{let n=await this.postGitAction(b("/git/push"),{});await this.finalizeGitAction({action:"push",result:n})}catch(n){this.toastController.show(n.message||"Failed to push branch")}})},async pullGitBranch(){await this.runGitActionWithStatus("Pulling branch...",async()=>{try{let n=await this.postGitAction(b("/git/pull"),{});await this.finalizeGitAction({action:"pull",result:n,showLocalFileToast:!0})}catch(n){this.toastController.show(n.message||"Failed to pull branch")}})},openGitResetDialog(n){if(!this.isTabActive||!n)return;let e=this.elements.gitResetDialog;!e||!this.elements.gitResetFileName||(this.pendingGitResetPath=n,this.elements.gitResetTitle&&(this.elements.gitResetTitle.textContent="Reset file to current branch"),this.elements.gitResetCopy&&(this.elements.gitResetCopy.textContent="Restore this file from the current checked-out branch. If this branch does not contain the file, the file will be deleted locally."),this.elements.gitResetFileName.value=n,this.elements.gitResetSubmit&&(this.elements.gitResetSubmit.textContent="Reset File"),this.elements.gitResetSubmit?.toggleAttribute("disabled",!1),!e.open&&(typeof e.showModal=="function"?e.showModal():e.setAttribute("open","true")))},async handleGitResetSubmit(){let n=this.pendingGitResetPath,e=this.elements.gitResetDialog,t=this.elements.gitResetSubmit;if(!(!n||!e)){t?.toggleAttribute("disabled",!0),t&&(t.textContent="Resetting...");try{await this.runGitActionWithStatus("Resetting file...",async()=>{let i=await this.postGitAction(b("/git/reset-file"),{path:n});await this.finalizeGitAction({action:"reset",filePath:n,result:i,showLocalFileToast:!0})}),e.close()}catch(i){this.toastController.show(i.message||"Failed to reset file")}finally{t&&(t.textContent="Reset File"),t?.toggleAttribute("disabled",!1)}}},openGitCommitDialog(){if(!this.isTabActive)return;let n=this.elements.gitCommitDialog,e=this.elements.gitCommitInput;if(!(!n||!e)){if(this.elements.gitCommitTitle&&(this.elements.gitCommitTitle.textContent="Commit staged changes"),this.elements.gitCommitCopy){let t=Number(this.gitPanel.status?.summary?.staged||0);this.elements.gitCommitCopy.textContent=t>0?`${t} staged file${t===1?"":"s"} will be included.`:"All staged changes will be included."}this.elements.gitCommitSubmit&&(this.elements.gitCommitSubmit.textContent="Commit staged changes"),e.value="",!n.open&&(typeof n.showModal=="function"?n.showModal():n.setAttribute("open","true"),requestAnimationFrame(()=>{e.focus(),e.select()}))}},async handleGitCommitSubmit(){let n=this.elements.gitCommitDialog,e=this.elements.gitCommitInput,t=this.elements.gitCommitSubmit,i=String(e?.value??"").trim();if(!(!n||!e)){if(!i){e.focus(),this.toastController.show("Commit message cannot be empty");return}t?.toggleAttribute("disabled",!0),t&&(t.textContent="Committing...");try{await this.runGitActionWithStatus("Committing changes...",async()=>{let s=await this.postGitAction(b("/git/commit"),{message:i});await this.finalizeGitAction({action:"commit",result:s})}),n.close()}catch(s){this.toastController.show(s.message||"Failed to commit staged changes")}finally{t&&(t.textContent="Commit staged changes"),t?.toggleAttribute("disabled",!1)}}}};var ri={updateGlobalUsers(n){this.globalUsers=n,this.syncFollowedUser(),this.renderAvatars(),this.renderChat(),this.renderPresence(),this.syncCurrentUserName()},updateFileAwareness(n){this.syncFollowedUser()},renderPresence(){let n=this.elements.userCount;if(!n)return;let e=!!this.session,t=!!(this.currentFilePath&&this.isExcalidrawFile?.(this.currentFilePath)),i=!!(this.currentFilePath&&this.isImageFile?.(this.currentFilePath)),r=!e&&(!this.currentFilePath||t||i)?this.lobby?.getConnectionState?.()??this.connectionState:this.connectionState;if(r.status==="connected"){n.textContent=`${this.globalUsers.length} online`,n.style.opacity="1";return}if(r.status==="connecting"){n.textContent=r.unreachable?"Unreachable":"Connecting...",n.style.opacity="0.6";return}n.textContent="Offline",n.style.opacity="0.6"},renderAvatars(){let n=this.elements.userAvatars;if(!n)return;n.innerHTML="";let e=[...this.globalUsers],t=e.findIndex(r=>r.isLocal);if(t>0){let[r]=e.splice(t,1);e.unshift(r)}let i=e.findIndex(r=>!r.isLocal&&r.clientId===this.followedUserClientId),s=e[0]?.isLocal?1:0;if(i>s){let[r]=e.splice(i,1);e.splice(s,0,r)}if(e.slice(0,5).forEach(r=>{let a=document.createElement(r.isLocal?"div":"button");a.className="user-avatar",a.classList.toggle("is-local",r.isLocal),a.style.backgroundColor=r.color,a.classList.toggle("is-following",r.clientId===this.followedUserClientId);let o=document.createElement("span");o.className="user-avatar-initial",o.textContent=r.name.charAt(0).toUpperCase(),a.appendChild(o);let l=r.currentFile&&r.currentFile===this.currentFilePath,h=r.currentFile?this.getDisplayName(r.currentFile):"No file";if(r.isLocal){let c=document.createElement("span");c.className="user-avatar-self-label",c.textContent="You",a.appendChild(c),a.title=`${r.name} (you) \u2014 ${h}`,a.setAttribute("role","img"),a.setAttribute("aria-label",`${r.name} (you) \u2014 ${h}`)}else{a.type="button",a.classList.add("user-avatar-button"),l||a.classList.add("different-file");let c=r.clientId===this.followedUserClientId?`Stop following ${r.name}`:l?`Follow ${r.name}`:`Follow ${r.name} \u2014 ${h}`;a.title=c,a.setAttribute("aria-label",c),a.addEventListener("click",()=>this.toggleFollowUser(r.clientId))}n.appendChild(a)}),e.length>5){let r=document.createElement("div");r.className="user-avatar",r.style.backgroundColor="var(--color-surface-dynamic)",r.style.color="var(--color-text-muted)";let a=document.createElement("span");a.className="user-avatar-initial",a.textContent=`+${e.length-5}`,r.appendChild(a),n.appendChild(r)}},toggleFollowUser(n){if(!n)return;if(this.followedUserClientId===n){this.stopFollowingUser();return}let e=this.globalUsers.find(t=>t.clientId===n&&!t.isLocal);if(e){if(this.followedUserClientId=n,this.followedCursorSignature="",this.renderAvatars(),e.currentFile&&e.currentFile!==this.currentFilePath){this.navigation.navigateToFile(e.currentFile);return}requestAnimationFrame(()=>{this.followedUserClientId===n&&this.followUserCursor(e,{force:!0})})}},stopFollowingUser(){this.followedUserClientId&&(this.currentFilePath&&this.isExcalidrawFile?.(this.currentFilePath)&&this.excalidrawEmbed?.setFollowedUser(this.currentFilePath,null),this.followedUserClientId=null,this.followedCursorSignature="",this.renderAvatars())},syncFollowedUser(){if(!this.followedUserClientId)return;let n=this.globalUsers.find(e=>e.clientId===this.followedUserClientId);if(!n||n.isLocal){this.stopFollowingUser();return}if(n.currentFile&&n.currentFile!==this.currentFilePath){this.navigation.navigateToFile(n.currentFile);return}this.followUserCursor(n)},followUserCursor(n,{force:e=!1}={}){if(this.currentFilePath&&this.isExcalidrawFile?.(this.currentFilePath)){this.followExcalidrawUser(n,{force:e});return}let t=this.resolveFileClientId(n.peerId),i=t!=null?this.session?.getUserViewport(t):null,s=t!=null?this.session?.getUserCursor(t):null,r=s?.cursorHead??null,a=s?.cursorLine??null,o=s?.cursorAnchor??null,l=i?.topLine??null,h=i?.viewportRatio??.35;if(!n||l==null&&(r==null||a==null)){this.followedCursorSignature="";return}let c=`${n.clientId}:${l??"no-viewport"}:${o??"no-anchor"}:${r??"no-head"}`;if(!e&&c===this.followedCursorSignature)return;(t!=null&&this.session?.scrollToUserViewport(t)||t!=null&&this.session?.scrollToUserCursor(t,"center")||r!=null&&this.session?.scrollToPosition(r,"center")||a!=null&&this.session?.scrollToLine(a,h))&&(this.followedCursorSignature=c)},followExcalidrawUser(n,{force:e=!1}={}){if(!n?.peerId||!this.currentFilePath){this.followedCursorSignature="";return}let t=`excalidraw:${this.currentFilePath}:${n.peerId}`;!e&&t===this.followedCursorSignature||Promise.resolve(this.excalidrawEmbed?.setFollowedUser(this.currentFilePath,n.peerId)).then(i=>{i===!1||this.followedUserClientId!==n.clientId||(this.followedCursorSignature=t)}).catch(()=>{})},resolveFileClientId(n){if(!n||!this.session?.awareness)return null;for(let[e,t]of this.session.awareness.getStates())if(t.user?.peerId===n)return e;return null}};var Wi="image/png,image/jpeg,image/webp,image/gif,image/svg+xml",ai={initialize(){this.themeController.initialize(),this.previewRenderer.applyTheme(this.themeController.getTheme()),this.previewRenderer.scheduleWorkerPrewarm(),this.scheduleEditorSessionPrewarm?.(),this.outlineController.initialize(),this.layoutController.initialize(),this.scrollSyncController.initialize(),this.fileExplorer.initialize(),this.gitPanel.initialize(),this.gitDiffView.initialize(),this.initializePreviewLayoutObserver(),this.syncCurrentUserName(),this.syncWrapToggle(),this.syncChatNotificationButton(),this.renderChat(),this.gitPanel.refresh({force:!0}),this.elements.chatInput?.setAttribute("maxlength",String(this.lobbyChatMessageMaxLength)),this.bindEvents(),this.restoreSidebarState(),this.tabActivityLock.initialize(),this.tabActivityLock.tryActivate(),window.addEventListener("hashchange",()=>this.handleHashChange()),window.addEventListener("resize",this.createResizeHandler()),this.fileExplorerReadyPromise=this.fileExplorer.refresh().then(()=>{if(this.fileExplorerReady=!0,this.isTabActive)return this.handleHashChange()})},bindEvents(){this.elements.emptyStateNewFileBtn?.addEventListener("click",()=>{this.fileExplorer.actionController.handleNewFile()}),this.elements.emptyStateSearchBtn?.addEventListener("click",()=>{this.toggleQuickSwitcher()}),this.elements.chatToggleButton?.addEventListener("click",()=>{this.toggleChatPanel()}),this.elements.chatForm?.addEventListener("submit",n=>{n.preventDefault(),this.handleChatSubmit()}),this.elements.chatNotificationButton?.addEventListener("click",()=>{this.handleChatNotificationToggle()}),this.elements.shareButton?.addEventListener("click",()=>{this.copyCurrentLink()}),this.elements.editNameButton?.addEventListener("click",()=>{this.openDisplayNameDialog()}),this.elements.displayNameCancel?.addEventListener("click",()=>{this.elements.displayNameDialog?.close()}),this.elements.gitCommitCancel?.addEventListener("click",()=>{this.elements.gitCommitDialog?.close()}),this.elements.gitResetCancel?.addEventListener("click",()=>{this.elements.gitResetDialog?.close()}),this.elements.gitResetSubmit?.addEventListener("click",()=>{this.handleGitResetSubmit()}),this.elements.gitCommitDialog?.addEventListener("close",()=>{this.elements.gitCommitInput&&(this.elements.gitCommitInput.value=""),this.elements.gitCommitSubmit&&(this.elements.gitCommitSubmit.textContent="Commit staged changes")}),this.elements.gitResetDialog?.addEventListener("close",()=>{this.pendingGitResetPath=null,this.elements.gitResetFileName&&(this.elements.gitResetFileName.value=""),this.elements.gitResetSubmit&&(this.elements.gitResetSubmit.textContent="Reset File")}),this.elements.markdownToolbar?.addEventListener("click",n=>{let t=(n.target instanceof Element?n.target.closest("[data-markdown-action]"):null)?.getAttribute("data-markdown-action");t&&this.applyMarkdownToolbarAction(t)}),this.elements.displayNameForm?.addEventListener("submit",n=>{n.preventDefault(),this.handleDisplayNameSubmit()}),this.elements.gitCommitForm?.addEventListener("submit",n=>{n.preventDefault(),this.handleGitCommitSubmit()}),this.elements.tabLockTakeoverButton?.addEventListener("click",()=>{this.handleTabTakeover()}),this.elements.toggleWrapButton?.addEventListener("click",()=>{this.toggleLineWrapping()}),this.elements.previewContent?.addEventListener("click",n=>{let e=n.target.closest("a.wiki-link[data-wiki-target]");e&&(n.preventDefault(),this.handleWikiLinkClick(e.dataset.wikiTarget))}),this.elements.sidebarToggle?.addEventListener("click",()=>{this.toggleSidebar()}),this.elements.sidebarClose?.addEventListener("click",()=>{this.closeSidebarOnMobile()}),this.elements.filesSidebarTab?.addEventListener("click",()=>{this.setSidebarTab("files")}),this.elements.gitSidebarTab?.addEventListener("click",()=>{this.gitRepoAvailable&&this.setSidebarTab("git")}),document.addEventListener("pointerdown",n=>{this.chatIsOpen&&(this.elements.chatContainer?.contains(n.target)||this.closeChatPanel())}),document.addEventListener("keydown",n=>{if(n.key==="Escape"&&this.chatIsOpen){this.closeChatPanel();return}(n.metaKey||n.ctrlKey)&&n.key==="k"&&(n.preventDefault(),this.toggleQuickSwitcher())})},isMobileViewport(){return this.mobileBreakpointQuery.matches},closeSidebarOnMobile(){let n=this.elements.sidebar;!n||!this.isMobileViewport()||n.classList.contains("collapsed")||this.setSidebarVisibility(!1)},toggleSidebar(){let n=this.elements.sidebar;if(!n)return;let e=n.classList.contains("collapsed");this.setSidebarVisibility(e)},restoreSidebarState(){if(!this.elements.sidebar)return;let e=this.isMobileViewport(),t=this.preferences.getSidebarVisible(),i=!0;t==="true"?i=!0:(t==="false"||e)&&(i=!1),this.applySidebarVisibility(i)},setSidebarVisibility(n){this.applySidebarVisibility(n),this.preferences.setSidebarVisible(n)},applySidebarVisibility(n){let e=this.elements.sidebar;if(!e)return;let t=!n,i=t&&this.isMobileViewport();e.classList.toggle("collapsed",t),e.toggleAttribute("hidden",i),e.setAttribute("aria-hidden",i?"true":"false"),e.inert=t},setSidebarTab(n){let e=n==="git"&&this.gitRepoAvailable?"git":"files";this.activeSidebarTab=e,this.elements.filesSidebarTab?.classList.toggle("active",e==="files"),this.elements.gitSidebarTab?.classList.toggle("active",e==="git"),document.getElementById("fileTree")?.classList.toggle("hidden",e!=="files"),this.elements.fileSearch?.classList.toggle("hidden",e!=="files"),this.elements.gitSearch?.classList.toggle("hidden",e!=="git"),document.getElementById("gitPanel")?.classList.toggle("active",e==="git"),document.getElementById("gitPanel")?.classList.toggle("hidden",e!=="git"),this.gitPanel.setActive(e==="git")},applyMarkdownToolbarAction(n){if(!this.session||!Y(this.currentFilePath))return;if(n==="image"){this.handleToolbarImageInsert();return}this.session.applyMarkdownToolbarAction(n)||this.toastController.show("Formatting action is unavailable")},async handleToolbarImageInsert(){let n=await this.pickImageFile();n&&await this.handleEditorImageInsert(n)},pickImageFile(){return new Promise(n=>{let e=document.createElement("input");e.type="file",e.accept=Wi,e.style.position="fixed",e.style.left="-9999px",document.body.appendChild(e);let t=!1,i=null,s=a=>{t||(t=!0,i&&window.clearTimeout(i),window.removeEventListener("focus",r),e.remove(),n(a))},r=()=>{i=window.setTimeout(()=>{t||e.files?.length||s(null)},250)};e.addEventListener("change",()=>{s(e.files?.[0]??null)},{once:!0}),e.addEventListener("cancel",()=>{s(null)},{once:!0}),window.addEventListener("focus",r,{once:!0}),e.click()})},async handleEditorImageInsert(n){if(!this.session||!Y(this.currentFilePath))return console.warn("[ui] Ignoring image insert because there is no active markdown session.",{currentFilePath:this.currentFilePath,hasSession:!!this.session}),!1;let e=this.currentFilePath,t=this.session;try{console.debug("[ui] Uploading image attachment.",{fileName:n?.name||"",size:n?.size??null,sourcePath:e,type:n?.type||""});let i=await this.vaultApiClient.uploadImageAttachment({file:n,fileName:n?.name||"",sourcePath:e});return await this.fileExplorer.refresh(),this.currentFilePath===e&&this.session&&this.session===t&&typeof i?.markdown=="string"&&(console.debug("[ui] Inserting uploaded image markdown into the editor.",{sourcePath:e,storedPath:i.path??""}),this.session.insertText(i.markdown)),!0}catch(i){return console.error("[ui] Failed to insert image attachment:",i),this.toastController.show(i.message||"Failed to upload image"),!1}},handleThemeChange(n){this.previewRenderer.applyTheme(n),!this.isExcalidrawFile(this.currentFilePath)&&!this.isImageFile?.(this.currentFilePath)&&this.previewRenderer.queueRender(),this.session?.applyTheme(n),this.excalidrawEmbed.updateTheme(n)},handleConnectionChange(n){this.connectionState=n,this.renderPresence(),n.unreachable&&!this.connectionHelpShown&&(this.connectionHelpShown=!0,this.toastController.show(`Cannot reach server at ${n.wsBaseUrl}`,6e3))},openDisplayNameDialog({mode:n="edit"}={}){if(!this.isTabActive)return;let e=this.elements.displayNameDialog,t=this.elements.displayNameInput,i=this.elements.displayNameTitle,s=this.elements.displayNameCopy,r=this.elements.displayNameCancel,a=this.elements.displayNameSubmit;if(!e||!t)return;let o=n==="onboarding";i&&(i.textContent=o?"Choose your display name":"Update display name"),s&&(s.textContent=o?"Pick a name collaborators will see. You can skip for now and continue as a guest.":"Your name will be visible to everyone editing this vault."),r&&(r.textContent=o?"Skip for now":"Cancel"),a&&(a.textContent=o?"Continue":"Save name"),t.value=o?"":this.getCurrentUserName(),!e.open&&(typeof e.showModal=="function"?e.showModal():e.setAttribute("open","true"),requestAnimationFrame(()=>{t.focus(),t.select()}))},promptForDisplayNameIfNeeded(){!this.isTabActive||this._hasPromptedForDisplayName||this.getStoredUserName()||(this._hasPromptedForDisplayName=!0,requestAnimationFrame(()=>{this.openDisplayNameDialog({mode:"onboarding"})}))},handleDisplayNameSubmit(){let n=this.elements.displayNameInput,e=this.elements.displayNameDialog;if(!n||!e)return;let t=this.session?this.session.setUserName(n.value):Nt(n.value);if(!t){n.focus(),this.toastController.show(`Name must be 1-${24} characters`);return}this.preferences.setUserName(t),this.lobby.setUserName(t),this.excalidrawEmbed.updateLocalUser(this.lobby.getLocalUser()),this.syncCurrentUserName(),this.renderChat(),e.close()},async copyCurrentLink(){try{await navigator.clipboard.writeText(window.location.href),this.toastController.show("Link copied")}catch{this.toastController.show("Failed to copy link")}},getCurrentUser(){return this.globalUsers.find(n=>n.isLocal)??this.session?.getLocalUser()??this.lobby?.getLocalUser()??null},getCurrentUserName(){return this.getCurrentUser()?.name??this.getStoredUserName()??""},getStoredUserName(){return this.preferences.getUserName()},syncCurrentUserName(){let n=this.elements.currentUserName;if(!n)return;let e=this.getCurrentUserName();n.textContent=e||"Set name",n.classList.toggle("has-name",!!e),this.elements.editNameButton?.setAttribute("aria-label",`${e||"Set name"}. Change display name`)},toggleLineWrapping(){let e=!(this.session?.isLineWrappingEnabled()??this.getStoredLineWrapping());this.session?.setLineWrapping(e),this.preferences.setLineWrappingEnabled(e),this.syncWrapToggle(e),this.session?.requestMeasure(),this.scrollSyncController.syncPreviewToEditor()},getStoredLineWrapping(){return this.preferences.getLineWrappingEnabled()},handleTabTakeover(){this.tabActivityLock.tryActivate({takeover:!0})},handleTabActivated({takeover:n=!1}={}){let e=!this.isTabActive;this.isTabActive=!0,this.hideTabLockOverlay(),this.lobby.provider||this.lobby.connect(),e&&(this.fileExplorerReady&&this.handleHashChange(),this.promptForDisplayNameIfNeeded()),n&&this.toastController.show("This tab is now active")},handleTabBlocked({reason:n}={}){let e=this.isTabActive;this.isTabActive=!1,this.elements.displayNameDialog?.open&&this.elements.displayNameDialog.close(),this.lobby.disconnect(),this.globalUsers=[],this.chatMessages=[],this.chatMessageIds.clear(),this.chatUnreadCount=0,this.chatInitialSyncComplete=!1,this.followedUserClientId=null,this.followedCursorSignature="",this.connectionState={status:"disconnected",unreachable:!1},this.showEmptyState(),this.renderChat(),this.showTabLockOverlay({reason:n}),e&&n==="taken-over"&&this.toastController.show("Another tab took over this session")},showTabLockOverlay({reason:n}={}){let e=this.elements.tabLockOverlay,t=this.elements.tabLockTitle,i=this.elements.tabLockCopy;e&&(t&&(t.textContent=n==="taken-over"?"This tab is no longer active":"This vault is active in another tab"),i&&(i.textContent=n==="taken-over"?"Another tab took over the live session. This tab is now disconnected until you explicitly take over here again.":"To avoid duplicate presence and chat, only one tab can stay connected at a time. Use the other tab, or take over the session here."),e.classList.remove("hidden"))},hideTabLockOverlay(){this.elements.tabLockOverlay?.classList.add("hidden")},syncWrapToggle(n){let e=n??this.session?.isLineWrappingEnabled()??this.getStoredLineWrapping(),t=this.elements.wrapToggleLabel,i=this.elements.toggleWrapButton,s=e?"Wrap on":"Wrap off";t&&(t.textContent=s),i&&i.setAttribute("aria-label",`${s}. ${e?"Disable line wrap":"Enable line wrap"}`)},scheduleBacklinkRefresh(){clearTimeout(this._backlinkRefreshTimer),this._backlinkRefreshTimer=setTimeout(()=>{ye(this.currentFilePath)&&this.backlinksPanel.load(this.currentFilePath)},2e3)},showEditorLoading(){this.elements.editorContainer&&(this.elements.editorContainer.classList.add("is-loading-editor"),this.elements.editorContainer.innerHTML=`
|
|
29
|
+
${r}`}getPreviewSource(e){let t=this.getSession()?.getText()??"";return this.isMermaidFile(e)?this.createDiagramPreviewDocument("mermaid",t):this.isPlantUmlFile(e)?this.createDiagramPreviewDocument("plantuml",t):t}resetPreviewMode(){this.elements.previewContent?.classList.remove("is-excalidraw-file-preview"),this.elements.previewContent?.classList.remove("is-image-file-preview"),this.elements.previewContent?.classList.remove("is-mermaid-file-preview"),this.elements.previewContent?.classList.remove("is-plantuml-file-preview")}syncFileChrome(e){let t=this.isExcalidrawFile(e),i=this.isImageFile(e),s=Z(e),r=this.isMermaidFile(e),a=this.isPlantUmlFile(e),o=Wt(e);if(this.elements.markdownToolbar?.classList.toggle("hidden",!s),this.elements.outlineToggle?.classList.toggle("hidden",o||i),this.elements.previewContent?.classList.toggle("is-mermaid-file-preview",r),this.elements.previewContent?.classList.toggle("is-plantuml-file-preview",a),t||i){this.layoutController.setView("preview",{persist:!1}),this.outlineController.close(),this.backlinksPanel.clear();return}(r||a)&&(this.outlineController.close(),this.backlinksPanel.clear())}renderExcalidrawFilePreview(e){let t=this.elements.previewContent;if(!t)return;this.videoEmbed?.detachForCommit(),this.excalidrawEmbed.detachForCommit(),this.resetPreviewMode(),t.classList.add("is-excalidraw-file-preview");let i=this.previewRenderer.ensureRenderHost();this.previewRenderer.normalizePreviewChildren(i);let s=document.createElement("div");s.className="excalidraw-embed-placeholder",s.dataset.embedKey=`${e}#file-preview`,s.dataset.embedLabel=this.getDisplayName(e),s.dataset.embedTarget=e;let r=document.createElement("div");r.className="preview-shell",r.textContent="Loading Excalidraw preview\u2026",s.appendChild(r),i&&(i.replaceChildren(s),i.style.minHeight=""),t.dataset.renderPhase="ready",this.outlineController.refresh(),this.scrollSyncController.setLargeDocumentMode(!1),this.scrollSyncController.invalidatePreviewBlocks(),this.videoEmbed?.reconcileEmbeds(t),this.excalidrawEmbed.reconcileEmbeds(t,{isLargeDocument:!1}),this.excalidrawEmbed.hydrateVisibleEmbeds(),this.schedulePreviewLayoutSyncCallback({delayMs:0})}renderImageFilePreview(e){let t=this.elements.previewContent;if(!t)return;this.videoEmbed?.detachForCommit(),this.excalidrawEmbed.detachForCommit(),this.resetPreviewMode(),t.classList.add("is-image-file-preview");let i=this.previewRenderer.ensureRenderHost();this.previewRenderer.normalizePreviewChildren(i);let s=document.createElement("figure");s.className="image-file-preview-shell";let r=document.createElement("img");r.className="image-file-preview-image",r.alt=this.getDisplayName(e),r.src=C(`/attachment?path=${encodeURIComponent(e)}`),s.appendChild(r),i&&(i.replaceChildren(s),i.style.minHeight=""),t.dataset.renderPhase="ready",this.outlineController.refresh(),this.scrollSyncController.setLargeDocumentMode(!1),this.scrollSyncController.invalidatePreviewBlocks(),this.videoEmbed?.reconcileEmbeds(t),this.schedulePreviewLayoutSyncCallback({delayMs:0})}createResizeHandler(e){let t=null;return()=>{clearTimeout(t),t=setTimeout(()=>{e?.(),this.schedulePreviewLayoutSyncCallback({delayMs:0})},100)}}initializePreviewLayoutObserver(e=()=>{}){if(typeof ResizeObserver!="function"||!this.elements.previewContent)return null;let t=new ResizeObserver(()=>{e()});return t.observe(this.elements.previewContent),t}schedulePreviewLayoutSync({hydrationPaused:e,previewLayoutSyncTimer:t,setPendingPreviewLayoutSync:i,setPreviewLayoutSyncTimer:s,delayMs:r=120}){if(e){i(!0);return}clearTimeout(t);let a=setTimeout(()=>{s(null);let o=!!this.getSession(),l=this.elements.previewContent?.classList?.contains?.("is-excalidraw-file-preview")??!1;if(!(!o&&!l||!this.elements.previewContent)&&this.elements.previewContent.dataset.renderPhase!=="shell"){if(e){i(!0);return}this.previewRenderer.scheduleActiveMermaidRefit(),this.previewRenderer.scheduleActivePlantUmlRefit(),this.videoEmbed?.syncLayout(),this.excalidrawEmbed.syncLayout(),!(l&&!o)&&(this.scrollSyncController.invalidatePreviewBlocks(),this.scrollSyncController.warmPreviewBlocks({onReady:()=>{this.getSession()&&(this.scrollSyncController.realignAfterLayoutChange(),this.outlineController.scheduleActiveHeadingUpdate())}}))}},r);s(a)}handleEditorScrollActivityChange({isActive:e,pendingPreviewLayoutSync:t,previewLayoutSyncTimer:i,setHydrationPaused:s,setPendingPreviewLayoutSync:r,setPreviewLayoutSyncTimer:a}){let o=!!e;if(s(o),this.previewRenderer.setHydrationPaused(o),this.excalidrawEmbed.setHydrationPaused(o),o){clearTimeout(i),a(null),r(!0);return}t&&(r(!1),this.schedulePreviewLayoutSync({delayMs:0,hydrationPaused:!1,previewLayoutSyncTimer:null,setPendingPreviewLayoutSync:r,setPreviewLayoutSyncTimer:a}))}};var Ne=class{constructor({attachEditorScroller:e,createEditorSession:t,loadEditorSessionClass:i,scrollContainerForSession:s}){this.attachEditorScroller=e,this.createEditorSession=t,this.loadEditorSessionClass=i,this.scrollContainerForSession=s}async createSession(e){let t=await this.loadEditorSessionClass();return this.createEditorSession(t,e)}attachSessionScroller(e){this.attachEditorScroller(this.scrollContainerForSession(e))}clearSessionScroller(){this.attachEditorScroller(null)}};var De=class{constructor({beginDocumentLoad:e,getDisplayName:t,loadBacklinks:i,onBeforeFileOpen:s,onFileOpenError:r,onFileOpenReady:a,onRenderExcalidrawPreview:o,onRenderImagePreview:l,onSyncWrapToggle:h,onUpdateActiveFile:c,onUpdateCurrentFile:u,onUpdateLobbyCurrentFile:p,onUpdateVisibleChrome:d,onViewModeReset:w,renderPresence:m,showEditorLoading:b,stateStore:E}){this.beginDocumentLoad=e,this.getDisplayName=t,this.loadBacklinks=i,this.onBeforeFileOpen=s,this.onFileOpenError=r,this.onFileOpenReady=a,this.onRenderExcalidrawPreview=o,this.onRenderImagePreview=l,this.onSyncWrapToggle=h,this.onUpdateActiveFile=c,this.onUpdateCurrentFile=u,this.onUpdateLobbyCurrentFile=p,this.onUpdateVisibleChrome=d,this.onViewModeReset=w,this.renderPresence=m,this.showEditorLoading=b,this.stateStore=E}prepareForFileOpen(e,{resetConnectionState:t=!0}={}){return this.onViewModeReset(),this.onBeforeFileOpen(),this.stateStore.set("connectionHelpShown",!1),t&&this.stateStore.set("connectionState",{status:"connecting",unreachable:!1}),this.stateStore.set("currentFilePath",e),this.onUpdateCurrentFile(e),this.onUpdateLobbyCurrentFile(e),this.onUpdateActiveFile(e),this.onUpdateVisibleChrome(e,{displayName:this.getDisplayName(e),isMarkdown:Z(e)}),this.showEditorLoading(),this.beginDocumentLoad(),this.renderPresence(),{supportsBacklinks:ve(e)}}markFileOpenReady(e){this.onFileOpenReady(e)}finalizeFileOpen({filePath:e,isExcalidraw:t=!1,isImage:i=!1,session:s=null,supportsBacklinks:r}){t&&this.onRenderExcalidrawPreview(e),i&&this.onRenderImagePreview(e),this.onSyncWrapToggle(),r&&s&&this.loadBacklinks(e)}handleFileOpenError(){this.onFileOpenError()}};var He=class{constructor({attachEditorScroller:e,beginDocumentLoad:t,cleanupAfterSessionDestroy:i,createEditorSession:s,getDisplayName:r,getFileList:a,getLineWrappingEnabled:o,getLocalUser:l,getStoredUserName:h,getTheme:c,isExcalidrawFile:u,isImageFile:p,isMermaidFile:d,isPlantUmlFile:w,isTabActive:m,loadEditorSessionClass:b,loadBacklinks:E,onBeforeFileOpen:I,onConnectionChange:F,onContentChange:A,onCommentsChange:z,onFileAwarenessChange:U,onFileOpenError:R,onFileOpenReady:B,onImagePaste:N,onSelectionChange:$,onSessionAssigned:G=null,onRenderExcalidrawPreview:V,onRenderImagePreview:Y,onSyncWrapToggle:K,onUpdateActiveFile:D,onUpdateCurrentFile:M,onUpdateLobbyCurrentFile:H,onUpdateVisibleChrome:te,onViewModeReset:O,renderPresence:_,scrollContainerForSession:f,showEditorLoading:y,stateStore:v}){this.attachEditorScroller=e,this.beginDocumentLoad=t,this.cleanupAfterSessionDestroy=i,this.createEditorSession=s,this.getDisplayName=r,this.getFileList=a,this.getLineWrappingEnabled=o,this.getLocalUser=l,this.getStoredUserName=h,this.getTheme=c,this.isExcalidrawFile=u??(()=>!1),this.isImageFile=p??(()=>!1),this.isMermaidFile=d??(()=>!1),this.isPlantUmlFile=w??(()=>!1),this.isTabActive=m,this.loadEditorSessionClassPort=b,this.loadBacklinks=E,this.onBeforeFileOpen=I,this.onConnectionChange=F,this.onContentChange=A,this.onCommentsChange=z,this.onFileAwarenessChange=U,this.onFileOpenError=R,this.onFileOpenReady=B,this.onImagePaste=N,this.onSelectionChange=$,this.onSessionAssigned=G,this.onRenderExcalidrawPreview=V,this.onSyncWrapToggle=K,this.onUpdateActiveFile=D,this.onUpdateCurrentFile=M,this.onUpdateLobbyCurrentFile=H,this.onUpdateVisibleChrome=te,this.renderPresence=_,this.stateStore=v,this.session=null,this.lifecycle=new Ne({attachEditorScroller:e,createEditorSession:s,loadEditorSessionClass:()=>this.loadEditorSessionClassPort(),scrollContainerForSession:f}),this.chromeController=new De({beginDocumentLoad:t,getDisplayName:r,loadBacklinks:E,onBeforeFileOpen:I,onFileOpenError:R,onFileOpenReady:B,onRenderExcalidrawPreview:V,onRenderImagePreview:Y,onSyncWrapToggle:K,onUpdateActiveFile:D,onUpdateCurrentFile:M,onUpdateLobbyCurrentFile:H,onUpdateVisibleChrome:te,onViewModeReset:O,renderPresence:_,showEditorLoading:y,stateStore:v})}getSession(){return this.session}loadEditorSessionClass(){return this.loadEditorSessionClassPort()}waitForNextPaint(){return new Promise(e=>{requestAnimationFrame(()=>{requestAnimationFrame(e)})})}cleanupSession(){this.session?.destroy(),this.session=null,this.lifecycle.clearSessionScroller(),this.cleanupAfterSessionDestroy()}async openFile(e){if(!this.isTabActive())return;let t=this.isExcalidrawFile(e),i=this.isImageFile(e),s=this.isMermaidFile(e),r=this.isPlantUmlFile(e);if(e===this.stateStore.get("currentFilePath")&&(this.session||t||i)){this.onUpdateActiveFile(e),this.onUpdateLobbyCurrentFile(e);return}let a=this.stateStore.nextSessionLoadToken();this.cleanupSession();let o=this.chromeController.prepareForFileOpen(e,{resetConnectionState:!t&&!i});if(t||i){if(this.onSessionAssigned?.(null),a!==this.stateStore.get("sessionLoadToken"))return;this.chromeController.markFileOpenReady(null),this.chromeController.finalizeFileOpen({filePath:e,isExcalidraw:t,isImage:i,session:null,supportsBacklinks:o.supportsBacklinks});return}let l=await this.lifecycle.createSession({filePath:e,getFileList:this.getFileList,lineWrappingEnabled:this.getLineWrappingEnabled(),localUser:this.getLocalUser(),onAwarenessChange:h=>this.onFileAwarenessChange(h),onConnectionChange:h=>this.onConnectionChange(h),onCommentsChange:h=>this.onCommentsChange?.(h),onContentChange:()=>{t||this.onContentChange({isMermaid:s,isPlantUml:r})},onImagePaste:h=>this.onImagePaste?.(h),preferredUserName:this.getStoredUserName(),onSelectionChange:h=>this.onSelectionChange?.(h),theme:this.getTheme()});this.session=l,this.onSessionAssigned?.(l);try{if(await l.initialize(e),a!==this.stateStore.get("sessionLoadToken")){l.destroy();return}if(this.lifecycle.attachSessionScroller(l),l.applyTheme(this.getTheme()),await l.waitForInitialSync(),l.ensureInitialContent?.(),a!==this.stateStore.get("sessionLoadToken")){l.destroy();return}if(this.chromeController.markFileOpenReady(l),l.requestMeasure(),await this.waitForNextPaint(),a!==this.stateStore.get("sessionLoadToken")){l.destroy();return}this.chromeController.finalizeFileOpen({filePath:e,isExcalidraw:t,session:l,supportsBacklinks:o.supportsBacklinks})}catch(h){if(console.error("[app] Failed to initialize editor:",h),l.destroy(),this.lifecycle.clearSessionScroller(),this.session===l&&(this.session=null),a!==this.stateStore.get("sessionLoadToken"))return;this.chromeController.handleFileOpenError()}}};var _e=class{constructor(e={}){this.state={activeSidebarTab:"files",chatInitialSyncComplete:!1,chatIsOpen:!1,chatMessageIds:new Set,chatMessages:[],chatUnreadCount:0,connectionHelpShown:!1,connectionState:{status:"disconnected",unreachable:!1},currentFilePath:null,fileExplorerReady:!1,followedCursorSignature:"",followedUserClientId:null,gitRepoAvailable:!1,globalUsers:[],isTabActive:!1,sessionLoadToken:0,...e}}get(e){return this.state[e]}set(e,t){return this.state[e]=t,t}nextSessionLoadToken(){let e=Number(this.state.sessionLoadToken||0)+1;return this.state.sessionLoadToken=e,e}replaceChatState({initialSyncComplete:e,isOpen:t,messageIds:i,messages:s,unreadCount:r}){this.state.chatMessages=Array.isArray(s)?s:[],this.state.chatMessageIds=i instanceof Set?i:new Set,this.state.chatUnreadCount=Number.isFinite(r)?r:0,this.state.chatIsOpen=!!t,this.state.chatInitialSyncComplete=!!e}};function ci(n=document){return{currentUserName:n.getElementById("currentUserName"),chatContainer:n.getElementById("chatContainer"),chatEmptyState:n.getElementById("chatEmptyState"),chatForm:n.getElementById("chatForm"),chatInput:n.getElementById("chatInput"),chatMessages:n.getElementById("chatMessages"),chatNotificationButton:n.getElementById("chatNotificationBtn"),chatPanel:n.getElementById("chatPanel"),chatStatus:n.getElementById("chatStatus"),chatToastContainer:n.getElementById("chatToastContainer"),chatToggleBadge:n.getElementById("chatToggleBadge"),chatToggleButton:n.getElementById("chatToggleBtn"),gitCommitCancel:n.getElementById("gitCommitCancel"),gitCommitCopy:n.getElementById("gitCommitCopy"),gitCommitDialog:n.getElementById("gitCommitDialog"),gitCommitForm:n.getElementById("gitCommitForm"),gitCommitInput:n.getElementById("gitCommitInput"),gitCommitSubmit:n.getElementById("gitCommitSubmit"),gitCommitTitle:n.getElementById("gitCommitTitle"),gitResetCancel:n.getElementById("gitResetCancel"),gitResetCopy:n.getElementById("gitResetCopy"),gitResetDialog:n.getElementById("gitResetDialog"),gitResetFileName:n.getElementById("gitResetFileName"),gitResetSubmit:n.getElementById("gitResetSubmit"),gitResetTitle:n.getElementById("gitResetTitle"),displayNameCancel:n.getElementById("displayNameCancel"),displayNameCopy:n.getElementById("displayNameCopy"),displayNameDialog:n.getElementById("displayNameDialog"),displayNameForm:n.getElementById("displayNameForm"),displayNameInput:n.getElementById("displayNameInput"),displayNameSubmit:n.getElementById("displayNameSubmit"),displayNameTitle:n.getElementById("displayNameTitle"),editNameButton:n.getElementById("editNameBtn"),editorContainer:n.getElementById("editorContainer"),markdownToolbar:n.getElementById("markdownToolbar"),editorPage:n.getElementById("editor-page"),diffPage:n.getElementById("diff-page"),fileSearch:n.getElementById("fileSearch"),filesSidebarTab:n.getElementById("filesSidebarTab"),gitSearch:n.getElementById("gitSearch"),gitSearchInput:n.getElementById("gitSearchInput"),gitSidebarTab:n.getElementById("gitSidebarTab"),gitOperationStatus:n.getElementById("gitOperationStatus"),lineInfo:n.getElementById("lineInfo"),mobileViewToggle:n.getElementById("mobileViewToggle"),previewContent:n.getElementById("previewContent"),previewContainer:n.getElementById("previewContainer"),shareButton:n.getElementById("shareBtn"),toastContainer:n.getElementById("toastContainer"),toggleWrapButton:n.getElementById("toggleWrapBtn"),userAvatars:n.getElementById("userAvatars"),userCount:n.getElementById("userCount"),wrapToggleLabel:n.getElementById("wrapToggleLabel"),activeFileName:n.getElementById("activeFileName"),sidebarToggle:n.getElementById("sidebarToggle"),sidebarClose:n.getElementById("sidebarClose"),sidebar:n.getElementById("sidebar"),emptyState:n.getElementById("emptyState"),emptyStateNewFileBtn:n.getElementById("emptyStateNewFileBtn"),emptyStateSearchBtn:n.getElementById("emptyStateSearchBtn"),backlinksPanel:n.getElementById("backlinksPanel"),backlinksInlinePanel:n.getElementById("backlinksInlinePanel"),commentSelectionButton:n.getElementById("commentSelectionBtn"),commentsDrawer:n.getElementById("commentsDrawer"),commentsDrawerEmpty:n.getElementById("commentsDrawerEmpty"),commentsDrawerList:n.getElementById("commentsDrawerList"),commentsToggleButton:n.getElementById("commentsToggle"),outlineToggle:n.getElementById("outlineToggle"),tabLockCopy:n.getElementById("tabLockCopy"),tabLockOverlay:n.getElementById("tabLockOverlay"),tabLockTakeoverButton:n.getElementById("tabLockTakeoverBtn"),tabLockTitle:n.getElementById("tabLockTitle"),toolbarCenter:n.getElementById("toolbarCenter"),toolbarDiffBadge:n.getElementById("toolbarDiffBadge"),sidebarTabs:n.getElementById("sidebarTabs")}}var hi={updateChatMessages(n,{initial:e=!1}={}){let t=new Set(this.chatMessageIds),i=this.lobby.getLocalUser()?.peerId??null;if(this.chatMessages=n,this.chatMessageIds=new Set(n.map(r=>r.id)),!this.chatInitialSyncComplete){e&&(this.chatInitialSyncComplete=!0),this.renderChat();return}let s=n.filter(r=>!t.has(r.id)&&r.peerId&&r.peerId!==i);this.chatIsOpen?this.chatUnreadCount=0:s.length>0&&(this.chatUnreadCount+=s.length);for(let r of s)this.maybeNotifyChatMessage(r);this.renderChat()},toggleChatPanel(){if(this.chatIsOpen){this.closeChatPanel();return}this.openChatPanel()},openChatPanel(){this.chatIsOpen=!0,this.chatUnreadCount=0,this.renderChat(),requestAnimationFrame(()=>{this.elements.chatInput?.focus(),this.scrollChatToBottom()})},closeChatPanel(){this.chatIsOpen&&(this.chatIsOpen=!1,this.renderChat())},handleChatSubmit(){if(!this.isTabActive)return;let n=this.elements.chatInput;if(!n)return;if(!this.lobby.sendChatMessage(n.value)){n.focus();return}if(n.value="",!this.chatIsOpen){this.openChatPanel();return}this.renderChat()},renderChat(){this.elements.chatContainer?.classList.toggle("is-open",this.chatIsOpen),this.elements.chatPanel?.classList.toggle("hidden",!this.chatIsOpen),this.syncChatToggleButton(),this.syncChatNotificationButton();let n=this.elements.chatMessages,e=this.elements.chatEmptyState;if(this.elements.chatStatus&&(this.elements.chatStatus.textContent=this.chatInitialSyncComplete?`${this.globalUsers.length} online`:"Syncing..."),!n)return;if(n.replaceChildren(),this.chatMessages.length===0){e?.classList.remove("hidden"),n.classList.add("hidden");return}e?.classList.add("hidden"),n.classList.remove("hidden");let t=document.createDocumentFragment();this.chatMessages.forEach(i=>{t.appendChild(this.createChatMessageElement(i))}),n.appendChild(t),this.chatIsOpen&&this.scrollChatToBottom()},createChatMessageElement(n){let e=document.createElement("article"),t=n.peerId===this.lobby.getLocalUser()?.peerId;e.className="chat-message",e.classList.toggle("is-local",t);let i=document.createElement("div");i.className="chat-message-avatar",i.style.backgroundColor=n.userColor||"var(--color-primary)",i.textContent=(n.userName||"?").charAt(0).toUpperCase(),i.setAttribute("aria-hidden","true");let s=document.createElement("div");s.className="chat-message-body";let r=document.createElement("div");r.className="chat-message-meta";let a=document.createElement("span");a.className="chat-message-author",a.textContent=t?`${n.userName} (you)`:n.userName;let o=document.createElement("span");o.className="chat-message-time",o.textContent=this.formatChatTimestamp(n.createdAt),r.append(a,o);let l=this.getChatMessageFileLabel(n.filePath);if(l){let c=document.createElement("span");c.className="chat-message-file",c.textContent=l,r.append(c)}let h=document.createElement("p");return h.className="chat-message-text",h.textContent=n.text,s.append(r,h),e.append(i,s),e},scrollChatToBottom(){let n=this.elements.chatMessages;n&&requestAnimationFrame(()=>{n.scrollTop=n.scrollHeight})},formatChatTimestamp(n){if(!Number.isFinite(n))return"";try{return this.chatTimeFormatter.format(new Date(n))}catch{return""}},getChatMessageFileLabel(n){return n?this.getDisplayName(n):""},formatChatToastMessage(n){let e=n?.userName||"Someone",t=String(n?.text??"").replace(/\s+/g," ").trim(),i=t.length>88?`${t.slice(0,85).trimEnd()}...`:t;return`${e}: ${i}`},syncChatToggleButton(){let n=this.elements.chatToggleButton,e=this.elements.chatToggleBadge;if(!n)return;let t=this.chatUnreadCount>0,i=t&&!this.chatIsOpen;n.classList.toggle("is-active",this.chatIsOpen),n.classList.toggle("is-unread",i),n.setAttribute("aria-expanded",String(this.chatIsOpen)),n.setAttribute("aria-label",t?`Open team chat, ${this.chatUnreadCount} unread`:"Open team chat"),n.title=this.chatUnreadCount>0?`Team chat (${this.chatUnreadCount} unread)`:"Team chat",e&&(e.classList.toggle("hidden",!t),e.textContent=this.chatUnreadCount>9?"9+":String(this.chatUnreadCount))},syncChatNotificationButton(){let n=this.elements.chatNotificationButton;if(!n)return;let e=this.notifications.getPermission();this.chatNotificationPermission=e;let t="Enable alerts",i="Enable browser notifications for new chat messages",s=!1;e==="unsupported"?(t="No alerts",i="Browser notifications are unavailable here"):e==="denied"?(t="Alerts blocked",i="Browser notifications are blocked for this site"):e==="granted"&&(s=this.chatNotificationsEnabled,t=s?"Alerts on":"Alerts off",i=s?"Disable browser notifications for chat":"Enable browser notifications for chat"),n.textContent=t,n.title=i,n.setAttribute("aria-pressed",String(s)),n.classList.toggle("is-enabled",s),n.classList.toggle("is-blocked",e==="denied")},async handleChatNotificationToggle(){let n=this.notifications.getPermission();if(this.chatNotificationPermission=n,n==="unsupported"){this.toastController.show("Browser notifications are unavailable here"),this.syncChatNotificationButton();return}if(n==="denied"){this.chatNotificationsEnabled=!1,this.preferences.setChatNotificationsEnabled(!1),this.toastController.show("Browser notifications are blocked for this site"),this.syncChatNotificationButton();return}if(n==="default"){let e=await this.notifications.requestPermission();if(this.chatNotificationPermission=e,e!=="granted"){this.chatNotificationsEnabled=!1,this.preferences.setChatNotificationsEnabled(!1),e==="denied"&&this.toastController.show("Browser notifications were blocked"),this.syncChatNotificationButton();return}this.chatNotificationsEnabled=!0,this.preferences.setChatNotificationsEnabled(!0),this.syncChatNotificationButton();return}this.chatNotificationsEnabled=!this.chatNotificationsEnabled,this.preferences.setChatNotificationsEnabled(this.chatNotificationsEnabled),this.syncChatNotificationButton()},maybeNotifyChatMessage(n){if(this.chatInitialSyncComplete){if(document.hidden){this.maybeShowBrowserChatNotification(n);return}!this.isTabActive||this.chatIsOpen||(this.chatToastController??this.toastController).show(this.formatChatToastMessage(n),4e3)}},maybeShowBrowserChatNotification(n){if(!this.chatNotificationsEnabled||this.notifications.getPermission()!=="granted")return;let e=`CollabMD chat \u2022 ${n.userName}`,t=this.getChatMessageFileLabel(n.filePath),i=t?`${t}: ${n.text}`:n.text,s=this.notifications.createNotification({body:i,onClick:()=>{n.filePath&&this.navigation.navigateToFile(n.filePath)},tag:`collabmd-chat-${n.id}`,title:e});s&&setTimeout(()=>{s.close?.()},6e3)}};var di={getCommentFileKind(n=this.currentFilePath){return Ut(n)||"markdown"},syncCommentChrome(n=this.currentFilePath){let e=Gt(n)&&!this.isExcalidrawFile(n);this.commentUi.setCurrentFile(n,{fileKind:this.getCommentFileKind(n),supported:e}),this.handleCommentThreadsChange(this.session?.getCommentThreads?.()??[]),this.handleCommentSelectionChange(this.session?.getCurrentSelectionCommentAnchor?.()??null)},handleCommentSelectionChange(n){this.commentUi.setSelectionAnchor(n)},handleCommentThreadsChange(n=[]){this.commentUi.setThreads(n)},handleCommentEditorContentChange(){this.commentUi.handleEditorContentChange()},refreshCommentUiLayout(){this.commentUi.refreshLayout()}};function Et(n=[]){return Array.from(new Set((n??[]).filter(Boolean)))}function sn(n=[]){return Array.from(new Map((n??[]).filter(e=>e?.oldPath&&e?.newPath&&e.oldPath!==e.newPath).map(e=>[`${e.oldPath}:${e.newPath}`,{newPath:e.newPath,oldPath:e.oldPath}])).values())}function rn(n=[]){return(n??[]).filter(e=>e?.path&&Number.isFinite(e?.from)&&Number.isFinite(e?.to)).map(e=>({from:Math.max(0,Math.round(e.from)),path:e.path,to:Math.max(0,Math.round(e.to))}))}function St({changedPaths:n=[],deletedPaths:e=[],refreshExplorer:t=!0,renamedPaths:i=[]}={}){return{changedPaths:Et(n),deletedPaths:Et(e),refreshExplorer:t!==!1,renamedPaths:sn(i)}}function kt(n){return!n||typeof n!="object"||typeof n.id!="string"?null:{action:typeof n.action=="string"?n.action:"workspace",createdAt:Number.isFinite(n.createdAt)?n.createdAt:Date.now(),highlightRanges:rn(n.highlightRanges),id:n.id,origin:typeof n.origin=="string"?n.origin:"api",reloadRequiredPaths:Et(n.reloadRequiredPaths),requestId:typeof n.requestId=="string"?n.requestId:null,sourceRef:typeof n.sourceRef=="string"?n.sourceRef:null,workspaceChange:St(n.workspaceChange)}}function ui(n={}){return St(n)}function an(){return globalThis.crypto?.randomUUID?globalThis.crypto.randomUUID():`workspace-${Date.now()}-${Math.random().toString(16).slice(2,10)}`}var mi={formatPullBackupToast(n=null){let e=Number(n?.fileCount||0);return e===1?"Pulled latest changes. 1 overlapping local file was backed up.":e>1?`Pulled latest changes. ${e} overlapping local files were backed up.`:"Pulled latest changes. Overlapping local changes were recorded in a pull backup."},setGitOperationStatus(n=""){let e=this.elements.gitOperationStatus;if(!e)return;let t=String(n??"").trim();e.textContent=t,e.classList.toggle("hidden",!t)},async runGitActionWithStatus(n,e){this.setGitOperationStatus(n);try{return await e()}finally{this.setGitOperationStatus("")}},handleGitDiffSelection(n,{closeSidebarOnMobile:e=!1,scope:t="working-tree"}={}){e&&this.closeSidebarOnMobile(),this.navigation.navigateToGitDiff({filePath:n,scope:t})},handleGitRepoChange(n,e=null){this.gitRepoAvailable=!!n,this.elements.sidebarTabs?.classList.toggle("hidden",!this.gitRepoAvailable),this.elements.gitSidebarTab?.classList.toggle("hidden",!this.gitRepoAvailable);let t=n&&e?.summary?.changedFiles>0;if(this.elements.gitSidebarTab?.classList.toggle("has-changes",t),this.gitDiffView.setRepoStatus(this.gitRepoAvailable?e:null),!this.gitRepoAvailable&&this.activeSidebarTab==="git"){this.setSidebarTab("files");return}this.gitRepoAvailable&&this.navigation.getHashRoute().type==="git-diff"&&this.activeSidebarTab!=="git"&&this.setSidebarTab("git")},syncMainChrome({mode:n,title:e=null}={}){let t=n==="diff";this.elements.toolbarCenter?.classList.toggle("hidden",t),this.elements.mobileViewToggle?.classList.toggle("hidden",t),this.elements.userCount?.classList.toggle("hidden",t),this.elements.toolbarDiffBadge?.classList.toggle("hidden",!t),e&&this.elements.activeFileName&&(this.elements.activeFileName.textContent=e)},async showGitDiff({filePath:n=null,scope:e="all"}={}){this.gitPanel.setSelection(n?{path:n,scope:e}:{}),this.showDiffState(),this.syncMainChrome({mode:"diff",title:this.gitDiffView.getToolbarTitle({filePath:n,scope:e})}),await this.gitDiffView.open({filePath:n,scope:e})},async postGitAction(n,e){let t=an();this.pendingWorkspaceRequestIds?.add(t);let i=await fetch(n,{body:JSON.stringify(e),headers:{"Content-Type":"application/json","X-CollabMD-Request-Id":t},method:"POST"}),s=await i.json();if(!i.ok){this.pendingWorkspaceRequestIds?.delete(t);let r=new Error(s.error||"Git action failed");throw typeof s?.code=="string"&&(r.code=s.code),r}return s},async refreshWorkspaceAfterGitAction({filePath:n=null,preferredScope:e=null}={}){await this.fileExplorer.refresh(),await this.refreshGitAfterAction({filePath:n,preferredScope:e})},async refreshGitAfterAction({filePath:n=null,preferredScope:e=null}={}){await this.gitPanel.refresh({force:!0});let t=this.navigation.getHashRoute();if(t.type!=="git-diff")return;let i=n??t.filePath,s=e??t.scope;if(s!==t.scope||i!==t.filePath){this.navigation.navigateToGitDiff({filePath:i,scope:s});return}await this.showGitDiff({filePath:t.filePath,scope:t.scope})},async finalizeGitAction({action:n,filePath:e=null,preferredScope:t=null,result:i={},showLocalFileToast:s=!1}={}){let r=ui(i.workspaceChange);return await this.refreshWorkspaceAfterGitAction({filePath:e,preferredScope:t}),this.handleWorkspaceChangeForCurrentFile(r,{action:n,local:!0,showToast:s}),r},handleWorkspaceChangeForCurrentFile(n,{action:e="git",local:t=!1,showToast:i=!0}={}){let s=this.currentFilePath;if(!s)return!1;let r=n.deletedPaths.includes(s),a=n.renamedPaths.find(l=>l.oldPath===s);if(!r&&!a)return!1;if(!i)return a?this.navigation.navigateToFile(a.newPath):this.navigation.navigateToFile(null),!0;let o=this.getDisplayName(s);return a?(this.navigation.navigateToFile(a.newPath),this.toastController.show(t?`${o} moved to ${this.getDisplayName(a.newPath)}`:`${o} moved on disk`),!0):(this.navigation.navigateToFile(null),this.toastController.show(t?`${o} was removed by ${e}`:`${o} was removed after a ${e} operation`),!0)},async handleIncomingWorkspaceEvent(n){if(!this.isTabActive||!n)return;if(n.requestId&&this.pendingWorkspaceRequestIds?.has(n.requestId)){this.pendingWorkspaceRequestIds.delete(n.requestId);return}let e=ui(n.workspaceChange);if(n.origin==="git"&&await this.refreshGitAfterAction(),this.handleWorkspaceChangeForCurrentFile(e,{action:n.action||n.origin||"workspace",local:!1,showToast:!0}),n.origin==="filesystem"&&this.currentFilePath&&e.changedPaths.includes(this.currentFilePath)){let i=e.changedPaths.length===1&&Array.isArray(n.highlightRanges)?n.highlightRanges.find(r=>r.path===this.currentFilePath):null;i&&this.session?.flashExternalUpdate?.(i)||this.toastController.show(`${this.getDisplayName(this.currentFilePath)} updated from disk`)}this.currentFilePath&&Array.isArray(n.reloadRequiredPaths)&&n.reloadRequiredPaths.includes(this.currentFilePath)&&this.toastController.show(`${this.getDisplayName(this.currentFilePath)} needs a manual reload`)},async stageGitFile(n,{scope:e="working-tree"}={}){n&&await this.runGitActionWithStatus("Staging changes...",async()=>{let t=await this.postGitAction(C("/git/stage"),{path:n});await this.finalizeGitAction({action:"stage",filePath:n,preferredScope:e==="all"?"all":"staged",result:t})})},async unstageGitFile(n,{scope:e="staged"}={}){n&&await this.runGitActionWithStatus("Unstaging changes...",async()=>{let t=await this.postGitAction(C("/git/unstage"),{path:n});await this.finalizeGitAction({action:"unstage",filePath:n,preferredScope:e==="all"?"all":"working-tree",result:t})})},async pushGitBranch(){await this.runGitActionWithStatus("Pushing branch...",async()=>{try{let n=await this.postGitAction(C("/git/push"),{});await this.finalizeGitAction({action:"push",result:n})}catch(n){this.toastController.show(n.message||"Failed to push branch")}})},async pullGitBranch(){await this.runGitActionWithStatus("Pulling branch...",async()=>{try{let n=await this.postGitAction(C("/git/pull"),{});await this.finalizeGitAction({action:"pull",result:n,showLocalFileToast:!0}),n.pullBackup&&this.toastController.show(this.formatPullBackupToast(n.pullBackup),5e3)}catch(n){if(n?.code==="pull_diverged_ff_only"){this.toastController.show("Cannot pull because local and remote commits have diverged. Fast-forward only pull is not possible.",5e3);return}if(n?.code==="pull_conflicted_after_autostash"){this.toastController.show("Pull updated the branch, but reapplying local changes caused conflicts. Review the conflicted files and the pull backup summary.",6e3);return}this.toastController.show(n.message||"Failed to pull branch")}})},openGitResetDialog(n){if(!this.isTabActive||!n)return;let e=this.elements.gitResetDialog;!e||!this.elements.gitResetFileName||(this.pendingGitResetPath=n,this.elements.gitResetTitle&&(this.elements.gitResetTitle.textContent="Reset file to current branch"),this.elements.gitResetCopy&&(this.elements.gitResetCopy.textContent="Restore this file from the current checked-out branch. If this branch does not contain the file, the file will be deleted locally."),this.elements.gitResetFileName.value=n,this.elements.gitResetSubmit&&(this.elements.gitResetSubmit.textContent="Reset File"),this.elements.gitResetSubmit?.toggleAttribute("disabled",!1),!e.open&&(typeof e.showModal=="function"?e.showModal():e.setAttribute("open","true")))},async handleGitResetSubmit(){let n=this.pendingGitResetPath,e=this.elements.gitResetDialog,t=this.elements.gitResetSubmit;if(!(!n||!e)){t?.toggleAttribute("disabled",!0),t&&(t.textContent="Resetting...");try{await this.runGitActionWithStatus("Resetting file...",async()=>{let i=await this.postGitAction(C("/git/reset-file"),{path:n});await this.finalizeGitAction({action:"reset",filePath:n,result:i,showLocalFileToast:!0})}),e.close()}catch(i){this.toastController.show(i.message||"Failed to reset file")}finally{t&&(t.textContent="Reset File"),t?.toggleAttribute("disabled",!1)}}},openGitCommitDialog(){if(!this.isTabActive)return;let n=this.elements.gitCommitDialog,e=this.elements.gitCommitInput;if(!(!n||!e)){if(this.elements.gitCommitTitle&&(this.elements.gitCommitTitle.textContent="Commit staged changes"),this.elements.gitCommitCopy){let t=Number(this.gitPanel.status?.summary?.staged||0);this.elements.gitCommitCopy.textContent=t>0?`${t} staged file${t===1?"":"s"} will be included.`:"All staged changes will be included."}this.elements.gitCommitSubmit&&(this.elements.gitCommitSubmit.textContent="Commit staged changes"),e.value="",!n.open&&(typeof n.showModal=="function"?n.showModal():n.setAttribute("open","true"),requestAnimationFrame(()=>{e.focus(),e.select()}))}},async handleGitCommitSubmit(){let n=this.elements.gitCommitDialog,e=this.elements.gitCommitInput,t=this.elements.gitCommitSubmit,i=String(e?.value??"").trim();if(!(!n||!e)){if(!i){e.focus(),this.toastController.show("Commit message cannot be empty");return}t?.toggleAttribute("disabled",!0),t&&(t.textContent="Committing...");try{await this.runGitActionWithStatus("Committing changes...",async()=>{let s=await this.postGitAction(C("/git/commit"),{message:i});await this.finalizeGitAction({action:"commit",result:s})}),n.close()}catch(s){this.toastController.show(s.message||"Failed to commit staged changes")}finally{t&&(t.textContent="Commit staged changes"),t?.toggleAttribute("disabled",!1)}}}};var pi={updateGlobalUsers(n){this.globalUsers=n,this.syncFollowedUser(),this.renderAvatars(),this.renderChat(),this.renderPresence(),this.syncCurrentUserName()},updateFileAwareness(n){this.syncFollowedUser()},renderPresence(){let n=this.elements.userCount;if(!n)return;let e=!!this.session,t=!!(this.currentFilePath&&this.isExcalidrawFile?.(this.currentFilePath)),i=!!(this.currentFilePath&&this.isImageFile?.(this.currentFilePath)),r=!e&&(!this.currentFilePath||t||i)?this.lobby?.getConnectionState?.()??this.connectionState:this.connectionState;if(r.status==="connected"){n.textContent=`${this.globalUsers.length} online`,n.style.opacity="1";return}if(r.status==="connecting"){n.textContent=r.unreachable?"Unreachable":"Connecting...",n.style.opacity="0.6";return}n.textContent="Offline",n.style.opacity="0.6"},renderAvatars(){let n=this.elements.userAvatars;if(!n)return;n.innerHTML="";let e=[...this.globalUsers],t=e.findIndex(r=>r.isLocal);if(t>0){let[r]=e.splice(t,1);e.unshift(r)}let i=e.findIndex(r=>!r.isLocal&&r.clientId===this.followedUserClientId),s=e[0]?.isLocal?1:0;if(i>s){let[r]=e.splice(i,1);e.splice(s,0,r)}if(e.slice(0,5).forEach(r=>{let a=document.createElement(r.isLocal?"div":"button");a.className="user-avatar",a.classList.toggle("is-local",r.isLocal),a.style.backgroundColor=r.color,a.classList.toggle("is-following",r.clientId===this.followedUserClientId);let o=document.createElement("span");o.className="user-avatar-initial",o.textContent=r.name.charAt(0).toUpperCase(),a.appendChild(o);let l=r.currentFile&&r.currentFile===this.currentFilePath,h=r.currentFile?this.getDisplayName(r.currentFile):"No file";if(r.isLocal){let c=document.createElement("span");c.className="user-avatar-self-label",c.textContent="You",a.appendChild(c),a.title=`${r.name} (you) \u2014 ${h}`,a.setAttribute("role","img"),a.setAttribute("aria-label",`${r.name} (you) \u2014 ${h}`)}else{a.type="button",a.classList.add("user-avatar-button"),l||a.classList.add("different-file");let c=r.clientId===this.followedUserClientId?`Stop following ${r.name}`:l?`Follow ${r.name}`:`Follow ${r.name} \u2014 ${h}`;a.title=c,a.setAttribute("aria-label",c),a.addEventListener("click",()=>this.toggleFollowUser(r.clientId))}n.appendChild(a)}),e.length>5){let r=document.createElement("div");r.className="user-avatar",r.style.backgroundColor="var(--color-surface-dynamic)",r.style.color="var(--color-text-muted)";let a=document.createElement("span");a.className="user-avatar-initial",a.textContent=`+${e.length-5}`,r.appendChild(a),n.appendChild(r)}},toggleFollowUser(n){if(!n)return;if(this.followedUserClientId===n){this.stopFollowingUser();return}let e=this.globalUsers.find(t=>t.clientId===n&&!t.isLocal);if(e){if(this.followedUserClientId=n,this.followedCursorSignature="",this.renderAvatars(),e.currentFile&&e.currentFile!==this.currentFilePath){this.navigation.navigateToFile(e.currentFile);return}requestAnimationFrame(()=>{this.followedUserClientId===n&&this.followUserCursor(e,{force:!0})})}},stopFollowingUser(){this.followedUserClientId&&(this.currentFilePath&&this.isExcalidrawFile?.(this.currentFilePath)&&this.excalidrawEmbed?.setFollowedUser(this.currentFilePath,null),this.followedUserClientId=null,this.followedCursorSignature="",this.renderAvatars())},syncFollowedUser(){if(!this.followedUserClientId)return;let n=this.globalUsers.find(e=>e.clientId===this.followedUserClientId);if(!n||n.isLocal){this.stopFollowingUser();return}if(n.currentFile&&n.currentFile!==this.currentFilePath){this.navigation.navigateToFile(n.currentFile);return}this.followUserCursor(n)},followUserCursor(n,{force:e=!1}={}){if(this.currentFilePath&&this.isExcalidrawFile?.(this.currentFilePath)){this.followExcalidrawUser(n,{force:e});return}let t=this.resolveFileClientId(n.peerId),i=t!=null?this.session?.getUserViewport(t):null,s=t!=null?this.session?.getUserCursor(t):null,r=s?.cursorHead??null,a=s?.cursorLine??null,o=s?.cursorAnchor??null,l=i?.topLine??null,h=i?.viewportRatio??.35;if(!n||l==null&&(r==null||a==null)){this.followedCursorSignature="";return}let c=`${n.clientId}:${l??"no-viewport"}:${o??"no-anchor"}:${r??"no-head"}`;if(!e&&c===this.followedCursorSignature)return;(t!=null&&this.session?.scrollToUserViewport(t)||t!=null&&this.session?.scrollToUserCursor(t,"center")||r!=null&&this.session?.scrollToPosition(r,"center")||a!=null&&this.session?.scrollToLine(a,h))&&(this.followedCursorSignature=c)},followExcalidrawUser(n,{force:e=!1}={}){if(!n?.peerId||!this.currentFilePath){this.followedCursorSignature="";return}let t=`excalidraw:${this.currentFilePath}:${n.peerId}`;!e&&t===this.followedCursorSignature||Promise.resolve(this.excalidrawEmbed?.setFollowedUser(this.currentFilePath,n.peerId)).then(i=>{i===!1||this.followedUserClientId!==n.clientId||(this.followedCursorSignature=t)}).catch(()=>{})},resolveFileClientId(n){if(!n||!this.session?.awareness)return null;for(let[e,t]of this.session.awareness.getStates())if(t.user?.peerId===n)return e;return null}};var ln="image/png,image/jpeg,image/webp,image/gif,image/svg+xml",fi={initialize(){this.themeController.initialize(),this.previewRenderer.applyTheme(this.themeController.getTheme()),this.previewRenderer.scheduleWorkerPrewarm(),this.scheduleEditorSessionPrewarm?.(),this.outlineController.initialize(),this.layoutController.initialize(),this.scrollSyncController.initialize(),this.fileExplorer.initialize(),this.gitPanel.initialize(),this.gitDiffView.initialize(),this.initializePreviewLayoutObserver(),this.syncCurrentUserName(),this.syncWrapToggle(),this.syncChatNotificationButton(),this.renderChat(),this.gitPanel.refresh({force:!0}),this.elements.chatInput?.setAttribute("maxlength",String(this.lobbyChatMessageMaxLength)),this.bindEvents(),this.restoreSidebarState(),this.tabActivityLock.initialize(),this.tabActivityLock.tryActivate(),window.addEventListener("hashchange",()=>this.handleHashChange()),window.addEventListener("resize",this.createResizeHandler()),this.fileExplorerReadyPromise=this.fileExplorer.refresh().then(()=>{if(this.fileExplorerReady=!0,this.isTabActive)return this.handleHashChange()})},bindEvents(){this.elements.emptyStateNewFileBtn?.addEventListener("click",()=>{this.fileExplorer.actionController.handleNewFile()}),this.elements.emptyStateSearchBtn?.addEventListener("click",()=>{this.toggleQuickSwitcher()}),this.elements.chatToggleButton?.addEventListener("click",()=>{this.toggleChatPanel()}),this.elements.chatForm?.addEventListener("submit",n=>{n.preventDefault(),this.handleChatSubmit()}),this.elements.chatNotificationButton?.addEventListener("click",()=>{this.handleChatNotificationToggle()}),this.elements.shareButton?.addEventListener("click",()=>{this.copyCurrentLink()}),this.elements.editNameButton?.addEventListener("click",()=>{this.openDisplayNameDialog()}),this.elements.displayNameCancel?.addEventListener("click",()=>{this.elements.displayNameDialog?.close()}),this.elements.gitCommitCancel?.addEventListener("click",()=>{this.elements.gitCommitDialog?.close()}),this.elements.gitResetCancel?.addEventListener("click",()=>{this.elements.gitResetDialog?.close()}),this.elements.gitResetSubmit?.addEventListener("click",()=>{this.handleGitResetSubmit()}),this.elements.gitCommitDialog?.addEventListener("close",()=>{this.elements.gitCommitInput&&(this.elements.gitCommitInput.value=""),this.elements.gitCommitSubmit&&(this.elements.gitCommitSubmit.textContent="Commit staged changes")}),this.elements.gitResetDialog?.addEventListener("close",()=>{this.pendingGitResetPath=null,this.elements.gitResetFileName&&(this.elements.gitResetFileName.value=""),this.elements.gitResetSubmit&&(this.elements.gitResetSubmit.textContent="Reset File")}),this.elements.markdownToolbar?.addEventListener("click",n=>{let t=(n.target instanceof Element?n.target.closest("[data-markdown-action]"):null)?.getAttribute("data-markdown-action");t&&this.applyMarkdownToolbarAction(t)}),this.elements.displayNameForm?.addEventListener("submit",n=>{n.preventDefault(),this.handleDisplayNameSubmit()}),this.elements.gitCommitForm?.addEventListener("submit",n=>{n.preventDefault(),this.handleGitCommitSubmit()}),this.elements.tabLockTakeoverButton?.addEventListener("click",()=>{this.handleTabTakeover()}),this.elements.toggleWrapButton?.addEventListener("click",()=>{this.toggleLineWrapping()}),this.elements.previewContent?.addEventListener("click",n=>{let e=n.target.closest("a.wiki-link[data-wiki-target]");e&&(n.preventDefault(),this.handleWikiLinkClick(e.dataset.wikiTarget))}),this.elements.sidebarToggle?.addEventListener("click",()=>{this.toggleSidebar()}),this.elements.sidebarClose?.addEventListener("click",()=>{this.closeSidebarOnMobile()}),this.elements.filesSidebarTab?.addEventListener("click",()=>{this.setSidebarTab("files")}),this.elements.gitSidebarTab?.addEventListener("click",()=>{this.gitRepoAvailable&&this.setSidebarTab("git")}),document.addEventListener("pointerdown",n=>{this.chatIsOpen&&(this.elements.chatContainer?.contains(n.target)||this.closeChatPanel())}),document.addEventListener("keydown",n=>{if(n.key==="Escape"&&this.chatIsOpen){this.closeChatPanel();return}(n.metaKey||n.ctrlKey)&&n.key==="k"&&(n.preventDefault(),this.toggleQuickSwitcher())})},isMobileViewport(){return this.mobileBreakpointQuery.matches},closeSidebarOnMobile(){let n=this.elements.sidebar;!n||!this.isMobileViewport()||n.classList.contains("collapsed")||this.setSidebarVisibility(!1)},toggleSidebar(){let n=this.elements.sidebar;if(!n)return;let e=n.classList.contains("collapsed");this.setSidebarVisibility(e)},restoreSidebarState(){if(!this.elements.sidebar)return;let e=this.isMobileViewport(),t=this.preferences.getSidebarVisible(),i=!0;t==="true"?i=!0:(t==="false"||e)&&(i=!1),this.applySidebarVisibility(i)},setSidebarVisibility(n){this.applySidebarVisibility(n),this.preferences.setSidebarVisible(n)},applySidebarVisibility(n){let e=this.elements.sidebar;if(!e)return;let t=!n,i=t&&this.isMobileViewport();e.classList.toggle("collapsed",t),e.toggleAttribute("hidden",i),e.setAttribute("aria-hidden",i?"true":"false"),e.inert=t},setSidebarTab(n){let e=n==="git"&&this.gitRepoAvailable?"git":"files";this.activeSidebarTab=e,this.elements.filesSidebarTab?.classList.toggle("active",e==="files"),this.elements.gitSidebarTab?.classList.toggle("active",e==="git"),document.getElementById("fileTree")?.classList.toggle("hidden",e!=="files"),this.elements.fileSearch?.classList.toggle("hidden",e!=="files"),this.elements.gitSearch?.classList.toggle("hidden",e!=="git"),document.getElementById("gitPanel")?.classList.toggle("active",e==="git"),document.getElementById("gitPanel")?.classList.toggle("hidden",e!=="git"),this.gitPanel.setActive(e==="git")},applyMarkdownToolbarAction(n){if(!this.session||!Z(this.currentFilePath))return;if(n==="image"){this.handleToolbarImageInsert();return}this.session.applyMarkdownToolbarAction(n)||this.toastController.show("Formatting action is unavailable")},async handleToolbarImageInsert(){let n=await this.pickImageFile();n&&await this.handleEditorImageInsert(n)},pickImageFile(){return new Promise(n=>{let e=document.createElement("input");e.type="file",e.accept=ln,e.style.position="fixed",e.style.left="-9999px",document.body.appendChild(e);let t=!1,i=null,s=a=>{t||(t=!0,i&&window.clearTimeout(i),window.removeEventListener("focus",r),e.remove(),n(a))},r=()=>{i=window.setTimeout(()=>{t||e.files?.length||s(null)},250)};e.addEventListener("change",()=>{s(e.files?.[0]??null)},{once:!0}),e.addEventListener("cancel",()=>{s(null)},{once:!0}),window.addEventListener("focus",r,{once:!0}),e.click()})},async handleEditorImageInsert(n){if(!this.session||!Z(this.currentFilePath))return console.warn("[ui] Ignoring image insert because there is no active markdown session.",{currentFilePath:this.currentFilePath,hasSession:!!this.session}),!1;let e=this.currentFilePath,t=this.session;try{console.debug("[ui] Uploading image attachment.",{fileName:n?.name||"",size:n?.size??null,sourcePath:e,type:n?.type||""});let i=await this.vaultApiClient.uploadImageAttachment({file:n,fileName:n?.name||"",sourcePath:e});return await this.fileExplorer.refresh(),this.currentFilePath===e&&this.session&&this.session===t&&typeof i?.markdown=="string"&&(console.debug("[ui] Inserting uploaded image markdown into the editor.",{sourcePath:e,storedPath:i.path??""}),this.session.insertText(i.markdown)),!0}catch(i){return console.error("[ui] Failed to insert image attachment:",i),this.toastController.show(i.message||"Failed to upload image"),!1}},handleThemeChange(n){this.previewRenderer.applyTheme(n),!this.isExcalidrawFile(this.currentFilePath)&&!this.isImageFile?.(this.currentFilePath)&&this.previewRenderer.queueRender(),this.session?.applyTheme(n),this.excalidrawEmbed.updateTheme(n)},handleConnectionChange(n){this.connectionState=n,this.renderPresence(),n.unreachable&&!this.connectionHelpShown&&(this.connectionHelpShown=!0,this.toastController.show(`Cannot reach server at ${n.wsBaseUrl}`,6e3))},openDisplayNameDialog({mode:n="edit"}={}){if(!this.isTabActive)return;let e=this.elements.displayNameDialog,t=this.elements.displayNameInput,i=this.elements.displayNameTitle,s=this.elements.displayNameCopy,r=this.elements.displayNameCancel,a=this.elements.displayNameSubmit;if(!e||!t)return;let o=n==="onboarding";i&&(i.textContent=o?"Choose your display name":"Update display name"),s&&(s.textContent=o?"Pick a name collaborators will see. You can skip for now and continue as a guest.":"Your name will be visible to everyone editing this vault."),r&&(r.textContent=o?"Skip for now":"Cancel"),a&&(a.textContent=o?"Continue":"Save name"),t.value=o?"":this.getCurrentUserName(),!e.open&&(typeof e.showModal=="function"?e.showModal():e.setAttribute("open","true"),requestAnimationFrame(()=>{t.focus(),t.select()}))},promptForDisplayNameIfNeeded(){!this.isTabActive||this._hasPromptedForDisplayName||this.getStoredUserName()||(this._hasPromptedForDisplayName=!0,requestAnimationFrame(()=>{this.openDisplayNameDialog({mode:"onboarding"})}))},handleDisplayNameSubmit(){let n=this.elements.displayNameInput,e=this.elements.displayNameDialog;if(!n||!e)return;let t=this.session?this.session.setUserName(n.value):Kt(n.value);if(!t){n.focus(),this.toastController.show(`Name must be 1-${24} characters`);return}this.preferences.setUserName(t),this.lobby.setUserName(t),this.excalidrawEmbed.updateLocalUser(this.lobby.getLocalUser()),this.syncCurrentUserName(),this.renderChat(),e.close()},async copyCurrentLink(){try{await navigator.clipboard.writeText(window.location.href),this.toastController.show("Link copied")}catch{this.toastController.show("Failed to copy link")}},getCurrentUser(){return this.globalUsers.find(n=>n.isLocal)??this.session?.getLocalUser()??this.lobby?.getLocalUser()??null},getCurrentUserName(){return this.getCurrentUser()?.name??this.getStoredUserName()??""},getStoredUserName(){return this.preferences.getUserName()},syncCurrentUserName(){let n=this.elements.currentUserName;if(!n)return;let e=this.getCurrentUserName();n.textContent=e||"Set name",n.classList.toggle("has-name",!!e),this.elements.editNameButton?.setAttribute("aria-label",`${e||"Set name"}. Change display name`)},toggleLineWrapping(){let e=!(this.session?.isLineWrappingEnabled()??this.getStoredLineWrapping());this.session?.setLineWrapping(e),this.preferences.setLineWrappingEnabled(e),this.syncWrapToggle(e),this.session?.requestMeasure(),this.scrollSyncController.syncPreviewToEditor()},getStoredLineWrapping(){return this.preferences.getLineWrappingEnabled()},handleTabTakeover(){this.tabActivityLock.tryActivate({takeover:!0})},handleTabActivated({takeover:n=!1}={}){let e=!this.isTabActive;this.isTabActive=!0,this.hideTabLockOverlay(),this.lobby.provider||this.lobby.connect(),this.workspaceSync.provider||this.workspaceSync.connect(),e&&(this.fileExplorerReady&&this.handleHashChange(),this.promptForDisplayNameIfNeeded()),n&&this.toastController.show("This tab is now active")},handleTabBlocked({reason:n}={}){let e=this.isTabActive;this.isTabActive=!1,this.elements.displayNameDialog?.open&&this.elements.displayNameDialog.close(),this.lobby.disconnect(),this.workspaceSync.disconnect(),this.globalUsers=[],this.chatMessages=[],this.chatMessageIds.clear(),this.chatUnreadCount=0,this.chatInitialSyncComplete=!1,this.followedUserClientId=null,this.followedCursorSignature="",this.connectionState={status:"disconnected",unreachable:!1},this.showEmptyState(),this.renderChat(),this.showTabLockOverlay({reason:n}),e&&n==="taken-over"&&this.toastController.show("Another tab took over this session")},showTabLockOverlay({reason:n}={}){let e=this.elements.tabLockOverlay,t=this.elements.tabLockTitle,i=this.elements.tabLockCopy;e&&(t&&(t.textContent=n==="taken-over"?"This tab is no longer active":"This vault is active in another tab"),i&&(i.textContent=n==="taken-over"?"Another tab took over the live session. This tab is now disconnected until you explicitly take over here again.":"To avoid duplicate presence and chat, only one tab can stay connected at a time. Use the other tab, or take over the session here."),e.classList.remove("hidden"))},hideTabLockOverlay(){this.elements.tabLockOverlay?.classList.add("hidden")},syncWrapToggle(n){let e=n??this.session?.isLineWrappingEnabled()??this.getStoredLineWrapping(),t=this.elements.wrapToggleLabel,i=this.elements.toggleWrapButton,s=e?"Wrap on":"Wrap off";t&&(t.textContent=s),i&&i.setAttribute("aria-label",`${s}. ${e?"Disable line wrap":"Enable line wrap"}`)},scheduleBacklinkRefresh(){clearTimeout(this._backlinkRefreshTimer),this._backlinkRefreshTimer=setTimeout(()=>{ve(this.currentFilePath)&&this.backlinksPanel.load(this.currentFilePath)},2e3)},showEditorLoading(){this.elements.editorContainer&&(this.elements.editorContainer.classList.add("is-loading-editor"),this.elements.editorContainer.innerHTML=`
|
|
30
30
|
<div class="editor-loading" id="editorLoading">
|
|
31
31
|
<div class="loading-spinner"></div>
|
|
32
32
|
<span class="loading-text">Loading file...</span>
|
|
33
33
|
</div>`)},hideEditorLoading(){this.elements.editorContainer&&(this.elements.editorContainer.classList.remove("is-loading-editor"),this.elements.editorContainer.querySelector("#editorLoading")?.remove())},showEditorLoadError(){this.elements.editorContainer&&(this.elements.editorContainer.classList.remove("is-loading-editor"),this.elements.editorContainer.innerHTML=`
|
|
34
34
|
<div class="editor-loading" id="editorLoading">
|
|
35
35
|
<span class="loading-text">Failed to load file</span>
|
|
36
|
-
</div>`)},clearInitialFileBootstrap(){document.documentElement.removeAttribute("data-initial-file-requested")}};var oi={isExcalidrawFile(n){return At(n)},isImageFile(n){return we(n)},isMermaidFile(n){return fe(n)},isPlantUmlFile(n){return ge(n)},createDiagramPreviewDocument(n,e=""){return this.workspacePreviewController.createDiagramPreviewDocument(n,e)},getPreviewSource(){return this.workspacePreviewController.getPreviewSource(this.currentFilePath)},getDisplayName(n){return q(String(n??"").split("/").pop())},resetPreviewMode(){this.workspacePreviewController.resetPreviewMode()},syncFileChrome(n){this.workspacePreviewController.syncFileChrome(n)},renderExcalidrawFilePreview(n){this.workspacePreviewController.renderExcalidrawFilePreview(n)},renderImageFilePreview(n){this.workspacePreviewController.renderImageFilePreview(n)},createResizeHandler(){return this.workspacePreviewController.createResizeHandler(()=>this.restoreSidebarState())},initializePreviewLayoutObserver(){this._previewLayoutResizeObserver?.disconnect(),this._previewLayoutResizeObserver=this.workspacePreviewController.initializePreviewLayoutObserver(()=>this.schedulePreviewLayoutSync())},schedulePreviewLayoutSync({delayMs:n=120}={}){this.workspacePreviewController.schedulePreviewLayoutSync({delayMs:n,hydrationPaused:this._previewHydrationPaused,previewLayoutSyncTimer:this._previewLayoutSyncTimer,setPendingPreviewLayoutSync:e=>{this._pendingPreviewLayoutSync=e},setPreviewLayoutSyncTimer:e=>{this._previewLayoutSyncTimer=e}})},handleEditorScrollActivityChange(n){this.workspacePreviewController.handleEditorScrollActivityChange({isActive:n,pendingPreviewLayoutSync:this._pendingPreviewLayoutSync,previewLayoutSyncTimer:this._previewLayoutSyncTimer,setHydrationPaused:e=>{this._previewHydrationPaused=e},setPendingPreviewLayoutSync:e=>{this._pendingPreviewLayoutSync=e},setPreviewLayoutSyncTimer:e=>{this._previewLayoutSyncTimer=e}})},async handleHashChange(){await this.workspaceRouteController.handleHashChange()},showEmptyState(){clearTimeout(this._previewLayoutSyncTimer),this._previewLayoutSyncTimer=null,this._pendingPreviewLayoutSync=!1,this._previewHydrationPaused=!1,this.workspaceRouteController.showEmptyState()},showDiffState(){clearTimeout(this._previewLayoutSyncTimer),this._previewLayoutSyncTimer=null,this._pendingPreviewLayoutSync=!1,this._previewHydrationPaused=!1,this.workspaceRouteController.showDiffState()},async openFile(n){await this.workspaceRouteController.openFile(n)},cleanupSession(){this.workspaceRouteController.cleanupSession()},handleWikiLinkClick(n){this.wikiLinkFileController.handleWikiLinkClick(n)},normalizeNewWikiFilePath(n){return this.wikiLinkFileController.normalizeNewWikiFilePath(n)},async createAndOpenFile(n,e){await this.wikiLinkFileController.createAndOpenFile(n,e)},handleFileSelection(n,{closeSidebarOnMobile:e=!1}={}){this.workspaceRouteController.handleFileSelection(n,{closeSidebarOnMobile:e})}};var Vi="__lobby__",gt=280,li=40;function Ki(n){return String(n??"").replace(/\s+/g," ").trim().slice(0,gt)||null}function ci(n){return globalThis.crypto?.randomUUID?globalThis.crypto.randomUUID():`${n||"user"}-${Date.now()}-${Math.random().toString(36).slice(2,10)}`}function ft(n){if(!n||typeof n!="object"||typeof n.id!="string")return null;let e=n.workspaceChange&&typeof n.workspaceChange=="object"?n.workspaceChange:{};return{action:typeof n.action=="string"?n.action:"git",createdAt:Number.isFinite(n.createdAt)?n.createdAt:Date.now(),id:n.id,peerId:typeof n.peerId=="string"?n.peerId:null,sourceRef:typeof n.sourceRef=="string"?n.sourceRef:null,workspaceChange:{changedPaths:Array.isArray(e.changedPaths)?e.changedPaths.filter(Boolean):[],deletedPaths:Array.isArray(e.deletedPaths)?e.deletedPaths.filter(Boolean):[],refreshExplorer:e.refreshExplorer!==!1,renamedPaths:Array.isArray(e.renamedPaths)?e.renamedPaths.filter(t=>t?.oldPath&&t?.newPath):[]}}}var Ne=class{constructor({preferredUserName:e,onChange:t,onChatChange:i,onWorkspaceEvent:s}){this.onChange=t,this.onChatChange=i,this.onWorkspaceEvent=s,this.wsBaseUrl=xt(),this.ydoc=new Dt,this.chatMessages=this.ydoc.getArray("chat-messages"),this.workspaceEvents=this.ydoc.getArray("workspace-events"),this.provider=null,this.awareness=null,this.localUser=Ht(e),this.currentFile=null,this._connected=!1,this._didInitialSync=!1,this.seenWorkspaceEventIds=new Set,this.handleAwarenessChange=()=>{this._emitChange()},this.handleChatMessagesChange=()=>{this._emitChatChange()},this.handleWorkspaceEventsChange=()=>{this._emitWorkspaceEvents()}}connect(){this.provider||(this._didInitialSync=!1,this.provider=new _t(this.wsBaseUrl,Vi,this.ydoc,{disableBc:!0,maxBackoffTime:5e3}),Ot(this.provider),this.awareness=this.provider.awareness,this.awareness.setLocalStateField("user",this.localUser),this.awareness.setLocalStateField("currentFile",this.currentFile),this.awareness.on("change",this.handleAwarenessChange),this.chatMessages.observe(this.handleChatMessagesChange),this.workspaceEvents.observe(this.handleWorkspaceEventsChange),this.provider.on("status",({status:e})=>{this._connected=e==="connected"}),this.provider.on("sync",e=>{!e||this._didInitialSync||(this._didInitialSync=!0,this._primeWorkspaceEventCache(),this._emitChange(),this._emitChatChange({initial:!0}))}))}setCurrentFile(e){this.currentFile=e,this.awareness&&this.awareness.setLocalStateField("currentFile",e)}setUserName(e){e&&(this.localUser={...this.localUser,name:e},this.awareness&&this.awareness.setLocalStateField("user",this.localUser))}getLocalUser(){return this.localUser}sendChatMessage(e){let t=Ki(e);if(!t)return null;let i={createdAt:Date.now(),filePath:this.currentFile??null,id:ci(this.localUser.peerId),peerId:this.localUser.peerId,text:t,userColor:this.localUser.color,userName:this.localUser.name};return this.ydoc.transact(()=>{this.chatMessages.push([i]);let s=this.chatMessages.length-li;s>0&&this.chatMessages.delete(0,s)},"lobby-chat-message"),i}sendWorkspaceEvent({action:e="git",sourceRef:t=null,workspaceChange:i={}}={}){let s=ft({action:e,createdAt:Date.now(),id:ci(this.localUser.peerId),peerId:this.localUser.peerId,sourceRef:t,workspaceChange:i});return s?(this.ydoc.transact(()=>{this.workspaceEvents.push([s]);let r=this.workspaceEvents.length-li;r>0&&this.workspaceEvents.delete(0,r)},"lobby-workspace-event"),this.seenWorkspaceEventIds.add(s.id),s):null}getMessages(){return this.chatMessages.toArray().filter(e=>e&&typeof e.id=="string"&&typeof e.peerId=="string"&&typeof e.text=="string"&&typeof e.userName=="string")}getUsers(){if(!this.awareness)return[];let e=[];return this.awareness.getStates().forEach((t,i)=>{t.user&&e.push({...t.user,clientId:i,currentFile:t.currentFile??null,isLocal:i===this.awareness.clientID})}),e}getConnectionState(){return this._connected?{status:"connected",unreachable:!1}:this.provider?{status:"connecting",unreachable:!1}:{status:"disconnected",unreachable:!1}}disconnect(){this.provider&&(this.awareness?.off("change",this.handleAwarenessChange),this.chatMessages?.unobserve(this.handleChatMessagesChange),this.workspaceEvents?.unobserve(this.handleWorkspaceEventsChange)),this.provider?.disconnect(),this.provider?.destroy(),this.provider=null,this.awareness=null,this._connected=!1,this._didInitialSync=!1,this.seenWorkspaceEventIds.clear()}destroy(){this.disconnect(),this.ydoc?.destroy(),this.ydoc=null}_emitChange(){this.onChange?.(this.getUsers())}_emitChatChange(e={}){this.onChatChange?.(this.getMessages(),e)}_primeWorkspaceEventCache(){this.workspaceEvents.toArray().forEach(e=>{let t=ft(e);t&&this.seenWorkspaceEventIds.add(t.id)})}_emitWorkspaceEvents(){if(!this._didInitialSync){this._primeWorkspaceEventCache();return}this.workspaceEvents.toArray().forEach(e=>{let t=ft(e);!t||this.seenWorkspaceEventIds.has(t.id)||(this.seenWorkspaceEventIds.add(t.id),t.peerId!==this.localUser.peerId&&this.onWorkspaceEvent?.(t))})}};var He=class{getHashRoute(){return zt()}navigateToFile(e){Ut(e)}navigateToGitDiff(e){$t(e)}};var De=class{constructor({NotificationImpl:e=globalThis.Notification,focusWindow:t=()=>globalThis.window?.focus?.()}={}){this.NotificationImpl=e,this.focusWindow=t}getPermission(){return typeof this.NotificationImpl!="function"?"unsupported":this.NotificationImpl.permission}async requestPermission(){return typeof this.NotificationImpl!="function"?"unsupported":this.NotificationImpl.requestPermission()}createNotification({body:e,onClick:t,tag:i,title:s}){if(typeof this.NotificationImpl!="function")return null;let r=new this.NotificationImpl(s,{body:e,tag:i});return typeof t=="function"&&r.addEventListener("click",()=>{this.focusWindow(),t()}),r}};var _e=class{constructor({chatNotificationsKey:e,lineWrappingKey:t,sidebarVisibleKey:i,userNameKey:s,storage:r=globalThis.localStorage}){this.chatNotificationsKey=e,this.lineWrappingKey=t,this.sidebarVisibleKey=i,this.storage=r,this.userNameKey=s}getUserName(){try{return this.storage.getItem(this.userNameKey)||""}catch{return""}}setUserName(e){try{this.storage.setItem(this.userNameKey,e)}catch{}}getLineWrappingEnabled(){try{return this.storage.getItem(this.lineWrappingKey)!=="false"}catch{return!0}}setLineWrappingEnabled(e){try{this.storage.setItem(this.lineWrappingKey,String(e))}catch{}}getSidebarVisible(){try{return this.storage.getItem(this.sidebarVisibleKey)}catch{return null}}setSidebarVisible(e){try{this.storage.setItem(this.sidebarVisibleKey,e?"true":"false")}catch{}}getChatNotificationsEnabled(){try{return this.storage.getItem(this.chatNotificationsKey)==="true"}catch{return!1}}setChatNotificationsEnabled(e){try{this.storage.setItem(this.chatNotificationsKey,String(e))}catch{}}};var ze="collabmd-active-tab-lock",hi="collabmd-tab-id",Gi="collabmd-tab-lock";function wt(){return Date.now()}function di(){return globalThis.crypto?.randomUUID?globalThis.crypto.randomUUID():`tab-${wt()}-${Math.random().toString(36).slice(2,10)}`}function ui(n){if(!n)return null;try{return JSON.parse(n)}catch{return null}}var Ue=class{constructor({heartbeatIntervalMs:e=4e3,onBlocked:t,onActivated:i,onStolen:s}={}){this.heartbeatIntervalMs=e,this.staleAfterMs=e*3,this.onBlocked=t,this.onActivated=i,this.onStolen=s,this.tabId=this.getOrCreateTabId(),this.channel=null,this.heartbeatTimer=null,this.isOwner=!1,this.handleStorageEvent=this.handleStorageEvent.bind(this),this.handlePageHide=this.handlePageHide.bind(this)}initialize(){window.addEventListener("storage",this.handleStorageEvent),window.addEventListener("pagehide",this.handlePageHide),"BroadcastChannel"in globalThis&&(this.channel=new BroadcastChannel(Gi),this.channel.addEventListener("message",e=>{this.handleChannelMessage(e.data)}))}destroy(){this.release(),window.removeEventListener("storage",this.handleStorageEvent),window.removeEventListener("pagehide",this.handlePageHide),this.channel?.close(),this.channel=null}tryActivate({takeover:e=!1}={}){let t=this.readLock();return this.isFreshLock(t)&&t.tabId!==this.tabId&&!e?(this.isOwner=!1,this.stopHeartbeat(),this.onBlocked?.({reason:"active-elsewhere",ownerTabId:t.tabId}),!1):(this.writeLock(),this.startHeartbeat(),this.isOwner=!0,this.channel?.postMessage({type:"claimed",takeover:e,tabId:this.tabId}),this.onActivated?.({takeover:e}),!0)}release(){this.readLock()?.tabId===this.tabId&&(localStorage.removeItem(ze),this.channel?.postMessage({type:"released",tabId:this.tabId})),this.isOwner=!1,this.stopHeartbeat()}getOrCreateTabId(){try{let e=window.sessionStorage.getItem(hi);if(e)return e;let t=di();return window.sessionStorage.setItem(hi,t),t}catch{return di()}}readLock(){try{return ui(window.localStorage.getItem(ze))}catch{return null}}isFreshLock(e){return!!(e&&typeof e.tabId=="string"&&Number.isFinite(e.updatedAt)&&wt()-e.updatedAt<this.staleAfterMs)}writeLock(){try{window.localStorage.setItem(ze,JSON.stringify({tabId:this.tabId,updatedAt:wt()}))}catch{}}startHeartbeat(){this.stopHeartbeat(),this.writeLock(),this.heartbeatTimer=window.setInterval(()=>{if(!this.isOwner){this.stopHeartbeat();return}this.writeLock()},this.heartbeatIntervalMs)}stopHeartbeat(){this.heartbeatTimer&&(window.clearInterval(this.heartbeatTimer),this.heartbeatTimer=null)}handleStorageEvent(e){if(e.key!==ze)return;let t=ui(e.newValue);this.handleExternalLockChange(t)}handleChannelMessage(e){!e||typeof e!="object"||e.tabId===this.tabId||e.type==="claimed"&&this.handleExternalLockChange(this.readLock())}handleExternalLockChange(e){this.isOwner&&this.isFreshLock(e)&&e.tabId!==this.tabId&&(this.isOwner=!1,this.stopHeartbeat(),this.onStolen?.({ownerTabId:e.tabId}))}handlePageHide(){this.release()}};function mi(n){return encodeURIComponent(String(n??""))}async function J(n,e){let t=await n.json().catch(()=>({}));if(!n.ok||t.ok===!1){let i=new Error(t.error||e);throw i.status=n.status,i.body=t,i}return t}var $e=class{async readTree(){let e=await fetch(b("/files"));return J(e,"Failed to load file tree")}async readFile(e){let t=await fetch(b(`/file?path=${encodeURIComponent(e)}`));return J(t,"Failed to read file")}async createFile({content:e,path:t}){let i=await fetch(b("/file"),{body:JSON.stringify({content:e,path:t}),headers:{"Content-Type":"application/json"},method:"POST"});return J(i,"Failed to create file")}async renameFile({oldPath:e,newPath:t}){let i=await fetch(b("/file"),{body:JSON.stringify({newPath:t,oldPath:e}),headers:{"Content-Type":"application/json"},method:"PATCH"});return J(i,"Failed to rename file")}async deleteFile(e){let t=await fetch(b(`/file?path=${encodeURIComponent(e)}`),{method:"DELETE"});return J(t,"Failed to delete file")}async createDirectory(e){let t=await fetch(b("/directory"),{body:JSON.stringify({path:e}),headers:{"Content-Type":"application/json"},method:"POST"});return J(t,"Failed to create folder")}async uploadImageAttachment({file:e,fileName:t="",sourcePath:i}){let s=await fetch(b("/attachments"),{body:e,headers:{"Content-Type":e?.type||"application/octet-stream","X-CollabMD-File-Name":mi(t),"X-CollabMD-Source-Path":mi(i)},method:"POST"});return J(s,"Failed to upload image")}},he=new $e;var Oe=class{constructor({panelElement:e,onFileSelect:t}){this.panel=e,this.onFileSelect=t,this.header=this.panel?.querySelector(".backlinks-header"),this.toggle=this.panel?.querySelector(".backlinks-toggle"),this.countBadge=this.panel?.querySelector(".backlinks-count"),this.body=this.panel?.querySelector(".backlinks-body"),this.list=this.panel?.querySelector(".backlinks-list"),this._expanded=!1,this._currentFile=null,this._fetchController=null,this._backlinks=[],this.bindEvents()}bindEvents(){this.header?.addEventListener("click",()=>{this._backlinks.length!==0&&(this._expanded=!this._expanded,this._applyExpandState())}),this.header?.addEventListener("keydown",e=>{e.key!=="Enter"&&e.key!==" "||(e.preventDefault(),this.header.click())})}async load(e){if(this._currentFile=e,!e){this._backlinks=[],this._render();return}this._fetchController?.abort(),this._fetchController=new AbortController;try{let i=await(await fetch(b(`/backlinks?file=${encodeURIComponent(e)}`),{signal:this._fetchController.signal})).json();if(this._currentFile!==e)return;this._backlinks=i.backlinks??[]}catch(t){if(t.name==="AbortError")return;console.warn("[backlinks] Failed to load:",t.message),this._backlinks=[]}this._render()}clear(){this._currentFile=null,this._backlinks=[],this._expanded=!1,this._render()}_render(){if(!this.panel)return;let e=this._backlinks.length,t=e===1?"1 Linked Mention":`${e} Linked Mentions`;if(this.countBadge&&(this.countBadge.textContent=e>0?String(e):""),this.toggle&&(this.toggle.textContent=t),this.panel.classList.toggle("hidden",!this._currentFile),this.header?.classList.toggle("backlinks-header-empty",e===0),e===0){this._expanded=!1,this._applyExpandState(),this.list&&(this.list.innerHTML="");return}this._renderList(),this._applyExpandState()}_renderList(){if(!this.list)return;this.list.innerHTML="";let e=document.createDocumentFragment();for(let t of this._backlinks){let i=t.file.replace(/\.md$/i,"").split("/").pop(),s=t.file.includes("/")?t.file.substring(0,t.file.lastIndexOf("/")):"",r=document.createElement("button");r.type="button",r.className="backlink-item",r.addEventListener("click",()=>{this.onFileSelect?.(t.file)});let a=document.createElement("div");a.className="backlink-file-name",a.innerHTML=`
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
36
|
+
</div>`)},clearInitialFileBootstrap(){document.documentElement.removeAttribute("data-initial-file-requested")}};var gi={isExcalidrawFile(n){return qt(n)},isImageFile(n){return ye(n)},isMermaidFile(n){return ge(n)},isPlantUmlFile(n){return we(n)},createDiagramPreviewDocument(n,e=""){return this.workspacePreviewController.createDiagramPreviewDocument(n,e)},getPreviewSource(){return this.workspacePreviewController.getPreviewSource(this.currentFilePath)},getDisplayName(n){return q(String(n??"").split("/").pop())},resetPreviewMode(){this.workspacePreviewController.resetPreviewMode()},syncFileChrome(n){this.workspacePreviewController.syncFileChrome(n)},renderExcalidrawFilePreview(n){this.workspacePreviewController.renderExcalidrawFilePreview(n)},renderImageFilePreview(n){this.workspacePreviewController.renderImageFilePreview(n)},createResizeHandler(){return this.workspacePreviewController.createResizeHandler(()=>this.restoreSidebarState())},initializePreviewLayoutObserver(){this._previewLayoutResizeObserver?.disconnect(),this._previewLayoutResizeObserver=this.workspacePreviewController.initializePreviewLayoutObserver(()=>this.schedulePreviewLayoutSync())},schedulePreviewLayoutSync({delayMs:n=120}={}){this.workspacePreviewController.schedulePreviewLayoutSync({delayMs:n,hydrationPaused:this._previewHydrationPaused,previewLayoutSyncTimer:this._previewLayoutSyncTimer,setPendingPreviewLayoutSync:e=>{this._pendingPreviewLayoutSync=e},setPreviewLayoutSyncTimer:e=>{this._previewLayoutSyncTimer=e}})},handleEditorScrollActivityChange(n){this.workspacePreviewController.handleEditorScrollActivityChange({isActive:n,pendingPreviewLayoutSync:this._pendingPreviewLayoutSync,previewLayoutSyncTimer:this._previewLayoutSyncTimer,setHydrationPaused:e=>{this._previewHydrationPaused=e},setPendingPreviewLayoutSync:e=>{this._pendingPreviewLayoutSync=e},setPreviewLayoutSyncTimer:e=>{this._previewLayoutSyncTimer=e}})},async handleHashChange(){await this.workspaceRouteController.handleHashChange()},showEmptyState(){clearTimeout(this._previewLayoutSyncTimer),this._previewLayoutSyncTimer=null,this._pendingPreviewLayoutSync=!1,this._previewHydrationPaused=!1,this.workspaceRouteController.showEmptyState()},showDiffState(){clearTimeout(this._previewLayoutSyncTimer),this._previewLayoutSyncTimer=null,this._pendingPreviewLayoutSync=!1,this._previewHydrationPaused=!1,this.workspaceRouteController.showDiffState()},async openFile(n){await this.workspaceRouteController.openFile(n)},cleanupSession(){this.workspaceRouteController.cleanupSession()},handleWikiLinkClick(n){this.wikiLinkFileController.handleWikiLinkClick(n)},normalizeNewWikiFilePath(n){return this.wikiLinkFileController.normalizeNewWikiFilePath(n)},async createAndOpenFile(n,e){await this.wikiLinkFileController.createAndOpenFile(n,e)},handleFileSelection(n,{closeSidebarOnMobile:e=!1}={}){this.workspaceRouteController.handleFileSelection(n,{closeSidebarOnMobile:e})}};var hn="__lobby__",Lt=280,wi=40;function dn(n){return String(n??"").replace(/\s+/g," ").trim().slice(0,Lt)||null}function yi(n){return globalThis.crypto?.randomUUID?globalThis.crypto.randomUUID():`${n||"user"}-${Date.now()}-${Math.random().toString(36).slice(2,10)}`}function Pt(n){if(!n||typeof n!="object"||typeof n.id!="string")return null;let e=n.workspaceChange&&typeof n.workspaceChange=="object"?n.workspaceChange:{};return{action:typeof n.action=="string"?n.action:"git",createdAt:Number.isFinite(n.createdAt)?n.createdAt:Date.now(),id:n.id,peerId:typeof n.peerId=="string"?n.peerId:null,sourceRef:typeof n.sourceRef=="string"?n.sourceRef:null,workspaceChange:{changedPaths:Array.isArray(e.changedPaths)?e.changedPaths.filter(Boolean):[],deletedPaths:Array.isArray(e.deletedPaths)?e.deletedPaths.filter(Boolean):[],refreshExplorer:e.refreshExplorer!==!1,renamedPaths:Array.isArray(e.renamedPaths)?e.renamedPaths.filter(t=>t?.oldPath&&t?.newPath):[]}}}var ze=class{constructor({preferredUserName:e,onChange:t,onChatChange:i,onWorkspaceEvent:s}){this.onChange=t,this.onChatChange=i,this.onWorkspaceEvent=s,this.wsBaseUrl=pe(),this.ydoc=new Ce,this.chatMessages=this.ydoc.getArray("chat-messages"),this.workspaceEvents=this.ydoc.getArray("workspace-events"),this.provider=null,this.awareness=null,this.localUser=jt(e),this.currentFile=null,this._connected=!1,this._didInitialSync=!1,this.seenWorkspaceEventIds=new Set,this.handleAwarenessChange=()=>{this._emitChange()},this.handleChatMessagesChange=()=>{this._emitChatChange()},this.handleWorkspaceEventsChange=()=>{this._emitWorkspaceEvents()}}connect(){this.provider||(this._didInitialSync=!1,this.provider=new Ee(this.wsBaseUrl,hn,this.ydoc,{disableBc:!0,maxBackoffTime:5e3}),ke(this.provider),this.awareness=this.provider.awareness,this.awareness.setLocalStateField("user",this.localUser),this.awareness.setLocalStateField("currentFile",this.currentFile),this.awareness.on("change",this.handleAwarenessChange),this.chatMessages.observe(this.handleChatMessagesChange),this.workspaceEvents.observe(this.handleWorkspaceEventsChange),this.provider.on("status",({status:e})=>{this._connected=e==="connected"}),this.provider.on("sync",e=>{!e||this._didInitialSync||(this._didInitialSync=!0,this._primeWorkspaceEventCache(),this._emitChange(),this._emitChatChange({initial:!0}))}))}setCurrentFile(e){this.currentFile=e,this.awareness&&this.awareness.setLocalStateField("currentFile",e)}setUserName(e){e&&(this.localUser={...this.localUser,name:e},this.awareness&&this.awareness.setLocalStateField("user",this.localUser))}getLocalUser(){return this.localUser}sendChatMessage(e){let t=dn(e);if(!t)return null;let i={createdAt:Date.now(),filePath:this.currentFile??null,id:yi(this.localUser.peerId),peerId:this.localUser.peerId,text:t,userColor:this.localUser.color,userName:this.localUser.name};return this.ydoc.transact(()=>{this.chatMessages.push([i]);let s=this.chatMessages.length-wi;s>0&&this.chatMessages.delete(0,s)},"lobby-chat-message"),i}sendWorkspaceEvent({action:e="git",sourceRef:t=null,workspaceChange:i={}}={}){let s=Pt({action:e,createdAt:Date.now(),id:yi(this.localUser.peerId),peerId:this.localUser.peerId,sourceRef:t,workspaceChange:i});return s?(this.ydoc.transact(()=>{this.workspaceEvents.push([s]);let r=this.workspaceEvents.length-wi;r>0&&this.workspaceEvents.delete(0,r)},"lobby-workspace-event"),this.seenWorkspaceEventIds.add(s.id),s):null}getMessages(){return this.chatMessages.toArray().filter(e=>e&&typeof e.id=="string"&&typeof e.peerId=="string"&&typeof e.text=="string"&&typeof e.userName=="string")}getUsers(){if(!this.awareness)return[];let e=[];return this.awareness.getStates().forEach((t,i)=>{t.user&&e.push({...t.user,clientId:i,currentFile:t.currentFile??null,isLocal:i===this.awareness.clientID})}),e}getConnectionState(){return this._connected?{status:"connected",unreachable:!1}:this.provider?{status:"connecting",unreachable:!1}:{status:"disconnected",unreachable:!1}}disconnect(){this.provider&&(this.awareness?.off("change",this.handleAwarenessChange),this.chatMessages?.unobserve(this.handleChatMessagesChange),this.workspaceEvents?.unobserve(this.handleWorkspaceEventsChange)),this.provider?.disconnect(),this.provider?.destroy(),this.provider=null,this.awareness=null,this._connected=!1,this._didInitialSync=!1,this.seenWorkspaceEventIds.clear()}destroy(){this.disconnect(),this.ydoc?.destroy(),this.ydoc=null}_emitChange(){this.onChange?.(this.getUsers())}_emitChatChange(e={}){this.onChatChange?.(this.getMessages(),e)}_primeWorkspaceEventCache(){this.workspaceEvents.toArray().forEach(e=>{let t=Pt(e);t&&this.seenWorkspaceEventIds.add(t.id)})}_emitWorkspaceEvents(){if(!this._didInitialSync){this._primeWorkspaceEventCache();return}this.workspaceEvents.toArray().forEach(e=>{let t=Pt(e);!t||this.seenWorkspaceEventIds.has(t.id)||(this.seenWorkspaceEventIds.add(t.id),t.peerId!==this.localUser.peerId&&this.onWorkspaceEvent?.(t))})}};var Ue=class{getHashRoute(){return Qt()}navigateToFile(e){Yt(e)}navigateToGitDiff(e){Zt(e)}};var $e=class{constructor({NotificationImpl:e=globalThis.Notification,focusWindow:t=()=>globalThis.window?.focus?.()}={}){this.NotificationImpl=e,this.focusWindow=t}getPermission(){return typeof this.NotificationImpl!="function"?"unsupported":this.NotificationImpl.permission}async requestPermission(){return typeof this.NotificationImpl!="function"?"unsupported":this.NotificationImpl.requestPermission()}createNotification({body:e,onClick:t,tag:i,title:s}){if(typeof this.NotificationImpl!="function")return null;let r=new this.NotificationImpl(s,{body:e,tag:i});return typeof t=="function"&&r.addEventListener("click",()=>{this.focusWindow(),t()}),r}};var Oe=class{constructor({chatNotificationsKey:e,lineWrappingKey:t,sidebarVisibleKey:i,userNameKey:s,storage:r=globalThis.localStorage}){this.chatNotificationsKey=e,this.lineWrappingKey=t,this.sidebarVisibleKey=i,this.storage=r,this.userNameKey=s}getUserName(){try{return this.storage.getItem(this.userNameKey)||""}catch{return""}}setUserName(e){try{this.storage.setItem(this.userNameKey,e)}catch{}}getLineWrappingEnabled(){try{return this.storage.getItem(this.lineWrappingKey)!=="false"}catch{return!0}}setLineWrappingEnabled(e){try{this.storage.setItem(this.lineWrappingKey,String(e))}catch{}}getSidebarVisible(){try{return this.storage.getItem(this.sidebarVisibleKey)}catch{return null}}setSidebarVisible(e){try{this.storage.setItem(this.sidebarVisibleKey,e?"true":"false")}catch{}}getChatNotificationsEnabled(){try{return this.storage.getItem(this.chatNotificationsKey)==="true"}catch{return!1}}setChatNotificationsEnabled(e){try{this.storage.setItem(this.chatNotificationsKey,String(e))}catch{}}};var qe="collabmd-active-tab-lock",vi="collabmd-tab-id",un="collabmd-tab-lock";function xt(){return Date.now()}function bi(){return globalThis.crypto?.randomUUID?globalThis.crypto.randomUUID():`tab-${xt()}-${Math.random().toString(36).slice(2,10)}`}function Ci(n){if(!n)return null;try{return JSON.parse(n)}catch{return null}}var We=class{constructor({heartbeatIntervalMs:e=4e3,onBlocked:t,onActivated:i,onStolen:s}={}){this.heartbeatIntervalMs=e,this.staleAfterMs=e*3,this.onBlocked=t,this.onActivated=i,this.onStolen=s,this.tabId=this.getOrCreateTabId(),this.channel=null,this.heartbeatTimer=null,this.isOwner=!1,this.handleStorageEvent=this.handleStorageEvent.bind(this),this.handlePageHide=this.handlePageHide.bind(this)}initialize(){window.addEventListener("storage",this.handleStorageEvent),window.addEventListener("pagehide",this.handlePageHide),"BroadcastChannel"in globalThis&&(this.channel=new BroadcastChannel(un),this.channel.addEventListener("message",e=>{this.handleChannelMessage(e.data)}))}destroy(){this.release(),window.removeEventListener("storage",this.handleStorageEvent),window.removeEventListener("pagehide",this.handlePageHide),this.channel?.close(),this.channel=null}tryActivate({takeover:e=!1}={}){let t=this.readLock();return this.isFreshLock(t)&&t.tabId!==this.tabId&&!e?(this.isOwner=!1,this.stopHeartbeat(),this.onBlocked?.({reason:"active-elsewhere",ownerTabId:t.tabId}),!1):(this.writeLock(),this.startHeartbeat(),this.isOwner=!0,this.channel?.postMessage({type:"claimed",takeover:e,tabId:this.tabId}),this.onActivated?.({takeover:e}),!0)}release(){this.readLock()?.tabId===this.tabId&&(localStorage.removeItem(qe),this.channel?.postMessage({type:"released",tabId:this.tabId})),this.isOwner=!1,this.stopHeartbeat()}getOrCreateTabId(){try{let e=window.sessionStorage.getItem(vi);if(e)return e;let t=bi();return window.sessionStorage.setItem(vi,t),t}catch{return bi()}}readLock(){try{return Ci(window.localStorage.getItem(qe))}catch{return null}}isFreshLock(e){return!!(e&&typeof e.tabId=="string"&&Number.isFinite(e.updatedAt)&&xt()-e.updatedAt<this.staleAfterMs)}writeLock(){try{window.localStorage.setItem(qe,JSON.stringify({tabId:this.tabId,updatedAt:xt()}))}catch{}}startHeartbeat(){this.stopHeartbeat(),this.writeLock(),this.heartbeatTimer=window.setInterval(()=>{if(!this.isOwner){this.stopHeartbeat();return}this.writeLock()},this.heartbeatIntervalMs)}stopHeartbeat(){this.heartbeatTimer&&(window.clearInterval(this.heartbeatTimer),this.heartbeatTimer=null)}handleStorageEvent(e){if(e.key!==qe)return;let t=Ci(e.newValue);this.handleExternalLockChange(t)}handleChannelMessage(e){!e||typeof e!="object"||e.tabId===this.tabId||e.type==="claimed"&&this.handleExternalLockChange(this.readLock())}handleExternalLockChange(e){this.isOwner&&this.isFreshLock(e)&&e.tabId!==this.tabId&&(this.isOwner=!1,this.stopHeartbeat(),this.onStolen?.({ownerTabId:e.tabId}))}handlePageHide(){this.release()}};function Ei(n){return encodeURIComponent(String(n??""))}async function J(n,e){let t=await n.json().catch(()=>({}));if(!n.ok||t.ok===!1){let i=new Error(t.error||e);throw i.status=n.status,i.body=t,i}return t}var Ge=class{async readTree(){let e=await fetch(C("/files"));return J(e,"Failed to load file tree")}async readFile(e){let t=await fetch(C(`/file?path=${encodeURIComponent(e)}`));return J(t,"Failed to read file")}async createFile({content:e,path:t}){let i=await fetch(C("/file"),{body:JSON.stringify({content:e,path:t}),headers:{"Content-Type":"application/json"},method:"POST"});return J(i,"Failed to create file")}async renameFile({oldPath:e,newPath:t}){let i=await fetch(C("/file"),{body:JSON.stringify({newPath:t,oldPath:e}),headers:{"Content-Type":"application/json"},method:"PATCH"});return J(i,"Failed to rename file")}async deleteFile(e){let t=await fetch(C(`/file?path=${encodeURIComponent(e)}`),{method:"DELETE"});return J(t,"Failed to delete file")}async createDirectory(e){let t=await fetch(C("/directory"),{body:JSON.stringify({path:e}),headers:{"Content-Type":"application/json"},method:"POST"});return J(t,"Failed to create folder")}async uploadImageAttachment({file:e,fileName:t="",sourcePath:i}){let s=await fetch(C("/attachments"),{body:e,headers:{"Content-Type":e?.type||"application/octet-stream","X-CollabMD-File-Name":Ei(t),"X-CollabMD-Source-Path":Ei(i)},method:"POST"});return J(s,"Failed to upload image")}},he=new Ge;var Si="__workspace__";function ki(n){return!n?.path||!n?.type?null:n.nodeType==="directory"||n.type==="directory"?{children:[],name:n.name,path:n.path,type:"directory"}:{name:n.name,path:n.path,type:n.type}}function Ft(n=[]){return n.sort((e,t)=>e.type==="directory"&&t.type!=="directory"?-1:e.type!=="directory"&&t.type==="directory"?1:e.name.localeCompare(t.name,void 0,{sensitivity:"base"})),n.forEach(e=>{Array.isArray(e.children)&&Ft(e.children)}),n}function mn(n){return n instanceof Map?n:new Map(Object.entries(n??{}))}function It(n=[],e="asc"){let t=e==="desc"?-1:1;return[...n].sort((i,s)=>{let r=i.split("/").length-s.split("/").length;return r!==0?r*t:i.localeCompare(s,void 0,{sensitivity:"base"})*t})}var Tt=class{constructor(){this.entriesByPath=new Map,this.nodesByPath=new Map,this.nodeParentPathByPath=new Map,this.roots=[]}reset(e){return this.entriesByPath=mn(e),this.nodesByPath=new Map,this.nodeParentPathByPath=new Map,this.roots=[],this.entriesByPath.forEach(t=>{let i=ki(t);i&&this.nodesByPath.set(t.path,i)}),It(Array.from(this.nodesByPath.keys())).forEach(t=>{let i=this.nodesByPath.get(t);i&&this.attachNode(t,i,this.entriesByPath.get(t)?.parentPath||"")}),Ft(this.roots),this.roots}getTree(){return this.roots}applyMapChanges(e,t){let i=[],s=[];return e.forEach((r,a)=>{r.action==="delete"?i.push(a):s.push(a)}),It(i,"desc").forEach(r=>{this.removeEntry(r)}),It(s).forEach(r=>{this.upsertEntry(r,t.get(r))}),Ft(this.roots),this.roots}removeEntry(e){let t=this.nodesByPath.get(e);if(!t){this.entriesByPath.delete(e),this.nodeParentPathByPath.delete(e);return}this.detachNode(e,t),this.nodesByPath.delete(e),this.entriesByPath.delete(e),this.nodeParentPathByPath.delete(e)}upsertEntry(e,t){if(!t?.path||!t?.type){this.removeEntry(e);return}let i=ki(t);if(!i){this.removeEntry(e);return}let r=this.nodesByPath.get(e);!r||r.type==="directory"!=(i.type==="directory")?(r&&this.detachNode(e,r),r=i,this.nodesByPath.set(e,r)):(r.name=i.name,r.path=i.path,r.type=i.type,r.type==="directory"&&!Array.isArray(r.children)&&(r.children=[]),r.type!=="directory"&&Array.isArray(r.children)&&delete r.children),this.entriesByPath.set(e,t),this.attachNode(e,r,t.parentPath||""),r.type==="directory"&&this.rehomeChildren(e)}detachNode(e,t){let i=this.nodeParentPathByPath.get(e)||"",s=i?this.nodesByPath.get(i)?.children:this.roots,r=s?.indexOf?.(t)??-1;r>=0&&s.splice(r,1),this.nodeParentPathByPath.delete(e)}attachNode(e,t,i=""){let s=this.nodesByPath.get(i)?.type==="directory"?i:"",r=this.nodeParentPathByPath.get(e);if(r===s)return;r!==void 0&&this.detachNode(e,t);let a=s?this.nodesByPath.get(s)?.children:this.roots;a.includes(t)||a.push(t),this.nodeParentPathByPath.set(e,s)}rehomeChildren(e){this.entriesByPath.forEach((t,i)=>{if(t?.parentPath!==e)return;let s=this.nodesByPath.get(i);s&&this.attachNode(i,s,e)})}},Ve=class{constructor({onTreeChange:e=()=>{},onWorkspaceEvent:t=()=>{}}={}){this.onTreeChange=e,this.onWorkspaceEvent=t,this.ydoc=new Ce,this.entries=this.ydoc.getMap("entries"),this.events=this.ydoc.getArray("events"),this.provider=null,this._didInitialSync=!1,this.seenEventIds=new Set,this.treeModel=new Tt,this.handleEntriesChange=i=>{!this._didInitialSync||!i||this.onTreeChange(this.treeModel.applyMapChanges(i.changes.keys,this.entries),{changedPaths:Array.from(i.changes.keys.keys()),reset:!1})},this.handleEventsChange=()=>{if(!this._didInitialSync){this.primeEventCache();return}this.events.toArray().forEach(i=>{let s=kt(i);!s||this.seenEventIds.has(s.id)||(this.seenEventIds.add(s.id),this.onWorkspaceEvent(s))})}}connect(){this.provider||(this._didInitialSync=!1,this.provider=new Ee(pe(),Si,this.ydoc,{disableBc:!0,maxBackoffTime:5e3}),ke(this.provider),this.entries.observe(this.handleEntriesChange),this.events.observe(this.handleEventsChange),this.provider.on("sync",e=>{!e||this._didInitialSync||(this._didInitialSync=!0,this.primeEventCache(),this.onTreeChange(this.treeModel.reset(this.entries.toJSON()),{changedPaths:[],reset:!0}))}))}primeEventCache(){this.events.toArray().forEach(e=>{let t=kt(e);t&&this.seenEventIds.add(t.id)})}disconnect(){this.entries.unobserve(this.handleEntriesChange),this.events.unobserve(this.handleEventsChange),this.provider?.disconnect(),this.provider?.destroy(),this.provider=null,this._didInitialSync=!1,this.seenEventIds.clear(),this.treeModel.reset(new Map)}destroy(){this.disconnect(),this.ydoc.destroy()}};var Ke=class{constructor({documentRef:e=document,inlinePanelElement:t=null,onFileSelect:i,panelElement:s}){this.documentRef=e,this.panelRoot=s,this.inlinePanel=t,this.onFileSelect=i,this._expanded=!1,this._currentFile=null,this._fetchController=null,this._backlinks=[];let r=this.panelRoot?.querySelector('[data-backlinks-variant="dock"]')??this.panelRoot;this.panels=[this._createPanelRef(r),this._createPanelRef(this.inlinePanel)].filter(Boolean),this.handleDocumentPointerDown=a=>{if(!this._expanded)return;let o=a?.target;o&&this.panels.some(({panel:l})=>l?.contains?.(o))||this.close()},this.handleDocumentKeyDown=a=>{!this._expanded||a?.key!=="Escape"||(a.preventDefault?.(),this.close())},this.bindEvents()}bindEvents(){this.panels.forEach(e=>{e.header?.addEventListener("click",()=>{this._backlinks.length!==0&&(this._expanded=!this._expanded,this._applyExpandState())}),e.header?.addEventListener("keydown",t=>{t.key!=="Enter"&&t.key!==" "||(t.preventDefault(),e.header.click())})}),this.documentRef?.addEventListener?.("pointerdown",this.handleDocumentPointerDown),this.documentRef?.addEventListener?.("keydown",this.handleDocumentKeyDown)}async load(e){let t=e!==this._currentFile;if(this._currentFile=e,t&&(this._expanded=!1),!e){this._backlinks=[],this._render();return}this._fetchController?.abort(),this._fetchController=new AbortController;try{let s=await(await fetch(C(`/backlinks?file=${encodeURIComponent(e)}`),{signal:this._fetchController.signal})).json();if(this._currentFile!==e)return;this._backlinks=s.backlinks??[]}catch(i){if(i.name==="AbortError")return;console.warn("[backlinks] Failed to load:",i.message),this._backlinks=[]}this._render()}clear(){this._currentFile=null,this._backlinks=[],this._expanded=!1,this._render()}close(){this._expanded&&(this._expanded=!1,this._applyExpandState())}_createPanelRef(e){return e?{panel:e,header:e.querySelector(".backlinks-header"),toggle:e.querySelector(".backlinks-toggle"),countBadge:e.querySelector(".backlinks-count"),body:e.querySelector(".backlinks-body"),list:e.querySelector(".backlinks-list")}:null}_render(){let e=this._backlinks.length,t=e===1?"Linked Mention":"Linked Mentions",i=!!this._currentFile&&e>0;this.panelRoot?.classList?.toggle("hidden",!i),this.inlinePanel?.classList?.toggle("hidden",!i),i||(this._expanded=!1),this.panels.forEach(s=>{s.countBadge.textContent=i?String(e):"",s.toggle.textContent=t,s.header?.classList.toggle("backlinks-header-empty",!i),i?this._renderList(s.list):s.list.innerHTML=""}),this._applyExpandState()}_renderList(e){if(!e)return;e.innerHTML="";let t=this.documentRef?.createDocumentFragment?.(),i=t??e;this._backlinks.forEach(s=>{i.appendChild(this._createBacklinkItem(s))}),t&&e.appendChild(t)}_createBacklinkItem(e){let t=e.file.replace(/\.md$/i,"").split("/").pop(),i=e.file.includes("/")?e.file.substring(0,e.file.lastIndexOf("/")):"",s=this.documentRef.createElement("button");s.type="button",s.className="backlink-item",s.addEventListener("click",()=>{this.close(),this.onFileSelect?.(e.file)});let r=this.documentRef.createElement("div");if(r.className="backlink-file-name",r.innerHTML=`
|
|
37
|
+
<svg class="backlink-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
38
|
+
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
|
|
39
|
+
<polyline points="14 2 14 8 20 8"/>
|
|
40
|
+
</svg>
|
|
41
|
+
<span>${g(t)}</span>
|
|
42
|
+
${i?`<span class="backlink-dir">${g(i)}</span>`:""}
|
|
43
|
+
`,s.appendChild(r),e.contexts.slice(0,3).forEach(a=>{let o=this.documentRef.createElement("div");o.className="backlink-context",o.textContent=a,s.appendChild(o)}),e.contexts.length>3){let a=this.documentRef.createElement("div");a.className="backlink-context backlink-more",a.textContent=`+${e.contexts.length-3} more`,s.appendChild(a)}return s}_applyExpandState(){let e=this._expanded&&this._backlinks.length>0;this.panels.forEach(t=>{t.panel.classList.toggle("expanded",e),t.header?.setAttribute("aria-expanded",String(e)),t.header?.setAttribute("aria-disabled",String(this._backlinks.length===0)),t.body?.setAttribute("aria-hidden",String(!e)),t.body?.toggleAttribute("inert",!e)})}};function At(n,e,t,i,s,r){return n?.(e,t,i,s,r)??r.renderToken(e,t,i)}function pn(n=""){return`<p>${g(String(n??"")).replace(/\n/g,"<br>")}</p>`}function fn(){let n=zt({breaks:!0,highlight(s,r){try{return r&&fe.getLanguage(r)?fe.highlight(s,{ignoreIllegals:!0,language:r}).value:fe.highlightAuto(s).value}catch{return g(s)}},html:!1,linkify:!0,typographer:!0}),e=n.renderer.rules.link_open,t=n.renderer.rules.table_open,i=n.renderer.rules.table_close;return n.renderer.rules.link_open=(s,r,a,o,l)=>(s[r].attrSet("target","_blank"),s[r].attrSet("rel","noopener noreferrer"),At(e,s,r,a,o,l)),n.renderer.rules.table_open=(s,r,a,o,l)=>`<div class="comment-markdown-table">${At(t,s,r,a,o,l)}`,n.renderer.rules.table_close=(s,r,a,o,l)=>`${At(i,s,r,a,o,l)}</div>`,n}var gn=fn();function Pi(n=""){let e=String(n??"");try{return gn.render(e)}catch{return pn(e)}}var Li=14,xi=520,wn=150,yn=12,je=36,Qe=30,vn=400,bn=769,Cn=Object.freeze(["\u{1F44D}","\u2764\uFE0F","\u{1F389}","\u{1F440}","\u{1F680}"]),En=Object.freeze(["\u{1F602}","\u{1F525}","\u2705","\u{1F64F}","\u{1F4A1}","\u{1F914}","\u{1F44F}","\u{1F604}","\u{1F3AF}","\u{1F64C}"]);function ee(n,e,t){return Math.min(Math.max(n,e),t)}function Sn(n=[]){return[...n].sort((e,t)=>(e.anchor?.startLine??0)-(t.anchor?.startLine??0)||e.createdAt-t.createdAt)}function Bt(n){return n?.anchorKind||n?.kind||"line"}function Mt(n){return Bt(n)==="text"&&Number.isFinite(n?.startIndex)&&Number.isFinite(n?.endIndex)&&n.endIndex>n.startIndex}function Ii(n,e){return n===e?!0:!n||!e?!1:Bt(n)===Bt(e)&&(n.startIndex??null)===(e.startIndex??null)&&(n.endIndex??null)===(e.endIndex??null)&&(n.startLine??null)===(e.startLine??null)&&(n.endLine??null)===(e.endLine??null)&&(n.anchorQuote??n.quote??"")===(e.anchorQuote??e.quote??"")}function Fi(n){return n?(n.kind||n.anchorKind)==="text"&&n.quote?n.startLine===n.endLine?`Line ${n.startLine}`:`Lines ${n.startLine}-${n.endLine}`:n.startLine===n.endLine?`Line ${n.startLine}`:`Lines ${n.startLine}-${n.endLine}`:"No source anchor"}function kn(n={}){return[n.kind||n.anchorKind||"line",n.startLine??0,n.endLine??0,n.quote||""].join("::")}function Pn(n){return n&&!n.querySelector("[data-source-line]")}function Ti(n){let e=Number.parseInt(n||"",10);return Number.isFinite(e)?e:null}function Ln(n=[]){return n.reduce((e,t)=>e?(t?.createdAt??0)>=(e?.createdAt??0)?t:e:t,null)}function xn(n){return n?.threads?.reduce((e,t)=>{let i=Ln(t?.messages??[]);return i&&(i.createdAt??0)>=(e?.createdAt??0)?i:e},null)}function Ai(n,e="comment-markdown"){let t=document.createElement("div");return t.className=e,t.innerHTML=Pi(n),t}function Mi(n,e){return!!(e&&n?.users?.some(t=>t?.userId===e))}function In(n){return String(Array.isArray(n?.users)?n.users.length:0)}function Rt(n,e,t){return n?.threadId===e&&n?.messageId===t}function Fn(n){let e=n?.querySelector?.(".comment-reaction-picker"),t=e?.closest?.(".comment-reaction-picker-wrap"),i=n?.querySelector?.(".comment-card-scroll");return!(e instanceof HTMLElement)||!(t instanceof HTMLElement)||!(i instanceof HTMLElement)?null:{picker:e,scroll:i,wrap:t}}function Ri(n,e){let t=Ti(n?.getAttribute?.("data-source-line")),i=Ti(n?.getAttribute?.("data-source-line-end"))??t;return!t||!i||!e?!1:e.startLine<=i&&e.endLine>=t}function Tn(n){let e=document.createTreeWalker(n,NodeFilter.SHOW_TEXT),t="",i=[],s=!0;for(;e.nextNode();){let r=e.currentNode,a=r.textContent||"";for(let o=0;o<a.length;o+=1){let l=a[o];if(/\s/.test(l)){if(s)continue;t+=" ",i.push({node:r,offset:o}),s=!0;continue}t+=l,i.push({node:r,offset:o}),s=!1}}for(;t.endsWith(" ");)t=t.slice(0,-1),i.pop();return{map:i,normalized:t}}function An(n,e){let t=Xt(e);if(!n||!t)return null;let i=Tn(n);if(!i.normalized)return null;let s=i.normalized.indexOf(t);if(s<0||i.normalized.indexOf(t,s+1)>=0)return null;let r=i.map[s],a=i.map[s+t.length-1];if(!r||!a)return null;let o=document.createRange();return o.setStart(r.node,r.offset),o.setEnd(a.node,a.offset+1),o}function Bi(n,e){return{bottom:n.bottom-e.top,height:n.height,left:n.left-e.left,right:n.right-e.left,top:n.top-e.top,width:n.width}}function Mn(n=[]){if(!Array.isArray(n)||n.length===0)return null;let e=Math.min(...n.map(r=>r.left)),t=Math.min(...n.map(r=>r.top)),i=Math.max(...n.map(r=>r.right)),s=Math.max(...n.map(r=>r.bottom));return{bottom:s,height:s-t,left:e,right:i,top:t,width:i-e}}function Rn(n,e,t){return t?n>=t.left&&n<=t.right&&e>=t.top&&e<=t.bottom:!1}function Ye(n=[]){return[...new Set(n.filter(Boolean))].sort()}function Bn(n=[]){return Ye(n).join(" ")}function Ni(n){let e=document.createDocumentFragment(),t=document.createElement("span");if(t.className="comment-marker-icon",t.setAttribute("aria-hidden","true"),t.innerHTML=`
|
|
44
44
|
<svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
45
45
|
<path d="M3 4.75A1.75 1.75 0 0 1 4.75 3h6.5A1.75 1.75 0 0 1 13 4.75v4.5A1.75 1.75 0 0 1 11.25 11H8.9L6.5 13v-2H4.75A1.75 1.75 0 0 1 3 9.25v-4.5Z" stroke="currentColor" stroke-width="1.35" stroke-linejoin="round"/>
|
|
46
46
|
</svg>
|
|
47
|
-
`,e.appendChild(t),n>1){let i=document.createElement("span");i.className="comment-marker-count",i.textContent=String(n),e.appendChild(i)}return e}var We=class{constructor({commentSelectionButton:e,commentsDrawer:t,commentsDrawerEmpty:i,commentsDrawerList:s,commentsToggleButton:r,editorContainer:a,onCreateThread:o,onNavigateToLine:l,onReplyToThread:h,onToggleReaction:c,onResolveThread:u,previewContainer:f,previewElement:d}){this.commentSelectionButton=e,this.commentsDrawer=t,this.commentsDrawerEmpty=i,this.commentsDrawerList=s,this.commentsToggleButton=r,this.editorContainer=a,this.onCreateThread=o,this.onNavigateToLine=l,this.onReplyToThread=h,this.onToggleReaction=c,this.onResolveThread=u,this.previewContainer=f,this.previewElement=d,this.currentFile=null,this.fileKind="markdown",this.supported=!1,this.drawerOpen=!1,this.threads=[],this.selectionAnchor=null,this.pendingSelectionAnchor=null,this.committedSelectionAnchor=null,this.selectionRevealTimer=0,this.pointerSelecting=!1,this.session=null,this.activeCard=null,this.editorLayer=null,this.previewLayer=null,this.previewHighlightLayer=null,this.cardRoot=null,this.pendingCardFocusElement=null,this.reactionPicker=null,this.layoutFrame=0,this.timeFormatter=new Intl.DateTimeFormat(void 0,{day:"numeric",hour:"numeric",minute:"2-digit",month:"short"}),this.handleEditorScroll=()=>this.scheduleLayoutRefresh(),this.handlePreviewScroll=()=>this.scheduleLayoutRefresh(),this.handleWindowResize=()=>this.scheduleLayoutRefresh(),this.handleCommentSelectionButtonPointerDown=g=>{g.preventDefault()},this.handleEditorPointerDown=g=>{g.button!==0||!this.supported||!this.session||!g.target?.closest?.(".cm-editor")||g.target?.closest?.(".comment-editor-layer")||(this.pointerSelecting=!0,this.clearSelectionRevealTimer(),this.committedSelectionAnchor&&(this.committedSelectionAnchor=null,this.scheduleLayoutRefresh()))},this.handleDocumentPointerUp=()=>{this.pointerSelecting&&requestAnimationFrame(()=>{let g=this.supported?this.session?.getCurrentSelectionCommentAnchor?.()??null:null;this.pointerSelecting=!1,this.selectionAnchor=g,this.renderToolbar(),this.pendingSelectionAnchor=vt(g)?g:null,this.clearSelectionRevealTimer(),this.committedSelectionAnchor=vt(g)&&this.activeCard?.mode!=="create"?g:null,this.scheduleLayoutRefresh()})},this.handleEditorFocusOut=g=>{let w=g.relatedTarget;w instanceof Node&&(this.editorContainer?.contains(w)||this.cardRoot?.contains(w)||this.commentSelectionButton?.contains(w))||(this.clearSelectionRevealTimer(),this.pendingSelectionAnchor=null,this.committedSelectionAnchor=null,this.scheduleLayoutRefresh())},this.handleDocumentPointerDown=g=>{!this.activeCard||!this.cardRoot||this.cardRoot.contains(g.target)||this.closeCard()},this.handleDocumentKeyDown=g=>{if(g.key==="Escape"&&this.reactionPicker){this.reactionPicker=null,this.renderCard();return}g.key==="Escape"&&this.activeCard&&this.closeCard(),g.key==="Escape"&&this.committedSelectionAnchor&&(this.clearSelectionRevealTimer(),this.pendingSelectionAnchor=null,this.committedSelectionAnchor=null,this.scheduleLayoutRefresh())},this.commentSelectionButton?.addEventListener("pointerdown",this.handleCommentSelectionButtonPointerDown),this.commentSelectionButton?.addEventListener("click",()=>{this.openComposerForSelection("toolbar")}),this.commentsToggleButton?.addEventListener("click",()=>{this.drawerOpen=!this.drawerOpen,this.render()}),this.previewContainer?.addEventListener("scroll",this.handlePreviewScroll,{passive:!0}),this.editorContainer?.addEventListener("pointerdown",this.handleEditorPointerDown),this.editorContainer?.addEventListener("focusout",this.handleEditorFocusOut),window.addEventListener("resize",this.handleWindowResize),document.addEventListener("pointerup",this.handleDocumentPointerUp),document.addEventListener("pointercancel",this.handleDocumentPointerUp),document.addEventListener("pointerdown",this.handleDocumentPointerDown),document.addEventListener("keydown",this.handleDocumentKeyDown)}destroy(){this.layoutFrame&&(cancelAnimationFrame(this.layoutFrame),this.layoutFrame=0),this.attachSession(null),this.previewContainer?.removeEventListener("scroll",this.handlePreviewScroll),this.commentSelectionButton?.removeEventListener("pointerdown",this.handleCommentSelectionButtonPointerDown),this.editorContainer?.removeEventListener("pointerdown",this.handleEditorPointerDown),this.editorContainer?.removeEventListener("focusout",this.handleEditorFocusOut),window.removeEventListener("resize",this.handleWindowResize),document.removeEventListener("pointerup",this.handleDocumentPointerUp),document.removeEventListener("pointercancel",this.handleDocumentPointerUp),document.removeEventListener("pointerdown",this.handleDocumentPointerDown),document.removeEventListener("keydown",this.handleDocumentKeyDown),this.cardRoot?.remove(),this.editorLayer?.remove(),this.previewLayer?.remove(),this.pendingCardFocusElement=null}attachSession(e){this.session?.getScrollContainer?.()?.removeEventListener("scroll",this.handleEditorScroll),this.session=e,this.selectionAnchor=e?.getCurrentSelectionCommentAnchor?.()??null,this.pendingSelectionAnchor=null,this.committedSelectionAnchor=null,this.reactionPicker=null,this.clearSelectionRevealTimer(),this.pointerSelecting=!1,e?.getScrollContainer?.()?.addEventListener("scroll",this.handleEditorScroll,{passive:!0}),this.render()}setCurrentFile(e,{fileKind:t="markdown",supported:i=!1}={}){let s=this.currentFile!==e;this.currentFile=e,this.fileKind=t,this.supported=!!(e&&i),s&&(this.drawerOpen=!1,this.threads=[],this.selectionAnchor=null,this.pendingSelectionAnchor=null,this.committedSelectionAnchor=null,this.clearSelectionRevealTimer(),this.pointerSelecting=!1,this.activeCard=null,this.reactionPicker=null),this.supported||(this.drawerOpen=!1,this.activeCard=null,this.threads=[],this.selectionAnchor=null,this.pendingSelectionAnchor=null,this.committedSelectionAnchor=null,this.clearSelectionRevealTimer(),this.pointerSelecting=!1,this.reactionPicker=null),this.render()}setSelectionAnchor(e){if(this.selectionAnchor=this.supported?e:null,!this.supported||!this.selectionAnchor){this.pendingSelectionAnchor=null,this.committedSelectionAnchor=null,this.clearSelectionRevealTimer(),this.renderToolbar(),this.scheduleLayoutRefresh();return}if(!vt(this.selectionAnchor)){this.pendingSelectionAnchor=null,this.committedSelectionAnchor=null,this.clearSelectionRevealTimer(),this.renderToolbar(),this.scheduleLayoutRefresh();return}if(this.pendingSelectionAnchor=this.selectionAnchor,this.activeCard?.mode==="create"){this.clearSelectionRevealTimer(),this.renderToolbar(),this.scheduleLayoutRefresh();return}if(this.pointerSelecting){this.clearSelectionRevealTimer(),this.committedSelectionAnchor=null,this.renderToolbar(),this.scheduleLayoutRefresh();return}if(wi(this.committedSelectionAnchor,this.selectionAnchor)){this.renderToolbar(),this.scheduleLayoutRefresh();return}this.scheduleSelectionReveal(this.selectionAnchor),this.renderToolbar(),this.scheduleLayoutRefresh()}handleEditorContentChange(){this.activeCard?.mode!=="create"&&(this.clearSelectionRevealTimer(),this.pendingSelectionAnchor=null,this.committedSelectionAnchor=null,this.scheduleLayoutRefresh())}setThreads(e=[]){this.threads=tn(e),this.activeCard?.mode==="group"&&!this.getThreadGroups().some(t=>t.key===this.activeCard.groupKey)&&(this.activeCard=null),this.reactionPicker&&!this.threads.some(t=>t.id===this.reactionPicker.threadId&&t.messages?.some(i=>i.id===this.reactionPicker.messageId))&&(this.reactionPicker=null),this.render()}refreshLayout(){this.renderEditorLayer(),this.renderPreviewLayer(),this.repositionActiveCard()}scheduleLayoutRefresh(){this.layoutFrame||(this.layoutFrame=requestAnimationFrame(()=>{this.layoutFrame=0,this.refreshLayout()}))}render(){this.renderToolbar(),this.renderDrawer(),this.renderCard(),this.scheduleLayoutRefresh()}renderToolbar(){let e=this.threads.length,t=this.supported&&!!this.session;if(this.commentSelectionButton?.classList.toggle("hidden",!t),this.commentsToggleButton?.classList.toggle("hidden",!this.supported),this.commentSelectionButton&&(this.commentSelectionButton.disabled=!this.selectionAnchor),this.commentsToggleButton){this.commentsToggleButton.classList.toggle("active",this.drawerOpen),this.commentsToggleButton.setAttribute("aria-expanded",String(this.drawerOpen));let i=e>0?`Comments ${e}`:"Comments",s=this.commentsToggleButton.querySelector(".pane-header-btn-label");s?s.textContent=i:this.commentsToggleButton.textContent=i}}renderDrawer(){if(!this.commentsDrawer||!this.commentsDrawerList)return;this.commentsDrawer.classList.toggle("hidden",!this.supported||!this.drawerOpen),this.commentsDrawerList.replaceChildren();let e=this.getThreadGroups();if(this.commentsDrawerEmpty?.classList.toggle("hidden",e.length>0),!this.supported||e.length===0)return;let t=document.createDocumentFragment();e.forEach(i=>{let s=document.createElement("button");s.type="button",s.className="comments-drawer-item",s.classList.toggle("is-active",this.activeCard?.groupKey===i.key),s.addEventListener("pointerdown",g=>{g.preventDefault()}),s.addEventListener("click",()=>{this.openThreadGroup(i,{anchor:i.anchor,origin:"drawer",sourceRect:s.getBoundingClientRect()})});let r=document.createElement("div");r.className="comments-drawer-item-header";let a=document.createElement("span");a.className="comments-drawer-item-title",a.textContent=yi(i.anchor);let o=document.createElement("span");o.className="comments-drawer-item-count",o.textContent=String(i.threads.length),r.append(a,o);let l=document.createElement("p");l.className="comments-drawer-item-quote",l.textContent=i.anchor.quote||i.anchor.excerpt||"Source anchored comment";let h=an(i),c=bi(h?.body||"","comment-markdown comments-drawer-item-preview"),u=document.createElement("div");u.className="comments-drawer-item-footer";let f=document.createElement("span");f.textContent=`${i.threads.length} thread${i.threads.length===1?"":"s"}`;let d=document.createElement("span");d.className="comments-drawer-item-updated",d.textContent=h?`${h.userName} \u2022 ${this.formatTimestamp(h.createdAt)}`:"",u.append(f,d),s.append(r,l,c,u),t.appendChild(s)}),this.commentsDrawerList.appendChild(t)}ensureEditorLayer(){if(this.editorLayer?.isConnected&&this.editorLayer.parentElement===this.editorContainer)return this.editorLayer;let e=document.createElement("div");return e.className="comment-editor-layer",this.editorContainer?.appendChild(e),this.editorLayer=e,e}renderEditorLayer(){let e=this.ensureEditorLayer();if(e.replaceChildren(),!this.supported||!this.session)return;let t=this.editorContainer?.getBoundingClientRect?.();if(!t)return;let i=this.getThreadGroups(),s=[];if(i.forEach(c=>{let u=this.session.getCommentAnchorClientRect?.(c.anchor);if(!u)return;let f=Si(u,t),d=document.createElement("button");d.type="button",d.className="comment-editor-badge",d.dataset.count=String(c.threads.length),d.classList.toggle("is-active",this.activeCard?.groupKey===c.key),d.setAttribute("aria-label",`${c.threads.length} comment thread${c.threads.length===1?"":"s"}`),d.appendChild(Li(c.threads.length));let g=Math.max(f.top,8);d.style.top=`${g}px`,d.style.left=`${Math.max(t.width-36,8)}px`,d.title=`${c.threads.length} comment${c.threads.length===1?"":"s"}`,d.addEventListener("pointerdown",w=>{w.preventDefault()}),d.addEventListener("click",()=>{this.openThreadGroup(c,{anchor:c.anchor,origin:"editor",sourceRect:u})}),e.appendChild(d),s.push(g)}),!this.committedSelectionAnchor||this.activeCard?.mode==="create")return;let r=this.session.getCommentAnchorClientRect?.(this.committedSelectionAnchor),a=this.session.getSelectionChipClientRect?.(this.committedSelectionAnchor)??r;if(!a)return;let o=Si(a,t);if(o.bottom<0||o.top>t.height)return;let l=re(o.top,8,Math.max(t.height-qe,8));for(;s.some(c=>Math.abs(c-l)<qe-4);)l=re(l+qe,8,Math.max(t.height-qe,8));let h=document.createElement("button");h.type="button",h.className="comment-selection-chip",h.textContent="Comment",h.style.top=`${l}px`,h.style.right=`${Xi}px`,h.addEventListener("pointerdown",c=>{c.preventDefault(),c.stopPropagation(),this.openComposerForSelection("editor",h.getBoundingClientRect())}),e.appendChild(h)}ensurePreviewLayer(){if(this.previewLayer?.isConnected&&this.previewLayer.parentElement===this.previewElement)return this.previewLayer;let e=document.createElement("div");e.className="comment-preview-highlights";let t=document.createElement("div");return t.className="comment-preview-layer",this.previewElement?.append(e,t),this.previewHighlightLayer=e,this.previewLayer=t,t}renderPreviewLayer(){if(this.ensurePreviewLayer(),this.previewLayer?.replaceChildren(),this.previewHighlightLayer?.replaceChildren(),!this.supported||!this.previewElement)return;let e=this.previewElement.getBoundingClientRect();this.getThreadGroups().forEach(i=>{let s=this.resolvePreviewTarget(i.anchor);if(!s?.bubbleRect)return;s.highlightRects?.forEach(a=>{let o=document.createElement("div");o.className="comment-preview-highlight",o.style.left=`${a.left-e.left}px`,o.style.top=`${a.top-e.top}px`,o.style.width=`${a.width}px`,o.style.height=`${a.height}px`,this.previewHighlightLayer?.appendChild(o)});let r=document.createElement("button");r.type="button",r.className="comment-preview-badge",r.classList.toggle("is-active",this.activeCard?.groupKey===i.key),r.setAttribute("aria-label",`${i.threads.length} comment thread${i.threads.length===1?"":"s"}`),r.appendChild(Li(i.threads.length)),r.style.left=`${re(s.bubbleRect.right-e.left+6,6,this.previewElement.clientWidth-34)}px`,r.style.top=`${Math.max(s.bubbleRect.top-e.top,6)}px`,r.title=`${i.threads.length} comment${i.threads.length===1?"":"s"}`,r.addEventListener("pointerdown",a=>{a.preventDefault()}),r.addEventListener("click",()=>{this.openThreadGroup(i,{anchor:i.anchor,origin:"preview",sourceRect:s.bubbleRect})}),this.previewLayer?.appendChild(r)})}resolvePreviewTarget(e){if(!this.previewElement||!e)return null;let t=Array.from(this.previewElement.querySelectorAll(".mermaid-shell, .plantuml-shell")).find(r=>Ei(r,e));if(t)return{bubbleRect:t.getBoundingClientRect(),highlightRects:[]};let i=Array.from(this.previewElement.querySelectorAll("[data-source-line]")).filter(r=>sn(r)&&Ei(r,e));if(e.kind==="text"&&e.quote){let r=i.map(a=>({element:a,range:hn(a,e.quote)})).filter(a=>a.range);if(r.length===1){let a=Array.from(r[0].range.getClientRects());return{bubbleRect:dn(a)||r[0].element.getBoundingClientRect(),highlightRects:a}}}let s=i[0];return s?{bubbleRect:s.getBoundingClientRect(),highlightRects:[]}:null}ensureCardRoot(){if(this.cardRoot?.isConnected&&this.cardRoot.parentElement===document.body)return this.cardRoot;let e=document.createElement("div");return e.className="comment-card-root hidden",document.body.appendChild(e),this.cardRoot=e,e}openComposerForSelection(e="editor",t=null){let i=this.session?.getCurrentSelectionCommentAnchor?.();if(!i)return;this.selectionAnchor=i,this.reactionPicker=null;let s=e==="editor"&&t?"editor-chip":e,r=t??(e==="toolbar"?this.commentSelectionButton?.getBoundingClientRect?.():this.session?.getCommentAnchorClientRect?.(i));this.activeCard={anchor:i,mode:"create",origin:s,replyThreadId:null,sourceRect:r},this.render()}openThreadGroup(e,{anchor:t,origin:i,sourceRect:s}){this.reactionPicker=null,this.activeCard={anchor:t,groupKey:e.key,mode:"group",origin:i,replyThreadId:null,sourceRect:s},this.renderDrawer(),this.renderCard()}closeCard(){this.activeCard=null,this.pendingCardFocusElement=null,this.reactionPicker=null,this.renderCard(),this.scheduleLayoutRefresh()}getThreadGroups(){let e=new Map;return this.threads.forEach(t=>{let i=nn(t.anchor),s=e.get(i);if(s){s.threads.push(t);return}e.set(i,{anchor:t.anchor,key:i,threads:[t]})}),Array.from(e.values()).sort((t,i)=>(t.anchor?.startLine??0)-(i.anchor?.startLine??0))}updateCardSourceRect(){return this.activeCard?this.activeCard.origin==="editor"?this.session?.getCommentAnchorClientRect?.(this.activeCard.anchor)??this.activeCard.sourceRect:this.activeCard.origin==="editor-chip"?this.activeCard.sourceRect:this.activeCard.origin==="preview"?this.resolvePreviewTarget(this.activeCard.anchor)?.bubbleRect??this.activeCard.sourceRect:this.activeCard.origin==="toolbar"?this.commentSelectionButton?.getBoundingClientRect?.()??this.activeCard.sourceRect:this.activeCard.sourceRect:null}renderCard(){let e=this.ensureCardRoot();if(e.replaceChildren(),e.classList.toggle("hidden",!this.activeCard),!this.activeCard){this.pendingCardFocusElement=null,e.style.visibility="";return}this.pendingCardFocusElement=null;let t=document.createElement("section");t.className="comment-card",t.addEventListener("click",h=>{!this.reactionPicker||h.target?.closest?.(".comment-reaction-picker-wrap")||(this.reactionPicker=null,requestAnimationFrame(()=>{this.activeCard&&this.renderCard()}))});let i=document.createElement("div");i.className="comment-card-header";let s=document.createElement("div");s.className="comment-card-title-wrap";let r=document.createElement("h3");r.className="comment-card-title",r.textContent=this.activeCard.mode==="create"?"New comment":"Comment threads";let a=document.createElement("p");a.className="comment-card-meta",a.textContent=yi(this.activeCard.anchor),s.append(r,a);let o=document.createElement("button");o.type="button",o.className="comment-card-close",o.setAttribute("aria-label","Close comments"),o.textContent="Close",o.addEventListener("click",()=>this.closeCard()),i.append(s,o),t.appendChild(i);let l=document.createElement("div");if(l.className="comment-card-scroll",this.activeCard.anchor?.quote){let h=document.createElement("p");h.className="comment-card-quote",h.textContent=this.activeCard.anchor.quote,l.appendChild(h)}if(this.activeCard.mode==="create")l.appendChild(this.createComposer());else{let h=this.getThreadGroups().find(c=>c.key===this.activeCard.groupKey);if(!h){this.closeCard();return}h.threads.forEach(c=>{l.appendChild(this.createThreadElement(c))})}e.style.visibility="hidden",t.appendChild(l),e.appendChild(t),this.updateReactionPickerPosition(t),this.positionCard(t),e.style.visibility="",this.flushPendingCardFocus(),this.scheduleLayoutRefresh()}updateReactionPickerPosition(e){let t=ln(e);if(!t)return;let{picker:i,scroll:s,wrap:r}=t;i.classList.remove("is-upward"),i.style.maxHeight="";let a=r.getBoundingClientRect(),o=s.getBoundingClientRect(),l=i.getBoundingClientRect(),h=12,c=window.innerHeight-12,u=Math.min(o.bottom,c),f=Math.max(o.top,h),d=Math.max(u-a.bottom-8,0),g=Math.max(a.top-f-8,0),w=l.height>d&&g>d,E=Math.max(w?g:d,120);i.classList.toggle("is-upward",w),i.style.maxHeight=`${E}px`}repositionActiveCard(){let e=this.cardRoot?.firstElementChild;if(!e||!this.activeCard){this.cardRoot&&(this.cardRoot.style.visibility="");return}this.positionCard(e),this.cardRoot.style.visibility="",this.flushPendingCardFocus()}createComposer(){let e=document.createElement("form");e.className="comment-card-form";let t=document.createElement("textarea");t.className="input comment-card-input",t.rows=4,t.maxLength=ut,t.placeholder="Add context, feedback, or a question...";let i=document.createElement("div");i.className="comment-card-actions";let s=document.createElement("button");s.type="button",s.className="btn btn-secondary",s.textContent="Cancel",s.addEventListener("click",()=>this.closeCard());let r=document.createElement("button");return r.type="submit",r.className="btn btn-primary",r.textContent="Post comment",i.append(s,r),e.append(t,i),e.addEventListener("submit",async a=>{if(a.preventDefault(),!await this.onCreateThread?.({anchor:this.activeCard?.anchor,body:t.value})){t.focus();return}this.closeCard()}),this.pendingCardFocusElement=t,e}createThreadElement(e){let t=document.createElement("article");t.className="comment-thread-card";let i=document.createElement("div");i.className="comment-thread-card-header";let s=document.createElement("div");s.className="comment-thread-card-heading";let r=document.createElement("span");r.className="comment-thread-card-author",r.textContent=e.createdByName;let a=document.createElement("span");a.className="comment-thread-card-time",a.textContent=this.formatTimestamp(e.createdAt);let o=document.createElement("div");o.className="comment-thread-card-actions";let l=document.createElement("button");l.type="button",l.className="comment-thread-card-action",l.textContent="Jump",l.addEventListener("click",()=>this.onNavigateToLine?.(e.anchor?.startLine??1));let h=document.createElement("button");h.type="button",h.className="comment-thread-card-action";let c=this.activeCard?.replyThreadId===e.id;h.classList.toggle("is-active",c),h.textContent="Reply",h.setAttribute("aria-pressed",String(c)),h.setAttribute("aria-label",c?"Cancel reply":"Reply to thread"),h.title=c?"Cancel reply":"Reply to thread",h.addEventListener("click",()=>{this.activeCard={...this.activeCard,replyThreadId:c?null:e.id},this.renderCard()});let u=document.createElement("button");return u.type="button",u.className="comment-thread-card-action is-danger",u.textContent="Resolve",u.addEventListener("click",async()=>{await this.onResolveThread?.(e.id)}),o.append(l,h,u),s.append(r,a),i.append(s,o),t.append(i),e.messages.forEach(f=>{t.appendChild(this.createMessageElement(e,f))}),this.activeCard?.replyThreadId===e.id&&t.appendChild(this.createReplyComposer(e)),t}createMessageElement(e,t){let i=document.createElement("div");i.className="comment-message-card";let s=document.createElement("div");s.className="comment-message-card-meta";let r=document.createElement("span");r.className="comment-message-card-author",r.textContent=t.userName;let a=document.createElement("span");a.className="comment-message-card-time",a.textContent=this.formatTimestamp(t.createdAt);let o=bi(t.body,"comment-message-card-body comment-markdown");return s.append(r,a),i.append(s,o),i.appendChild(this.createReactionBar(e,t)),i}createReactionBar(e,t){let i=this.session?.getLocalUser?.()?.userId??"",s=document.createElement("div");s.className="comment-reaction-bar";let r=new Set((t.reactions??[]).map(c=>c.emoji)),a=document.createElement("div");a.className="comment-reaction-chips",(t.reactions??[]).forEach(c=>{let u=document.createElement("button");u.type="button",u.className="comment-reaction-chip",u.classList.toggle("is-active",Ci(c,i)),u.setAttribute("aria-pressed",String(Ci(c,i))),u.title=c.users?.map(g=>g.userName).join(", ")||c.emoji;let f=document.createElement("span");f.className="comment-reaction-chip-emoji",f.textContent=c.emoji;let d=document.createElement("span");d.className="comment-reaction-chip-count",d.textContent=on(c),u.append(f,d),u.addEventListener("click",async()=>{await this.onToggleReaction?.(e.id,t.id,c.emoji)}),a.appendChild(u)});let o=document.createElement("div");o.className="comment-reaction-actions",Ji.filter(c=>!r.has(c)).forEach(c=>{o.appendChild(this.createQuickReactionButton(e,t,c))});let l=document.createElement("div");l.className="comment-reaction-picker-wrap";let h=document.createElement("button");return h.type="button",h.className="comment-reaction-more-trigger",h.dataset.reactionPickerToggle="true",h.setAttribute("aria-expanded",String(bt(this.reactionPicker,e.id,t.id))),h.textContent="More",h.addEventListener("click",()=>{let c=bt(this.reactionPicker,e.id,t.id);this.reactionPicker=c?null:{messageId:t.id,threadId:e.id},this.renderCard()}),l.appendChild(h),bt(this.reactionPicker,e.id,t.id)&&l.appendChild(this.createReactionPicker(e,t)),o.appendChild(l),s.append(a,o),s}createQuickReactionButton(e,t,i){let s=document.createElement("button");return s.type="button",s.className="comment-reaction-quick-add",s.textContent=i,s.title=`React with ${i}`,s.addEventListener("click",async()=>{await this.onToggleReaction?.(e.id,t.id,i)}),s}createReactionPicker(e,t){let i=document.createElement("div");i.className="comment-reaction-picker";let s=document.createElement("div");return s.className="comment-reaction-picker-grid",en.forEach(r=>{s.appendChild(this.createReactionPickerButton(e,t,r))}),i.appendChild(s),i}createReactionPickerButton(e,t,i){let s=document.createElement("button");return s.type="button",s.className="comment-reaction-picker-btn",s.textContent=i,s.title=`React with ${i}`,s.addEventListener("click",async()=>{await this.onToggleReaction?.(e.id,t.id,i)&&(this.reactionPicker=null,this.renderCard())}),s}createReplyComposer(e){let t=document.createElement("form");t.className="comment-reply-form";let i=document.createElement("textarea");i.className="input comment-card-input",i.rows=3,i.maxLength=ut,i.placeholder="Reply to thread...";let s=document.createElement("div");s.className="comment-card-actions";let r=document.createElement("button");r.type="button",r.className="btn btn-secondary",r.textContent="Cancel",r.addEventListener("click",()=>{this.activeCard={...this.activeCard,replyThreadId:null},this.renderCard()});let a=document.createElement("button");return a.type="submit",a.className="btn btn-primary",a.textContent="Reply",s.append(r,a),t.append(i,s),this.pendingCardFocusElement=i,t.addEventListener("submit",async o=>{if(o.preventDefault(),!await this.onReplyToThread?.(e.id,i.value)){i.focus();return}this.activeCard={...this.activeCard,replyThreadId:null},this.renderCard()}),t}positionCard(e){let t=this.updateCardSourceRect(),i=window.innerWidth,s=window.innerHeight,r=e.getBoundingClientRect(),a=re((i-r.width)/2,16,i-r.width-16),o=re((s-r.height)/4,16,s-r.height-16),l=a,h=o;t&&(l=re(t.left,16,i-Math.min(r.width,gi)-16),h=t.bottom+fi,h+r.height>s-16&&(h=Math.max(t.top-r.height-fi,16))),this.cardRoot.style.left=`${l}px`,this.cardRoot.style.top=`${h}px`,this.cardRoot.style.width=`${Math.min(Math.max(r.width,gi),i-32)}px`}formatTimestamp(e){if(!Number.isFinite(e))return"";try{return this.timeFormatter.format(new Date(e))}catch{return""}}flushPendingCardFocus(){let e=this.pendingCardFocusElement;if(!(e instanceof HTMLElement)||!e.isConnected){this.pendingCardFocusElement=null;return}this.pendingCardFocusElement=null;let t=()=>{if(!e.isConnected)return;let i=document.activeElement;i instanceof HTMLElement&&this.editorContainer?.contains(i)&&i.blur(),e.focus({preventScroll:!0})};t(),document.activeElement!==e&&requestAnimationFrame(()=>{t(),document.activeElement!==e&&setTimeout(()=>{t()},50)})}clearSelectionRevealTimer(){this.selectionRevealTimer&&(clearTimeout(this.selectionRevealTimer),this.selectionRevealTimer=0)}scheduleSelectionReveal(e){this.clearSelectionRevealTimer(),this.selectionRevealTimer=window.setTimeout(()=>{this.selectionRevealTimer=0,!(this.pointerSelecting||this.activeCard?.mode==="create"||!wi(this.pendingSelectionAnchor,e))&&(this.committedSelectionAnchor=e,this.scheduleLayoutRefresh())},Yi)}};function Ve(n,e){let t=new Map;e.forEach(s=>{let a=n.get(s.key)??{filePath:s.filePath,iframe:null,instanceId:null,key:s.key,label:s.label,placeholder:s.placeholder,queued:!1,reusedFromEmbed:!1,wrapper:null};a.filePath=s.filePath,a.key=s.key,a.label=s.label,a.placeholder=s.placeholder,t.set(s.key,a)});let i=[];return n.forEach((s,r)=>{t.has(r)||i.push(s)}),{nextEntries:t,removedEntries:i}}var de=420,un=500,mn=15e3,pn=800,fn=3,gn=200,wn="/excalidraw-editor.html";function yn(n,e){return typeof window.requestIdleCallback=="function"?window.requestIdleCallback(n,{timeout:e}):window.setTimeout(()=>{n({didTimeout:!1,timeRemaining:()=>0})},1)}function Ke(n){if(n!==null){if(typeof window.cancelIdleCallback=="function"){window.cancelIdleCallback(n);return}window.clearTimeout(n)}}function vn(n,e,t){if(!n||!e)return!1;let i=e.getBoundingClientRect(),s=n.getBoundingClientRect();return s.bottom>=i.top-t&&s.top<=i.bottom+t}var Ge=class{constructor({getTheme:e,getLocalUser:t,onOpenFile:i=null,previewContainer:s,previewElement:r,toastController:a}){this.getTheme=e,this.getLocalUser=t,this.onOpenFile=i,this.previewContainer=s,this.previewElement=r,this.toastController=a,this.embedEntries=new Map,this.hydrationQueue=[],this.hydrationIdleId=null,this.hydrationPaused=!1,this.hydrationInProgress=!1,this.instanceCounter=0,this.isLargeDocument=!1,this.maximizedEmbed=null,this.overlayRoot=null,this.maximizedRoot=null,this.placeholderObserver=null,this.followedPeerIdsByFilePath=new Map,this._onMessage=this._onMessage.bind(this),this._onKeyDown=this._onKeyDown.bind(this),this._onPreviewClick=this._onPreviewClick.bind(this),window.addEventListener("message",this._onMessage),window.addEventListener("keydown",this._onKeyDown),this.previewElement?.addEventListener("click",this._onPreviewClick)}destroy(){window.removeEventListener("message",this._onMessage),window.removeEventListener("keydown",this._onKeyDown),this.previewElement?.removeEventListener("click",this._onPreviewClick),this._disconnectPlaceholderObserver(),Ke(this.hydrationIdleId),this.hydrationIdleId=null,this.hydrationQueue=[],this._exitMaximizedEmbed(),document.body.classList.remove("excalidraw-maximized-open"),this.embedEntries.forEach(e=>{this._clearEntryBootTimeout(e),e.wrapper?.remove(),e.placeholder=null}),this.embedEntries.clear(),this.followedPeerIdsByFilePath.clear(),this.overlayRoot?.remove(),this.overlayRoot=null,this.maximizedRoot?.remove(),this.maximizedRoot=null}async setFollowedUser(e,t=null){if(!e)return!1;this.followedPeerIdsByFilePath.set(e,t||null);let i=this._findEntryByFilePath(e);return i&&(i.wrapper||await this._hydrateEntry(i),i.followedPeerId=this.followedPeerIdsByFilePath.get(e)??null,this._syncEntryFollowState(i)),!0}detachForCommit(){this._disconnectPlaceholderObserver(),Ke(this.hydrationIdleId),this.hydrationIdleId=null,this.hydrationQueue=[],this.hydrationInProgress=!1,this.overlayRoot&&(this.overlayRoot.hidden=!0),this.maximizedRoot&&(this.maximizedRoot.hidden=!0),this.embedEntries.forEach(e=>{e.queued=!1,e.placeholder=null})}setHydrationPaused(e){if(this.hydrationPaused=!!e,this.hydrationPaused){Ke(this.hydrationIdleId),this.hydrationIdleId=null;return}this.hydrateVisibleEmbeds(),this._scheduleHydration()}reconcileEmbeds(e,{isLargeDocument:t=!1}={}){this.isLargeDocument=!!t,this._disconnectPlaceholderObserver(),Ke(this.hydrationIdleId),this.hydrationIdleId=null,this.hydrationQueue=[],this.hydrationInProgress=!1;let i=Array.from(e.querySelectorAll(".excalidraw-embed-placeholder[data-embed-key]")).map(a=>({filePath:a.dataset.embedTarget,key:a.dataset.embedKey,label:a.dataset.embedLabel||a.dataset.embedTarget,placeholder:a})),{nextEntries:s,removedEntries:r}=Ve(this.embedEntries,i);this._adoptReusableEntries(s,r),r.forEach(a=>this._destroyEntry(a)),this.embedEntries=s,this._ensurePlaceholderObserver(),this.embedEntries.forEach(a=>{if(a.queued=!1,a.followedPeerId=this.followedPeerIdsByFilePath.get(a.filePath),a.wrapper){this._updateEmbedLabel(a),this._attachWrapper(a);return}a.placeholder&&this.placeholderObserver?.observe(a.placeholder)}),this.hydrationPaused||this.hydrateVisibleEmbeds(),this.syncLayout()}hydrateVisibleEmbeds(){if(this.hydrationPaused)return;let e=this.isLargeDocument?180:420;this.embedEntries.forEach(t=>{t.wrapper||!t.placeholder?.isConnected||vn(t.placeholder,this.previewContainer,e)&&this._enqueueHydration(t,{prioritize:!0})})}updateTheme(e){this.embedEntries.forEach(t=>{this._postMessageToEntry(t,{source:"collabmd-host",type:"set-theme",theme:e})})}updateLocalUser(e){this.embedEntries.forEach(t=>{this._syncEntryUser(t,e)})}_ensurePlaceholderObserver(){this.previewContainer&&(this.placeholderObserver=new IntersectionObserver(e=>{e.forEach(t=>{if(!t.isIntersecting)return;let i=this.embedEntries.get(t.target.dataset.embedKey);i&&this._enqueueHydration(i)})},{root:this.previewContainer,rootMargin:this.isLargeDocument?"180px 0px":"420px 0px"}))}_disconnectPlaceholderObserver(){this.placeholderObserver&&(this.placeholderObserver.disconnect(),this.placeholderObserver=null)}_enqueueHydration(e,{prioritize:t=!1}={}){if(!(!e||e.wrapper||e.queued)&&(e.queued=!0,t?this.hydrationQueue.unshift(e.key):this.hydrationQueue.push(e.key),!this.hydrationPaused)){if(t&&!this.hydrationInProgress&&this.hydrationIdleId===null){this._flushHydrationQueue();return}this._scheduleHydration()}}_scheduleHydration(){this.hydrationPaused||this.hydrationInProgress||this.hydrationIdleId!==null||(this.hydrationIdleId=yn(()=>{this.hydrationIdleId=null,this._flushHydrationQueue()},un))}async _flushHydrationQueue(){if(this.hydrationPaused||this.hydrationInProgress)return;let e=null;for(;this.hydrationQueue.length>0&&!e;){let t=this.hydrationQueue.shift(),i=this.embedEntries.get(t);if(!i||i.wrapper||!i.placeholder?.isConnected){i&&(i.queued=!1);continue}e=i}e&&(this.hydrationInProgress=!0,e.queued=!1,await this._hydrateEntry(e),this.hydrationInProgress=!1,this.hydrationQueue.length>0&&this._scheduleHydration())}async _hydrateEntry(e){if(!(!e.placeholder?.isConnected&&!e.wrapper)){if(!e.wrapper){let t=this._createEmbedContainer(e);e.wrapper=t.wrapper,e.iframe=t.iframe,e.labelElement=t.labelElement,e.instanceId=t.instanceId,e.isReady=!1,e.bootAttempts=(e.bootAttempts??0)+1,this._armEntryBootTimeout(e)}e.followedPeerId=this.followedPeerIdsByFilePath.get(e.filePath),this._updateEmbedLabel(e),this._attachWrapper(e)}}_attachWrapper(e){let t=e.placeholder?.isConnected?e.placeholder:this.previewElement?.querySelector(`.excalidraw-embed-placeholder[data-embed-key="${e.key}"]`);if(!t)return;if(e.placeholder=t,this._syncMountedEntryMetadata(e),this._shouldInlineFilePreview(e)){e.wrapper.style.position="",e.wrapper.style.top="",e.wrapper.style.left="",e.wrapper.style.width="",e.wrapper.style.margin="",e.wrapper.style.pointerEvents="auto",t.replaceWith(e.wrapper),e.placeholder=null;return}let i=this._ensureOverlayRoot();i.hidden=!1,e.wrapper?.parentElement!==i&&i.appendChild(e.wrapper),this._syncEntryLayout(e)}_adoptReusableEntries(e,t){e.forEach((i,s)=>{if(i.wrapper||i.iframe)return;let r=t.findIndex(o=>o.filePath===i.filePath&&this._getEntryMode(o)===this._getEntryMode(i)&&(o.wrapper||o.iframe));if(r<0)return;let[a]=t.splice(r,1);a.filePath=i.filePath,a.key=i.key,a.label=i.label,a.placeholder=i.placeholder,a.queued=!1,a.reusedFromEmbed=this._isFilePreviewEntry(i),e.set(s,a)})}_destroyEntry(e){this.maximizedEmbed?.wrapper===e.wrapper&&this._exitMaximizedEmbed(),this._clearEntryBootTimeout(e),this._resetPlaceholderLayout(e),e.wrapper?.remove(),e.placeholder=null}_armEntryBootTimeout(e){this._clearEntryBootTimeout(e),e.bootTimerId=window.setTimeout(()=>{this._handleEntryBootTimeout(e)},mn)}_clearEntryBootTimeout(e){e?.bootTimerId&&(window.clearTimeout(e.bootTimerId),e.bootTimerId=null)}async _handleEntryBootTimeout(e){if(e?.iframe?.isConnected){if((e.bootAttempts??0)>=fn){this._clearEntryBootTimeout(e),this.toastController?.show(`Excalidraw embed timed out: ${e.label}`);return}await this._retryEntryBootstrap(e)}}async _retryEntryBootstrap(e){e&&(this._clearEntryBootTimeout(e),this._resetPlaceholderLayout(e),this.maximizedEmbed?.wrapper===e.wrapper&&this._exitMaximizedEmbed(),e.wrapper?.remove(),e.wrapper=null,e.iframe=null,e.labelElement=null,e.instanceId=null,e.isReady=!1,await this._hydrateEntry(e))}_findEntryByContentWindow(e){if(!e)return null;for(let t of this.embedEntries.values())if(t.iframe?.contentWindow===e)return t;return null}_findEntryByFilePath(e){if(!e)return null;for(let t of this.embedEntries.values())if(t.filePath===e)return t;return null}_updateEmbedLabel(e){e.labelElement&&(e.labelElement.textContent=e.label.replace(/\.excalidraw$/i,""))}_syncMountedEntryMetadata(e){e.wrapper&&(e.wrapper.dataset.embedKey=e.key,e.wrapper.dataset.file=e.filePath),e.iframe&&(e.iframe.title=`Excalidraw: ${e.filePath}`)}_buildIframeUrl(e){let t=new URL(kt(wn)),i=this.getTheme?.()||"dark";t.searchParams.set("file",e.filePath),t.searchParams.set("theme",i),t.searchParams.set("boot",e.instanceId||""),this._isFilePreviewEntry(e)||t.searchParams.set("mode","preview");let s=this.getLocalUser?.();s?.name&&t.searchParams.set("userName",s.name),s?.color&&t.searchParams.set("userColor",s.color),s?.colorLight&&t.searchParams.set("userColorLight",s.colorLight),s?.peerId&&t.searchParams.set("userPeerId",s.peerId);let r=new URLSearchParams(window.location.search),a=r.get("server");return a&&t.searchParams.set("server",a),r.get("test")==="1"&&t.searchParams.set("test","1"),r.has("syncTimeoutMs")&&t.searchParams.set("syncTimeoutMs",r.get("syncTimeoutMs")),t}_createEmbedContainer(e){let t=document.createElement("div");t.className="excalidraw-embed diagram-preview-shell",t.dataset.embedKey=e.key,t.dataset.file=e.filePath;let i=document.createElement("div");i.className="excalidraw-embed-header diagram-preview-toolbar";let s=document.createElement("span");s.className="excalidraw-embed-icon",s.innerHTML='<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 19l7-7 3 3-7 7-3-3z"/><path d="M18 13l-1.5-7.5L2 2l3.5 14.5L13 18l5-5z"/><path d="M2 2l7.586 7.586"/><circle cx="11" cy="11" r="2"/></svg>';let r=document.createElement("span");r.className="excalidraw-embed-label",r.textContent=e.label.replace(/\.excalidraw$/i,"");let a=document.createElement("button");a.type="button",a.className="excalidraw-embed-btn diagram-preview-action-btn",a.title="Edit in Excalidraw",a.setAttribute("aria-label","Edit in Excalidraw"),T(a,"edit");let o=document.createElement("button");o.type="button",o.className="excalidraw-embed-btn diagram-preview-action-btn",o.title="Maximize diagram",o.setAttribute("aria-label","Maximize diagram"),T(o,"maximize"),i.append(s,r),this._isFilePreviewEntry(e)||i.append(a),i.append(o);let l=document.createElement("iframe");l.className="excalidraw-embed-iframe",l.dataset.instanceId=String(++this.instanceCounter),e.instanceId=l.dataset.instanceId,l.src=this._buildIframeUrl(e).toString(),l.setAttribute("loading","eager"),l.title=`Excalidraw: ${e.filePath}`,l.style.height=`${de}px`;let h=document.createElement("div");h.className="excalidraw-embed-resizer",h.title="Drag to resize",this._setupResizer(h,l,()=>this._syncEntryLayout(e)),t.append(i,l,h);let c=!1,u=`${de}px`,f=()=>{T(o,c?"restore":"maximize"),o.title=c?"Restore diagram size":"Maximize diagram",o.setAttribute("aria-label",c?"Restore diagram size":"Maximize diagram")},d=()=>{c&&(c=!1,t.classList.remove("is-maximized"),f(),document.body.classList.remove("excalidraw-maximized-open"),this._restoreWrapperMount(e),l.style.height=u,this.maximizedEmbed?.wrapper===t&&(this.maximizedEmbed=null),this._syncEntryLayout(e))},g=()=>{c||(this._exitMaximizedEmbed(),c=!0,u=l.style.height||`${de}px`,this._mountWrapperInMaximizedRoot(e),t.classList.add("is-maximized"),f(),document.body.classList.add("excalidraw-maximized-open"),this.maximizedEmbed={wrapper:t,exit:d},this._syncEntryLayout(e))};return o.addEventListener("click",()=>{c?d():g()}),a.addEventListener("click",()=>{this.onOpenFile?.(e.filePath)}),f(),{iframe:l,instanceId:l.dataset.instanceId,labelElement:r,wrapper:t}}_setupResizer(e,t,i=null){let s=0,r=0,a=l=>{let h=l.clientY-s,c=Math.min(Math.max(r+h,gn),pn);t.style.height=`${c}px`,t.style.pointerEvents="none"},o=()=>{t.style.pointerEvents="",document.removeEventListener("pointermove",a),document.removeEventListener("pointerup",o),i?.()};e.addEventListener("pointerdown",l=>{l.preventDefault(),s=l.clientY,r=t.offsetHeight,document.addEventListener("pointermove",a),document.addEventListener("pointerup",o)})}_ensureOverlayRoot(){if(this.overlayRoot?.isConnected&&this.overlayRoot.parentElement===this.previewElement)return this.overlayRoot;let e=this.previewElement?.querySelector('[data-excalidraw-overlay-root="true"]');return e||(e=document.createElement("div"),e.dataset.excalidrawOverlayRoot="true",e.className="excalidraw-embed-overlay-root",this.previewElement?.appendChild(e)),this.overlayRoot=e,e}_ensureMaximizedRoot(){if(this.maximizedRoot?.isConnected&&this.maximizedRoot.parentElement===document.body)return this.maximizedRoot;let e=document.body.querySelector('[data-excalidraw-maximized-root="true"]');return e||(e=document.createElement("div"),e.dataset.excalidrawMaximizedRoot="true",e.className="excalidraw-maximized-root",document.body.appendChild(e)),this.maximizedRoot=e,e}_isFilePreviewEntry(e){return e?.key===`${e?.filePath}#file-preview`}_getEntryMode(e){return this._isFilePreviewEntry(e)?"edit":"preview"}_shouldInlineFilePreview(e){return this._isFilePreviewEntry(e)&&!e?.reusedFromEmbed}_resetPlaceholderLayout(e){!e?.placeholder?.isConnected||this._shouldInlineFilePreview(e)||(e.placeholder.classList.remove("is-hydrated"),e.placeholder.removeAttribute("data-embed-hydrated"),e.placeholder.style.height="",e.placeholder.style.pointerEvents="")}_mountWrapperInMaximizedRoot(e){if(!e?.wrapper)return;let t=this._ensureMaximizedRoot();t.hidden=!1,e.restoreParent=e.wrapper.parentElement||null,e.restoreNextSibling=e.wrapper.nextSibling||null,e.wrapper.style.position="",e.wrapper.style.top="",e.wrapper.style.left="",e.wrapper.style.width="",e.wrapper.style.margin="",e.wrapper.parentElement!==t&&t.appendChild(e.wrapper)}_restoreWrapperMount(e){if(e?.wrapper){if(this._shouldInlineFilePreview(e)){let{restoreParent:t,restoreNextSibling:i}=e;t?.isConnected&&(i?.parentElement===t?t.insertBefore(e.wrapper,i):t.appendChild(e.wrapper))}else{let t=this._ensureOverlayRoot();t.hidden=!1,e.wrapper.parentElement!==t&&t.appendChild(e.wrapper)}e.restoreParent=null,e.restoreNextSibling=null,this.maximizedRoot&&this.maximizedRoot.childElementCount===0&&(this.maximizedRoot.hidden=!0)}}_syncEntryLayout(e){if(!e?.wrapper||this._shouldInlineFilePreview(e))return;let t=e.placeholder?.isConnected?e.placeholder:this.previewElement?.querySelector(`.excalidraw-embed-placeholder[data-embed-key="${e.key}"]`);if(!t)return;e.placeholder=t,t.classList.add("is-hydrated"),t.dataset.embedHydrated="true",t.style.pointerEvents="none",this._isFilePreviewEntry(e)&&t.childElementCount>0&&t.replaceChildren();let i=e.wrapper.classList.contains("is-maximized"),s=e.wrapper.querySelector(".excalidraw-embed-header")?.offsetHeight||0,r=e.iframe?.offsetHeight||Number.parseFloat(e.iframe?.style.height||"")||de,a=i?0:e.wrapper.querySelector(".excalidraw-embed-resizer")?.offsetHeight||0,o=Math.ceil(s+r+a);if(i||(e.inlineHeightPx=o),t.style.height=`${Math.ceil(e.inlineHeightPx||o||de)}px`,e.wrapper.style.pointerEvents="auto",i){e.wrapper.style.position="",e.wrapper.style.top="",e.wrapper.style.left="",e.wrapper.style.width="",e.wrapper.style.margin="";return}e.wrapper.style.position="absolute",e.wrapper.style.top=`${t.offsetTop}px`,e.wrapper.style.left=`${t.offsetLeft}px`,e.wrapper.style.width=`${t.offsetWidth}px`,e.wrapper.style.margin="0"}syncLayout(){this.embedEntries.forEach(e=>{e.wrapper&&!this._shouldInlineFilePreview(e)&&this._syncEntryLayout(e)})}_onPreviewClick(e){let t=e.target.closest(".excalidraw-embed-placeholder-btn");if(!t)return;e.preventDefault();let i=this.embedEntries.get(t.dataset.embedKey);i&&this._hydrateEntry(i)}_onMessage(e){if(e.origin!==window.location.origin)return;let t=e.data;if(!t||t.source!=="excalidraw-editor")return;let i=this._findEntryByContentWindow(e.source);if(i){if(t.type==="ready"){i.isReady=!0,this._clearEntryBootTimeout(i),this._syncEntryUser(i),this._postMessageToEntry(i,{source:"collabmd-host",type:"set-theme",theme:this.getTheme?.()||"dark"}),this._syncEntryFollowState(i);return}t.type==="error"&&(i.isReady=!1,this._handleEntryBootTimeout(i))}}_onKeyDown(e){e.key==="Escape"&&this._exitMaximizedEmbed()}_exitMaximizedEmbed(){this.maximizedEmbed?.exit&&this.maximizedEmbed.exit(),this.maximizedEmbed=null,document.body.classList.remove("excalidraw-maximized-open")}_postMessageToEntry(e,t){e?.iframe?.contentWindow?.postMessage(t,window.location.origin)}_syncEntryUser(e,t=null){let i=t||this.getLocalUser?.();i&&this._postMessageToEntry(e,{source:"collabmd-host",type:"set-user",user:{color:i.color||"",colorLight:i.colorLight||"",name:i.name||"",peerId:i.peerId||""}})}_syncEntryFollowState(e){!e?.isReady||e.followedPeerId===void 0||this._postMessageToEntry(e,{source:"collabmd-host",type:"follow-user",peerId:e.followedPeerId})}};function bn(n){return String(n??"").replace(/\/+$/u,"").split("/").filter(Boolean).pop()||""}function Cn(){return JSON.stringify({type:"excalidraw",version:2,source:"collabmd",elements:[],appState:{viewBackgroundColor:"#ffffff",gridSize:null},files:{}})}var je=class{constructor({onFileDelete:e,onFileSelect:t,state:i,toastController:s,vaultClient:r,view:a,refresh:o}){this.onFileDelete=e,this.onFileSelect=t,this.state=i,this.toastController=s,this.vaultClient=r,this.view=a,this.refresh=o,this.newFileButton=document.getElementById("newFileBtn"),this.newDrawingButton=document.getElementById("newDrawingBtn"),this.newMermaidButton=document.getElementById("newMermaidBtn"),this.newPlantumlButton=document.getElementById("newPlantumlBtn"),this.newFolderButton=document.getElementById("newFolderBtn"),this.refreshButton=document.getElementById("refreshFilesBtn"),this.actionDialog=document.getElementById("fileActionDialog"),this.actionForm=document.getElementById("fileActionForm"),this.actionTitle=document.getElementById("fileActionTitle"),this.actionCopy=document.getElementById("fileActionCopy"),this.actionField=document.getElementById("fileActionField"),this.actionLabel=document.getElementById("fileActionLabel"),this.actionInput=document.getElementById("fileActionInput"),this.actionHint=document.getElementById("fileActionHint"),this.actionNote=document.getElementById("fileActionNote"),this.actionCancelButton=document.getElementById("fileActionCancel"),this.actionSubmitButton=document.getElementById("fileActionSubmit"),this.pendingAction=null,this.actionBusy=!1}initialize(){this.newFileButton?.addEventListener("click",()=>this.handleNewFile()),this.newDrawingButton?.addEventListener("click",()=>this.handleNewDrawing()),this.newMermaidButton?.addEventListener("click",()=>this.handleNewMermaid()),this.newPlantumlButton?.addEventListener("click",()=>this.handleNewPlantUml()),this.newFolderButton?.addEventListener("click",()=>this.handleNewFolder()),this.refreshButton?.addEventListener("click",()=>this.refresh()),this.actionCancelButton?.addEventListener("click",()=>this.closeActionDialog()),this.actionForm?.addEventListener("submit",e=>{e.preventDefault(),this.handleActionSubmit()}),this.actionDialog?.addEventListener("close",()=>this.resetActionDialog())}createContextMenuItems(e=""){return[{label:"New markdown file",onSelect:()=>this.handleNewFile({parentDir:e})},{label:"New Excalidraw drawing",onSelect:()=>this.handleNewDrawing({parentDir:e})},{label:"New Mermaid diagram",onSelect:()=>this.handleNewMermaid({parentDir:e})},{label:"New PlantUML diagram",onSelect:()=>this.handleNewPlantUml({parentDir:e})},{label:"New folder",onSelect:()=>this.handleNewFolder({parentDir:e})}]}getFileContextMenuItems(e){return[{label:"Rename",onSelect:()=>this.handleRename(e)},{label:"Delete",danger:!0,onSelect:()=>this.handleDelete(e)}]}showToast(e){e&&this.toastController?.show(String(e))}showError(e,t){this.showToast(t?.message?`${e}: ${t.message}`:e)}ensureExtension(e,t){return Yt(e,t)}openActionDialog({title:e,copy:t,label:i="Path",hint:s="",note:r="",placeholder:a="",value:o="",submitLabel:l="Save",destructive:h=!1,requiresInput:c=!0,emptyMessage:u="A value is required",onSubmit:f}){!this.actionDialog||!this.actionTitle||!this.actionCopy||!this.actionSubmitButton||!this.actionCancelButton||c&&!this.actionInput||(this.actionDialog.open&&(typeof this.actionDialog.close=="function"?this.actionDialog.close():(this.actionDialog.removeAttribute("open"),this.resetActionDialog())),this.pendingAction={requiresInput:c,emptyMessage:u,onSubmit:f},this.view?.removeContextMenu?.(),this.actionTitle.textContent=e,this.actionCopy.textContent=t,this.actionField&&(this.actionField.hidden=!c),this.actionLabel&&(this.actionLabel.textContent=i),this.actionInput&&(this.actionInput.value=o,this.actionInput.placeholder=a,this.actionInput.required=c,this.actionInput.disabled=!1),this.actionHint&&(this.actionHint.textContent=s,this.actionHint.hidden=!c||!s),this.actionNote&&(this.actionNote.textContent=r,this.actionNote.hidden=!r,this.actionNote.classList.toggle("is-danger",h)),this.actionSubmitButton.textContent=l,this.actionSubmitButton.disabled=!1,this.actionSubmitButton.classList.toggle("btn-primary",!h),this.actionSubmitButton.classList.toggle("btn-danger",h),this.actionCancelButton.disabled=!1,typeof this.actionDialog.showModal=="function"?this.actionDialog.showModal():this.actionDialog.setAttribute("open","true"),requestAnimationFrame(()=>{if(!c||!this.actionInput){this.actionSubmitButton.focus();return}this.actionInput.focus(),o&&this.actionInput.select()}))}resetActionDialog(){this.pendingAction=null,this.actionBusy=!1,this.actionField&&(this.actionField.hidden=!1),this.actionLabel&&(this.actionLabel.textContent="Path"),this.actionInput&&(this.actionInput.value="",this.actionInput.placeholder="",this.actionInput.required=!0,this.actionInput.disabled=!1),this.actionHint&&(this.actionHint.textContent="",this.actionHint.hidden=!0),this.actionNote&&(this.actionNote.textContent="",this.actionNote.hidden=!0,this.actionNote.classList.remove("is-danger")),this.actionSubmitButton&&(this.actionSubmitButton.textContent="Save",this.actionSubmitButton.disabled=!1,this.actionSubmitButton.classList.add("btn-primary"),this.actionSubmitButton.classList.remove("btn-danger")),this.actionCancelButton&&(this.actionCancelButton.disabled=!1)}closeActionDialog(){if(this.actionDialog){if(this.actionDialog.open&&typeof this.actionDialog.close=="function"){this.actionDialog.close();return}this.actionDialog.removeAttribute("open"),this.resetActionDialog()}}setActionDialogBusy(e){this.actionBusy=e,this.actionInput&&(this.actionInput.disabled=e||!(this.pendingAction?.requiresInput??!0)),this.actionCancelButton&&(this.actionCancelButton.disabled=e),this.actionSubmitButton&&(this.actionSubmitButton.disabled=e)}async handleActionSubmit(){if(!this.pendingAction?.onSubmit||this.actionBusy)return;let e=this.pendingAction.requiresInput,t=e?this.actionInput?.value.trim()??"":void 0;if(e&&!t){this.showToast(this.pendingAction.emptyMessage),this.actionInput?.focus();return}this.setActionDialogBusy(!0);let i=!1;try{i=await this.pendingAction.onSubmit(t)}catch(s){i=!1,this.showError("Failed to complete action",s)}if(this.setActionDialogBusy(!1),i!==!1){this.closeActionDialog();return}e&&this.actionInput&&(this.actionInput.focus(),this.actionInput.select())}async createVaultFile(e,t,{openAfterCreate:i=!1,errorMessage:s="Failed to create file"}={}){try{return await this.vaultClient.createFile({content:t,path:e}),this.state.expandDirectoryPath(e,{includeLeaf:!1}),await this.refresh(),i&&this.onFileSelect?.(e),!0}catch(r){return this.showToast(r?.message||s),!1}}async createDirectory(e){let t=x(e);if(!t)return this.showToast("Folder path is required"),!1;try{return await this.vaultClient.createDirectory(t),this.state.expandDirectoryPath(t),await this.refresh(),!0}catch(i){return this.showToast(i?.message||"Failed to create folder"),!1}}async renameVaultFile(e,t,i){let s=String(t??"").trim();if(!s)return this.showToast("File name is required"),!1;if(/[\\/]/u.test(s))return this.showToast("Rename only supports the file name right now"),!1;let r=q(s).trim();if(!r)return this.showToast("File name is required"),!1;let o=`${e.includes("/")?e.substring(0,e.lastIndexOf("/")+1):""}${r}${i}`;if(o===e)return!0;try{return await this.vaultClient.renameFile({newPath:o,oldPath:e}),this.state.expandDirectoryPath(o,{includeLeaf:!1}),await this.refresh(),this.state.activeFilePath===e&&(this.state.activeFilePath=o,this.onFileSelect?.(o)),!0}catch(l){return this.showToast(l?.message||"Failed to rename"),!1}}async deleteVaultFile(e){try{return await this.vaultClient.deleteFile(e),await this.refresh(),this.state.activeFilePath===e&&(this.state.activeFilePath=null,this.onFileDelete?.(e)),!0}catch(t){return this.showToast(t?.message||"Failed to delete"),!1}}getCreateContext(e=""){let t=x(e);return{hintPrefix:t?'Use "/" to create nested items under this folder.':'Use "/" to place it inside a folder.',inputLabelSuffix:t?"name or path":"path",note:t?`Parent folder: ${t}`:"",normalizedParentDir:t}}handleNewFile({parentDir:e=""}={}){let t=this.getCreateContext(e);this.openActionDialog({title:"Create markdown file",copy:t.normalizedParentDir?"Add a new note inside the selected folder. It opens immediately after creation.":"Add a new note to the vault. It opens immediately after creation.",label:`File ${t.inputLabelSuffix}`,hint:`${t.hintPrefix} ".md" is added automatically.`,note:t.note,placeholder:t.normalizedParentDir?"my-note":"notes/my-note",submitLabel:"Create file",emptyMessage:"File path is required",onSubmit:i=>{let s=x(i);if(!s)return this.showToast("File path is required"),!1;let r=this.ensureExtension(se(t.normalizedParentDir,s),".md");return this.createVaultFile(r,Pe(r),{errorMessage:"Failed to create file",openAfterCreate:!0})}})}handleNewFolder({parentDir:e=""}={}){let t=this.getCreateContext(e);this.openActionDialog({title:"Create folder",copy:t.normalizedParentDir?"Add a new folder inside the selected folder.":"Add a new folder to organize notes and diagrams.",label:`Folder ${t.inputLabelSuffix}`,hint:t.hintPrefix,note:t.note,placeholder:t.normalizedParentDir?"archive":"notes/archive",submitLabel:"Create folder",emptyMessage:"Folder path is required",onSubmit:i=>this.createDirectory(se(t.normalizedParentDir,i))})}handleNewDrawing({parentDir:e=""}={}){let t=this.getCreateContext(e);this.openActionDialog({title:"Create Excalidraw drawing",copy:t.normalizedParentDir?"Start a new drawing inside the selected folder.":"Start a new drawing file in the vault.",label:`Drawing ${t.inputLabelSuffix}`,hint:`${t.hintPrefix} ".excalidraw" is added automatically.`,note:t.note,placeholder:t.normalizedParentDir?"architecture":"diagrams/architecture",submitLabel:"Create drawing",emptyMessage:"Drawing path is required",onSubmit:i=>{let s=x(i);if(!s)return this.showToast("Drawing path is required"),!1;let r=this.ensureExtension(se(t.normalizedParentDir,s),".excalidraw");return this.createVaultFile(r,Cn(),{errorMessage:"Failed to create drawing",openAfterCreate:!0})}})}handleNewMermaid({parentDir:e=""}={}){let t=this.getCreateContext(e);this.openActionDialog({title:"Create Mermaid diagram",copy:t.normalizedParentDir?"Create a new `.mmd` or `.mermaid` file inside the selected folder.":"Create a new `.mmd` or `.mermaid` file with starter diagram content.",label:`Diagram ${t.inputLabelSuffix}`,hint:`${t.hintPrefix} ".mmd" is added automatically unless you enter ".mermaid".`,note:t.note,placeholder:t.normalizedParentDir?"flow":"diagrams/flow",submitLabel:"Create diagram",emptyMessage:"Diagram path is required",onSubmit:i=>{let s=x(i);if(!s)return this.showToast("Diagram path is required"),!1;let r=Xt(se(t.normalizedParentDir,s));return this.createVaultFile(r.path,r.content,{errorMessage:"Failed to create Mermaid diagram",openAfterCreate:!0})}})}handleNewPlantUml({parentDir:e=""}={}){let t=this.getCreateContext(e);this.openActionDialog({title:"Create PlantUML diagram",copy:t.normalizedParentDir?"Create a new `.puml` or `.plantuml` file inside the selected folder.":"Create a new `.puml` or `.plantuml` file with starter diagram content.",label:`Diagram ${t.inputLabelSuffix}`,hint:`${t.hintPrefix} ".puml" is added automatically unless you enter ".plantuml".`,note:t.note,placeholder:t.normalizedParentDir?"sequence-flow":"diagrams/sequence-flow",submitLabel:"Create diagram",emptyMessage:"Diagram path is required",onSubmit:i=>{let s=x(i);if(!s)return this.showToast("Diagram path is required"),!1;let r=Jt(se(t.normalizedParentDir,s));return this.createVaultFile(r.path,r.content,{errorMessage:"Failed to create PlantUML diagram",openAfterCreate:!0})}})}handleRename(e){let t=bn(e),i=Tt(t)??".md";this.openActionDialog({title:"Rename file",copy:"Update the file name without changing its current type.",label:"Name",hint:`${i} is kept automatically.`,value:q(t),submitLabel:"Rename file",emptyMessage:"File name is required",onSubmit:s=>this.renameVaultFile(e,s,i)})}handleDelete(e){this.openActionDialog({title:"Delete file",copy:"This permanently removes the file from the vault.",note:e,submitLabel:"Delete file",destructive:!0,requiresInput:!1,onSubmit:()=>this.deleteVaultFile(e)})}};function ki(n,e=[]){for(let t of n){if(t.type==="file"||t.type==="excalidraw"||t.type==="mermaid"||t.type==="plantuml"||t.type==="image"){e.push(t.path);continue}t.type==="directory"&&Array.isArray(t.children)&&ki(t.children,e)}return e}var Qe=class{constructor(){this.tree=[],this.flatFiles=[],this.activeFilePath=null,this.expandedDirs=new Set,this.searchQuery=""}setTree(e){this.tree=Array.isArray(e)?e:[],this.flatFiles=ki(this.tree,[])}setSearchQuery(e){this.searchQuery=String(e??"").trim().toLowerCase()}getSearchMatches(){return this.searchQuery?this.flatFiles.filter(e=>e.toLowerCase().includes(this.searchQuery)):[]}setActiveFile(e){this.activeFilePath=e||null,e&&this.expandDirectoryPath(e,{includeLeaf:!1})}toggleDirectory(e){return this.expandedDirs.has(e)?(this.expandedDirs.delete(e),!1):(this.expandedDirs.add(e),!0)}expandDirectoryPath(e,{includeLeaf:t=!0}={}){let i=x(e);if(!i)return;let s=i.split("/"),r=t?s.length:Math.max(s.length-1,0),a="";for(let o=0;o<r;o+=1)a=a?`${a}/${s[o]}`:s[o],this.expandedDirs.add(a)}};function En(n){return String(n??"").replace(/\/+$/u,"").split("/").filter(Boolean).pop()||""}var Ze=class{constructor({onDirectoryToggle:e,onFileContextMenu:t,onFileSelect:i,onSearchChange:s,onTreeContextMenu:r}){this.onDirectoryToggle=e,this.onFileContextMenu=t,this.onFileSelect=i,this.onSearchChange=s,this.onTreeContextMenu=r,this.treeContainer=document.getElementById("fileTree"),this.searchInput=document.getElementById("fileSearchInput")}initialize(){this.searchInput?.addEventListener("input",e=>{this.onSearchChange?.(e.target.value)}),this.treeContainer?.addEventListener("contextmenu",e=>{e.target.closest(".file-tree-item")||(e.preventDefault(),this.onTreeContextMenu?.(e))})}render({activeFilePath:e,expandedDirs:t,searchMatches:i,searchQuery:s,tree:r}){if(!this.treeContainer)return;if(s){this.renderSearchResults(i,e);return}if(this.treeContainer.innerHTML="",r.length===0){this.treeContainer.innerHTML='<div class="file-tree-empty">No vault files found</div>';return}let a=document.createDocumentFragment();this.renderNodes(r,a,{activeFilePath:e,depth:0,expandedDirs:t}),this.treeContainer.appendChild(a)}renderSearchResults(e,t){if(!this.treeContainer)return;if(this.treeContainer.innerHTML="",e.length===0){this.treeContainer.innerHTML='<div class="file-tree-empty">No matches</div>';return}let i=document.createDocumentFragment();for(let s of e)i.appendChild(this.createFileItem({activeFilePath:t,depth:0,filePath:s,fileType:It(s)??"file",name:En(s)}));this.treeContainer.appendChild(i)}renderNodes(e,t,{activeFilePath:i,depth:s,expandedDirs:r}){for(let a of e){if(a.type==="directory"){t.appendChild(this.createDirectoryItem(a,{activeFilePath:i,depth:s,expandedDirs:r}));continue}t.appendChild(this.createFileItem({activeFilePath:i,depth:s,filePath:a.path,fileType:a.type,name:a.name}))}}createDirectoryItem(e,{activeFilePath:t,depth:i,expandedDirs:s}){let r=document.createElement("div");r.className="file-tree-group";let a=document.createElement("button");a.className="file-tree-item file-tree-dir",a.style.setProperty("--depth",i),a.dataset.depth=i;let o=s.has(e.path);if(a.setAttribute("aria-expanded",String(o)),a.innerHTML=`
|
|
47
|
+
`,e.appendChild(t),n>1){let i=document.createElement("span");i.className="comment-marker-count",i.textContent=String(n),e.appendChild(i)}return e}var Ze=class{constructor({commentSelectionButton:e,commentsDrawer:t,commentsDrawerEmpty:i,commentsDrawerList:s,commentsToggleButton:r,editorContainer:a,onWillOpenDrawer:o,onCreateThread:l,onNavigateToLine:h,onReplyToThread:c,onToggleReaction:u,onResolveThread:p,previewContainer:d,previewElement:w}){this.commentSelectionButton=e,this.commentsDrawer=t,this.commentsDrawerEmpty=i,this.commentsDrawerList=s,this.commentsToggleButton=r,this.editorContainer=a,this.onWillOpenDrawer=o,this.onCreateThread=l,this.onNavigateToLine=h,this.onReplyToThread=c,this.onToggleReaction=u,this.onResolveThread=p,this.previewContainer=d,this.previewElement=w,this.currentFile=null,this.fileKind="markdown",this.supported=!1,this.drawerOpen=!1,this.threads=[],this.selectionAnchor=null,this.pendingSelectionAnchor=null,this.committedSelectionAnchor=null,this.selectionRevealTimer=0,this.pointerSelecting=!1,this.session=null,this.activeCard=null,this.hoveredEditorGroupKeys=[],this.hoveredEditorGroupKeysSignature="",this.hoveredPreviewGroupKeys=[],this.hoveredPreviewGroupKeysSignature="",this.previewHoverRegions=[],this.lastPreviewPointerPosition=null,this.editorLayer=null,this.previewLayer=null,this.previewHighlightLayer=null,this.cardRoot=null,this.pendingCardFocusElement=null,this.reactionPicker=null,this.layoutFrame=0,this.timeFormatter=new Intl.DateTimeFormat(void 0,{day:"numeric",hour:"numeric",minute:"2-digit",month:"short"}),this.handleEditorScroll=()=>this.scheduleLayoutRefresh(),this.handlePreviewScroll=()=>this.scheduleLayoutRefresh(),this.handleWindowResize=()=>this.scheduleLayoutRefresh(),this.handlePreviewPointerMove=m=>{this.lastPreviewPointerPosition={x:m.clientX,y:m.clientY},this.updateHoveredPreviewGroups(this.getPreviewGroupKeysAtPoint(m.clientX,m.clientY))},this.handlePreviewPointerLeave=()=>{this.lastPreviewPointerPosition=null,this.updateHoveredPreviewGroups([])},this.handlePreviewFocusIn=m=>{this.updateHoveredPreviewGroups(this.getPreviewGroupKeysForTarget(m.target))},this.handlePreviewFocusOut=m=>{this.updateHoveredPreviewGroups(this.getPreviewGroupKeysForTarget(m.relatedTarget))},this.handleCommentSelectionButtonPointerDown=m=>{m.preventDefault()},this.handleEditorPointerDown=m=>{m.button!==0||!this.supported||!this.session||!m.target?.closest?.(".cm-editor")||m.target?.closest?.(".comment-editor-layer")||(this.pointerSelecting=!0,this.clearSelectionRevealTimer(),this.committedSelectionAnchor&&(this.committedSelectionAnchor=null,this.scheduleLayoutRefresh()))},this.handleDocumentPointerUp=()=>{this.pointerSelecting&&requestAnimationFrame(()=>{let m=this.supported?this.session?.getCurrentSelectionCommentAnchor?.()??null:null;this.pointerSelecting=!1,this.selectionAnchor=m,this.renderToolbar(),this.pendingSelectionAnchor=Mt(m)?m:null,this.clearSelectionRevealTimer(),this.committedSelectionAnchor=Mt(m)&&this.activeCard?.mode!=="create"?m:null,this.scheduleLayoutRefresh()})},this.handleEditorFocusOut=m=>{let b=m.relatedTarget;b instanceof Node&&(this.editorContainer?.contains(b)||this.cardRoot?.contains(b)||this.commentSelectionButton?.contains(b))||(this.clearSelectionRevealTimer(),this.pendingSelectionAnchor=null,this.committedSelectionAnchor=null,this.scheduleLayoutRefresh())},this.handleDocumentPointerDown=m=>{let b=m.target;if(this.activeCard&&this.cardRoot){if(this.cardRoot.contains(b))return;this.closeCard()}this.drawerOpen&&(b instanceof Node&&(this.commentsDrawer?.contains(b)||this.commentsToggleButton?.contains(b))||this.closeDrawer())},this.handleDocumentKeyDown=m=>{if(m.key==="Escape"&&this.reactionPicker){this.reactionPicker=null,this.renderCard();return}m.key==="Escape"&&this.activeCard&&this.closeCard(),m.key==="Escape"&&this.committedSelectionAnchor&&(this.clearSelectionRevealTimer(),this.pendingSelectionAnchor=null,this.committedSelectionAnchor=null,this.scheduleLayoutRefresh())},this.commentSelectionButton?.addEventListener("pointerdown",this.handleCommentSelectionButtonPointerDown),this.commentSelectionButton?.addEventListener("click",()=>{this.openComposerForSelection("toolbar")}),this.commentsToggleButton?.addEventListener("click",()=>{this.setDrawerOpen(!this.drawerOpen)}),this.previewContainer?.addEventListener("scroll",this.handlePreviewScroll,{passive:!0}),this.previewElement?.addEventListener("pointermove",this.handlePreviewPointerMove,{passive:!0}),this.previewElement?.addEventListener("pointerleave",this.handlePreviewPointerLeave),this.previewElement?.addEventListener("focusin",this.handlePreviewFocusIn),this.previewElement?.addEventListener("focusout",this.handlePreviewFocusOut),this.editorContainer?.addEventListener("pointerdown",this.handleEditorPointerDown),this.editorContainer?.addEventListener("focusout",this.handleEditorFocusOut),window.addEventListener("resize",this.handleWindowResize),document.addEventListener("pointerup",this.handleDocumentPointerUp),document.addEventListener("pointercancel",this.handleDocumentPointerUp),document.addEventListener("pointerdown",this.handleDocumentPointerDown),document.addEventListener("keydown",this.handleDocumentKeyDown)}destroy(){this.layoutFrame&&(cancelAnimationFrame(this.layoutFrame),this.layoutFrame=0),this.attachSession(null),this.previewContainer?.removeEventListener("scroll",this.handlePreviewScroll),this.previewElement?.removeEventListener("pointermove",this.handlePreviewPointerMove),this.previewElement?.removeEventListener("pointerleave",this.handlePreviewPointerLeave),this.previewElement?.removeEventListener("focusin",this.handlePreviewFocusIn),this.previewElement?.removeEventListener("focusout",this.handlePreviewFocusOut),this.commentSelectionButton?.removeEventListener("pointerdown",this.handleCommentSelectionButtonPointerDown),this.editorContainer?.removeEventListener("pointerdown",this.handleEditorPointerDown),this.editorContainer?.removeEventListener("focusout",this.handleEditorFocusOut),window.removeEventListener("resize",this.handleWindowResize),document.removeEventListener("pointerup",this.handleDocumentPointerUp),document.removeEventListener("pointercancel",this.handleDocumentPointerUp),document.removeEventListener("pointerdown",this.handleDocumentPointerDown),document.removeEventListener("keydown",this.handleDocumentKeyDown),this.previewHoverRegions=[],this.cardRoot?.remove(),this.editorLayer?.remove(),this.previewLayer?.remove(),this.pendingCardFocusElement=null}attachSession(e){this.session?.getScrollContainer?.()?.removeEventListener("scroll",this.handleEditorScroll),this.session=e,this.selectionAnchor=e?.getCurrentSelectionCommentAnchor?.()??null,this.pendingSelectionAnchor=null,this.committedSelectionAnchor=null,this.reactionPicker=null,this.clearSelectionRevealTimer(),this.pointerSelecting=!1,e?.getScrollContainer?.()?.addEventListener("scroll",this.handleEditorScroll,{passive:!0}),this.render()}setCurrentFile(e,{fileKind:t="markdown",supported:i=!1}={}){let s=this.currentFile!==e;this.currentFile=e,this.fileKind=t,this.supported=!!(e&&i),s&&(this.drawerOpen=!1,this.threads=[],this.selectionAnchor=null,this.pendingSelectionAnchor=null,this.committedSelectionAnchor=null,this.clearSelectionRevealTimer(),this.pointerSelecting=!1,this.activeCard=null,this.updateHoveredEditorGroups([]),this.updateHoveredPreviewGroups([]),this.previewHoverRegions=[],this.lastPreviewPointerPosition=null,this.reactionPicker=null),this.supported||(this.drawerOpen=!1,this.activeCard=null,this.threads=[],this.selectionAnchor=null,this.pendingSelectionAnchor=null,this.committedSelectionAnchor=null,this.clearSelectionRevealTimer(),this.pointerSelecting=!1,this.updateHoveredEditorGroups([]),this.updateHoveredPreviewGroups([]),this.previewHoverRegions=[],this.lastPreviewPointerPosition=null,this.reactionPicker=null),this.render()}setSelectionAnchor(e){if(this.selectionAnchor=this.supported?e:null,!this.supported||!this.selectionAnchor){this.pendingSelectionAnchor=null,this.committedSelectionAnchor=null,this.clearSelectionRevealTimer(),this.renderToolbar(),this.scheduleLayoutRefresh();return}if(!Mt(this.selectionAnchor)){this.pendingSelectionAnchor=null,this.committedSelectionAnchor=null,this.clearSelectionRevealTimer(),this.renderToolbar(),this.scheduleLayoutRefresh();return}if(this.pendingSelectionAnchor=this.selectionAnchor,this.activeCard?.mode==="create"){this.clearSelectionRevealTimer(),this.renderToolbar(),this.scheduleLayoutRefresh();return}if(this.pointerSelecting){this.clearSelectionRevealTimer(),this.committedSelectionAnchor=null,this.renderToolbar(),this.scheduleLayoutRefresh();return}if(Ii(this.committedSelectionAnchor,this.selectionAnchor)){this.renderToolbar(),this.scheduleLayoutRefresh();return}this.scheduleSelectionReveal(this.selectionAnchor),this.renderToolbar(),this.scheduleLayoutRefresh()}handleEditorContentChange(){this.activeCard?.mode!=="create"&&(this.clearSelectionRevealTimer(),this.pendingSelectionAnchor=null,this.committedSelectionAnchor=null,this.scheduleLayoutRefresh())}setThreads(e=[]){this.threads=Sn(e),this.activeCard?.mode==="group"&&!this.getThreadGroups().some(t=>t.key===this.activeCard.groupKey)&&(this.activeCard=null),this.reactionPicker&&!this.threads.some(t=>t.id===this.reactionPicker.threadId&&t.messages?.some(i=>i.id===this.reactionPicker.messageId))&&(this.reactionPicker=null),this.render()}setDrawerOpen(e){let t=!!e;t!==this.drawerOpen&&(t&&this.onWillOpenDrawer?.(),this.drawerOpen=t,this.render())}closeDrawer(){this.setDrawerOpen(!1)}refreshLayout(){this.renderEditorLayer(),this.renderPreviewLayer(),this.repositionActiveCard()}scheduleLayoutRefresh(){this.layoutFrame||(this.layoutFrame=requestAnimationFrame(()=>{this.layoutFrame=0,this.refreshLayout()}))}render(){this.renderToolbar(),this.renderDrawer(),this.renderCard(),this.scheduleLayoutRefresh()}renderToolbar(){let e=this.threads.length,t=this.supported&&!!this.session;if(this.commentSelectionButton?.classList.toggle("hidden",!t),this.commentsToggleButton?.classList.toggle("hidden",!this.supported),this.commentSelectionButton&&(this.commentSelectionButton.disabled=!this.selectionAnchor),this.commentsToggleButton){this.commentsToggleButton.classList.toggle("active",this.drawerOpen),this.commentsToggleButton.setAttribute("aria-expanded",String(this.drawerOpen));let i=e>0?`Comments ${e}`:"Comments",s=this.commentsToggleButton.querySelector(".pane-header-btn-label");s?s.textContent=i:this.commentsToggleButton.textContent=i}}renderDrawer(){if(!this.commentsDrawer||!this.commentsDrawerList)return;this.commentsDrawer.classList.toggle("hidden",!this.supported||!this.drawerOpen),this.commentsDrawerList.replaceChildren();let e=this.getThreadGroups();if(this.commentsDrawerEmpty?.classList.toggle("hidden",e.length>0),!this.supported||e.length===0)return;let t=document.createDocumentFragment();e.forEach(i=>{let s=document.createElement("button");s.type="button",s.className="comments-drawer-item",s.classList.toggle("is-active",this.activeCard?.groupKey===i.key),s.addEventListener("pointerdown",w=>{w.preventDefault()}),s.addEventListener("click",()=>{this.openThreadGroup(i,{anchor:i.anchor,origin:"drawer",sourceRect:s.getBoundingClientRect()})});let r=document.createElement("div");r.className="comments-drawer-item-header";let a=document.createElement("span");a.className="comments-drawer-item-title",a.textContent=Fi(i.anchor);let o=document.createElement("span");o.className="comments-drawer-item-count",o.textContent=String(i.threads.length),r.append(a,o);let l=document.createElement("p");l.className="comments-drawer-item-quote",l.textContent=i.anchor.quote||i.anchor.excerpt||"Source anchored comment";let h=xn(i),c=Ai(h?.body||"","comment-markdown comments-drawer-item-preview"),u=document.createElement("div");u.className="comments-drawer-item-footer";let p=document.createElement("span");p.textContent=`${i.threads.length} thread${i.threads.length===1?"":"s"}`;let d=document.createElement("span");d.className="comments-drawer-item-updated",d.textContent=h?`${h.userName} \u2022 ${this.formatTimestamp(h.createdAt)}`:"",u.append(p,d),s.append(r,l,c,u),t.appendChild(s)}),this.commentsDrawerList.appendChild(t)}ensureEditorLayer(){if(this.editorLayer?.isConnected&&this.editorLayer.parentElement===this.editorContainer)return this.editorLayer;let e=document.createElement("div");return e.className="comment-editor-layer",this.editorContainer?.appendChild(e),this.editorLayer=e,e}renderEditorLayer(){let e=this.ensureEditorLayer();if(e.replaceChildren(),!this.supported||!this.session)return;let t=this.editorContainer?.getBoundingClientRect?.();if(!t)return;let i=this.getThreadGroups(),s=[];if(i.forEach(c=>{let u=this.session.getCommentAnchorClientRect?.(c.anchor);if(!u)return;let p=Bi(u,t);if(p.bottom<0||p.top>t.height)return;let d=document.createElement("button");d.type="button",d.className="comment-editor-badge",d.dataset.count=String(c.threads.length);let w=this.activeCard?.groupKey===c.key,m=this.hoveredEditorGroupKeys.includes(c.key);d.classList.toggle("is-active",w),d.classList.toggle("is-hovered",m),d.classList.toggle("is-passive",!w&&!m),d.setAttribute("aria-label",`${c.threads.length} comment thread${c.threads.length===1?"":"s"}`),d.appendChild(Ni(c.threads.length));let b=Math.max(p.top,8);d.style.top=`${b}px`,d.style.left=`${Math.max(t.width-36,8)}px`,d.title=`${c.threads.length} comment${c.threads.length===1?"":"s"}`,d.addEventListener("pointerdown",E=>{E.preventDefault()}),d.addEventListener("pointerenter",()=>{this.updateHoveredEditorGroups([c.key])}),d.addEventListener("pointerleave",()=>{this.updateHoveredEditorGroups([])}),d.addEventListener("focusin",()=>{this.updateHoveredEditorGroups([c.key])}),d.addEventListener("focusout",()=>{this.updateHoveredEditorGroups([])}),d.addEventListener("click",()=>{this.openThreadGroup(c,{anchor:c.anchor,origin:"editor",sourceRect:u})}),e.appendChild(d),s.push(b)}),!this.committedSelectionAnchor||this.activeCard?.mode==="create")return;let r=this.session.getCommentAnchorClientRect?.(this.committedSelectionAnchor),a=this.session.getSelectionChipClientRect?.(this.committedSelectionAnchor)??r;if(!a)return;let o=Bi(a,t);if(o.bottom<0||o.top>t.height)return;let l=ee(o.top,8,Math.max(t.height-je,8));for(;s.some(c=>Math.abs(c-l)<je-4);)l=ee(l+je,8,Math.max(t.height-je,8));let h=document.createElement("button");h.type="button",h.className="comment-selection-chip",h.textContent="Comment",h.style.top=`${l}px`,h.style.right=`${yn}px`,h.addEventListener("pointerdown",c=>{c.preventDefault(),c.stopPropagation(),this.openComposerForSelection("editor",h.getBoundingClientRect())}),e.appendChild(h)}ensurePreviewLayer(){if(this.previewLayer?.isConnected&&this.previewLayer.parentElement===this.previewElement)return this.previewLayer;let e=document.createElement("div");e.className="comment-preview-highlights";let t=document.createElement("div");return t.className="comment-preview-layer",this.previewElement?.append(e,t),this.previewHighlightLayer=e,this.previewLayer=t,t}renderPreviewLayer(){if(this.ensurePreviewLayer(),this.previewLayer?.replaceChildren(),this.previewHighlightLayer?.replaceChildren(),!this.supported||!this.previewElement){this.previewHoverRegions=[];return}let e=this.previewElement.getBoundingClientRect(),t=this.getThreadGroups(),i=[],s=[],r=this.shouldRenderPassivePreviewMarkers();t.forEach(a=>{let o=this.resolvePreviewTarget(a.anchor);if(!o?.bubbleRect)return;s.push({key:a.key,rects:o.hoverRects?.length>0?o.hoverRects:[o.bubbleRect]});let l=this.activeCard?.groupKey===a.key,h=this.hoveredPreviewGroupKeys.includes(a.key),c=l||h;if(o.highlightRects?.forEach(d=>{let w=document.createElement("div");w.className="comment-preview-highlight",w.classList.toggle("is-active",l),w.classList.toggle("is-hovered",h),w.classList.toggle("is-passive",!c),w.style.left=`${d.left-e.left}px`,w.style.top=`${d.top-e.top}px`,w.style.width=`${d.width}px`,w.style.height=`${d.height}px`,this.previewHighlightLayer?.appendChild(w)}),!r&&!c)return;let u=document.createElement("button");u.type="button",u.className="comment-preview-badge",u.dataset.commentPreviewGroupKeys=a.key,u.classList.toggle("is-active",l),u.classList.toggle("is-hovered",h),u.classList.toggle("is-passive",!c),u.setAttribute("aria-label",`${a.threads.length} comment thread${a.threads.length===1?"":"s"}`),u.appendChild(Ni(a.threads.length));let p=ee(o.bubbleRect.top-e.top,6,Math.max(this.previewElement.clientHeight-Qe,6));for(;i.some(d=>Math.abs(d-p)<Qe-4);)p=ee(p+Qe,6,Math.max(this.previewElement.clientHeight-Qe,6));u.style.top=`${p}px`,u.title=`${a.threads.length} comment${a.threads.length===1?"":"s"}`,u.addEventListener("pointerdown",d=>{d.preventDefault()}),u.addEventListener("click",()=>{this.openThreadGroup(a,{anchor:a.anchor,origin:"preview",sourceRect:u.getBoundingClientRect()})}),this.previewLayer?.appendChild(u),i.push(p)}),this.previewHoverRegions=s,this.lastPreviewPointerPosition&&this.updateHoveredPreviewGroups(this.getPreviewGroupKeysAtPoint(this.lastPreviewPointerPosition.x,this.lastPreviewPointerPosition.y))}resolvePreviewTarget(e){if(!this.previewElement||!e)return null;let t=Array.from(this.previewElement.querySelectorAll(".mermaid-shell, .plantuml-shell")).find(r=>Ri(r,e));if(t)return{bubbleRect:t.getBoundingClientRect(),highlightRects:[],hoverRects:[t.getBoundingClientRect()]};let i=Array.from(this.previewElement.querySelectorAll("[data-source-line]")).filter(r=>Pn(r)&&Ri(r,e));if(e.kind==="text"&&e.quote){let r=i.map(a=>({element:a,range:An(a,e.quote)})).filter(a=>a.range);if(r.length===1){let a=Array.from(r[0].range.getClientRects());return{bubbleRect:Mn(a)||r[0].element.getBoundingClientRect(),highlightRects:a,hoverRects:a}}}let s=i[0];return s?{bubbleRect:s.getBoundingClientRect(),highlightRects:[],hoverRects:[s.getBoundingClientRect()]}:null}ensureCardRoot(){if(this.cardRoot?.isConnected&&this.cardRoot.parentElement===document.body)return this.cardRoot;let e=document.createElement("div");return e.className="comment-card-root hidden",document.body.appendChild(e),this.cardRoot=e,e}openComposerForSelection(e="editor",t=null){let i=this.session?.getCurrentSelectionCommentAnchor?.();if(!i)return;this.selectionAnchor=i,this.reactionPicker=null;let s=e==="editor"&&t?"editor-chip":e,r=t??(e==="toolbar"?this.commentSelectionButton?.getBoundingClientRect?.():this.session?.getCommentAnchorClientRect?.(i));this.activeCard={anchor:i,mode:"create",origin:s,replyThreadId:null,sourceRect:r},this.render()}openThreadGroup(e,{anchor:t,origin:i,sourceRect:s}){this.reactionPicker=null,this.activeCard={anchor:t,groupKey:e.key,mode:"group",origin:i,replyThreadId:null,sourceRect:s},this.renderDrawer(),this.renderCard()}closeCard(){this.activeCard=null,this.pendingCardFocusElement=null,this.reactionPicker=null,this.renderCard(),this.scheduleLayoutRefresh()}getThreadGroups(){let e=new Map;return this.threads.forEach(t=>{let i=kn(t.anchor),s=e.get(i);if(s){s.threads.push(t);return}e.set(i,{anchor:t.anchor,key:i,threads:[t]})}),Array.from(e.values()).sort((t,i)=>(t.anchor?.startLine??0)-(i.anchor?.startLine??0))}updateCardSourceRect(){return this.activeCard?this.activeCard.origin==="editor"?this.session?.getCommentAnchorClientRect?.(this.activeCard.anchor)??this.activeCard.sourceRect:this.activeCard.origin==="editor-chip"?this.activeCard.sourceRect:this.activeCard.origin==="preview"?this.resolvePreviewTarget(this.activeCard.anchor)?.bubbleRect??this.activeCard.sourceRect:this.activeCard.origin==="toolbar"?this.commentSelectionButton?.getBoundingClientRect?.()??this.activeCard.sourceRect:this.activeCard.sourceRect:null}renderCard(){let e=this.ensureCardRoot();if(e.replaceChildren(),e.classList.toggle("hidden",!this.activeCard),!this.activeCard){this.pendingCardFocusElement=null,e.style.visibility="";return}this.pendingCardFocusElement=null;let t=document.createElement("section");t.className="comment-card",t.addEventListener("click",h=>{!this.reactionPicker||h.target?.closest?.(".comment-reaction-picker-wrap")||(this.reactionPicker=null,requestAnimationFrame(()=>{this.activeCard&&this.renderCard()}))});let i=document.createElement("div");i.className="comment-card-header";let s=document.createElement("div");s.className="comment-card-title-wrap";let r=document.createElement("h3");r.className="comment-card-title",r.textContent=this.activeCard.mode==="create"?"New comment":"Comment threads";let a=document.createElement("p");a.className="comment-card-meta",a.textContent=Fi(this.activeCard.anchor),s.append(r,a);let o=document.createElement("button");o.type="button",o.className="comment-card-close",o.setAttribute("aria-label","Close comments"),o.textContent="Close",o.addEventListener("click",()=>this.closeCard()),i.append(s,o),t.appendChild(i);let l=document.createElement("div");if(l.className="comment-card-scroll",this.activeCard.anchor?.quote){let h=document.createElement("p");h.className="comment-card-quote",h.textContent=this.activeCard.anchor.quote,l.appendChild(h)}if(this.activeCard.mode==="create")l.appendChild(this.createComposer());else{let h=this.getThreadGroups().find(c=>c.key===this.activeCard.groupKey);if(!h){this.closeCard();return}h.threads.forEach(c=>{l.appendChild(this.createThreadElement(c))})}e.style.visibility="hidden",t.appendChild(l),e.appendChild(t),this.updateReactionPickerPosition(t),this.positionCard(t),e.style.visibility="",this.flushPendingCardFocus(),this.scheduleLayoutRefresh()}getPreviewGroupKeysForTarget(e){if(!(e instanceof Node))return[];let t=e.closest?.("[data-comment-preview-group-keys]");return Bn(String(t?.dataset?.commentPreviewGroupKeys??"").split(/\s+/).filter(Boolean)).split(" ").filter(Boolean)}getPreviewGroupKeysAtPoint(e,t){if(!Number.isFinite(e)||!Number.isFinite(t))return[];let i=document.elementFromPoint(e,t),s=this.getPreviewGroupKeysForTarget(i);if(s.length>0)return s;let r=this.previewHoverRegions.filter(a=>a.rects.some(o=>Rn(e,t,o))).map(a=>a.key);return Ye(r)}updateHoveredPreviewGroups(e=[]){let t=Ye(e),i=t.join(" ");i!==this.hoveredPreviewGroupKeysSignature&&(this.hoveredPreviewGroupKeys=t,this.hoveredPreviewGroupKeysSignature=i,this.scheduleLayoutRefresh())}updateHoveredEditorGroups(e=[]){let t=Ye(e),i=t.join(" ");i!==this.hoveredEditorGroupKeysSignature&&(this.hoveredEditorGroupKeys=t,this.hoveredEditorGroupKeysSignature=i,this.scheduleLayoutRefresh())}syncHoveredPreviewGroupsFromTarget(e){this.updateHoveredPreviewGroups(this.getPreviewGroupKeysForTarget(e))}shouldRenderPassivePreviewMarkers(){let e=this.previewContainer?.clientWidth??this.previewElement?.clientWidth??0;return window.innerWidth>=bn&&e>=vn}updateReactionPickerPosition(e){let t=Fn(e);if(!t)return;let{picker:i,scroll:s,wrap:r}=t;i.classList.remove("is-upward"),i.style.maxHeight="";let a=r.getBoundingClientRect(),o=s.getBoundingClientRect(),l=i.getBoundingClientRect(),h=12,c=window.innerHeight-12,u=Math.min(o.bottom,c),p=Math.max(o.top,h),d=Math.max(u-a.bottom-8,0),w=Math.max(a.top-p-8,0),m=l.height>d&&w>d,b=Math.max(m?w:d,120);i.classList.toggle("is-upward",m),i.style.maxHeight=`${b}px`}repositionActiveCard(){let e=this.cardRoot?.firstElementChild;if(!e||!this.activeCard){this.cardRoot&&(this.cardRoot.style.visibility="");return}this.positionCard(e),this.cardRoot.style.visibility="",this.flushPendingCardFocus()}createComposer(){let e=document.createElement("form");e.className="comment-card-form";let t=document.createElement("textarea");t.className="input comment-card-input",t.rows=4,t.maxLength=vt,t.placeholder="Add context, feedback, or a question...";let i=document.createElement("div");i.className="comment-card-actions";let s=document.createElement("button");s.type="button",s.className="btn btn-secondary",s.textContent="Cancel",s.addEventListener("click",()=>this.closeCard());let r=document.createElement("button");return r.type="submit",r.className="btn btn-primary",r.textContent="Post comment",i.append(s,r),e.append(t,i),e.addEventListener("submit",async a=>{if(a.preventDefault(),!await this.onCreateThread?.({anchor:this.activeCard?.anchor,body:t.value})){t.focus();return}this.closeCard()}),this.pendingCardFocusElement=t,e}createThreadElement(e){let t=document.createElement("article");t.className="comment-thread-card";let i=document.createElement("div");i.className="comment-thread-card-header";let s=document.createElement("div");s.className="comment-thread-card-heading";let r=document.createElement("span");r.className="comment-thread-card-author",r.textContent=e.createdByName;let a=document.createElement("span");a.className="comment-thread-card-time",a.textContent=this.formatTimestamp(e.createdAt);let o=document.createElement("div");o.className="comment-thread-card-actions";let l=document.createElement("button");l.type="button",l.className="comment-thread-card-action",l.textContent="Jump",l.addEventListener("click",()=>this.onNavigateToLine?.(e.anchor?.startLine??1));let h=document.createElement("button");h.type="button",h.className="comment-thread-card-action";let c=this.activeCard?.replyThreadId===e.id;h.classList.toggle("is-active",c),h.textContent="Reply",h.setAttribute("aria-pressed",String(c)),h.setAttribute("aria-label",c?"Cancel reply":"Reply to thread"),h.title=c?"Cancel reply":"Reply to thread",h.addEventListener("click",()=>{this.activeCard={...this.activeCard,replyThreadId:c?null:e.id},this.renderCard()});let u=document.createElement("button");return u.type="button",u.className="comment-thread-card-action is-danger",u.textContent="Resolve",u.addEventListener("click",async()=>{await this.onResolveThread?.(e.id)}),o.append(l,h,u),s.append(r,a),i.append(s,o),t.append(i),e.messages.forEach(p=>{t.appendChild(this.createMessageElement(e,p))}),this.activeCard?.replyThreadId===e.id&&t.appendChild(this.createReplyComposer(e)),t}createMessageElement(e,t){let i=document.createElement("div");i.className="comment-message-card";let s=document.createElement("div");s.className="comment-message-card-meta";let r=document.createElement("span");r.className="comment-message-card-author",r.textContent=t.userName;let a=document.createElement("span");a.className="comment-message-card-time",a.textContent=this.formatTimestamp(t.createdAt);let o=Ai(t.body,"comment-message-card-body comment-markdown");return s.append(r,a),i.append(s,o),i.appendChild(this.createReactionBar(e,t)),i}createReactionBar(e,t){let i=this.session?.getLocalUser?.()?.userId??"",s=document.createElement("div");s.className="comment-reaction-bar";let r=new Set((t.reactions??[]).map(c=>c.emoji)),a=document.createElement("div");a.className="comment-reaction-chips",(t.reactions??[]).forEach(c=>{let u=document.createElement("button");u.type="button",u.className="comment-reaction-chip",u.classList.toggle("is-active",Mi(c,i)),u.setAttribute("aria-pressed",String(Mi(c,i))),u.title=c.users?.map(w=>w.userName).join(", ")||c.emoji;let p=document.createElement("span");p.className="comment-reaction-chip-emoji",p.textContent=c.emoji;let d=document.createElement("span");d.className="comment-reaction-chip-count",d.textContent=In(c),u.append(p,d),u.addEventListener("click",async()=>{await this.onToggleReaction?.(e.id,t.id,c.emoji)}),a.appendChild(u)});let o=document.createElement("div");o.className="comment-reaction-actions",Cn.filter(c=>!r.has(c)).forEach(c=>{o.appendChild(this.createQuickReactionButton(e,t,c))});let l=document.createElement("div");l.className="comment-reaction-picker-wrap";let h=document.createElement("button");return h.type="button",h.className="comment-reaction-more-trigger",h.dataset.reactionPickerToggle="true",h.setAttribute("aria-expanded",String(Rt(this.reactionPicker,e.id,t.id))),h.textContent="More",h.addEventListener("click",()=>{let c=Rt(this.reactionPicker,e.id,t.id);this.reactionPicker=c?null:{messageId:t.id,threadId:e.id},this.renderCard()}),l.appendChild(h),Rt(this.reactionPicker,e.id,t.id)&&l.appendChild(this.createReactionPicker(e,t)),o.appendChild(l),s.append(a,o),s}createQuickReactionButton(e,t,i){let s=document.createElement("button");return s.type="button",s.className="comment-reaction-quick-add",s.textContent=i,s.title=`React with ${i}`,s.addEventListener("click",async()=>{await this.onToggleReaction?.(e.id,t.id,i)}),s}createReactionPicker(e,t){let i=document.createElement("div");i.className="comment-reaction-picker";let s=document.createElement("div");return s.className="comment-reaction-picker-grid",En.forEach(r=>{s.appendChild(this.createReactionPickerButton(e,t,r))}),i.appendChild(s),i}createReactionPickerButton(e,t,i){let s=document.createElement("button");return s.type="button",s.className="comment-reaction-picker-btn",s.textContent=i,s.title=`React with ${i}`,s.addEventListener("click",async()=>{await this.onToggleReaction?.(e.id,t.id,i)&&(this.reactionPicker=null,this.renderCard())}),s}createReplyComposer(e){let t=document.createElement("form");t.className="comment-reply-form";let i=document.createElement("textarea");i.className="input comment-card-input",i.rows=3,i.maxLength=vt,i.placeholder="Reply to thread...";let s=document.createElement("div");s.className="comment-card-actions";let r=document.createElement("button");r.type="button",r.className="btn btn-secondary",r.textContent="Cancel",r.addEventListener("click",()=>{this.activeCard={...this.activeCard,replyThreadId:null},this.renderCard()});let a=document.createElement("button");return a.type="submit",a.className="btn btn-primary",a.textContent="Reply",s.append(r,a),t.append(i,s),this.pendingCardFocusElement=i,t.addEventListener("submit",async o=>{if(o.preventDefault(),!await this.onReplyToThread?.(e.id,i.value)){i.focus();return}this.activeCard={...this.activeCard,replyThreadId:null},this.renderCard()}),t}positionCard(e){let t=this.updateCardSourceRect(),i=window.innerWidth,s=window.innerHeight,r=e.getBoundingClientRect(),a=ee((i-r.width)/2,16,i-r.width-16),o=ee((s-r.height)/4,16,s-r.height-16),l=a,h=o;t&&(l=ee(t.left,16,i-Math.min(r.width,xi)-16),h=t.bottom+Li,h+r.height>s-16&&(h=Math.max(t.top-r.height-Li,16))),this.cardRoot.style.left=`${l}px`,this.cardRoot.style.top=`${h}px`,this.cardRoot.style.width=`${Math.min(Math.max(r.width,xi),i-32)}px`}formatTimestamp(e){if(!Number.isFinite(e))return"";try{return this.timeFormatter.format(new Date(e))}catch{return""}}flushPendingCardFocus(){let e=this.pendingCardFocusElement;if(!(e instanceof HTMLElement)||!e.isConnected){this.pendingCardFocusElement=null;return}this.pendingCardFocusElement=null;let t=()=>{if(!e.isConnected)return;let i=document.activeElement;i instanceof HTMLElement&&this.editorContainer?.contains(i)&&i.blur(),e.focus({preventScroll:!0})};t(),document.activeElement!==e&&requestAnimationFrame(()=>{t(),document.activeElement!==e&&setTimeout(()=>{t()},50)})}clearSelectionRevealTimer(){this.selectionRevealTimer&&(clearTimeout(this.selectionRevealTimer),this.selectionRevealTimer=0)}scheduleSelectionReveal(e){this.clearSelectionRevealTimer(),this.selectionRevealTimer=window.setTimeout(()=>{this.selectionRevealTimer=0,!(this.pointerSelecting||this.activeCard?.mode==="create"||!Ii(this.pendingSelectionAnchor,e))&&(this.committedSelectionAnchor=e,this.scheduleLayoutRefresh())},wn)}};function Xe(n,e){let t=new Map;e.forEach(s=>{let a=n.get(s.key)??{filePath:s.filePath,iframe:null,instanceId:null,key:s.key,label:s.label,placeholder:s.placeholder,queued:!1,reusedFromEmbed:!1,wrapper:null};a.filePath=s.filePath,a.key=s.key,a.label=s.label,a.placeholder=s.placeholder,t.set(s.key,a)});let i=[];return n.forEach((s,r)=>{t.has(r)||i.push(s)}),{nextEntries:t,removedEntries:i}}var de=420,Nn=500,Dn=15e3,Hn=800,_n=3,zn=200,Un="/excalidraw-editor.html";function $n(n,e){return typeof window.requestIdleCallback=="function"?window.requestIdleCallback(n,{timeout:e}):window.setTimeout(()=>{n({didTimeout:!1,timeRemaining:()=>0})},1)}function Je(n){if(n!==null){if(typeof window.cancelIdleCallback=="function"){window.cancelIdleCallback(n);return}window.clearTimeout(n)}}function On(n,e,t){if(!n||!e)return!1;let i=e.getBoundingClientRect(),s=n.getBoundingClientRect();return s.bottom>=i.top-t&&s.top<=i.bottom+t}var et=class{constructor({getTheme:e,getLocalUser:t,onOpenFile:i=null,previewContainer:s,previewElement:r,toastController:a}){this.getTheme=e,this.getLocalUser=t,this.onOpenFile=i,this.previewContainer=s,this.previewElement=r,this.toastController=a,this.embedEntries=new Map,this.hydrationQueue=[],this.hydrationIdleId=null,this.hydrationPaused=!1,this.hydrationInProgress=!1,this.instanceCounter=0,this.isLargeDocument=!1,this.maximizedEmbed=null,this.overlayRoot=null,this.maximizedRoot=null,this.placeholderObserver=null,this.followedPeerIdsByFilePath=new Map,this._onMessage=this._onMessage.bind(this),this._onKeyDown=this._onKeyDown.bind(this),this._onPreviewClick=this._onPreviewClick.bind(this),window.addEventListener("message",this._onMessage),window.addEventListener("keydown",this._onKeyDown),this.previewElement?.addEventListener("click",this._onPreviewClick)}destroy(){window.removeEventListener("message",this._onMessage),window.removeEventListener("keydown",this._onKeyDown),this.previewElement?.removeEventListener("click",this._onPreviewClick),this._disconnectPlaceholderObserver(),Je(this.hydrationIdleId),this.hydrationIdleId=null,this.hydrationQueue=[],this._exitMaximizedEmbed(),document.body.classList.remove("excalidraw-maximized-open"),this.embedEntries.forEach(e=>{this._clearEntryBootTimeout(e),e.wrapper?.remove(),e.placeholder=null}),this.embedEntries.clear(),this.followedPeerIdsByFilePath.clear(),this.overlayRoot?.remove(),this.overlayRoot=null,this.maximizedRoot?.remove(),this.maximizedRoot=null}async setFollowedUser(e,t=null){if(!e)return!1;this.followedPeerIdsByFilePath.set(e,t||null);let i=this._findEntryByFilePath(e);return i&&(i.wrapper||await this._hydrateEntry(i),i.followedPeerId=this.followedPeerIdsByFilePath.get(e)??null,this._syncEntryFollowState(i)),!0}detachForCommit(){this._disconnectPlaceholderObserver(),Je(this.hydrationIdleId),this.hydrationIdleId=null,this.hydrationQueue=[],this.hydrationInProgress=!1,this.overlayRoot&&(this.overlayRoot.hidden=!0),this.maximizedRoot&&(this.maximizedRoot.hidden=!0),this.embedEntries.forEach(e=>{e.queued=!1,e.placeholder=null})}setHydrationPaused(e){if(this.hydrationPaused=!!e,this.hydrationPaused){Je(this.hydrationIdleId),this.hydrationIdleId=null;return}this.hydrateVisibleEmbeds(),this._scheduleHydration()}reconcileEmbeds(e,{isLargeDocument:t=!1}={}){this.isLargeDocument=!!t,this._disconnectPlaceholderObserver(),Je(this.hydrationIdleId),this.hydrationIdleId=null,this.hydrationQueue=[],this.hydrationInProgress=!1;let i=Array.from(e.querySelectorAll(".excalidraw-embed-placeholder[data-embed-key]")).map(a=>({filePath:a.dataset.embedTarget,key:a.dataset.embedKey,label:a.dataset.embedLabel||a.dataset.embedTarget,placeholder:a})),{nextEntries:s,removedEntries:r}=Xe(this.embedEntries,i);this._adoptReusableEntries(s,r),r.forEach(a=>this._destroyEntry(a)),this.embedEntries=s,this._ensurePlaceholderObserver(),this.embedEntries.forEach(a=>{if(a.queued=!1,a.followedPeerId=this.followedPeerIdsByFilePath.get(a.filePath),a.wrapper){this._updateEmbedLabel(a),this._attachWrapper(a);return}a.placeholder&&this.placeholderObserver?.observe(a.placeholder)}),this.hydrationPaused||this.hydrateVisibleEmbeds(),this.syncLayout()}hydrateVisibleEmbeds(){if(this.hydrationPaused)return;let e=this.isLargeDocument?180:420;this.embedEntries.forEach(t=>{t.wrapper||!t.placeholder?.isConnected||On(t.placeholder,this.previewContainer,e)&&this._enqueueHydration(t,{prioritize:!0})})}updateTheme(e){this.embedEntries.forEach(t=>{this._postMessageToEntry(t,{source:"collabmd-host",type:"set-theme",theme:e})})}updateLocalUser(e){this.embedEntries.forEach(t=>{this._syncEntryUser(t,e)})}_ensurePlaceholderObserver(){this.previewContainer&&(this.placeholderObserver=new IntersectionObserver(e=>{e.forEach(t=>{if(!t.isIntersecting)return;let i=this.embedEntries.get(t.target.dataset.embedKey);i&&this._enqueueHydration(i)})},{root:this.previewContainer,rootMargin:this.isLargeDocument?"180px 0px":"420px 0px"}))}_disconnectPlaceholderObserver(){this.placeholderObserver&&(this.placeholderObserver.disconnect(),this.placeholderObserver=null)}_enqueueHydration(e,{prioritize:t=!1}={}){if(!(!e||e.wrapper||e.queued)&&(e.queued=!0,t?this.hydrationQueue.unshift(e.key):this.hydrationQueue.push(e.key),!this.hydrationPaused)){if(t&&!this.hydrationInProgress&&this.hydrationIdleId===null){this._flushHydrationQueue();return}this._scheduleHydration()}}_scheduleHydration(){this.hydrationPaused||this.hydrationInProgress||this.hydrationIdleId!==null||(this.hydrationIdleId=$n(()=>{this.hydrationIdleId=null,this._flushHydrationQueue()},Nn))}async _flushHydrationQueue(){if(this.hydrationPaused||this.hydrationInProgress)return;let e=null;for(;this.hydrationQueue.length>0&&!e;){let t=this.hydrationQueue.shift(),i=this.embedEntries.get(t);if(!i||i.wrapper||!i.placeholder?.isConnected){i&&(i.queued=!1);continue}e=i}e&&(this.hydrationInProgress=!0,e.queued=!1,await this._hydrateEntry(e),this.hydrationInProgress=!1,this.hydrationQueue.length>0&&this._scheduleHydration())}async _hydrateEntry(e){if(!(!e.placeholder?.isConnected&&!e.wrapper)){if(!e.wrapper){let t=this._createEmbedContainer(e);e.wrapper=t.wrapper,e.iframe=t.iframe,e.labelElement=t.labelElement,e.instanceId=t.instanceId,e.isReady=!1,e.bootAttempts=(e.bootAttempts??0)+1,this._armEntryBootTimeout(e)}e.followedPeerId=this.followedPeerIdsByFilePath.get(e.filePath),this._updateEmbedLabel(e),this._attachWrapper(e)}}_attachWrapper(e){let t=e.placeholder?.isConnected?e.placeholder:this.previewElement?.querySelector(`.excalidraw-embed-placeholder[data-embed-key="${e.key}"]`);if(!t)return;if(e.placeholder=t,this._syncMountedEntryMetadata(e),this._shouldInlineFilePreview(e)){e.wrapper.style.position="",e.wrapper.style.top="",e.wrapper.style.left="",e.wrapper.style.width="",e.wrapper.style.margin="",e.wrapper.style.pointerEvents="auto",t.replaceWith(e.wrapper),e.placeholder=null;return}let i=this._ensureOverlayRoot();i.hidden=!1,e.wrapper?.parentElement!==i&&i.appendChild(e.wrapper),this._syncEntryLayout(e)}_adoptReusableEntries(e,t){e.forEach((i,s)=>{if(i.wrapper||i.iframe)return;let r=t.findIndex(o=>o.filePath===i.filePath&&this._getEntryMode(o)===this._getEntryMode(i)&&(o.wrapper||o.iframe));if(r<0)return;let[a]=t.splice(r,1);a.filePath=i.filePath,a.key=i.key,a.label=i.label,a.placeholder=i.placeholder,a.queued=!1,a.reusedFromEmbed=this._isFilePreviewEntry(i),e.set(s,a)})}_destroyEntry(e){this.maximizedEmbed?.wrapper===e.wrapper&&this._exitMaximizedEmbed(),this._clearEntryBootTimeout(e),this._resetPlaceholderLayout(e),e.wrapper?.remove(),e.placeholder=null}_armEntryBootTimeout(e){this._clearEntryBootTimeout(e),e.bootTimerId=window.setTimeout(()=>{this._handleEntryBootTimeout(e)},Dn)}_clearEntryBootTimeout(e){e?.bootTimerId&&(window.clearTimeout(e.bootTimerId),e.bootTimerId=null)}async _handleEntryBootTimeout(e){if(e?.iframe?.isConnected){if((e.bootAttempts??0)>=_n){this._clearEntryBootTimeout(e),this.toastController?.show(`Excalidraw embed timed out: ${e.label}`);return}await this._retryEntryBootstrap(e)}}async _retryEntryBootstrap(e){e&&(this._clearEntryBootTimeout(e),this._resetPlaceholderLayout(e),this.maximizedEmbed?.wrapper===e.wrapper&&this._exitMaximizedEmbed(),e.wrapper?.remove(),e.wrapper=null,e.iframe=null,e.labelElement=null,e.instanceId=null,e.isReady=!1,await this._hydrateEntry(e))}_findEntryByContentWindow(e){if(!e)return null;for(let t of this.embedEntries.values())if(t.iframe?.contentWindow===e)return t;return null}_findEntryByFilePath(e){if(!e)return null;for(let t of this.embedEntries.values())if(t.filePath===e)return t;return null}_updateEmbedLabel(e){e.labelElement&&(e.labelElement.textContent=e.label.replace(/\.excalidraw$/i,""))}_syncMountedEntryMetadata(e){e.wrapper&&(e.wrapper.dataset.embedKey=e.key,e.wrapper.dataset.file=e.filePath),e.iframe&&(e.iframe.title=`Excalidraw: ${e.filePath}`)}_buildIframeUrl(e){let t=new URL(_t(Un)),i=this.getTheme?.()||"dark";t.searchParams.set("file",e.filePath),t.searchParams.set("theme",i),t.searchParams.set("boot",e.instanceId||""),this._isFilePreviewEntry(e)||t.searchParams.set("mode","preview");let s=this.getLocalUser?.();s?.name&&t.searchParams.set("userName",s.name),s?.color&&t.searchParams.set("userColor",s.color),s?.colorLight&&t.searchParams.set("userColorLight",s.colorLight),s?.peerId&&t.searchParams.set("userPeerId",s.peerId);let r=new URLSearchParams(window.location.search),a=r.get("server");return a&&t.searchParams.set("server",a),r.get("test")==="1"&&t.searchParams.set("test","1"),r.has("syncTimeoutMs")&&t.searchParams.set("syncTimeoutMs",r.get("syncTimeoutMs")),t}_createEmbedContainer(e){let t=document.createElement("div");t.className="excalidraw-embed diagram-preview-shell",t.dataset.embedKey=e.key,t.dataset.file=e.filePath;let i=document.createElement("div");i.className="excalidraw-embed-header diagram-preview-toolbar";let s=document.createElement("span");s.className="excalidraw-embed-icon",s.innerHTML='<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 19l7-7 3 3-7 7-3-3z"/><path d="M18 13l-1.5-7.5L2 2l3.5 14.5L13 18l5-5z"/><path d="M2 2l7.586 7.586"/><circle cx="11" cy="11" r="2"/></svg>';let r=document.createElement("span");r.className="excalidraw-embed-label",r.textContent=e.label.replace(/\.excalidraw$/i,"");let a=document.createElement("button");a.type="button",a.className="excalidraw-embed-btn diagram-preview-action-btn",a.title="Edit in Excalidraw",a.setAttribute("aria-label","Edit in Excalidraw"),T(a,"edit");let o=document.createElement("button");o.type="button",o.className="excalidraw-embed-btn diagram-preview-action-btn",o.title="Maximize diagram",o.setAttribute("aria-label","Maximize diagram"),T(o,"maximize"),i.append(s,r),this._isFilePreviewEntry(e)||i.append(a),i.append(o);let l=document.createElement("iframe");l.className="excalidraw-embed-iframe",l.dataset.instanceId=String(++this.instanceCounter),e.instanceId=l.dataset.instanceId,l.src=this._buildIframeUrl(e).toString(),l.setAttribute("loading","eager"),l.title=`Excalidraw: ${e.filePath}`,l.style.height=`${de}px`;let h=document.createElement("div");h.className="excalidraw-embed-resizer",h.title="Drag to resize",this._setupResizer(h,l,()=>this._syncEntryLayout(e)),t.append(i,l,h);let c=!1,u=`${de}px`,p=()=>{T(o,c?"restore":"maximize"),o.title=c?"Restore diagram size":"Maximize diagram",o.setAttribute("aria-label",c?"Restore diagram size":"Maximize diagram")},d=()=>{c&&(c=!1,t.classList.remove("is-maximized"),p(),document.body.classList.remove("excalidraw-maximized-open"),this._restoreWrapperMount(e),l.style.height=u,this.maximizedEmbed?.wrapper===t&&(this.maximizedEmbed=null),this._syncEntryLayout(e))},w=()=>{c||(this._exitMaximizedEmbed(),c=!0,u=l.style.height||`${de}px`,this._mountWrapperInMaximizedRoot(e),t.classList.add("is-maximized"),p(),document.body.classList.add("excalidraw-maximized-open"),this.maximizedEmbed={wrapper:t,exit:d},this._syncEntryLayout(e))};return o.addEventListener("click",()=>{c?d():w()}),a.addEventListener("click",()=>{this.onOpenFile?.(e.filePath)}),p(),{iframe:l,instanceId:l.dataset.instanceId,labelElement:r,wrapper:t}}_setupResizer(e,t,i=null){let s=0,r=0,a=l=>{let h=l.clientY-s,c=Math.min(Math.max(r+h,zn),Hn);t.style.height=`${c}px`,t.style.pointerEvents="none"},o=()=>{t.style.pointerEvents="",document.removeEventListener("pointermove",a),document.removeEventListener("pointerup",o),i?.()};e.addEventListener("pointerdown",l=>{l.preventDefault(),s=l.clientY,r=t.offsetHeight,document.addEventListener("pointermove",a),document.addEventListener("pointerup",o)})}_ensureOverlayRoot(){if(this.overlayRoot?.isConnected&&this.overlayRoot.parentElement===this.previewElement)return this.overlayRoot;let e=this.previewElement?.querySelector('[data-excalidraw-overlay-root="true"]');return e||(e=document.createElement("div"),e.dataset.excalidrawOverlayRoot="true",e.className="excalidraw-embed-overlay-root",this.previewElement?.appendChild(e)),this.overlayRoot=e,e}_ensureMaximizedRoot(){if(this.maximizedRoot?.isConnected&&this.maximizedRoot.parentElement===document.body)return this.maximizedRoot;let e=document.body.querySelector('[data-excalidraw-maximized-root="true"]');return e||(e=document.createElement("div"),e.dataset.excalidrawMaximizedRoot="true",e.className="excalidraw-maximized-root",document.body.appendChild(e)),this.maximizedRoot=e,e}_isFilePreviewEntry(e){return e?.key===`${e?.filePath}#file-preview`}_getEntryMode(e){return this._isFilePreviewEntry(e)?"edit":"preview"}_shouldInlineFilePreview(e){return this._isFilePreviewEntry(e)&&!e?.reusedFromEmbed}_resetPlaceholderLayout(e){!e?.placeholder?.isConnected||this._shouldInlineFilePreview(e)||(e.placeholder.classList.remove("is-hydrated"),e.placeholder.removeAttribute("data-embed-hydrated"),e.placeholder.style.height="",e.placeholder.style.pointerEvents="")}_mountWrapperInMaximizedRoot(e){if(!e?.wrapper)return;let t=this._ensureMaximizedRoot();t.hidden=!1,e.restoreParent=e.wrapper.parentElement||null,e.restoreNextSibling=e.wrapper.nextSibling||null,e.wrapper.style.position="",e.wrapper.style.top="",e.wrapper.style.left="",e.wrapper.style.width="",e.wrapper.style.margin="",e.wrapper.parentElement!==t&&t.appendChild(e.wrapper)}_restoreWrapperMount(e){if(e?.wrapper){if(this._shouldInlineFilePreview(e)){let{restoreParent:t,restoreNextSibling:i}=e;t?.isConnected&&(i?.parentElement===t?t.insertBefore(e.wrapper,i):t.appendChild(e.wrapper))}else{let t=this._ensureOverlayRoot();t.hidden=!1,e.wrapper.parentElement!==t&&t.appendChild(e.wrapper)}e.restoreParent=null,e.restoreNextSibling=null,this.maximizedRoot&&this.maximizedRoot.childElementCount===0&&(this.maximizedRoot.hidden=!0)}}_syncEntryLayout(e){if(!e?.wrapper||this._shouldInlineFilePreview(e))return;let t=e.placeholder?.isConnected?e.placeholder:this.previewElement?.querySelector(`.excalidraw-embed-placeholder[data-embed-key="${e.key}"]`);if(!t)return;e.placeholder=t,t.classList.add("is-hydrated"),t.dataset.embedHydrated="true",t.style.pointerEvents="none",this._isFilePreviewEntry(e)&&t.childElementCount>0&&t.replaceChildren();let i=e.wrapper.classList.contains("is-maximized"),s=e.wrapper.querySelector(".excalidraw-embed-header")?.offsetHeight||0,r=e.iframe?.offsetHeight||Number.parseFloat(e.iframe?.style.height||"")||de,a=i?0:e.wrapper.querySelector(".excalidraw-embed-resizer")?.offsetHeight||0,o=Math.ceil(s+r+a);if(i||(e.inlineHeightPx=o),t.style.height=`${Math.ceil(e.inlineHeightPx||o||de)}px`,e.wrapper.style.pointerEvents="auto",i){e.wrapper.style.position="",e.wrapper.style.top="",e.wrapper.style.left="",e.wrapper.style.width="",e.wrapper.style.margin="";return}e.wrapper.style.position="absolute",e.wrapper.style.top=`${t.offsetTop}px`,e.wrapper.style.left=`${t.offsetLeft}px`,e.wrapper.style.width=`${t.offsetWidth}px`,e.wrapper.style.margin="0"}syncLayout(){this.embedEntries.forEach(e=>{e.wrapper&&!this._shouldInlineFilePreview(e)&&this._syncEntryLayout(e)})}_onPreviewClick(e){let t=e.target.closest(".excalidraw-embed-placeholder-btn");if(!t)return;e.preventDefault();let i=this.embedEntries.get(t.dataset.embedKey);i&&this._hydrateEntry(i)}_onMessage(e){if(e.origin!==window.location.origin)return;let t=e.data;if(!t||t.source!=="excalidraw-editor")return;let i=this._findEntryByContentWindow(e.source);if(i){if(t.type==="ready"){i.isReady=!0,this._clearEntryBootTimeout(i),this._syncEntryUser(i),this._postMessageToEntry(i,{source:"collabmd-host",type:"set-theme",theme:this.getTheme?.()||"dark"}),this._syncEntryFollowState(i);return}t.type==="error"&&(i.isReady=!1,this._handleEntryBootTimeout(i))}}_onKeyDown(e){e.key==="Escape"&&this._exitMaximizedEmbed()}_exitMaximizedEmbed(){this.maximizedEmbed?.exit&&this.maximizedEmbed.exit(),this.maximizedEmbed=null,document.body.classList.remove("excalidraw-maximized-open")}_postMessageToEntry(e,t){e?.iframe?.contentWindow?.postMessage(t,window.location.origin)}_syncEntryUser(e,t=null){let i=t||this.getLocalUser?.();i&&this._postMessageToEntry(e,{source:"collabmd-host",type:"set-user",user:{color:i.color||"",colorLight:i.colorLight||"",name:i.name||"",peerId:i.peerId||""}})}_syncEntryFollowState(e){!e?.isReady||e.followedPeerId===void 0||this._postMessageToEntry(e,{source:"collabmd-host",type:"follow-user",peerId:e.followedPeerId})}};function qn(n){return String(n??"").replace(/\/+$/u,"").split("/").filter(Boolean).pop()||""}function Wn(){return JSON.stringify({type:"excalidraw",version:2,source:"collabmd",elements:[],appState:{viewBackgroundColor:"#ffffff",gridSize:null},files:{}})}var tt=class{constructor({onFileDelete:e,onFileSelect:t,state:i,toastController:s,vaultClient:r,view:a,refresh:o}){this.onFileDelete=e,this.onFileSelect=t,this.state=i,this.toastController=s,this.vaultClient=r,this.view=a,this.refresh=o,this.newFileButton=document.getElementById("newFileBtn"),this.newDrawingButton=document.getElementById("newDrawingBtn"),this.newMermaidButton=document.getElementById("newMermaidBtn"),this.newPlantumlButton=document.getElementById("newPlantumlBtn"),this.newFolderButton=document.getElementById("newFolderBtn"),this.refreshButton=document.getElementById("refreshFilesBtn"),this.actionDialog=document.getElementById("fileActionDialog"),this.actionForm=document.getElementById("fileActionForm"),this.actionTitle=document.getElementById("fileActionTitle"),this.actionCopy=document.getElementById("fileActionCopy"),this.actionField=document.getElementById("fileActionField"),this.actionLabel=document.getElementById("fileActionLabel"),this.actionInput=document.getElementById("fileActionInput"),this.actionHint=document.getElementById("fileActionHint"),this.actionNote=document.getElementById("fileActionNote"),this.actionCancelButton=document.getElementById("fileActionCancel"),this.actionSubmitButton=document.getElementById("fileActionSubmit"),this.pendingAction=null,this.actionBusy=!1}initialize(){this.newFileButton?.addEventListener("click",()=>this.handleNewFile()),this.newDrawingButton?.addEventListener("click",()=>this.handleNewDrawing()),this.newMermaidButton?.addEventListener("click",()=>this.handleNewMermaid()),this.newPlantumlButton?.addEventListener("click",()=>this.handleNewPlantUml()),this.newFolderButton?.addEventListener("click",()=>this.handleNewFolder()),this.refreshButton?.addEventListener("click",()=>this.refresh()),this.actionCancelButton?.addEventListener("click",()=>this.closeActionDialog()),this.actionForm?.addEventListener("submit",e=>{e.preventDefault(),this.handleActionSubmit()}),this.actionDialog?.addEventListener("close",()=>this.resetActionDialog())}createContextMenuItems(e=""){return[{label:"New markdown file",onSelect:()=>this.handleNewFile({parentDir:e})},{label:"New Excalidraw drawing",onSelect:()=>this.handleNewDrawing({parentDir:e})},{label:"New Mermaid diagram",onSelect:()=>this.handleNewMermaid({parentDir:e})},{label:"New PlantUML diagram",onSelect:()=>this.handleNewPlantUml({parentDir:e})},{label:"New folder",onSelect:()=>this.handleNewFolder({parentDir:e})}]}getFileContextMenuItems(e){return[{label:"Rename",onSelect:()=>this.handleRename(e)},{label:"Delete",danger:!0,onSelect:()=>this.handleDelete(e)}]}showToast(e){e&&this.toastController?.show(String(e))}showError(e,t){this.showToast(t?.message?`${e}: ${t.message}`:e)}ensureExtension(e,t){return ai(e,t)}openActionDialog({title:e,copy:t,label:i="Path",hint:s="",note:r="",placeholder:a="",value:o="",submitLabel:l="Save",destructive:h=!1,requiresInput:c=!0,emptyMessage:u="A value is required",onSubmit:p}){!this.actionDialog||!this.actionTitle||!this.actionCopy||!this.actionSubmitButton||!this.actionCancelButton||c&&!this.actionInput||(this.actionDialog.open&&(typeof this.actionDialog.close=="function"?this.actionDialog.close():(this.actionDialog.removeAttribute("open"),this.resetActionDialog())),this.pendingAction={requiresInput:c,emptyMessage:u,onSubmit:p},this.view?.removeContextMenu?.(),this.actionTitle.textContent=e,this.actionCopy.textContent=t,this.actionField&&(this.actionField.hidden=!c),this.actionLabel&&(this.actionLabel.textContent=i),this.actionInput&&(this.actionInput.value=o,this.actionInput.placeholder=a,this.actionInput.required=c,this.actionInput.disabled=!1),this.actionHint&&(this.actionHint.textContent=s,this.actionHint.hidden=!c||!s),this.actionNote&&(this.actionNote.textContent=r,this.actionNote.hidden=!r,this.actionNote.classList.toggle("is-danger",h)),this.actionSubmitButton.textContent=l,this.actionSubmitButton.disabled=!1,this.actionSubmitButton.classList.toggle("btn-primary",!h),this.actionSubmitButton.classList.toggle("btn-danger",h),this.actionCancelButton.disabled=!1,typeof this.actionDialog.showModal=="function"?this.actionDialog.showModal():this.actionDialog.setAttribute("open","true"),requestAnimationFrame(()=>{if(!c||!this.actionInput){this.actionSubmitButton.focus();return}this.actionInput.focus(),o&&this.actionInput.select()}))}resetActionDialog(){this.pendingAction=null,this.actionBusy=!1,this.actionField&&(this.actionField.hidden=!1),this.actionLabel&&(this.actionLabel.textContent="Path"),this.actionInput&&(this.actionInput.value="",this.actionInput.placeholder="",this.actionInput.required=!0,this.actionInput.disabled=!1),this.actionHint&&(this.actionHint.textContent="",this.actionHint.hidden=!0),this.actionNote&&(this.actionNote.textContent="",this.actionNote.hidden=!0,this.actionNote.classList.remove("is-danger")),this.actionSubmitButton&&(this.actionSubmitButton.textContent="Save",this.actionSubmitButton.disabled=!1,this.actionSubmitButton.classList.add("btn-primary"),this.actionSubmitButton.classList.remove("btn-danger")),this.actionCancelButton&&(this.actionCancelButton.disabled=!1)}closeActionDialog(){if(this.actionDialog){if(this.actionDialog.open&&typeof this.actionDialog.close=="function"){this.actionDialog.close();return}this.actionDialog.removeAttribute("open"),this.resetActionDialog()}}setActionDialogBusy(e){this.actionBusy=e,this.actionInput&&(this.actionInput.disabled=e||!(this.pendingAction?.requiresInput??!0)),this.actionCancelButton&&(this.actionCancelButton.disabled=e),this.actionSubmitButton&&(this.actionSubmitButton.disabled=e)}async handleActionSubmit(){if(!this.pendingAction?.onSubmit||this.actionBusy)return;let e=this.pendingAction.requiresInput,t=e?this.actionInput?.value.trim()??"":void 0;if(e&&!t){this.showToast(this.pendingAction.emptyMessage),this.actionInput?.focus();return}this.setActionDialogBusy(!0);let i=!1;try{i=await this.pendingAction.onSubmit(t)}catch(s){i=!1,this.showError("Failed to complete action",s)}if(this.setActionDialogBusy(!1),i!==!1){this.closeActionDialog();return}e&&this.actionInput&&(this.actionInput.focus(),this.actionInput.select())}async createVaultFile(e,t,{openAfterCreate:i=!1,errorMessage:s="Failed to create file"}={}){try{return await this.vaultClient.createFile({content:t,path:e}),this.state.expandDirectoryPath(e,{includeLeaf:!1}),await this.refresh(),i&&this.onFileSelect?.(e),!0}catch(r){return this.showToast(r?.message||s),!1}}async createDirectory(e){let t=L(e);if(!t)return this.showToast("Folder path is required"),!1;try{return await this.vaultClient.createDirectory(t),this.state.expandDirectoryPath(t),await this.refresh(),!0}catch(i){return this.showToast(i?.message||"Failed to create folder"),!1}}async renameVaultFile(e,t,i){let s=String(t??"").trim();if(!s)return this.showToast("File name is required"),!1;if(/[\\/]/u.test(s))return this.showToast("Rename only supports the file name right now"),!1;let r=q(s).trim();if(!r)return this.showToast("File name is required"),!1;let o=`${e.includes("/")?e.substring(0,e.lastIndexOf("/")+1):""}${r}${i}`;if(o===e)return!0;try{return await this.vaultClient.renameFile({newPath:o,oldPath:e}),this.state.expandDirectoryPath(o,{includeLeaf:!1}),await this.refresh(),this.state.activeFilePath===e&&(this.state.activeFilePath=o,this.onFileSelect?.(o)),!0}catch(l){return this.showToast(l?.message||"Failed to rename"),!1}}async deleteVaultFile(e){try{return await this.vaultClient.deleteFile(e),await this.refresh(),this.state.activeFilePath===e&&(this.state.activeFilePath=null,this.onFileDelete?.(e)),!0}catch(t){return this.showToast(t?.message||"Failed to delete"),!1}}getCreateContext(e=""){let t=L(e);return{hintPrefix:t?'Use "/" to create nested items under this folder.':'Use "/" to place it inside a folder.',inputLabelSuffix:t?"name or path":"path",note:t?`Parent folder: ${t}`:"",normalizedParentDir:t}}handleNewFile({parentDir:e=""}={}){let t=this.getCreateContext(e);this.openActionDialog({title:"Create markdown file",copy:t.normalizedParentDir?"Add a new note inside the selected folder. It opens immediately after creation.":"Add a new note to the vault. It opens immediately after creation.",label:`File ${t.inputLabelSuffix}`,hint:`${t.hintPrefix} ".md" is added automatically.`,note:t.note,placeholder:t.normalizedParentDir?"my-note":"notes/my-note",submitLabel:"Create file",emptyMessage:"File path is required",onSubmit:i=>{let s=L(i);if(!s)return this.showToast("File path is required"),!1;let r=this.ensureExtension(re(t.normalizedParentDir,s),".md");return this.createVaultFile(r,Me(r),{errorMessage:"Failed to create file",openAfterCreate:!0})}})}handleNewFolder({parentDir:e=""}={}){let t=this.getCreateContext(e);this.openActionDialog({title:"Create folder",copy:t.normalizedParentDir?"Add a new folder inside the selected folder.":"Add a new folder to organize notes and diagrams.",label:`Folder ${t.inputLabelSuffix}`,hint:t.hintPrefix,note:t.note,placeholder:t.normalizedParentDir?"archive":"notes/archive",submitLabel:"Create folder",emptyMessage:"Folder path is required",onSubmit:i=>this.createDirectory(re(t.normalizedParentDir,i))})}handleNewDrawing({parentDir:e=""}={}){let t=this.getCreateContext(e);this.openActionDialog({title:"Create Excalidraw drawing",copy:t.normalizedParentDir?"Start a new drawing inside the selected folder.":"Start a new drawing file in the vault.",label:`Drawing ${t.inputLabelSuffix}`,hint:`${t.hintPrefix} ".excalidraw" is added automatically.`,note:t.note,placeholder:t.normalizedParentDir?"architecture":"diagrams/architecture",submitLabel:"Create drawing",emptyMessage:"Drawing path is required",onSubmit:i=>{let s=L(i);if(!s)return this.showToast("Drawing path is required"),!1;let r=this.ensureExtension(re(t.normalizedParentDir,s),".excalidraw");return this.createVaultFile(r,Wn(),{errorMessage:"Failed to create drawing",openAfterCreate:!0})}})}handleNewMermaid({parentDir:e=""}={}){let t=this.getCreateContext(e);this.openActionDialog({title:"Create Mermaid diagram",copy:t.normalizedParentDir?"Create a new `.mmd` or `.mermaid` file inside the selected folder.":"Create a new `.mmd` or `.mermaid` file with starter diagram content.",label:`Diagram ${t.inputLabelSuffix}`,hint:`${t.hintPrefix} ".mmd" is added automatically unless you enter ".mermaid".`,note:t.note,placeholder:t.normalizedParentDir?"flow":"diagrams/flow",submitLabel:"Create diagram",emptyMessage:"Diagram path is required",onSubmit:i=>{let s=L(i);if(!s)return this.showToast("Diagram path is required"),!1;let r=oi(re(t.normalizedParentDir,s));return this.createVaultFile(r.path,r.content,{errorMessage:"Failed to create Mermaid diagram",openAfterCreate:!0})}})}handleNewPlantUml({parentDir:e=""}={}){let t=this.getCreateContext(e);this.openActionDialog({title:"Create PlantUML diagram",copy:t.normalizedParentDir?"Create a new `.puml` or `.plantuml` file inside the selected folder.":"Create a new `.puml` or `.plantuml` file with starter diagram content.",label:`Diagram ${t.inputLabelSuffix}`,hint:`${t.hintPrefix} ".puml" is added automatically unless you enter ".plantuml".`,note:t.note,placeholder:t.normalizedParentDir?"sequence-flow":"diagrams/sequence-flow",submitLabel:"Create diagram",emptyMessage:"Diagram path is required",onSubmit:i=>{let s=L(i);if(!s)return this.showToast("Diagram path is required"),!1;let r=li(re(t.normalizedParentDir,s));return this.createVaultFile(r.path,r.content,{errorMessage:"Failed to create PlantUML diagram",openAfterCreate:!0})}})}handleRename(e){let t=qn(e),i=Ot(t)??".md";this.openActionDialog({title:"Rename file",copy:"Update the file name without changing its current type.",label:"Name",hint:`${i} is kept automatically.`,value:q(t),submitLabel:"Rename file",emptyMessage:"File name is required",onSubmit:s=>this.renameVaultFile(e,s,i)})}handleDelete(e){this.openActionDialog({title:"Delete file",copy:"This permanently removes the file from the vault.",note:e,submitLabel:"Delete file",destructive:!0,requiresInput:!1,onSubmit:()=>this.deleteVaultFile(e)})}};function Di(n,e=[]){for(let t of n){if(t.type==="file"||t.type==="excalidraw"||t.type==="mermaid"||t.type==="plantuml"||t.type==="image"){e.push(t.path);continue}t.type==="directory"&&Array.isArray(t.children)&&Di(t.children,e)}return e}var it=class{constructor(){this.tree=[],this.flatFiles=[],this.activeFilePath=null,this.expandedDirs=new Set,this.searchQuery=""}setTree(e){this.tree=Array.isArray(e)?e:[],this.flatFiles=Di(this.tree,[])}setSearchQuery(e){this.searchQuery=String(e??"").trim().toLowerCase()}getSearchMatches(){return this.searchQuery?this.flatFiles.filter(e=>e.toLowerCase().includes(this.searchQuery)):[]}setActiveFile(e){this.activeFilePath=e||null,e&&this.expandDirectoryPath(e,{includeLeaf:!1})}toggleDirectory(e){return this.expandedDirs.has(e)?(this.expandedDirs.delete(e),!1):(this.expandedDirs.add(e),!0)}expandDirectoryPath(e,{includeLeaf:t=!0}={}){let i=L(e);if(!i)return;let s=i.split("/"),r=t?s.length:Math.max(s.length-1,0),a="";for(let o=0;o<r;o+=1)a=a?`${a}/${s[o]}`:s[o],this.expandedDirs.add(a)}};function Gn(n){return String(n??"").replace(/\/+$/u,"").split("/").filter(Boolean).pop()||""}function Vn(n){let e=String(n??"").replace(/\/+$/u,""),t=e.lastIndexOf("/");return t>=0?e.slice(0,t):""}function Hi(n=[],e=""){for(let t of n){if(t.path===e)return t;if(t.type==="directory"&&Array.isArray(t.children)){let i=Hi(t.children,e);if(i)return i}}return null}var nt=class{constructor({onDirectoryToggle:e,onFileContextMenu:t,onFileSelect:i,onSearchChange:s,onTreeContextMenu:r}){this.onDirectoryToggle=e,this.onFileContextMenu=t,this.onFileSelect=i,this.onSearchChange=s,this.onTreeContextMenu=r,this.treeContainer=document.getElementById("fileTree"),this.searchInput=document.getElementById("fileSearchInput"),this.renderedDirectoryWrappers=new Map,this.renderedChildContainers=new Map,this.lastRenderMode="tree"}initialize(){this.searchInput?.addEventListener("input",e=>{this.onSearchChange?.(e.target.value)}),this.treeContainer?.addEventListener("contextmenu",e=>{e.target.closest(".file-tree-item")||(e.preventDefault(),this.onTreeContextMenu?.(e))})}render({activeFilePath:e,changedPaths:t=null,expandedDirs:i,reset:s=!1,searchMatches:r,searchQuery:a,tree:o}){if(!this.treeContainer)return;if(a){this.lastRenderMode="search",this.renderSearchResults(r,e);return}if(s||this.lastRenderMode!=="tree"||!Array.isArray(t)||t.length===0){this.renderFullTree(o,{activeFilePath:e,expandedDirs:i}),this.lastRenderMode="tree";return}let l=Array.from(new Set(t.map(h=>Vn(h)))).sort((h,c)=>h.split("/").length-c.split("/").length).filter((h,c,u)=>!u.slice(0,c).some(p=>p&&h.startsWith(`${p}/`)));if(l.includes("")){this.renderFullTree(o,{activeFilePath:e,expandedDirs:i}),this.lastRenderMode="tree";return}for(let h of l)if(!this.rerenderDirectoryBranch(h,o,{activeFilePath:e,expandedDirs:i})){this.renderFullTree(o,{activeFilePath:e,expandedDirs:i}),this.lastRenderMode="tree";return}this.lastRenderMode="tree"}renderSearchResults(e,t){if(!this.treeContainer)return;if(this.resetTreeIndexes(),this.treeContainer.innerHTML="",e.length===0){this.treeContainer.innerHTML='<div class="file-tree-empty">No matches</div>';return}let i=document.createDocumentFragment();for(let s of e)i.appendChild(this.createFileItem({activeFilePath:t,depth:0,filePath:s,fileType:$t(s)??"file",name:Gn(s)}));this.treeContainer.appendChild(i)}renderFullTree(e,{activeFilePath:t,expandedDirs:i}){if(this.resetTreeIndexes(),this.treeContainer.innerHTML="",e.length===0){this.treeContainer.innerHTML='<div class="file-tree-empty">No vault files found</div>';return}let s=document.createDocumentFragment();this.renderNodes(e,s,{activeFilePath:t,depth:0,expandedDirs:i}),this.treeContainer.appendChild(s)}resetTreeIndexes(){this.renderedDirectoryWrappers.clear(),this.renderedChildContainers.clear()}renderNodes(e,t,{activeFilePath:i,depth:s,expandedDirs:r}){for(let a of e){if(a.type==="directory"){t.appendChild(this.createDirectoryItem(a,{activeFilePath:i,depth:s,expandedDirs:r}));continue}t.appendChild(this.createFileItem({activeFilePath:i,depth:s,filePath:a.path,fileType:a.type,name:a.name}))}}createDirectoryItem(e,{activeFilePath:t,depth:i,expandedDirs:s}){let r=document.createElement("div");r.className="file-tree-group";let a=document.createElement("button");a.className="file-tree-item file-tree-dir",a.style.setProperty("--depth",i),a.dataset.depth=i;let o=s.has(e.path);if(a.setAttribute("aria-expanded",String(o)),a.innerHTML=`
|
|
48
48
|
<svg class="file-tree-chevron${o?" expanded":""}" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="9 18 15 12 9 6"/></svg>
|
|
49
49
|
<svg class="file-tree-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg>
|
|
50
|
-
<span class="file-tree-name">${
|
|
51
|
-
`,a.addEventListener("click",()=>{this.onDirectoryToggle?.(e.path)}),a.addEventListener("contextmenu",l=>{l.preventDefault(),this.onFileContextMenu?.(l,{directoryPath:e.path,type:"directory"})}),r.appendChild(a),o&&Array.isArray(e.children)){let l=document.createElement("div");l.className="file-tree-children",this.renderNodes(e.children,l,{activeFilePath:t,depth:i+1,expandedDirs:s}),r.appendChild(l)}return r}createFileItem({activeFilePath:e,depth:t,filePath:i,fileType:s="file",name:r}){let a=document.createElement("button");a.className="file-tree-item file-tree-file";let o=s==="excalidraw",l=s==="image",h=s==="mermaid",c=s==="plantuml";return o&&a.classList.add("is-excalidraw"),l&&a.classList.add("is-image"),h&&a.classList.add("is-mermaid"),c&&a.classList.add("is-plantuml"),i===e&&a.classList.add("active"),a.style.setProperty("--depth",t),a.dataset.depth=t,a.dataset.path=i,a.innerHTML=`
|
|
50
|
+
<span class="file-tree-name">${g(e.name)}</span>
|
|
51
|
+
`,a.addEventListener("click",()=>{this.onDirectoryToggle?.(e.path)}),a.addEventListener("contextmenu",l=>{l.preventDefault(),this.onFileContextMenu?.(l,{directoryPath:e.path,type:"directory"})}),r.appendChild(a),this.renderedDirectoryWrappers.set(e.path,r),o&&Array.isArray(e.children)){let l=document.createElement("div");l.className="file-tree-children",this.renderedChildContainers.set(e.path,l),this.renderNodes(e.children,l,{activeFilePath:t,depth:i+1,expandedDirs:s}),r.appendChild(l)}else this.renderedChildContainers.delete(e.path);return r}rerenderDirectoryBranch(e,t,{activeFilePath:i,expandedDirs:s}){let r=this.renderedDirectoryWrappers.get(e),a=Hi(t,e);if(!r||a?.type!=="directory")return!1;let o=r.querySelector(".file-tree-dir"),l=s.has(e);o?.setAttribute("aria-expanded",String(l)),o?.querySelector(".file-tree-chevron")?.classList.toggle("expanded",l);let h=Number(o?.dataset.depth??0),c=this.renderedChildContainers.get(e)??r.querySelector(".file-tree-children");return this.clearRenderedDescendants(e),l?(c?c.innerHTML="":(c=document.createElement("div"),c.className="file-tree-children",r.appendChild(c)),this.renderedChildContainers.set(e,c),this.renderNodes(a.children??[],c,{activeFilePath:i,depth:h+1,expandedDirs:s}),!0):(c?.remove(),this.renderedChildContainers.delete(e),!0)}clearRenderedDescendants(e){let t=`${e}/`;Array.from(this.renderedDirectoryWrappers.keys()).forEach(i=>{i.startsWith(t)&&this.renderedDirectoryWrappers.delete(i)}),Array.from(this.renderedChildContainers.keys()).forEach(i=>{i.startsWith(t)&&this.renderedChildContainers.delete(i)})}createFileItem({activeFilePath:e,depth:t,filePath:i,fileType:s="file",name:r}){let a=document.createElement("button");a.className="file-tree-item file-tree-file";let o=s==="excalidraw",l=s==="image",h=s==="mermaid",c=s==="plantuml";return o&&a.classList.add("is-excalidraw"),l&&a.classList.add("is-image"),h&&a.classList.add("is-mermaid"),c&&a.classList.add("is-plantuml"),i===e&&a.classList.add("active"),a.style.setProperty("--depth",t),a.dataset.depth=t,a.dataset.path=i,a.innerHTML=`
|
|
52
52
|
${this.getFileIconSvg({isExcalidraw:o,isImage:l,isMermaid:h,isPlantUml:c})}
|
|
53
|
-
<span class="file-tree-name">${
|
|
54
|
-
`,a.addEventListener("click",()=>{this.onFileSelect?.(i)}),a.addEventListener("contextmenu",u=>{u.preventDefault(),this.onFileContextMenu?.(u,{filePath:i,type:"file"})}),a}getFileIconSvg({isExcalidraw:e,isImage:t,isMermaid:i,isPlantUml:s}){return e?'<svg class="file-tree-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 19l7-7 3 3-7 7-3-3z"/><path d="M18 13l-1.5-7.5L2 2l3.5 14.5L13 18l5-5z"/><path d="M2 2l7.586 7.586"/><circle cx="11" cy="11" r="2"/></svg>':t?'<svg class="file-tree-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="16" rx="2"/><circle cx="9" cy="10" r="1.5"/><path d="m21 16-5-5L7 20"/><path d="m14 14 2 2"/></svg>':i?'<svg class="file-tree-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 7.5c0-1.38 1.12-2.5 2.5-2.5 1.04 0 1.93.64 2.3 1.56A2.5 2.5 0 0 1 14 8.5v1"/><path d="M19 16.5c0 1.38-1.12 2.5-2.5 2.5-1.04 0-1.93-.64-2.3-1.56A2.5 2.5 0 0 1 10 15.5v-1"/><path d="M8 10.5h8"/><path d="M8 13.5h8"/><path d="M10 8.5v7"/><path d="M14 8.5v7"/></svg>':s?'<svg class="file-tree-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="7" height="6" rx="1"/><rect x="14" y="4" width="7" height="6" rx="1"/><rect x="8.5" y="14" width="7" height="6" rx="1"/><path d="M10 7h4"/><path d="M17.5 10v2.5"/><path d="M6.5 10v2.5"/><path d="M6.5 12.5h11"/></svg>':'<svg class="file-tree-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>'}showContextMenu(e,t){if(this.removeContextMenu(),!Array.isArray(t)||t.length===0)return;let i=document.createElement("div");i.className="file-context-menu";for(let l of t){let h=document.createElement("button");h.className=`file-context-item${l.danger?" file-context-danger":""}`,h.textContent=l.label,h.addEventListener("click",()=>{this.removeContextMenu(),l.onSelect?.()}),i.appendChild(h)}document.body.appendChild(i);let s=i.getBoundingClientRect(),r=Math.max(8,window.innerWidth-s.width-8),a=Math.max(8,window.innerHeight-s.height-8);i.style.left=`${Math.max(8,Math.min(e.clientX,r))}px`,i.style.top=`${Math.max(8,Math.min(e.clientY,a))}px`;let o=l=>{i.contains(l.target)||(this.removeContextMenu(),document.removeEventListener("click",o))};setTimeout(()=>document.addEventListener("click",o),0)}removeContextMenu(){document.querySelectorAll(".file-context-menu").forEach(e=>e.remove())}};var
|
|
53
|
+
<span class="file-tree-name">${g(q(r))}</span>
|
|
54
|
+
`,a.addEventListener("click",()=>{this.onFileSelect?.(i)}),a.addEventListener("contextmenu",u=>{u.preventDefault(),this.onFileContextMenu?.(u,{filePath:i,type:"file"})}),a}getFileIconSvg({isExcalidraw:e,isImage:t,isMermaid:i,isPlantUml:s}){return e?'<svg class="file-tree-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 19l7-7 3 3-7 7-3-3z"/><path d="M18 13l-1.5-7.5L2 2l3.5 14.5L13 18l5-5z"/><path d="M2 2l7.586 7.586"/><circle cx="11" cy="11" r="2"/></svg>':t?'<svg class="file-tree-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="16" rx="2"/><circle cx="9" cy="10" r="1.5"/><path d="m21 16-5-5L7 20"/><path d="m14 14 2 2"/></svg>':i?'<svg class="file-tree-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 7.5c0-1.38 1.12-2.5 2.5-2.5 1.04 0 1.93.64 2.3 1.56A2.5 2.5 0 0 1 14 8.5v1"/><path d="M19 16.5c0 1.38-1.12 2.5-2.5 2.5-1.04 0-1.93-.64-2.3-1.56A2.5 2.5 0 0 1 10 15.5v-1"/><path d="M8 10.5h8"/><path d="M8 13.5h8"/><path d="M10 8.5v7"/><path d="M14 8.5v7"/></svg>':s?'<svg class="file-tree-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="7" height="6" rx="1"/><rect x="14" y="4" width="7" height="6" rx="1"/><rect x="8.5" y="14" width="7" height="6" rx="1"/><path d="M10 7h4"/><path d="M17.5 10v2.5"/><path d="M6.5 10v2.5"/><path d="M6.5 12.5h11"/></svg>':'<svg class="file-tree-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>'}showContextMenu(e,t){if(this.removeContextMenu(),!Array.isArray(t)||t.length===0)return;let i=document.createElement("div");i.className="file-context-menu";for(let l of t){let h=document.createElement("button");h.className=`file-context-item${l.danger?" file-context-danger":""}`,h.textContent=l.label,h.addEventListener("click",()=>{this.removeContextMenu(),l.onSelect?.()}),i.appendChild(h)}document.body.appendChild(i);let s=i.getBoundingClientRect(),r=Math.max(8,window.innerWidth-s.width-8),a=Math.max(8,window.innerHeight-s.height-8);i.style.left=`${Math.max(8,Math.min(e.clientX,r))}px`,i.style.top=`${Math.max(8,Math.min(e.clientY,a))}px`;let o=l=>{i.contains(l.target)||(this.removeContextMenu(),document.removeEventListener("click",o))};setTimeout(()=>document.addEventListener("click",o),0)}removeContextMenu(){document.querySelectorAll(".file-context-menu").forEach(e=>e.remove())}};var st=class{constructor({onFileSelect:e,onFileDelete:t,toastController:i,vaultClient:s=he}){this.onFileSelect=e,this.onFileDelete=t,this.toastController=i,this.vaultClient=s,this.state=new it,this.view=new nt({onDirectoryToggle:r=>{this.state.toggleDirectory(r),this.renderTree()},onFileContextMenu:(r,a)=>{if(a.type==="directory"){this.view.showContextMenu(r,this.actionController.createContextMenuItems(a.directoryPath));return}this.view.showContextMenu(r,this.actionController.getFileContextMenuItems(a.filePath))},onFileSelect:r=>{this.onFileSelect?.(r)},onSearchChange:r=>{this.state.setSearchQuery(r),this.renderTree()},onTreeContextMenu:r=>{this.view.showContextMenu(r,this.actionController.createContextMenuItems())}}),this.actionController=new tt({onFileDelete:this.onFileDelete,onFileSelect:this.onFileSelect,refresh:()=>this.refresh(),state:this.state,toastController:this.toastController,vaultClient:this.vaultClient,view:this.view})}initialize(){this.view.initialize(),this.actionController.initialize()}async refresh(){try{let e=await this.vaultClient.readTree();this.setTree(e.tree||[])}catch(e){console.error("[explorer] Failed to load file tree:",e.message)}}setTree(e,{changedPaths:t=null,reset:i=!1}={}){this.state.setTree(e),this.renderTree({changedPaths:t,reset:i})}setActiveFile(e){this.state.setActiveFile(e),this.renderTree()}get flatFiles(){return this.state.flatFiles}get flatDocumentFiles(){return this.state.flatFiles.filter(e=>!ye(e))}renderTree({changedPaths:e=null,reset:t=!1}={}){this.view.render({activeFilePath:this.state.activeFilePath,changedPaths:e,expandedDirs:this.state.expandedDirs,reset:t,searchMatches:this.state.getSearchMatches(),searchQuery:this.state.searchQuery,tree:this.state.tree})}};function Kn(n){return String(n??"").split("/").pop()||""}function ue(n){switch(n){case"added":case"untracked":return"added";case"deleted":return"deleted";case"renamed":return"renamed";default:return"modified"}}function jn(n,e){let t=0;for(;t<n.length&&t<e.length&&n[t]===e[t];)t+=1;return t}function Qn(n,e,t){let i=0,s=Math.min(n.length,e.length)-t;for(;i<s;){let r=n.length-1-i,a=e.length-1-i;if(n[r]!==e[a])break;i+=1}return i}function Ui(n,e){let t=jn(n,e),i=Qn(n,e,t),s=Math.max(t,n.length-i),r=Math.max(t,e.length-i),a=`${g(n.slice(0,t))}${s>t?`<span class="diff-highlight-del">${g(n.slice(t,s))}</span>`:""}${g(n.slice(s))}`,o=`${g(e.slice(0,t))}${r>t?`<span class="diff-highlight-add">${g(e.slice(t,r))}</span>`:""}${g(e.slice(r))}`;return{leftHtml:a,rightHtml:o}}function _i(n=[]){let e=[];for(let t=0;t<n.length;t+=1){let i=n[t];if(i.type==="context"||i.type==="note"){e.push({additions:[],context:[i],deletions:[]});continue}if(i.type!=="deletion"&&i.type!=="addition")continue;let s=[],r=[];for(;t<n.length&&n[t].type==="deletion";)s.push(n[t]),t+=1;for(;t<n.length&&n[t].type==="addition";)r.push(n[t]),t+=1;t-=1,e.push({additions:r,context:[],deletions:s})}return e}function Nt(n,e,t){let i=Number.isInteger(n.oldLine)?n.oldLine:"",s=Number.isInteger(n.newLine)?n.newLine:"",r=n.type==="note"?"note":n.type,a=n.type==="context"||n.type==="note"?" ":e;return`
|
|
55
55
|
<div class="diff-line ${r}">
|
|
56
56
|
<div class="diff-line-numbers">
|
|
57
57
|
<span class="diff-line-num">${i}</span>
|
|
58
58
|
<span class="diff-line-num">${s}</span>
|
|
59
59
|
</div>
|
|
60
|
-
<div class="diff-line-prefix">${
|
|
60
|
+
<div class="diff-line-prefix">${g(a)}</div>
|
|
61
61
|
<div class="diff-line-content">${t}</div>
|
|
62
62
|
</div>
|
|
63
|
-
`}function
|
|
63
|
+
`}function zi(n,e){let t=n?g(n.content):"",i=e?g(e.content):"";if(n&&e&&n.type==="deletion"&&e.type==="addition"){let s=Ui(n.content,e.content);t=s.leftHtml,i=s.rightHtml}return`
|
|
64
64
|
<div class="diff-split-row">
|
|
65
65
|
<div class="diff-split-line ${n?.type||"empty"}">
|
|
66
66
|
<span class="diff-split-num">${Number.isInteger(n?.oldLine)?n.oldLine:""}</span>
|
|
@@ -71,27 +71,27 @@ ${r}`}getPreviewSource(e){let t=this.getSession()?.getText()??"";return this.isM
|
|
|
71
71
|
<span class="diff-split-content">${i}</span>
|
|
72
72
|
</div>
|
|
73
73
|
</div>
|
|
74
|
-
`}var
|
|
75
|
-
<div class="diff-hunk-header">${
|
|
74
|
+
`}var rt=class{constructor({onCommitStaged:e=null,onOpenFile:t=null,onStageFile:i=null,onUnstageFile:s=null,toastController:r=null}={}){this.onCommitStaged=e,this.onOpenFile=t,this.onStageFile=i,this.onUnstageFile=s,this.toastController=r,this.page=document.getElementById("diff-page"),this.content=document.getElementById("diffContent"),this.scrollContainer=document.getElementById("diffScroll"),this.fileIndicator=document.getElementById("diffFileIndicator"),this.openEditorButton=document.getElementById("diffOpenEditorBtn"),this.primaryActionButton=document.getElementById("diffPrimaryActionBtn"),this.commitButton=document.getElementById("diffCommitBtn"),this.stats=document.getElementById("diffStats"),this.prevButton=document.getElementById("diffPrevBtn"),this.nextButton=document.getElementById("diffNextBtn"),this.modeButtons=Array.from(document.querySelectorAll("[data-diff-mode]")),this.mode="unified",this.data=null,this.currentIndex=0,this.fileCache=new Map,this.loadingFilePath=null,this.requestScope="all",this.pendingAction=null,this.repoStatus=null}initialize(){this.prevButton?.addEventListener("click",()=>this.navigateFile(-1)),this.nextButton?.addEventListener("click",()=>this.navigateFile(1)),this.openEditorButton?.addEventListener("click",()=>{let e=this.getCurrentFile();e?.path&&this.onOpenFile?.(e.path)}),this.primaryActionButton?.addEventListener("click",()=>{let e=this.getPrimaryAction();e&&this.handleFileAction(e)}),this.commitButton?.addEventListener("click",()=>{this.handleFileAction("commit")}),this.content?.addEventListener("click",e=>{e.target instanceof Element&&e.target.closest("[data-load-full-diff]")&&this.loadCurrentFile({forceFullPatch:!0})}),this.modeButtons.forEach(e=>{e.addEventListener("click",()=>{let t=e.getAttribute("data-diff-mode");!t||t===this.mode||(this.mode=t,this.render())})})}hide(){this.page?.classList.add("hidden"),this.content&&(this.content.innerHTML=""),this.data=null,this.currentIndex=0,this.fileCache.clear(),this.loadingFilePath=null,this.pendingAction=null,this.repoStatus=null,this.syncToolbar()}async open({filePath:e=null,scope:t="all"}={}){this.fileCache.clear(),this.loadingFilePath=null,this.requestScope=t,this.renderLoading("Loading diff summary...");try{let i=new URLSearchParams;i.set("scope",t),e&&i.set("path",e),i.set("metaOnly","true");let s=await fetch(C(`/git/diff?${i.toString()}`)),r=await s.json();if(!s.ok)throw new Error(r.error||"Failed to load git diff");this.data=r;let a=e?Math.max(0,r.files.findIndex(o=>o.path===e)):0;return this.currentIndex=a,(r.files?.length??0)===0?(this.render(),r):(await this.loadCurrentFile(),r)}catch(i){return console.error("[git-diff] Failed to load diff:",i),this.toastController?.show("Failed to load git diff"),this.data={files:[],metaOnly:!1,summary:{additions:0,deletions:0,filesChanged:0}},this.renderEmpty("Failed to load git diff"),this.data}}navigateFile(e){if(!this.data?.files?.length)return;let t=Math.max(0,Math.min(this.currentIndex+e,this.data.files.length-1));t!==this.currentIndex&&(this.currentIndex=t,this.scrollContainer?.scrollTo({top:0,behavior:"auto"}),this.loadCurrentFile())}renderLoading(e="Loading git diff..."){this.page?.classList.remove("hidden"),this.content&&(this.content.innerHTML=`<div class="diff-empty-state">${g(e)}</div>`),this.data=null,this.syncToolbar()}renderEmpty(e){this.page?.classList.remove("hidden"),this.content&&(this.content.innerHTML=`<div class="diff-empty-state">${g(e)}</div>`),this.syncToolbar()}renderUnifiedHunk(e){let t=[];for(let i of _i(e.lines)){if(i.context.length>0){for(let r of i.context)t.push(Nt(r," ",g(r.content)));continue}let s=Math.max(i.deletions.length,i.additions.length);for(let r=0;r<s;r+=1){let a=i.deletions[r]??null,o=i.additions[r]??null,l=a&&o?Ui(a.content,o.content):null;a&&t.push(Nt(a,"-",l?.leftHtml??g(a.content))),o&&t.push(Nt(o,"+",l?.rightHtml??g(o.content)))}}return`
|
|
75
|
+
<div class="diff-hunk-header">${g(e.header)}</div>
|
|
76
76
|
${t.join("")}
|
|
77
77
|
`}renderUnifiedFile(e,t){return`
|
|
78
78
|
<section class="diff-file-block" data-diff-file-index="${t}">
|
|
79
79
|
<div class="diff-file-header">
|
|
80
|
-
<span class="diff-file-path">${
|
|
81
|
-
<span class="git-status-badge ${ue(e.status)}">${
|
|
80
|
+
<span class="diff-file-path">${g(e.path)}</span>
|
|
81
|
+
<span class="git-status-badge ${ue(e.status)}">${g(e.status)}</span>
|
|
82
82
|
<span class="diff-file-header-stats"><span class="diff-stats-add">+${e.stats?.additions??0}</span><span class="diff-stats-del">-${e.stats?.deletions??0}</span></span>
|
|
83
83
|
</div>
|
|
84
|
-
${e.isBinary?`<div class="diff-binary-message">${
|
|
84
|
+
${e.isBinary?`<div class="diff-binary-message">${g(e.binaryMessage||"Binary file changed")}</div>`:""}
|
|
85
85
|
${e.hunks.map(i=>this.renderUnifiedHunk(i)).join("")}
|
|
86
86
|
</section>
|
|
87
|
-
`}renderSplitFile(e,t){let i=e.hunks.map(s=>{let r=[];for(let a of
|
|
88
|
-
<div class="diff-split-hunk">${
|
|
87
|
+
`}renderSplitFile(e,t){let i=e.hunks.map(s=>{let r=[];for(let a of _i(s.lines)){if(a.context.length>0){for(let l of a.context)r.push(zi(l,l));continue}let o=Math.max(a.deletions.length,a.additions.length);for(let l=0;l<o;l+=1)r.push(zi(a.deletions[l]??null,a.additions[l]??null))}return`
|
|
88
|
+
<div class="diff-split-hunk">${g(s.header)}</div>
|
|
89
89
|
${r.join("")}
|
|
90
90
|
`}).join("");return`
|
|
91
91
|
<section class="diff-file-block" data-diff-file-index="${t}">
|
|
92
92
|
<div class="diff-file-header">
|
|
93
|
-
<span class="diff-file-path">${
|
|
94
|
-
<span class="git-status-badge ${ue(e.status)}">${
|
|
93
|
+
<span class="diff-file-path">${g(e.path)}</span>
|
|
94
|
+
<span class="git-status-badge ${ue(e.status)}">${g(e.status)}</span>
|
|
95
95
|
<span class="diff-file-header-stats"><span class="diff-stats-add">+${e.stats?.additions??0}</span><span class="diff-stats-del">-${e.stats?.deletions??0}</span></span>
|
|
96
96
|
</div>
|
|
97
97
|
<div class="diff-split">
|
|
@@ -101,19 +101,19 @@ ${r}`}getPreviewSource(e){let t=this.getSession()?.getText()??"";return this.isM
|
|
|
101
101
|
</div>
|
|
102
102
|
</div>
|
|
103
103
|
</section>
|
|
104
|
-
`}getCurrentFile(){let e=this.data?.files??[];return e.length===0?null:e[this.currentIndex]??e[0]??null}getCurrentCacheKey(){let e=this.getCurrentFile();return e?.path?`${this.requestScope}:${e.path}`:null}getCurrentFileDetail(){let e=this.getCurrentCacheKey();return e?this.fileCache.get(e):null}getCurrentActionState(){let e=this.getCurrentFile(),t=this.getCurrentFileDetail()??e,i=Number(this.repoStatus?.summary?.staged||0);return t?.path?{canCommit:i>0,canStage:!!(t.hasWorkingTreeChanges||t.hasUntrackedChanges),canUnstage:!!t.hasStagedChanges}:{canCommit:i>0,canStage:!1,canUnstage:!1}}getPrimaryAction(){let e=this.getCurrentActionState();return e.canStage&&!e.canUnstage?"stage":e.canUnstage&&!e.canStage||this.requestScope==="staged"&&e.canUnstage?"unstage":e.canStage?"stage":e.canUnstage?"unstage":null}async handleFileAction(e){let t=this.getCurrentFile();if(!(!t?.path||this.pendingAction)){this.pendingAction=e,this.syncToolbar();try{e==="stage"?await this.onStageFile?.(t.path,{scope:this.requestScope}):e==="unstage"?await this.onUnstageFile?.(t.path,{scope:this.requestScope}):e==="commit"&&await this.onCommitStaged?.()}finally{this.pendingAction=null,this.syncToolbar()}}}setRepoStatus(e){this.repoStatus=e,this.syncToolbar()}async loadCurrentFile({forceFullPatch:e=!1}={}){let t=this.getCurrentFile();if(!t?.path)return this.render(),null;let i=this.getCurrentCacheKey(),s=i?this.fileCache.get(i):null;if(s&&(!s.tooLarge||!e))return this.loadingFilePath=null,this.render(),s;this.loadingFilePath=t.path,this.render();try{let r=new URLSearchParams;r.set("scope",this.requestScope),r.set("path",t.path),e&&r.set("allowLargePatch","true");let a=await fetch(
|
|
104
|
+
`}getCurrentFile(){let e=this.data?.files??[];return e.length===0?null:e[this.currentIndex]??e[0]??null}getCurrentCacheKey(){let e=this.getCurrentFile();return e?.path?`${this.requestScope}:${e.path}`:null}getCurrentFileDetail(){let e=this.getCurrentCacheKey();return e?this.fileCache.get(e):null}getCurrentActionState(){let e=this.getCurrentFile(),t=this.getCurrentFileDetail()??e,i=Number(this.repoStatus?.summary?.staged||0);return t?.path?{canCommit:i>0,canStage:!!(t.hasWorkingTreeChanges||t.hasUntrackedChanges),canUnstage:!!t.hasStagedChanges}:{canCommit:i>0,canStage:!1,canUnstage:!1}}getPrimaryAction(){let e=this.getCurrentActionState();return e.canStage&&!e.canUnstage?"stage":e.canUnstage&&!e.canStage||this.requestScope==="staged"&&e.canUnstage?"unstage":e.canStage?"stage":e.canUnstage?"unstage":null}async handleFileAction(e){let t=this.getCurrentFile();if(!(!t?.path||this.pendingAction)){this.pendingAction=e,this.syncToolbar();try{e==="stage"?await this.onStageFile?.(t.path,{scope:this.requestScope}):e==="unstage"?await this.onUnstageFile?.(t.path,{scope:this.requestScope}):e==="commit"&&await this.onCommitStaged?.()}finally{this.pendingAction=null,this.syncToolbar()}}}setRepoStatus(e){this.repoStatus=e,this.syncToolbar()}async loadCurrentFile({forceFullPatch:e=!1}={}){let t=this.getCurrentFile();if(!t?.path)return this.render(),null;let i=this.getCurrentCacheKey(),s=i?this.fileCache.get(i):null;if(s&&(!s.tooLarge||!e))return this.loadingFilePath=null,this.render(),s;this.loadingFilePath=t.path,this.render();try{let r=new URLSearchParams;r.set("scope",this.requestScope),r.set("path",t.path),e&&r.set("allowLargePatch","true");let a=await fetch(C(`/git/diff?${r.toString()}`)),o=await a.json();if(!a.ok)throw new Error(o.error||"Failed to load file diff");let l={...t,...o.files?.[0]??{}};return i&&this.fileCache.set(i,l),this.loadingFilePath=null,this.render(),l}catch(r){return console.error("[git-diff] Failed to load file diff:",r),this.toastController?.show("Failed to load file diff"),this.loadingFilePath=null,this.render(),null}}renderCurrentFile(){let e=this.getCurrentFile();if(!e)return'<div class="diff-empty-state">No changes to display.</div>';let t=this.getCurrentFileDetail();return this.loadingFilePath===e.path?`
|
|
105
105
|
<section class="diff-file-block">
|
|
106
106
|
<div class="diff-file-header">
|
|
107
|
-
<span class="diff-file-path">${
|
|
108
|
-
<span class="git-status-badge ${ue(e.status)}">${
|
|
107
|
+
<span class="diff-file-path">${g(e.path)}</span>
|
|
108
|
+
<span class="git-status-badge ${ue(e.status)}">${g(e.status)}</span>
|
|
109
109
|
</div>
|
|
110
110
|
<div class="diff-empty-state">Loading file diff...</div>
|
|
111
111
|
</section>
|
|
112
112
|
`:t?t.tooLarge?`
|
|
113
113
|
<section class="diff-file-block">
|
|
114
114
|
<div class="diff-file-header">
|
|
115
|
-
<span class="diff-file-path">${
|
|
116
|
-
<span class="git-status-badge ${ue(t.status)}">${
|
|
115
|
+
<span class="diff-file-path">${g(t.path)}</span>
|
|
116
|
+
<span class="git-status-badge ${ue(t.status)}">${g(t.status)}</span>
|
|
117
117
|
<span class="diff-file-header-stats"><span class="diff-stats-add">+${t.stats?.additions??0}</span><span class="diff-stats-del">-${t.stats?.deletions??0}</span></span>
|
|
118
118
|
</div>
|
|
119
119
|
<div class="diff-limit-card">
|
|
@@ -125,15 +125,15 @@ ${r}`}getPreviewSource(e){let t=this.getSession()?.getText()??"";return this.isM
|
|
|
125
125
|
`:this.mode==="split"?this.renderSplitFile(t,this.currentIndex):this.renderUnifiedFile(t,this.currentIndex):`
|
|
126
126
|
<section class="diff-file-block">
|
|
127
127
|
<div class="diff-file-header">
|
|
128
|
-
<span class="diff-file-path">${
|
|
129
|
-
<span class="git-status-badge ${ue(e.status)}">${
|
|
128
|
+
<span class="diff-file-path">${g(e.path)}</span>
|
|
129
|
+
<span class="git-status-badge ${ue(e.status)}">${g(e.status)}</span>
|
|
130
130
|
</div>
|
|
131
131
|
<div class="diff-empty-state">Select a file to load its diff.</div>
|
|
132
132
|
</section>
|
|
133
133
|
`}syncToolbar(){let e=this.data?.files?.length??0,t=e===0?0:this.currentIndex+1;if(this.fileIndicator&&(this.fileIndicator.textContent=e>0?`${t} / ${e} files`:"0 / 0 files"),this.stats){let a=this.data?.summary?.additions??0,o=this.data?.summary?.deletions??0;this.stats.innerHTML=`
|
|
134
134
|
<span class="diff-stats-add">+${a}</span>
|
|
135
135
|
<span class="diff-stats-del">-${o}</span>
|
|
136
|
-
`}this.modeButtons.forEach(a=>{a.classList.toggle("active",a.getAttribute("data-diff-mode")===this.mode)});let i=!!this.getCurrentFile()?.path,s=this.getCurrentActionState(),r=this.getPrimaryAction();this.openEditorButton?.toggleAttribute("disabled",!i),this.primaryActionButton&&(this.primaryActionButton.textContent=this.pendingAction===r?"Working...":r==="unstage"?"Unstage":"Stage",this.primaryActionButton.toggleAttribute("disabled",!i||!r||!!this.pendingAction)),this.commitButton&&(this.commitButton.textContent=this.pendingAction==="commit"?"Working...":"Commit Staged"),this.commitButton?.toggleAttribute("disabled",!s.canCommit||!!this.pendingAction),this.prevButton?.toggleAttribute("disabled",this.currentIndex<=0),this.nextButton?.toggleAttribute("disabled",e===0||this.currentIndex>=e-1)}render(){if(this.page?.classList.remove("hidden"),(this.data?.files??[]).length===0){this.renderEmpty("No changes to display.");return}this.content&&(this.content.innerHTML=this.renderCurrentFile(),this.syncToolbar())}getToolbarTitle({filePath:e=null,scope:t="all"}={}){return e?
|
|
136
|
+
`}this.modeButtons.forEach(a=>{a.classList.toggle("active",a.getAttribute("data-diff-mode")===this.mode)});let i=!!this.getCurrentFile()?.path,s=this.getCurrentActionState(),r=this.getPrimaryAction();this.openEditorButton?.toggleAttribute("disabled",!i),this.primaryActionButton&&(this.primaryActionButton.textContent=this.pendingAction===r?"Working...":r==="unstage"?"Unstage":"Stage",this.primaryActionButton.toggleAttribute("disabled",!i||!r||!!this.pendingAction)),this.commitButton&&(this.commitButton.textContent=this.pendingAction==="commit"?"Working...":"Commit Staged"),this.commitButton?.toggleAttribute("disabled",!s.canCommit||!!this.pendingAction),this.prevButton?.toggleAttribute("disabled",this.currentIndex<=0),this.nextButton?.toggleAttribute("disabled",e===0||this.currentIndex>=e-1)}render(){if(this.page?.classList.remove("hidden"),(this.data?.files??[]).length===0){this.renderEmpty("No changes to display.");return}this.content&&(this.content.innerHTML=this.renderCurrentFile(),this.syncToolbar())}getToolbarTitle({filePath:e=null,scope:t="all"}={}){return e?Kn(e):t==="staged"?"Staged Changes":t==="working-tree"?"Working Tree Changes":"All Changes"}};var Yn=1e4;function Zn(n){let e=String(n??"").split("/");return e.pop(),e.join("/")}function Xn(n){return String(n??"").split("/").pop()||""}function $i(){return'<svg class="git-file-icon" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>'}function Jn(){return'<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="18" cy="18" r="3"/><circle cx="6" cy="6" r="3"/><path d="M13 6h3a2 2 0 0 1 2 2v7"/><path d="M6 9v12"/></svg>'}function Oi(n){return`<svg class="git-section-chevron${n?" collapsed":""}" width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" aria-hidden="true"><polyline points="6 9 12 15 18 9"/></svg>`}function at(n){switch(n){case"commit":return'<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5"/></svg>';case"pull":return'<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 5v14"/><path d="m18 13-6 6-6-6"/></svg>';case"push":return'<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 19V5"/><path d="m6 11 6-6 6 6"/></svg>';case"unstage":return'<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 12H8"/><path d="m12 16-4-4 4-4"/></svg>';case"reset":return'<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 12a9 9 0 1 0 3-6.7"/><path d="M3 4v5h5"/></svg>';default:return'<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 5v14"/><path d="M5 12h14"/></svg>'}}function es(n){switch(n){case"added":return"added";case"deleted":return"deleted";case"renamed":return"renamed";case"untracked":return"untracked";default:return"modified"}}function ts(n={},e={}){let t=Number(n.additions||0),i=Number(n.deletions||0);return Number(n.changedFiles||0)>0||t>0||i>0?`
|
|
137
137
|
<span class="git-change-stats" aria-label="Local diff summary">
|
|
138
138
|
<span class="git-change-add">+${t}</span>
|
|
139
139
|
<span class="git-change-del">-${i}</span>
|
|
@@ -143,93 +143,120 @@ ${r}`}getPreviewSource(e){let t=this.getSession()?.getText()??"";return this.isM
|
|
|
143
143
|
<span style="color: var(--color-success);">↑${Number(e.ahead||0)}</span>
|
|
144
144
|
<span style="color: var(--color-text-faint);">↓${Number(e.behind||0)}</span>
|
|
145
145
|
</span>
|
|
146
|
-
`:'<span class="git-sync-info git-sync-info-muted">Clean</span>'}var
|
|
146
|
+
`:'<span class="git-sync-info git-sync-info-muted">Clean</span>'}var ot=class{constructor({enabled:e=!0,onCommitStaged:t=()=>{},onOpenPullBackup:i=()=>{},onPullBranch:s=()=>{},onPushBranch:r=()=>{},onRepoChange:a=()=>{},onResetFile:o=()=>{},onSelectDiff:l=()=>{},onStageFile:h=()=>{},onUnstageFile:c=()=>{},onViewAllDiff:u=()=>{},searchInput:p=null,toastController:d=null}={}){this.enabled=e,this.onCommitStaged=t,this.onOpenPullBackup=i,this.onPullBranch=s,this.onPushBranch=r,this.onRepoChange=a,this.onResetFile=o,this.onSelectDiff=l,this.onStageFile=h,this.onUnstageFile=c,this.onViewAllDiff=u,this.searchInput=p,this.toastController=d,this.panel=document.getElementById("gitPanel"),this.pullBackups=[],this.status=null,this.active=!1,this.refreshTimer=null,this.searchQuery="",this.collapsedSections=new Set,this.selection={path:null,scope:null},this.pendingActionKey=null}initialize(){this.panel?.addEventListener("click",e=>{let t=e.target instanceof Element?e.target.closest("[data-git-section-toggle]"):null;if(t){let h=t.getAttribute("data-git-section-toggle");this.toggleSection(h);return}let i=e.target instanceof Element?e.target.closest("[data-git-path]"):null;if(i&&!e.target.closest("[data-git-file-action]")){let h=i.getAttribute("data-git-path"),c=i.getAttribute("data-git-scope")||"working-tree";if(!h)return;this.onSelectDiff(h,{scope:c});return}let s=e.target instanceof Element?e.target.closest("[data-git-pull-backup-path]"):null;if(s){let h=s.getAttribute("data-git-pull-backup-path");if(!h)return;this.onOpenPullBackup(h);return}let r=e.target instanceof Element?e.target.closest("[data-git-file-action]"):null;if(r){let h=r.getAttribute("data-git-file-action"),c=r.getAttribute("data-git-path"),u=r.getAttribute("data-git-scope")||"working-tree";if(!h||!c)return;e.preventDefault(),e.stopPropagation(),this.handleFileAction(h,c,u);return}if(e.target instanceof Element?e.target.closest("[data-git-view-all]"):null){this.onViewAllDiff();return}if(e.target instanceof Element?e.target.closest("[data-git-commit-staged]"):null){this.handleCommitStaged();return}let l=e.target instanceof Element?e.target.closest("[data-git-sync-action]"):null;if(l){let h=l.getAttribute("data-git-sync-action");(h==="pull"||h==="push")&&this.handleSyncAction(h)}}),this.searchInput?.addEventListener("input",e=>{this.searchQuery=String(e.target?.value??"").trim().toLowerCase(),this.render()})}setActive(e){let t=!!e;if(!(this.active===t&&(!t||this.refreshTimer))){if(this.active=t,!this.active){clearInterval(this.refreshTimer),this.refreshTimer=null;return}this.refresh(),this.refreshTimer||(this.refreshTimer=setInterval(()=>{this.refresh()},Yn))}}setSelection({path:e=null,scope:t=null}={}){this.selection={path:e,scope:t},this.render()}toggleSection(e){e&&(this.collapsedSections.has(e)?this.collapsedSections.delete(e):this.collapsedSections.add(e),this.render())}async refresh({force:e=!1}={}){if(!this.enabled)return this.status={isGitRepo:!1,sections:[],summary:{changedFiles:0}},this.pullBackups=[],this.onRepoChange(!1,this.status),this.render(),this.status;try{let t=await fetch(C(`/git/status${e?"?force=true":""}`)),i=await t.json();if(!t.ok)throw new Error(i.error||"Failed to load git status");if(this.status=i,this.pullBackups=[],i.isGitRepo)try{let s=await fetch(C("/git/pull-backups")),r=await s.json();if(!s.ok)throw new Error(r.error||"Failed to load pull backups");this.pullBackups=Array.isArray(r.backups)?r.backups:[]}catch(s){console.error("[git-panel] Failed to load pull backups:",s)}return this.onRepoChange(!!i.isGitRepo,i),this.render(),i}catch(t){return console.error("[git-panel] Failed to load git status:",t),this.toastController?.show("Failed to load git status"),this.status={isGitRepo:!1,sections:[],summary:{changedFiles:0}},this.pullBackups=[],this.onRepoChange(!1,this.status),this.render(),this.status}}filterFiles(e=[]){return this.searchQuery?e.filter(t=>t.path.toLowerCase().includes(this.searchQuery)||String(t.oldPath||"").toLowerCase().includes(this.searchQuery)):e}async handleFileAction(e,t,i){let s=`${e}:${i}:${t}`;if(this.pendingActionKey!==s){this.pendingActionKey=s,this.render();try{e==="stage"?await this.onStageFile(t,{scope:i}):e==="unstage"?await this.onUnstageFile(t,{scope:i}):e==="reset"&&await this.onResetFile(t,{scope:i})}finally{this.pendingActionKey=null,this.render()}}}async handleCommitStaged(){let e="commit-staged";if(this.pendingActionKey!==e){this.pendingActionKey=e,this.render();try{await this.onCommitStaged()}finally{this.pendingActionKey=null,this.render()}}}async handleSyncAction(e){let t=`sync:${e}`;if(this.pendingActionKey!==t){this.pendingActionKey=t,this.render();try{e==="pull"?await this.onPullBranch():e==="push"&&await this.onPushBranch()}finally{this.pendingActionKey=null,this.render()}}}renderSection(e){let t=this.filterFiles(e.files);if(t.length===0)return"";let i=this.collapsedSections.has(e.key);return`
|
|
147
147
|
<section class="git-section">
|
|
148
|
-
<button class="git-section-header" type="button" data-git-section-toggle="${
|
|
149
|
-
${
|
|
150
|
-
${
|
|
148
|
+
<button class="git-section-header" type="button" data-git-section-toggle="${g(e.key)}">
|
|
149
|
+
${Oi(i)}
|
|
150
|
+
${g(e.label)}
|
|
151
151
|
<span class="git-section-count">${t.length}</span>
|
|
152
152
|
</button>
|
|
153
153
|
<div class="git-file-list${i?" hidden":""}">
|
|
154
154
|
${t.map(s=>this.renderFile(s)).join("")}
|
|
155
155
|
</div>
|
|
156
156
|
</section>
|
|
157
|
-
`}
|
|
157
|
+
`}renderPullBackupsSection(){return!Array.isArray(this.pullBackups)||this.pullBackups.length===0?"":`
|
|
158
|
+
<section class="git-section">
|
|
159
|
+
<button class="git-section-header" type="button" data-git-section-toggle="pull-backups">
|
|
160
|
+
${Oi(this.collapsedSections.has("pull-backups"))}
|
|
161
|
+
Pull Backups
|
|
162
|
+
<span class="git-section-count">${this.pullBackups.length}</span>
|
|
163
|
+
</button>
|
|
164
|
+
<div class="git-file-list${this.collapsedSections.has("pull-backups")?" hidden":""}">
|
|
165
|
+
${this.pullBackups.map(e=>this.renderPullBackup(e)).join("")}
|
|
166
|
+
</div>
|
|
167
|
+
</section>
|
|
168
|
+
`}renderPullBackup(e){let t=String(e?.createdAt||"").replace("T"," ").replace(/\.\d+Z?$/u,"Z"),i=Number(e?.fileCount||0);return`
|
|
169
|
+
<div class="git-file-row">
|
|
170
|
+
<button
|
|
171
|
+
class="git-file-item"
|
|
172
|
+
type="button"
|
|
173
|
+
data-git-pull-backup-path="${g(e.summaryPath||"")}"
|
|
174
|
+
>
|
|
175
|
+
${$i()}
|
|
176
|
+
<span class="git-file-copy">
|
|
177
|
+
<span class="git-file-name">Pull backup ${g(e.id||"")}</span>
|
|
178
|
+
<span class="git-file-path">${g(`${t} \xB7 ${e.branch||"HEAD"} \xB7 ${i} file${i===1?"":"s"}`)}</span>
|
|
179
|
+
</span>
|
|
180
|
+
<span class="git-status-badge modified">BK</span>
|
|
181
|
+
</button>
|
|
182
|
+
</div>
|
|
183
|
+
`}renderFile(e){let t=this.selection.path===e.path&&this.selection.scope===e.scope,i=Zn(e.path),s=Xn(e.path),r=es(e.status),a=e.scope==="staged"?{label:"Unstage",value:"unstage"}:{label:"Stage",value:"stage"},o=`${a.value}:${e.scope}:${e.path}`,l=this.pendingActionKey===o,h=`reset:${e.scope}:${e.path}`,c=this.pendingActionKey===h;return`
|
|
158
184
|
<div class="git-file-row${t?" active":""}">
|
|
159
185
|
<button
|
|
160
186
|
class="git-file-item${t?" active":""}"
|
|
161
187
|
type="button"
|
|
162
|
-
data-git-path="${
|
|
163
|
-
data-git-scope="${
|
|
188
|
+
data-git-path="${g(e.path)}"
|
|
189
|
+
data-git-scope="${g(e.scope)}"
|
|
164
190
|
>
|
|
165
|
-
${
|
|
191
|
+
${$i()}
|
|
166
192
|
<span class="git-file-copy">
|
|
167
|
-
<span class="git-file-name">${
|
|
168
|
-
${i?`<span class="git-file-path">${
|
|
193
|
+
<span class="git-file-name">${g(s)}</span>
|
|
194
|
+
${i?`<span class="git-file-path">${g(i)}</span>`:""}
|
|
169
195
|
</span>
|
|
170
|
-
<span class="git-status-badge ${r}">${
|
|
196
|
+
<span class="git-status-badge ${r}">${g(e.code)}</span>
|
|
171
197
|
</button>
|
|
172
198
|
<div class="git-file-actions">
|
|
173
199
|
<button
|
|
174
200
|
class="git-file-action-btn"
|
|
175
201
|
type="button"
|
|
176
202
|
data-git-file-action="reset"
|
|
177
|
-
data-git-path="${
|
|
178
|
-
data-git-scope="${
|
|
179
|
-
aria-label="Reset ${
|
|
203
|
+
data-git-path="${g(e.path)}"
|
|
204
|
+
data-git-scope="${g(e.scope)}"
|
|
205
|
+
aria-label="Reset ${g(s)}"
|
|
180
206
|
title="Reset to current branch"
|
|
181
207
|
${c?"disabled":""}
|
|
182
208
|
>
|
|
183
|
-
${c?"...":
|
|
209
|
+
${c?"...":at("reset")}
|
|
184
210
|
</button>
|
|
185
211
|
<button
|
|
186
212
|
class="git-file-action-btn"
|
|
187
213
|
type="button"
|
|
188
214
|
data-git-file-action="${a.value}"
|
|
189
|
-
data-git-path="${
|
|
190
|
-
data-git-scope="${
|
|
191
|
-
aria-label="${
|
|
192
|
-
title="${
|
|
215
|
+
data-git-path="${g(e.path)}"
|
|
216
|
+
data-git-scope="${g(e.scope)}"
|
|
217
|
+
aria-label="${g(a.label)} ${g(s)}"
|
|
218
|
+
title="${g(a.label)}"
|
|
193
219
|
${l?"disabled":""}
|
|
194
220
|
>
|
|
195
|
-
${l?"...":
|
|
221
|
+
${l?"...":at(a.value)}
|
|
196
222
|
</button>
|
|
197
223
|
</div>
|
|
198
224
|
</div>
|
|
199
|
-
`}renderEmpty(e){this.panel&&(this.panel.innerHTML=`<div class="git-panel-empty">${
|
|
225
|
+
`}renderEmpty(e){this.panel&&(this.panel.innerHTML=`<div class="git-panel-empty">${g(e)}</div>`)}render(){if(!this.panel)return;if(!this.status){this.renderEmpty("Loading git status...");return}if(!this.status.isGitRepo){this.renderEmpty("Git is unavailable for this vault.");return}let e=this.status.branch??{},t=this.renderPullBackupsSection(),i=(this.status.sections??[]).map(c=>this.renderSection(c)).filter(Boolean).join(""),s=!!this.status.summary?.changedFiles,r=Number(this.status.summary?.staged||0)>0,a=this.pendingActionKey==="commit-staged",o=!!e.upstream,l=this.pendingActionKey==="sync:pull",h=this.pendingActionKey==="sync:push";this.panel.innerHTML=`
|
|
200
226
|
<div class="git-branch-bar">
|
|
201
227
|
<div class="git-branch-meta">
|
|
202
228
|
<span class="git-branch-name">
|
|
203
|
-
${
|
|
204
|
-
${
|
|
229
|
+
${Jn()}
|
|
230
|
+
${g(e.name||"HEAD")}
|
|
205
231
|
</span>
|
|
206
|
-
${
|
|
232
|
+
${ts(this.status.summary,e)}
|
|
207
233
|
</div>
|
|
208
234
|
<div class="git-branch-actions" role="group" aria-label="Remote sync actions">
|
|
209
235
|
<button
|
|
210
236
|
class="git-branch-action-btn"
|
|
211
237
|
type="button"
|
|
212
238
|
data-git-sync-action="pull"
|
|
213
|
-
title="${
|
|
239
|
+
title="${o?"Pull remote changes (fast-forward only)":"No upstream branch configured"}"
|
|
214
240
|
aria-label="Pull branch"
|
|
215
|
-
${!
|
|
241
|
+
${!o||l?"disabled":""}
|
|
216
242
|
>
|
|
217
|
-
${
|
|
243
|
+
${l?"...":`${at("pull")}<span>Pull</span>`}
|
|
218
244
|
</button>
|
|
219
245
|
<button
|
|
220
246
|
class="git-branch-action-btn"
|
|
221
247
|
type="button"
|
|
222
248
|
data-git-sync-action="push"
|
|
223
|
-
title="${
|
|
249
|
+
title="${o?"Push local commits":"No upstream branch configured"}"
|
|
224
250
|
aria-label="Push branch"
|
|
225
|
-
${!
|
|
251
|
+
${!o||h?"disabled":""}
|
|
226
252
|
>
|
|
227
|
-
${
|
|
253
|
+
${h?"...":`${at("push")}<span>Push</span>`}
|
|
228
254
|
</button>
|
|
229
255
|
</div>
|
|
230
256
|
</div>
|
|
231
|
-
${t
|
|
232
|
-
${i
|
|
257
|
+
${t}
|
|
258
|
+
${i||'<div class="git-panel-empty">No local changes</div>'}
|
|
259
|
+
${s?`
|
|
233
260
|
<div class="git-panel-footer">
|
|
234
261
|
<div class="git-panel-footer-actions">
|
|
235
262
|
<button class="git-view-all-btn" type="button" data-git-view-all>
|
|
@@ -240,14 +267,14 @@ ${r}`}getPreviewSource(e){let t=this.getSession()?.getText()??"";return this.isM
|
|
|
240
267
|
class="git-footer-commit-btn"
|
|
241
268
|
type="button"
|
|
242
269
|
data-git-commit-staged
|
|
243
|
-
${!
|
|
270
|
+
${!r||a?"disabled":""}
|
|
244
271
|
>
|
|
245
|
-
${
|
|
272
|
+
${a?"Working...":"Commit Staged"}
|
|
246
273
|
</button>
|
|
247
274
|
</div>
|
|
248
275
|
</div>
|
|
249
276
|
`:""}
|
|
250
|
-
`}};var tt=class{constructor({mobileBreakpointQuery:e=window.matchMedia("(max-width: 768px)"),onMeasureEditor:t}){this.mobileBreakpointQuery=e,this.onMeasureEditor=t,this.preferredView="split",this.mobileShowsEditor=!this.isMobileViewport(),this.currentView=this.mobileShowsEditor?this.preferredView:"preview",this.editorLayout=document.getElementById("editorLayout"),this.editorPane=document.getElementById("editorPane"),this.previewPane=document.getElementById("previewPane"),this.mobileToggleButton=document.getElementById("mobileViewToggle"),this.resizer=document.getElementById("resizer"),this.viewButtons=Array.from(document.querySelectorAll(".view-btn"))}isMobileViewport(){return this.mobileBreakpointQuery.matches}initialize(){this.viewButtons.forEach(e=>{e.addEventListener("click",()=>this.setView(e.dataset.view))}),this.mobileToggleButton?.addEventListener("click",()=>this.toggleMobileView()),this.initializeResizer(),this.restorePreferredView()}reset(){this.restorePreferredView(),this.editorPane&&(this.editorPane.style.flex=""),this.previewPane&&(this.previewPane.style.flex=""),this.updateResizerValue()}restorePreferredView(){let e=this.isMobileViewport()?this.mobileShowsEditor?"split":"preview":this.preferredView;this.applyView(e),this.updateMobileToggleButton(this.mobileShowsEditor?"Preview":"Editor")}applyView(e){this.currentView=e,this.editorLayout?.setAttribute("data-view",e),this.syncViewButtons()}setView(e,{persist:t=!0}={}){e&&(t&&(this.preferredView=e),this.applyView(e),(e==="split"||e==="editor")&&this.scheduleEditorMeasure())}toggleMobileView(){this.mobileShowsEditor=!this.mobileShowsEditor,this.applyView(this.mobileShowsEditor?"split":"preview"),this.updateMobileToggleButton(this.mobileShowsEditor?"Preview":"Editor"),this.mobileShowsEditor&&this.scheduleEditorMeasure()}scheduleEditorMeasure(){this.onMeasureEditor&&setTimeout(()=>this.onMeasureEditor(),50)}updateMobileToggleButton(e){if(!this.mobileToggleButton)return;let t='<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>',i='<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="18" height="18" rx="2"/><line x1="8" y1="8" x2="16" y2="8"/><line x1="8" y1="12" x2="14" y2="12"/><line x1="8" y1="16" x2="12" y2="16"/></svg>';this.mobileToggleButton.innerHTML=`${e==="Editor"?i:t}<span class="toolbar-btn-label">${e}</span>`}syncViewButtons(){this.viewButtons.forEach(e=>{let t=e.dataset.view===this.currentView;e.classList.toggle("active",t),e.setAttribute("aria-pressed",String(t))})}updateResizerValue(){if(!this.resizer||!this.editorLayout||!this.editorPane)return;let e=this.editorLayout.offsetWidth;if(!Number.isFinite(e)||e<=0)return;let t=Math.round(this.editorPane.offsetWidth/e*100);this.resizer.setAttribute("aria-valuenow",String(Math.max(20,Math.min(80,t))))}applyEditorPaneWidth(e){if(!this.editorLayout||!this.editorPane||!this.previewPane)return;let t=this.editorLayout.offsetWidth;if(!Number.isFinite(t)||t<=0)return;let i=200,r=Math.max(i,Math.min(t-i,e))/t*100;this.editorPane.style.flex=`0 0 ${r}%`,this.previewPane.style.flex="1",this.updateResizerValue()}initializeResizer(){if(!this.resizer||!this.editorLayout||!this.editorPane||!this.previewPane)return;let e=!1,t=0,i=0;this.resizer.addEventListener("mousedown",s=>{e=!0,t=s.clientX,i=this.editorPane.offsetWidth,this.resizer.classList.add("dragging"),document.body.style.cursor="col-resize",document.body.style.userSelect="none",s.preventDefault()}),document.addEventListener("mousemove",s=>{if(!e)return;let r=s.clientX-t;this.applyEditorPaneWidth(i+r)}),document.addEventListener("mouseup",()=>{e&&(e=!1,this.resizer.classList.remove("dragging"),document.body.style.cursor="",document.body.style.userSelect="",this.scheduleEditorMeasure())}),this.resizer.addEventListener("keydown",s=>{let r=this.editorLayout.offsetWidth;if(!Number.isFinite(r)||r<=0)return;let a=Math.max(24,Math.round(r*.05));if(s.key==="ArrowLeft"){s.preventDefault(),this.applyEditorPaneWidth(this.editorPane.offsetWidth-a),this.scheduleEditorMeasure();return}if(s.key==="ArrowRight"){s.preventDefault(),this.applyEditorPaneWidth(this.editorPane.offsetWidth+a),this.scheduleEditorMeasure();return}if(s.key==="Home"){s.preventDefault(),this.applyEditorPaneWidth(r*.2),this.scheduleEditorMeasure();return}s.key==="End"&&(s.preventDefault(),this.applyEditorPaneWidth(r*.8),this.scheduleEditorMeasure())}),this.updateResizerValue()}};var it=class{constructor({mobileBreakpointQuery:e=window.matchMedia("(max-width: 768px)"),onNavigateToHeading:t}={}){this.outlineOpen=!1,this.activeHeadingFrame=null,this.activeHeadingId=null,this.headings=[],this.pinnedHeadingId=null,this.onNavigateToHeading=t,this.panel=document.getElementById("outlinePanel"),this.navigation=document.getElementById("outlineNav"),this.previewContainer=document.getElementById("previewContainer"),this.toggleButton=document.getElementById("outlineToggle"),this.mobileBreakpointQuery=e,this.handlePreviewScroll=()=>this.scheduleActiveHeadingUpdate()}initialize(){this.toggleButton?.addEventListener("click",()=>this.toggle())}toggle(){this.setOpenState(!this.outlineOpen)}close(){this.setOpenState(!1)}setOpenState(e){if(this.outlineOpen=e,this.panel?.classList.toggle("hidden",!this.outlineOpen),this.toggleButton?.classList.toggle("active",this.outlineOpen),this.outlineOpen){this.refresh();return}this.cleanup()}refresh(){if(!this.navigation)return;if(!this.outlineOpen){this.cleanup();return}let t=document.getElementById("previewContent")?.querySelectorAll("h1, h2, h3, h4, h5, h6")??[];if(t.length===0){this.navigation.innerHTML='<div class="outline-empty">No headings found</div>',this.cleanup();return}let i=Array.from(t).map((s,r)=>(s.id||(s.id=`heading-${r}-${s.textContent.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"").slice(0,40)}`),{id:s.id,level:Number.parseInt(s.tagName[1],10),sourceLine:Number.parseInt(s.getAttribute("data-source-line")||"",10),text:s.textContent.trim()}));this.navigation.innerHTML=i.map(s=>`<button class="outline-item" data-level="${s.level}" data-target="${s.id}"${Number.isFinite(s.sourceLine)?` data-source-line="${s.sourceLine}"`:""} title="${s.text.replace(/"/g,""")}">${s.text}</button>`).join(""),this.navigation.querySelectorAll(".outline-item").forEach(s=>{s.addEventListener("click",()=>{let r=document.getElementById(s.dataset.target);this.pinnedHeadingId=s.dataset.target,this.notifyHeadingNavigation(r,s.dataset.target),this.scrollHeadingIntoView(r,{behavior:"auto"}),this.setActiveItem(s.dataset.target,{behavior:"auto"}),this.mobileBreakpointQuery.matches&&this.close()})}),this.observeHeadings(Array.from(t))}cleanup(){this.activeHeadingFrame&&(cancelAnimationFrame(this.activeHeadingFrame),this.activeHeadingFrame=null),this.previewContainer?.removeEventListener("scroll",this.handlePreviewScroll),this.headings=[],this.pinnedHeadingId=null}setActiveItem(e,{scrollIntoView:t=!0,behavior:i="smooth"}={}){this.activeHeadingId=e,this.navigation?.querySelectorAll(".outline-item").forEach(s=>{s.classList.toggle("active",s.dataset.target===e)}),t&&this.navigation?.querySelector(".outline-item.active")?.scrollIntoView({behavior:i,block:"nearest"})}observeHeadings(e){this.cleanup(),!(!this.previewContainer||e.length===0)&&(this.headings=e,this.previewContainer.addEventListener("scroll",this.handlePreviewScroll,{passive:!0}),this.updateActiveHeading())}scheduleActiveHeadingUpdate(){this.activeHeadingFrame||(this.activeHeadingFrame=requestAnimationFrame(()=>{this.activeHeadingFrame=null,this.updateActiveHeading()}))}updateActiveHeading(){if(!this.previewContainer||this.headings.length===0)return;let e=this.getPinnedHeading();if(e&&this.shouldKeepPinnedHeadingActive(e)){this.setActiveItem(e.id,{behavior:"auto",scrollIntoView:!0});return}this.pinnedHeadingId=null;let t=this.previewContainer.scrollTop,i=this.headings[0];for(let s of this.headings){if(this.getHeadingScrollTop(s)>t)break;i=s}this.setActiveItem(i.id,{behavior:"auto",scrollIntoView:!0})}getHeadingScrollTop(e){if(!this.previewContainer)return 0;let t=this.previewContainer.getBoundingClientRect(),i=e.getBoundingClientRect();return this.previewContainer.scrollTop+(i.top-t.top)}getPinnedHeading(){return this.pinnedHeadingId?this.headings.find(e=>e.id===this.pinnedHeadingId)??null:null}shouldKeepPinnedHeadingActive(e){if(!this.previewContainer||!e?.isConnected)return!1;let t=this.getHeadingScrollTop(e)-this.previewContainer.scrollTop,i=t+e.getBoundingClientRect().height,s=this.previewContainer.clientHeight*.45;return i>-48&&t<s}notifyHeadingNavigation(e,t){if(!e)return;let i=Number.parseInt(e.getAttribute("data-source-line")||"",10);this.onNavigateToHeading?.({headingId:t,sourceLine:Number.isFinite(i)?i:null})}scrollHeadingIntoView(e,{behavior:t="smooth"}={}){if(!e||!this.previewContainer)return;let i=this.previewContainer.getBoundingClientRect(),s=e.getBoundingClientRect(),r=this.previewContainer.scrollTop+(s.top-i.top);this.previewContainer.scrollTo({behavior:t,top:Math.max(r,0)})}};var Ai=.35,Bn=120,Nn=12,Hn=2;function nt(n){return Math.max(n.scrollHeight-n.clientHeight,0)}function Dn(n){return Math.max(n,0)}function Ii(n){return Math.max(n.clientHeight*Ai,Nn)}function _n(n){return(n?.scrollTop??0)<=Hn}function zn(n,e){let t=n.getBoundingClientRect();return e.getBoundingClientRect().top-t.top+n.scrollTop}function Un(n){return!n.querySelector("[data-source-line]")}function $n(n){return typeof window.requestIdleCallback=="function"?window.requestIdleCallback(n,{timeout:500}):window.setTimeout(()=>{n({didTimeout:!1,timeRemaining:()=>0})},1)}function Ti(n){if(n!==null){if(typeof window.cancelIdleCallback=="function"){window.cancelIdleCallback(n);return}window.clearTimeout(n)}}var st=class{constructor({getEditorLineNumber:e,onEditorScrollActivityChange:t,previewContainer:i,previewElement:s,scrollEditorToLine:r}){this.getEditorLineNumber=e,this.onEditorScrollActivityChange=t,this.previewContainer=i,this.previewElement=s,this.scrollEditorToLine=r,this.editorScroller=null,this.editorScrollActive=!1,this.editorScrollIdleTimer=null,this.lockedElements=new Set,this.pendingSync=null,this.frameId=null,this.previewBlocks=null,this.previewBlocksWarmId=null,this.previewBlocksReadyCallbacks=[],this.largeDocumentMode=!1,this.lastInteractionSource="editor",this.suspendedUntil=0,this.handleEditorScroll=()=>{if(!(!this.editorScroller||this.lockedElements.has(this.editorScroller)||this.isSuspended())){if(this.lastInteractionSource="editor",this.largeDocumentMode){this.setEditorScrollActive(!0),this.scheduleEditorScrollIdle(),this.scheduleSync(this.editorScroller,this.previewContainer,{preferApproximateMapping:!0});return}this.scheduleSync(this.editorScroller,this.previewContainer)}},this.handlePreviewScroll=()=>{!this.previewContainer||this.lockedElements.has(this.previewContainer)||this.isSuspended()||(this.lastInteractionSource="preview",this.scheduleSync(this.previewContainer,this.editorScroller))}}initialize(){this.previewContainer?.addEventListener("scroll",this.handlePreviewScroll,{passive:!0})}attachEditorScroller(e){this.editorScroller!==e&&(this.editorScroller?.removeEventListener("scroll",this.handleEditorScroll),this.editorScroller=e,this.editorScroller?.addEventListener("scroll",this.handleEditorScroll,{passive:!0}))}syncPreviewToEditor(){this.lastInteractionSource="editor",this.sync(this.editorScroller,this.previewContainer)}syncEditorToPreview(){this.lastInteractionSource="preview",this.sync(this.previewContainer,this.editorScroller)}destroy(){this.previewContainer?.removeEventListener("scroll",this.handlePreviewScroll),this.editorScroller?.removeEventListener("scroll",this.handleEditorScroll),this.editorScroller=null,clearTimeout(this.editorScrollIdleTimer),this.editorScrollIdleTimer=null,this.pendingSync=null,this.previewBlocks=null,Ti(this.previewBlocksWarmId),this.previewBlocksWarmId=null,this.previewBlocksReadyCallbacks=[],this.lockedElements.clear(),this.editorScrollActive=!1,this.lastInteractionSource="editor",this.suspendedUntil=0,this.frameId&&(cancelAnimationFrame(this.frameId),this.frameId=null)}scheduleSync(e,t,{preferApproximateMapping:i=!1}={}){!e||!t||this.lockedElements.has(e)||this.isSuspended()||(this.pendingSync={preferApproximateMapping:i,source:e,target:t},!this.frameId&&(this.frameId=requestAnimationFrame(()=>{if(this.frameId=null,!this.pendingSync)return;let{preferApproximateMapping:s,source:r,target:a}=this.pendingSync;this.pendingSync=null,this.sync(r,a,{preferApproximateMapping:s})})))}invalidatePreviewBlocks(){this.previewBlocks=null,Ti(this.previewBlocksWarmId),this.previewBlocksWarmId=null,this.previewBlocksReadyCallbacks=[]}setLargeDocumentMode(e){this.largeDocumentMode=!!e,this.largeDocumentMode||(clearTimeout(this.editorScrollIdleTimer),this.editorScrollIdleTimer=null,this.setEditorScrollActive(!1))}warmPreviewBlocks({onReady:e}={}){if(typeof e=="function"&&(this.previewBlocks?e(this.previewBlocks):this.previewBlocksReadyCallbacks.push(e)),!this.largeDocumentMode){this.previewBlocks||(this.previewBlocks=this.buildPreviewBlocks()),this.flushPreviewBlocksReadyCallbacks();return}this.previewBlocks||this.previewBlocksWarmId!==null||(this.previewBlocksWarmId=$n(()=>{this.previewBlocksWarmId=null,this.previewBlocks=this.buildPreviewBlocks(),this.flushPreviewBlocksReadyCallbacks()}))}realignAfterLayoutChange(){let e=()=>{if(this.lastInteractionSource==="preview"){this.syncEditorToPreview();return}this.syncPreviewToEditor()};if(this.largeDocumentMode&&!this.previewBlocks){this.warmPreviewBlocks({onReady:()=>e()});return}e()}suspendSync(e=250){this.suspendedUntil=performance.now()+e}isSuspended(){return performance.now()<this.suspendedUntil}flushPreviewBlocksReadyCallbacks(){if(this.previewBlocksReadyCallbacks.length===0)return;this.previewBlocksReadyCallbacks.splice(0).forEach(t=>{try{t(this.previewBlocks??[])}catch(i){console.warn("[scroll-sync] Preview block callback failed:",i)}})}setEditorScrollActive(e){this.editorScrollActive!==e&&(this.editorScrollActive=e,this.onEditorScrollActivityChange?.(e))}scheduleEditorScrollIdle(){clearTimeout(this.editorScrollIdleTimer),this.editorScrollIdleTimer=setTimeout(()=>{this.editorScrollIdleTimer=null,this.setEditorScrollActive(!1),this.syncPreviewToEditor()},Bn)}sync(e,t,{preferApproximateMapping:i=!1}={}){if(!e||!t||this.lockedElements.has(e)||this.isSuspended())return;if(!i&&e===this.editorScroller&&t===this.previewContainer){let l=this.getPreviewScrollTopForEditorLine();if(l!==null){this.setScrollTop(t,l);return}}if(e===this.previewContainer&&t===this.editorScroller){let l=this.getEditorLineNumberForPreviewScroll();if(l!==null){this.lockedElements.add(t),this.scrollEditorToLine?.(l,Ai),requestAnimationFrame(()=>{this.lockedElements.delete(t)});return}}let s=nt(e),r=nt(t),a=s>0?e.scrollTop/s:0,o=r>0?r*a:0;this.setScrollTop(t,o)}setScrollTop(e,t){this.lockedElements.add(e),e.scrollTop=Dn(t),requestAnimationFrame(()=>{this.lockedElements.delete(e)})}getPreviewScrollTopForEditorLine(){if(_n(this.editorScroller))return 0;let e=this.getEditorLineNumber?.();if(!Number.isFinite(e))return null;let t=this.getPreviewBlocks();if(t.length===0||!this.previewContainer)return null;let{block:i,index:s}=this.findBlockForLine(t,e),r=this.getPreviewSpan(t,s),a=Math.max(i.end-i.start,1),o=F((e-i.start)/a,0,1),l=nt(this.previewContainer),h=Ii(this.previewContainer);return F(i.top+r*o-h,0,l)}getEditorLineNumberForPreviewScroll(){if(!this.previewContainer)return null;let e=this.getPreviewBlocks();if(e.length===0)return null;let t=this.previewContainer.scrollTop+Ii(this.previewContainer),{block:i,index:s}=this.findBlockForScrollTop(e,t),r=this.getPreviewSpan(e,s),a=Math.max(i.end-i.start,1),o=r>0?F((t-i.top)/r,0,1):0;return Math.round(i.start+a*o)}getPreviewBlocks(){return this.previewBlocks?this.previewBlocks:!this.previewContainer||!this.previewElement?[]:this.largeDocumentMode?[]:(this.previewBlocks=this.buildPreviewBlocks(),this.previewBlocks)}buildPreviewBlocks(){let e=Array.from(this.previewElement.querySelectorAll("[data-source-line]")).map(s=>{let r=Number.parseInt(s.getAttribute("data-source-line")||"",10),a=Number.parseInt(s.getAttribute("data-source-line-end")||"",10);return Number.isFinite(r)?{element:s,end:Number.isFinite(a)?Math.max(a,r+1):r+1,start:r,top:zn(this.previewContainer,s)}:null}).filter(Boolean).sort((s,r)=>s.top-r.top||s.start-r.start||s.end-r.end),t=e.filter(s=>Un(s.element)),i=t.length>0?t:e;return i.filter((s,r)=>{let a=i[r-1];return!a||Math.abs(a.top-s.top)>1||a.start!==s.start||a.end!==s.end})}findBlockForLine(e,t){let i=null,s=-1;for(let a=0;a<e.length;a+=1){let o=e[a];if(t>=o.start&&t<o.end){if(!i){i=o,s=a;continue}let l=i.end-i.start,h=o.end-o.start;(h<l||h===l&&o.start>=i.start)&&(i=o,s=a)}}if(i)return{block:i,index:s};let r=0;for(let a=0;a<e.length&&!(e[a].start>t);a+=1)r=a;return{block:e[r],index:r}}findBlockForScrollTop(e,t){for(let s=0;s<e.length;s+=1){let r=this.getPreviewSpan(e,s)+e[s].top;if(t<r)return{block:e[s],index:s}}let i=e.length-1;return{block:e[i],index:i}}getPreviewSpan(e,t){if(!this.previewContainer)return 1;let i=e[t],s=e[t+1],r=i.element.getBoundingClientRect().height;if(!s){let a=nt(this.previewContainer);return Math.max(a-i.top+this.previewContainer.clientHeight,r,1)}return Math.max(s.top-i.top,r,1)}};var On='<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="5"/><path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/></svg>',qn='<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg>',rt=class{constructor({storageKey:e="collabmd-theme",onChange:t}){this.storageKey=e,this.onChange=t,this.currentTheme="dark"}initialize(){this.currentTheme=this.readPreferredTheme(),this.applyTheme(),document.querySelectorAll("[data-theme-toggle]").forEach(e=>{e.addEventListener("click",()=>this.toggle())})}getTheme(){return this.currentTheme}toggle(){this.currentTheme=this.currentTheme==="dark"?"light":"dark",this.persistTheme(),this.applyTheme()}readPreferredTheme(){try{let e=window.localStorage.getItem(this.storageKey);if(e==="light"||e==="dark")return e}catch{}return window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"}persistTheme(){try{window.localStorage.setItem(this.storageKey,this.currentTheme)}catch{}}applyTheme(){document.documentElement.setAttribute("data-theme",this.currentTheme),this.updateToggleIcons(),this.onChange?.(this.currentTheme)}updateToggleIcons(){let e=this.currentTheme==="dark"?On:qn;document.querySelectorAll("[data-theme-toggle]").forEach(t=>{t.innerHTML=e})}};var me=class{constructor(e){this.container=e}show(e,t=3e3){if(!this.container)return;let i=document.createElement("div");i.className="toast",i.textContent=e,this.container.appendChild(i),setTimeout(()=>{i.classList.add("leaving"),i.addEventListener("animationend",()=>i.remove(),{once:!0})},t)}};var Mi=16/9,Wn=240,Vn=720,Kn=180;function Gn(n){return Math.max(Kn,Math.min(Vn,Math.ceil(n||Wn)))}var at=class{constructor({previewElement:e}){this.previewElement=e,this.embedEntries=new Map,this.overlayRoot=null}destroy(){this.embedEntries.forEach(e=>{e.hydrateFrameId&&(cancelAnimationFrame(e.hydrateFrameId),e.hydrateFrameId=null),e.wrapper?.remove(),e.placeholder=null}),this.embedEntries.clear(),this.overlayRoot?.remove(),this.overlayRoot=null}detachForCommit(){this.embedEntries.forEach(e=>{e.placeholder=null})}reconcileEmbeds(e=this.previewElement){if(this.previewElement=e,!e)return;let t=Array.from(e.querySelectorAll(".video-embed-placeholder[data-video-embed-key]")).map(r=>({filePath:r.dataset.videoEmbedSource,key:r.dataset.videoEmbedKey,label:r.dataset.videoEmbedLabel||"Embedded video",placeholder:r,source:r.dataset.videoEmbedSource||"",kind:r.dataset.videoEmbedKind||"",url:r.dataset.videoEmbedUrl||"",mimeType:r.dataset.videoEmbedMimeType||""})),{nextEntries:i,removedEntries:s}=Ve(this.embedEntries,t);s.forEach(r=>this._destroyEntry(r)),this.embedEntries=i,this.embedEntries.forEach(r=>{r.aspectRatio=r.aspectRatio||Mi,r.kind=r.placeholder?.dataset.videoEmbedKind||r.kind,r.label=r.placeholder?.dataset.videoEmbedLabel||r.label,r.mimeType=r.placeholder?.dataset.videoEmbedMimeType||r.mimeType,r.source=r.placeholder?.dataset.videoEmbedSource||r.source,r.url=r.placeholder?.dataset.videoEmbedUrl||r.url,r.wrapper||this._createEmbed(r),this._attachWrapper(r)}),this.syncLayout(),this.embedEntries.size===0&&(this.overlayRoot?.remove(),this.overlayRoot=null)}syncLayout(){this.embedEntries.forEach(e=>{e.wrapper&&this._syncEntryLayout(e)})}_destroyEntry(e){e.hydrateFrameId&&(cancelAnimationFrame(e.hydrateFrameId),e.hydrateFrameId=null),e.wrapper?.remove(),e.placeholder=null}_createEmbed(e){let t=document.createElement("div");if(t.className=`video-embed video-embed-shell diagram-preview-shell is-${e.kind}`,e.kind==="youtube"){let i=document.createElement("div");i.className="video-embed-frame video-embed-frame-youtube";let s=document.createElement("iframe");s.className="video-embed-iframe",s.title=e.label||"Embedded YouTube video",s.referrerPolicy="strict-origin-when-cross-origin",s.allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share",s.allowFullscreen=!0,i.appendChild(s),t.appendChild(i),e.mediaElement=s}else{let i=document.createElement("video");i.className="video-embed-player",i.controls=!0,i.preload="metadata",i.playsInline=!0,e.label&&(i.title=e.label,i.setAttribute("aria-label",e.label));let s=document.createElement("source");s.src=e.url,e.mimeType&&(s.type=e.mimeType),i.appendChild(s),i.addEventListener("loadedmetadata",()=>{Number.isFinite(i.videoWidth)&&Number.isFinite(i.videoHeight)&&i.videoWidth>0&&i.videoHeight>0&&(e.aspectRatio=i.videoWidth/i.videoHeight,this._syncEntryLayout(e))}),t.appendChild(i),e.mediaElement=i}e.wrapper=t}_attachWrapper(e){let t=e.placeholder?.isConnected?e.placeholder:this.previewElement?.querySelector(`.video-embed-placeholder[data-video-embed-key="${e.key}"]`);if(!t)return;e.placeholder=t,t.classList.add("is-hydrated"),t.dataset.videoEmbedHydrated="true",t.style.pointerEvents="none";let i=this._ensureOverlayRoot();e.wrapper?.parentElement!==i&&i.appendChild(e.wrapper)}_syncEntryLayout(e){let t=e.placeholder?.isConnected?e.placeholder:this.previewElement?.querySelector(`.video-embed-placeholder[data-video-embed-key="${e.key}"]`);if(!t||!e.wrapper)return;e.placeholder=t;let i=t.offsetWidth||t.clientWidth||0;if(i<=0&&e.inlineHeightPx)return;let s=Gn(i>0?i/(e.aspectRatio||Mi):e.inlineHeightPx);e.inlineHeightPx=s,Q(t,"height",`${s}px`),Q(e.wrapper,"position","absolute"),Q(e.wrapper,"top",`${t.offsetTop}px`),Q(e.wrapper,"left",`${t.offsetLeft}px`),Q(e.wrapper,"width",`${t.offsetWidth}px`),Q(e.wrapper,"height",`${s}px`),Q(e.wrapper,"margin","0"),Q(e.wrapper,"pointerEvents","auto"),this._hydrateEntryMedia(e)}_ensureOverlayRoot(){let e=this.previewElement?.querySelector('[data-video-overlay-root="true"]');return e||(e=document.createElement("div"),e.dataset.videoOverlayRoot="true",e.className="video-embed-overlay-root",this.previewElement?.appendChild(e)),this.overlayRoot=e,e}_hydrateEntryMedia(e){if(e.kind!=="youtube")return;let t=e.mediaElement;t instanceof HTMLIFrameElement&&(!e.url||t.getAttribute("src")===e.url||e.wrapper?.offsetWidth<=0||e.wrapper?.offsetHeight<=0||e.hydrateFrameId||(e.hydrateFrameId=requestAnimationFrame(()=>{if(e.hydrateFrameId=null,!e.url||t.getAttribute("src")===e.url)return;let i=Math.round(e.wrapper?.offsetWidth||0),s=Math.round(e.wrapper?.offsetHeight||0);i<=0||s<=0||(t.width=String(i),t.height=String(s),t.src=e.url)})))}};function Q(n,e,t){!n||n.style[e]===t||(n.style[e]=t)}function jn(n){let e=Number(n);return Number.isFinite(e)?Math.min(6,Math.max(1,Math.round(e*100)/100)):1}function Ri(n,{contentSize:e=0,scale:t=1,viewportSize:i=0}={}){let s=Number(n),r=Number(e),a=Number(t),o=Number(i);if(!Number.isFinite(s)||!Number.isFinite(r)||!Number.isFinite(a)||!Number.isFinite(o))return 0;let l=(r*a-o)/2;return l<=0?0:Math.min(Math.max(s,-l),l)}var ot=class{constructor({previewElement:e,documentRef:t=document,windowRef:i=window}){this.previewElement=e,this.document=t,this.window=i,this.overlayRoot=null,this.viewport=null,this.imageElement=null,this.zoomLabel=null,this.titleElement=null,this.isOpen=!1,this.scale=1,this.offsetX=0,this.offsetY=0,this.activePointerId=null,this.dragStartX=0,this.dragStartY=0,this.dragOriginX=0,this.dragOriginY=0,this.didDrag=!1,this.resetButton=null,this.handlePreviewClick=s=>{let r=s.target;if(!(r instanceof this.window.Element))return;let a=r.closest("img");!a||!this.previewElement?.contains(a)||a.closest('[data-video-overlay-root="true"], [data-excalidraw-overlay-root="true"]')||(s.preventDefault(),s.stopImmediatePropagation?.(),this.openFromImage(a))},this.handleKeyDown=s=>{if(this.isOpen){if(s.key==="Escape"){s.preventDefault(),this.close();return}if(s.key==="+"||s.key==="="){s.preventDefault(),this.zoomBy(.25);return}if(s.key==="-"){s.preventDefault(),this.zoomBy(-.25);return}s.key==="0"&&(s.preventDefault(),this.resetView())}},this.handleWindowResize=()=>{this.isOpen&&(this.clampOffsets(),this.syncTransform())},this.previewElement?.addEventListener("click",this.handlePreviewClick),this.document.addEventListener("keydown",this.handleKeyDown),this.window.addEventListener("resize",this.handleWindowResize)}destroy(){this.previewElement?.removeEventListener("click",this.handlePreviewClick),this.document.removeEventListener("keydown",this.handleKeyDown),this.window.removeEventListener("resize",this.handleWindowResize),this.close(),this.overlayRoot?.remove(),this.overlayRoot=null,this.viewport=null,this.imageElement=null,this.zoomLabel=null,this.titleElement=null,this.resetButton=null}openFromImage(e){let t=e?.currentSrc||e?.getAttribute?.("src")||"";return t?(this.ensureOverlayRoot(),this.resetView(),this.titleElement.textContent=e.getAttribute("alt")||"Image preview",this.imageElement.src=t,this.imageElement.alt=e.getAttribute("alt")||"",this.overlayRoot.hidden=!1,this.isOpen=!0,this.document.body.classList.add("image-lightbox-open"),this.syncTransform(),this.overlayRoot.focus?.(),!0):!1}close(){!this.isOpen&&!this.overlayRoot||(this.activePointerId=null,this.didDrag=!1,this.viewport?.classList?.remove("is-dragging"),this.overlayRoot&&(this.overlayRoot.hidden=!0),this.isOpen=!1,this.document.body.classList.remove("image-lightbox-open"))}resetView(){this.scale=1,this.offsetX=0,this.offsetY=0,this.syncTransform()}zoomBy(e){this.setScale(this.scale+e)}setScale(e){this.scale=jn(e),this.clampOffsets(),this.syncTransform()}clampOffsets(){if(!this.viewport||!this.imageElement){this.offsetX=0,this.offsetY=0;return}this.offsetX=Ri(this.offsetX,{contentSize:this.imageElement.offsetWidth||0,scale:this.scale,viewportSize:this.viewport.clientWidth||0}),this.offsetY=Ri(this.offsetY,{contentSize:this.imageElement.offsetHeight||0,scale:this.scale,viewportSize:this.viewport.clientHeight||0})}syncTransform(){this.imageElement&&(this.imageElement.style.transform=`translate3d(${this.offsetX}px, ${this.offsetY}px, 0) scale(${this.scale})`,this.imageElement.style.cursor=this.scale>1?"grab":"zoom-in",this.zoomLabel&&(this.zoomLabel.textContent=`${Math.round(this.scale*100)}%`),this.resetButton&&(this.resetButton.disabled=this.scale<=1&&this.offsetX===0&&this.offsetY===0))}ensureOverlayRoot(){if(this.overlayRoot?.isConnected&&this.overlayRoot.parentElement===this.document.body)return this.overlayRoot;let e=this.document.createElement("div");e.className="image-lightbox-root",e.dataset.imageLightboxRoot="true",e.hidden=!0,e.tabIndex=-1;let t=this.document.createElement("button");t.className="image-lightbox-backdrop",t.type="button",t.setAttribute("aria-label","Close image preview"),t.addEventListener("click",d=>{d.preventDefault(),d.stopPropagation(),this.close()});let i=this.document.createElement("div");i.className="image-lightbox-shell",i.setAttribute("role","dialog"),i.setAttribute("aria-modal","true"),i.setAttribute("aria-label","Image preview"),i.addEventListener("click",d=>d.stopPropagation()),i.addEventListener("pointerdown",d=>d.stopPropagation());let s=this.document.createElement("div");s.className="image-lightbox-toolbar";let r=this.document.createElement("div");r.className="image-lightbox-title",r.textContent="Image preview";let a=this.document.createElement("div");a.className="image-lightbox-controls";let o=this.document.createElement("span");o.className="image-lightbox-zoom-label",o.textContent="100%";let l=this.createControlButton("Reset","Reset zoom and position",()=>this.resetView()),h=this.createControlButton("Close","Close image preview",()=>this.close());a.append(o,l,h),s.append(r,a);let c=this.document.createElement("div");c.className="image-lightbox-viewport";let u=this.document.createElement("img");u.className="image-lightbox-image",u.alt="",u.addEventListener("load",()=>{this.clampOffsets(),this.syncTransform()}),c.addEventListener("wheel",d=>{this.isOpen&&(d.preventDefault(),this.zoomBy(d.deltaY<0?.25:-.25))},{passive:!1}),c.addEventListener("pointerdown",d=>{!this.isOpen||this.scale<=1||d.button!==0||(this.activePointerId=d.pointerId,this.dragStartX=d.clientX,this.dragStartY=d.clientY,this.dragOriginX=this.offsetX,this.dragOriginY=this.offsetY,this.didDrag=!1,c.classList.add("is-dragging"),c.setPointerCapture?.(d.pointerId),d.preventDefault())}),c.addEventListener("pointermove",d=>{!this.isOpen||this.activePointerId!==d.pointerId||(!this.didDrag&&(Math.abs(d.clientX-this.dragStartX)>=6||Math.abs(d.clientY-this.dragStartY)>=6)&&(this.didDrag=!0),this.offsetX=this.dragOriginX+(d.clientX-this.dragStartX),this.offsetY=this.dragOriginY+(d.clientY-this.dragStartY),this.clampOffsets(),this.syncTransform())});let f=d=>{this.activePointerId===d.pointerId&&(this.activePointerId=null,c.classList.remove("is-dragging"),c.releasePointerCapture?.(d.pointerId),this.imageElement.style.cursor=this.scale>1?"grab":"zoom-in")};return c.addEventListener("pointerup",f),c.addEventListener("pointercancel",f),u.addEventListener("click",d=>{if(this.isOpen){if(d.preventDefault(),d.stopPropagation(),this.didDrag){this.didDrag=!1;return}this.scale<=1&&this.setScale(2)}}),c.appendChild(u),i.append(s,c),e.append(t,i),this.document.body.appendChild(e),this.overlayRoot=e,this.viewport=c,this.imageElement=u,this.zoomLabel=o,this.titleElement=r,this.resetButton=l,this.syncTransform(),e}createControlButton(e,t,i,{className:s=""}={}){let r=this.document.createElement("button");return r.className=`image-lightbox-btn ${s}`.trim(),r.type="button",r.setAttribute("aria-label",t),r.textContent=e,r.addEventListener("click",a=>{a.preventDefault(),a.stopPropagation(),i(a)}),r}};var Qn=Object.freeze({chat:ti,comments:ii,git:si,presence:ri,ui:ai,workspace:oi});function Zn(n){let e={};Object.entries(Qn).forEach(([t,i])=>{Object.entries(i).forEach(([s,r])=>{if(typeof r=="function"){if(Object.hasOwn(e,s))throw new Error(`CollabMdAppShell feature method "${s}" is declared by both "${e[s]}" and "${t}".`);if(s in n)throw new Error(`CollabMdAppShell feature method "${s}" conflicts with an existing app shell member.`);Object.defineProperty(n,s,{configurable:!0,enumerable:!1,value:r.bind(n),writable:!1}),e[s]=t}})}),Object.defineProperty(n,"featureMethodOwners",{configurable:!1,enumerable:!1,value:Object.freeze(e),writable:!1})}var lt=class{constructor(){Zn(this),this.elements=ei(document),this.runtimeConfig=be(),this.stateStore=new Be,this.navigation=new He,this.preferences=new _e({chatNotificationsKey:"collabmd-chat-notifications-enabled",lineWrappingKey:"collabmd-editor-line-wrap",sidebarVisibleKey:"collabmd-sidebar-visible",userNameKey:"collabmd-user-name"}),this.notifications=new De,this.vaultApiClient=he,this._session=null,this._hasPromptedForDisplayName=!1,this._backlinkRefreshTimer=null,this._pendingPreviewLayoutSync=!1,this._previewHydrationPaused=!1,this._previewLayoutResizeObserver=null,this._previewLayoutSyncTimer=null,this.pendingGitResetPath=null,this.chatTimeFormatter=new Intl.DateTimeFormat(void 0,{hour:"numeric",minute:"2-digit"}),this.chatNotificationsEnabled=this.preferences.getChatNotificationsEnabled(),this.chatNotificationPermission=this.notifications.getPermission(),this.lobbyChatMessageMaxLength=gt,this.quickSwitcher=null,this.quickSwitcherModulePromise=null,this.fileExplorerReadyPromise=Promise.resolve(),this.mobileBreakpointQuery=window.matchMedia("(max-width: 768px)"),this.lobby=new Ne({preferredUserName:this.getStoredUserName(),onChange:e=>this.updateGlobalUsers(e),onChatChange:(e,t)=>this.updateChatMessages(e,t),onWorkspaceEvent:e=>{this.handleIncomingWorkspaceEvent(e)}}),this.toastController=new me(this.elements.toastContainer),this.chatToastController=new me(this.elements.chatToastContainer),this.fileExplorer=new Ye({onFileDelete:()=>this.navigation.navigateToFile(null),onFileSelect:e=>this.handleFileSelection(e,{closeSidebarOnMobile:!0}),toastController:this.toastController}),this.gitPanel=new et({enabled:this.runtimeConfig.gitEnabled!==!1,onCommitStaged:()=>this.openGitCommitDialog(),onPullBranch:()=>this.pullGitBranch(),onPushBranch:()=>this.pushGitBranch(),onRepoChange:(e,t)=>this.handleGitRepoChange(e,t),onResetFile:(e,{scope:t})=>this.openGitResetDialog(e,{scope:t}),onSelectDiff:(e,{scope:t})=>this.handleGitDiffSelection(e,{closeSidebarOnMobile:!0,scope:t}),onStageFile:(e,{scope:t})=>this.stageGitFile(e,{scope:t}),onUnstageFile:(e,{scope:t})=>this.unstageGitFile(e,{scope:t}),onViewAllDiff:()=>this.handleGitDiffSelection(null,{closeSidebarOnMobile:!0,scope:"all"}),searchInput:this.elements.gitSearchInput,toastController:this.toastController}),this.outlineController=new it({mobileBreakpointQuery:this.mobileBreakpointQuery,onNavigateToHeading:({sourceLine:e})=>{Number.isFinite(e)&&(this.scrollSyncController.suspendSync(250),this.session?.scrollToLine(e,0))}}),this.videoEmbed=new at({previewElement:this.elements.previewContent}),this.imageLightbox=new ot({previewElement:this.elements.previewContent}),this.previewRenderer=new xe({getContent:()=>this.getPreviewSource(),getFileList:()=>this.fileExplorer.flatDocumentFiles,getSourceFilePath:()=>this.currentFilePath,onAfterRenderCommit:(e,t)=>{this.videoEmbed.reconcileEmbeds(this.elements.previewContent),this.videoEmbed.syncLayout(),this.excalidrawEmbed.reconcileEmbeds(this.elements.previewContent,{isLargeDocument:t.isLargeDocument}),this.excalidrawEmbed.syncLayout(),this.scrollSyncController.setLargeDocumentMode(t.isLargeDocument),this.schedulePreviewLayoutSync({delayMs:0}),this.refreshCommentUiLayout()},onBeforeRenderCommit:()=>{this.videoEmbed.detachForCommit(),this.excalidrawEmbed.detachForCommit()},onRenderComplete:()=>{this.videoEmbed.syncLayout(),this.excalidrawEmbed.syncLayout(),this.schedulePreviewLayoutSync({delayMs:0}),this.refreshCommentUiLayout()},outlineController:this.outlineController,previewContainer:this.elements.previewContainer,previewElement:this.elements.previewContent}),this.themeController=new rt({onChange:e=>this.handleThemeChange(e)}),this.layoutController=new tt({mobileBreakpointQuery:this.mobileBreakpointQuery,onMeasureEditor:()=>this.session?.requestMeasure()}),this.scrollSyncController=new st({getEditorLineNumber:()=>this.session?.getTopVisibleLineNumber(.35)??1,onEditorScrollActivityChange:e=>this.handleEditorScrollActivityChange(e),previewContainer:this.elements.previewContainer,previewElement:this.elements.previewContent,scrollEditorToLine:(e,t)=>this.session?.scrollToLine(e,t)}),this.backlinksPanel=new Oe({onFileSelect:e=>this.handleFileSelection(e,{closeSidebarOnMobile:!0}),panelElement:this.elements.backlinksPanel}),this.excalidrawEmbed=new Ge({getLocalUser:()=>this.lobby.getLocalUser(),getTheme:()=>this.themeController.getTheme(),onOpenFile:e=>e&&this.navigation.navigateToFile(e),previewContainer:this.elements.previewContainer,previewElement:this.elements.previewContent,toastController:this.toastController}),this.commentUi=new We({commentSelectionButton:this.elements.commentSelectionButton,commentsDrawer:this.elements.commentsDrawer,commentsDrawerEmpty:this.elements.commentsDrawerEmpty,commentsDrawerList:this.elements.commentsDrawerList,commentsToggleButton:this.elements.commentsToggleButton,editorContainer:this.elements.editorContainer,previewContainer:this.elements.previewContainer,previewElement:this.elements.previewContent,onCreateThread:({anchor:e,body:t})=>this.session?.createCommentThread({anchor:e,body:t}),onNavigateToLine:e=>{this.scrollSyncController.suspendSync(250),this.session?.scrollToLine(e,.2)},onReplyToThread:(e,t)=>this.session?.replyToCommentThread(e,t),onToggleReaction:(e,t,i)=>this.session?.toggleCommentReaction(e,t,i),onResolveThread:e=>this.session?.deleteCommentThread(e)}),this.workspacePreviewController=new Te({backlinksPanel:this.backlinksPanel,elements:this.elements,excalidrawEmbed:this.excalidrawEmbed,getDisplayName:e=>this.getDisplayName(e),getSession:()=>this.session,isExcalidrawFile:e=>this.isExcalidrawFile(e),isImageFile:e=>this.isImageFile(e),isMermaidFile:e=>this.isMermaidFile(e),isPlantUmlFile:e=>this.isPlantUmlFile(e),layoutController:this.layoutController,outlineController:this.outlineController,previewRenderer:this.previewRenderer,schedulePreviewLayoutSync:e=>this.schedulePreviewLayoutSync(e),scrollSyncController:this.scrollSyncController,videoEmbed:this.videoEmbed}),this.wikiLinkFileController=new Ie({getFileList:()=>this.fileExplorer.flatDocumentFiles,navigation:this.navigation,refreshExplorer:()=>this.fileExplorer.refresh(),toastController:this.toastController,vaultApiClient:this.vaultApiClient}),this.gitDiffView=new Xe({onCommitStaged:()=>this.openGitCommitDialog(),onOpenFile:e=>e&&this.navigation.navigateToFile(e),onStageFile:(e,{scope:t})=>this.stageGitFile(e,{scope:t}),onUnstageFile:(e,{scope:t})=>this.unstageGitFile(e,{scope:t}),toastController:this.toastController}),this.tabActivityLock=new Ue({onActivated:({takeover:e})=>this.handleTabActivated({takeover:e}),onBlocked:()=>this.handleTabBlocked({reason:"active-elsewhere"}),onStolen:()=>this.handleTabBlocked({reason:"taken-over"})}),this.workspaceCoordinator=new Re({attachEditorScroller:e=>this.scrollSyncController.attachEditorScroller(e),beginDocumentLoad:()=>this.previewRenderer.beginDocumentLoad(),cleanupAfterSessionDestroy:()=>{this.scrollSyncController.setLargeDocumentMode(!1),this.scrollSyncController.invalidatePreviewBlocks(),this.outlineController.cleanup(),this.followedCursorSignature="",clearTimeout(this._backlinkRefreshTimer)},createEditorSession:(e,t)=>new e({editorContainer:this.elements.editorContainer,getFileList:t.getFileList,initialTheme:t.theme,lineInfoElement:this.elements.lineInfo,lineWrappingEnabled:t.lineWrappingEnabled,localUser:t.localUser,onImagePaste:t.onImagePaste,onAwarenessChange:t.onAwarenessChange,onCommentsChange:t.onCommentsChange,onConnectionChange:t.onConnectionChange,onContentChange:t.onContentChange,onSelectionChange:t.onSelectionChange,preferredUserName:t.preferredUserName}),getDisplayName:e=>this.getDisplayName(e),getFileList:()=>this.fileExplorer.flatDocumentFiles,getLineWrappingEnabled:()=>this.getStoredLineWrapping(),getLocalUser:()=>this.lobby.getLocalUser(),getStoredUserName:()=>this.getStoredUserName(),getTheme:()=>this.themeController.getTheme(),isExcalidrawFile:e=>this.isExcalidrawFile(e),isImageFile:e=>this.isImageFile(e),isMermaidFile:e=>this.isMermaidFile(e),isPlantUmlFile:e=>this.isPlantUmlFile(e),isTabActive:()=>this.isTabActive,loadEditorSessionClass:()=>this.loadEditorSessionClass(),loadBacklinks:e=>this.backlinksPanel.load(e),onBeforeFileOpen:()=>{this.session=null,this.commentUi.attachSession(null),this.layoutController.reset(),this.resetPreviewMode(),this.elements.emptyState?.classList.add("hidden"),this.elements.editorPage?.classList.remove("hidden"),this.elements.diffPage?.classList.add("hidden"),this.clearInitialFileBootstrap()},onConnectionChange:e=>this.handleConnectionChange(e),onContentChange:({isMermaid:e,isPlantUml:t})=>{this.handleCommentEditorContentChange(),this.previewRenderer.queueRender(),!e&&!t&&this.scheduleBacklinkRefresh()},onCommentsChange:e=>this.handleCommentThreadsChange(e),onFileAwarenessChange:e=>this.updateFileAwareness(e),onFileOpenError:()=>{this.showEditorLoadError(),this.syncWrapToggle(),this.toastController.show("Failed to initialize editor")},onFileOpenReady:()=>{this.hideEditorLoading()},onSelectionChange:e=>this.handleCommentSelectionChange(e),onImagePaste:e=>this.handleEditorImageInsert(e),onSessionAssigned:e=>{this.session=e,this.commentUi.attachSession(e)},onRenderExcalidrawPreview:e=>this.renderExcalidrawFilePreview(e),onRenderImagePreview:e=>this.renderImageFilePreview(e),onSyncWrapToggle:()=>this.syncWrapToggle(),onUpdateActiveFile:e=>this.fileExplorer.setActiveFile(e),onUpdateCurrentFile:e=>{this.currentFilePath=e},onUpdateLobbyCurrentFile:e=>this.lobby.setCurrentFile(e),onUpdateVisibleChrome:(e,{displayName:t})=>{this.syncFileChrome(e),this.syncCommentChrome(e),this.elements.activeFileName&&(this.elements.activeFileName.textContent=t)},onViewModeReset:()=>this.resetPreviewMode(),renderPresence:()=>this.renderPresence(),scrollContainerForSession:e=>e.getScrollContainer(),showEditorLoading:()=>this.showEditorLoading(),stateStore:this.stateStore}),this.workspaceRouteController=new Fe({backlinksPanel:this.backlinksPanel,clearInitialFileBootstrap:()=>this.clearInitialFileBootstrap(),closeSidebarOnMobile:()=>this.closeSidebarOnMobile(),elements:this.elements,excalidrawEmbed:this.excalidrawEmbed,fileExplorer:this.fileExplorer,getIsTabActive:()=>this.isTabActive,getSessionLoadToken:()=>this.sessionLoadToken,gitDiffView:this.gitDiffView,gitPanel:this.gitPanel,imageLightbox:this.imageLightbox,layoutController:this.layoutController,lobby:this.lobby,navigation:this.navigation,previewRenderer:this.previewRenderer,renderAvatars:()=>this.renderAvatars(),renderPresence:()=>this.renderPresence(),resetPreviewMode:()=>this.resetPreviewMode(),scrollSyncController:this.scrollSyncController,setCurrentFilePath:e=>{this.currentFilePath=e,e||(this.commentUi.setCurrentFile(null,{supported:!1}),this.handleCommentThreadsChange([]),this.handleCommentSelectionChange(null))},setSession:e=>{this.session=e,this.commentUi.attachSession(e)},setSessionLoadToken:e=>{this.sessionLoadToken=e},setSidebarTab:e=>this.setSidebarTab(e),showGitDiff:e=>this.showGitDiff(e),syncMainChrome:e=>this.syncMainChrome(e),videoEmbed:this.videoEmbed,workspaceCoordinator:this.workspaceCoordinator}),this.chatNotificationPermission!=="granted"&&(this.chatNotificationsEnabled=!1)}get session(){return this._session}set session(e){this._session=e}get currentFilePath(){return this.stateStore.get("currentFilePath")}set currentFilePath(e){this.stateStore.set("currentFilePath",e)}get globalUsers(){return this.stateStore.get("globalUsers")}set globalUsers(e){this.stateStore.set("globalUsers",e)}get connectionState(){return this.stateStore.get("connectionState")}set connectionState(e){this.stateStore.set("connectionState",e)}get sessionLoadToken(){return this.stateStore.get("sessionLoadToken")}set sessionLoadToken(e){this.stateStore.set("sessionLoadToken",e)}get connectionHelpShown(){return this.stateStore.get("connectionHelpShown")}set connectionHelpShown(e){this.stateStore.set("connectionHelpShown",e)}get chatMessages(){return this.stateStore.get("chatMessages")}set chatMessages(e){this.stateStore.set("chatMessages",e)}get chatMessageIds(){return this.stateStore.get("chatMessageIds")}set chatMessageIds(e){this.stateStore.set("chatMessageIds",e)}get chatUnreadCount(){return this.stateStore.get("chatUnreadCount")}set chatUnreadCount(e){this.stateStore.set("chatUnreadCount",e)}get chatIsOpen(){return this.stateStore.get("chatIsOpen")}set chatIsOpen(e){this.stateStore.set("chatIsOpen",e)}get chatInitialSyncComplete(){return this.stateStore.get("chatInitialSyncComplete")}set chatInitialSyncComplete(e){this.stateStore.set("chatInitialSyncComplete",e)}get isTabActive(){return this.stateStore.get("isTabActive")}set isTabActive(e){this.stateStore.set("isTabActive",e)}get fileExplorerReady(){return this.stateStore.get("fileExplorerReady")}set fileExplorerReady(e){this.stateStore.set("fileExplorerReady",e)}get gitRepoAvailable(){return this.stateStore.get("gitRepoAvailable")}set gitRepoAvailable(e){this.stateStore.set("gitRepoAvailable",e)}get activeSidebarTab(){return this.stateStore.get("activeSidebarTab")}set activeSidebarTab(e){this.stateStore.set("activeSidebarTab",e)}get followedUserClientId(){return this.stateStore.get("followedUserClientId")}set followedUserClientId(e){this.stateStore.set("followedUserClientId",e)}get followedCursorSignature(){return this.stateStore.get("followedCursorSignature")}set followedCursorSignature(e){this.stateStore.set("followedCursorSignature",e)}loadEditorSessionClass(){return this._editorSessionModulePromise||(this._editorSessionModulePromise=import("./chunks/editor-session-AH6Z3MXW.js").then(e=>e.EditorSession)),this._editorSessionModulePromise}scheduleEditorSessionPrewarm({timeout:e=1500}={}){if(this._editorSessionModulePromise||this._editorSessionPrewarmHandle)return;let t=()=>{this._editorSessionPrewarmHandle=null,this.loadEditorSessionClass()};if(typeof window.requestIdleCallback=="function"){this._editorSessionPrewarmHandle=window.requestIdleCallback(t,{timeout:e});return}this._editorSessionPrewarmHandle=window.setTimeout(t,0)}async ensureQuickSwitcher(){if(this.quickSwitcher)return this.quickSwitcher;this.quickSwitcherModulePromise||(this.quickSwitcherModulePromise=import("./chunks/quick-switcher-controller-J7I3CUET.js").then(t=>t.QuickSwitcherController));let e=await this.quickSwitcherModulePromise;return this.quickSwitcher||(this.quickSwitcher=new e({getFileList:()=>this.fileExplorer.flatFiles,onFileSelect:t=>this.handleFileSelection(t,{closeSidebarOnMobile:!0})})),this.quickSwitcher}async toggleQuickSwitcher(){(await this.ensureQuickSwitcher()).toggle()}};var Yn={enabled:!1,implemented:!0,passwordLabel:"Password",requiresLogin:!1,sessionEndpoint:"/api/auth/session",statusEndpoint:"/api/auth/status",strategy:"none",submitLabel:"Continue"},Bi=!1;function Xn(){if(Bi||!document.head)return;let n=document.createElement("style");n.textContent=`
|
|
277
|
+
`}};var lt=class{constructor({mobileBreakpointQuery:e=window.matchMedia("(max-width: 768px)"),onMeasureEditor:t}){this.mobileBreakpointQuery=e,this.onMeasureEditor=t,this.preferredView="split",this.mobileShowsEditor=!this.isMobileViewport(),this.currentView=this.mobileShowsEditor?this.preferredView:"preview",this.editorLayout=document.getElementById("editorLayout"),this.editorPane=document.getElementById("editorPane"),this.previewPane=document.getElementById("previewPane"),this.mobileToggleButton=document.getElementById("mobileViewToggle"),this.resizer=document.getElementById("resizer"),this.viewButtons=Array.from(document.querySelectorAll(".view-btn"))}isMobileViewport(){return this.mobileBreakpointQuery.matches}initialize(){this.viewButtons.forEach(e=>{e.addEventListener("click",()=>this.setView(e.dataset.view))}),this.mobileToggleButton?.addEventListener("click",()=>this.toggleMobileView()),this.initializeResizer(),this.restorePreferredView()}reset(){this.restorePreferredView(),this.editorPane&&(this.editorPane.style.flex=""),this.previewPane&&(this.previewPane.style.flex=""),this.updateResizerValue()}restorePreferredView(){let e=this.isMobileViewport()?this.mobileShowsEditor?"split":"preview":this.preferredView;this.applyView(e),this.updateMobileToggleButton(this.mobileShowsEditor?"Preview":"Editor")}applyView(e){this.currentView=e,this.editorLayout?.setAttribute("data-view",e),this.syncViewButtons()}setView(e,{persist:t=!0}={}){e&&(t&&(this.preferredView=e),this.applyView(e),(e==="split"||e==="editor")&&this.scheduleEditorMeasure())}toggleMobileView(){this.mobileShowsEditor=!this.mobileShowsEditor,this.applyView(this.mobileShowsEditor?"split":"preview"),this.updateMobileToggleButton(this.mobileShowsEditor?"Preview":"Editor"),this.mobileShowsEditor&&this.scheduleEditorMeasure()}scheduleEditorMeasure(){this.onMeasureEditor&&setTimeout(()=>this.onMeasureEditor(),50)}updateMobileToggleButton(e){if(!this.mobileToggleButton)return;let t='<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>',i='<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="18" height="18" rx="2"/><line x1="8" y1="8" x2="16" y2="8"/><line x1="8" y1="12" x2="14" y2="12"/><line x1="8" y1="16" x2="12" y2="16"/></svg>';this.mobileToggleButton.innerHTML=`${e==="Editor"?i:t}<span class="toolbar-btn-label">${e}</span>`}syncViewButtons(){this.viewButtons.forEach(e=>{let t=e.dataset.view===this.currentView;e.classList.toggle("active",t),e.setAttribute("aria-pressed",String(t))})}updateResizerValue(){if(!this.resizer||!this.editorLayout||!this.editorPane)return;let e=this.editorLayout.offsetWidth;if(!Number.isFinite(e)||e<=0)return;let t=Math.round(this.editorPane.offsetWidth/e*100);this.resizer.setAttribute("aria-valuenow",String(Math.max(20,Math.min(80,t))))}applyEditorPaneWidth(e){if(!this.editorLayout||!this.editorPane||!this.previewPane)return;let t=this.editorLayout.offsetWidth;if(!Number.isFinite(t)||t<=0)return;let i=200,r=Math.max(i,Math.min(t-i,e))/t*100;this.editorPane.style.flex=`0 0 ${r}%`,this.previewPane.style.flex="1",this.updateResizerValue()}initializeResizer(){if(!this.resizer||!this.editorLayout||!this.editorPane||!this.previewPane)return;let e=!1,t=0,i=0;this.resizer.addEventListener("mousedown",s=>{e=!0,t=s.clientX,i=this.editorPane.offsetWidth,this.resizer.classList.add("dragging"),document.body.style.cursor="col-resize",document.body.style.userSelect="none",s.preventDefault()}),document.addEventListener("mousemove",s=>{if(!e)return;let r=s.clientX-t;this.applyEditorPaneWidth(i+r)}),document.addEventListener("mouseup",()=>{e&&(e=!1,this.resizer.classList.remove("dragging"),document.body.style.cursor="",document.body.style.userSelect="",this.scheduleEditorMeasure())}),this.resizer.addEventListener("keydown",s=>{let r=this.editorLayout.offsetWidth;if(!Number.isFinite(r)||r<=0)return;let a=Math.max(24,Math.round(r*.05));if(s.key==="ArrowLeft"){s.preventDefault(),this.applyEditorPaneWidth(this.editorPane.offsetWidth-a),this.scheduleEditorMeasure();return}if(s.key==="ArrowRight"){s.preventDefault(),this.applyEditorPaneWidth(this.editorPane.offsetWidth+a),this.scheduleEditorMeasure();return}if(s.key==="Home"){s.preventDefault(),this.applyEditorPaneWidth(r*.2),this.scheduleEditorMeasure();return}s.key==="End"&&(s.preventDefault(),this.applyEditorPaneWidth(r*.8),this.scheduleEditorMeasure())}),this.updateResizerValue()}};var ct=class{constructor({mobileBreakpointQuery:e=window.matchMedia("(max-width: 768px)"),onNavigateToHeading:t,onWillOpen:i}={}){this.outlineOpen=!1,this.activeHeadingFrame=null,this.activeHeadingId=null,this.headings=[],this.pinnedHeadingId=null,this.onNavigateToHeading=t,this.onWillOpen=i,this.panel=document.getElementById("outlinePanel"),this.navigation=document.getElementById("outlineNav"),this.previewContainer=document.getElementById("previewContainer"),this.toggleButton=document.getElementById("outlineToggle"),this.mobileBreakpointQuery=e,this.handlePreviewScroll=()=>this.scheduleActiveHeadingUpdate(),this.handleDocumentPointerDown=s=>{if(!this.outlineOpen)return;let r=s.target;r instanceof Node&&(this.panel?.contains(r)||this.toggleButton?.contains(r))||this.close()}}initialize(){this.toggleButton?.addEventListener("click",()=>this.toggle()),document.addEventListener("pointerdown",this.handleDocumentPointerDown)}toggle(){this.setOpenState(!this.outlineOpen)}close(){this.setOpenState(!1)}setOpenState(e){if(e&&!this.outlineOpen&&this.onWillOpen?.(),this.outlineOpen=e,this.panel?.classList.toggle("hidden",!this.outlineOpen),this.toggleButton?.classList.toggle("active",this.outlineOpen),this.outlineOpen){this.refresh();return}this.cleanup()}refresh(){if(!this.navigation)return;if(!this.outlineOpen){this.cleanup();return}let t=document.getElementById("previewContent")?.querySelectorAll("h1, h2, h3, h4, h5, h6")??[];if(t.length===0){this.navigation.innerHTML='<div class="outline-empty">No headings found</div>',this.cleanup();return}let i=Array.from(t).map((s,r)=>(s.id||(s.id=`heading-${r}-${s.textContent.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"").slice(0,40)}`),{id:s.id,level:Number.parseInt(s.tagName[1],10),sourceLine:Number.parseInt(s.getAttribute("data-source-line")||"",10),text:s.textContent.trim()}));this.navigation.innerHTML=i.map(s=>`<button class="outline-item" data-level="${s.level}" data-target="${s.id}"${Number.isFinite(s.sourceLine)?` data-source-line="${s.sourceLine}"`:""} title="${s.text.replace(/"/g,""")}">${s.text}</button>`).join(""),this.navigation.querySelectorAll(".outline-item").forEach(s=>{s.addEventListener("click",()=>{let r=document.getElementById(s.dataset.target);this.pinnedHeadingId=s.dataset.target,this.notifyHeadingNavigation(r,s.dataset.target),this.scrollHeadingIntoView(r,{behavior:"auto"}),this.setActiveItem(s.dataset.target,{behavior:"auto"}),this.mobileBreakpointQuery.matches&&this.close()})}),this.observeHeadings(Array.from(t))}cleanup(){this.activeHeadingFrame&&(cancelAnimationFrame(this.activeHeadingFrame),this.activeHeadingFrame=null),this.previewContainer?.removeEventListener("scroll",this.handlePreviewScroll),this.headings=[],this.pinnedHeadingId=null}setActiveItem(e,{scrollIntoView:t=!0,behavior:i="smooth"}={}){this.activeHeadingId=e,this.navigation?.querySelectorAll(".outline-item").forEach(s=>{s.classList.toggle("active",s.dataset.target===e)}),t&&this.navigation?.querySelector(".outline-item.active")?.scrollIntoView({behavior:i,block:"nearest"})}observeHeadings(e){this.cleanup(),!(!this.previewContainer||e.length===0)&&(this.headings=e,this.previewContainer.addEventListener("scroll",this.handlePreviewScroll,{passive:!0}),this.updateActiveHeading())}scheduleActiveHeadingUpdate(){this.activeHeadingFrame||(this.activeHeadingFrame=requestAnimationFrame(()=>{this.activeHeadingFrame=null,this.updateActiveHeading()}))}updateActiveHeading(){if(!this.previewContainer||this.headings.length===0)return;let e=this.getPinnedHeading();if(e&&this.shouldKeepPinnedHeadingActive(e)){this.setActiveItem(e.id,{behavior:"auto",scrollIntoView:!0});return}this.pinnedHeadingId=null;let t=this.previewContainer.scrollTop,i=this.headings[0];for(let s of this.headings){if(this.getHeadingScrollTop(s)>t)break;i=s}this.setActiveItem(i.id,{behavior:"auto",scrollIntoView:!0})}getHeadingScrollTop(e){if(!this.previewContainer)return 0;let t=this.previewContainer.getBoundingClientRect(),i=e.getBoundingClientRect();return this.previewContainer.scrollTop+(i.top-t.top)}getPinnedHeading(){return this.pinnedHeadingId?this.headings.find(e=>e.id===this.pinnedHeadingId)??null:null}shouldKeepPinnedHeadingActive(e){if(!this.previewContainer||!e?.isConnected)return!1;let t=this.getHeadingScrollTop(e)-this.previewContainer.scrollTop,i=t+e.getBoundingClientRect().height,s=this.previewContainer.clientHeight*.45;return i>-48&&t<s}notifyHeadingNavigation(e,t){if(!e)return;let i=Number.parseInt(e.getAttribute("data-source-line")||"",10);this.onNavigateToHeading?.({headingId:t,sourceLine:Number.isFinite(i)?i:null})}scrollHeadingIntoView(e,{behavior:t="smooth"}={}){if(!e||!this.previewContainer)return;let i=this.previewContainer.getBoundingClientRect(),s=e.getBoundingClientRect(),r=this.previewContainer.scrollTop+(s.top-i.top);this.previewContainer.scrollTo({behavior:t,top:Math.max(r,0)})}};var Gi=.35,is=120,ns=12,ss=2;function ht(n){return Math.max(n.scrollHeight-n.clientHeight,0)}function rs(n){return Math.max(n,0)}function qi(n){return Math.max(n.clientHeight*Gi,ns)}function as(n){return(n?.scrollTop??0)<=ss}function os(n,e){let t=n.getBoundingClientRect();return e.getBoundingClientRect().top-t.top+n.scrollTop}function ls(n){return!n.querySelector("[data-source-line]")}function cs(n){return typeof window.requestIdleCallback=="function"?window.requestIdleCallback(n,{timeout:500}):window.setTimeout(()=>{n({didTimeout:!1,timeRemaining:()=>0})},1)}function Wi(n){if(n!==null){if(typeof window.cancelIdleCallback=="function"){window.cancelIdleCallback(n);return}window.clearTimeout(n)}}var dt=class{constructor({getEditorLineNumber:e,onEditorScrollActivityChange:t,previewContainer:i,previewElement:s,scrollEditorToLine:r}){this.getEditorLineNumber=e,this.onEditorScrollActivityChange=t,this.previewContainer=i,this.previewElement=s,this.scrollEditorToLine=r,this.editorScroller=null,this.editorScrollActive=!1,this.editorScrollIdleTimer=null,this.lockedElements=new Set,this.pendingSync=null,this.frameId=null,this.previewBlocks=null,this.previewBlocksWarmId=null,this.previewBlocksReadyCallbacks=[],this.largeDocumentMode=!1,this.lastInteractionSource="editor",this.suspendedUntil=0,this.handleEditorScroll=()=>{if(!(!this.editorScroller||this.lockedElements.has(this.editorScroller)||this.isSuspended())){if(this.lastInteractionSource="editor",this.largeDocumentMode){this.setEditorScrollActive(!0),this.scheduleEditorScrollIdle(),this.scheduleSync(this.editorScroller,this.previewContainer,{preferApproximateMapping:!0});return}this.scheduleSync(this.editorScroller,this.previewContainer)}},this.handlePreviewScroll=()=>{!this.previewContainer||this.lockedElements.has(this.previewContainer)||this.isSuspended()||(this.lastInteractionSource="preview",this.scheduleSync(this.previewContainer,this.editorScroller))}}initialize(){this.previewContainer?.addEventListener("scroll",this.handlePreviewScroll,{passive:!0})}attachEditorScroller(e){this.editorScroller!==e&&(this.editorScroller?.removeEventListener("scroll",this.handleEditorScroll),this.editorScroller=e,this.editorScroller?.addEventListener("scroll",this.handleEditorScroll,{passive:!0}))}syncPreviewToEditor(){this.lastInteractionSource="editor",this.sync(this.editorScroller,this.previewContainer)}syncEditorToPreview(){this.lastInteractionSource="preview",this.sync(this.previewContainer,this.editorScroller)}destroy(){this.previewContainer?.removeEventListener("scroll",this.handlePreviewScroll),this.editorScroller?.removeEventListener("scroll",this.handleEditorScroll),this.editorScroller=null,clearTimeout(this.editorScrollIdleTimer),this.editorScrollIdleTimer=null,this.pendingSync=null,this.previewBlocks=null,Wi(this.previewBlocksWarmId),this.previewBlocksWarmId=null,this.previewBlocksReadyCallbacks=[],this.lockedElements.clear(),this.editorScrollActive=!1,this.lastInteractionSource="editor",this.suspendedUntil=0,this.frameId&&(cancelAnimationFrame(this.frameId),this.frameId=null)}scheduleSync(e,t,{preferApproximateMapping:i=!1}={}){!e||!t||this.lockedElements.has(e)||this.isSuspended()||(this.pendingSync={preferApproximateMapping:i,source:e,target:t},!this.frameId&&(this.frameId=requestAnimationFrame(()=>{if(this.frameId=null,!this.pendingSync)return;let{preferApproximateMapping:s,source:r,target:a}=this.pendingSync;this.pendingSync=null,this.sync(r,a,{preferApproximateMapping:s})})))}invalidatePreviewBlocks(){this.previewBlocks=null,Wi(this.previewBlocksWarmId),this.previewBlocksWarmId=null,this.previewBlocksReadyCallbacks=[]}setLargeDocumentMode(e){this.largeDocumentMode=!!e,this.largeDocumentMode||(clearTimeout(this.editorScrollIdleTimer),this.editorScrollIdleTimer=null,this.setEditorScrollActive(!1))}warmPreviewBlocks({onReady:e}={}){if(typeof e=="function"&&(this.previewBlocks?e(this.previewBlocks):this.previewBlocksReadyCallbacks.push(e)),!this.largeDocumentMode){this.previewBlocks||(this.previewBlocks=this.buildPreviewBlocks()),this.flushPreviewBlocksReadyCallbacks();return}this.previewBlocks||this.previewBlocksWarmId!==null||(this.previewBlocksWarmId=cs(()=>{this.previewBlocksWarmId=null,this.previewBlocks=this.buildPreviewBlocks(),this.flushPreviewBlocksReadyCallbacks()}))}realignAfterLayoutChange(){let e=()=>{if(this.lastInteractionSource==="preview"){this.syncEditorToPreview();return}this.syncPreviewToEditor()};if(this.largeDocumentMode&&!this.previewBlocks){this.warmPreviewBlocks({onReady:()=>e()});return}e()}suspendSync(e=250){this.suspendedUntil=performance.now()+e}isSuspended(){return performance.now()<this.suspendedUntil}flushPreviewBlocksReadyCallbacks(){if(this.previewBlocksReadyCallbacks.length===0)return;this.previewBlocksReadyCallbacks.splice(0).forEach(t=>{try{t(this.previewBlocks??[])}catch(i){console.warn("[scroll-sync] Preview block callback failed:",i)}})}setEditorScrollActive(e){this.editorScrollActive!==e&&(this.editorScrollActive=e,this.onEditorScrollActivityChange?.(e))}scheduleEditorScrollIdle(){clearTimeout(this.editorScrollIdleTimer),this.editorScrollIdleTimer=setTimeout(()=>{this.editorScrollIdleTimer=null,this.setEditorScrollActive(!1),this.syncPreviewToEditor()},is)}sync(e,t,{preferApproximateMapping:i=!1}={}){if(!e||!t||this.lockedElements.has(e)||this.isSuspended())return;if(!i&&e===this.editorScroller&&t===this.previewContainer){let l=this.getPreviewScrollTopForEditorLine();if(l!==null){this.setScrollTop(t,l);return}}if(e===this.previewContainer&&t===this.editorScroller){let l=this.getEditorLineNumberForPreviewScroll();if(l!==null){this.lockedElements.add(t),this.scrollEditorToLine?.(l,Gi),requestAnimationFrame(()=>{this.lockedElements.delete(t)});return}}let s=ht(e),r=ht(t),a=s>0?e.scrollTop/s:0,o=r>0?r*a:0;this.setScrollTop(t,o)}setScrollTop(e,t){this.lockedElements.add(e),e.scrollTop=rs(t),requestAnimationFrame(()=>{this.lockedElements.delete(e)})}getPreviewScrollTopForEditorLine(){if(as(this.editorScroller))return 0;let e=this.getEditorLineNumber?.();if(!Number.isFinite(e))return null;let t=this.getPreviewBlocks();if(t.length===0||!this.previewContainer)return null;let{block:i,index:s}=this.findBlockForLine(t,e),r=this.getPreviewSpan(t,s),a=Math.max(i.end-i.start,1),o=x((e-i.start)/a,0,1),l=ht(this.previewContainer),h=qi(this.previewContainer);return x(i.top+r*o-h,0,l)}getEditorLineNumberForPreviewScroll(){if(!this.previewContainer)return null;let e=this.getPreviewBlocks();if(e.length===0)return null;let t=this.previewContainer.scrollTop+qi(this.previewContainer),{block:i,index:s}=this.findBlockForScrollTop(e,t),r=this.getPreviewSpan(e,s),a=Math.max(i.end-i.start,1),o=r>0?x((t-i.top)/r,0,1):0;return Math.round(i.start+a*o)}getPreviewBlocks(){return this.previewBlocks?this.previewBlocks:!this.previewContainer||!this.previewElement?[]:this.largeDocumentMode?[]:(this.previewBlocks=this.buildPreviewBlocks(),this.previewBlocks)}buildPreviewBlocks(){let e=Array.from(this.previewElement.querySelectorAll("[data-source-line]")).map(s=>{let r=Number.parseInt(s.getAttribute("data-source-line")||"",10),a=Number.parseInt(s.getAttribute("data-source-line-end")||"",10);return Number.isFinite(r)?{element:s,end:Number.isFinite(a)?Math.max(a,r+1):r+1,start:r,top:os(this.previewContainer,s)}:null}).filter(Boolean).sort((s,r)=>s.top-r.top||s.start-r.start||s.end-r.end),t=e.filter(s=>ls(s.element)),i=t.length>0?t:e;return i.filter((s,r)=>{let a=i[r-1];return!a||Math.abs(a.top-s.top)>1||a.start!==s.start||a.end!==s.end})}findBlockForLine(e,t){let i=null,s=-1;for(let a=0;a<e.length;a+=1){let o=e[a];if(t>=o.start&&t<o.end){if(!i){i=o,s=a;continue}let l=i.end-i.start,h=o.end-o.start;(h<l||h===l&&o.start>=i.start)&&(i=o,s=a)}}if(i)return{block:i,index:s};let r=0;for(let a=0;a<e.length&&!(e[a].start>t);a+=1)r=a;return{block:e[r],index:r}}findBlockForScrollTop(e,t){for(let s=0;s<e.length;s+=1){let r=this.getPreviewSpan(e,s)+e[s].top;if(t<r)return{block:e[s],index:s}}let i=e.length-1;return{block:e[i],index:i}}getPreviewSpan(e,t){if(!this.previewContainer)return 1;let i=e[t],s=e[t+1],r=i.element.getBoundingClientRect().height;if(!s){let a=ht(this.previewContainer);return Math.max(a-i.top+this.previewContainer.clientHeight,r,1)}return Math.max(s.top-i.top,r,1)}};var hs='<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="5"/><path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/></svg>',ds='<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg>',ut=class{constructor({storageKey:e="collabmd-theme",onChange:t}){this.storageKey=e,this.onChange=t,this.currentTheme="dark"}initialize(){this.currentTheme=this.readPreferredTheme(),this.applyTheme(),document.querySelectorAll("[data-theme-toggle]").forEach(e=>{e.addEventListener("click",()=>this.toggle())})}getTheme(){return this.currentTheme}toggle(){this.currentTheme=this.currentTheme==="dark"?"light":"dark",this.persistTheme(),this.applyTheme()}readPreferredTheme(){try{let e=window.localStorage.getItem(this.storageKey);if(e==="light"||e==="dark")return e}catch{}return window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"}persistTheme(){try{window.localStorage.setItem(this.storageKey,this.currentTheme)}catch{}}applyTheme(){document.documentElement.setAttribute("data-theme",this.currentTheme),this.updateToggleIcons(),this.onChange?.(this.currentTheme)}updateToggleIcons(){let e=this.currentTheme==="dark"?hs:ds;document.querySelectorAll("[data-theme-toggle]").forEach(t=>{t.innerHTML=e})}};var me=class{constructor(e){this.container=e}show(e,t=3e3){if(!this.container)return;let i=document.createElement("div");i.className="toast",i.textContent=e,this.container.appendChild(i),setTimeout(()=>{i.classList.add("leaving"),i.addEventListener("animationend",()=>i.remove(),{once:!0})},t)}};var Vi=16/9,us=240,ms=720,ps=180;function fs(n){return Math.max(ps,Math.min(ms,Math.ceil(n||us)))}var mt=class{constructor({previewElement:e}){this.previewElement=e,this.embedEntries=new Map,this.overlayRoot=null}destroy(){this.embedEntries.forEach(e=>{e.hydrateFrameId&&(cancelAnimationFrame(e.hydrateFrameId),e.hydrateFrameId=null),e.wrapper?.remove(),e.placeholder=null}),this.embedEntries.clear(),this.overlayRoot?.remove(),this.overlayRoot=null}detachForCommit(){this.embedEntries.forEach(e=>{e.placeholder=null})}reconcileEmbeds(e=this.previewElement){if(this.previewElement=e,!e)return;let t=Array.from(e.querySelectorAll(".video-embed-placeholder[data-video-embed-key]")).map(r=>({filePath:r.dataset.videoEmbedSource,key:r.dataset.videoEmbedKey,label:r.dataset.videoEmbedLabel||"Embedded video",placeholder:r,source:r.dataset.videoEmbedSource||"",kind:r.dataset.videoEmbedKind||"",url:r.dataset.videoEmbedUrl||"",mimeType:r.dataset.videoEmbedMimeType||""})),{nextEntries:i,removedEntries:s}=Xe(this.embedEntries,t);s.forEach(r=>this._destroyEntry(r)),this.embedEntries=i,this.embedEntries.forEach(r=>{r.aspectRatio=r.aspectRatio||Vi,r.kind=r.placeholder?.dataset.videoEmbedKind||r.kind,r.label=r.placeholder?.dataset.videoEmbedLabel||r.label,r.mimeType=r.placeholder?.dataset.videoEmbedMimeType||r.mimeType,r.source=r.placeholder?.dataset.videoEmbedSource||r.source,r.url=r.placeholder?.dataset.videoEmbedUrl||r.url,r.wrapper||this._createEmbed(r),this._attachWrapper(r)}),this.syncLayout(),this.embedEntries.size===0&&(this.overlayRoot?.remove(),this.overlayRoot=null)}syncLayout(){this.embedEntries.forEach(e=>{e.wrapper&&this._syncEntryLayout(e)})}_destroyEntry(e){e.hydrateFrameId&&(cancelAnimationFrame(e.hydrateFrameId),e.hydrateFrameId=null),e.wrapper?.remove(),e.placeholder=null}_createEmbed(e){let t=document.createElement("div");if(t.className=`video-embed video-embed-shell diagram-preview-shell is-${e.kind}`,e.kind==="youtube"){let i=document.createElement("div");i.className="video-embed-frame video-embed-frame-youtube";let s=document.createElement("iframe");s.className="video-embed-iframe",s.title=e.label||"Embedded YouTube video",s.referrerPolicy="strict-origin-when-cross-origin",s.allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share",s.allowFullscreen=!0,i.appendChild(s),t.appendChild(i),e.mediaElement=s}else{let i=document.createElement("video");i.className="video-embed-player",i.controls=!0,i.preload="metadata",i.playsInline=!0,e.label&&(i.title=e.label,i.setAttribute("aria-label",e.label));let s=document.createElement("source");s.src=e.url,e.mimeType&&(s.type=e.mimeType),i.appendChild(s),i.addEventListener("loadedmetadata",()=>{Number.isFinite(i.videoWidth)&&Number.isFinite(i.videoHeight)&&i.videoWidth>0&&i.videoHeight>0&&(e.aspectRatio=i.videoWidth/i.videoHeight,this._syncEntryLayout(e))}),t.appendChild(i),e.mediaElement=i}e.wrapper=t}_attachWrapper(e){let t=e.placeholder?.isConnected?e.placeholder:this.previewElement?.querySelector(`.video-embed-placeholder[data-video-embed-key="${e.key}"]`);if(!t)return;e.placeholder=t,t.classList.add("is-hydrated"),t.dataset.videoEmbedHydrated="true",t.style.pointerEvents="none";let i=this._ensureOverlayRoot();e.wrapper?.parentElement!==i&&i.appendChild(e.wrapper)}_syncEntryLayout(e){let t=e.placeholder?.isConnected?e.placeholder:this.previewElement?.querySelector(`.video-embed-placeholder[data-video-embed-key="${e.key}"]`);if(!t||!e.wrapper)return;e.placeholder=t;let i=t.offsetWidth||t.clientWidth||0;if(i<=0&&e.inlineHeightPx)return;let s=fs(i>0?i/(e.aspectRatio||Vi):e.inlineHeightPx);e.inlineHeightPx=s,Q(t,"height",`${s}px`),Q(e.wrapper,"position","absolute"),Q(e.wrapper,"top",`${t.offsetTop}px`),Q(e.wrapper,"left",`${t.offsetLeft}px`),Q(e.wrapper,"width",`${t.offsetWidth}px`),Q(e.wrapper,"height",`${s}px`),Q(e.wrapper,"margin","0"),Q(e.wrapper,"pointerEvents","auto"),this._hydrateEntryMedia(e)}_ensureOverlayRoot(){let e=this.previewElement?.querySelector('[data-video-overlay-root="true"]');return e||(e=document.createElement("div"),e.dataset.videoOverlayRoot="true",e.className="video-embed-overlay-root",this.previewElement?.appendChild(e)),this.overlayRoot=e,e}_hydrateEntryMedia(e){if(e.kind!=="youtube")return;let t=e.mediaElement;t instanceof HTMLIFrameElement&&(!e.url||t.getAttribute("src")===e.url||e.wrapper?.offsetWidth<=0||e.wrapper?.offsetHeight<=0||e.hydrateFrameId||(e.hydrateFrameId=requestAnimationFrame(()=>{if(e.hydrateFrameId=null,!e.url||t.getAttribute("src")===e.url)return;let i=Math.round(e.wrapper?.offsetWidth||0),s=Math.round(e.wrapper?.offsetHeight||0);i<=0||s<=0||(t.width=String(i),t.height=String(s),t.src=e.url)})))}};function Q(n,e,t){!n||n.style[e]===t||(n.style[e]=t)}function gs(n){let e=Number(n);return Number.isFinite(e)?Math.min(6,Math.max(1,Math.round(e*100)/100)):1}function Ki(n,{contentSize:e=0,scale:t=1,viewportSize:i=0}={}){let s=Number(n),r=Number(e),a=Number(t),o=Number(i);if(!Number.isFinite(s)||!Number.isFinite(r)||!Number.isFinite(a)||!Number.isFinite(o))return 0;let l=(r*a-o)/2;return l<=0?0:Math.min(Math.max(s,-l),l)}var pt=class{constructor({previewElement:e,documentRef:t=document,windowRef:i=window}){this.previewElement=e,this.document=t,this.window=i,this.overlayRoot=null,this.viewport=null,this.imageElement=null,this.zoomLabel=null,this.titleElement=null,this.isOpen=!1,this.scale=1,this.offsetX=0,this.offsetY=0,this.activePointerId=null,this.dragStartX=0,this.dragStartY=0,this.dragOriginX=0,this.dragOriginY=0,this.didDrag=!1,this.resetButton=null,this.handlePreviewClick=s=>{let r=s.target;if(!(r instanceof this.window.Element))return;let a=r.closest("img");!a||!this.previewElement?.contains(a)||a.closest('[data-video-overlay-root="true"], [data-excalidraw-overlay-root="true"]')||(s.preventDefault(),s.stopImmediatePropagation?.(),this.openFromImage(a))},this.handleKeyDown=s=>{if(this.isOpen){if(s.key==="Escape"){s.preventDefault(),this.close();return}if(s.key==="+"||s.key==="="){s.preventDefault(),this.zoomBy(.25);return}if(s.key==="-"){s.preventDefault(),this.zoomBy(-.25);return}s.key==="0"&&(s.preventDefault(),this.resetView())}},this.handleWindowResize=()=>{this.isOpen&&(this.clampOffsets(),this.syncTransform())},this.previewElement?.addEventListener("click",this.handlePreviewClick),this.document.addEventListener("keydown",this.handleKeyDown),this.window.addEventListener("resize",this.handleWindowResize)}destroy(){this.previewElement?.removeEventListener("click",this.handlePreviewClick),this.document.removeEventListener("keydown",this.handleKeyDown),this.window.removeEventListener("resize",this.handleWindowResize),this.close(),this.overlayRoot?.remove(),this.overlayRoot=null,this.viewport=null,this.imageElement=null,this.zoomLabel=null,this.titleElement=null,this.resetButton=null}openFromImage(e){let t=e?.currentSrc||e?.getAttribute?.("src")||"";return t?(this.ensureOverlayRoot(),this.resetView(),this.titleElement.textContent=e.getAttribute("alt")||"Image preview",this.imageElement.src=t,this.imageElement.alt=e.getAttribute("alt")||"",this.overlayRoot.hidden=!1,this.isOpen=!0,this.document.body.classList.add("image-lightbox-open"),this.syncTransform(),this.overlayRoot.focus?.(),!0):!1}close(){!this.isOpen&&!this.overlayRoot||(this.activePointerId=null,this.didDrag=!1,this.viewport?.classList?.remove("is-dragging"),this.overlayRoot&&(this.overlayRoot.hidden=!0),this.isOpen=!1,this.document.body.classList.remove("image-lightbox-open"))}resetView(){this.scale=1,this.offsetX=0,this.offsetY=0,this.syncTransform()}zoomBy(e){this.setScale(this.scale+e)}setScale(e){this.scale=gs(e),this.clampOffsets(),this.syncTransform()}clampOffsets(){if(!this.viewport||!this.imageElement){this.offsetX=0,this.offsetY=0;return}this.offsetX=Ki(this.offsetX,{contentSize:this.imageElement.offsetWidth||0,scale:this.scale,viewportSize:this.viewport.clientWidth||0}),this.offsetY=Ki(this.offsetY,{contentSize:this.imageElement.offsetHeight||0,scale:this.scale,viewportSize:this.viewport.clientHeight||0})}syncTransform(){this.imageElement&&(this.imageElement.style.transform=`translate3d(${this.offsetX}px, ${this.offsetY}px, 0) scale(${this.scale})`,this.imageElement.style.cursor=this.scale>1?"grab":"zoom-in",this.zoomLabel&&(this.zoomLabel.textContent=`${Math.round(this.scale*100)}%`),this.resetButton&&(this.resetButton.disabled=this.scale<=1&&this.offsetX===0&&this.offsetY===0))}ensureOverlayRoot(){if(this.overlayRoot?.isConnected&&this.overlayRoot.parentElement===this.document.body)return this.overlayRoot;let e=this.document.createElement("div");e.className="image-lightbox-root",e.dataset.imageLightboxRoot="true",e.hidden=!0,e.tabIndex=-1;let t=this.document.createElement("button");t.className="image-lightbox-backdrop",t.type="button",t.setAttribute("aria-label","Close image preview"),t.addEventListener("click",d=>{d.preventDefault(),d.stopPropagation(),this.close()});let i=this.document.createElement("div");i.className="image-lightbox-shell",i.setAttribute("role","dialog"),i.setAttribute("aria-modal","true"),i.setAttribute("aria-label","Image preview"),i.addEventListener("click",d=>d.stopPropagation()),i.addEventListener("pointerdown",d=>d.stopPropagation());let s=this.document.createElement("div");s.className="image-lightbox-toolbar";let r=this.document.createElement("div");r.className="image-lightbox-title",r.textContent="Image preview";let a=this.document.createElement("div");a.className="image-lightbox-controls";let o=this.document.createElement("span");o.className="image-lightbox-zoom-label",o.textContent="100%";let l=this.createControlButton("Reset","Reset zoom and position",()=>this.resetView()),h=this.createControlButton("Close","Close image preview",()=>this.close());a.append(o,l,h),s.append(r,a);let c=this.document.createElement("div");c.className="image-lightbox-viewport";let u=this.document.createElement("img");u.className="image-lightbox-image",u.alt="",u.addEventListener("load",()=>{this.clampOffsets(),this.syncTransform()}),c.addEventListener("wheel",d=>{this.isOpen&&(d.preventDefault(),this.zoomBy(d.deltaY<0?.25:-.25))},{passive:!1}),c.addEventListener("pointerdown",d=>{!this.isOpen||this.scale<=1||d.button!==0||(this.activePointerId=d.pointerId,this.dragStartX=d.clientX,this.dragStartY=d.clientY,this.dragOriginX=this.offsetX,this.dragOriginY=this.offsetY,this.didDrag=!1,c.classList.add("is-dragging"),c.setPointerCapture?.(d.pointerId),d.preventDefault())}),c.addEventListener("pointermove",d=>{!this.isOpen||this.activePointerId!==d.pointerId||(!this.didDrag&&(Math.abs(d.clientX-this.dragStartX)>=6||Math.abs(d.clientY-this.dragStartY)>=6)&&(this.didDrag=!0),this.offsetX=this.dragOriginX+(d.clientX-this.dragStartX),this.offsetY=this.dragOriginY+(d.clientY-this.dragStartY),this.clampOffsets(),this.syncTransform())});let p=d=>{this.activePointerId===d.pointerId&&(this.activePointerId=null,c.classList.remove("is-dragging"),c.releasePointerCapture?.(d.pointerId),this.imageElement.style.cursor=this.scale>1?"grab":"zoom-in")};return c.addEventListener("pointerup",p),c.addEventListener("pointercancel",p),u.addEventListener("click",d=>{if(this.isOpen){if(d.preventDefault(),d.stopPropagation(),this.didDrag){this.didDrag=!1;return}this.scale<=1&&this.setScale(2)}}),c.appendChild(u),i.append(s,c),e.append(t,i),this.document.body.appendChild(e),this.overlayRoot=e,this.viewport=c,this.imageElement=u,this.zoomLabel=o,this.titleElement=r,this.resetButton=l,this.syncTransform(),e}createControlButton(e,t,i,{className:s=""}={}){let r=this.document.createElement("button");return r.className=`image-lightbox-btn ${s}`.trim(),r.type="button",r.setAttribute("aria-label",t),r.textContent=e,r.addEventListener("click",a=>{a.preventDefault(),a.stopPropagation(),i(a)}),r}};var ws=Object.freeze({chat:hi,comments:di,git:mi,presence:pi,ui:fi,workspace:gi});function ys(n){let e={};Object.entries(ws).forEach(([t,i])=>{Object.entries(i).forEach(([s,r])=>{if(typeof r=="function"){if(Object.hasOwn(e,s))throw new Error(`CollabMdAppShell feature method "${s}" is declared by both "${e[s]}" and "${t}".`);if(s in n)throw new Error(`CollabMdAppShell feature method "${s}" conflicts with an existing app shell member.`);Object.defineProperty(n,s,{configurable:!0,enumerable:!1,value:r.bind(n),writable:!1}),e[s]=t}})}),Object.defineProperty(n,"featureMethodOwners",{configurable:!1,enumerable:!1,value:Object.freeze(e),writable:!1})}var ft=class{constructor(){ys(this),this.elements=ci(document),this.runtimeConfig=Se(),this.stateStore=new _e,this.navigation=new Ue,this.preferences=new Oe({chatNotificationsKey:"collabmd-chat-notifications-enabled",lineWrappingKey:"collabmd-editor-line-wrap",sidebarVisibleKey:"collabmd-sidebar-visible",userNameKey:"collabmd-user-name"}),this.notifications=new $e,this.vaultApiClient=he,this._session=null,this._hasPromptedForDisplayName=!1,this._backlinkRefreshTimer=null,this._pendingPreviewLayoutSync=!1,this._previewHydrationPaused=!1,this._previewLayoutResizeObserver=null,this._previewLayoutSyncTimer=null,this.pendingGitResetPath=null,this.chatTimeFormatter=new Intl.DateTimeFormat(void 0,{hour:"numeric",minute:"2-digit"}),this.chatNotificationsEnabled=this.preferences.getChatNotificationsEnabled(),this.chatNotificationPermission=this.notifications.getPermission(),this.lobbyChatMessageMaxLength=Lt,this.quickSwitcher=null,this.quickSwitcherModulePromise=null,this.fileExplorerReadyPromise=Promise.resolve(),this.mobileBreakpointQuery=window.matchMedia("(max-width: 768px)"),this.pendingWorkspaceRequestIds=new Set,this.lobby=new ze({preferredUserName:this.getStoredUserName(),onChange:e=>this.updateGlobalUsers(e),onChatChange:(e,t)=>this.updateChatMessages(e,t)}),this.workspaceSync=new Ve({onTreeChange:(e,t={})=>{let i=this.fileExplorerReady;this.fileExplorer.setTree(e,t),this.fileExplorerReady=!0,!i&&this.isTabActive&&this.handleHashChange()},onWorkspaceEvent:e=>{this.handleIncomingWorkspaceEvent(e)}}),this.toastController=new me(this.elements.toastContainer),this.chatToastController=new me(this.elements.chatToastContainer),this.fileExplorer=new st({onFileDelete:()=>this.navigation.navigateToFile(null),onFileSelect:e=>this.handleFileSelection(e,{closeSidebarOnMobile:!0}),toastController:this.toastController}),this.gitPanel=new ot({enabled:this.runtimeConfig.gitEnabled!==!1,onCommitStaged:()=>this.openGitCommitDialog(),onOpenPullBackup:e=>e&&this.navigation.navigateToFile(e),onPullBranch:()=>this.pullGitBranch(),onPushBranch:()=>this.pushGitBranch(),onRepoChange:(e,t)=>this.handleGitRepoChange(e,t),onResetFile:(e,{scope:t})=>this.openGitResetDialog(e,{scope:t}),onSelectDiff:(e,{scope:t})=>this.handleGitDiffSelection(e,{closeSidebarOnMobile:!0,scope:t}),onStageFile:(e,{scope:t})=>this.stageGitFile(e,{scope:t}),onUnstageFile:(e,{scope:t})=>this.unstageGitFile(e,{scope:t}),onViewAllDiff:()=>this.handleGitDiffSelection(null,{closeSidebarOnMobile:!0,scope:"all"}),searchInput:this.elements.gitSearchInput,toastController:this.toastController}),this.outlineController=new ct({mobileBreakpointQuery:this.mobileBreakpointQuery,onNavigateToHeading:({sourceLine:e})=>{Number.isFinite(e)&&(this.scrollSyncController.suspendSync(250),this.session?.scrollToLine(e,0))},onWillOpen:()=>this.commentUi?.closeDrawer()}),this.videoEmbed=new mt({previewElement:this.elements.previewContent}),this.imageLightbox=new pt({previewElement:this.elements.previewContent}),this.previewRenderer=new Te({getContent:()=>this.getPreviewSource(),getFileList:()=>this.fileExplorer.flatDocumentFiles,getSourceFilePath:()=>this.currentFilePath,onAfterRenderCommit:(e,t)=>{this.videoEmbed.reconcileEmbeds(this.elements.previewContent),this.videoEmbed.syncLayout(),this.excalidrawEmbed.reconcileEmbeds(this.elements.previewContent,{isLargeDocument:t.isLargeDocument}),this.excalidrawEmbed.syncLayout(),this.scrollSyncController.setLargeDocumentMode(t.isLargeDocument),this.schedulePreviewLayoutSync({delayMs:0}),this.refreshCommentUiLayout()},onBeforeRenderCommit:()=>{this.videoEmbed.detachForCommit(),this.excalidrawEmbed.detachForCommit()},onRenderComplete:()=>{this.videoEmbed.syncLayout(),this.excalidrawEmbed.syncLayout(),this.schedulePreviewLayoutSync({delayMs:0}),this.refreshCommentUiLayout()},outlineController:this.outlineController,previewContainer:this.elements.previewContainer,previewElement:this.elements.previewContent}),this.themeController=new ut({onChange:e=>this.handleThemeChange(e)}),this.layoutController=new lt({mobileBreakpointQuery:this.mobileBreakpointQuery,onMeasureEditor:()=>this.session?.requestMeasure()}),this.scrollSyncController=new dt({getEditorLineNumber:()=>this.session?.getTopVisibleLineNumber(.35)??1,onEditorScrollActivityChange:e=>this.handleEditorScrollActivityChange(e),previewContainer:this.elements.previewContainer,previewElement:this.elements.previewContent,scrollEditorToLine:(e,t)=>this.session?.scrollToLine(e,t)}),this.backlinksPanel=new Ke({inlinePanelElement:this.elements.backlinksInlinePanel,onFileSelect:e=>this.handleFileSelection(e,{closeSidebarOnMobile:!0}),panelElement:this.elements.backlinksPanel}),this.excalidrawEmbed=new et({getLocalUser:()=>this.lobby.getLocalUser(),getTheme:()=>this.themeController.getTheme(),onOpenFile:e=>e&&this.navigation.navigateToFile(e),previewContainer:this.elements.previewContainer,previewElement:this.elements.previewContent,toastController:this.toastController}),this.commentUi=new Ze({commentSelectionButton:this.elements.commentSelectionButton,commentsDrawer:this.elements.commentsDrawer,commentsDrawerEmpty:this.elements.commentsDrawerEmpty,commentsDrawerList:this.elements.commentsDrawerList,commentsToggleButton:this.elements.commentsToggleButton,editorContainer:this.elements.editorContainer,onWillOpenDrawer:()=>this.outlineController.close(),previewContainer:this.elements.previewContainer,previewElement:this.elements.previewContent,onCreateThread:({anchor:e,body:t})=>this.session?.createCommentThread({anchor:e,body:t}),onNavigateToLine:e=>{this.scrollSyncController.suspendSync(250),this.session?.scrollToLine(e,.2)},onReplyToThread:(e,t)=>this.session?.replyToCommentThread(e,t),onToggleReaction:(e,t,i)=>this.session?.toggleCommentReaction(e,t,i),onResolveThread:e=>this.session?.deleteCommentThread(e)}),this.workspacePreviewController=new Be({backlinksPanel:this.backlinksPanel,elements:this.elements,excalidrawEmbed:this.excalidrawEmbed,getDisplayName:e=>this.getDisplayName(e),getSession:()=>this.session,isExcalidrawFile:e=>this.isExcalidrawFile(e),isImageFile:e=>this.isImageFile(e),isMermaidFile:e=>this.isMermaidFile(e),isPlantUmlFile:e=>this.isPlantUmlFile(e),layoutController:this.layoutController,outlineController:this.outlineController,previewRenderer:this.previewRenderer,schedulePreviewLayoutSync:e=>this.schedulePreviewLayoutSync(e),scrollSyncController:this.scrollSyncController,videoEmbed:this.videoEmbed}),this.wikiLinkFileController=new Re({getFileList:()=>this.fileExplorer.flatDocumentFiles,navigation:this.navigation,refreshExplorer:()=>this.fileExplorer.refresh(),toastController:this.toastController,vaultApiClient:this.vaultApiClient}),this.gitDiffView=new rt({onCommitStaged:()=>this.openGitCommitDialog(),onOpenFile:e=>e&&this.navigation.navigateToFile(e),onStageFile:(e,{scope:t})=>this.stageGitFile(e,{scope:t}),onUnstageFile:(e,{scope:t})=>this.unstageGitFile(e,{scope:t}),toastController:this.toastController}),this.tabActivityLock=new We({onActivated:({takeover:e})=>this.handleTabActivated({takeover:e}),onBlocked:()=>this.handleTabBlocked({reason:"active-elsewhere"}),onStolen:()=>this.handleTabBlocked({reason:"taken-over"})}),this.workspaceCoordinator=new He({attachEditorScroller:e=>this.scrollSyncController.attachEditorScroller(e),beginDocumentLoad:()=>this.previewRenderer.beginDocumentLoad(),cleanupAfterSessionDestroy:()=>{this.scrollSyncController.setLargeDocumentMode(!1),this.scrollSyncController.invalidatePreviewBlocks(),this.outlineController.cleanup(),this.followedCursorSignature="",clearTimeout(this._backlinkRefreshTimer)},createEditorSession:(e,t)=>new e({editorContainer:this.elements.editorContainer,getFileList:t.getFileList,initialTheme:t.theme,lineInfoElement:this.elements.lineInfo,lineWrappingEnabled:t.lineWrappingEnabled,localUser:t.localUser,onImagePaste:t.onImagePaste,onAwarenessChange:t.onAwarenessChange,onCommentsChange:t.onCommentsChange,onConnectionChange:t.onConnectionChange,onContentChange:t.onContentChange,onSelectionChange:t.onSelectionChange,preferredUserName:t.preferredUserName}),getDisplayName:e=>this.getDisplayName(e),getFileList:()=>this.fileExplorer.flatDocumentFiles,getLineWrappingEnabled:()=>this.getStoredLineWrapping(),getLocalUser:()=>this.lobby.getLocalUser(),getStoredUserName:()=>this.getStoredUserName(),getTheme:()=>this.themeController.getTheme(),isExcalidrawFile:e=>this.isExcalidrawFile(e),isImageFile:e=>this.isImageFile(e),isMermaidFile:e=>this.isMermaidFile(e),isPlantUmlFile:e=>this.isPlantUmlFile(e),isTabActive:()=>this.isTabActive,loadEditorSessionClass:()=>this.loadEditorSessionClass(),loadBacklinks:e=>this.backlinksPanel.load(e),onBeforeFileOpen:()=>{this.session=null,this.commentUi.attachSession(null),this.layoutController.reset(),this.resetPreviewMode(),this.elements.emptyState?.classList.add("hidden"),this.elements.editorPage?.classList.remove("hidden"),this.elements.diffPage?.classList.add("hidden"),this.clearInitialFileBootstrap()},onConnectionChange:e=>this.handleConnectionChange(e),onContentChange:({isMermaid:e,isPlantUml:t})=>{this.handleCommentEditorContentChange(),this.previewRenderer.queueRender(),!e&&!t&&this.scheduleBacklinkRefresh()},onCommentsChange:e=>this.handleCommentThreadsChange(e),onFileAwarenessChange:e=>this.updateFileAwareness(e),onFileOpenError:()=>{this.showEditorLoadError(),this.syncWrapToggle(),this.toastController.show("Failed to initialize editor")},onFileOpenReady:()=>{this.hideEditorLoading()},onSelectionChange:e=>this.handleCommentSelectionChange(e),onImagePaste:e=>this.handleEditorImageInsert(e),onSessionAssigned:e=>{this.session=e,this.commentUi.attachSession(e)},onRenderExcalidrawPreview:e=>this.renderExcalidrawFilePreview(e),onRenderImagePreview:e=>this.renderImageFilePreview(e),onSyncWrapToggle:()=>this.syncWrapToggle(),onUpdateActiveFile:e=>this.fileExplorer.setActiveFile(e),onUpdateCurrentFile:e=>{this.currentFilePath=e},onUpdateLobbyCurrentFile:e=>this.lobby.setCurrentFile(e),onUpdateVisibleChrome:(e,{displayName:t})=>{this.syncFileChrome(e),this.syncCommentChrome(e),this.elements.activeFileName&&(this.elements.activeFileName.textContent=t)},onViewModeReset:()=>this.resetPreviewMode(),renderPresence:()=>this.renderPresence(),scrollContainerForSession:e=>e.getScrollContainer(),showEditorLoading:()=>this.showEditorLoading(),stateStore:this.stateStore}),this.workspaceRouteController=new Ae({backlinksPanel:this.backlinksPanel,clearInitialFileBootstrap:()=>this.clearInitialFileBootstrap(),closeSidebarOnMobile:()=>this.closeSidebarOnMobile(),elements:this.elements,excalidrawEmbed:this.excalidrawEmbed,fileExplorer:this.fileExplorer,getIsTabActive:()=>this.isTabActive,getSessionLoadToken:()=>this.sessionLoadToken,gitDiffView:this.gitDiffView,gitPanel:this.gitPanel,imageLightbox:this.imageLightbox,layoutController:this.layoutController,lobby:this.lobby,navigation:this.navigation,previewRenderer:this.previewRenderer,renderAvatars:()=>this.renderAvatars(),renderPresence:()=>this.renderPresence(),resetPreviewMode:()=>this.resetPreviewMode(),scrollSyncController:this.scrollSyncController,setCurrentFilePath:e=>{this.currentFilePath=e,e||(this.commentUi.setCurrentFile(null,{supported:!1}),this.handleCommentThreadsChange([]),this.handleCommentSelectionChange(null))},setSession:e=>{this.session=e,this.commentUi.attachSession(e)},setSessionLoadToken:e=>{this.sessionLoadToken=e},setSidebarTab:e=>this.setSidebarTab(e),showGitDiff:e=>this.showGitDiff(e),syncMainChrome:e=>this.syncMainChrome(e),videoEmbed:this.videoEmbed,workspaceCoordinator:this.workspaceCoordinator}),this.chatNotificationPermission!=="granted"&&(this.chatNotificationsEnabled=!1)}get session(){return this._session}set session(e){this._session=e}get currentFilePath(){return this.stateStore.get("currentFilePath")}set currentFilePath(e){this.stateStore.set("currentFilePath",e)}get globalUsers(){return this.stateStore.get("globalUsers")}set globalUsers(e){this.stateStore.set("globalUsers",e)}get connectionState(){return this.stateStore.get("connectionState")}set connectionState(e){this.stateStore.set("connectionState",e)}get sessionLoadToken(){return this.stateStore.get("sessionLoadToken")}set sessionLoadToken(e){this.stateStore.set("sessionLoadToken",e)}get connectionHelpShown(){return this.stateStore.get("connectionHelpShown")}set connectionHelpShown(e){this.stateStore.set("connectionHelpShown",e)}get chatMessages(){return this.stateStore.get("chatMessages")}set chatMessages(e){this.stateStore.set("chatMessages",e)}get chatMessageIds(){return this.stateStore.get("chatMessageIds")}set chatMessageIds(e){this.stateStore.set("chatMessageIds",e)}get chatUnreadCount(){return this.stateStore.get("chatUnreadCount")}set chatUnreadCount(e){this.stateStore.set("chatUnreadCount",e)}get chatIsOpen(){return this.stateStore.get("chatIsOpen")}set chatIsOpen(e){this.stateStore.set("chatIsOpen",e)}get chatInitialSyncComplete(){return this.stateStore.get("chatInitialSyncComplete")}set chatInitialSyncComplete(e){this.stateStore.set("chatInitialSyncComplete",e)}get isTabActive(){return this.stateStore.get("isTabActive")}set isTabActive(e){this.stateStore.set("isTabActive",e)}get fileExplorerReady(){return this.stateStore.get("fileExplorerReady")}set fileExplorerReady(e){this.stateStore.set("fileExplorerReady",e)}get gitRepoAvailable(){return this.stateStore.get("gitRepoAvailable")}set gitRepoAvailable(e){this.stateStore.set("gitRepoAvailable",e)}get activeSidebarTab(){return this.stateStore.get("activeSidebarTab")}set activeSidebarTab(e){this.stateStore.set("activeSidebarTab",e)}get followedUserClientId(){return this.stateStore.get("followedUserClientId")}set followedUserClientId(e){this.stateStore.set("followedUserClientId",e)}get followedCursorSignature(){return this.stateStore.get("followedCursorSignature")}set followedCursorSignature(e){this.stateStore.set("followedCursorSignature",e)}loadEditorSessionClass(){return this._editorSessionModulePromise||(this._editorSessionModulePromise=import("./chunks/editor-session-EAUBJCHH.js").then(e=>e.EditorSession)),this._editorSessionModulePromise}scheduleEditorSessionPrewarm({timeout:e=1500}={}){if(this._editorSessionModulePromise||this._editorSessionPrewarmHandle)return;let t=()=>{this._editorSessionPrewarmHandle=null,this.loadEditorSessionClass()};if(typeof window.requestIdleCallback=="function"){this._editorSessionPrewarmHandle=window.requestIdleCallback(t,{timeout:e});return}this._editorSessionPrewarmHandle=window.setTimeout(t,0)}async ensureQuickSwitcher(){if(this.quickSwitcher)return this.quickSwitcher;this.quickSwitcherModulePromise||(this.quickSwitcherModulePromise=import("./chunks/quick-switcher-controller-A6SKH5HI.js").then(t=>t.QuickSwitcherController));let e=await this.quickSwitcherModulePromise;return this.quickSwitcher||(this.quickSwitcher=new e({getFileList:()=>this.fileExplorer.flatFiles,onFileSelect:t=>this.handleFileSelection(t,{closeSidebarOnMobile:!0})})),this.quickSwitcher}async toggleQuickSwitcher(){(await this.ensureQuickSwitcher()).toggle()}};var vs={enabled:!1,implemented:!0,passwordLabel:"Password",requiresLogin:!1,sessionEndpoint:"/api/auth/session",statusEndpoint:"/api/auth/status",strategy:"none",submitLabel:"Continue"},ji=!1;function bs(){if(ji||!document.head)return;let n=document.createElement("style");n.textContent=`
|
|
251
278
|
.auth-gate-overlay {
|
|
252
279
|
position: fixed;
|
|
253
280
|
inset: 0;
|
|
@@ -351,4 +378,4 @@ ${r}`}getPreviewSource(e){let t=this.getSession()?.getText()??"";return this.isM
|
|
|
351
378
|
color: #fca5a5;
|
|
352
379
|
font-size: 0.92rem;
|
|
353
380
|
}
|
|
354
|
-
`,document.head.append(n),
|
|
381
|
+
`,document.head.append(n),ji=!0}function Cs(){return{...vs,...Se().auth??{}}}function Zi(){let n=window.location.hash.startsWith("#")?window.location.hash.slice(1):window.location.hash;return new URLSearchParams(n)}function Es(){return Zi().get("auth_password")||""}function Qi(){let n=Zi();if(!n.has("auth_password"))return;n.delete("auth_password");let e=n.toString(),t=`${window.location.pathname}${window.location.search}${e?`#${e}`:""}`;window.history.replaceState(null,"",t)}async function Ss(n){let e=await fetch(n.statusEndpoint,{headers:{Accept:"application/json"}}),t=await e.json().catch(()=>({}));if(!e.ok)throw new Error(t.error||"Failed to read auth status");return t}async function Yi(n,e){let t=await fetch(n.sessionEndpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({password:e})}),i=await t.json().catch(()=>({}));if(!t.ok)throw new Error(i.error||"Authentication failed");return i}function ks(){bs();let n=document.createElement("div");n.className="auth-gate-overlay";let e=document.createElement("section");return e.className="auth-gate-card",n.append(e),{card:e,overlay:n}}function Dt(n,{title:e,body:t,secondaryActionLabel:i="",onSecondaryAction:s=null}){n.replaceChildren();let r=document.createElement("h1");r.textContent=e;let a=document.createElement("p");if(a.textContent=t,n.append(r,a),i&&typeof s=="function"){let o=document.createElement("button");o.className="auth-gate-secondary-button",o.type="button",o.textContent=i,o.addEventListener("click",()=>{s()}),n.append(o)}}function Ps(n,e,{onSubmit:t,onRetryStatus:i}){n.replaceChildren();let s=document.createElement("h1");s.textContent="Authentication required";let r=document.createElement("p");r.textContent="Enter the host password to join this shared session.";let a=document.createElement("form");a.className="auth-gate-form";let o=document.createElement("label");o.className="auth-gate-label",o.textContent=e.passwordLabel;let l=document.createElement("input");l.className="auth-gate-input",l.type="password",l.name="password",l.autocomplete="current-password",l.required=!0;let h=document.createElement("div");h.className="auth-gate-error";let c=document.createElement("div");c.className="auth-gate-actions";let u=document.createElement("button");u.className="auth-gate-secondary-button",u.type="button",u.textContent="Retry status";let p=document.createElement("button");p.className="auth-gate-button",p.type="submit",p.textContent=e.submitLabel,c.append(u,p),o.append(l),a.append(s,r,o,h,c),n.append(a),u.addEventListener("click",()=>{i()}),a.addEventListener("submit",d=>{d.preventDefault();let w=l.value;l.disabled=!0,p.disabled=!0,u.disabled=!0,h.textContent="",t(w).catch(m=>{h.textContent=m instanceof Error?m.message:"Authentication failed",l.disabled=!1,p.disabled=!1,u.disabled=!1,l.select(),l.focus()})}),queueMicrotask(()=>{l.focus()})}async function Xi(){let n=Cs();if(!n.enabled||n.strategy==="none")return{authenticated:!0,auth:n};let{card:e,overlay:t}=ks();return document.body.append(t),new Promise(i=>{let s=()=>{Qi(),t.remove(),i({authenticated:!0,auth:n})},r=async()=>{Dt(e,{body:"Checking access to this session\u2026",title:"CollabMD"});try{if((await Ss(n)).authenticated){s();return}}catch(a){Dt(e,{body:a instanceof Error?a.message:"Failed to contact the auth service.",secondaryActionLabel:"Retry",title:"Cannot verify access",onSecondaryAction:r});return}if(n.strategy==="password"){let a=Es();if(a)try{Qi(),await Yi(n,a),s();return}catch{}Ps(e,n,{onRetryStatus:r,onSubmit:async o=>{await Yi(n,o),s()}});return}Dt(e,{body:n.strategy==="oidc"?"OIDC authentication is configured but not implemented in this build yet.":"This authentication strategy is not available.",secondaryActionLabel:"Retry status",title:"Authentication unavailable",onSecondaryAction:r})};r()})}async function Ji(){await Xi(),new ft().initialize()}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>{Ji()},{once:!0}):Ji();
|