Skip to content

Commit

Permalink
dev: experiment new text selection 2
Browse files Browse the repository at this point in the history
  • Loading branch information
Myriad-Dreamin committed Dec 26, 2023
1 parent 09a1938 commit 4be652e
Showing 1 changed file with 2 additions and 2 deletions.
4 changes: 2 additions & 2 deletions frontend/src/svg_utils.cjs
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
const ignoredEvent=function(){const t={};let e,n;return function(s,r,c){n=new Date().getTime(),c=c||"ignored event",e=t[c]?n-t[c]:n,e>r&&(t[c]=n,s())}}(),fc=(t,e)=>{const n=[];for(let s=0;s<t.length;s++){const r=t[s];e(r)&&n.push(r)}return n},overLappingDom=(t,e)=>!(t.right<e.left||t.left>e.right||t.bottom<e.top||t.top>e.bottom),almostOverLapping=(t,e)=>{const n=t.getBoundingClientRect(),s=e.getBoundingClientRect();return overLappingDom(n,s)&&Math.abs(n.left-s.left)+Math.abs(n.right-s.right)<.5*Math.max(n.width,s.width)&&Math.abs(n.bottom-s.bottom)+Math.abs(n.top-s.top)<.5*Math.max(n.height,s.height)},gr=window.typstGetRelatedElements=t=>{let e=t.relatedElements;return e==null&&(e=t.relatedElements=searchIntersections(t)),e},getRelatedElements=t=>gr(t.target),findAncestor=(t,e)=>{for(;t&&!t.classList.contains(e);)t=t.parentElement;return t};function findGlyphListForText(t){const e=findAncestor(t,"typst-text");return e&&fc(e.children,n=>n.tagName==="use")}const searchIntersections=function(t){const e=findAncestor(t,"typst-group");return e&&fc(e.children,n=>almostOverLapping(n,t))};function nextNode(t){if(t.hasChildNodes())return t.firstChild;for(;t&&!t.nextSibling;)t=t.parentNode;return t?t.nextSibling:null}function getRangeSelectedNodes(t,e){var n=t.startContainer,s=t.endContainer;if(n==s){if(e(n))return[n];if(e(n.parentElement))return[n.parentElement]}for(var r=[];n&&n!=s;)n=nextNode(n),e(n)&&r.push(n);for(n=t.startContainer;n&&n!=t.commonAncestorContainer;)e(n)&&r.unshift(n),n=n.parentNode;return r}function getSelectedNodes(t){if(window.getSelection){var e=window.getSelection();if(!e.isCollapsed){if(e.rangeCount===1)return getRangeSelectedNodes(e.getRangeAt(0),t);let n=[];for(let s=0,r=e.rangeCount;s<r;s++)n.push(...getRangeSelectedNodes(e.getRangeAt(s),t));return n}}return[]}function getGlyphLenShape(t){return t.map(e=>{const n=e.getAttribute("href"),s=document.getElementById(n.slice(1));return 1+Number.parseInt(s?.getAttribute("data-liga-len")||"0")})}function getGlyphAdvanceShape(t){return t.map(e=>Number.parseInt(e.getAttribute("x")||"0"))}const linkmove=t=>ignoredEvent(()=>gr(t)?.forEach(e=>e.classList.add("hover")),200,"mouse-move"),linkleave=t=>gr(t)?.forEach(e=>e.classList.remove("hover"));window.typstProcessSvg=function(t,e){for(var n=t.getElementsByClassName("pseudo-link"),s=0;s<n.length;s++){var r=n[s];r.addEventListener("mousemove",d=>linkmove(d.target)),r.addEventListener("mouseleave",d=>linkleave(d.target))}if((e?.layoutText??!0)&&setTimeout(()=>{const d=document.createElement("style");d.innerHTML=`.tsel { font-family: monospace; text-align-last: left !important; -moz-text-size-adjust: none; -webkit-text-size-adjust: none; text-size-adjust: none; overflow: hidden; }
.tsel span { position: relative !important; width: fit-content !important; }`,document.getElementsByTagName("head")[0].appendChild(d),window.layoutText(t)},0),t.addEventListener("click",d=>{let i=d.target;for(;i;){const g=i.getAttribute("data-span");if(g){console.log("source-span of this svg element",g);const y=document.body||document.firstElementChild,h=y.getBoundingClientRect(),E=window.innerWidth||0,u=d.clientX-h.left+.015*E,f=d.clientY-h.top+.015*E;triggerRipple(y,u,f,"typst-debug-react-ripple","typst-debug-react-ripple-effect .4s linear");return}i=i.parentElement}}),window.location.hash){const i=window.location.hash.split("-");if(i.length===2&&i[0]==="#loc"){const g=i[1].split("x");if(g.length===3){const y=Number.parseInt(g[0]),h=Number.parseFloat(g[1]),E=Number.parseFloat(g[2]);window.handleTypstLocation(t,y,h,E)}}}};const LB=`
`.codePointAt(0);window.layoutText=async function(t){const e=Array.from(t.querySelectorAll(".tsel, .typst-content-hint, .pseudo-link")),n=performance.now(),s=document.createElementNS("http://www.w3.org/1999/xhtml","canvas").getContext("2d");s.font="128px monospace";const r=s.measureText("A").width;var c=t.getBoundingClientRect();const d=(u,f,m)=>{var o=u.getScreenCTM();return o?{x:o.a*f+o.c*m+o.e,y:o.b*f+o.d*m+o.f}:{x:0,y:0}};let i=document.createElement("div");t.parentElement?(t.parentElement?.insertBefore(i,t.nextSibling),i.style.position="absolute",i.style.left="0",i.style.top="0",i.style.zIndex="1",i.style.float="left"):i=void 0;const y=(u,f="span")=>{const m=u.getBBox(),o=d(u,m.x,m.y),a=d(u,m.x+m.width,m.y+m.height),l={x:Math.min(o.x,a.x),y:Math.min(o.y,a.y),width:Math.abs(o.x-a.x),height:Math.abs(o.y-a.y)},p=document.createElement(f);return p.classList.add("tsel"),p.style.position="absolute",p.style.left=`${l.x}px`,p.style.top=`${l.y}px`,p.style.width=`${l.width}px`,p.style.height=`${l.height}px`,p},h=(u,f)=>{const m=e.slice(u,f);for(let o of m)if(!o.getAttribute("data-typst-layout-checked")){if(o.setAttribute("data-typst-layout-checked","1"),i){if(o.classList.contains("typst-content-hint")){const a=y(o);a.style.fontSize="1px",a.style.width="1px",a.style.height="1px";const l=Number.parseInt(o.getAttribute("data-hint")||"0",16)||LB;a.innerHTML=l===LB?"<br/>":`&#x${l.toString(16)};`,i.append(a);continue}else if(o.classList.contains("pseudo-link")){const a=y(o,"a");a.style.cursor="pointer",a.addEventListener("mousemove",()=>linkmove(o)),a.addEventListener("mouseleave",()=>linkleave(o)),a.onclick=()=>{o.dispatchEvent(new MouseEvent("click",{bubbles:!0}))},a.addEventListener("mouseenter",()=>{const l=o.parentElement?.getAttribute("href")||o.parentElement?.getAttribute("xlink:href");a.getAttribute("href")!==l&&a.setAttribute("href",l||"")}),i.append(a);continue}}if(o.style.fontSize){const a=o.innerText,l=r*Number.parseFloat(o.style.fontSize)/128,p=findGlyphListForText(o);if(!p)continue;const C=getGlyphLenShape(p),T=getGlyphAdvanceShape(p).map(v=>v/16);let M=!1;const x=[];let b=0,w=0,N=0,A,B=0;for(let v of a){if(b>=T.length){M=!0;break}let L=T[b];C[b]>1&&(L+=w*l),w++,w>=C[b]&&(b++,w=0);const S=document.createElement("span");S.textContent=v,S.classList.add("tsel-tok"),A&&(A.style.letterSpacing=`${L-B-l}px`),A=S,B=L,x.push(S),N+=1}if(M)continue;if(o.innerHTML="",i){const v=o.parentElement,L=Number.parseFloat(o.style.fontSize||"0"),S=Math.abs(d(v,0,L).y-d(v,0,0).y),H=S/L;for(let k of x)k.style.letterSpacing=`${Number.parseFloat(k.style.letterSpacing||"0")*H}px`;const R=y(v);R.style.fontSize=`${S}px`,R.append(...x),i.append(R)}else o.append(...x)}}console.log(`layoutText ${e.length} elements used since ${performance.now()-n} ms`)},E=100;for(let u=0;u<e.length;u+=E){const f=u;await new Promise(m=>{setTimeout(()=>{h(f,f+E),m(void 0)})})}},window.handleTypstLocation=function(t,e,n,s,r){const c=r?.behavior||"smooth",d=window.assignSemaHash||((h,E,u)=>{location.hash=`loc-${h}x${E.toFixed(2)}x${u.toFixed(2)}`}),i=findAncestor(t,"typst-doc");if(!i){console.warn("no typst-doc found",t);return}const g=i.children;let y=0;for(let h=0;h<g.length;h++)if(g[h].tagName==="g"&&y++,y==e){const E=window.innerWidth*.01,u=window.innerHeight*.01,f=g[h],m=Number.parseFloat(i.getAttribute("data-width")||i.getAttribute("width")||"0")||0,o=Number.parseFloat(i.getAttribute("data-height")||i.getAttribute("height")||"0")||0,a=i.getBoundingClientRect(),l={left:a.left,top:a.top,width:a.width,height:a.height},p=7*E,C=38.2*u,T=f.transform.baseVal.consolidate()?.matrix;T&&(l.left+=T.e/m*l.width,l.top+=T.f/o*l.height);const M=document.body||document.firstElementChild,x=M.getBoundingClientRect(),b=l.left-x.left+n/m*l.width-p,w=l.top-x.top+s/o*l.height-C,N=b+p,A=w+C;window.scrollTo({behavior:c,left:b,top:w}),c!=="instant"&&triggerRipple(M,N,A,"typst-jump-ripple","typst-jump-ripple-effect .4s linear"),d(y,n,s);return}};function triggerRipple(t,e,n,s,r){const c=document.createElement("div");c.className=s,c.style.left=`${e}px`,c.style.top=`${n}px`,t.appendChild(c),c.style.animation=r,c.onanimationend=()=>{t.removeChild(c)}}var scriptTag=document.currentScript;if(scriptTag){console.log("new svg util updated 37 ",performance.now());const t=findAncestor(scriptTag,"typst-doc");t&&window.typstProcessSvg(t)}
.tsel span { position: relative !important; width: fit-content !important; }`,document.getElementsByTagName("head")[0].appendChild(d),window.layoutText(t)},0),t.addEventListener("click",d=>{let a=d.target;for(;a;){const g=a.getAttribute("data-span");if(g){console.log("source-span of this svg element",g);const E=document.body||document.firstElementChild,f=E.getBoundingClientRect(),b=window.innerWidth||0,w=d.clientX-f.left+.015*b,m=d.clientY-f.top+.015*b;triggerRipple(E,w,m,"typst-debug-react-ripple","typst-debug-react-ripple-effect .4s linear");return}a=a.parentElement}}),window.location.hash){const a=window.location.hash.split("-");if(a.length===2&&a[0]==="#loc"){const g=a[1].split("x");if(g.length===3){const E=Number.parseInt(g[0]),f=Number.parseFloat(g[1]),b=Number.parseFloat(g[2]);window.handleTypstLocation(t,E,f,b)}}}};const LB=`
`.codePointAt(0);window.layoutText=async function(t){const e=Array.from(t.querySelectorAll(".tsel, .typst-content-hint, .pseudo-link")),n=performance.now(),s=document.createElementNS("http://www.w3.org/1999/xhtml","canvas").getContext("2d");s.font="128px monospace";const r=s.measureText("A").width;var c=t.getBoundingClientRect();const d=(m,h,l)=>{var o=m.getScreenCTM();return o?{x:o.a*h+o.c*l+o.e,y:o.b*h+o.d*l+o.f}:{x:0,y:0}};let a=document.createElement("div");t.parentElement?(t.parentElement?.insertBefore(a,t.nextSibling),a.style.position="absolute",a.style.left="0",a.style.top="0",a.style.zIndex="1",a.style.float="left"):a=void 0;const E=[],f=(m,h="span")=>{const l=m.getBBox(),o=d(m,l.x,l.y),i=d(m,l.x+l.width,l.y+l.height),y=Math.min(o.x,i.x)+window.scrollX,S=Math.min(o.y,i.y)+window.scrollY,T=Math.abs(o.x-i.x),x=Math.abs(o.y-i.y),u=document.createElement(h);return u.classList.add("tsel"),u.style.position="relative",u.style.display="inline-block",u.style.width=`${T}px`,u.style.height=`${x}px`,E.push({e:u,x:y,y:S}),u},b=(m,h)=>{const l=e.slice(m,h);for(let o of l)if(!o.getAttribute("data-typst-layout-checked")){if(o.setAttribute("data-typst-layout-checked","1"),a){if(o.classList.contains("typst-content-hint")){const i=f(o);i.style.fontSize="0.1px",i.style.width="0.1px",i.style.height="0.1px";const p=Number.parseInt(o.getAttribute("data-hint")||"0",16)||LB;i.innerHTML=p===LB?"<br/>":`&#x${p.toString(16)};`,a.append(i);continue}else if(o.classList.contains("pseudo-link")){const i=f(o,"a");i.style.cursor="pointer",i.addEventListener("mousemove",()=>linkmove(o)),i.addEventListener("mouseleave",()=>linkleave(o)),i.onclick=()=>{o.dispatchEvent(new MouseEvent("click",{bubbles:!0}))},i.addEventListener("mouseenter",()=>{const p=o.parentElement?.getAttribute("href")||o.parentElement?.getAttribute("xlink:href");i.getAttribute("href")!==p&&i.setAttribute("href",p||"")}),a.append(i);continue}}if(o.style.fontSize){const i=o.innerText,p=r*Number.parseFloat(o.style.fontSize)/128,y=findGlyphListForText(o);if(!y)continue;const v=getGlyphLenShape(y),S=getGlyphAdvanceShape(y).map(L=>L/16);let T=!1;const x=[];let u=0,M=0,N=0,R,B=0;for(let L of i){if(u>=S.length){T=!0;break}let A=S[u];v[u]>1&&(A+=M*p),M++,M>=v[u]&&(u++,M=0);const C=document.createElement("span");C.textContent=L,C.classList.add("tsel-tok"),R&&(R.style.letterSpacing=`${A-B-p}px`),R=C,B=A,x.push(C),N+=1}if(T)continue;if(o.innerHTML="",a){const L=o.parentElement,A=Number.parseFloat(o.style.fontSize||"0"),C=Math.abs(d(L,0,A).y-d(L,0,0).y),G=C/A;for(let H of x)H.style.letterSpacing=`${Number.parseFloat(H.style.letterSpacing||"0")*G}px`;const k=f(L);k.style.fontSize=`${C}px`,k.append(...x),a.append(k)}else o.append(...x)}}console.log(`layoutText ${e.length} elements used since ${performance.now()-n} ms`)},w=100;for(let m=0;m<e.length;m+=w){const h=m;await new Promise(l=>{setTimeout(()=>{b(h,h+w),l(void 0)})})}if(a?.children.length){const m=performance.now();Array.from(E).map(({e:l,x:o,y:i})=>{const p=l.offsetLeft,y=l.offsetTop;return{e:l,x:o,y:i,offsetLeft:p,offsetTop:y}}).forEach(({e:l,x:o,y:i,offsetLeft:p,offsetTop:y})=>{l.style.left=`${o-p}px`,l.style.top=`${i-y}px`}),console.log(`relative positioning elements used since ${performance.now()-m} ms`)}},window.handleTypstLocation=function(t,e,n,s,r){const c=r?.behavior||"smooth",d=window.assignSemaHash||((f,b,w)=>{location.hash=`loc-${f}x${b.toFixed(2)}x${w.toFixed(2)}`}),a=findAncestor(t,"typst-doc");if(!a){console.warn("no typst-doc found",t);return}const g=a.children;let E=0;for(let f=0;f<g.length;f++)if(g[f].tagName==="g"&&E++,E==e){const b=window.innerWidth*.01,w=window.innerHeight*.01,m=g[f],h=Number.parseFloat(a.getAttribute("data-width")||a.getAttribute("width")||"0")||0,l=Number.parseFloat(a.getAttribute("data-height")||a.getAttribute("height")||"0")||0,o=a.getBoundingClientRect(),i={left:o.left,top:o.top,width:o.width,height:o.height},p=7*b,y=38.2*w,v=m.transform.baseVal.consolidate()?.matrix;v&&(i.left+=v.e/h*i.width,i.top+=v.f/l*i.height);const S=document.body||document.firstElementChild,T=S.getBoundingClientRect(),x=i.left-T.left+n/h*i.width-p,u=i.top-T.top+s/l*i.height-y,M=x+p,N=u+y;window.scrollTo({behavior:c,left:x,top:u}),c!=="instant"&&triggerRipple(S,M,N,"typst-jump-ripple","typst-jump-ripple-effect .4s linear"),d(E,n,s);return}};function triggerRipple(t,e,n,s,r){const c=document.createElement("div");c.className=s,c.style.left=`${e}px`,c.style.top=`${n}px`,t.appendChild(c),c.style.animation=r,c.onanimationend=()=>{t.removeChild(c)}}var scriptTag=document.currentScript;if(scriptTag){console.log("new svg util updated 37 ",performance.now());const t=findAncestor(scriptTag,"typst-doc");t&&window.typstProcessSvg(t)}

0 comments on commit 4be652e

Please sign in to comment.