mirror of
https://github.com/kevin-DL/sapper.git
synced 2026-01-12 11:15:14 +00:00
Merge branch 'master' into navigate_fix
This commit is contained in:
@@ -10,6 +10,7 @@ import {
|
||||
ComponentLoader,
|
||||
ComponentConstructor,
|
||||
Route,
|
||||
Query,
|
||||
Page
|
||||
} from './types';
|
||||
import goto from './goto';
|
||||
@@ -80,6 +81,20 @@ export { _history as history };
|
||||
|
||||
export const scroll_history: Record<string, ScrollPosition> = {};
|
||||
|
||||
export function extract_query(search: string) {
|
||||
const query = Object.create(null);
|
||||
if (search.length > 0) {
|
||||
search.slice(1).split('&').forEach(searchParam => {
|
||||
let [, key, value] = /([^=]*)(?:=(.*))?/.exec(decodeURIComponent(searchParam));
|
||||
value = (value || '').replace(/\+/g, ' ');
|
||||
if (typeof query[key] === 'string') query[key] = [<string>query[key]];
|
||||
if (typeof query[key] === 'object') (query[key] as string[]).push(value);
|
||||
else query[key] = value;
|
||||
});
|
||||
}
|
||||
return query;
|
||||
}
|
||||
|
||||
export function select_target(url: URL): Target {
|
||||
if (url.origin !== location.origin) return null;
|
||||
if (!url.pathname.startsWith(initial_data.baseUrl)) return null;
|
||||
@@ -93,18 +108,9 @@ export function select_target(url: URL): Target {
|
||||
const route = routes[i];
|
||||
|
||||
const match = route.pattern.exec(path);
|
||||
if (match) {
|
||||
const query: Record<string, string | string[]> = Object.create(null);
|
||||
if (url.search.length > 0) {
|
||||
url.search.slice(1).split('&').forEach(searchParam => {
|
||||
let [, key, value] = /([^=]*)(?:=(.*))?/.exec(decodeURIComponent(searchParam));
|
||||
value = (value || '').replace(/\+/g, ' ');
|
||||
if (typeof query[key] === 'string') query[key] = [<string>query[key]];
|
||||
if (typeof query[key] === 'object') (query[key] as string[]).push(value);
|
||||
else query[key] = value;
|
||||
});
|
||||
}
|
||||
|
||||
if (match) {
|
||||
const query: Query = extract_query(url.search);
|
||||
const part = route.parts[route.parts.length - 1];
|
||||
const params = part.params ? part.params(match) : {};
|
||||
|
||||
@@ -115,6 +121,35 @@ export function select_target(url: URL): Target {
|
||||
}
|
||||
}
|
||||
|
||||
export function handle_error(url: URL) {
|
||||
const { pathname, search } = location;
|
||||
const { session, preloaded, status, error } = initial_data;
|
||||
|
||||
if (!root_preloaded) {
|
||||
root_preloaded = preloaded && preloaded[0]
|
||||
}
|
||||
|
||||
const props = {
|
||||
error,
|
||||
status,
|
||||
session,
|
||||
level0: {
|
||||
props: root_preloaded
|
||||
},
|
||||
level1: {
|
||||
props: {
|
||||
status,
|
||||
error
|
||||
},
|
||||
component: ErrorComponent
|
||||
},
|
||||
segments: preloaded
|
||||
|
||||
}
|
||||
const query = extract_query(search);
|
||||
render(null, [], props, { path: pathname, query, params: {} });
|
||||
}
|
||||
|
||||
export function scroll_state() {
|
||||
return {
|
||||
x: pageXOffset,
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
scroll_history,
|
||||
scroll_state,
|
||||
select_target,
|
||||
handle_error,
|
||||
set_target,
|
||||
uid,
|
||||
set_uid,
|
||||
@@ -34,10 +35,12 @@ export default function start(opts: {
|
||||
|
||||
history.replaceState({ id: uid }, '', href);
|
||||
|
||||
if (!initial_data.error) {
|
||||
const target = select_target(new URL(location.href));
|
||||
if (target) return navigate(target, uid, false, hash);
|
||||
}
|
||||
const url = new URL(location.href);
|
||||
|
||||
if (initial_data.error) return handle_error(url);
|
||||
|
||||
const target = select_target(url);
|
||||
if (target) return navigate(target, uid, false, hash);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -127,4 +130,4 @@ function handle_popstate(event: PopStateEvent) {
|
||||
set_cid(uid);
|
||||
history.replaceState({ id: cid }, '', location.href);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,11 +243,12 @@ export function get_page_handler(
|
||||
preloaded: `[${preloaded.map(data => try_serialize(data)).join(',')}]`,
|
||||
session: session && try_serialize(session, err => {
|
||||
throw new Error(`Failed to serialize session data: ${err.message}`);
|
||||
})
|
||||
}),
|
||||
error: error && try_serialize(props.error)
|
||||
};
|
||||
|
||||
let script = `__SAPPER__={${[
|
||||
error && `error:1`,
|
||||
error && `error:${serialized.error},status:${status}`,
|
||||
`baseUrl:"${req.baseUrl}"`,
|
||||
serialized.preloaded && `preloaded:${serialized.preloaded}`,
|
||||
serialized.session && `session:${serialized.session}`
|
||||
@@ -329,12 +330,10 @@ export function get_page_handler(
|
||||
return;
|
||||
}
|
||||
|
||||
if (!server_routes.some(route => route.pattern.test(req.path))) {
|
||||
for (const page of pages) {
|
||||
if (page.pattern.test(req.path)) {
|
||||
handle_page(page, req, res);
|
||||
return;
|
||||
}
|
||||
for (const page of pages) {
|
||||
if (page.pattern.test(req.path)) {
|
||||
handle_page(page, req, res);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user