import * as plugins from './smartrouter.plugins'; const routeLog = message => { console.log(`%c[Router]%c ${message}`, 'color: rgb(255, 105, 100);', 'color: inherit'); }; export interface IRouterOptions { debug?: boolean; } /** * Router */ export class SmartRouter { public options: IRouterOptions = { debug: false }; /** * the routes we are handling */ public routes: Array<{ matchFunction: plugins.pathToRegExp.MatchFunction; handler: (matchArg: plugins.pathToRegExp.Match) => Promise; }> = []; /** * Creates an instance of Router. */ constructor(optionsArg: IRouterOptions) { // lets set the router options this.options = { ...this.options, ...optionsArg }; // lets subscribe to route changes window.addEventListener('popstate', popStateEventArg => { popStateEventArg.preventDefault(); this._handleRouteState(); }); window.addEventListener('DOMContentLoaded', () => { this._handleRouteState(); }); } /** * Push route state to history stack */ public async pushUrl(url: string = '/', state: any = {}) { if (url !== window.location.pathname) { window.history.pushState(state, window.document.title, url); } else { window.history.replaceState(state, window.document.title, url); } await this._handleRouteState(); } /** * Attach route with handler * @param {string|RegExp} routeArg * @param {function} handlerArg */ public on(routeArg: string, handlerArg: () => Promise) { this.routes.push({ matchFunction: plugins.pathToRegExp.match(routeArg), handler: handlerArg }); } /** * Apply routes handler to current route */ async _handleRouteState() { const currentLocation = window.location.pathname; const wantedRoute = this.routes.find(routeArg => { return !!routeArg.matchFunction(currentLocation); }); if (wantedRoute) { const routeResult = wantedRoute.matchFunction(currentLocation); await wantedRoute.handler(routeResult); } } }