UNPKG

@eolme/vma-router

Version:
100 lines (99 loc) 2.68 kB
import * as qs from 'querystring'; import { parse as parseToTokens, tokensToRegexp, tokensToFunction } from 'path-to-regexp'; const PATH_CONFIG = { delimiter: '/', end: false, strict: false, sensitive: false }; const cachedPaths = new Map(); const cachedConverts = new Map(); const cacheLimit = 512; let cacheCount = 0; export function parsePage(page) { const cached = cachedPaths.get(page); if (cached) { return cached; } const tokens = parseToTokens(page, PATH_CONFIG); const generator = tokensToFunction(tokens, PATH_CONFIG); if (cacheCount < cacheLimit) { cachedPaths.set(page, [generator, tokens]); cacheCount++; } return [generator, tokens]; } export function buildPage(page, params = {}) { if (page === '/') { return page; } const [generatePath, tokens] = parsePage(page); const path = generatePath(params); const query = { ...params }; tokens.forEach((token) => { if (typeof token === 'object') { delete query[token.name]; } }); return path + '?' + qs.stringify(query); } export function convertPage(page) { const cached = cachedConverts.get(page); if (cached) { return cached; } const tokens = parseToTokens(page, PATH_CONFIG); const keys = []; const regexp = tokensToRegexp(tokens, keys, PATH_CONFIG); const result = { regexp, keys }; if (cacheCount < cacheLimit) { cachedConverts.set(page, result); cacheCount++; } return result; } export function matchPage(page, path) { const { regexp, keys } = convertPage(page); const match = regexp.exec(path); if (!match) { return null; } const [url, ...values] = match; const params = keys.reduce((acc, key, index) => { if (typeof key === 'object') { acc[key.name] = values[index]; } return acc; }, {}); const uri = page === '/' && url === '' ? '/' : url; const exact = path === url; return { uri, exact, params }; } export function parsePath(path) { if (!path.includes('?')) { return { url: path, params: {} }; } const [url, query] = path.split('?', 2); if (!query) { return { url, params: {} }; } return { url, params: qs.parse(query) }; } export function preventScrollRestoration() { if (window.history.scrollRestoration) { window.history.scrollRestoration = 'manual'; } }