<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>WebVLogger</title><style>
:root {--healthy:#7D0;--base:#fff;--back:#222;--warn:#FC0;--error:#F45;--info:#58F;--x:#F15;--y:#0F3;--z:#25F;}
body{margin:0px;font-family:sans;}
#m{position:absolute;bottom:0;overflow:scroll;max-height:30%;background:#2228;border-right:2px solid #FFF;border-top:2px solid #FFF;border-top-right-radius:6px;}
#m a{display:block;word-break: break-all;}
#m a>a{display:inline;color:inherit;}
#b{width:100vw;height:100vh;background:var(--back);}
#b svg{position:absolute;top:0;left:0;pointer-events:none;}
a{pointer-events:visible;}
#s{margin:10px;padding:3px;background:#444;border:2px solid #CCC;border-radius:6px;position:absolute;top:0;right:0;max-height:80%;overflow:scroll;}
#s button{display:block;border:none;background:#444;margin: top 2px bottom 2px;width:100%;height:21pt;font-size:14pt;}
#s button:hover{background:#666;}
</style><script>
$=(n)=>document.getElementById(n)
$c=(t)=>document.createElementNS("http://www.w3.org/2000/svg",t)
$C=(t)=>document.createElement(t)
$s=(x,y,z)=>x.setAttribute(y,z)
$a=(p,c)=>p.appendChild(c)
I="ideographic",T="transform",M="middle"
document.addEventListener("DOMContentLoaded",(_)=>{
function txt(l,si,co,an,bl){
t=$c('text')
t.textContent=l;Object.assign(t.style,{fill:co,stroke:"black",strokeWidth:1.5,strokeJoin:"bevel",paintOrder:"stroke",fontSize:typeof si==="string"?si:`${si}px`,textAnchor:an,dominantBaseline:bl})}
function addlbl(p,lbl,si,co,al,hr){
a=$c('a')
$s(a,"href",hr)
txt(lbl,si==0?"1.8vh":si,co,al==1?M:(al==0?"start":(al==2?"end":M)),al==3?I:"central")
$s(t,"x",p[0]+.5)
$s(t,"y",p[1]+.5)
$a(a,t);$a(vg,a)}
function addpt(p,lbl,si,co,s,hr){
gc=$c('a')
$s(gc,"href",hr)
d=s.includes("Di")
q=s[0]=="P"
R=s=="PointCross"
P=s=="Point"
st=s.endsWith("ne")||!s.includes("Fi")&&!q
if(s.endsWith("le")||P||s=="PointOutline"){
c=$c('circle')
c.style.r=q?`${si/20}vh`:`${si/2}px`
c.style.fill=s=="FilledCircle"||P?co:"none"
if(st){c.style.stroke=co;c.style.strokeWidth='.2vh'}
$a(gc,c)
}else if(d||s.includes("Sq")){
c = $c('rect'),x=si*0.443
if(!q){x=si/2}
v=q?`${-x/10}vh`:-x
$s(c,"x",v)
$s(c,"y",v)
v=q?`${x*2/10}vh`:x*2
$s(c,"width",v)
$s(c,"height",v)
if(d){$s(c,T,"rotate(45)")}
if(st){c.style.stroke=co;c.style.strokeWidth='.2vh';c.style.fill="none"} else {c.style.fill=co}
$a(gc,c)
}else if(R){
x=si/28.284
for(y of [-x,x]){
l=$c('line');l.style.stroke=co;l.style.strokeWidth='.2vh'
$s(l,"x1",`${-x}vh`);$s(l,"y1",`${-y}vh`);$s(l,"x2",`${x}vh`);$s(l,"y2",`${y}vh`);
$a(gc,l)}}
if(s.startsWith("Da")){c.style.strokeDasharray="4 3"}
if(lbl){
b=lbl.length*10<=si&&!R
txt(lbl,q?"1.8vh":"16px",(s.includes("F")||(q&&!s.endsWith("ne")))&&b?"white":co,M,b?"central":I);
if(!b){$s(t,"y",-si/2)}
$a(gc,t)}
$s(gc,T,`translate(${p[0]+.5},${p[1]+.5})`)
$a(vg,gc)}
function addl(p1,p2,lbl,th,co,s,hr){
a=$c('a')
$s(a,"href",hr)
l=$c('line'),S={stroke:co,strokeWidth:th==0?'.2vh':`${th}px`,strokeLinecap:'round'}
Object.assign(l.style,S)
for([k,v]of[["x1",p1[0]],["y1",p1[1]],["x2",p2[0]],["y2",p2[1]]]){$s(l,k,v+.5)}
$a(a,l)
x=p2[0]-p1[0],y=p2[1]-p1[1],h=th*2/Math.hypot(x,y)
if(s=="Arrow"){
$s(l,"x2",p2[0]-x*h+.5)
$s(l,"y2",p2[1]-y*h+.5)
z=$c('path')
$s(z,"d","M-2 -1v 2L0 0Z")
z.style.fill=co
$s(z,T,`translate(${p2[0]+.5},${p2[1]+.5}) scale(${th+3}) rotate(${Math.atan2(p2[1]-p1[1],p2[0]-p1[0])*180/3.1415})`)
$a(a,z)}else if(s.endsWith("CW")){H=$c('line'),v=s.endsWith("CCW")?1:-1
Object.assign(H.style,S);
for([k,v]of[["x1",p1[0]+x/2+x*h],["y1",p1[1]+y/2+y*h],["x2",p1[0]+x/2+y*h*v],["y2",p1[1]+y/2-x*h*v]])$s(H,k,v+.5)
$a(a,H)}l.style.strokeDasharray=s=="Dashed"?`${th} ${2*th}`:""
if(lbl){txt(lbl,16,co,M,I)
$s(t,"x",p1[0]+x/2)
$s(t,"y",p1[1]+y/2)
$a(a,t)}$a(vg,a)}
m=$("m");qu=[];scr=()=>m.scrollTop=m.scrollHeight;sx=0;sy=0;
zoom=(e)=>{if(e.ctrlKey===false){sx+=Math.sign(e.deltaX)*15;sy+=Math.sign(e.deltaY)*15}for(s of $('b').children){s.setAttribute("viewBox",`${sx} ${sy} ${window.innerWidth} ${window.innerHeight}`)}};
ws=new WebSocket(`ws://${location.hostname}:${location.port}`)
f=e=>{let q=qu
qu=[]
for(j of q){let s=`_${j.surf}`,hr,p;vg=$(s);
if(vg==null){vg=$c('svg')
$s(vg,"width","100%")
$s(vg,"height","100%")
vg.id=s
$a($('b'),vg)
zoom(e)}if(j.meta){hr=`vscode://file/${j.meta.file}:${j.meta.line}:0`}
if(j.msg) {let a=$C("a"),A=$C("a"),p=m.children[m.children.length-1];a.dataset["t"]=a.textContent=`${j.meta.target}: ${j.msg} `;A.textContent=`(line ${j.meta.line})`;$a(a,A);A.href=hr;a.dataset["s"]=j.surf;a.dataset["i"]=1;a.style.color=j.col;
if(p===undefined||p.dataset["t"]!=a.dataset["t"]||p.dataset["s"]!=a.dataset["s"]){$a(m,a);scr()}else{p.dataset["i"]=Number(p.dataset["i"])+1;p.textContent=a.textContent+`×${p.dataset["i"]}`}}
else if(j.clear){vg.innerHTML="";for(e of m.children){if(j.surf==e.dataset["s"]){e.remove()}}}
else if(j.pos2!==undefined){addl(j.pos,j.pos2,j.lbl,j.size,j.col,String(j.style),hr)}
else if(j.align!==undefined&&j.lbl){addlbl(j.pos,j.lbl,j.size,j.col,j.align,hr)}
else {addpt(j.pos,j.lbl,j.size,j.col,String(j.style),hr)}
s=`-${j.surf}`
btn=$(s)
if(!btn){btn=$C('button');btn.id=s;btn.textContent=`${j.surf}`;btn.style.color="#FFF";
let sb=vg;btn.onclick=(e)=>{if(sb.style.visibility!="hidden")
{btn.style.color="#777";sb.style.visibility="hidden"}else
{btn.style.color="#FFF";sb.style.visibility="visible"}
for(e of $("m").children){let s=e.dataset["s"];if(s!=null){if($(`_${s}`).style.visibility!="hidden"){e.style.display="block"}else {e.style.display="none"}}}scr()};
$a($('s'),btn)}}}
ws.onmessage=(e)=>{
let j=JSON.parse(e.data.replaceAll("\\'","'"));
if(j.surf!==undefined){qu.push(j)
requestAnimationFrame(f)}}
ws.onclose=e=>{f();let a=$C("a");a.textContent=`Connection Closed`;a.style.color="var(--error)";a.style.fontWeight="bold";$a(m,a);scr()};
window.onresize=zoom;$("b").onwheel=zoom;});
</script></head><body><div id="b"></div><div id="s"></div><div id="m"></div></body></html>