rvx
Version:
A signal based rendering library
87 lines • 3.12 kB
JavaScript
import { $, get, watch } from "../core/signals.js";
import { nest } from "../core/view.js";
import { ChildRouter } from "./child-router.js";
import { normalize } from "./path.js";
import { ROUTER } from "./router.js";
export function matchRoute(path, routes) {
for (const route of routes) {
if (typeof route.match === "string") {
const test = route.match === "/" ? "" : route.match;
if (test.endsWith("/")) {
if (path.startsWith(test) || path === test.slice(0, -1)) {
return {
route,
path: normalize(path.slice(0, test.length - 1)),
params: undefined,
rest: normalize(path.slice(test.length)),
};
}
}
else if (test === path) {
return { route, path, rest: "" };
}
}
else if (typeof route.match === "function") {
const match = route.match(path);
if (match !== undefined) {
let rest = path;
if (path.startsWith(match.path) && (path.length === match.path.length || path[match.path.length] === "/")) {
rest = normalize(path.slice(match.path.length));
}
return { ...match, route, rest };
}
}
else if (route.match instanceof RegExp) {
const match = route.match.exec(path);
if (match !== null) {
const matched = normalize(match[0], false);
let rest = path;
if (path.startsWith(matched) && (path.length === matched.length || path[matched.length] === "/")) {
rest = normalize(path.slice(matched.length));
}
return { route, path: matched, params: match, rest };
}
}
else {
return { route, path: "", rest: path };
}
}
}
export function watchRoutes(path, routes) {
const parent = $(undefined);
const rest = $(undefined);
watch(() => matchRoute(get(path), get(routes)), match => {
if (match) {
if (!parent.value || parent.value.path !== match.path || parent.value.route !== match.route) {
parent.value = match;
}
rest.value = match.rest;
}
else {
parent.value = undefined;
rest.value = "";
}
});
return {
match: () => parent.value,
rest: () => rest.value,
};
}
export function routes(routes) {
const router = ROUTER.current;
if (!router) {
throw new Error("G3");
}
const watched = watchRoutes(() => router.path, routes);
return nest(watched.match, match => {
if (match) {
return ROUTER.inject(new ChildRouter(router, match.path, watched.rest), () => {
return match.route.content({ params: match.params });
});
}
});
}
export function Routes(props) {
return routes(props.routes);
}
//# sourceMappingURL=route.js.map