svelte-router-spa
Version:
A full featured router component for Svelte and your Single Page Applications.
147 lines (125 loc) • 4.93 kB
JavaScript
import { UrlParser } from './url_parser.js';
import { RouterRedirect } from './redirect.js';
import { RouterRoute } from './route.js';
import { RouterPath } from './path.js';
import { anyEmptyNestedRoutes, pathWithoutQueryParams, startsWithNamedParam } from '../lib/utils.js';
const NotFoundPage = '/404.html';
function RouterFinder({ routes, currentUrl, routerOptions, convert }) {
const defaultLanguage = routerOptions.defaultLanguage;
const sitePrefix = routerOptions.prefix ? routerOptions.prefix.toLowerCase() : '';
const urlParser = parseCurrentUrl(currentUrl, sitePrefix);
let redirectTo = '';
let routeNamedParams = {};
let staticParamMatch = false;
function findActiveRoute() {
let searchActiveRoute = searchActiveRoutes(routes, '', urlParser.pathNames, routerOptions.lang, convert);
if (!searchActiveRoute || !Object.keys(searchActiveRoute).length || anyEmptyNestedRoutes(searchActiveRoute)) {
if (typeof window !== 'undefined') {
searchActiveRoute = routeNotFound(routerOptions.lang);
}
} else {
searchActiveRoute.path = pathWithoutQueryParams(searchActiveRoute);
if (sitePrefix) {
searchActiveRoute.path = `/${sitePrefix}${searchActiveRoute.path}`;
}
}
return searchActiveRoute;
}
/**
* Gets an array of routes and the browser pathname and return the active route
* @param routes
* @param basePath
* @param pathNames
**/
function searchActiveRoutes(routes, basePath, pathNames, currentLanguage, convert) {
let currentRoute = {};
let basePathName = pathNames.shift().toLowerCase();
const routerPath = RouterPath({ basePath, basePathName, pathNames, convert, currentLanguage });
staticParamMatch = false;
routes.forEach(function(route) {
routerPath.updatedPath(route);
if (matchRoute(routerPath, route.name)) {
let routePath = routerPath.routePath();
redirectTo = RouterRedirect(route, redirectTo).path();
if (currentRoute.name !== routePath) {
currentRoute = setCurrentRoute({
route,
routePath,
routeLanguage: routerPath.routeLanguage(),
urlParser,
namedPath: routerPath.namedPath(),
});
}
if (route.nestedRoutes && route.nestedRoutes.length > 0 && routerPath.pathNames.length > 0) {
currentRoute.childRoute = searchActiveRoutes(
route.nestedRoutes,
routePath,
routerPath.pathNames,
routerPath.routeLanguage(),
convert
);
currentRoute.path = currentRoute.childRoute.path;
currentRoute.language = currentRoute.childRoute.language;
} else if (nestedRoutesAndNoPath(route, routerPath.pathNames)) {
const indexRoute = searchActiveRoutes(
route.nestedRoutes,
routePath,
['index'],
routerPath.routeLanguage(),
convert
);
if (indexRoute && Object.keys(indexRoute).length > 0) {
currentRoute.childRoute = indexRoute;
currentRoute.language = currentRoute.childRoute.language;
}
}
}
});
if (redirectTo) {
currentRoute.redirectTo = redirectTo;
}
return currentRoute;
}
function matchRoute(routerPath, routeName) {
const basePathSameAsLocalised = routerPath.basePathSameAsLocalised();
if (basePathSameAsLocalised) {
staticParamMatch = true;
}
return basePathSameAsLocalised || (!staticParamMatch && startsWithNamedParam(routeName));
}
function nestedRoutesAndNoPath(route, pathNames) {
return route.nestedRoutes && route.nestedRoutes.length > 0 && pathNames.length === 0;
}
function parseCurrentUrl(currentUrl, sitePrefix) {
if (sitePrefix && sitePrefix.trim().length > 0) {
const replacePattern = currentUrl.endsWith(sitePrefix) ? sitePrefix : sitePrefix + "/";
const noPrefixUrl = currentUrl.replace(replacePattern, '');
return UrlParser(noPrefixUrl);
} else {
return UrlParser(currentUrl);
}
}
function setCurrentRoute({ route, routePath, routeLanguage, urlParser, namedPath }) {
const routerRoute = RouterRoute({
routeInfo: route,
urlParser,
path: routePath,
routeNamedParams,
namedPath,
language: routeLanguage || defaultLanguage,
});
routeNamedParams = routerRoute.namedParams();
return routerRoute.get();
}
const routeNotFound = (customLanguage) => {
const custom404Page = routes.find((route) => route.name == '404');
const language = customLanguage || defaultLanguage || '';
if (custom404Page) {
return { ...custom404Page, language, path: '404' };
} else {
return { name: '404', component: '', path: '404', redirectTo: NotFoundPage };
}
};
return Object.freeze({ findActiveRoute });
}
export { RouterFinder };