/** @returns {void} */ export function noop() {} export const identity = (x) => x; /** * @template T * @template S * @param {T} tar * @param {S} src * @returns {T & S} */ export function assign(tar, src) { // @ts-ignore for (const k in src) tar[k] = src[k]; return /** @type {T & S} */ (tar); } // Adapted from https://github.com/then/is-promise/blob/master/index.js // Distributed under MIT License https://github.com/then/is-promise/blob/master/LICENSE /** * @param {any} value * @returns {value is PromiseLike} */ export function is_promise(value) { return ( !!value && (typeof value === 'object' || typeof value === 'function') && typeof (/** @type {any} */ (value).then) === 'function' ); } /** @returns {void} */ export function add_location(element, file, line, column, char) { element.__svelte_meta = { loc: { file, line, column, char } }; } export function run(fn) { return fn(); } export function blank_object() { return Object.create(null); } /** * @param {Function[]} fns * @returns {void} */ export function run_all(fns) { fns.forEach(run); } /** * @param {any} thing * @returns {thing is Function} */ export function is_function(thing) { return typeof thing === 'function'; } /** @returns {boolean} */ export function safe_not_equal(a, b) { return a != a ? b == b : a !== b || (a && typeof a === 'object') || typeof a === 'function'; } let src_url_equal_anchor; /** * @param {string} element_src * @param {string} url * @returns {boolean} */ export function src_url_equal(element_src, url) { if (element_src === url) return true; if (!src_url_equal_anchor) { src_url_equal_anchor = document.createElement('a'); } // This is actually faster than doing URL(..).href src_url_equal_anchor.href = url; return element_src === src_url_equal_anchor.href; } /** @param {string} srcset */ function split_srcset(srcset) { return srcset.split(',').map((src) => src.trim().split(' ').filter(Boolean)); } /** * @param {HTMLSourceElement | HTMLImageElement} element_srcset * @param {string | undefined | null} srcset * @returns {boolean} */ export function srcset_url_equal(element_srcset, srcset) { const element_urls = split_srcset(element_srcset.srcset); const urls = split_srcset(srcset || ''); return ( urls.length === element_urls.length && urls.every( ([url, width], i) => width === element_urls[i][1] && // We need to test both ways because Vite will create an a full URL with // `new URL(asset, import.meta.url).href` for the client when `base: './'`, and the // relative URLs inside srcset are not automatically resolved to absolute URLs by // browsers (in contrast to img.src). This means both SSR and DOM code could // contain relative or absolute URLs. (src_url_equal(element_urls[i][0], url) || src_url_equal(url, element_urls[i][0])) ) ); } /** @returns {boolean} */ export function not_equal(a, b) { return a != a ? b == b : a !== b; } /** @returns {boolean} */ export function is_empty(obj) { return Object.keys(obj).length === 0; } /** @returns {void} */ export function validate_store(store, name) { if (store != null && typeof store.subscribe !== 'function') { throw new Error(`'${name}' is not a store with a 'subscribe' method`); } } export function subscribe(store, ...callbacks) { if (store == null) { for (const callback of callbacks) { callback(undefined); } return noop; } const unsub = store.subscribe(...callbacks); return unsub.unsubscribe ? () => unsub.unsubscribe() : unsub; } /** * Get the current value from a store by subscribing and immediately unsubscribing. * * https://svelte.dev/docs/svelte-store#get * @template T * @param {import('../store/public.js').Readable} store * @returns {T} */ export function get_store_value(store) { let value; subscribe(store, (_) => (value = _))(); return value; } /** @returns {void} */ export function component_subscribe(component, store, callback) { component.$$.on_destroy.push(subscribe(store, callback)); } export function create_slot(definition, ctx, $$scope, fn) { if (definition) { const slot_ctx = get_slot_context(definition, ctx, $$scope, fn); return definition[0](slot_ctx); } } function get_slot_context(definition, ctx, $$scope, fn) { return definition[1] && fn ? assign($$scope.ctx.slice(), definition[1](fn(ctx))) : $$scope.ctx; } export function get_slot_changes(definition, $$scope, dirty, fn) { if (definition[2] && fn) { const lets = definition[2](fn(dirty)); if ($$scope.dirty === undefined) { return lets; } if (typeof lets === 'object') { const merged = []; const len = Math.max($$scope.dirty.length, lets.length); for (let i = 0; i < len; i += 1) { merged[i] = $$scope.dirty[i] | lets[i]; } return merged; } return $$scope.dirty | lets; } return $$scope.dirty; } /** @returns {void} */ export function update_slot_base( slot, slot_definition, ctx, $$scope, slot_changes, get_slot_context_fn ) { if (slot_changes) { const slot_context = get_slot_context(slot_definition, ctx, $$scope, get_slot_context_fn); slot.p(slot_context, slot_changes); } } /** @returns {void} */ export function update_slot( slot, slot_definition, ctx, $$scope, dirty, get_slot_changes_fn, get_slot_context_fn ) { const slot_changes = get_slot_changes(slot_definition, $$scope, dirty, get_slot_changes_fn); update_slot_base(slot, slot_definition, ctx, $$scope, slot_changes, get_slot_context_fn); } /** @returns {any[] | -1} */ export function get_all_dirty_from_scope($$scope) { if ($$scope.ctx.length > 32) { const dirty = []; const length = $$scope.ctx.length / 32; for (let i = 0; i < length; i++) { dirty[i] = -1; } return dirty; } return -1; } /** @returns {{}} */ export function exclude_internal_props(props) { const result = {}; for (const k in props) if (k[0] !== '$') result[k] = props[k]; return result; } /** @returns {{}} */ export function compute_rest_props(props, keys) { const rest = {}; keys = new Set(keys); for (const k in props) if (!keys.has(k) && k[0] !== '$') rest[k] = props[k]; return rest; } /** @returns {{}} */ export function compute_slots(slots) { const result = {}; for (const key in slots) { result[key] = true; } return result; } /** @returns {(this: any, ...args: any[]) => void} */ export function once(fn) { let ran = false; return function (...args) { if (ran) return; ran = true; fn.call(this, ...args); }; } export function null_to_empty(value) { return value == null ? '' : value; } export function set_store_value(store, ret, value) { store.set(value); return ret; } export const has_prop = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop); export function action_destroyer(action_result) { return action_result && is_function(action_result.destroy) ? action_result.destroy : noop; } /** @param {number | string} value * @returns {[number, string]} */ export function split_css_unit(value) { const split = typeof value === 'string' && value.match(/^\s*(-?[\d.]+)([^\s]*)\s*$/); return split ? [parseFloat(split[1]), split[2] || 'px'] : [/** @type {number} */ (value), 'px']; } export const contenteditable_truthy_values = ['', true, 1, 'true', 'contenteditable'];