• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

IgniteUI / igniteui-angular / 12072443768

28 Nov 2024 04:16PM UTC coverage: 91.621%. Remained the same
12072443768

Pull #15120

github

web-flow
fix(excel-style-filtering): reset filter value (#15090)

* fix(esf): show filters based on column name

* fix(esf-custom-dialog): filter expressionsList by column name

* chore(*): revert changes after branch retarget

---------

Co-authored-by: RadoMirchev <radoslav.p.mirchev@gmail.com>
Co-authored-by: Konstantin Dinev <kdinev@mail.bw.edu>
Co-authored-by: Galina Edinakova <gedinakova@infragistics.com>
Pull Request #15120: Mass Merge 19.0.x to master

12969 of 15202 branches covered (85.31%)

54 of 65 new or added lines in 14 files covered. (83.08%)

111 existing lines in 6 files now uncovered.

26309 of 28715 relevant lines covered (91.62%)

34021.05 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

84.31
/projects/igniteui-angular/src/lib/core/utils.ts
1
import { CurrencyPipe, formatDate as _formatDate, isPlatformBrowser } from '@angular/common';
2
import { Inject, Injectable, InjectionToken, PLATFORM_ID, inject } from '@angular/core';
3
import { mergeWith } from 'lodash-es';
4
import { NEVER, Observable } from 'rxjs';
5
import { setImmediate } from './setImmediate';
6
import { isDevMode } from '@angular/core';
7

8
/** @hidden @internal */
9
export const ELEMENTS_TOKEN = /*@__PURE__*/new InjectionToken<boolean>('elements environment');
2✔
10

11
/**
12
 * @hidden
13
 */
14
export const showMessage = (message: string, isMessageShown: boolean): boolean => {
2✔
UNCOV
15
    if (!isMessageShown && isDevMode()) {
×
16
        console.warn(message);
×
17
    }
18

UNCOV
19
    return true;
×
20
};
21

22
export const mkenum = <T extends { [index: string]: U }, U extends string>(x: T) => x;
4,305✔
23

24
/**
25
 *
26
 * @hidden @internal
27
 */
28
export const getResizeObserver = () => globalThis.window?.ResizeObserver;
27,035✔
29

30
/**
31
 * @hidden
32
 */
33
export const cloneArray = (array: any[], deep?: boolean) => {
2✔
34
    const arr = [];
23,888✔
35
    if (!array) {
23,888✔
36
        return arr;
7✔
37
    }
38
    let i = array.length;
23,881✔
39
    while (i--) {
23,881✔
40
        arr[i] = deep ? cloneValue(array[i]) : array[i];
205,705✔
41
    }
42
    return arr;
23,881✔
43
};
44

45
/**
46
 * Doesn't clone leaf items
47
 *
48
 * @hidden
49
 */
50
export const cloneHierarchicalArray = (array: any[], childDataKey: any): any[] => {
2✔
51
    const result: any[] = [];
542✔
52
    if (!array) {
542!
UNCOV
53
        return result;
×
54
    }
55

56
    for (const item of array) {
542✔
57
        const clonedItem = cloneValue(item);
908✔
58
        if (Array.isArray(item[childDataKey])) {
908✔
59
            clonedItem[childDataKey] = cloneHierarchicalArray(clonedItem[childDataKey], childDataKey);
469✔
60
        }
61
        result.push(clonedItem);
908✔
62
    }
63
    return result;
542✔
64
};
65

66
/**
67
 * Creates an object with prototype from provided source and copies
68
 * all properties descriptors from provided source
69
 * @param obj Source to copy prototype and descriptors from
70
 * @returns New object with cloned prototype and property descriptors
71
 */
72
export const copyDescriptors = (obj) => {
2✔
73
    if (obj) {
133✔
74
        return Object.create(
133✔
75
            Object.getPrototypeOf(obj),
76
            Object.getOwnPropertyDescriptors(obj)
77
        );
78
    }
79
}
80

81

82
/**
83
 * Deep clones all first level keys of Obj2 and merges them to Obj1
84
 *
85
 * @param obj1 Object to merge into
86
 * @param obj2 Object to merge from
87
 * @returns Obj1 with merged cloned keys from Obj2
88
 * @hidden
89
 */
90
export const mergeObjects = (obj1: any, obj2: any): any => mergeWith(obj1, obj2, (objValue, srcValue) => {
5,382✔
91
    if (Array.isArray(srcValue)) {
6,107✔
92
        return objValue = srcValue;
96✔
93
    }
94
});
95

96
/**
97
 * Creates deep clone of provided value.
98
 * Supports primitive values, dates and objects.
99
 * If passed value is array returns shallow copy of the array.
100
 *
101
 * @param value value to clone
102
 * @returns Deep copy of provided value
103
 * @hidden
104
 */
105
export const cloneValue = (value: any): any => {
2✔
106
    if (isDate(value)) {
914,176✔
107
        return new Date(value.getTime());
22,053✔
108
    }
109
    if (Array.isArray(value)) {
892,123✔
110
        return [...value];
19,289✔
111
    }
112

113
    if (value instanceof Map || value instanceof Set) {
872,834✔
114
        return value;
37,348✔
115
    }
116

117
    if (isObject(value)) {
835,486✔
118
        const result = {};
124,143✔
119

120
        for (const key of Object.keys(value)) {
124,143✔
121
            if (key === "externalObject") {
827,201!
UNCOV
122
                continue;
×
123
            }
124
            result[key] = cloneValue(value[key]);
827,201✔
125
        }
126
        return result;
124,143✔
127
    }
128
    return value;
711,343✔
129
};
130

131
/**
132
 * Creates deep clone of provided value.
133
 * Supports primitive values, dates and objects.
134
 * If passed value is array returns shallow copy of the array.
135
 * For Objects property values and references are cached and reused.
136
 * This allows for circular references to same objects.
137
 *
138
 * @param value value to clone
139
 * @param cache map of cached values already parsed
140
 * @returns Deep copy of provided value
141
 * @hidden
142
 */
143
export const cloneValueCached = (value: any, cache: Map<any, any>): any => {
2✔
UNCOV
144
    if (isDate(value)) {
×
145
        return new Date(value.getTime());
×
146
    }
UNCOV
147
    if (Array.isArray(value)) {
×
148
        return [...value];
×
149
    }
150

UNCOV
151
    if (value instanceof Map || value instanceof Set) {
×
152
        return value;
×
153
    }
154

UNCOV
155
    if (isObject(value)) {
×
156
        if (cache.has(value)) {
×
157
            return cache.get(value);
×
158
        }
159

UNCOV
160
        const result = {};
×
161
        cache.set(value, result);
×
162

UNCOV
163
        for (const key of Object.keys(value)) {
×
164
            result[key] = cloneValueCached(value[key], cache);
×
165
        }
UNCOV
166
        return result;
×
167
    }
UNCOV
168
    return value;
×
169
};
170

171
/**
172
 * Parse provided input to Date.
173
 *
174
 * @param value input to parse
175
 * @returns Date if parse succeed or null
176
 * @hidden
177
 */
178
export const parseDate = (value: any): Date | null => {
2✔
179
    // if value is Invalid Date return null
180
    if (isDate(value)) {
47,645✔
181
        return !isNaN(value.getTime()) ? value : null;
2,824!
182
    }
183
    return value ? new Date(value) : null;
44,821✔
184
};
185

186
/**
187
 * Returns an array with unique dates only.
188
 *
189
 * @param columnValues collection of date values (might be numbers or ISO 8601 strings)
190
 * @returns collection of unique dates.
191
 * @hidden
192
 */
193
export const uniqueDates = (columnValues: any[]) => columnValues.reduce((a, c) => {
2✔
UNCOV
194
    if (!a.cache[c.label]) {
×
195
        a.result.push(c);
×
196
    }
UNCOV
197
    a.cache[c.label] = true;
×
198
    return a;
×
199
}, { result: [], cache: {} }).result;
200

201
/**
202
 * Checks if provided variable is Object
203
 *
204
 * @param value Value to check
205
 * @returns true if provided variable is Object
206
 * @hidden
207
 */
208
export const isObject = (value: any): boolean => !!(value && value.toString() === '[object Object]');
843,286✔
209

210
/**
211
 * Checks if provided variable is Date
212
 *
213
 * @param value Value to check
214
 * @returns true if provided variable is Date
215
 * @hidden
216
 */
217
export const isDate = (value: any): value is Date => {
2✔
218
    return Object.prototype.toString.call(value) === "[object Date]";
3,251,489✔
219
}
220

221
/**
222
 * Checks if the two passed arguments are equal
223
 * Currently supports date objects
224
 *
225
 * @param obj1
226
 * @param obj2
227
 * @returns: `boolean`
228
 * @hidden
229
 */
230
export const isEqual = (obj1, obj2): boolean => {
2✔
231
    if (isDate(obj1) && isDate(obj2)) {
780✔
232
        return obj1.getTime() === obj2.getTime();
175✔
233
    }
234
    return obj1 === obj2;
605✔
235
};
236

237
/**
238
 * Utility service taking care of various utility functions such as
239
 * detecting browser features, general cross browser DOM manipulation, etc.
240
 *
241
 * @hidden @internal
242
 */
243
@Injectable({ providedIn: 'root' })
244
export class PlatformUtil {
2✔
245
    public isBrowser: boolean = isPlatformBrowser(this.platformId);
4,233✔
246
    public isIOS = this.isBrowser && /iPad|iPhone|iPod/.test(navigator.userAgent) && !('MSStream' in window);
4,233!
247
    public isSafari = this.isBrowser && /Safari[\/\s](\d+\.\d+)/.test(navigator.userAgent);
4,233✔
248
    public isFirefox = this.isBrowser && /Firefox[\/\s](\d+\.\d+)/.test(navigator.userAgent);
4,233✔
249
    public isEdge = this.isBrowser && /Edge[\/\s](\d+\.\d+)/.test(navigator.userAgent);
4,233✔
250
    public isChromium = this.isBrowser && (/Chrom|e?ium/g.test(navigator.userAgent) ||
4,233!
251
        /Google Inc/g.test(navigator.vendor)) && !/Edge/g.test(navigator.userAgent);
252
    public browserVersion = this.isBrowser ? parseFloat(navigator.userAgent.match(/Version\/([\d.]+)/)?.at(1)) : 0;
4,233!
253

254
    /** @hidden @internal */
255
    public isElements = inject(ELEMENTS_TOKEN, { optional: true });
4,233✔
256

257
    public KEYMAP = mkenum({
4,233✔
258
        ENTER: 'Enter',
259
        SPACE: ' ',
260
        ESCAPE: 'Escape',
261
        ARROW_DOWN: 'ArrowDown',
262
        ARROW_UP: 'ArrowUp',
263
        ARROW_LEFT: 'ArrowLeft',
264
        ARROW_RIGHT: 'ArrowRight',
265
        END: 'End',
266
        HOME: 'Home',
267
        PAGE_DOWN: 'PageDown',
268
        PAGE_UP: 'PageUp',
269
        F2: 'F2',
270
        TAB: 'Tab',
271
        SEMICOLON: ';',
272
        // https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values#editing_keys
273
        DELETE: 'Delete',
274
        BACKSPACE: 'Backspace',
275
        CONTROL: 'Control',
276
        X: 'x',
277
        Y: 'y',
278
        Z: 'z'
279
    });
280

281
    constructor(@Inject(PLATFORM_ID) private platformId: any) { }
4,233✔
282

283
    /**
284
     * @hidden @internal
285
     * Returns the actual size of the node content, using Range
286
     * ```typescript
287
     * let range = document.createRange();
288
     * let column = this.grid.columnList.filter(c => c.field === 'ID')[0];
289
     *
290
     * let size = getNodeSizeViaRange(range, column.cells[0].nativeElement);
291
     *
292
     * @remarks
293
     * The last parameter is useful when the size of the element to measure is modified by a
294
     * parent element that has explicit size. In such cases the calculated size is never lower
295
     * and the function may instead remove the parent size while measuring to get the correct value.
296
     * ```
297
     */
298
    public getNodeSizeViaRange(range: Range, node: HTMLElement, sizeHoldingNode?: HTMLElement) {
299
        let overflow = null;
305✔
300
        let nodeStyles;
301

302
        if (!this.isFirefox) {
305✔
303
            overflow = node.style.overflow;
305✔
304
            // we need that hack - otherwise content won't be measured correctly in IE/Edge
305
            node.style.overflow = 'visible';
305✔
306
        }
307

308
        if (sizeHoldingNode) {
305✔
309
            const style = sizeHoldingNode.style;
35✔
310
            nodeStyles = [style.width, style.minWidth, style.flexBasis];
35✔
311
            style.width = '';
35✔
312
            style.minWidth = '';
35✔
313
            style.flexBasis = '';
35✔
314
        }
315

316
        range.selectNodeContents(node);
305✔
317
        const scale = node.getBoundingClientRect().width / node.offsetWidth;
305✔
318
        const width = range.getBoundingClientRect().width / scale;
305✔
319

320
        if (!this.isFirefox) {
305✔
321
            // we need that hack - otherwise content won't be measured correctly in IE/Edge
322
            node.style.overflow = overflow;
305✔
323
        }
324

325
        if (sizeHoldingNode) {
305✔
326
            sizeHoldingNode.style.width = nodeStyles[0];
35✔
327
            sizeHoldingNode.style.minWidth = nodeStyles[1];
35✔
328
            sizeHoldingNode.style.flexBasis = nodeStyles[2];
35✔
329
        }
330

331
        return width;
305✔
332
    }
333

334

335
    /**
336
     * Returns true if the current keyboard event is an activation key (Enter/Space bar)
337
     *
338
     * @hidden
339
     * @internal
340
     *
341
     * @memberof PlatformUtil
342
     */
343
    public isActivationKey(event: KeyboardEvent) {
344
        return event.key === this.KEYMAP.ENTER || event.key === this.KEYMAP.SPACE;
59✔
345
    }
346

347
    /**
348
     * Returns true if the current keyboard event is a combination that closes the filtering UI of the grid. (Escape/Ctrl+Shift+L)
349
     *
350
     * @hidden
351
     * @internal
352
     * @param event
353
     * @memberof PlatformUtil
354
     */
355
    public isFilteringKeyCombo(event: KeyboardEvent) {
356
        return event.key === this.KEYMAP.ESCAPE || (event.ctrlKey && event.shiftKey && event.key.toLowerCase() === 'l');
45✔
357
    }
358

359
    /**
360
     * @hidden @internal
361
     */
362
    public isLeftClick(event: PointerEvent | MouseEvent) {
363
        return event.button === 0;
801✔
364
    }
365

366
    /**
367
     * @hidden @internal
368
     */
369
    public isNavigationKey(key: string) {
370
        return [
10✔
371
            this.KEYMAP.HOME, this.KEYMAP.END, this.KEYMAP.SPACE,
372
            this.KEYMAP.ARROW_DOWN, this.KEYMAP.ARROW_LEFT, this.KEYMAP.ARROW_RIGHT, this.KEYMAP.ARROW_UP
373
        ].includes(key as any);
374
    }
375
}
376

377
/**
378
 * @hidden
379
 */
380
export const flatten = (arr: any[]) => {
2✔
381
    let result = [];
350,065✔
382

383
    arr.forEach(el => {
350,065✔
384
        result.push(el);
601,214✔
385
        if (el.children) {
601,214✔
386
            const children = Array.isArray(el.children) ? el.children : el.children.toArray();
174,312!
387
            result = result.concat(flatten(children));
174,312✔
388
        }
389
    });
390
    return result;
350,065✔
391
};
392

393
export interface CancelableEventArgs {
394
    /**
395
     * Provides the ability to cancel the event.
396
     */
397
    cancel: boolean;
398
}
399

400
export interface IBaseEventArgs {
401
    /**
402
     * Provides reference to the owner component.
403
     */
404
    owner?: any;
405
}
406

407
export interface CancelableBrowserEventArgs extends CancelableEventArgs {
408
    /* blazorSuppress */
409
    /** Browser event */
410
    event?: Event;
411
}
412

413
export interface IBaseCancelableBrowserEventArgs extends CancelableBrowserEventArgs, IBaseEventArgs { }
414

415
export interface IBaseCancelableEventArgs extends CancelableEventArgs, IBaseEventArgs { }
416

417
export const HORIZONTAL_NAV_KEYS = new Set(['arrowleft', 'left', 'arrowright', 'right', 'home', 'end']);
2✔
418

419
export const NAVIGATION_KEYS = new Set([
2✔
420
    'down',
421
    'up',
422
    'left',
423
    'right',
424
    'arrowdown',
425
    'arrowup',
426
    'arrowleft',
427
    'arrowright',
428
    'home',
429
    'end',
430
    'space',
431
    'spacebar',
432
    ' '
433
]);
434
export const ACCORDION_NAVIGATION_KEYS = new Set('up down arrowup arrowdown home end'.split(' '));
2✔
435
export const ROW_EXPAND_KEYS = new Set('right down arrowright arrowdown'.split(' '));
2✔
436
export const ROW_COLLAPSE_KEYS = new Set('left up arrowleft arrowup'.split(' '));
2✔
437
export const ROW_ADD_KEYS = new Set(['+', 'add', '≠', '±', '=']);
2✔
438
export const SUPPORTED_KEYS = new Set([...Array.from(NAVIGATION_KEYS),
2✔
439
...Array.from(ROW_ADD_KEYS), 'enter', 'f2', 'escape', 'esc', 'pagedown', 'pageup']);
440
export const HEADER_KEYS = new Set([...Array.from(NAVIGATION_KEYS), 'escape', 'esc', 'l',
2✔
441
    /** This symbol corresponds to the Alt + L combination under MAC. */
442
    '¬']);
443

444
/**
445
 * @hidden
446
 * @internal
447
 *
448
 * Creates a new ResizeObserver on `target` and returns it as an Observable.
449
 * Run the resizeObservable outside angular zone, because it patches the MutationObserver which causes an infinite loop.
450
 * Related issue: https://github.com/angular/angular/issues/31712
451
 */
452
export const resizeObservable = (target: HTMLElement): Observable<ResizeObserverEntry[]> => {
2✔
453
    const resizeObserver = getResizeObserver();
15,160✔
454
    // check whether we are on server env or client env
455
    if (resizeObserver) {
15,160!
456
        return new Observable((observer) => {
15,160✔
457
                const instance = new resizeObserver((entries: ResizeObserverEntry[]) => {
15,160✔
458
                    observer.next(entries);
6,018✔
459
                });
460
                instance.observe(target);
15,160✔
461
                const unsubscribe = () => instance.disconnect();
15,160✔
462
                return unsubscribe;
15,160✔
463
        });
464
    } else {
465
        // if on a server env return a empty observable that does not complete immediately
UNCOV
466
        return NEVER;
×
467
    }
468
}
469

470
/**
471
 * @hidden
472
 * @internal
473
 *
474
 * Compares two maps.
475
 */
476
export const compareMaps = (map1: Map<any, any>, map2: Map<any, any>): boolean => {
2✔
477
    if (!map2) {
463✔
478
        return !map1 ? true : false;
3!
479
    }
480
    if (map1.size !== map2.size) {
460!
UNCOV
481
        return false;
×
482
    }
483
    let match = true;
460✔
484
    const keys = Array.from(map2.keys());
460✔
485
    for (const key of keys) {
460✔
486
        if (map1.has(key)) {
460!
487
            match = map1.get(key) === map2.get(key);
460✔
488
        } else {
UNCOV
489
            match = false;
×
490
        }
491
        if (!match) {
460✔
492
            break;
12✔
493
        }
494
    }
495
    return match;
460✔
496
};
497

498
/**
499
 *
500
 * Given a property access path in the format `x.y.z` resolves and returns
501
 * the value of the `z` property in the passed object.
502
 *
503
 * @hidden
504
 * @internal
505
 */
506
export const resolveNestedPath = (obj: any, path: string) => {
2✔
507
    const parts = path?.split('.') ?? [];
358,480✔
508
    let current = obj[parts.shift()];
358,480✔
509

510
    parts.forEach(prop => {
358,480✔
511
        if (current) {
1,180✔
512
            current = current[prop];
823✔
513
        }
514
    });
515

516
    return current;
358,480✔
517
};
518

519
/**
520
 *
521
 * Given a property access path in the format `x.y.z` and a value
522
 * this functions builds and returns an object following the access path.
523
 *
524
 * @example
525
 * ```typescript
526
 * console.log('x.y.z.', 42);
527
 * >> { x: { y: { z: 42 } } }
528
 * ```
529
 *
530
 * @hidden
531
 * @internal
532
 */
533
export const reverseMapper = (path: string, value: any) => {
2✔
534
    const obj = {};
191✔
535
    const parts = path?.split('.') ?? [];
191!
536

537
    let _prop = parts.shift();
191✔
538
    let mapping: any;
539

540
    // Initial binding for first level bindings
541
    obj[_prop] = value;
191✔
542
    mapping = obj;
191✔
543

544
    parts.forEach(prop => {
191✔
545
        // Start building the hierarchy
546
        mapping[_prop] = {};
13✔
547
        // Go down a level
548
        mapping = mapping[_prop];
13✔
549
        // Bind the value and move the key
550
        mapping[prop] = value;
13✔
551
        _prop = prop;
13✔
552
    });
553

554
    return obj;
191✔
555
};
556

557
export const yieldingLoop = (count: number, chunkSize: number, callback: (index: number) => void, done: () => void) => {
2✔
558
    let i = 0;
399✔
559
    const chunk = () => {
399✔
560
        const end = Math.min(i + chunkSize, count);
405✔
561
        for (; i < end; ++i) {
405✔
562
            callback(i);
5,671✔
563
        }
564
        if (i < count) {
405✔
565
            setImmediate(chunk);
6✔
566
        } else {
567
            done();
399✔
568
        }
569
    };
570
    chunk();
399✔
571
};
572

573
export const isConstructor = (ref: any) => typeof ref === 'function' && Boolean(ref.prototype) && Boolean(ref.prototype.constructor);
24,122✔
574

575
/**
576
 * Similar to Angular's formatDate. However it will not throw on `undefined | null | ''` instead
577
 * coalescing to an empty string.
578
 */
579
export const formatDate = (value: string | number | Date, format: string, locale: string, timezone?: string): string => {
2✔
580
    if (value === null || value === undefined || value === '') {
173,621✔
581
        return '';
24,195✔
582
    }
583
    return _formatDate(value, format, locale, timezone);
149,426✔
584
};
585

586
export const formatCurrency = new CurrencyPipe(undefined).transform;
2✔
587

588
/** Converts pixel values to their rem counterparts for a base value */
589
export const rem = (value: number | string) => {
2✔
590
    const base = parseFloat(globalThis.window?.getComputedStyle(globalThis.document?.documentElement).getPropertyValue('--ig-base-font-size'))
131,588✔
591
    return Number(value) / base;
131,588✔
592
}
593

594
/** Get the size of the component as derived from the CSS size variable */
595
export function getComponentSize(el: Element) {
596
    return globalThis.window?.getComputedStyle(el).getPropertyValue('--component-size');
103✔
597
}
598

599
/** Get the first item in an array */
600
export function first<T>(arr: T[]) {
601
    return arr.at(0) as T;
157,161✔
602
}
603

604
/** Get the last item in an array */
605
export function last<T>(arr: T[]) {
606
    return arr.at(-1) as T;
152,530✔
607
}
608

609
/** Calculates the modulo of two numbers, ensuring a non-negative result. */
610
export function modulo(n: number, d: number) {
611
    return ((n % d) + d) % d;
4,131✔
612
}
613

614
/**
615
 * Splits an array into chunks of length `size` and returns a generator
616
 * yielding each chunk.
617
 * The last chunk may contain less than `size` elements.
618
 *
619
 * @example
620
 * ```typescript
621
 * const arr = [0,1,2,3,4,5,6,7,8,9];
622
 *
623
 * Array.from(chunk(arr, 2)) // [[0, 1], [2, 3], [4, 5], [6, 7], [8, 9]]
624
 * Array.from(chunk(arr, 3)) // [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]
625
 * Array.from(chunk([], 3)) // []
626
 * Array.from(chunk(arr, -3)) // Error
627
 * ```
628
 */
629
export function* intoChunks<T>(arr: T[], size: number) {
630
  if (size < 1) {
4,130!
UNCOV
631
    throw new Error('size must be an integer >= 1');
×
632
  }
633
  for (let i = 0; i < arr.length; i += size) {
4,130✔
634
    yield arr.slice(i, i + size);
24,780✔
635
  }
636
}
637

638
/**
639
 * @param size
640
 * @returns string that represents the --component-size default value
641
 */
642
export function getComponentCssSizeVar(size: string) {
UNCOV
643
    switch (size) {
×
644
        case "1":
UNCOV
645
            return 'var(--ig-size, var(--ig-size-small))';
×
646
        case "2":
UNCOV
647
            return 'var(--ig-size, var(--ig-size-medium))';
×
648
        case "3":
649
        default:
UNCOV
650
            return 'var(--ig-size, var(--ig-size-large))';
×
651
    }
652
}
653

654
/**
655
 * @param path - The URI path to be normalized.
656
 * @returns string encoded using the encodeURI function.
657
 */
658
 export function normalizeURI(path: string) {
659
     return path.split('/').map(encodeURI).join('/');
5✔
660
 }
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc