87 lines
2.0 KiB
Svelte
87 lines
2.0 KiB
Svelte
<script>
|
|
import { onMount } from 'svelte';
|
|
let { loading, fallback } = $props();
|
|
const modules = import.meta.glob('../../routes/**/*.svelte');
|
|
const routes = Object.entries(modules).map(([key, load]) => {
|
|
const path = key
|
|
.replace('../../routes', '')
|
|
.replace('.svelte', '')
|
|
.replace(/\/index$/, '') || '/';
|
|
|
|
return {
|
|
pattern: new RegExp(path.replace(/\[([^\]]+)\]/g, '(?<$1>[^/]+)') + '$'),
|
|
load
|
|
};
|
|
});
|
|
|
|
let match = $state(null);
|
|
let CurrentPage = $state(null);
|
|
let params = $state({});
|
|
|
|
async function update() {
|
|
const path = window.location.pathname;
|
|
let found = null;
|
|
|
|
for (const r of routes) {
|
|
const m = path.match(r.pattern);
|
|
if (m) {
|
|
found = r;
|
|
params = m.groups || {};
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (found) {
|
|
const mod = await found.load();
|
|
CurrentPage = mod.default;
|
|
match = true;
|
|
} else {
|
|
match = false;
|
|
}
|
|
}
|
|
|
|
onMount(() => {
|
|
update();
|
|
|
|
const handlePopState = () => update();
|
|
window.addEventListener('popstate', handlePopState);
|
|
|
|
const handleClick = (e) => {
|
|
const a = e.target.closest('a');
|
|
if (!a || a.target === '_blank' || e.ctrlKey || e.metaKey) return;
|
|
const href = a.getAttribute('href');
|
|
if (!href || href.startsWith('#') || href.includes('://')) return;
|
|
|
|
e.preventDefault();
|
|
history.pushState({}, '', new URL(href, window.location.href).pathname);
|
|
update();
|
|
};
|
|
|
|
window.addEventListener('click', handleClick);
|
|
|
|
return () => {
|
|
window.removeEventListener('popstate', handlePopState);
|
|
window.removeEventListener('click', handleClick);
|
|
};
|
|
});
|
|
</script>
|
|
|
|
{#if match === true}
|
|
{#if CurrentPage}
|
|
{#key CurrentPage}
|
|
<CurrentPage {...params} />
|
|
{/key}
|
|
{/if}
|
|
{:else if match === false}
|
|
{#if fallback}
|
|
{@render fallback()}
|
|
{:else}
|
|
<h1>404 - Not found</h1>
|
|
{/if}
|
|
{:else}
|
|
{#if loading}
|
|
{@render loading()}
|
|
{:else}
|
|
<p>Loading...</p>
|
|
{/if}
|
|
{/if} |