feat: add project and email service
This commit is contained in:
parent
99715f6105
commit
f48390b15e
29 changed files with 2631 additions and 63 deletions
68
src/router.ts
Normal file
68
src/router.ts
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
type PageHandler = (
|
||||
outlet: HTMLElement,
|
||||
params: Record<string, string>,
|
||||
) => void | Promise<void>;
|
||||
|
||||
interface Route {
|
||||
pattern: RegExp;
|
||||
keys: string[];
|
||||
handler: PageHandler;
|
||||
}
|
||||
|
||||
const routes: Route[] = [];
|
||||
let notFoundHandler: PageHandler | null = null;
|
||||
|
||||
export function route(path: string, handler: PageHandler) {
|
||||
if (path === "*") {
|
||||
notFoundHandler = handler;
|
||||
return;
|
||||
}
|
||||
const keys: string[] = [];
|
||||
const pattern = path.replace(/:(\w+)/g, (_, key: string) => {
|
||||
keys.push(key);
|
||||
return "([^/]+)";
|
||||
});
|
||||
routes.push({ pattern: new RegExp(`^${pattern}$`), keys, handler });
|
||||
}
|
||||
|
||||
export function navigate(path: string) {
|
||||
history.pushState(null, "", path);
|
||||
void render();
|
||||
}
|
||||
|
||||
async function render() {
|
||||
const path = location.pathname;
|
||||
const outlet = document.getElementById("outlet")!;
|
||||
|
||||
for (const r of routes) {
|
||||
const match = path.match(r.pattern);
|
||||
if (match) {
|
||||
const params: Record<string, string> = {};
|
||||
r.keys.forEach((key, i) => {
|
||||
params[key] = match[i + 1]!;
|
||||
});
|
||||
outlet.innerHTML = "";
|
||||
await r.handler(outlet, params);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
outlet.innerHTML = "";
|
||||
if (notFoundHandler) {
|
||||
await notFoundHandler(outlet, {});
|
||||
}
|
||||
}
|
||||
|
||||
export function initRouter() {
|
||||
window.addEventListener("popstate", () => void render());
|
||||
|
||||
document.addEventListener("click", (e) => {
|
||||
const anchor = (e.target as HTMLElement).closest("a");
|
||||
if (anchor?.origin === location.origin && !anchor.hasAttribute("download")) {
|
||||
e.preventDefault();
|
||||
navigate(anchor.pathname);
|
||||
}
|
||||
});
|
||||
|
||||
void render();
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue