@absolutejs/absolute 0.19.0-beta.830 → 0.19.0-beta.832

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,8 +2,7 @@
2
2
  import { getContext, onDestroy, type Snippet } from 'svelte';
3
3
  import type { ExtractRouteParams } from '../../types/svelteRouter';
4
4
  import type { RouterRegistry } from './Router.svelte';
5
- import { compilePattern, joinBasepath, matchPattern } from './matchPath';
6
- import { page } from './page.js';
5
+ import { compilePattern, joinBasepath } from './matchPath';
7
6
 
8
7
  const ROUTER_CONTEXT_KEY = Symbol.for('absolutejs.svelte-router');
9
8
 
@@ -26,18 +25,22 @@
26
25
  const registrationOrder = Number(id.slice(1));
27
26
 
28
27
  // Register synchronously at script-body time so SSR (which doesn't
29
- // run $effect) sees the registration. On the client, $effect
30
- // re-registers when path or basepath changes.
28
+ // run $effect) sees the registration. The Router itself owns
29
+ // rendering of the winning route's content — Route emits no DOM and
30
+ // no hydration markers, so a page with N <Route>s produces ONE
31
+ // `{#if}` block in the rendered HTML, not N.
31
32
  const initialCompiled = compilePattern(
32
33
  joinBasepath(registry.basepath, path)
33
34
  );
34
35
  registry.register(id, {
36
+ content: content as Snippet<[Record<string, string | undefined>]>,
35
37
  pattern: initialCompiled,
36
38
  registrationOrder
37
39
  });
38
40
 
39
41
  $effect(() => {
40
42
  registry.register(id, {
43
+ content: content as Snippet<[Record<string, string | undefined>]>,
41
44
  pattern: compilePattern(joinBasepath(registry.basepath, path)),
42
45
  registrationOrder
43
46
  });
@@ -45,11 +48,3 @@
45
48
 
46
49
  onDestroy(() => registry.deregister(id));
47
50
  </script>
48
-
49
- {#if registry.isWinner(id)}
50
- {@const compiled = compilePattern(joinBasepath(registry.basepath, path))}
51
- {@const match = matchPattern<Path>(compiled, page.url.pathname)}
52
- {#if match.matched}
53
- {@render content(match.params)}
54
- {/if}
55
- {/if}
@@ -1,23 +1,28 @@
1
1
  <script lang="ts" module>
2
- type CompiledPatternBox = {
2
+ import type { Snippet } from 'svelte';
3
+
4
+ type RouteEntry = {
3
5
  // reactive — read by the winner-resolver
4
6
  pattern: ReturnType<typeof import('./matchPath').compilePattern>;
5
7
  // stable — assigned at registration time, used as tiebreaker
6
8
  registrationOrder: number;
9
+ // the snippet the winning Route should render — extraction lives
10
+ // on the Router so the active branch renders inside ONE if-block
11
+ // instead of one per Route (one set of hydration markers, not N)
12
+ content: Snippet<[Record<string, string | undefined>]>;
7
13
  };
8
14
 
9
15
  export type RouterRegistry = {
10
16
  basepath: string;
11
17
  mode: import('../../types/svelteRouter').RouterMode;
12
- register: (id: string, entry: CompiledPatternBox) => void;
18
+ register: (id: string, entry: RouteEntry) => void;
13
19
  deregister: (id: string) => void;
14
- isWinner: (id: string) => boolean;
15
20
  nextRouteId: () => string;
16
21
  };
17
22
  </script>
18
23
 
19
24
  <script lang="ts">
20
- import { getContext, onMount, setContext, type Snippet } from 'svelte';
25
+ import { getContext, onMount, setContext } from 'svelte';
21
26
  import type { RouterMode } from '../../types/svelteRouter';
22
27
  import { setRouterMode } from './goto';
23
28
  import { hashPathnameOf } from './hashMode';
@@ -59,15 +64,16 @@
59
64
  const isOutermost = parent === undefined;
60
65
 
61
66
  // Specificity ranking across siblings: each <Route> registers with
62
- // its compiled pattern + a stable mount-order index. The winner is
63
- // recomputed eagerly inside `isWinner()` rather than via $derived
64
- // that avoids an SSR timing edge where $derived caches a value from
65
- // before later siblings have registered.
66
- const routes = $state(new Map<string, CompiledPatternBox>());
67
+ // its compiled pattern + content snippet + a stable mount-order
68
+ // index. The winner is computed lazily from the current URL highest
69
+ // score wins; ties break by earlier registration order.
70
+ const routes = $state(new Map<string, RouteEntry>());
67
71
  let routeCounter = 0;
68
72
 
69
- const computeWinnerId = () => {
73
+ const computeWinner = () => {
70
74
  let bestId: string | null = null;
75
+ let bestEntry: RouteEntry | null = null;
76
+ let bestParams: Record<string, string | undefined> | null = null;
71
77
  let bestScore = -Infinity;
72
78
  let bestOrder = Infinity;
73
79
 
@@ -83,10 +89,14 @@
83
89
  bestScore = entry.pattern.score;
84
90
  bestOrder = entry.registrationOrder;
85
91
  bestId = id;
92
+ bestEntry = entry;
93
+ bestParams = match.params as Record<string, string | undefined>;
86
94
  }
87
95
  }
88
96
 
89
- return bestId;
97
+ return bestId && bestEntry && bestParams
98
+ ? { content: bestEntry.content, params: bestParams }
99
+ : null;
90
100
  };
91
101
 
92
102
  const registry: RouterRegistry = {
@@ -94,7 +104,6 @@
94
104
  deregister: (id) => {
95
105
  routes.delete(id);
96
106
  },
97
- isWinner: (id) => computeWinnerId() === id,
98
107
  mode: stackedMode,
99
108
  nextRouteId: () => `r${routeCounter++}`,
100
109
  register: (id, entry) => {
@@ -104,6 +113,10 @@
104
113
 
105
114
  setContext<RouterRegistry>(ROUTER_CONTEXT_KEY, registry);
106
115
 
116
+ // Recompute on every page.url change OR routes registry mutation.
117
+ // Reading $state during $derived auto-tracks both dependencies.
118
+ const winner = $derived(computeWinner());
119
+
107
120
  if (isOutermost) {
108
121
  setRouterMode(stackedMode);
109
122
 
@@ -163,3 +176,6 @@
163
176
  </script>
164
177
 
165
178
  {@render children?.()}
179
+ {#if winner}
180
+ {@render winner.content(winner.params)}
181
+ {/if}
package/package.json CHANGED
@@ -384,5 +384,5 @@
384
384
  ]
385
385
  }
386
386
  },
387
- "version": "0.19.0-beta.830"
387
+ "version": "0.19.0-beta.832"
388
388
  }