this repo has no description
1/** @returns {void} */
2export function noop() {}
3
4export const identity = (x) => x;
5
6/**
7 * @template T
8 * @template S
9 * @param {T} tar
10 * @param {S} src
11 * @returns {T & S}
12 */
13export function assign(tar, src) {
14 // @ts-ignore
15 for (const k in src) tar[k] = src[k];
16 return /** @type {T & S} */ (tar);
17}
18
19// Adapted from https://github.com/then/is-promise/blob/master/index.js
20// Distributed under MIT License https://github.com/then/is-promise/blob/master/LICENSE
21/**
22 * @param {any} value
23 * @returns {value is PromiseLike<any>}
24 */
25export function is_promise(value) {
26 return (
27 !!value &&
28 (typeof value === 'object' || typeof value === 'function') &&
29 typeof (/** @type {any} */ (value).then) === 'function'
30 );
31}
32
33/** @returns {void} */
34export function add_location(element, file, line, column, char) {
35 element.__svelte_meta = {
36 loc: { file, line, column, char }
37 };
38}
39
40export function run(fn) {
41 return fn();
42}
43
44export function blank_object() {
45 return Object.create(null);
46}
47
48/**
49 * @param {Function[]} fns
50 * @returns {void}
51 */
52export function run_all(fns) {
53 fns.forEach(run);
54}
55
56/**
57 * @param {any} thing
58 * @returns {thing is Function}
59 */
60export function is_function(thing) {
61 return typeof thing === 'function';
62}
63
64/** @returns {boolean} */
65export function safe_not_equal(a, b) {
66 return a != a ? b == b : a !== b || (a && typeof a === 'object') || typeof a === 'function';
67}
68
69let src_url_equal_anchor;
70
71/**
72 * @param {string} element_src
73 * @param {string} url
74 * @returns {boolean}
75 */
76export function src_url_equal(element_src, url) {
77 if (element_src === url) return true;
78 if (!src_url_equal_anchor) {
79 src_url_equal_anchor = document.createElement('a');
80 }
81 // This is actually faster than doing URL(..).href
82 src_url_equal_anchor.href = url;
83 return element_src === src_url_equal_anchor.href;
84}
85
86/** @param {string} srcset */
87function split_srcset(srcset) {
88 return srcset.split(',').map((src) => src.trim().split(' ').filter(Boolean));
89}
90
91/**
92 * @param {HTMLSourceElement | HTMLImageElement} element_srcset
93 * @param {string | undefined | null} srcset
94 * @returns {boolean}
95 */
96export function srcset_url_equal(element_srcset, srcset) {
97 const element_urls = split_srcset(element_srcset.srcset);
98 const urls = split_srcset(srcset || '');
99
100 return (
101 urls.length === element_urls.length &&
102 urls.every(
103 ([url, width], i) =>
104 width === element_urls[i][1] &&
105 // We need to test both ways because Vite will create an a full URL with
106 // `new URL(asset, import.meta.url).href` for the client when `base: './'`, and the
107 // relative URLs inside srcset are not automatically resolved to absolute URLs by
108 // browsers (in contrast to img.src). This means both SSR and DOM code could
109 // contain relative or absolute URLs.
110 (src_url_equal(element_urls[i][0], url) || src_url_equal(url, element_urls[i][0]))
111 )
112 );
113}
114
115/** @returns {boolean} */
116export function not_equal(a, b) {
117 return a != a ? b == b : a !== b;
118}
119
120/** @returns {boolean} */
121export function is_empty(obj) {
122 return Object.keys(obj).length === 0;
123}
124
125/** @returns {void} */
126export function validate_store(store, name) {
127 if (store != null && typeof store.subscribe !== 'function') {
128 throw new Error(`'${name}' is not a store with a 'subscribe' method`);
129 }
130}
131
132export function subscribe(store, ...callbacks) {
133 if (store == null) {
134 for (const callback of callbacks) {
135 callback(undefined);
136 }
137 return noop;
138 }
139 const unsub = store.subscribe(...callbacks);
140 return unsub.unsubscribe ? () => unsub.unsubscribe() : unsub;
141}
142
143/**
144 * Get the current value from a store by subscribing and immediately unsubscribing.
145 *
146 * https://svelte.dev/docs/svelte-store#get
147 * @template T
148 * @param {import('../store/public.js').Readable<T>} store
149 * @returns {T}
150 */
151export function get_store_value(store) {
152 let value;
153 subscribe(store, (_) => (value = _))();
154 return value;
155}
156
157/** @returns {void} */
158export function component_subscribe(component, store, callback) {
159 component.$$.on_destroy.push(subscribe(store, callback));
160}
161
162export function create_slot(definition, ctx, $$scope, fn) {
163 if (definition) {
164 const slot_ctx = get_slot_context(definition, ctx, $$scope, fn);
165 return definition[0](slot_ctx);
166 }
167}
168
169function get_slot_context(definition, ctx, $$scope, fn) {
170 return definition[1] && fn ? assign($$scope.ctx.slice(), definition[1](fn(ctx))) : $$scope.ctx;
171}
172
173export function get_slot_changes(definition, $$scope, dirty, fn) {
174 if (definition[2] && fn) {
175 const lets = definition[2](fn(dirty));
176 if ($$scope.dirty === undefined) {
177 return lets;
178 }
179 if (typeof lets === 'object') {
180 const merged = [];
181 const len = Math.max($$scope.dirty.length, lets.length);
182 for (let i = 0; i < len; i += 1) {
183 merged[i] = $$scope.dirty[i] | lets[i];
184 }
185 return merged;
186 }
187 return $$scope.dirty | lets;
188 }
189 return $$scope.dirty;
190}
191
192/** @returns {void} */
193export function update_slot_base(
194 slot,
195 slot_definition,
196 ctx,
197 $$scope,
198 slot_changes,
199 get_slot_context_fn
200) {
201 if (slot_changes) {
202 const slot_context = get_slot_context(slot_definition, ctx, $$scope, get_slot_context_fn);
203 slot.p(slot_context, slot_changes);
204 }
205}
206
207/** @returns {void} */
208export function update_slot(
209 slot,
210 slot_definition,
211 ctx,
212 $$scope,
213 dirty,
214 get_slot_changes_fn,
215 get_slot_context_fn
216) {
217 const slot_changes = get_slot_changes(slot_definition, $$scope, dirty, get_slot_changes_fn);
218 update_slot_base(slot, slot_definition, ctx, $$scope, slot_changes, get_slot_context_fn);
219}
220
221/** @returns {any[] | -1} */
222export function get_all_dirty_from_scope($$scope) {
223 if ($$scope.ctx.length > 32) {
224 const dirty = [];
225 const length = $$scope.ctx.length / 32;
226 for (let i = 0; i < length; i++) {
227 dirty[i] = -1;
228 }
229 return dirty;
230 }
231 return -1;
232}
233
234/** @returns {{}} */
235export function exclude_internal_props(props) {
236 const result = {};
237 for (const k in props) if (k[0] !== '$') result[k] = props[k];
238 return result;
239}
240
241/** @returns {{}} */
242export function compute_rest_props(props, keys) {
243 const rest = {};
244 keys = new Set(keys);
245 for (const k in props) if (!keys.has(k) && k[0] !== '$') rest[k] = props[k];
246 return rest;
247}
248
249/** @returns {{}} */
250export function compute_slots(slots) {
251 const result = {};
252 for (const key in slots) {
253 result[key] = true;
254 }
255 return result;
256}
257
258/** @returns {(this: any, ...args: any[]) => void} */
259export function once(fn) {
260 let ran = false;
261 return function (...args) {
262 if (ran) return;
263 ran = true;
264 fn.call(this, ...args);
265 };
266}
267
268export function null_to_empty(value) {
269 return value == null ? '' : value;
270}
271
272export function set_store_value(store, ret, value) {
273 store.set(value);
274 return ret;
275}
276
277export const has_prop = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop);
278
279export function action_destroyer(action_result) {
280 return action_result && is_function(action_result.destroy) ? action_result.destroy : noop;
281}
282
283/** @param {number | string} value
284 * @returns {[number, string]}
285 */
286export function split_css_unit(value) {
287 const split = typeof value === 'string' && value.match(/^\s*(-?[\d.]+)([^\s]*)\s*$/);
288 return split ? [parseFloat(split[1]), split[2] || 'px'] : [/** @type {number} */ (value), 'px'];
289}
290
291export const contenteditable_truthy_values = ['', true, 1, 'true', 'contenteditable'];