mirror of
https://github.com/kevin-DL/sapper.git
synced 2026-01-12 03:05:12 +00:00
return a promise from init - fixes #99
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { detach, findAnchor, scroll_state, which } from './utils';
|
||||
import { Component, ComponentConstructor, Params, Query, Route, RouteData, ScrollPosition } from './interfaces';
|
||||
import { Component, ComponentConstructor, Params, Query, Route, RouteData, ScrollPosition, Target } from './interfaces';
|
||||
|
||||
export let component: Component;
|
||||
let target: Node;
|
||||
@@ -19,7 +19,7 @@ if ('scrollRestoration' in history) {
|
||||
history.scrollRestoration = 'manual';
|
||||
}
|
||||
|
||||
function select_route(url: URL): { route: Route, data: RouteData } {
|
||||
function select_route(url: URL): Target {
|
||||
if (url.origin !== window.location.origin) return null;
|
||||
|
||||
for (const route of routes) {
|
||||
@@ -30,7 +30,7 @@ function select_route(url: URL): { route: Route, data: RouteData } {
|
||||
const query: Record<string, string | true> = {};
|
||||
for (const [key, value] of url.searchParams) query[key] = value || true;
|
||||
|
||||
return { route, data: { params, query } };
|
||||
return { url, route, data: { params, query } };
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -83,35 +83,31 @@ function prepare_route(Component: ComponentConstructor, data: RouteData) {
|
||||
});
|
||||
}
|
||||
|
||||
function navigate(url: URL, id: number) {
|
||||
const selected = select_route(url);
|
||||
if (selected) {
|
||||
if (id) {
|
||||
// popstate or initial navigation
|
||||
cid = id;
|
||||
} else {
|
||||
// clicked on a link. preserve scroll state
|
||||
scroll_history[cid] = scroll_state();
|
||||
|
||||
id = cid = ++uid;
|
||||
scroll_history[cid] = { x: 0, y: 0 };
|
||||
}
|
||||
|
||||
const loaded = prefetching && prefetching.href === url.href ?
|
||||
prefetching.promise :
|
||||
selected.route.load().then(mod => prepare_route(mod.default, selected.data));
|
||||
|
||||
prefetching = null;
|
||||
|
||||
const token = current_token = {};
|
||||
|
||||
loaded.then(({ Component, data }) => {
|
||||
render(Component, data, scroll_history[id], token);
|
||||
});
|
||||
|
||||
function navigate(target: Target, id: number) {
|
||||
if (id) {
|
||||
// popstate or initial navigation
|
||||
cid = id;
|
||||
return true;
|
||||
} else {
|
||||
// clicked on a link. preserve scroll state
|
||||
scroll_history[cid] = scroll_state();
|
||||
|
||||
id = cid = ++uid;
|
||||
scroll_history[cid] = { x: 0, y: 0 };
|
||||
}
|
||||
|
||||
cid = id;
|
||||
|
||||
const loaded = prefetching && prefetching.href === target.url.href ?
|
||||
prefetching.promise :
|
||||
target.route.load().then(mod => prepare_route(mod.default, target.data));
|
||||
|
||||
prefetching = null;
|
||||
|
||||
const token = current_token = {};
|
||||
|
||||
return loaded.then(({ Component, data }) => {
|
||||
render(Component, data, scroll_history[id], token);
|
||||
});
|
||||
}
|
||||
|
||||
function handle_click(event: MouseEvent) {
|
||||
@@ -147,7 +143,9 @@ function handle_click(event: MouseEvent) {
|
||||
// Don't handle hash changes
|
||||
if (url.pathname === window.location.pathname && url.search === window.location.search) return;
|
||||
|
||||
if (navigate(url, null)) {
|
||||
const target = select_route(url);
|
||||
if (target) {
|
||||
navigate(target, null);
|
||||
event.preventDefault();
|
||||
history.pushState({ id: cid }, '', url.href);
|
||||
}
|
||||
@@ -157,7 +155,9 @@ function handle_popstate(event: PopStateEvent) {
|
||||
scroll_history[cid] = scroll_state();
|
||||
|
||||
if (event.state) {
|
||||
navigate(new URL(window.location.href), event.state.id);
|
||||
const url = new URL(window.location.href);
|
||||
const target = select_route(url);
|
||||
navigate(target, event.state.id);
|
||||
} else {
|
||||
// hashchange
|
||||
cid = ++uid;
|
||||
@@ -205,7 +205,7 @@ export function init(_target: Node, _routes: Route[]) {
|
||||
inited = true;
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
return Promise.resolve().then(() => {
|
||||
const { hash, href } = window.location;
|
||||
|
||||
const deep_linked = hash && document.querySelector(hash);
|
||||
@@ -214,12 +214,16 @@ export function init(_target: Node, _routes: Route[]) {
|
||||
scroll_state();
|
||||
|
||||
history.replaceState({ id: uid }, '', href);
|
||||
navigate(new URL(window.location.href), uid);
|
||||
|
||||
const target = select_route(new URL(window.location.href));
|
||||
return navigate(target, uid);
|
||||
});
|
||||
}
|
||||
|
||||
export function goto(href: string, opts = { replaceState: false }) {
|
||||
if (navigate(new URL(href, window.location.href), null)) {
|
||||
const target = select_route(new URL(href, window.location.href));
|
||||
if (target) {
|
||||
navigate(target, null);
|
||||
if (history) history[opts.replaceState ? 'replaceState' : 'pushState']({ id: cid }, '', href);
|
||||
} else {
|
||||
window.location.href = href;
|
||||
|
||||
@@ -20,4 +20,10 @@ export type Route = {
|
||||
export type ScrollPosition = {
|
||||
x: number;
|
||||
y: number;
|
||||
};
|
||||
|
||||
export type Target = {
|
||||
url: URL;
|
||||
route: Route;
|
||||
data: RouteData;
|
||||
};
|
||||
@@ -1,6 +1,5 @@
|
||||
import { init } from '../../../runtime.js';
|
||||
|
||||
window.init = () => {
|
||||
init(document.querySelector('#sapper'), __routes__);
|
||||
window.READY = true;
|
||||
return init(document.querySelector('#sapper'), __routes__);
|
||||
};
|
||||
@@ -183,7 +183,7 @@ function run(env) {
|
||||
});
|
||||
|
||||
it('navigates to a new page without reloading', () => {
|
||||
return nightmare.goto(base).init().wait(200)
|
||||
return nightmare.goto(base).init().wait(100)
|
||||
.then(() => {
|
||||
return capture(() => nightmare.click('a[href="/about"]'));
|
||||
})
|
||||
@@ -204,7 +204,6 @@ function run(env) {
|
||||
return nightmare
|
||||
.goto(`${base}/about`)
|
||||
.init()
|
||||
.wait(100)
|
||||
.click('.goto')
|
||||
.wait(() => window.location.pathname === '/blog/what-is-sapper')
|
||||
.wait(100)
|
||||
@@ -218,7 +217,6 @@ function run(env) {
|
||||
return nightmare
|
||||
.goto(`${base}/about`)
|
||||
.init()
|
||||
.wait(100)
|
||||
.then(() => {
|
||||
return capture(() => {
|
||||
return nightmare
|
||||
@@ -235,7 +233,6 @@ function run(env) {
|
||||
return nightmare
|
||||
.goto(`${base}/blog/a-very-long-post#four`)
|
||||
.init()
|
||||
.wait(100)
|
||||
.evaluate(() => window.scrollY)
|
||||
.then(scrollY => {
|
||||
assert.ok(scrollY > 0, scrollY);
|
||||
@@ -246,7 +243,6 @@ function run(env) {
|
||||
return nightmare
|
||||
.goto(`${base}/blog`)
|
||||
.init()
|
||||
.wait(200)
|
||||
.then(() => {
|
||||
return capture(() => {
|
||||
return nightmare
|
||||
@@ -310,7 +306,7 @@ function run(env) {
|
||||
it('calls a delete handler', () => {
|
||||
return nightmare
|
||||
.goto(`${base}/delete-test`)
|
||||
.init().wait(100)
|
||||
.init()
|
||||
.click('.del')
|
||||
.wait(() => window.deleted)
|
||||
.evaluate(() => window.deleted.id)
|
||||
@@ -325,7 +321,7 @@ function run(env) {
|
||||
.evaluate(() => {
|
||||
window.el = document.querySelector('.hydrate-test');
|
||||
})
|
||||
.init().wait(100)
|
||||
.init()
|
||||
.evaluate(() => {
|
||||
return document.querySelector('.hydrate-test') === window.el;
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user