doz-router
Version:
The doz router
2 lines (1 loc) • 8.02 kB
JavaScript
import{mixin as t}from"doz";const e={ROUTE:/route(?:\s+)?=(?:\s+)?"(.*?)"/,CHANGE:/route-change(?:\s+)?=(?:\s+)?"(.*?)"/,IS_PRESERVE:/\spreserve[>\s=]/},i="*",s="___doz_router___hashchangeListener",r="___doz_router___popstateListener",n="___doz_router___DOMContentLoadedListener",o="__DOZ_PRERENDER_PUBLIC_URL__",h="__DOZ_SSR_PATH__";function a(t){const e={};if(!t)return e;const i=t.split("&");for(let t=0,s=i.length;t<s;t++){const s=i[t].split("=");if(s.length){e[s.splice(0,1)[0]]=decodeURIComponent(s.join("="))}}return e}function l(t){return t.toString().replace(/\/+$/,"").replace(/^\//,"")}function u(t){return t.replace(/\/{2,}/g,"/")}function c(t,e){console.warn("[DEPRECATION]",`"${t}" is deprecated use "${e}" instead`)}var p={name:"doz-router",suspendContent:!0,props:{hash:"#",classActiveLink:"router-link-active",linkAttr:"data-router-link",isLinkAttr:"data-is-router-link",mode:"hash",root:"/",initialRedirect:""},autoCreateChildren:!1,onBeforeCreate(){let t=location.search.split("?");t[1]?(this._query=a(t[1]),this._queryRaw=t[1]):(this._query={},this._queryRaw="")},onCreate(){this._currentView=null,this._currentViewRaw="",this._currentFullPath=null,this._currentPath=null,this._routes=[],this._paramMap={},this._param={},this._routeNotFound="",this._link={},this._pauseHashListener=!1,this._noDestroy=this.props.hasOwnProperty("noDestroy"),this._noDestroyedInstances={},this._lastUrl="","function"==typeof t&&t({router:this}),this._LS_LAST_PATH=this.props.initialRedirectLastKeyName||"dozRouterLastPath",this.props.hasOwnProperty("initialRedirectLast")&&window.localStorage&&window.localStorage.getItem(this._LS_LAST_PATH)&&(this._lastUrl=window.localStorage.getItem(this._LS_LAST_PATH))},removeView(){if(this._currentView){if(this._noDestroy){let t=this._currentView.unmount();this._noDestroyedInstances[t.rawChildren[0]]=t}else this._currentView.destroy();this._currentView=null,this.flushDeadLink()}},setView(t,e,i){const s=this._currentViewRaw===t;if(e&&s){let t=this._currentView.children[0],i=t[e];"function"==typeof i&&i.call(t,this)}else if(i&&s)this.inject?this._currentView.render():this._currentView.children[0].render();else if(this.inject){if(this._currentViewSymbol){if(this._noDestroy){let t=this._currentView.unmount();this._noDestroyedInstances[t.rawChildren[0]]=t}else this.eject(this._currentViewSymbol);this._currentView=null,this.flushDeadLink()}"string"==typeof t&&(t=this.h`<span>${t}</span>`),this._currentViewSymbol=null,this._currentView=this._noDestroy&&this._noDestroyedInstances[t]?this._noDestroyedInstances[t].mount():this.inject(t),this._currentView.cmp&&(this._currentViewSymbol=this._currentView.cmp,this._currentView=this._currentView.cmp)}else this.removeView(),this._currentView=this._noDestroy&&this._noDestroyedInstances[t]?this._noDestroyedInstances[t].mount():this.mount(t);this._currentViewRaw=t},query(t){return this._query[t]},param(t){return this._param[t]},navigate(t,e,i){if("history"===this.props.mode){if(window[o])history.pushState(t,null,u(window[o].replace(location.origin,"")+t));else{if(i)return history.replaceState(t,null,u(this.props.root+t));history.pushState(t,null,u(this.props.root+t))}this._navigate(t,e)}else this._pauseHashListener=!0,window.location.href=this.props.hash+t,this._navigate(t,e),this._pauseHashListener=!1},currentPath(t=!0){return t?this._currentFullPath:this._currentPath},$query(t){return c("$query","query"),this.query(t)},$param(t){return c("$param","param"),this.param(t)},$navigate(...t){c("$navigate","navigate"),this.navigate.apply(this,t)},$currentPath(...t){return c("$currentPath","currentPath"),this.currentPath.apply(this,t)},_navigate(t,e,i=!1){let s,r=!1,n=window.location.hash.slice(this.props.hash.length),c=window.location.pathname+window.location.search,p=t;if(t=t||n,"history"===this.props.mode&&(t=c),!window[o]&&!window[h]){if(("/"===p||""===p||null===p)&&i&&this._lastUrl){let t=this._lastUrl;if(this.props.root&&t){let e=this.props.root.replace(/\//g,"\\/");t=t.replace(new RegExp("^"+e,""),"")}return this.navigate(t)}if(("/"===t||""===t)&&i&&this.props.initialRedirect)return this.navigate(this.props.initialRedirect)}t=window[h]||t,window[o]&&(t=(location.origin+t).replace(window[o],"")),s=t=this.electronFixer(t);let _,d=t.split("?");if(t=l(d[0]),this._currentFullPath===s)return!1;this._queryRaw=d[1]||"",("/"===t||""===t)&&i&&this.props.initialRedirect&&(t=u(l(this.props.root)+this.props.initialRedirect));for(let i=0;i<this._routes.length;i++){let n=this._routes[i];_="*"===n.path?t?new RegExp(".+"):new RegExp("^$"):new RegExp("^/?"+n.path+"$");let o=t.match(_);if(o){if(r=!0,e&&"object"==typeof e)this._param=Object.assign({},e);else{let t=this._paramMap[n.path];this._query=a(this._queryRaw),o.slice(1).forEach(((e,i)=>{this._param[t[i]]=e}))}this._currentPath=t,this._currentFullPath=s,this.setView(n.view,n.cb,n.preserve),window.localStorage&&window.localStorage.setItem(this._LS_LAST_PATH,s);break}}return r||(this._currentPath=null,this._currentFullPath=null,this.setView(this._routeNotFound||`"${t}" not found`)),this.activeLink(),r},activeLink(){Object.keys(this._link).forEach((t=>{const e=Boolean(this._link[t].size>1&&this._queryRaw);this._link[t].forEach((i=>{let s=!0;e&&(s=new RegExp(`${this._queryRaw}$`,"g").test(i.href)),t=this.electronFixer(t);let r=!1;if(void 0!==i.dataset.routerLinkRadix&&t&&this._currentPath){let e=t.split("/"),i=this._currentPath.split("/");r=e[0]===i[0]}(t===this._currentPath||r)&&s?i.classList.add(this.props.classActiveLink):i.classList.remove(this.props.classActiveLink)}))}))},electronFixer:t=>("file:"===location.protocol&&t.includes(":")&&(t=t.substr(3)),t),add(t,s){if(t===i)this._routeNotFound=s;else{let i=[],r=l(t);r=r.replace(/:(\w+)/g,((t,e)=>(i.push(e),"([\\w-]+)"))),r=r.replace(/\/\*/g,"(?:/.*)?"),this._paramMap[r]=i;let n=null,o=!1;"string"==typeof s?(n=s.match(e.CHANGE),o=e.IS_PRESERVE.test(s)):(n=s.props["route-change"],o=s.props.preserve),n&&(n=n[1]),""===o&&(o=!0),this._routes.push({path:r,view:s,cb:n,preserve:o})}},remove(t){for(let e=0;e<this._routes.length;e++){this._routes[e].path===l(t)&&this._routes.splice(e,1)}},checkIfAlreadyRootExists(){},bindLink(){window.document.querySelectorAll(`[${this.props.linkAttr}]`).forEach((t=>{if(t.dataset.isRouterLink&&"history"!==this.props.mode)return;let e=t.pathname||t.href;if(t.dataset.isRouterLink="true","history"===this.props.mode){void 0===t.dataset.routerAnchorLink&&(t.pathname?e=t.pathname=u(this.props.root+t.pathname):t.href&&(e=t.href=u(this.props.root+t.href)));let i=e+t.search;t.dataset.routerPath=i,window[o]||t.dataset.routerListener||(t.addEventListener("click",(e=>{e.preventDefault();let i=t.dataset.routerPath;history.pushState(i,null,i),this._navigate(i)})),t.dataset.routerListener="true")}else t.href=this.props.hash+e+t.search;let i=e.split("?");e=l(i[0]),void 0===this._link[e]?(this._link[e]=new Set,this._link[e].add(t)):this._link[e].has(t)||this._link[e].add(t)}))},flushDeadLink(){Object.keys(this._link).forEach((t=>{this._link[t]&&this._link[t].forEach((e=>{e.isConnected||this._link[t].delete(e)}))}))},init(){window.removeEventListener("popstate",window[r]),window[r]=t=>{let e=t.state;if(null==e&&this.props.initialRedirect)return this.navigate(this.props.initialRedirect,{},!0);this._navigate(e)},window.removeEventListener("hashchange",window[s]),window[s]=()=>{this._pauseHashListener||this._navigate()},window.removeEventListener("DOMContentLoaded",window[n]),window[n]=()=>{this._navigate(null,null,!0)},this.rawChildrenObject&&this.rawChildrenObject.length?this.rawChildrenObject.forEach((t=>{if(!t||"object"!=typeof t)return;let e=t.props.route;e&&this.add(e,t)})):this.rawChildren.forEach((t=>{let i=t.match(e.ROUTE);i&&this.add(i[1],t)})),this.bindLink(),"history"===this.props.mode?window.addEventListener("popstate",window[r]):window.addEventListener("hashchange",window[s]),window.addEventListener("DOMContentLoaded",window[n])},onAppReady(){this.init()},onMountAsync(){this._navigate(null,null,!0)}};export{p as default};