speexjs-core 0.7.0
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 +117 -0
- package/CONTRIBUTING.md +55 -0
- package/PUBLISH.md +45 -0
- package/README.md +174 -0
- package/ROADMAP.md +72 -0
- package/SECURITY.md +35 -0
- package/SUMMARY.md +321 -0
- package/dist/async/index.d.ts +232 -0
- package/dist/async/index.js +366 -0
- package/dist/async/index.js.map +1 -0
- package/dist/collection/index.d.ts +230 -0
- package/dist/collection/index.js +375 -0
- package/dist/collection/index.js.map +1 -0
- package/dist/color/index.d.ts +128 -0
- package/dist/color/index.js +167 -0
- package/dist/color/index.js.map +1 -0
- package/dist/core/index.d.ts +119 -0
- package/dist/core/index.js +324 -0
- package/dist/core/index.js.map +1 -0
- package/dist/crypto/index.d.ts +84 -0
- package/dist/crypto/index.js +144 -0
- package/dist/crypto/index.js.map +1 -0
- package/dist/date/index.d.ts +588 -0
- package/dist/date/index.js +737 -0
- package/dist/date/index.js.map +1 -0
- package/dist/dep-exray/analyzer/index.d.ts +7 -0
- package/dist/dep-exray/analyzer/index.js +68 -0
- package/dist/dep-exray/analyzer/index.js.map +1 -0
- package/dist/dep-exray/cli.d.ts +1 -0
- package/dist/dep-exray/cli.js +441 -0
- package/dist/dep-exray/cli.js.map +1 -0
- package/dist/dep-exray/index.d.ts +5 -0
- package/dist/dep-exray/index.js +454 -0
- package/dist/dep-exray/index.js.map +1 -0
- package/dist/dep-exray/known-mappings.d.ts +17 -0
- package/dist/dep-exray/known-mappings.js +122 -0
- package/dist/dep-exray/known-mappings.js.map +1 -0
- package/dist/dep-exray/reporter/index.d.ts +5 -0
- package/dist/dep-exray/reporter/index.js +89 -0
- package/dist/dep-exray/reporter/index.js.map +1 -0
- package/dist/dep-exray/scanner/index.d.ts +5 -0
- package/dist/dep-exray/scanner/index.js +299 -0
- package/dist/dep-exray/scanner/index.js.map +1 -0
- package/dist/dep-exray/types.d.ts +38 -0
- package/dist/dep-exray/types.js +1 -0
- package/dist/dep-exray/types.js.map +1 -0
- package/dist/error/index.d.ts +148 -0
- package/dist/error/index.js +115 -0
- package/dist/error/index.js.map +1 -0
- package/dist/index-BgG21uJC.d.ts +166 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +4378 -0
- package/dist/index.js.map +1 -0
- package/dist/io/index.d.ts +39 -0
- package/dist/io/index.js +111 -0
- package/dist/io/index.js.map +1 -0
- package/dist/logger/index.d.ts +1 -0
- package/dist/logger/index.js +214 -0
- package/dist/logger/index.js.map +1 -0
- package/dist/logger/transports.d.ts +1 -0
- package/dist/logger/transports.js +122 -0
- package/dist/logger/transports.js.map +1 -0
- package/dist/math/index.d.ts +362 -0
- package/dist/math/index.js +372 -0
- package/dist/math/index.js.map +1 -0
- package/dist/path/index.d.ts +81 -0
- package/dist/path/index.js +134 -0
- package/dist/path/index.js.map +1 -0
- package/dist/string/index.d.ts +234 -0
- package/dist/string/index.js +411 -0
- package/dist/string/index.js.map +1 -0
- package/dist/type/index.d.ts +85 -0
- package/dist/type/index.js +107 -0
- package/dist/type/index.js.map +1 -0
- package/dist/validation/index.d.ts +203 -0
- package/dist/validation/index.js +402 -0
- package/dist/validation/index.js.map +1 -0
- package/package.json +172 -0
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capitalizes the first character and lowercases the rest.
|
|
3
|
+
*/
|
|
4
|
+
declare function capitalize(str: string): string;
|
|
5
|
+
/**
|
|
6
|
+
* Converts a string to camelCase.
|
|
7
|
+
*/
|
|
8
|
+
declare function camelCase(str: string): string;
|
|
9
|
+
/**
|
|
10
|
+
* Converts a string to kebab-case.
|
|
11
|
+
*/
|
|
12
|
+
declare function kebabCase(str: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* Converts a string to snake_case.
|
|
15
|
+
*/
|
|
16
|
+
declare function snakeCase(str: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* Converts a string to PascalCase.
|
|
19
|
+
*/
|
|
20
|
+
declare function pascalCase(str: string): string;
|
|
21
|
+
/**
|
|
22
|
+
* Truncates a string to the specified length, appending a suffix (default "...").
|
|
23
|
+
*/
|
|
24
|
+
declare function truncate(str: string, maxLength: number, suffix?: string): string;
|
|
25
|
+
/**
|
|
26
|
+
* Simple string interpolation using {{key}} syntax.
|
|
27
|
+
*
|
|
28
|
+
* @example template("Hello {{name}}", { name: "world" }) // => "Hello world"
|
|
29
|
+
*/
|
|
30
|
+
declare function template(str: string, data: Record<string, string | number>): string;
|
|
31
|
+
/**
|
|
32
|
+
* Generates a UUID v4 string.
|
|
33
|
+
* Uses crypto.randomUUID when available, falls back to manual implementation.
|
|
34
|
+
*/
|
|
35
|
+
declare function uuid(): string;
|
|
36
|
+
/**
|
|
37
|
+
* Generates a short random ID with configurable length and alphabet.
|
|
38
|
+
*
|
|
39
|
+
* @default size = 21, alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-"
|
|
40
|
+
*/
|
|
41
|
+
declare function nanoid(size?: number, alphabet?: string): string;
|
|
42
|
+
/**
|
|
43
|
+
* Escapes HTML special characters (&, <, >, ", ').
|
|
44
|
+
*/
|
|
45
|
+
declare function escapeHtml(str: string): string;
|
|
46
|
+
/**
|
|
47
|
+
* Unescapes common HTML entities.
|
|
48
|
+
*/
|
|
49
|
+
declare function unescapeHtml(str: string): string;
|
|
50
|
+
/**
|
|
51
|
+
* Removes whitespace from both ends of a string.
|
|
52
|
+
*/
|
|
53
|
+
declare function trim(str: string): string;
|
|
54
|
+
/**
|
|
55
|
+
* Removes whitespace from the start of a string.
|
|
56
|
+
*/
|
|
57
|
+
declare function trimStart(str: string): string;
|
|
58
|
+
/**
|
|
59
|
+
* Removes whitespace from the end of a string.
|
|
60
|
+
*/
|
|
61
|
+
declare function trimEnd(str: string): string;
|
|
62
|
+
/**
|
|
63
|
+
* Pads a string to the given length by adding characters to both sides.
|
|
64
|
+
*/
|
|
65
|
+
declare function pad(str: string, length: number, char?: string): string;
|
|
66
|
+
/**
|
|
67
|
+
* Pads the start of a string to the given length.
|
|
68
|
+
*/
|
|
69
|
+
declare function padStart(str: string, length: number, char?: string): string;
|
|
70
|
+
/**
|
|
71
|
+
* Pads the end of a string to the given length.
|
|
72
|
+
*/
|
|
73
|
+
declare function padEnd(str: string, length: number, char?: string): string;
|
|
74
|
+
/**
|
|
75
|
+
* Reverses a string.
|
|
76
|
+
*/
|
|
77
|
+
declare function reverse(str: string): string;
|
|
78
|
+
/**
|
|
79
|
+
* Splits a string into words.
|
|
80
|
+
*/
|
|
81
|
+
declare function words(str: string): string[];
|
|
82
|
+
/**
|
|
83
|
+
* Converts a string to a URL-friendly slug.
|
|
84
|
+
*/
|
|
85
|
+
declare function slugify(str: string): string;
|
|
86
|
+
/**
|
|
87
|
+
* Counts occurrences of a substring in a string.
|
|
88
|
+
*/
|
|
89
|
+
declare function countOccurrences(str: string, substring: string): number;
|
|
90
|
+
/**
|
|
91
|
+
* Computes the Levenshtein distance between two strings.
|
|
92
|
+
* Uses iterative DP with O(min(m,n)) space.
|
|
93
|
+
*/
|
|
94
|
+
declare function levenshtein(a: string, b: string): number;
|
|
95
|
+
/**
|
|
96
|
+
* Performs a simple fuzzy match: checks if all characters of query
|
|
97
|
+
* appear in str in order (case-insensitive).
|
|
98
|
+
*/
|
|
99
|
+
declare function fuzzyMatch(str: string, query: string): boolean;
|
|
100
|
+
/**
|
|
101
|
+
* Masks parts of a string, useful for data compliance (PDPA/GDPR).
|
|
102
|
+
*
|
|
103
|
+
* @example maskString('08123456789') // "0812****789"
|
|
104
|
+
* @example maskString('hello@email.com') // "h***@e***.com"
|
|
105
|
+
* @example maskString('1234567890', { start: 0, end: 4, char: '#' }) // "####567890"
|
|
106
|
+
*/
|
|
107
|
+
declare function maskString(str: string, options?: {
|
|
108
|
+
start?: number;
|
|
109
|
+
end?: number;
|
|
110
|
+
char?: string;
|
|
111
|
+
}): string;
|
|
112
|
+
/**
|
|
113
|
+
* Converts a number to Indonesian words (terbilang).
|
|
114
|
+
*
|
|
115
|
+
* @example terbilang(1500000) // "satu juta lima ratus ribu"
|
|
116
|
+
* @example terbilang(2024) // "dua ribu dua puluh empat"
|
|
117
|
+
* @example terbilang(11) // "sebelas"
|
|
118
|
+
* @example terbilang(100) // "seratus"
|
|
119
|
+
*/
|
|
120
|
+
declare function terbilang(value: number): string;
|
|
121
|
+
/**
|
|
122
|
+
* Formats a number as Indonesian Rupiah string.
|
|
123
|
+
*
|
|
124
|
+
* @example formatRupiah(1500000) // "Rp1.500.000"
|
|
125
|
+
* @example formatRupiah(1500000, { notation: 'compact' }) // "Rp1,5 jt"
|
|
126
|
+
*/
|
|
127
|
+
declare function formatRupiah(value: number, options?: {
|
|
128
|
+
notation?: 'standard' | 'compact';
|
|
129
|
+
}): string;
|
|
130
|
+
/**
|
|
131
|
+
* Formats a byte count into a human-readable string.
|
|
132
|
+
*
|
|
133
|
+
* @example formatBytes(1024) // "1 KB"
|
|
134
|
+
* @example formatBytes(1536) // "1.5 KB"
|
|
135
|
+
* @example formatBytes(1048576) // "1 MB"
|
|
136
|
+
* @example formatBytes(0) // "0 B"
|
|
137
|
+
*/
|
|
138
|
+
declare function formatBytes(bytes: number, options?: {
|
|
139
|
+
decimals?: number;
|
|
140
|
+
}): string;
|
|
141
|
+
/**
|
|
142
|
+
* Generates a random alphanumeric string of the specified length.
|
|
143
|
+
*
|
|
144
|
+
* @example randomString() // "a3F8k2..."
|
|
145
|
+
* @example randomString(8) // "X7j2K9mQ"
|
|
146
|
+
*/
|
|
147
|
+
declare function randomString(length?: number): string;
|
|
148
|
+
/**
|
|
149
|
+
* Returns a random boolean value.
|
|
150
|
+
*
|
|
151
|
+
* @example randomBoolean() // true or false
|
|
152
|
+
*/
|
|
153
|
+
declare function randomBoolean(): boolean;
|
|
154
|
+
/**
|
|
155
|
+
* Basic English pluralization helper. Adds 's' or 'es' based on simple rules.
|
|
156
|
+
*
|
|
157
|
+
* @example pluralize(1, 'apple') // "apple"
|
|
158
|
+
* @example pluralize(3, 'apple') // "apples"
|
|
159
|
+
* @example pluralize(0, 'box') // "boxes"
|
|
160
|
+
* @example pluralize(1, 'box') // "box"
|
|
161
|
+
*/
|
|
162
|
+
declare function pluralize(count: number, singular: string): string;
|
|
163
|
+
/**
|
|
164
|
+
* Removes all HTML tags from a string, including script and style content.
|
|
165
|
+
*
|
|
166
|
+
* @example stripHtml('<p>Hello <b>world</b></p>') // "Hello world"
|
|
167
|
+
* @example stripHtml('<script>alert("x")</script>hi') // "hi"
|
|
168
|
+
*/
|
|
169
|
+
declare function stripHtml(str: string): string;
|
|
170
|
+
/**
|
|
171
|
+
* Truncates a string by word count, appending a suffix when truncated.
|
|
172
|
+
*
|
|
173
|
+
* @example truncateWords('hello world foo bar', 2) // "hello world..."
|
|
174
|
+
* @example truncateWords('hello world foo bar', 2, '…') // "hello world…"
|
|
175
|
+
*/
|
|
176
|
+
declare function truncateWords(str: string, count: number, suffix?: string): string;
|
|
177
|
+
/**
|
|
178
|
+
* Checks if a string is a palindrome, ignoring case, spaces, and punctuation.
|
|
179
|
+
*
|
|
180
|
+
* @example isPalindrome('A man, a plan, a canal: Panama') // true
|
|
181
|
+
* @example isPalindrome('race a car') // false
|
|
182
|
+
*/
|
|
183
|
+
declare function isPalindrome(str: string): boolean;
|
|
184
|
+
/**
|
|
185
|
+
* Checks if two strings are anagrams, ignoring case and spaces.
|
|
186
|
+
*
|
|
187
|
+
* @example isAnagram('listen', 'silent') // true
|
|
188
|
+
* @example isAnagram('hello', 'world') // false
|
|
189
|
+
*/
|
|
190
|
+
declare function isAnagram(str1: string, str2: string): boolean;
|
|
191
|
+
/**
|
|
192
|
+
* Computes the Dice coefficient similarity between two strings (0-1).
|
|
193
|
+
*
|
|
194
|
+
* @example similarity('hello', 'hallo') // 0.666...
|
|
195
|
+
* @example similarity('abc', 'xyz') // 0
|
|
196
|
+
*/
|
|
197
|
+
declare function similarity(a: string, b: string): number;
|
|
198
|
+
/**
|
|
199
|
+
* Removes common leading whitespace from each line in a multi-line string.
|
|
200
|
+
*
|
|
201
|
+
* @example dedent(' hello\n world') // "hello\nworld"
|
|
202
|
+
* @example dedent(' foo\n bar') // "foo\n bar"
|
|
203
|
+
*/
|
|
204
|
+
declare function dedent(str: string): string;
|
|
205
|
+
/**
|
|
206
|
+
* Counts the number of words in a string, handling multiple spaces and punctuation.
|
|
207
|
+
*
|
|
208
|
+
* @example wordCount('hello world') // 2
|
|
209
|
+
* @example wordCount(' hello world! ') // 2
|
|
210
|
+
*/
|
|
211
|
+
declare function wordCount(str: string): number;
|
|
212
|
+
/**
|
|
213
|
+
* Swaps the case of each character in a string (upper to lower, lower to upper).
|
|
214
|
+
*
|
|
215
|
+
* @example swapCase('Hello World') // "hELLO wORLD"
|
|
216
|
+
* @example swapCase('ABC123') // "abc123"
|
|
217
|
+
*/
|
|
218
|
+
declare function swapCase(str: string): string;
|
|
219
|
+
/**
|
|
220
|
+
* Converts a string to COBOL / SCREAMING_SNAKE_CASE.
|
|
221
|
+
*
|
|
222
|
+
* @example toCobolCase('helloWorld') // "HELLO_WORLD"
|
|
223
|
+
* @example toCobolCase('getUserByID') // "GET_USER_BY_ID"
|
|
224
|
+
*/
|
|
225
|
+
declare function toCobolCase(str: string): string;
|
|
226
|
+
/**
|
|
227
|
+
* Counts character frequency in a string.
|
|
228
|
+
*
|
|
229
|
+
* @example charCount('hello') // { h: 1, e: 1, l: 2, o: 1 }
|
|
230
|
+
* @example charCount('aabb') // { a: 2, b: 2 }
|
|
231
|
+
*/
|
|
232
|
+
declare function charCount(str: string): Record<string, number>;
|
|
233
|
+
|
|
234
|
+
export { camelCase, capitalize, charCount, countOccurrences, dedent, escapeHtml, formatBytes, formatRupiah, fuzzyMatch, isAnagram, isPalindrome, kebabCase, levenshtein, maskString, nanoid, pad, padEnd, padStart, pascalCase, pluralize, randomBoolean, randomString, reverse, similarity, slugify, snakeCase, stripHtml, swapCase, template, terbilang, toCobolCase, trim, trimEnd, trimStart, truncate, truncateWords, unescapeHtml, uuid, wordCount, words };
|
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
// src/math/index.ts
|
|
2
|
+
function formatCurrency(value, options) {
|
|
3
|
+
const locale = options?.locale ?? "id-ID";
|
|
4
|
+
const currency = options?.currency ?? "IDR";
|
|
5
|
+
const notation = options?.notation ?? "standard";
|
|
6
|
+
try {
|
|
7
|
+
return new Intl.NumberFormat(locale, {
|
|
8
|
+
style: "currency",
|
|
9
|
+
currency,
|
|
10
|
+
notation,
|
|
11
|
+
minimumFractionDigits: 0,
|
|
12
|
+
maximumFractionDigits: 2
|
|
13
|
+
}).format(value);
|
|
14
|
+
} catch {
|
|
15
|
+
return `${currency} ${value.toLocaleString(locale)}`;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// src/string/index.ts
|
|
20
|
+
var WORD_SPLIT_RE = /[A-Z]?[a-z]+|[A-Z]+(?=[A-Z][a-z]|\d|\b)|\d+/g;
|
|
21
|
+
function splitWords(str) {
|
|
22
|
+
return str.match(WORD_SPLIT_RE) ?? [];
|
|
23
|
+
}
|
|
24
|
+
function capitalize(str) {
|
|
25
|
+
if (str.length === 0) return str;
|
|
26
|
+
return str[0].toUpperCase() + str.slice(1).toLowerCase();
|
|
27
|
+
}
|
|
28
|
+
function camelCase(str) {
|
|
29
|
+
const words2 = splitWords(str);
|
|
30
|
+
if (words2.length === 0) return "";
|
|
31
|
+
const [firstWord, ...rest] = words2;
|
|
32
|
+
return firstWord.toLowerCase() + rest.map((w) => w[0].toUpperCase() + w.slice(1).toLowerCase()).join("");
|
|
33
|
+
}
|
|
34
|
+
function kebabCase(str) {
|
|
35
|
+
return splitWords(str).map((w) => w.toLowerCase()).join("-");
|
|
36
|
+
}
|
|
37
|
+
function snakeCase(str) {
|
|
38
|
+
return splitWords(str).map((w) => w.toLowerCase()).join("_");
|
|
39
|
+
}
|
|
40
|
+
function pascalCase(str) {
|
|
41
|
+
return splitWords(str).map((w) => w[0].toUpperCase() + w.slice(1).toLowerCase()).join("");
|
|
42
|
+
}
|
|
43
|
+
function truncate(str, maxLength, suffix = "...") {
|
|
44
|
+
if (str.length <= maxLength) return str;
|
|
45
|
+
return str.slice(0, Math.max(0, maxLength - suffix.length)) + suffix;
|
|
46
|
+
}
|
|
47
|
+
function template(str, data) {
|
|
48
|
+
return str.replace(/\{\{(\w+)\}\}/g, (_, key) => {
|
|
49
|
+
if (key === "__proto__" || key === "constructor" || key === "prototype") return `{{${key}}}`;
|
|
50
|
+
const value = data[key];
|
|
51
|
+
return value !== void 0 ? String(value) : `{{${key}}}`;
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
function uuid() {
|
|
55
|
+
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
56
|
+
return crypto.randomUUID();
|
|
57
|
+
}
|
|
58
|
+
const hex = "0123456789abcdef";
|
|
59
|
+
const chars = [];
|
|
60
|
+
for (let i = 0; i < 36; i++) {
|
|
61
|
+
if (i === 8 || i === 13 || i === 18 || i === 23) {
|
|
62
|
+
chars.push("-");
|
|
63
|
+
} else if (i === 14) {
|
|
64
|
+
chars.push("4");
|
|
65
|
+
} else if (i === 19) {
|
|
66
|
+
chars.push(hex[Math.floor(Math.random() * 4) + 8]);
|
|
67
|
+
} else {
|
|
68
|
+
chars.push(hex[Math.floor(Math.random() * 16)]);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return chars.join("");
|
|
72
|
+
}
|
|
73
|
+
function nanoid(size = 21, alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-") {
|
|
74
|
+
const len = alphabet.length;
|
|
75
|
+
const bytes = new Uint8Array(size);
|
|
76
|
+
if (typeof crypto !== "undefined" && typeof crypto.getRandomValues === "function") {
|
|
77
|
+
crypto.getRandomValues(bytes);
|
|
78
|
+
} else {
|
|
79
|
+
throw new Error("Crypto API unavailable. Cannot generate secure random ID.");
|
|
80
|
+
}
|
|
81
|
+
let result = "";
|
|
82
|
+
for (let i = 0; i < size; i++) {
|
|
83
|
+
result += alphabet[bytes[i] % len];
|
|
84
|
+
}
|
|
85
|
+
return result;
|
|
86
|
+
}
|
|
87
|
+
var HTML_ESCAPE_MAP = {
|
|
88
|
+
"&": "&",
|
|
89
|
+
"<": "<",
|
|
90
|
+
">": ">",
|
|
91
|
+
'"': """,
|
|
92
|
+
"'": "'",
|
|
93
|
+
"`": "`",
|
|
94
|
+
"/": "/"
|
|
95
|
+
};
|
|
96
|
+
var HTML_UNESCAPE_MAP = {
|
|
97
|
+
"&": "&",
|
|
98
|
+
"<": "<",
|
|
99
|
+
">": ">",
|
|
100
|
+
""": '"',
|
|
101
|
+
"'": "'",
|
|
102
|
+
"'": "'",
|
|
103
|
+
"`": "`",
|
|
104
|
+
"/": "/"
|
|
105
|
+
};
|
|
106
|
+
function escapeHtml(str) {
|
|
107
|
+
return str.replace(/[&<>"'`\/]/g, (ch) => HTML_ESCAPE_MAP[ch] ?? ch);
|
|
108
|
+
}
|
|
109
|
+
function unescapeHtml(str) {
|
|
110
|
+
return str.replace(/&(?:amp|lt|gt|quot|#39|#x27|#96|#x2F);/g, (entity) => HTML_UNESCAPE_MAP[entity] ?? entity);
|
|
111
|
+
}
|
|
112
|
+
function trim(str) {
|
|
113
|
+
return str.trim();
|
|
114
|
+
}
|
|
115
|
+
function trimStart(str) {
|
|
116
|
+
return str.trimStart();
|
|
117
|
+
}
|
|
118
|
+
function trimEnd(str) {
|
|
119
|
+
return str.trimEnd();
|
|
120
|
+
}
|
|
121
|
+
function pad(str, length, char = " ") {
|
|
122
|
+
const totalPadding = Math.max(0, length - str.length);
|
|
123
|
+
const leftPad = Math.floor(totalPadding / 2);
|
|
124
|
+
const rightPad = totalPadding - leftPad;
|
|
125
|
+
return char.repeat(leftPad) + str + char.repeat(rightPad);
|
|
126
|
+
}
|
|
127
|
+
function padStart(str, length, char = " ") {
|
|
128
|
+
return str.padStart(length, char);
|
|
129
|
+
}
|
|
130
|
+
function padEnd(str, length, char = " ") {
|
|
131
|
+
return str.padEnd(length, char);
|
|
132
|
+
}
|
|
133
|
+
function reverse(str) {
|
|
134
|
+
return str.split("").reverse().join("");
|
|
135
|
+
}
|
|
136
|
+
function words(str) {
|
|
137
|
+
return splitWords(str);
|
|
138
|
+
}
|
|
139
|
+
function slugify(str) {
|
|
140
|
+
return str.toLowerCase().replace(/[^\w\s-]/g, "").replace(/[\s_]+/g, "-").replace(/-+/g, "-").replace(/^-+/, "").replace(/-+$/, "");
|
|
141
|
+
}
|
|
142
|
+
function countOccurrences(str, substring) {
|
|
143
|
+
if (substring.length === 0 || str.length === 0) return 0;
|
|
144
|
+
let count = 0;
|
|
145
|
+
let pos = 0;
|
|
146
|
+
while ((pos = str.indexOf(substring, pos)) !== -1) {
|
|
147
|
+
count++;
|
|
148
|
+
pos += substring.length;
|
|
149
|
+
}
|
|
150
|
+
return count;
|
|
151
|
+
}
|
|
152
|
+
function levenshtein(a, b) {
|
|
153
|
+
const an = a.length;
|
|
154
|
+
const bn = b.length;
|
|
155
|
+
if (an === 0) return bn;
|
|
156
|
+
if (bn === 0) return an;
|
|
157
|
+
if (an < bn) return levenshtein(b, a);
|
|
158
|
+
let prev = new Uint32Array(bn + 1);
|
|
159
|
+
let curr = new Uint32Array(bn + 1);
|
|
160
|
+
for (let j = 0; j <= bn; j++) prev[j] = j;
|
|
161
|
+
for (let i = 1; i <= an; i++) {
|
|
162
|
+
curr[0] = i;
|
|
163
|
+
for (let j = 1; j <= bn; j++) {
|
|
164
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
165
|
+
curr[j] = Math.min(
|
|
166
|
+
prev[j] + 1,
|
|
167
|
+
curr[j - 1] + 1,
|
|
168
|
+
prev[j - 1] + cost
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
;
|
|
172
|
+
[prev, curr] = [curr, prev];
|
|
173
|
+
}
|
|
174
|
+
return prev[bn];
|
|
175
|
+
}
|
|
176
|
+
function fuzzyMatch(str, query) {
|
|
177
|
+
if (query.length === 0) return true;
|
|
178
|
+
if (str.length === 0) return false;
|
|
179
|
+
const sl = str.toLowerCase();
|
|
180
|
+
const ql = query.toLowerCase();
|
|
181
|
+
let si = 0;
|
|
182
|
+
for (let qi = 0; qi < ql.length; qi++) {
|
|
183
|
+
si = sl.indexOf(ql[qi], si);
|
|
184
|
+
if (si === -1) return false;
|
|
185
|
+
si++;
|
|
186
|
+
}
|
|
187
|
+
return true;
|
|
188
|
+
}
|
|
189
|
+
function maskString(str, options) {
|
|
190
|
+
if (str.length === 0) return str;
|
|
191
|
+
const maskChar = options?.char ?? "*";
|
|
192
|
+
const start = options?.start ?? Math.ceil(str.length * 0.25);
|
|
193
|
+
const end = options?.end ?? Math.floor(str.length * 0.75);
|
|
194
|
+
if (start >= end || start < 0) return str;
|
|
195
|
+
const clampedStart = Math.max(0, start);
|
|
196
|
+
const clampedEnd = Math.min(str.length, end);
|
|
197
|
+
return str.slice(0, clampedStart) + maskChar.repeat(clampedEnd - clampedStart) + str.slice(clampedEnd);
|
|
198
|
+
}
|
|
199
|
+
var SATUAN = ["", "satu", "dua", "tiga", "empat", "lima", "enam", "tujuh", "delapan", "sembilan"];
|
|
200
|
+
var BELASAN = ["sepuluh", "sebelas", "dua belas", "tiga belas", "empat belas", "lima belas", "enam belas", "tujuh belas", "delapan belas", "sembilan belas"];
|
|
201
|
+
var PULUHAN = ["", "", "dua puluh", "tiga puluh", "empat puluh", "lima puluh", "enam puluh", "tujuh puluh", "delapan puluh", "sembilan puluh"];
|
|
202
|
+
function _terbilang(n) {
|
|
203
|
+
if (n < 0) return "minus " + _terbilang(-n);
|
|
204
|
+
if (n === 0) return "nol";
|
|
205
|
+
if (n < 10) return SATUAN[n];
|
|
206
|
+
if (n < 20) return n === 10 ? "sepuluh" : n === 11 ? "sebelas" : BELASAN[n - 10];
|
|
207
|
+
if (n < 100) {
|
|
208
|
+
const pul = Math.floor(n / 10);
|
|
209
|
+
const sat = n % 10;
|
|
210
|
+
return PULUHAN[pul] + (sat > 0 ? " " + SATUAN[sat] : "");
|
|
211
|
+
}
|
|
212
|
+
if (n < 1e3) {
|
|
213
|
+
const ratus = Math.floor(n / 100);
|
|
214
|
+
const sis2 = n % 100;
|
|
215
|
+
const ratusStr = ratus === 1 ? "seratus" : SATUAN[ratus] + " ratus";
|
|
216
|
+
return ratusStr + (sis2 > 0 ? " " + _terbilang(sis2) : "");
|
|
217
|
+
}
|
|
218
|
+
if (n < 1e6) {
|
|
219
|
+
const rib = Math.floor(n / 1e3);
|
|
220
|
+
const sis2 = n % 1e3;
|
|
221
|
+
const ribStr = rib === 1 ? "seribu" : _terbilang(rib) + " ribu";
|
|
222
|
+
return ribStr + (sis2 > 0 ? " " + _terbilang(sis2) : "");
|
|
223
|
+
}
|
|
224
|
+
if (n < 1e9) {
|
|
225
|
+
const jut = Math.floor(n / 1e6);
|
|
226
|
+
const sis2 = n % 1e6;
|
|
227
|
+
return _terbilang(jut) + " juta" + (sis2 > 0 ? " " + _terbilang(sis2) : "");
|
|
228
|
+
}
|
|
229
|
+
if (n < 1e12) {
|
|
230
|
+
const mil = Math.floor(n / 1e9);
|
|
231
|
+
const sis2 = n % 1e9;
|
|
232
|
+
return _terbilang(mil) + " miliar" + (sis2 > 0 ? " " + _terbilang(sis2) : "");
|
|
233
|
+
}
|
|
234
|
+
const tril = Math.floor(n / 1e12);
|
|
235
|
+
const sis = n % 1e12;
|
|
236
|
+
return _terbilang(tril) + " triliun" + (sis > 0 ? " " + _terbilang(sis) : "");
|
|
237
|
+
}
|
|
238
|
+
function terbilang(value) {
|
|
239
|
+
if (!Number.isFinite(value)) throw new RangeError("Input must be a finite number");
|
|
240
|
+
if (value > Number.MAX_SAFE_INTEGER) throw new RangeError("Input terlalu besar");
|
|
241
|
+
return _terbilang(Math.floor(Math.abs(value)));
|
|
242
|
+
}
|
|
243
|
+
function formatRupiah(value, options) {
|
|
244
|
+
return formatCurrency(value, { locale: "id-ID", currency: "IDR", notation: options?.notation });
|
|
245
|
+
}
|
|
246
|
+
function formatBytes(bytes, options) {
|
|
247
|
+
if (bytes === 0) return "0 B";
|
|
248
|
+
if (!Number.isFinite(bytes) || bytes < 0) return "0 B";
|
|
249
|
+
const k = 1024;
|
|
250
|
+
const sizes = ["B", "KB", "MB", "GB", "TB", "PB", "EB"];
|
|
251
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
252
|
+
const dm = options?.decimals ?? (i === 0 ? 0 : 1);
|
|
253
|
+
const index = Math.min(i, sizes.length - 1);
|
|
254
|
+
return parseFloat((bytes / Math.pow(k, index)).toFixed(dm)) + " " + sizes[index];
|
|
255
|
+
}
|
|
256
|
+
function randomString(length = 16) {
|
|
257
|
+
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
258
|
+
const bytes = new Uint8Array(length);
|
|
259
|
+
if (typeof crypto !== "undefined" && typeof crypto.getRandomValues === "function") {
|
|
260
|
+
crypto.getRandomValues(bytes);
|
|
261
|
+
} else {
|
|
262
|
+
throw new Error("Crypto API unavailable. Cannot generate secure random string.");
|
|
263
|
+
}
|
|
264
|
+
let result = "";
|
|
265
|
+
for (let i = 0; i < length; i++) {
|
|
266
|
+
result += chars[bytes[i] % chars.length];
|
|
267
|
+
}
|
|
268
|
+
return result;
|
|
269
|
+
}
|
|
270
|
+
function randomBoolean() {
|
|
271
|
+
return Math.random() >= 0.5;
|
|
272
|
+
}
|
|
273
|
+
function pluralize(count, singular) {
|
|
274
|
+
if (count === 1) return singular;
|
|
275
|
+
const last = singular[singular.length - 1];
|
|
276
|
+
const lastTwo = singular.slice(-2);
|
|
277
|
+
if (last === "s" || last === "x" || last === "z" || lastTwo === "ch" || lastTwo === "sh") {
|
|
278
|
+
return singular + "es";
|
|
279
|
+
}
|
|
280
|
+
if (last === "y" && singular.length > 2 && !"aeiou".includes(singular[singular.length - 2])) {
|
|
281
|
+
return singular.slice(0, -1) + "ies";
|
|
282
|
+
}
|
|
283
|
+
return singular + "s";
|
|
284
|
+
}
|
|
285
|
+
function stripHtml(str) {
|
|
286
|
+
return str.replace(/<[^>]*>/g, "");
|
|
287
|
+
}
|
|
288
|
+
function truncateWords(str, count, suffix = "...") {
|
|
289
|
+
const words2 = str.split(/\s+/).filter(Boolean);
|
|
290
|
+
if (words2.length <= count) return str;
|
|
291
|
+
return words2.slice(0, count).join(" ") + suffix;
|
|
292
|
+
}
|
|
293
|
+
function isPalindrome(str) {
|
|
294
|
+
const cleaned = str.replace(/[^a-zA-Z0-9]/g, "").toLowerCase();
|
|
295
|
+
if (cleaned.length <= 1) return true;
|
|
296
|
+
let left = 0;
|
|
297
|
+
let right = cleaned.length - 1;
|
|
298
|
+
while (left < right) {
|
|
299
|
+
if (cleaned[left] !== cleaned[right]) return false;
|
|
300
|
+
left++;
|
|
301
|
+
right--;
|
|
302
|
+
}
|
|
303
|
+
return true;
|
|
304
|
+
}
|
|
305
|
+
function isAnagram(str1, str2) {
|
|
306
|
+
const clean = (s) => s.replace(/\s/g, "").toLowerCase().split("").sort().join("");
|
|
307
|
+
return clean(str1) === clean(str2);
|
|
308
|
+
}
|
|
309
|
+
function similarity(a, b) {
|
|
310
|
+
if (a === b) return 1;
|
|
311
|
+
if (a.length < 2 || b.length < 2) return 0;
|
|
312
|
+
const bigrams = /* @__PURE__ */ new Map();
|
|
313
|
+
for (let i = 0; i < a.length - 1; i++) {
|
|
314
|
+
const bg = a.slice(i, i + 2);
|
|
315
|
+
bigrams.set(bg, (bigrams.get(bg) ?? 0) + 1);
|
|
316
|
+
}
|
|
317
|
+
let intersection = 0;
|
|
318
|
+
for (let i = 0; i < b.length - 1; i++) {
|
|
319
|
+
const bg = b.slice(i, i + 2);
|
|
320
|
+
const count = bigrams.get(bg) ?? 0;
|
|
321
|
+
if (count > 0) {
|
|
322
|
+
bigrams.set(bg, count - 1);
|
|
323
|
+
intersection++;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
return 2 * intersection / (a.length + b.length - 2);
|
|
327
|
+
}
|
|
328
|
+
function dedent(str) {
|
|
329
|
+
const lines = str.split("\n");
|
|
330
|
+
if (lines.length === 0) return str;
|
|
331
|
+
const indent = lines.reduce((min, line) => {
|
|
332
|
+
if (line.trim().length === 0) return min;
|
|
333
|
+
const leading = line.match(/^[ \t]*/)?.[0]?.length ?? 0;
|
|
334
|
+
return min === null ? leading : Math.min(min, leading);
|
|
335
|
+
}, null);
|
|
336
|
+
if (indent === null || indent === 0) return str;
|
|
337
|
+
return lines.map((line) => line.slice(indent)).join("\n");
|
|
338
|
+
}
|
|
339
|
+
function wordCount(str) {
|
|
340
|
+
const match = str.match(/[a-zA-Z0-9]+(?:['\u2019][a-zA-Z]+)?/g);
|
|
341
|
+
return match ? match.length : 0;
|
|
342
|
+
}
|
|
343
|
+
function swapCase(str) {
|
|
344
|
+
let result = "";
|
|
345
|
+
for (let i = 0; i < str.length; i++) {
|
|
346
|
+
const ch = str[i];
|
|
347
|
+
if (ch >= "a" && ch <= "z") {
|
|
348
|
+
result += ch.toUpperCase();
|
|
349
|
+
} else if (ch >= "A" && ch <= "Z") {
|
|
350
|
+
result += ch.toLowerCase();
|
|
351
|
+
} else {
|
|
352
|
+
result += ch;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
return result;
|
|
356
|
+
}
|
|
357
|
+
function toCobolCase(str) {
|
|
358
|
+
const words2 = splitWords(str);
|
|
359
|
+
return words2.map((w) => w.toUpperCase()).join("_");
|
|
360
|
+
}
|
|
361
|
+
function charCount(str) {
|
|
362
|
+
const result = {};
|
|
363
|
+
for (let i = 0; i < str.length; i++) {
|
|
364
|
+
const ch = str[i];
|
|
365
|
+
result[ch] = (result[ch] ?? 0) + 1;
|
|
366
|
+
}
|
|
367
|
+
return result;
|
|
368
|
+
}
|
|
369
|
+
export {
|
|
370
|
+
camelCase,
|
|
371
|
+
capitalize,
|
|
372
|
+
charCount,
|
|
373
|
+
countOccurrences,
|
|
374
|
+
dedent,
|
|
375
|
+
escapeHtml,
|
|
376
|
+
formatBytes,
|
|
377
|
+
formatRupiah,
|
|
378
|
+
fuzzyMatch,
|
|
379
|
+
isAnagram,
|
|
380
|
+
isPalindrome,
|
|
381
|
+
kebabCase,
|
|
382
|
+
levenshtein,
|
|
383
|
+
maskString,
|
|
384
|
+
nanoid,
|
|
385
|
+
pad,
|
|
386
|
+
padEnd,
|
|
387
|
+
padStart,
|
|
388
|
+
pascalCase,
|
|
389
|
+
pluralize,
|
|
390
|
+
randomBoolean,
|
|
391
|
+
randomString,
|
|
392
|
+
reverse,
|
|
393
|
+
similarity,
|
|
394
|
+
slugify,
|
|
395
|
+
snakeCase,
|
|
396
|
+
stripHtml,
|
|
397
|
+
swapCase,
|
|
398
|
+
template,
|
|
399
|
+
terbilang,
|
|
400
|
+
toCobolCase,
|
|
401
|
+
trim,
|
|
402
|
+
trimEnd,
|
|
403
|
+
trimStart,
|
|
404
|
+
truncate,
|
|
405
|
+
truncateWords,
|
|
406
|
+
unescapeHtml,
|
|
407
|
+
uuid,
|
|
408
|
+
wordCount,
|
|
409
|
+
words
|
|
410
|
+
};
|
|
411
|
+
//# sourceMappingURL=index.js.map
|