mark-3 0.0.4 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/components/index.js +1 -0
- package/components/scroll-aware-content.vue +162 -0
- package/composables/index.js +5 -0
- package/composables/use-event-listener.js +20 -6
- package/composables/use-intersection-observer.js +67 -0
- package/composables/use-outside-clicks.js +62 -0
- package/composables/use-pointer-swipe.js +138 -0
- package/composables/use-scroll-event.js +97 -0
- package/composables/use-swipeable-drawer.js +161 -0
- package/helpers/array/index.js +1 -0
- package/helpers/array/pick-random.js +24 -0
- package/helpers/array/tests/pick-random.test.js +39 -0
- package/helpers/date/index.js +1 -1
- package/helpers/date/{from-timestamp/index.test.js → tests/format-timestamp.test.js} +1 -1
- package/helpers/date/tests/format.test.js +97 -0
- package/helpers/date/{is-on-same-day/index.test.js → tests/is-on-same-day.test.js} +1 -1
- package/helpers/date/{is-on-same-year/index.test.js → tests/is-on-same-year.test.js} +1 -1
- package/helpers/number/clamp.js +17 -0
- package/helpers/number/index.js +2 -0
- package/helpers/number/random.js +24 -0
- package/helpers/number/tests/clamp.test.js +37 -0
- package/helpers/number/tests/random.test.js +51 -0
- package/helpers/string/{camel-to-dash/index.js → camel-to-dash.js} +2 -2
- package/helpers/string/encode-subscript.js +45 -0
- package/helpers/string/encode-superscript.js +46 -0
- package/helpers/string/{escape-regex/index.js → escape-regex.js} +1 -1
- package/helpers/string/index.js +2 -0
- package/helpers/string/{camel-to-dash/index.test.js → tests/camel-to-dash.test.js} +1 -1
- package/helpers/string/tests/encode-subscript.test.js +41 -0
- package/helpers/string/tests/encode-superscript.test.js +42 -0
- package/helpers/string/{escape-regex/index.test.js → tests/escape-regex.test.js} +1 -1
- package/helpers/string/{trim/index.test.js → tests/trim.test.js} +1 -1
- package/helpers/string/{trim/index.js → trim.js} +2 -2
- package/helpers/time/debounce.js +29 -0
- package/helpers/time/index.js +1 -0
- package/helpers/time/tests/debounce.test.js +58 -0
- package/helpers/types/index.js +1 -0
- package/helpers/types/{is-empty/index.js → is-empty.js} +1 -1
- package/helpers/types/{is-map/index.js → is-map.js} +1 -1
- package/helpers/types/is-numeric.js +22 -0
- package/helpers/types/{is-set/index.js → is-set.js} +1 -1
- package/helpers/types/{get-type-name/index.test.js → tests/get-type-name.test.js} +2 -2
- package/helpers/types/{is-array/index.test.js → tests/is-array.test.js} +1 -1
- package/helpers/types/{is-empty/index.test.js → tests/is-empty.test.js} +1 -1
- package/helpers/types/{is-map/index.test.js → tests/is-map.test.js} +1 -1
- package/helpers/types/tests/is-numeric.test.js +51 -0
- package/helpers/types/{is-plain-object/index.test.js → tests/is-plain-object.test.js} +1 -1
- package/helpers/types/{is-set/index.test.js → tests/is-set.test.js} +1 -1
- package/helpers/types/{is-string/index.test.js → tests/is-string.test.js} +1 -1
- package/package.json +4 -1
- package/helpers/date/format/README.md +0 -33
- package/helpers/date/format/index.test.js +0 -97
- package/helpers/date/from-timestamp/README.md +0 -14
- package/helpers/date/is-on-same-day/README.md +0 -12
- package/helpers/date/is-on-same-year/README.md +0 -13
- package/helpers/string/camel-to-dash/README.md +0 -24
- package/helpers/string/escape-regex/README.md +0 -12
- package/helpers/string/trim/README.md +0 -66
- package/helpers/types/get-type-name/README.md +0 -11
- package/helpers/types/is-array/README.md +0 -11
- package/helpers/types/is-empty/README.md +0 -35
- package/helpers/types/is-map/README.md +0 -15
- package/helpers/types/is-plain-object/README.md +0 -17
- package/helpers/types/is-set/README.md +0 -15
- package/helpers/types/is-string/README.md +0 -12
- /package/helpers/date/{from-timestamp/index.js → format-timestamp.js} +0 -0
- /package/helpers/date/{format/index.js → format.js} +0 -0
- /package/helpers/date/{is-on-same-day/index.js → is-on-same-day.js} +0 -0
- /package/helpers/date/{is-on-same-year/index.js → is-on-same-year.js} +0 -0
- /package/helpers/types/{get-type-name/index.js → get-type-name.js} +0 -0
- /package/helpers/types/{is-array/index.js → is-array.js} +0 -0
- /package/helpers/types/{is-plain-object/index.js → is-plain-object.js} +0 -0
- /package/helpers/types/{is-string/index.js → is-string.js} +0 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { ref, watch, provide } from "vue";
|
|
2
|
+
import { usePointerSwipe } from ".";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A composition function that provides a swipeable drawer.
|
|
6
|
+
*
|
|
7
|
+
* @param {string} name - A unique name for the drawer.
|
|
8
|
+
* @param {object} [options] - Configuration options.
|
|
9
|
+
* @param {number} [options.drawerSize=0] - The width of the drawer.
|
|
10
|
+
* @param {"horizontal"|"vertical"} [options.axis="horizontal"] - The axis of the drawer's movement.
|
|
11
|
+
* @param {"left"|"right"|"up"|"down"} [options.openFrom="left"] - The starting position of the drawer.
|
|
12
|
+
* @returns {SwipeableDrawerReturnValue} - An object containing reactive properties
|
|
13
|
+
* and methods related to the drawer.
|
|
14
|
+
*/
|
|
15
|
+
export default function useSwipeableDrawer(
|
|
16
|
+
name,
|
|
17
|
+
{ drawerSize, axis = "horizontal", openFrom = "left" } = {}
|
|
18
|
+
)
|
|
19
|
+
{
|
|
20
|
+
const swipeDistance = ref( 0 );
|
|
21
|
+
const swipeableEl = ref( null );
|
|
22
|
+
const swipeTriggerEl = ref( null );
|
|
23
|
+
const isDrawerOpen = ref( false );
|
|
24
|
+
const { min, max } = Math;
|
|
25
|
+
|
|
26
|
+
const { isSwiping, distanceX, distanceY, direction, velocity } =
|
|
27
|
+
usePointerSwipe( swipeTriggerEl,
|
|
28
|
+
{
|
|
29
|
+
threshold: 0
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const axialDistance = (
|
|
33
|
+
{
|
|
34
|
+
horizontal: distanceX,
|
|
35
|
+
vertical: distanceY
|
|
36
|
+
})[ axis ];
|
|
37
|
+
|
|
38
|
+
const motionReversalMap =
|
|
39
|
+
{
|
|
40
|
+
left: "right",
|
|
41
|
+
right: "left",
|
|
42
|
+
up: "down",
|
|
43
|
+
down: "up"
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
watch( axialDistance, () =>
|
|
47
|
+
{
|
|
48
|
+
// opening movement
|
|
49
|
+
if( direction.value == openFrom )
|
|
50
|
+
{
|
|
51
|
+
if( isDrawerOpen.value )
|
|
52
|
+
{
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
swipeDistance.value = min( drawerSize, axialDistance.value );
|
|
57
|
+
}
|
|
58
|
+
// closing movement
|
|
59
|
+
else if( direction.value == reverse( openFrom ))
|
|
60
|
+
{
|
|
61
|
+
if( ! isDrawerOpen.value )
|
|
62
|
+
{
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
swipeDistance.value = max( 0, drawerSize + axialDistance.value );
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
watch( isSwiping, () =>
|
|
71
|
+
{
|
|
72
|
+
if( isSwiping.value )
|
|
73
|
+
{
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// opening movement
|
|
78
|
+
if( direction.value == openFrom )
|
|
79
|
+
{
|
|
80
|
+
velocity.value >= 0.25 || swipeDistance.value > .35 * drawerSize
|
|
81
|
+
? open()
|
|
82
|
+
: close();
|
|
83
|
+
}
|
|
84
|
+
// closing movement
|
|
85
|
+
else if( direction.value == reverse( openFrom ))
|
|
86
|
+
{
|
|
87
|
+
velocity.value >= 0.25 || swipeDistance.value < .65 * drawerSize
|
|
88
|
+
? close()
|
|
89
|
+
: open();
|
|
90
|
+
}
|
|
91
|
+
// movements on the other axis
|
|
92
|
+
else
|
|
93
|
+
{
|
|
94
|
+
close();
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
function open()
|
|
99
|
+
{
|
|
100
|
+
swipeDistance.value = drawerSize;
|
|
101
|
+
isDrawerOpen.value = true;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function close()
|
|
105
|
+
{
|
|
106
|
+
swipeDistance.value = 0;
|
|
107
|
+
isDrawerOpen.value = false;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function toggle()
|
|
111
|
+
{
|
|
112
|
+
isDrawerOpen.value
|
|
113
|
+
? close()
|
|
114
|
+
: open();
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function reverse( motion )
|
|
118
|
+
{
|
|
119
|
+
return motionReversalMap[ motion ];
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const returnValue =
|
|
123
|
+
{
|
|
124
|
+
swipeableEl,
|
|
125
|
+
swipeTriggerEl,
|
|
126
|
+
isSwiping,
|
|
127
|
+
swipeDistance,
|
|
128
|
+
isDrawerOpen,
|
|
129
|
+
openDrawer: open,
|
|
130
|
+
closeDrawer: close,
|
|
131
|
+
toggleDrawer: toggle
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
provide( "drawer:" + name, returnValue );
|
|
135
|
+
|
|
136
|
+
return returnValue;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* @template T
|
|
141
|
+
* @typedef {import("vue").Ref<T>} Ref
|
|
142
|
+
*/
|
|
143
|
+
/**
|
|
144
|
+
* @template T
|
|
145
|
+
* @typedef {import("vue").ComputedRef<T>} ComputedRef
|
|
146
|
+
*/
|
|
147
|
+
/**
|
|
148
|
+
* @template T
|
|
149
|
+
* @typedef {import("vue").Reactive<T>} Reactive
|
|
150
|
+
*/
|
|
151
|
+
/**
|
|
152
|
+
* @typedef {object} SwipeableDrawerReturnValue
|
|
153
|
+
* @property {Ref<EventTarget>} swipeableEl - The element that is the drawer.
|
|
154
|
+
* @property {Ref<EventTarget>} swipeTriggerEl - The element that can trigger the drawer's opening.
|
|
155
|
+
* @property {Ref<boolean>} isSwiping - Indicates if a swipe is currently happening.
|
|
156
|
+
* @property {Ref<number>} swipeDistance - The distance of the drawer from its starting position.
|
|
157
|
+
* @property {Ref<boolean>} isDrawerOpen - Indicates if the drawer is open.
|
|
158
|
+
* @property {function():void} openDrawer - Opens the drawer.
|
|
159
|
+
* @property {function():void} closeDrawer - Closes the drawer.
|
|
160
|
+
* @property {function():void} toggleDrawer - Toggles the drawer's open state.
|
|
161
|
+
*/
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as pickRandom } from "./pick-random";
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { random } from "../number";
|
|
2
|
+
import { isArray } from "../types";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Picks a random element from the given array.
|
|
6
|
+
*
|
|
7
|
+
* @template T
|
|
8
|
+
* @param {T[]} arr - The array to pick a random element from.
|
|
9
|
+
* @returns {T|undefined} - The random element from the array, or undefined if the array is empty.
|
|
10
|
+
*/
|
|
11
|
+
export default function pickRandom( arr )
|
|
12
|
+
{
|
|
13
|
+
if( ! isArray( arr ))
|
|
14
|
+
{
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if( arr.length === 0 )
|
|
19
|
+
{
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return arr[ random( 0, arr.length - 1 )];
|
|
24
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { pickRandom } from "..";
|
|
3
|
+
|
|
4
|
+
// örnek test verisi
|
|
5
|
+
const sampleArray = [10, 20, 30, 40, 50];
|
|
6
|
+
|
|
7
|
+
describe("pickRandom", () =>
|
|
8
|
+
{
|
|
9
|
+
it("should return undefined if input is not an array", () =>
|
|
10
|
+
{
|
|
11
|
+
expect(pickRandom(null)).toBeUndefined();
|
|
12
|
+
expect(pickRandom({})).toBeUndefined();
|
|
13
|
+
expect(pickRandom("not array")).toBeUndefined();
|
|
14
|
+
expect(pickRandom(123)).toBeUndefined();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it("should return undefined if array is empty", () =>
|
|
18
|
+
{
|
|
19
|
+
expect(pickRandom([])).toBeUndefined();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("should return an element from the array", () =>
|
|
23
|
+
{
|
|
24
|
+
const value = pickRandom(sampleArray);
|
|
25
|
+
expect(sampleArray).toContain(value);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it("should return different results across multiple calls", () =>
|
|
29
|
+
{
|
|
30
|
+
const results = new Set();
|
|
31
|
+
for (let i = 0; i < 20; i++)
|
|
32
|
+
{
|
|
33
|
+
const val = pickRandom(sampleArray);
|
|
34
|
+
results.add(val);
|
|
35
|
+
}
|
|
36
|
+
// Rastgelelik garantisi yok ama çeşitlilik kontrolü yapılabilir
|
|
37
|
+
expect(results.size).toBeGreaterThan(1);
|
|
38
|
+
});
|
|
39
|
+
});
|
package/helpers/date/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { default as format } from "./format";
|
|
2
2
|
export { default as isOnSameDay } from "./is-on-same-day";
|
|
3
|
-
export { default as fromTimestamp } from "./
|
|
3
|
+
export { default as fromTimestamp } from "./format-timestamp";
|
|
4
4
|
export { default as isOnSameYear } from "./is-on-same-year";
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { format } from "..";
|
|
3
|
+
|
|
4
|
+
describe( "format", () =>
|
|
5
|
+
{
|
|
6
|
+
const date = new Date( "2025-12-21T22:10:05" );
|
|
7
|
+
|
|
8
|
+
it( "formats full year (Y)", () =>
|
|
9
|
+
{
|
|
10
|
+
expect( format( date, "Y" )).toBe( "2025" );
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it( "formats short year (y)", () =>
|
|
14
|
+
{
|
|
15
|
+
expect( format( date, "y" )).toBe( "25" );
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it( "formats zero-padded month (m)", () =>
|
|
19
|
+
{
|
|
20
|
+
expect( format( date, "m" )).toBe( "12" );
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it( "formats non-padded month (n)", () =>
|
|
24
|
+
{
|
|
25
|
+
expect( format( date, "n" )).toBe( "12" );
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it( "formats short month name (M)", () =>
|
|
29
|
+
{
|
|
30
|
+
expect( format( date, "M" )).toBe( "Dec" );
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it( "formats full month name (MM)", () =>
|
|
34
|
+
{
|
|
35
|
+
expect( format( date, "MM" )).toBe( "December" );
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it( "formats day padded (d)", () =>
|
|
39
|
+
{
|
|
40
|
+
expect( format( date, "d" )).toBe( "21" );
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it( "formats day non-padded (j)", () =>
|
|
44
|
+
{
|
|
45
|
+
expect( format( date, "j" )).toBe( "21" );
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it( "formats zero-padded hour (H)", () =>
|
|
49
|
+
{
|
|
50
|
+
expect( format( date, "H" )).toBe( "22" );
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it( "formats non-padded hour (G)", () =>
|
|
54
|
+
{
|
|
55
|
+
expect( format( date, "G" )).toBe( "22" );
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it( "formats minutes (i)", () =>
|
|
59
|
+
{
|
|
60
|
+
expect( format( date, "i" )).toBe( "10" );
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it( "formats seconds (s)", () =>
|
|
64
|
+
{
|
|
65
|
+
expect( format( date, "s" )).toBe( "05" );
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it( "formats a custom pattern", () =>
|
|
69
|
+
{
|
|
70
|
+
expect( format( date, "d.m.Y H:i" )).toBe( "21.12.2025 22:10" );
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it( "supports localized short month (M) in TR", () =>
|
|
74
|
+
{
|
|
75
|
+
expect( format( date, "M", "tr" )).toBe( "Ara" ); // Aralık
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it( "supports localized long month (MM) in TR", () =>
|
|
79
|
+
{
|
|
80
|
+
expect( format( date, "MM", "tr" )).toBe( "Aralık" );
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it( "returns empty string for empty pattern", () =>
|
|
84
|
+
{
|
|
85
|
+
expect( format( date, "" )).toBe( "" );
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it( "leaves unknown tokens as-is", () =>
|
|
89
|
+
{
|
|
90
|
+
expect( format( date, "[foo] Y" )).toBe( "[foo] 2025" );
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it( "mixes plain text and tokens", () =>
|
|
94
|
+
{
|
|
95
|
+
expect( format( date, "d MM Y, H:i" )).toBe( "21 December 2025, 22:10" );
|
|
96
|
+
});
|
|
97
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clamps a value within a range.
|
|
3
|
+
*
|
|
4
|
+
* @param {number} value value to be clamped
|
|
5
|
+
* @param {number} min minimum value
|
|
6
|
+
* @param {number} max maximum value
|
|
7
|
+
* @return {number} clamped value
|
|
8
|
+
*/
|
|
9
|
+
export default function clamp( value, min, max )
|
|
10
|
+
{
|
|
11
|
+
if( min > max )
|
|
12
|
+
{
|
|
13
|
+
[ min, max ] = [ max, min ];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return Math.max( min, Math.min( max, value ));
|
|
17
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { clamp } from ".";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Produce a random number between two values. If no value is provided,
|
|
5
|
+
* a random number is produced.
|
|
6
|
+
*
|
|
7
|
+
* @param {number} min minimum value
|
|
8
|
+
* @param {number} max maximum value
|
|
9
|
+
* @param {boolean} shouldFloat should the result be a float
|
|
10
|
+
* @return {number}
|
|
11
|
+
*/
|
|
12
|
+
export default function random( min = 0, max = 1, shouldFloat = false )
|
|
13
|
+
{
|
|
14
|
+
if( min > max )
|
|
15
|
+
{
|
|
16
|
+
[ min, max ] = [ max, min ];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const rnd = clamp( Math.random() * max, min, max );
|
|
20
|
+
|
|
21
|
+
return shouldFloat
|
|
22
|
+
? parseFloat( rnd )
|
|
23
|
+
: Math.floor( rnd );
|
|
24
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { clamp } from "..";
|
|
3
|
+
|
|
4
|
+
describe("clamp()", () =>
|
|
5
|
+
{
|
|
6
|
+
it("returns the same value if it is within the min and max range", () =>
|
|
7
|
+
{
|
|
8
|
+
expect(clamp(5, 0, 10)).toBe(5);
|
|
9
|
+
expect(clamp(0, -10, 10)).toBe(0);
|
|
10
|
+
expect(clamp(9.5, 0, 10)).toBe(9.5);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it("clamps the value to the min if it is less than min", () =>
|
|
14
|
+
{
|
|
15
|
+
expect(clamp(-5, 0, 10)).toBe(0);
|
|
16
|
+
expect(clamp(-100, -10, 10)).toBe(-10);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("clamps the value to the max if it is greater than max", () =>
|
|
20
|
+
{
|
|
21
|
+
expect(clamp(15, 0, 10)).toBe(10);
|
|
22
|
+
expect(clamp(99, -10, 10)).toBe(10);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it("returns the only possible value if min and max are equal", () =>
|
|
26
|
+
{
|
|
27
|
+
expect(clamp(5, 7, 7)).toBe(7);
|
|
28
|
+
expect(clamp(10, 10, 10)).toBe(10);
|
|
29
|
+
expect(clamp(-5, -3, -3)).toBe(-3);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it("swaps min and max if needed", () =>
|
|
33
|
+
{
|
|
34
|
+
expect(clamp(5, 10, 0)).toBe(5);
|
|
35
|
+
expect(clamp(-5, 3, -3)).toBe(-3);
|
|
36
|
+
});
|
|
37
|
+
});
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { random } from "..";
|
|
3
|
+
|
|
4
|
+
describe("random", () =>
|
|
5
|
+
{
|
|
6
|
+
it("should return a number between 0 and 1 by default", () =>
|
|
7
|
+
{
|
|
8
|
+
const result = random();
|
|
9
|
+
expect(result).toBeGreaterThanOrEqual(0);
|
|
10
|
+
expect(result).toBeLessThanOrEqual(1);
|
|
11
|
+
expect(Number.isInteger(result)).toBe(true);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it("should return float if shouldFloat is true", () =>
|
|
15
|
+
{
|
|
16
|
+
const result = random(0, 1, true);
|
|
17
|
+
expect(result).toBeGreaterThanOrEqual(0);
|
|
18
|
+
expect(result).toBeLessThanOrEqual(1);
|
|
19
|
+
expect(Number.isInteger(result)).toBe(false);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("should respect min and max range with integers", () =>
|
|
23
|
+
{
|
|
24
|
+
const result = random(5, 10);
|
|
25
|
+
expect(result).toBeGreaterThanOrEqual(5);
|
|
26
|
+
expect(result).toBeLessThanOrEqual(10);
|
|
27
|
+
expect(Number.isInteger(result)).toBe(true);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("should respect min and max range with floats", () =>
|
|
31
|
+
{
|
|
32
|
+
const result = random(5, 10, true);
|
|
33
|
+
expect(result).toBeGreaterThanOrEqual(5);
|
|
34
|
+
expect(result).toBeLessThanOrEqual(10);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("should always return at least the min value", () =>
|
|
38
|
+
{
|
|
39
|
+
for (let i = 0; i < 100; i++)
|
|
40
|
+
{
|
|
41
|
+
const result = random(10, 20);
|
|
42
|
+
expect(result).toBeGreaterThanOrEqual(10);
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("should return exactly min if min and max are both 0", () =>
|
|
47
|
+
{
|
|
48
|
+
const result = random(0, 0);
|
|
49
|
+
expect(result).toBe(0);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const map =
|
|
2
|
+
{
|
|
3
|
+
0: "₀", 1: "₁", 2: "₂", 3: "₃", 4: "₄", 5: "₅", 6: "₆", 7: "₇", 8: "₈", 9: "₉",
|
|
4
|
+
a: "ₐ", e: "ₑ", h: "ₕ", k: "ₖ", l: "ₗ", m: "ₘ", n: "ₙ", o: "ₒ", p: "ₚ", s: "ₛ",
|
|
5
|
+
t: "ₜ", "+": "₊", "-": "₋", "=": "₌", "(": "₍", ")": "₎",
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Converts a given string into its subscript equivalent, if available.
|
|
10
|
+
*
|
|
11
|
+
* @param {string} str - The string to be converted.
|
|
12
|
+
* @param {boolean} [rollbackWhenMismatch=true] If true, returns the original string
|
|
13
|
+
* a character is not in the map.
|
|
14
|
+
* @returns {string} The subscript representation of the string if it exists in the
|
|
15
|
+
* map, otherwise the original string.
|
|
16
|
+
*/
|
|
17
|
+
export default function encodeSubscript( str, rollbackWhenMismatch = true )
|
|
18
|
+
{
|
|
19
|
+
if( typeof str !== "string" )
|
|
20
|
+
{
|
|
21
|
+
return str;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if( rollbackWhenMismatch )
|
|
25
|
+
{
|
|
26
|
+
let stack = "";
|
|
27
|
+
|
|
28
|
+
for( let char of str )
|
|
29
|
+
{
|
|
30
|
+
if( ! ( char in map ))
|
|
31
|
+
{
|
|
32
|
+
return str;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
stack += map[ char ];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return stack;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return str
|
|
42
|
+
.split( "" )
|
|
43
|
+
.map( char => map[ char ] || char )
|
|
44
|
+
.join( "" );
|
|
45
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const map =
|
|
2
|
+
{
|
|
3
|
+
1: "¹", 2: "²", 3: "³", 4: "⁴", 5: "⁵", 6: "⁶", 7: "⁷", 8: "⁸", 9: "⁹", 0: "⁰",
|
|
4
|
+
a: "ᵃ", b: "ᵇ", c: "ᶜ", d: "ᵈ", e: "ᵉ", f: "ᶠ", g: "ᵍ", h: "ʰ", i: "ⁱ", j: "ʲ",
|
|
5
|
+
k: "ᵏ", l: "ˡ", m: "ᵐ", n: "ⁿ", o: "ᵒ", p: "ᵖ", r: "ʳ", s: "ˢ", t: "ᵗ", u: "ᵘ",
|
|
6
|
+
v: "ᵛ", w: "ʷ", x: "ˣ", y: "ʸ", z: "ᶻ",
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Converts a given string into its superscript equivalent, if available.
|
|
11
|
+
*
|
|
12
|
+
* @param {string} str - The string to be converted.
|
|
13
|
+
* @param {boolean} [rollbackWhenMismatch=true] If true, returns the original string
|
|
14
|
+
* when a character is not in the map.
|
|
15
|
+
* @returns {string} The superscript representation of the string if it exists in the
|
|
16
|
+
* map, otherwise the original string.
|
|
17
|
+
*/
|
|
18
|
+
export default function convertToSuperscript( str, rollbackWhenMismatch = true )
|
|
19
|
+
{
|
|
20
|
+
if( typeof str !== "string" )
|
|
21
|
+
{
|
|
22
|
+
return str;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if( rollbackWhenMismatch )
|
|
26
|
+
{
|
|
27
|
+
let stack = "";
|
|
28
|
+
|
|
29
|
+
for( let char of str )
|
|
30
|
+
{
|
|
31
|
+
if( ! ( char in map ))
|
|
32
|
+
{
|
|
33
|
+
return str;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
stack += map[ char ];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return stack;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return str
|
|
43
|
+
.split( "" )
|
|
44
|
+
.map( char => map[ char ] || char )
|
|
45
|
+
.join( "" );
|
|
46
|
+
}
|
package/helpers/string/index.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export { default as trim } from "./trim";
|
|
2
2
|
export { default as escapeRegex } from "./escape-regex";
|
|
3
3
|
export { default as camelToDash } from "./camel-to-dash";
|
|
4
|
+
export { default as encodeSubscript } from "./encode-subscript";
|
|
5
|
+
export { default as encodeSuperscript } from "./encode-superscript";
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { encodeSubscript } from "..";
|
|
3
|
+
|
|
4
|
+
describe("encodeSubscript", () =>
|
|
5
|
+
{
|
|
6
|
+
it("converts full match to subscript", () =>
|
|
7
|
+
{
|
|
8
|
+
expect(encodeSubscript("h2o")).toBe("ₕ₂ₒ");
|
|
9
|
+
expect(encodeSubscript("123")).toBe("₁₂₃");
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it("returns original string if any character mismatches and rollbackWhenMismatch is true", () =>
|
|
13
|
+
{
|
|
14
|
+
expect(encodeSubscript("H2O")).toBe("H2O"); // 'H' and 'O' not in map
|
|
15
|
+
expect(encodeSubscript("x+2")).toBe("x+2"); // 'x' not in map
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it("fallbacks partially when rollbackWhenMismatch is false", () =>
|
|
19
|
+
{
|
|
20
|
+
expect(encodeSubscript("x+2", false)).toBe("x₊₂");
|
|
21
|
+
expect(encodeSubscript("H2O", false)).toBe("H₂O");
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("returns non-string inputs as-is", () =>
|
|
25
|
+
{
|
|
26
|
+
expect(encodeSubscript(null)).toBe(null);
|
|
27
|
+
expect(encodeSubscript(undefined)).toBe(undefined);
|
|
28
|
+
expect(encodeSubscript(123)).toBe(123);
|
|
29
|
+
expect(encodeSubscript({})).toEqual({});
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it("handles empty string correctly", () =>
|
|
33
|
+
{
|
|
34
|
+
expect(encodeSubscript("")).toBe("");
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("works with symbols like + - ( )", () =>
|
|
38
|
+
{
|
|
39
|
+
expect(encodeSubscript("2+(3-1)", false)).toBe("₂₊₍₃₋₁₎");
|
|
40
|
+
});
|
|
41
|
+
});
|