1
1
import { detach , findAnchor , scroll_state , which } from './utils' ;
2
- import { Component , ComponentConstructor , Params , Query , Route , RouteData , ScrollPosition } from './interfaces' ;
2
+ import { Component , ComponentConstructor , Params , Query , Route , RouteData , ScrollPosition , Target } from './interfaces' ;
3
3
4
4
export let component : Component ;
5
5
let target : Node ;
@@ -19,7 +19,7 @@ if ('scrollRestoration' in history) {
19
19
history . scrollRestoration = 'manual' ;
20
20
}
21
21
22
- function select_route ( url : URL ) : { route : Route , data : RouteData } {
22
+ function select_route ( url : URL ) : Target {
23
23
if ( url . origin !== window . location . origin ) return null ;
24
24
25
25
for ( const route of routes ) {
@@ -30,7 +30,7 @@ function select_route(url: URL): { route: Route, data: RouteData } {
30
30
const query : Record < string , string | true > = { } ;
31
31
for ( const [ key , value ] of url . searchParams ) query [ key ] = value || true ;
32
32
33
- return { route, data : { params, query } } ;
33
+ return { url , route, data : { params, query } } ;
34
34
}
35
35
}
36
36
}
@@ -83,35 +83,31 @@ function prepare_route(Component: ComponentConstructor, data: RouteData) {
83
83
} ) ;
84
84
}
85
85
86
- function navigate ( url : URL , id : number ) {
87
- const selected = select_route ( url ) ;
88
- if ( selected ) {
89
- if ( id ) {
90
- // popstate or initial navigation
91
- cid = id ;
92
- } else {
93
- // clicked on a link. preserve scroll state
94
- scroll_history [ cid ] = scroll_state ( ) ;
95
-
96
- id = cid = ++ uid ;
97
- scroll_history [ cid ] = { x : 0 , y : 0 } ;
98
- }
86
+ function navigate ( target : Target , id : number ) {
87
+ if ( id ) {
88
+ // popstate or initial navigation
89
+ cid = id ;
90
+ } else {
91
+ // clicked on a link. preserve scroll state
92
+ scroll_history [ cid ] = scroll_state ( ) ;
93
+
94
+ id = cid = ++ uid ;
95
+ scroll_history [ cid ] = { x : 0 , y : 0 } ;
96
+ }
99
97
100
- const loaded = prefetching && prefetching . href === url . href ?
101
- prefetching . promise :
102
- selected . route . load ( ) . then ( mod => prepare_route ( mod . default , selected . data ) ) ;
98
+ cid = id ;
103
99
104
- prefetching = null ;
100
+ const loaded = prefetching && prefetching . href === target . url . href ?
101
+ prefetching . promise :
102
+ target . route . load ( ) . then ( mod => prepare_route ( mod . default , target . data ) ) ;
105
103
106
- const token = current_token = { } ;
104
+ prefetching = null ;
107
105
108
- loaded . then ( ( { Component, data } ) => {
109
- render ( Component , data , scroll_history [ id ] , token ) ;
110
- } ) ;
106
+ const token = current_token = { } ;
111
107
112
- cid = id ;
113
- return true ;
114
- }
108
+ return loaded . then ( ( { Component , data } ) => {
109
+ render ( Component , data , scroll_history [ id ] , token ) ;
110
+ } ) ;
115
111
}
116
112
117
113
function handle_click ( event : MouseEvent ) {
@@ -147,7 +143,9 @@ function handle_click(event: MouseEvent) {
147
143
// Don't handle hash changes
148
144
if ( url . pathname === window . location . pathname && url . search === window . location . search ) return ;
149
145
150
- if ( navigate ( url , null ) ) {
146
+ const target = select_route ( url ) ;
147
+ if ( target ) {
148
+ navigate ( target , null ) ;
151
149
event . preventDefault ( ) ;
152
150
history . pushState ( { id : cid } , '' , url . href ) ;
153
151
}
@@ -157,7 +155,9 @@ function handle_popstate(event: PopStateEvent) {
157
155
scroll_history [ cid ] = scroll_state ( ) ;
158
156
159
157
if ( event . state ) {
160
- navigate ( new URL ( window . location . href ) , event . state . id ) ;
158
+ const url = new URL ( window . location . href ) ;
159
+ const target = select_route ( url ) ;
160
+ navigate ( target , event . state . id ) ;
161
161
} else {
162
162
// hashchange
163
163
cid = ++ uid ;
@@ -205,7 +205,7 @@ export function init(_target: Node, _routes: Route[]) {
205
205
inited = true ;
206
206
}
207
207
208
- setTimeout ( ( ) => {
208
+ return Promise . resolve ( ) . then ( ( ) => {
209
209
const { hash, href } = window . location ;
210
210
211
211
const deep_linked = hash && document . querySelector ( hash ) ;
@@ -214,12 +214,16 @@ export function init(_target: Node, _routes: Route[]) {
214
214
scroll_state ( ) ;
215
215
216
216
history . replaceState ( { id : uid } , '' , href ) ;
217
- navigate ( new URL ( window . location . href ) , uid ) ;
217
+
218
+ const target = select_route ( new URL ( window . location . href ) ) ;
219
+ return navigate ( target , uid ) ;
218
220
} ) ;
219
221
}
220
222
221
223
export function goto ( href : string , opts = { replaceState : false } ) {
222
- if ( navigate ( new URL ( href , window . location . href ) , null ) ) {
224
+ const target = select_route ( new URL ( href , window . location . href ) ) ;
225
+ if ( target ) {
226
+ navigate ( target , null ) ;
223
227
if ( history ) history [ opts . replaceState ? 'replaceState' : 'pushState' ] ( { id : cid } , '' , href ) ;
224
228
} else {
225
229
window . location . href = href ;
0 commit comments