UNPKG

@exlinep/router

Version:
179 lines (148 loc) 4.15 kB
import { generatePath, MatchInterface, matchPath } from '../workWithPathRegexp'; import { Page } from './Page'; import { RouteList } from './Router'; import { PageParams } from './Types'; /** * @ignore */ export const POPUP_KEY = 'p'; /** * @ignore */ export const MODAL_KEY = 'm'; let routeUniqueId = 1; function getNextUniqId() { return routeUniqueId++; } function searchParamsToObject(searchParams: URLSearchParams): {} { const obj: { [key: string]: string } = {}; for (const [key, value] of searchParams) { obj[key] = value; } return obj; } export class Route { /** * @type {Page} */ structure: Page; pageId: string; params: PageParams = {}; uniqId: number; constructor(structure: Page, pageId: string, params: PageParams) { this.structure = structure; this.pageId = pageId; this.params = params; this.uniqId = getNextUniqId(); } static getParamsFromPath(location: string) { if (location.includes('?')) { const [, qs] = location.split('?', 2); return searchParamsToObject(new URLSearchParams(qs)); } else { return {}; } } /** * @param {RouteList} routeList * @param location "info?w=about&show=1" то, что лежит в window.location.hash * @param noSlash */ static fromLocation(routeList: RouteList, location: string, noSlash = true) { const params = Route.getParamsFromPath(location); location = location.replace('#', ''); if (noSlash && location.length && !location.startsWith('/')) { location = `/${location}`; } if (noSlash && !location.length) { location = `/${location}`; } location = location.split('?', 2).shift() || (noSlash ? '/' : ''); let match: null | MatchInterface = null; for (let pageId in routeList) { if (routeList.hasOwnProperty(pageId)) { match = matchPath(location, pageId); if (match && match.isExact) { break; } } } if (!match) { throw new Error('ROUTE_NOT_FOUND'); } const ps = routeList[match.path]; if (!ps) { throw new Error(`Router fail: cant find structure in routes for ${location}`); } return new Route(ps, match.path, { ...params, ...match.params }); } static fromPageId(routeList: RouteList, pageId: string, params?: PageParams) { const ps = routeList[pageId]; if (!ps) { throw new Error(`Router fail: cant find structure in routes for ${pageId}`); } return new Route(ps, pageId, params || {}); } clone(): Route { const copy = new Route(this.structure.clone(), this.pageId, { ...this.params }); copy.uniqId = this.uniqId; return copy; } getLocation() { return generatePath(this.pageId, this.params); } getPageId() { return this.pageId; } getPanelId(): string { if (this.structure.isInfinityPanel) { return `_${this.structure.panelId}..${String(this.uniqId)}`; } return this.structure.panelId; } getPanelIdWithoutInfinity(): string { return this.structure.panelId; } getViewId() { return this.structure.viewId; } getRootId() { return this.structure.rootId; } getParams(): PageParams { return this.params; } setParams(params: PageParams = {}): Route { this.params = { ...this.params, ...params }; return this; } isPopup(): boolean { return !!this.getPopupId(); } getPopupId(): string | null { return this.params[POPUP_KEY]?.toString() || null; } setPopupId(popupId: string): Route { this.params[POPUP_KEY] = popupId; return this; } isModal(): boolean { return !!this.getModalId(); } hasOverlay() { return this.isModal() || this.isPopup(); } getModalId(): string | null { return this.params[MODAL_KEY]?.toString() || null; } setModalId(modalId: string): Route { this.params[MODAL_KEY] = modalId; return this; } out() { // $TSFixMe } in() { // $TSFixMe } }