All files matcher.ts

100% Statements 54/54
100% Branches 15/15
100% Functions 4/4
100% Lines 54/54

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 602x     2x 630x 630x 2204x 2204x 2204x 2204x 2256x 2256x 2256x   3339x 3339x 52x 3339x 26x 26x 26x 3313x 3339x 2087x 2087x 2087x 2087x 2087x 2087x 3339x 143x 2256x 2204x 2204x 2204x 630x   727x 727x 727x 727x 727x 2196x 2196x 2196x 2196x 2196x 2196x 2196x 2196x 97x 2098x 2196x 727x 727x   2x 2304x 2304x  
import { compile, match } from 'path-to-regexp';
import type { RouteConfig, RouteMatcher, RouteParsedConfig } from './types';
 
export function createMatcher(routes: RouteConfig[]): RouteMatcher {
    const compiledRoutes = createRouteMatches(routes);
    return (toURL: URL, baseURL: URL) => {
        const matchPath = toURL.pathname.substring(baseURL.pathname.length - 1);
        const matches: RouteParsedConfig[] = [];
        const params: Record<string, string | string[]> = {};
        const collectMatchingRoutes = (
            routes: RouteParsedConfig[]
        ): boolean => {
            for (const item of routes) {
                // Depth-first traversal
                if (
                    item.children.length &&
                    collectMatchingRoutes(item.children)
                ) {
                    matches.unshift(item);
                    return true;
                }
                const result = item.match(matchPath);
                if (result) {
                    matches.unshift(item);
                    if (typeof result === 'object') {
                        Object.assign(params, result.params);
                    }
                    return true;
                }
            }
            return false;
        };
        collectMatchingRoutes(compiledRoutes);
        return { matches: Object.freeze(matches), params };
    };
}
 
function createRouteMatches(
    routes: RouteConfig[],
    base = ''
): RouteParsedConfig[] {
    return routes.map((route: RouteConfig): RouteParsedConfig => {
        const compilePath = joinPathname(route.path, base);
        return {
            ...route,
            compilePath,
            match: match(compilePath),
            compile: compile(compilePath),
            meta: route.meta || {},
            children: Array.isArray(route.children)
                ? createRouteMatches(route.children, compilePath)
                : []
        };
    });
}
 
export function joinPathname(pathname: string, base = '') {
    return '/' + `${base}/${pathname}`.split('/').filter(Boolean).join('/');
}