UNPKG

@xan105/vanilla-router

Version:

Simple Vanilla JS router based on the Navigation API and URLPattern API

2 lines (1 loc) 3.88 kB
function h(){[...document.head.querySelectorAll('meta[property^="og:"]'),...document.head.querySelectorAll('meta[property^="article:"]'),...document.head.querySelectorAll('meta[property^="book:"]'),...document.head.querySelectorAll('meta[property^="profile:"]'),...document.head.querySelectorAll('meta[property^="video:"]'),...document.head.querySelectorAll('meta[property^="music:"]'),...document.head.querySelectorAll('link[rel^="canonical"]')].forEach(o=>document.head.removeChild(o))}function p(o){if(!Array.isArray(o))return;let e=["og: https://ogp.me/ns/#"];h();for(let{name:t,content:r,details:a}of o){switch(t){case"title":{document.title=r;break}case"description":{let n=document.head.querySelector(`meta[name="${t}"]`)??document.head.appendChild(document.createElement("meta"));n.setAttribute("name",t),n.setAttribute("content",r);break}case"url":{let n=document.head.querySelector('link[rel="canonical"]')??document.head.appendChild(document.createElement("link"));n.setAttribute("rel","canonical"),n.setAttribute("href",r);break}case"type":{let n=`${r}: https://ogp.me/ns/${r}#`;e.push(n);break}}let i=document.createElement("meta");i.setAttribute("property","og:"+t),i.setAttribute("content",r),document.head.appendChild(i);for(let[n,c]of Object.entries(a??{})){let l=Array.isArray(c)?c:[c];for(let d of l){let s=document.createElement("meta");if(t==="type"){let[m]=r.split(".");s.setAttribute("property",m+":"+n)}else s.setAttribute("property","og:"+t+":"+n);s.setAttribute("content",d),document.head.appendChild(s)}}}document.head.setAttribute("prefix",e.join(" "))}var u=class extends EventTarget{#e;#t;constructor(e={}){super(),this.#e=Object.create(null),this.#t=Symbol("404"),this.autoFire=e?.autoFire??!0,this.sensitive=e?.sensitive??!0,this.autoFocus=e?.autoFocus??!0,this.autoScroll=e?.autoScroll??!0,this.deferredCommit=e?.deferredCommit??!1}get routes(){return Reflect.ownKeys(this.#e)}get current(){return navigation.currentEntry}get history(){return navigation.entries()}back(){if(navigation.canGoBack)return navigation.back()}forward(){if(navigation.canGoForward)return navigation.forward()}navigate(e,t){return navigation.navigate(e,t)}on(e,t,r={}){return typeof t!="function"?this:(typeof e=="string"&&e.length>0?this.#e[e]={handler:t,options:r}:e===404&&(this.#e[this.#t]={handler:t,options:r}),this)}off(e){return typeof e=="string"&&e.length>0?delete this.#e[e]:e===404&&delete this.#e[this.#t],this}#r(e){if(this.sensitive===!0&&Object.hasOwn(this.#e,e))return this.#e[e];for(let[t,{handler:r,options:a}]of Object.entries(this.#e)){let n=new URLPattern({pathname:t},{ignoreCase:this.sensitive===!1}).exec({pathname:e});if(n)return{handler:r,options:a,param:n.pathname.groups}}return this.#e[this.#t]}listen(){return navigation.addEventListener("navigateerror",e=>{let t=new URL(e.currentTarget.currentEntry.url);this.dispatchEvent(new CustomEvent("error",{detail:{error:e.message,url:t}}))}),navigation.addEventListener("navigatesuccess",e=>{let t=new URL(e.currentTarget.currentEntry.url);this.dispatchEvent(new CustomEvent("did-navigate",{detail:{url:t}}))}),navigation.addEventListener("navigate",e=>{if(!e.canIntercept||e.hashChange||e.downloadRequest!==null||e.formData)return;let t=new URL(e.destination.url),{handler:r,options:a,param:i}=this.#r(t.pathname)??{};if(!r){this.dispatchEvent(new CustomEvent("error",{detail:{error:"No handler found !",url:t}}));return}this.dispatchEvent(new CustomEvent("will-navigate",{detail:{url:t}})),e.intercept({focusReset:(a?.autoFocus??this.autoFocus)===!0?"after-transition":"manual",scroll:(a?.autoScroll??this.autoScroll)===!0?"after-transition":"manual",commit:(a?.deferredCommit??this.deferredCommit)===!0?"after-transition":"immediate",handler:r.bind(this,e,t,i??{})})}),this.autoFire===!0&&this.navigate(location.pathname,{history:"replace"}),this}};export{u as Router,p as updateMetadata};