feat: docker compose maybe
This commit is contained in:
2090
node_modules/@sveltejs/kit/src/runtime/client/client.js
generated
vendored
Normal file
2090
node_modules/@sveltejs/kit/src/runtime/client/client.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
11
node_modules/@sveltejs/kit/src/runtime/client/constants.js
generated
vendored
Normal file
11
node_modules/@sveltejs/kit/src/runtime/client/constants.js
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
export const SNAPSHOT_KEY = 'sveltekit:snapshot';
|
||||
export const SCROLL_KEY = 'sveltekit:scroll';
|
||||
export const INDEX_KEY = 'sveltekit:index';
|
||||
|
||||
export const PRELOAD_PRIORITIES = /** @type {const} */ ({
|
||||
tap: 1,
|
||||
hover: 2,
|
||||
viewport: 3,
|
||||
eager: 4,
|
||||
off: -1
|
||||
});
|
167
node_modules/@sveltejs/kit/src/runtime/client/fetcher.js
generated
vendored
Normal file
167
node_modules/@sveltejs/kit/src/runtime/client/fetcher.js
generated
vendored
Normal file
@ -0,0 +1,167 @@
|
||||
import { DEV } from 'esm-env';
|
||||
import { hash } from '../hash.js';
|
||||
|
||||
let loading = 0;
|
||||
|
||||
export const native_fetch = window.fetch;
|
||||
|
||||
export function lock_fetch() {
|
||||
loading += 1;
|
||||
}
|
||||
|
||||
export function unlock_fetch() {
|
||||
loading -= 1;
|
||||
}
|
||||
|
||||
if (DEV) {
|
||||
let can_inspect_stack_trace = false;
|
||||
|
||||
const check_stack_trace = async () => {
|
||||
const stack = /** @type {string} */ (new Error().stack);
|
||||
can_inspect_stack_trace = stack.includes('check_stack_trace');
|
||||
};
|
||||
|
||||
check_stack_trace();
|
||||
|
||||
/**
|
||||
* @param {RequestInfo | URL} input
|
||||
* @param {RequestInit & Record<string, any> | undefined} init
|
||||
*/
|
||||
window.fetch = (input, init) => {
|
||||
// Check if fetch was called via load_node. the lock method only checks if it was called at the
|
||||
// same time, but not necessarily if it was called from `load`.
|
||||
// We use just the filename as the method name sometimes does not appear on the CI.
|
||||
const url = input instanceof Request ? input.url : input.toString();
|
||||
const stack_array = /** @type {string} */ (new Error().stack).split('\n');
|
||||
// We need to do a cutoff because Safari and Firefox maintain the stack
|
||||
// across events and for example traces a `fetch` call triggered from a button
|
||||
// back to the creation of the event listener and the element creation itself,
|
||||
// where at some point client.js will show up, leading to false positives.
|
||||
const cutoff = stack_array.findIndex((a) => a.includes('load@') || a.includes('at load'));
|
||||
const stack = stack_array.slice(0, cutoff + 2).join('\n');
|
||||
|
||||
const in_load_heuristic = can_inspect_stack_trace
|
||||
? stack.includes('src/runtime/client/client.js')
|
||||
: loading;
|
||||
|
||||
// This flag is set in initial_fetch and subsequent_fetch
|
||||
const used_kit_fetch = init?.__sveltekit_fetch__;
|
||||
|
||||
if (in_load_heuristic && !used_kit_fetch) {
|
||||
console.warn(
|
||||
`Loading ${url} using \`window.fetch\`. For best results, use the \`fetch\` that is passed to your \`load\` function: https://kit.svelte.dev/docs/load#making-fetch-requests`
|
||||
);
|
||||
}
|
||||
|
||||
const method = input instanceof Request ? input.method : init?.method || 'GET';
|
||||
|
||||
if (method !== 'GET') {
|
||||
cache.delete(build_selector(input));
|
||||
}
|
||||
|
||||
return native_fetch(input, init);
|
||||
};
|
||||
} else {
|
||||
window.fetch = (input, init) => {
|
||||
const method = input instanceof Request ? input.method : init?.method || 'GET';
|
||||
|
||||
if (method !== 'GET') {
|
||||
cache.delete(build_selector(input));
|
||||
}
|
||||
|
||||
return native_fetch(input, init);
|
||||
};
|
||||
}
|
||||
|
||||
const cache = new Map();
|
||||
|
||||
/**
|
||||
* Should be called on the initial run of load functions that hydrate the page.
|
||||
* Saves any requests with cache-control max-age to the cache.
|
||||
* @param {URL | string} resource
|
||||
* @param {RequestInit} [opts]
|
||||
*/
|
||||
export function initial_fetch(resource, opts) {
|
||||
const selector = build_selector(resource, opts);
|
||||
|
||||
const script = document.querySelector(selector);
|
||||
if (script?.textContent) {
|
||||
const { body, ...init } = JSON.parse(script.textContent);
|
||||
|
||||
const ttl = script.getAttribute('data-ttl');
|
||||
if (ttl) cache.set(selector, { body, init, ttl: 1000 * Number(ttl) });
|
||||
|
||||
return Promise.resolve(new Response(body, init));
|
||||
}
|
||||
|
||||
return DEV ? dev_fetch(resource, opts) : window.fetch(resource, opts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to get the response from the cache, if max-age allows it, else does a fetch.
|
||||
* @param {URL | string} resource
|
||||
* @param {string} resolved
|
||||
* @param {RequestInit} [opts]
|
||||
*/
|
||||
export function subsequent_fetch(resource, resolved, opts) {
|
||||
if (cache.size > 0) {
|
||||
const selector = build_selector(resource, opts);
|
||||
const cached = cache.get(selector);
|
||||
if (cached) {
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/Request/cache#value
|
||||
if (
|
||||
performance.now() < cached.ttl &&
|
||||
['default', 'force-cache', 'only-if-cached', undefined].includes(opts?.cache)
|
||||
) {
|
||||
return new Response(cached.body, cached.init);
|
||||
}
|
||||
|
||||
cache.delete(selector);
|
||||
}
|
||||
}
|
||||
|
||||
return DEV ? dev_fetch(resolved, opts) : window.fetch(resolved, opts);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {RequestInfo | URL} resource
|
||||
* @param {RequestInit & Record<string, any> | undefined} opts
|
||||
*/
|
||||
function dev_fetch(resource, opts) {
|
||||
const patched_opts = { ...opts };
|
||||
// This assigns the __sveltekit_fetch__ flag and makes it non-enumerable
|
||||
Object.defineProperty(patched_opts, '__sveltekit_fetch__', {
|
||||
value: true,
|
||||
writable: true,
|
||||
configurable: true
|
||||
});
|
||||
return window.fetch(resource, patched_opts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the cache key for a given request
|
||||
* @param {URL | RequestInfo} resource
|
||||
* @param {RequestInit} [opts]
|
||||
*/
|
||||
function build_selector(resource, opts) {
|
||||
const url = JSON.stringify(resource instanceof Request ? resource.url : resource);
|
||||
|
||||
let selector = `script[data-sveltekit-fetched][data-url=${url}]`;
|
||||
|
||||
if (opts?.headers || opts?.body) {
|
||||
/** @type {import('types').StrictBody[]} */
|
||||
const values = [];
|
||||
|
||||
if (opts.headers) {
|
||||
values.push([...new Headers(opts.headers)].join(','));
|
||||
}
|
||||
|
||||
if (opts.body && (typeof opts.body === 'string' || ArrayBuffer.isView(opts.body))) {
|
||||
values.push(opts.body);
|
||||
}
|
||||
|
||||
selector += `[data-hash="${hash(...values)}"]`;
|
||||
}
|
||||
|
||||
return selector;
|
||||
}
|
57
node_modules/@sveltejs/kit/src/runtime/client/parse.js
generated
vendored
Normal file
57
node_modules/@sveltejs/kit/src/runtime/client/parse.js
generated
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
import { exec, parse_route_id } from '../../utils/routing.js';
|
||||
|
||||
/**
|
||||
* @param {import('./types.js').SvelteKitApp} app
|
||||
* @returns {import('types').CSRRoute[]}
|
||||
*/
|
||||
export function parse({ nodes, server_loads, dictionary, matchers }) {
|
||||
const layouts_with_server_load = new Set(server_loads);
|
||||
|
||||
return Object.entries(dictionary).map(([id, [leaf, layouts, errors]]) => {
|
||||
const { pattern, params } = parse_route_id(id);
|
||||
|
||||
const route = {
|
||||
id,
|
||||
/** @param {string} path */
|
||||
exec: (path) => {
|
||||
const match = pattern.exec(path);
|
||||
if (match) return exec(match, params, matchers);
|
||||
},
|
||||
errors: [1, ...(errors || [])].map((n) => nodes[n]),
|
||||
layouts: [0, ...(layouts || [])].map(create_layout_loader),
|
||||
leaf: create_leaf_loader(leaf)
|
||||
};
|
||||
|
||||
// bit of a hack, but ensures that layout/error node lists are the same
|
||||
// length, without which the wrong data will be applied if the route
|
||||
// manifest looks like `[[a, b], [c,], d]`
|
||||
route.errors.length = route.layouts.length = Math.max(
|
||||
route.errors.length,
|
||||
route.layouts.length
|
||||
);
|
||||
|
||||
return route;
|
||||
});
|
||||
|
||||
/**
|
||||
* @param {number} id
|
||||
* @returns {[boolean, import('types').CSRPageNodeLoader]}
|
||||
*/
|
||||
function create_leaf_loader(id) {
|
||||
// whether or not the route uses the server data is
|
||||
// encoded using the ones' complement, to save space
|
||||
const uses_server_data = id < 0;
|
||||
if (uses_server_data) id = ~id;
|
||||
return [uses_server_data, nodes[id]];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number | undefined} id
|
||||
* @returns {[boolean, import('types').CSRPageNodeLoader] | undefined}
|
||||
*/
|
||||
function create_layout_loader(id) {
|
||||
// whether or not the layout uses the server data is
|
||||
// encoded in the layouts array, to save space
|
||||
return id === undefined ? id : [layouts_with_server_load.has(id), nodes[id]];
|
||||
}
|
||||
}
|
25
node_modules/@sveltejs/kit/src/runtime/client/session-storage.js
generated
vendored
Normal file
25
node_modules/@sveltejs/kit/src/runtime/client/session-storage.js
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Read a value from `sessionStorage`
|
||||
* @param {string} key
|
||||
*/
|
||||
export function get(key) {
|
||||
try {
|
||||
return JSON.parse(sessionStorage[key]);
|
||||
} catch {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a value to `sessionStorage`
|
||||
* @param {string} key
|
||||
* @param {any} value
|
||||
*/
|
||||
export function set(key, value) {
|
||||
const json = JSON.stringify(value);
|
||||
try {
|
||||
sessionStorage[key] = json;
|
||||
} catch {
|
||||
// do nothing
|
||||
}
|
||||
}
|
53
node_modules/@sveltejs/kit/src/runtime/client/singletons.js
generated
vendored
Normal file
53
node_modules/@sveltejs/kit/src/runtime/client/singletons.js
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
import { writable } from 'svelte/store';
|
||||
import { create_updated_store, notifiable_store } from './utils.js';
|
||||
import { BROWSER } from 'esm-env';
|
||||
|
||||
/** @type {import('./types.js').Client} */
|
||||
export let client;
|
||||
|
||||
/**
|
||||
* @param {{
|
||||
* client: import('./types.js').Client;
|
||||
* }} opts
|
||||
*/
|
||||
export function init(opts) {
|
||||
client = opts.client;
|
||||
}
|
||||
|
||||
/**
|
||||
* @template {keyof typeof client} T
|
||||
* @param {T} key
|
||||
* @returns {typeof client[T]}
|
||||
*/
|
||||
export function client_method(key) {
|
||||
if (!BROWSER) {
|
||||
if (key === 'before_navigate' || key === 'after_navigate' || key === 'on_navigate') {
|
||||
// @ts-expect-error doesn't recognize that both keys here return void so expects a async function
|
||||
return () => {};
|
||||
} else {
|
||||
/** @type {Record<string, string>} */
|
||||
const name_lookup = {
|
||||
disable_scroll_handling: 'disableScrollHandling',
|
||||
preload_data: 'preloadData',
|
||||
preload_code: 'preloadCode',
|
||||
invalidate_all: 'invalidateAll'
|
||||
};
|
||||
|
||||
return () => {
|
||||
throw new Error(`Cannot call ${name_lookup[key] ?? key}(...) on the server`);
|
||||
};
|
||||
}
|
||||
} else {
|
||||
// @ts-expect-error
|
||||
return (...args) => client[key](...args);
|
||||
}
|
||||
}
|
||||
|
||||
export const stores = {
|
||||
url: /* @__PURE__ */ notifiable_store({}),
|
||||
page: /* @__PURE__ */ notifiable_store({}),
|
||||
navigating: /* @__PURE__ */ writable(
|
||||
/** @type {import('@sveltejs/kit').Navigation | null} */ (null)
|
||||
),
|
||||
updated: /* @__PURE__ */ create_updated_store()
|
||||
};
|
28
node_modules/@sveltejs/kit/src/runtime/client/start.js
generated
vendored
Normal file
28
node_modules/@sveltejs/kit/src/runtime/client/start.js
generated
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
import { DEV } from 'esm-env';
|
||||
import { create_client } from './client.js';
|
||||
import { init } from './singletons.js';
|
||||
|
||||
/**
|
||||
* @param {import('./types.js').SvelteKitApp} app
|
||||
* @param {HTMLElement} target
|
||||
* @param {Parameters<import('./types.js').Client['_hydrate']>[0]} [hydrate]
|
||||
*/
|
||||
export async function start(app, target, hydrate) {
|
||||
if (DEV && target === document.body) {
|
||||
console.warn(
|
||||
'Placing %sveltekit.body% directly inside <body> is not recommended, as your app may break for users who have certain browser extensions installed.\n\nConsider wrapping it in an element:\n\n<div style="display: contents">\n %sveltekit.body%\n</div>'
|
||||
);
|
||||
}
|
||||
|
||||
const client = create_client(app, target);
|
||||
|
||||
init({ client });
|
||||
|
||||
if (hydrate) {
|
||||
await client._hydrate(hydrate);
|
||||
} else {
|
||||
client.goto(location.href, { replaceState: true });
|
||||
}
|
||||
|
||||
client._start_router();
|
||||
}
|
123
node_modules/@sveltejs/kit/src/runtime/client/types.d.ts
generated
vendored
Normal file
123
node_modules/@sveltejs/kit/src/runtime/client/types.d.ts
generated
vendored
Normal file
@ -0,0 +1,123 @@
|
||||
import { applyAction } from '../app/forms.js';
|
||||
import {
|
||||
afterNavigate,
|
||||
beforeNavigate,
|
||||
onNavigate,
|
||||
goto,
|
||||
invalidate,
|
||||
invalidateAll,
|
||||
preloadCode,
|
||||
preloadData
|
||||
} from '../app/navigation.js';
|
||||
import { SvelteComponent } from 'svelte';
|
||||
import { ClientHooks, CSRPageNode, CSRPageNodeLoader, CSRRoute, TrailingSlash, Uses } from 'types';
|
||||
import { Page, ParamMatcher } from '@sveltejs/kit';
|
||||
|
||||
export interface SvelteKitApp {
|
||||
/**
|
||||
* A list of all the error/layout/page nodes used in the app
|
||||
*/
|
||||
nodes: CSRPageNodeLoader[];
|
||||
|
||||
/**
|
||||
* A list of all layout node ids that have a server load function.
|
||||
* Pages are not present because it's shorter to encode it on the leaf itself.
|
||||
*/
|
||||
server_loads: number[];
|
||||
|
||||
/**
|
||||
* A map of `[routeId: string]: [leaf, layouts, errors]` tuples, which
|
||||
* is parsed into an array of routes on startup. The numbers refer to the indices in `nodes`.
|
||||
* If the leaf number is negative, it means it does use a server load function and the complement is the node index.
|
||||
* The route layout and error nodes are not referenced, they are always number 0 and 1 and always apply.
|
||||
*/
|
||||
dictionary: Record<string, [leaf: number, layouts: number[], errors?: number[]]>;
|
||||
|
||||
matchers: Record<string, ParamMatcher>;
|
||||
|
||||
hooks: ClientHooks;
|
||||
|
||||
root: typeof SvelteComponent;
|
||||
}
|
||||
|
||||
export interface Client {
|
||||
// public API, exposed via $app/navigation
|
||||
after_navigate: typeof afterNavigate;
|
||||
before_navigate: typeof beforeNavigate;
|
||||
on_navigate: typeof onNavigate;
|
||||
disable_scroll_handling(): void;
|
||||
goto: typeof goto;
|
||||
invalidate: typeof invalidate;
|
||||
invalidate_all: typeof invalidateAll;
|
||||
preload_code: typeof preloadCode;
|
||||
preload_data: typeof preloadData;
|
||||
apply_action: typeof applyAction;
|
||||
|
||||
// private API
|
||||
_hydrate(opts: {
|
||||
status: number;
|
||||
error: App.Error | null;
|
||||
node_ids: number[];
|
||||
params: Record<string, string>;
|
||||
route: { id: string | null };
|
||||
data: Array<import('types').ServerDataNode | null>;
|
||||
form: Record<string, any> | null;
|
||||
}): Promise<void>;
|
||||
_start_router(): void;
|
||||
}
|
||||
|
||||
export type NavigationIntent = {
|
||||
/** `url.pathname + url.search` */
|
||||
id: string;
|
||||
/** Whether we are invalidating or navigating */
|
||||
invalidating: boolean;
|
||||
/** The route parameters */
|
||||
params: Record<string, string>;
|
||||
/** The route that matches `path` */
|
||||
route: CSRRoute;
|
||||
/** The destination URL */
|
||||
url: URL;
|
||||
};
|
||||
|
||||
export type NavigationResult = NavigationRedirect | NavigationFinished;
|
||||
|
||||
export type NavigationRedirect = {
|
||||
type: 'redirect';
|
||||
location: string;
|
||||
};
|
||||
|
||||
export type NavigationFinished = {
|
||||
type: 'loaded';
|
||||
state: NavigationState;
|
||||
props: {
|
||||
constructors: Array<typeof SvelteComponent>;
|
||||
components?: Array<SvelteComponent>;
|
||||
page?: Page;
|
||||
form?: Record<string, any> | null;
|
||||
[key: `data_${number}`]: Record<string, any>;
|
||||
};
|
||||
};
|
||||
|
||||
export type BranchNode = {
|
||||
node: CSRPageNode;
|
||||
loader: CSRPageNodeLoader;
|
||||
server: DataNode | null;
|
||||
universal: DataNode | null;
|
||||
data: Record<string, any> | null;
|
||||
slash?: TrailingSlash;
|
||||
};
|
||||
|
||||
export interface DataNode {
|
||||
type: 'data';
|
||||
data: Record<string, any> | null;
|
||||
uses: Uses;
|
||||
slash?: TrailingSlash;
|
||||
}
|
||||
|
||||
export interface NavigationState {
|
||||
branch: Array<BranchNode | undefined>;
|
||||
error: App.Error | null;
|
||||
params: Record<string, string>;
|
||||
route: CSRRoute | null;
|
||||
url: URL;
|
||||
}
|
296
node_modules/@sveltejs/kit/src/runtime/client/utils.js
generated
vendored
Normal file
296
node_modules/@sveltejs/kit/src/runtime/client/utils.js
generated
vendored
Normal file
@ -0,0 +1,296 @@
|
||||
import { BROWSER, DEV } from 'esm-env';
|
||||
import { writable } from 'svelte/store';
|
||||
import { assets } from '__sveltekit/paths';
|
||||
import { version } from '__sveltekit/environment';
|
||||
import { PRELOAD_PRIORITIES } from './constants.js';
|
||||
|
||||
/* global __SVELTEKIT_APP_VERSION_FILE__, __SVELTEKIT_APP_VERSION_POLL_INTERVAL__ */
|
||||
|
||||
export const origin = BROWSER ? location.origin : '';
|
||||
|
||||
/** @param {HTMLDocument} doc */
|
||||
export function get_base_uri(doc) {
|
||||
let baseURI = doc.baseURI;
|
||||
|
||||
if (!baseURI) {
|
||||
const baseTags = doc.getElementsByTagName('base');
|
||||
baseURI = baseTags.length ? baseTags[0].href : doc.URL;
|
||||
}
|
||||
|
||||
return baseURI;
|
||||
}
|
||||
|
||||
export function scroll_state() {
|
||||
return {
|
||||
x: pageXOffset,
|
||||
y: pageYOffset
|
||||
};
|
||||
}
|
||||
|
||||
const warned = new WeakSet();
|
||||
|
||||
/** @typedef {keyof typeof valid_link_options} LinkOptionName */
|
||||
|
||||
const valid_link_options = /** @type {const} */ ({
|
||||
'preload-code': ['', 'off', 'tap', 'hover', 'viewport', 'eager'],
|
||||
'preload-data': ['', 'off', 'tap', 'hover'],
|
||||
keepfocus: ['', 'true', 'off', 'false'],
|
||||
noscroll: ['', 'true', 'off', 'false'],
|
||||
reload: ['', 'true', 'off', 'false'],
|
||||
replacestate: ['', 'true', 'off', 'false']
|
||||
});
|
||||
|
||||
/**
|
||||
* @template {LinkOptionName} T
|
||||
* @typedef {typeof valid_link_options[T][number]} ValidLinkOptions
|
||||
*/
|
||||
|
||||
/**
|
||||
* @template {LinkOptionName} T
|
||||
* @param {Element} element
|
||||
* @param {T} name
|
||||
*/
|
||||
function link_option(element, name) {
|
||||
const value = /** @type {ValidLinkOptions<T> | null} */ (
|
||||
element.getAttribute(`data-sveltekit-${name}`)
|
||||
);
|
||||
|
||||
if (DEV) {
|
||||
validate_link_option(element, name, value);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @template {LinkOptionName} T
|
||||
* @template {ValidLinkOptions<T> | null} U
|
||||
* @param {Element} element
|
||||
* @param {T} name
|
||||
* @param {U} value
|
||||
*/
|
||||
function validate_link_option(element, name, value) {
|
||||
if (value === null) return;
|
||||
|
||||
// @ts-expect-error - includes is dumb
|
||||
if (!warned.has(element) && !valid_link_options[name].includes(value)) {
|
||||
console.error(
|
||||
`Unexpected value for ${name} — should be one of ${valid_link_options[name]
|
||||
.map((option) => JSON.stringify(option))
|
||||
.join(', ')}`,
|
||||
element
|
||||
);
|
||||
|
||||
warned.add(element);
|
||||
}
|
||||
}
|
||||
|
||||
const levels = {
|
||||
...PRELOAD_PRIORITIES,
|
||||
'': PRELOAD_PRIORITIES.hover
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Element} element
|
||||
* @returns {Element | null}
|
||||
*/
|
||||
function parent_element(element) {
|
||||
let parent = element.assignedSlot ?? element.parentNode;
|
||||
|
||||
// @ts-expect-error handle shadow roots
|
||||
if (parent?.nodeType === 11) parent = parent.host;
|
||||
|
||||
return /** @type {Element} */ (parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} element
|
||||
* @param {Element} target
|
||||
*/
|
||||
export function find_anchor(element, target) {
|
||||
while (element && element !== target) {
|
||||
if (element.nodeName.toUpperCase() === 'A' && element.hasAttribute('href')) {
|
||||
return /** @type {HTMLAnchorElement | SVGAElement} */ (element);
|
||||
}
|
||||
|
||||
element = /** @type {Element} */ (parent_element(element));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLAnchorElement | SVGAElement} a
|
||||
* @param {string} base
|
||||
*/
|
||||
export function get_link_info(a, base) {
|
||||
/** @type {URL | undefined} */
|
||||
let url;
|
||||
|
||||
try {
|
||||
url = new URL(a instanceof SVGAElement ? a.href.baseVal : a.href, document.baseURI);
|
||||
} catch {}
|
||||
|
||||
const target = a instanceof SVGAElement ? a.target.baseVal : a.target;
|
||||
|
||||
const external =
|
||||
!url ||
|
||||
!!target ||
|
||||
is_external_url(url, base) ||
|
||||
(a.getAttribute('rel') || '').split(/\s+/).includes('external');
|
||||
|
||||
const download = url?.origin === origin && a.hasAttribute('download');
|
||||
|
||||
return { url, external, target, download };
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLFormElement | HTMLAnchorElement | SVGAElement} element
|
||||
*/
|
||||
export function get_router_options(element) {
|
||||
/** @type {ValidLinkOptions<'keepfocus'> | null} */
|
||||
let keep_focus = null;
|
||||
|
||||
/** @type {ValidLinkOptions<'noscroll'> | null} */
|
||||
let noscroll = null;
|
||||
|
||||
/** @type {ValidLinkOptions<'preload-code'> | null} */
|
||||
let preload_code = null;
|
||||
|
||||
/** @type {ValidLinkOptions<'preload-data'> | null} */
|
||||
let preload_data = null;
|
||||
|
||||
/** @type {ValidLinkOptions<'reload'> | null} */
|
||||
let reload = null;
|
||||
|
||||
/** @type {ValidLinkOptions<'replacestate'> | null} */
|
||||
let replace_state = null;
|
||||
|
||||
/** @type {Element} */
|
||||
let el = element;
|
||||
|
||||
while (el && el !== document.documentElement) {
|
||||
if (preload_code === null) preload_code = link_option(el, 'preload-code');
|
||||
if (preload_data === null) preload_data = link_option(el, 'preload-data');
|
||||
if (keep_focus === null) keep_focus = link_option(el, 'keepfocus');
|
||||
if (noscroll === null) noscroll = link_option(el, 'noscroll');
|
||||
if (reload === null) reload = link_option(el, 'reload');
|
||||
if (replace_state === null) replace_state = link_option(el, 'replacestate');
|
||||
|
||||
el = /** @type {Element} */ (parent_element(el));
|
||||
}
|
||||
|
||||
/** @param {string | null} value */
|
||||
function get_option_state(value) {
|
||||
switch (value) {
|
||||
case '':
|
||||
case 'true':
|
||||
return true;
|
||||
case 'off':
|
||||
case 'false':
|
||||
return false;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
preload_code: levels[preload_code ?? 'off'],
|
||||
preload_data: levels[preload_data ?? 'off'],
|
||||
keep_focus: get_option_state(keep_focus),
|
||||
noscroll: get_option_state(noscroll),
|
||||
reload: get_option_state(reload),
|
||||
replace_state: get_option_state(replace_state)
|
||||
};
|
||||
}
|
||||
|
||||
/** @param {any} value */
|
||||
export function notifiable_store(value) {
|
||||
const store = writable(value);
|
||||
let ready = true;
|
||||
|
||||
function notify() {
|
||||
ready = true;
|
||||
store.update((val) => val);
|
||||
}
|
||||
|
||||
/** @param {any} new_value */
|
||||
function set(new_value) {
|
||||
ready = false;
|
||||
store.set(new_value);
|
||||
}
|
||||
|
||||
/** @param {(value: any) => void} run */
|
||||
function subscribe(run) {
|
||||
/** @type {any} */
|
||||
let old_value;
|
||||
return store.subscribe((new_value) => {
|
||||
if (old_value === undefined || (ready && new_value !== old_value)) {
|
||||
run((old_value = new_value));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return { notify, set, subscribe };
|
||||
}
|
||||
|
||||
export function create_updated_store() {
|
||||
const { set, subscribe } = writable(false);
|
||||
|
||||
if (DEV || !BROWSER) {
|
||||
return {
|
||||
subscribe,
|
||||
check: async () => false
|
||||
};
|
||||
}
|
||||
|
||||
const interval = __SVELTEKIT_APP_VERSION_POLL_INTERVAL__;
|
||||
|
||||
/** @type {NodeJS.Timeout} */
|
||||
let timeout;
|
||||
|
||||
/** @type {() => Promise<boolean>} */
|
||||
async function check() {
|
||||
clearTimeout(timeout);
|
||||
|
||||
if (interval) timeout = setTimeout(check, interval);
|
||||
|
||||
try {
|
||||
const res = await fetch(`${assets}/${__SVELTEKIT_APP_VERSION_FILE__}`, {
|
||||
headers: {
|
||||
pragma: 'no-cache',
|
||||
'cache-control': 'no-cache'
|
||||
}
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const data = await res.json();
|
||||
const updated = data.version !== version;
|
||||
|
||||
if (updated) {
|
||||
set(true);
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
|
||||
return updated;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (interval) timeout = setTimeout(check, interval);
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
check
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {URL} url
|
||||
* @param {string} base
|
||||
*/
|
||||
export function is_external_url(url, base) {
|
||||
return url.origin !== origin || !url.pathname.startsWith(base);
|
||||
}
|
Reference in New Issue
Block a user