neotoc
Version:
Neotoc is a smoothly animated, foldable table of contents generator.
3 lines (2 loc) • 14.3 kB
JavaScript
function t(t){if(t===document.documentElement)return[0,t.clientHeight];const e=t.getBoundingClientRect().y+t.clientTop;return[e,e+t.clientHeight]}function e([l,o],n){const[i,r]=t(n);let d=null,s=null;return null===l?[l,o]:(l<=i?o>i&&(d=i):l<r&&(d=l),o<=r?o>i&&(s=o):l<r&&(s=r),n===document.documentElement?[d,s]:e([d,s],n.parentElement))}function l(l,o,n){const[i,r]=t(l),[d,s]=[i+o,r-n],a=l.parentElement;return a?e([d,s],a):[d,s]}function o(t,e){let l=t.parentElement.parentElement.parentElement;return"A"===t.tagName&&(l=l.parentElement),l.classList.contains(e)?l:null}function n(t,e){let l=e;for(let e=0;e<t.length;e++){const o=t[e].getBoundingClientRect().bottom;o<l&&(l=o)}return l}function i(t,e,l){for(let o=0;o<e.length;o++){const n=e[o];if(l.get(n).includes(t))return!0}return!1}function r(t,e){const l=t.scrollTop;return[l+e,l+t.clientHeight-e]}function d(t,e,l){const o=l?30:-30,n=l?.5:-.5;for(let i=0;(l?i<o:i>o)&&(t.scrollTop=e+i,!(l?t.scrollTop>=e:t.scrollTop<=e));i+=n);}function s(t,e,l){if(l.isScrolling){const n=()=>{const e=l.motorcycleScrollingStartScrollTop+l.scrollNeeded;let o=!0;l.scrollNeeded>0?o=!0:l.scrollNeeded<0&&(o=!1),d(t,e,o),l.isScrolling=!1},i=t.scrollTop;l.timeFrac=(e-l.motorcycleScrollingStartTime)/300,l.timeFrac>1&&(l.timeFrac=1);const r=l.scrollNeeded*(o=l.timeFrac,1-Math.pow(1-o,3));null===l.lastAutoScrollTop||l.lastAutoScrollTop===i?(t.scrollTop=l.motorcycleScrollingStartScrollTop+r,l.lastAutoScrollTop=t.scrollTop):(l.isScrolling=!1,l.lastAutoScrollTop=null),1==l.timeFrac&&n()}var o}function a(t){return`calc(calc(var(--toggle-fold-btn-width) / 2) * pow(calc(100 / var(--relative-font-size)), ${t}) + calc(var(--indent-line-width) / 2))`}function c(t){return`calc(var(--max-indent-width) - ${a(t)})`}function u({io:t,to:e,title:u="On this page",fillAnchor:p=t=>t.textContent,onBreadcrumbChange:g=()=>{},ellipsis:m=!1,classPrefix:h="nt-",initialFoldLevel:f=6,offsetTop:w=0,offsetBottom:v=0,autoFold:T=!1,autoScroll:b=!0,autoScrollOffset:y=50,toggleFoldIcon:q='<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 16 16"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M3.75 5.75L8 10.25l4.25-4.5"/></svg>',unfoldableIcon:F='<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><circle cx="12.1" cy="12.1" r="1" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2.65"/></svg>',foldIcon:B='<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="m12 16.9l-2.4 2.4q-.275.275-.7.275t-.7-.275t-.275-.7t.275-.7l3.1-3.1q.15-.15.325-.212t.375-.063t.375.063t.325.212l3.1 3.1q.275.275.275.7t-.275.7t-.7.275t-.7-.275zm0-9.8l2.4-2.4q.275-.275.7-.275t.7.275t.275.7t-.275.7l-3.1 3.1q-.15.15-.325.213T12 9.475t-.375-.062T11.3 9.2L8.2 6.1q-.275-.275-.275-.7t.275-.7t.7-.275t.7.275z"/></svg>',foldAllIcon:L='<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M12.025 20.8L9.55 23.25q-.275.275-.687.288t-.713-.288q-.275-.275-.275-.7t.275-.7l3.175-3.175q.15-.15.325-.213t.375-.062t.375.063t.325.212L15.9 21.85q.275.275.275.688t-.275.712q-.3.3-.712.3t-.713-.3zm0-5L9.55 18.25q-.275.275-.687.288t-.713-.288q-.275-.275-.275-.7t.275-.7l3.175-3.175q.15-.15.325-.213t.375-.062t.375.063t.325.212L15.9 16.85q.275.275.275.688t-.275.712q-.3.3-.712.3t-.713-.3zm0-7.65l2.45-2.45q.3-.3.713-.3t.712.3t.3.7t-.3.7l-3.175 3.2q-.15.15-.325.213t-.375.062t-.375-.062t-.325-.213l-3.2-3.2q-.3-.3-.288-.712t.313-.713t.713-.3t.712.3zm0-5L14.475.7q.3-.3.713-.3t.712.3t.3.7t-.3.7l-3.175 3.2q-.15.15-.325.213t-.375.062t-.375-.062t-.325-.213l-3.2-3.2q-.3-.3-.288-.712T8.15.675t.713-.3t.712.3z"/></svg>',unfoldIcon:S='<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="m12 18.1l2.325-2.325q.3-.3.725-.3t.725.3t.3.725t-.3.725L12.7 20.3q-.15.15-.325.213t-.375.062t-.375-.062t-.325-.213l-3.075-3.075q-.3-.3-.3-.725t.3-.725t.725-.3t.725.3zM12 6L9.675 8.325q-.3.3-.725.3t-.725-.3t-.3-.725t.3-.725L11.3 3.8q.15-.15.325-.213T12 3.526t.375.063t.325.212l3.075 3.075q.3.3.3.725t-.3.725t-.725.3t-.725-.3z"/></svg>',unfoldAllIcon:E='<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="m12.025 21.15l2.475-2.475q.3-.3.7-.288t.7.313q.275.3.287.7t-.287.7l-3.175 3.175q-.15.15-.325.213t-.375.062t-.375-.062t-.325-.213L8.15 20.1q-.275-.275-.288-.687t.288-.713q.275-.275.7-.275t.7.275zm0-5l2.475-2.475q.3-.3.7-.287t.7.312q.275.3.287.7t-.287.7l-3.175 3.175q-.15.15-.325.213t-.375.062t-.375-.062t-.325-.213L8.15 15.1q-.275-.275-.288-.687t.288-.713q.275-.275.7-.275t.7.275zm0-8.325L9.55 10.3q-.3.3-.712.288t-.713-.313t-.3-.712t.3-.713l3.2-3.175q.15-.15.325-.213t.375-.062t.375.062t.325.213l3.175 3.2q.3.3.3.7t-.3.7t-.713.3t-.712-.3zm0-5L9.55 5.3q-.3.3-.712.288t-.713-.313t-.3-.712t.3-.713l3.2-3.175q.15-.15.325-.212T12.025.4t.375.063t.325.212l3.175 3.2q.3.3.3.7t-.3.7t-.713.3t-.712-.3z"/></svg>'}){function x(t,e){const l=document.createElement(t);return e&&(l.className=h+e),l}function A(t,e){t.classList.add(h+e)}function M(t,e){t.classList.toggle(h+e)}T&&(f=1);const C=[],$={startTime:0,duration:1e3,on:!1},k={startTime:0,duration:1e3,lastTop:0,on:!1};let I=0,N=0;const H={},z={},R=new Map,U=new Map,P=new Map,[V,j,D]=t.split(">>").map((t=>t.trim()));const O=document.querySelectorAll(`${V} :is(${"h*"==j?"h1,h2,h3,h4,h5,h6":j})`),G=O.length>0?+O[0].tagName[1]:0;function J(t,e){for(let l=0;l<C.length;l++){const{isFolded:o,level:n,toggleFold:i}=C[l];t?!o&&n>=e&&(i(),T&&(C[l].isManuallyToggledFoldInAutoFold=!0)):o&&n<=e&&(i(),T&&(C[l].isManuallyToggledFoldInAutoFold=!0))}Q()}let K;function Q(){const t=C[0].isFolded;let e,l=!0;for(let e=1;e<C.length;e++)C[e].isFolded!=t&&(l=!1);var o;e=l?t?"allFolded":"allUnfolded":"mixed",e!=K&&(K=e,"allFolded"==(o=e)?(it.disabled=!0,dt.disabled=!1,nt.disabled=!0,rt.disabled=!1):"allUnfolded"==o?(it.disabled=!1,dt.disabled=!0,nt.disabled=!1,rt.disabled=!0):"mixed"==o&&(it.disabled=!1,dt.disabled=!1,nt.disabled=!1,rt.disabled=!1))}function W(){let t,e;for(let l=0;l<C.length;l++){const{isFolded:o,level:n}=C[l];o?e?n<e&&(e=n):e=n:t?n>t&&(t=n):t=n}return[e,t]}const X=function t(e){if(!e.length)return;const l=x("ul");for(let o=0;o<e.length;o++){const n=e[o],i=x("li"),r=x("a","a"),d=x("div","non-foldable");r.href=`#${n.id}`,r.append(p(n)),z[`#${n.id}`]=n;const s=n.textContent.trim().replace(/\s+/g," ");m&&(A(r,"ellipsis"),d.title=s),d.append(r),i.append(d),H[n.id]=r;const u=[],g=+n.tagName[1];I&&N?(g<I&&(I=g),g>N&&(N=g)):I=N=g;for(let t=o+1;t<e.length&&+e[t].tagName[1]>g;t++)u.push(e[t]);const w=g-G;if(u.length>0){const e=t(u),l=x("div","toggle-fold-btn"),o=x("div","foldable"),n=x("hr","fold-indicator-line"),s=g>=f;s&&A(o,"foldable-folded"),l.tabIndex=0,l.role="button",l.ariaPressed=s?"true":"false",l.ariaExpanded=s?"false":"true",l.ariaLabel="Toggle fold",l.title="",l.innerHTML=q,l.classList.add(h+`level-${w+1}`);const a="toggle-fold-btn-folded",c="opacity-1";s&&(A(l,a),A(n,c)),d.prepend(l),d.append(n),o.append(e),i.append(o);const p={isFolded:s,level:g,toggleFold(){p.isFolded=!p.isFolded,l.ariaPressed=p.isFolded?"true":"false",l.ariaExpanded=p.isFolded?"false":"true",M(o,"foldable-folded"),M(l,a),M(n,c),p.isFolded&&($.on=!0),Q()},foldableDiv:o,anchor:r,isManuallyToggledFoldInAutoFold:!1};C.push(p);const m=()=>{T&&(p.isManuallyToggledFoldInAutoFold=!0),p.toggleFold()};l.addEventListener("click",(()=>{m()})),l.addEventListener("keydown",(t=>{"Enter"!=t.key&&" "!=t.key||(" "==t.key&&t.preventDefault(),m())}))}else{const t=x("div","unfoldable-icon");t.innerHTML=F,d.prepend(t)}let v="",b="";for(let t=1;t<=w;t++){const e=x("div","indent-block");d.prepend(e),v=`${a(t)} ${t==w?"":c(t)} var(--indent-line-gap) ${v}`,b=`calc(${a(t)} ${t==w?"":`+ ${c(t)}`} + var(--indent-line-gap)) ${b?`+ ${b}`:""}`}d.style.cssText=`--max-indent-width: ${a(w)}; grid-template-columns: ${v} var(--toggle-fold-btn-width) 1fr`,b=`calc(${b?`${b} + `:""}var(--toggle-fold-btn-width) + var(--anchor-padding-inline))`,r.style.paddingLeft=b,l.append(i),o+=u.length}return l}(O);if(!X)return()=>{};const Y=D?document.querySelector(D):e;if(!Y)throw new Error("Nothing was found to append Neotoc to!");const Z=x("div","widget"),_=x("div","body"),tt=x("div","header"),et=x("h2","title"),lt=x("div","btn-group"),ot="header-btn",nt=x("button",ot),it=x("button",ot),rt=x("button",ot),dt=x("button",ot),st=x("div","top-gradient"),at=x("div","bottom-gradient");_.style.position="relative",_.ariaLabel=u,_.tabIndex=0,nt.innerHTML=B,it.innerHTML=L,rt.innerHTML=S,dt.innerHTML=E;const ct=["Fold one level","Fold all","Unfold one level","Unfold all"];if(nt.ariaLabel=ct[0],nt.title=ct[0],it.ariaLabel=ct[1],it.title=ct[1],rt.ariaLabel=ct[2],rt.title=ct[2],dt.ariaLabel=ct[3],dt.title=ct[3],C.length){N-I>1?lt.append(nt,rt,it,dt):lt.append(nt,rt),Q()}et.innerHTML=u,tt.append(et,lt),_.append(X,st,at),Z.append(tt),Z.append(_),Y.append(Z);const ut=+getComputedStyle(_).paddingTop.slice(0,-2)+ +getComputedStyle(_).paddingBottom.slice(0,-2);function pt(){const t=_.scrollTop,e=_.scrollHeight-_.clientHeight;st.style.top=t+"px",at.style.bottom=-t+"px",st.style.opacity=t>5?"1":"0",at.style.opacity=t+5<e?"1":"0"}pt(),X.querySelectorAll("a").forEach((t=>{const[e,l]=function(t,e,l){const n=[],i=[],r=l+e;let d=o(t,r);for(;d;)n.push(d),i.push(d.previousSibling.lastChild.previousSibling),d=o(d,r);return[n,i]}(t,"foldable",h);R.set(t,e),U.set(t,l),P.set(t,[...l.reverse(),t].map((t=>({content:p(z[t.getAttribute("href")]),hash:t.hash}))))}));const gt=document.querySelector(V);let mt;const ht={isScrolling:!1,wasTopEndAboveTopBoundary:null,wasBottomEndBelowBottomBoundary:null,timeFrac:0,scrollNeeded:0,motorcycleScrollingStartScrollTop:0,motorcycleScrollingStartTime:0,lastAutoScrollTop:null},ft=function(t){let e=t.parentElement;for(;e;){const{overflow:t}=window.getComputedStyle(e);if(t.split(" ").every((t=>"auto"===t||"scroll"===t)))return e;e=e.parentElement}return document.documentElement}(gt),wt=function(t,e,l,o,n){const i=e("div","light-bar"),r=e("div","light-bar-top"),d=e("div","light"),s=e("div","light-bar-bottom");i.append(r,d,s),i.style.position="absolute",i.style.display="none",t.append(i);let a=[];const c="on-fold",u="enlightend-a";return t=>{if(t.isVisible){const{top:e,height:d,isTopInAFold:p,isBottomInAFold:g,anchors:m}=t;i.style.display="",i.style.top=`${e}px`,i.style.height=`${d}px`,p?l(r,c):o(r,c),g?l(s,c):o(s,c),a.forEach((t=>{m.includes(t)||o(t,u)})),m.forEach((t=>{n(t,u)||l(t,u)})),a=m}else i.style.display="none",a.forEach((t=>o(t,u)))}}(_,x,A,(function(t,e){t.classList.remove(h+e)}),(function(t,e){return t.classList.contains(h+e)}));let vt=null,Tt=null,bt=null,yt=null,qt=null,Ft=null,Bt=null,Lt=null,St=null;const Et=t=>{((Bt!==bt||Lt!==yt)&&Ft!==Tt||qt!==vt)&&t()},xt=t=>{const[e,o]=l(ft,w+1,v),a=[];let c=null,u=null,p=null;const m=()=>{T&&function(t,e,l,o){for(let n=0;n<t.length;n++){const{anchor:r,isFolded:d,toggleFold:s}=t[n],a=!t[n].isManuallyToggledFoldInAutoFold,c=()=>{t[n].isManuallyToggledFoldInAutoFold=!1},u=()=>{a&&s()},p=()=>{d?c():u()};if(e.length){const t=i(r,e,l);e.includes(r)||t?d?(u(),t&&(o.on=!0)):c():p()}else p()}}(C,a,U,k)};for(let t=0;t<O.length;t++){const l=O[t],n=O[t+1],i=l.getBoundingClientRect().top,r=n?n.getBoundingClientRect().top:gt.getBoundingClientRect().bottom,d=r-i;if(null!==e)if(i<e){if(r>e){const t=(Math.min(r,o)-e)/d;c?u=t:c=t,a.push(H[l.id]),null===p&&(p=(e-i)/d)}}else if(i<o){const t=(Math.min(r,o)-i)/d;c?u=t:c=t,a.push(H[l.id]),null===p&&(p=0)}}if(a.length){const l=a[0],i=l.parentElement.getBoundingClientRect(),h=i.top+i.height*p;let f=h+i.height*c;const w=R.get(l),v=n(w,h);let T=n(w,f);if(a.length>1){const t=a[a.length-1],e=t.parentElement.getBoundingClientRect();f=e.top+e.height*u,T=n(R.get(t),f)}const q=_.getBoundingClientRect().top,F=_.scrollTop,B=_.clientTop;qt=null===e?null:o-e;const L=v+F-q-B,S=T+F-q-B;Ft=ft.scrollTop,Bt=Math.round(h+F-q-B),Lt=Math.round(f+F-q-B),Et((()=>{const e=Ft-(Tt||Ft),l=e>0?"down":e<0?"up":"down";m(),b&&(function(t,e,l,o,n){const i=t.scrollTop,[s,a]=r(t,o),c=e<s,u=l>a;null===n.wasTopEndAboveTopBoundary&&(n.wasTopEndAboveTopBoundary=c),null===n.wasBottomEndBelowBottomBoundary&&(n.wasBottomEndBelowBottomBoundary=u),c&&!1===n.wasTopEndAboveTopBoundary&&d(t,i-(s-e),!1);u&&!1===n.wasBottomEndBelowBottomBoundary&&d(t,i+l-a,!0)}(_,L,S,y,ht),function(t,e,l,o,n,i,d){const[s,a]=r(e,n);if(d.isScrolling=!(l>s&&o<a)&&(l===s?"up"!=t&&o>a:o!==a||"down"!=t&&l<s),d.isScrolling){d.scrollNeeded="up"==t?l-s:o-a;const n=e.scrollTop,r=e.scrollHeight-e.clientHeight,c=n+d.scrollNeeded;c<0?d.scrollNeeded=-n:c>r&&(d.scrollNeeded=r-n),d.scrollNeeded||(d.isScrolling=!1),d.timeFrac=0,d.motorcycleScrollingStartTime=i,d.motorcycleScrollingStartScrollTop=n}}(l,_,L,S,y,t,ht))})),b&&(!function(t,e,l,o,n){const[i,d]=r(t,o),s=e<i,a=l>d;n.wasTopEndAboveTopBoundary=s,n.wasBottomEndBelowBottomBoundary=a}(_,L,S,y,ht),s(_,t,ht)),wt({height:T-v,top:L,bottom:S,isTopInAFold:Math.round(v)<Math.round(h),isBottomInAFold:Math.round(T)<Math.round(f),anchors:a,time:t,isVisible:!0}),pt();const E=a[0];if(E!==St){const t=P.get(E);t&&g(t)}k.on&&(0==k.startTime&&(k.startTime=t,k.lastTop=L),_.scrollTop=_.scrollTop+(L-k.lastTop),t-k.startTime>k.duration&&(k.on=!1,k.startTime=0),k.lastTop=L),vt=qt,Tt=Ft,bt=Bt,yt=Lt,St=E}else qt=Ft=Bt=Lt=null,Et((()=>{m()})),wt({isVisible:!1,time:t}),pt(),St&&g([]),vt=Tt=bt=yt=St=null;if($.on){0===$.startTime&&($.startTime=t);const e=_.scrollHeight;let l=_.firstElementChild?.getBoundingClientRect().height;"number"==typeof l&&(l=Math.round(l+ut),0!=_.scrollTop&&(_.scrollTop=_.scrollTop-(e-l))),t-$.startTime>$.duration&&($.on=!1,$.startTime=0)}};let At=0;const Mt=t=>{(0===At||t-At>8)&&(xt(t),At=t),mt=window.requestAnimationFrame(Mt)};return mt=window.requestAnimationFrame(Mt),nt.addEventListener("click",(()=>{const[t,e]=W();t?J(!0,t-1):e&&J(!0,e)})),rt.addEventListener("click",(()=>{const[t]=W();t&&(J(!0,t+1),J(!1,t))})),it.addEventListener("click",(()=>J(!0,1))),dt.addEventListener("click",(()=>J(!1,5))),()=>{Z.remove(),window.cancelAnimationFrame(mt)}}export{u as default};
//# sourceMappingURL=index.js.map