|
import { BROWSER, DEV } from 'esm-env'; |
|
|
|
|
|
|
|
|
|
|
|
export const SCHEME = /^[a-z][a-z\d+\-.]+:/i; |
|
|
|
const internal = new URL('sveltekit-internal://'); |
|
|
|
|
|
|
|
|
|
|
|
export function resolve(base, path) { |
|
|
|
if (path[0] === '/' && path[1] === '/') return path; |
|
|
|
let url = new URL(base, internal); |
|
url = new URL(path, url); |
|
|
|
return url.protocol === internal.protocol ? url.pathname + url.search + url.hash : url.href; |
|
} |
|
|
|
|
|
export function is_root_relative(path) { |
|
return path[0] === '/' && path[1] !== '/'; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
export function normalize_path(path, trailing_slash) { |
|
if (path === '/' || trailing_slash === 'ignore') return path; |
|
|
|
if (trailing_slash === 'never') { |
|
return path.endsWith('/') ? path.slice(0, -1) : path; |
|
} else if (trailing_slash === 'always' && !path.endsWith('/')) { |
|
return path + '/'; |
|
} |
|
|
|
return path; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
export function decode_pathname(pathname) { |
|
return pathname.split('%25').map(decodeURI).join('%25'); |
|
} |
|
|
|
|
|
export function decode_params(params) { |
|
for (const key in params) { |
|
|
|
|
|
params[key] = decodeURIComponent(params[key]); |
|
} |
|
|
|
return params; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
export function decode_uri(uri) { |
|
try { |
|
return decodeURI(uri); |
|
} catch (e) { |
|
if (e instanceof Error) { |
|
e.message = `Failed to decode URI: ${uri}\n` + e.message; |
|
} |
|
throw e; |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
export function strip_hash({ href }) { |
|
return href.split('#')[0]; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
const tracked_url_properties = ([ |
|
'href', |
|
'pathname', |
|
'search', |
|
'toString', |
|
'toJSON' |
|
]); |
|
|
|
|
|
|
|
|
|
|
|
|
|
export function make_trackable(url, callback, search_params_callback) { |
|
const tracked = new URL(url); |
|
|
|
Object.defineProperty(tracked, 'searchParams', { |
|
value: new Proxy(tracked.searchParams, { |
|
get(obj, key) { |
|
if (key === 'get' || key === 'getAll' || key === 'has') { |
|
return ( param) => { |
|
search_params_callback(param); |
|
return obj[key](param); |
|
}; |
|
} |
|
|
|
|
|
|
|
callback(); |
|
|
|
const value = Reflect.get(obj, key); |
|
return typeof value === 'function' ? value.bind(obj) : value; |
|
} |
|
}), |
|
enumerable: true, |
|
configurable: true |
|
}); |
|
|
|
for (const property of tracked_url_properties) { |
|
Object.defineProperty(tracked, property, { |
|
get() { |
|
callback(); |
|
return url[property]; |
|
}, |
|
|
|
enumerable: true, |
|
configurable: true |
|
}); |
|
} |
|
|
|
if (!BROWSER) { |
|
|
|
tracked[Symbol.for('nodejs.util.inspect.custom')] = (depth, opts, inspect) => { |
|
return inspect(url, opts); |
|
}; |
|
} |
|
|
|
if (DEV || !BROWSER) { |
|
disable_hash(tracked); |
|
} |
|
|
|
return tracked; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
function disable_hash(url) { |
|
allow_nodejs_console_log(url); |
|
|
|
Object.defineProperty(url, 'hash', { |
|
get() { |
|
throw new Error( |
|
'Cannot access event.url.hash. Consider using `$page.url.hash` inside a component instead' |
|
); |
|
} |
|
}); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
export function disable_search(url) { |
|
allow_nodejs_console_log(url); |
|
|
|
for (const property of ['search', 'searchParams']) { |
|
Object.defineProperty(url, property, { |
|
get() { |
|
throw new Error(`Cannot access url.${property} on a page with prerendering enabled`); |
|
} |
|
}); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
function allow_nodejs_console_log(url) { |
|
if (!BROWSER) { |
|
|
|
url[Symbol.for('nodejs.util.inspect.custom')] = (depth, opts, inspect) => { |
|
return inspect(new URL(url), opts); |
|
}; |
|
} |
|
} |
|
|
|
const DATA_SUFFIX = '/__data.json'; |
|
const HTML_DATA_SUFFIX = '.html__data.json'; |
|
|
|
|
|
export function has_data_suffix(pathname) { |
|
return pathname.endsWith(DATA_SUFFIX) || pathname.endsWith(HTML_DATA_SUFFIX); |
|
} |
|
|
|
|
|
export function add_data_suffix(pathname) { |
|
if (pathname.endsWith('.html')) return pathname.replace(/\.html$/, HTML_DATA_SUFFIX); |
|
return pathname.replace(/\/$/, '') + DATA_SUFFIX; |
|
} |
|
|
|
|
|
export function strip_data_suffix(pathname) { |
|
if (pathname.endsWith(HTML_DATA_SUFFIX)) { |
|
return pathname.slice(0, -HTML_DATA_SUFFIX.length) + '.html'; |
|
} |
|
|
|
return pathname.slice(0, -DATA_SUFFIX.length); |
|
} |
|
|