stringzy 4.1.0 → 4.2.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.
Files changed (82) hide show
  1. package/.github/workflows/auto-assign.yml +26 -0
  2. package/CODE_OF_CONDUCT.MD +115 -0
  3. package/README.md +591 -79
  4. package/dist/analyzing/checkMultiplePatterns.d.ts +2 -2
  5. package/dist/analyzing/checkMultiplePatterns.js +43 -31
  6. package/dist/analyzing/index.d.ts +3 -0
  7. package/dist/analyzing/index.js +6 -2
  8. package/dist/analyzing/lexicographicalRank.d.ts +26 -0
  9. package/dist/analyzing/lexicographicalRank.js +66 -0
  10. package/dist/formatting/binary.d.ts +24 -0
  11. package/dist/formatting/binary.js +49 -0
  12. package/dist/formatting/creditCard.d.ts +8 -0
  13. package/dist/formatting/creditCard.js +28 -0
  14. package/dist/formatting/decimal.d.ts +21 -0
  15. package/dist/formatting/decimal.js +73 -0
  16. package/dist/formatting/duration.d.ts +27 -0
  17. package/dist/formatting/duration.js +92 -0
  18. package/dist/formatting/fileSize.d.ts +18 -0
  19. package/dist/formatting/fileSize.js +39 -0
  20. package/dist/formatting/hexadecimal.d.ts +14 -0
  21. package/dist/formatting/hexadecimal.js +38 -0
  22. package/dist/formatting/index.d.ts +42 -0
  23. package/dist/formatting/index.js +57 -1
  24. package/dist/formatting/listToString.d.ts +17 -0
  25. package/dist/formatting/listToString.js +35 -0
  26. package/dist/formatting/octal.d.ts +19 -0
  27. package/dist/formatting/octal.js +31 -0
  28. package/dist/formatting/ordinal.d.ts +20 -0
  29. package/dist/formatting/ordinal.js +43 -0
  30. package/dist/formatting/percentage.d.ts +19 -0
  31. package/dist/formatting/percentage.js +31 -0
  32. package/dist/formatting/romanNumerals.d.ts +20 -0
  33. package/dist/formatting/romanNumerals.js +53 -0
  34. package/dist/formatting/scientific.d.ts +14 -0
  35. package/dist/formatting/scientific.js +24 -0
  36. package/dist/formatting/temperature.d.ts +6 -0
  37. package/dist/formatting/temperature.js +27 -0
  38. package/dist/formatting/trim.d.ts +10 -0
  39. package/dist/formatting/trim.js +20 -0
  40. package/dist/index.d.ts +17 -0
  41. package/dist/tests/analyzing/lexicographicalRank.test.d.ts +1 -0
  42. package/dist/tests/analyzing/lexicographicalRank.test.js +43 -0
  43. package/dist/tests/formatting/binary.test.d.ts +1 -0
  44. package/dist/tests/formatting/binary.test.js +53 -0
  45. package/dist/tests/formatting/creditCard.test.d.ts +1 -0
  46. package/dist/tests/formatting/creditCard.test.js +31 -0
  47. package/dist/tests/formatting/decimal.test.d.ts +1 -0
  48. package/dist/tests/formatting/decimal.test.js +62 -0
  49. package/dist/tests/formatting/duration.test.d.ts +1 -0
  50. package/dist/tests/formatting/duration.test.js +61 -0
  51. package/dist/tests/formatting/fileSize.test.d.ts +1 -0
  52. package/dist/tests/formatting/fileSize.test.js +39 -0
  53. package/dist/tests/formatting/hexadecimal.test.d.ts +1 -0
  54. package/dist/tests/formatting/hexadecimal.test.js +38 -0
  55. package/dist/tests/formatting/listToString.test.d.ts +1 -0
  56. package/dist/tests/formatting/listToString.test.js +37 -0
  57. package/dist/tests/formatting/octal.test.d.ts +1 -0
  58. package/dist/tests/formatting/octal.test.js +36 -0
  59. package/dist/tests/formatting/ordinal.test.d.ts +1 -0
  60. package/dist/tests/formatting/ordinal.test.js +37 -0
  61. package/dist/tests/formatting/percentage.test.d.ts +1 -0
  62. package/dist/tests/formatting/percentage.test.js +38 -0
  63. package/dist/tests/formatting/romanNumerals.test.d.ts +1 -0
  64. package/dist/tests/formatting/romanNumerals.test.js +35 -0
  65. package/dist/tests/formatting/scientific.test.d.ts +1 -0
  66. package/dist/tests/formatting/scientific.test.js +35 -0
  67. package/dist/tests/formatting/temperature.test.d.ts +1 -0
  68. package/dist/tests/formatting/temperature.test.js +34 -0
  69. package/dist/tests/formatting/trim.test.d.ts +1 -0
  70. package/dist/tests/formatting/trim.test.js +42 -0
  71. package/dist/tests/transformations/stringPermutations.test.js +70 -0
  72. package/dist/tests/validations/isIPv6.test.d.ts +1 -0
  73. package/dist/tests/validations/isIPv6.test.js +65 -0
  74. package/dist/transformations/index.d.ts +3 -2
  75. package/dist/transformations/index.js +3 -1
  76. package/dist/transformations/stringPermutations.d.ts +23 -1
  77. package/dist/transformations/stringPermutations.js +127 -1
  78. package/dist/validations/index.d.ts +3 -0
  79. package/dist/validations/index.js +5 -1
  80. package/dist/validations/isIPv6.d.ts +24 -0
  81. package/dist/validations/isIPv6.js +45 -0
  82. package/package.json +1 -1
@@ -1,9 +1,9 @@
1
1
  /**
2
- * Finds occurrences of multiple patterns within a given text using RabinKarp algorithm.
2
+ * Finds occurrences of multiple patterns within a given text using AhoCorasick algorithm.
3
3
  *
4
4
  * - Accepts an array of patterns.
5
5
  * - Returns all matches of each pattern along with starting indices.
6
- * - Handles hash collisions by verifying actual substrings.
6
+ * - Handles overlapping matches.
7
7
  * - Is case sensitive
8
8
  *
9
9
  * @param {string} text - The text to search within.
@@ -1,10 +1,10 @@
1
1
  "use strict";
2
2
  /**
3
- * Finds occurrences of multiple patterns within a given text using RabinKarp algorithm.
3
+ * Finds occurrences of multiple patterns within a given text using AhoCorasick algorithm.
4
4
  *
5
5
  * - Accepts an array of patterns.
6
6
  * - Returns all matches of each pattern along with starting indices.
7
- * - Handles hash collisions by verifying actual substrings.
7
+ * - Handles overlapping matches.
8
8
  * - Is case sensitive
9
9
  *
10
10
  * @param {string} text - The text to search within.
@@ -25,38 +25,50 @@ function checkMultiplePatterns(text, patterns) {
25
25
  if (text.length === 0 || patterns.length === 0) {
26
26
  return result;
27
27
  }
28
- const prime = 101; // A prime base for hashing
29
- const getHash = (str, m) => {
30
- let h = 0;
31
- for (let i = 0; i < m; i++) {
32
- h = (h * 256 + str.charCodeAt(i)) % prime;
33
- }
34
- return h;
35
- };
36
- const recomputeHash = (oldHash, dropped, added, m) => {
37
- let h = (oldHash - dropped.charCodeAt(0) * Math.pow(256, m - 1)) % prime;
38
- h = (h * 256 + added.charCodeAt(0)) % prime;
39
- if (h < 0)
40
- h += prime;
41
- return h;
42
- };
28
+ const root = { next: {}, fail: null, output: [] };
43
29
  for (const pattern of patterns) {
44
- const m = pattern.length;
30
+ let node = root;
31
+ for (const ch of pattern) {
32
+ if (!node.next[ch])
33
+ node.next[ch] = { next: {}, fail: null, output: [] };
34
+ node = node.next[ch];
35
+ }
36
+ node.output.push(pattern);
45
37
  result[pattern] = [];
46
- if (m === 0 || m > text.length)
47
- continue;
48
- const patternHash = getHash(pattern, m);
49
- let windowHash = getHash(text, m);
50
- for (let i = 0; i <= text.length - m; i++) {
51
- if (patternHash === windowHash) {
52
- // Verify to avoid collision false positives
53
- if (text.slice(i, i + m) === pattern) {
54
- result[pattern].push(i);
55
- }
56
- }
57
- if (i < text.length - m) {
58
- windowHash = recomputeHash(windowHash, text[i], text[i + m], m);
38
+ }
39
+ const queue = [];
40
+ for (const ch in root.next) {
41
+ const node = root.next[ch];
42
+ node.fail = root;
43
+ queue.push(node);
44
+ }
45
+ while (queue.length) {
46
+ const current = queue.shift();
47
+ for (const ch in current.next) {
48
+ const child = current.next[ch];
49
+ let fail = current.fail;
50
+ // Find deepest fail link with the same transition
51
+ while (fail && !fail.next[ch]) {
52
+ fail = fail.fail;
59
53
  }
54
+ child.fail = fail ? fail.next[ch] : root;
55
+ child.output = child.output.concat(child.fail.output);
56
+ queue.push(child);
57
+ }
58
+ }
59
+ let node = root;
60
+ for (let i = 0; i < text.length; i++) {
61
+ const ch = text[i];
62
+ while (node && !node.next[ch]) {
63
+ node = node.fail;
64
+ }
65
+ if (!node) {
66
+ node = root;
67
+ continue;
68
+ }
69
+ node = node.next[ch];
70
+ for (const pattern of node.output) {
71
+ result[pattern].push(i - pattern.length + 1);
60
72
  }
61
73
  }
62
74
  return result;
@@ -11,6 +11,7 @@ export { checkSubsequence } from './checkSubsequence';
11
11
  export { functionWordCount } from './functionWordCount';
12
12
  export { contentWordCount } from './contentWordCount';
13
13
  export { checkStringRotations } from './stringRotation';
14
+ export { lexicographicalRank } from './lexicographicalRank';
14
15
  import { characterCount } from './characterCount';
15
16
  import { characterFrequency } from './characterFrequency';
16
17
  import { complexity } from './complexity';
@@ -22,6 +23,7 @@ import { vowelConsonantCount } from './vowelConsonantCount';
22
23
  import { checkMultiplePatterns } from './checkMultiplePatterns';
23
24
  import { checkSubsequence } from './checkSubsequence';
24
25
  import { checkStringRotations } from './stringRotation';
26
+ import { lexicographicalRank } from './lexicographicalRank';
25
27
  export declare const analyzing: {
26
28
  characterCount: typeof characterCount;
27
29
  characterFrequency: typeof characterFrequency;
@@ -34,4 +36,5 @@ export declare const analyzing: {
34
36
  checkMultiplePatterns: typeof checkMultiplePatterns;
35
37
  checkSubsequence: typeof checkSubsequence;
36
38
  checkStringRotations: typeof checkStringRotations;
39
+ lexicographicalRank: typeof lexicographicalRank;
37
40
  };
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.analyzing = exports.checkStringRotations = exports.contentWordCount = exports.functionWordCount = exports.checkSubsequence = exports.checkMultiplePatterns = exports.vowelConsonantCount = exports.patternCount = exports.stringSimilarity = exports.wordCount = exports.readingDuration = exports.complexity = exports.characterFrequency = exports.characterCount = void 0;
3
+ exports.analyzing = exports.lexicographicalRank = exports.checkStringRotations = exports.contentWordCount = exports.functionWordCount = exports.checkSubsequence = exports.checkMultiplePatterns = exports.vowelConsonantCount = exports.patternCount = exports.stringSimilarity = exports.wordCount = exports.readingDuration = exports.complexity = exports.characterFrequency = exports.characterCount = void 0;
4
4
  var characterCount_1 = require("./characterCount");
5
5
  Object.defineProperty(exports, "characterCount", { enumerable: true, get: function () { return characterCount_1.characterCount; } });
6
6
  var characterFrequency_1 = require("./characterFrequency");
@@ -27,6 +27,8 @@ var contentWordCount_1 = require("./contentWordCount");
27
27
  Object.defineProperty(exports, "contentWordCount", { enumerable: true, get: function () { return contentWordCount_1.contentWordCount; } });
28
28
  var stringRotation_1 = require("./stringRotation");
29
29
  Object.defineProperty(exports, "checkStringRotations", { enumerable: true, get: function () { return stringRotation_1.checkStringRotations; } });
30
+ var lexicographicalRank_1 = require("./lexicographicalRank");
31
+ Object.defineProperty(exports, "lexicographicalRank", { enumerable: true, get: function () { return lexicographicalRank_1.lexicographicalRank; } });
30
32
  const characterCount_2 = require("./characterCount");
31
33
  const characterFrequency_2 = require("./characterFrequency");
32
34
  const complexity_2 = require("./complexity");
@@ -38,6 +40,7 @@ const vowelConsonantCount_2 = require("./vowelConsonantCount");
38
40
  const checkMultiplePatterns_2 = require("./checkMultiplePatterns");
39
41
  const checkSubsequence_2 = require("./checkSubsequence");
40
42
  const stringRotation_2 = require("./stringRotation");
43
+ const lexicographicalRank_2 = require("./lexicographicalRank");
41
44
  exports.analyzing = {
42
45
  characterCount: characterCount_2.characterCount,
43
46
  characterFrequency: characterFrequency_2.characterFrequency,
@@ -49,5 +52,6 @@ exports.analyzing = {
49
52
  vowelConsonantCount: vowelConsonantCount_2.vowelConsonantCount,
50
53
  checkMultiplePatterns: checkMultiplePatterns_2.checkMultiplePatterns,
51
54
  checkSubsequence: checkSubsequence_2.checkSubsequence,
52
- checkStringRotations: stringRotation_2.checkStringRotations
55
+ checkStringRotations: stringRotation_2.checkStringRotations,
56
+ lexicographicalRank: lexicographicalRank_2.lexicographicalRank
53
57
  };
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Calculates the lexicographic rank of a string among all its unique permutations.
3
+ *
4
+ * The rank is 1-based (i.e., the first permutation has rank 1).
5
+ * Handles strings with duplicate characters correctly by adjusting for repetition.
6
+ *
7
+ * @param {string} str - The input string.
8
+ * @returns {number} The 1-based lexicographic rank of the string.
9
+ * @throws {TypeError} If the input is not a string.
10
+ *
11
+ * @example
12
+ * lexicographicRank("acb"); // 2
13
+ *
14
+ * @example
15
+ * lexicographicRank("string"); // 598
16
+ *
17
+ * @example
18
+ * lexicographicRank("cba"); // 6
19
+ *
20
+ * @example
21
+ * lexicographicRank("aba"); // 2
22
+ *
23
+ * @example
24
+ * lexicographicRank("a"); // 1
25
+ */
26
+ export declare function lexicographicalRank(str: string): number;
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.lexicographicalRank = lexicographicalRank;
4
+ /**
5
+ * Calculates the lexicographic rank of a string among all its unique permutations.
6
+ *
7
+ * The rank is 1-based (i.e., the first permutation has rank 1).
8
+ * Handles strings with duplicate characters correctly by adjusting for repetition.
9
+ *
10
+ * @param {string} str - The input string.
11
+ * @returns {number} The 1-based lexicographic rank of the string.
12
+ * @throws {TypeError} If the input is not a string.
13
+ *
14
+ * @example
15
+ * lexicographicRank("acb"); // 2
16
+ *
17
+ * @example
18
+ * lexicographicRank("string"); // 598
19
+ *
20
+ * @example
21
+ * lexicographicRank("cba"); // 6
22
+ *
23
+ * @example
24
+ * lexicographicRank("aba"); // 2
25
+ *
26
+ * @example
27
+ * lexicographicRank("a"); // 1
28
+ */
29
+ function lexicographicalRank(str) {
30
+ if (typeof str !== 'string') {
31
+ throw new TypeError('Input must be a string');
32
+ }
33
+ if (str.length === 0)
34
+ return 1;
35
+ const factorial = (n) => (n <= 1 ? 1 : n * factorial(n - 1));
36
+ const charCount = {};
37
+ for (const ch of str) {
38
+ charCount[ch] = (charCount[ch] || 0) + 1;
39
+ }
40
+ const chars = Object.keys(charCount).sort();
41
+ let rank = 1;
42
+ for (let i = 0; i < str.length; i++) {
43
+ const ch = str[i];
44
+ for (const smaller of chars) {
45
+ if (smaller >= ch)
46
+ break;
47
+ if (charCount[smaller] > 0) {
48
+ charCount[smaller]--;
49
+ let denom = 1;
50
+ const remaining = str.length - i - 1;
51
+ for (const count of Object.values(charCount)) {
52
+ denom *= factorial(count);
53
+ }
54
+ rank += factorial(remaining) / denom;
55
+ charCount[smaller]++;
56
+ }
57
+ }
58
+ if (charCount[ch] > 0) {
59
+ charCount[ch]--;
60
+ }
61
+ else {
62
+ break; // shouldn't happen unless str has invalid chars
63
+ }
64
+ }
65
+ return rank;
66
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Converts a decimal integer to its binary (base-2) string representation.
3
+ *
4
+ * - Supports negative numbers (prefixed with '-')
5
+ * - Optional grouping from the least significant bit for readability
6
+ *
7
+ * Examples:
8
+ * 5 → "101"
9
+ * 10 → "1010"
10
+ * 255 → "11111111"
11
+ * 0 → "0"
12
+ *
13
+ * Grouping examples (from right to left):
14
+ * formatToBinary(255, { group: 4 }) → "1111 1111"
15
+ * formatToBinary(10, { group: 2 }) → "10 10"
16
+ *
17
+ * @param {number} num - The decimal integer to convert.
18
+ * @param {{ group?: number }} [options] - Optional grouping configuration.
19
+ * @returns {string} The binary string representation.
20
+ * @throws {TypeError} If input is not a number, is NaN, or not an integer.
21
+ */
22
+ export declare function formatToBinary(num: number, options?: {
23
+ group?: number;
24
+ }): string;
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formatToBinary = formatToBinary;
4
+ /**
5
+ * Converts a decimal integer to its binary (base-2) string representation.
6
+ *
7
+ * - Supports negative numbers (prefixed with '-')
8
+ * - Optional grouping from the least significant bit for readability
9
+ *
10
+ * Examples:
11
+ * 5 → "101"
12
+ * 10 → "1010"
13
+ * 255 → "11111111"
14
+ * 0 → "0"
15
+ *
16
+ * Grouping examples (from right to left):
17
+ * formatToBinary(255, { group: 4 }) → "1111 1111"
18
+ * formatToBinary(10, { group: 2 }) → "10 10"
19
+ *
20
+ * @param {number} num - The decimal integer to convert.
21
+ * @param {{ group?: number }} [options] - Optional grouping configuration.
22
+ * @returns {string} The binary string representation.
23
+ * @throws {TypeError} If input is not a number, is NaN, or not an integer.
24
+ */
25
+ function formatToBinary(num, options) {
26
+ if (typeof num !== 'number' || Number.isNaN(num)) {
27
+ throw new TypeError('Input must be a number');
28
+ }
29
+ if (!Number.isInteger(num)) {
30
+ throw new TypeError('Input must be an integer');
31
+ }
32
+ const isNegative = num < 0;
33
+ const absoluteValue = Math.abs(num);
34
+ // Handle zero explicitly to avoid "-0" or empty strings
35
+ const core = absoluteValue.toString(2);
36
+ const groupSize = options === null || options === void 0 ? void 0 : options.group;
37
+ if (groupSize !== undefined) {
38
+ if (typeof groupSize !== 'number' ||
39
+ Number.isNaN(groupSize) ||
40
+ !Number.isInteger(groupSize) ||
41
+ groupSize <= 0) {
42
+ throw new TypeError('Group size must be a positive integer');
43
+ }
44
+ }
45
+ const grouped = groupSize && core.length > groupSize
46
+ ? core.replace(new RegExp(`\\B(?=(\\d{${groupSize}})+(?!\\d))`, 'g'), ' ')
47
+ : core;
48
+ return isNegative ? `-${grouped}` : grouped;
49
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Formats a credit card number by grouping digits into readable parts.
3
+ *
4
+ * @param {string} cardNumber - The credit card number to format.
5
+ * @returns {string} The formatted credit card number.
6
+ * @throws {TypeError} If the input is not a string.
7
+ */
8
+ export declare function formatCreditCard(cardNumber: string): string;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formatCreditCard = formatCreditCard;
4
+ /**
5
+ * Formats a credit card number by grouping digits into readable parts.
6
+ *
7
+ * @param {string} cardNumber - The credit card number to format.
8
+ * @returns {string} The formatted credit card number.
9
+ * @throws {TypeError} If the input is not a string.
10
+ */
11
+ function formatCreditCard(cardNumber) {
12
+ if (typeof cardNumber !== 'string') {
13
+ throw new TypeError('Input must be a string');
14
+ }
15
+ // Remove all non-digit characters
16
+ const cleaned = cardNumber.replace(/\D/g, '');
17
+ // Only accept 15 or 16 digit card numbers
18
+ if (cleaned.length !== 15 && cleaned.length !== 16) {
19
+ return '';
20
+ }
21
+ // Format based on length:
22
+ // 16 digits → 4-4-4-4 (Visa, MasterCard)
23
+ if (cleaned.length === 16) {
24
+ return cleaned.replace(/(\d{4})(?=\d)/g, '$1 ').trim();
25
+ }
26
+ // 15 digits → 4-6-5 (AmEx)
27
+ return cleaned.replace(/(\d{4})(\d{6})(\d{5})/, '$1 $2 $3');
28
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Converts a string in base 2, 8, or 16 to its decimal (base-10) number.
3
+ *
4
+ * - Supports optional standard prefixes: 0b, 0o, 0x (case-insensitive)
5
+ * - Trims leading/trailing whitespace
6
+ * - Supports uppercase and lowercase characters for hexadecimal
7
+ *
8
+ * Examples:
9
+ * formatToDecimal('1010', { base: 2 }) → 10
10
+ * formatToDecimal('12', { base: 8 }) → 10
11
+ * formatToDecimal('FF', { base: 16 }) → 255
12
+ * formatToDecimal('0xFF', { base: 16 })→ 255
13
+ *
14
+ * @param {string} value - The input string representing a number in the given base.
15
+ * @param {{ base: 2 | 8 | 16 }} options - Options containing the base of the input string.
16
+ * @returns {number} The decimal (base-10) representation.
17
+ * @throws {TypeError} For non-string inputs, unsupported bases, or malformed values.
18
+ */
19
+ export declare function formatToDecimal(value: string, options: {
20
+ base: 2 | 8 | 16;
21
+ }): number;
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formatToDecimal = formatToDecimal;
4
+ /**
5
+ * Converts a string in base 2, 8, or 16 to its decimal (base-10) number.
6
+ *
7
+ * - Supports optional standard prefixes: 0b, 0o, 0x (case-insensitive)
8
+ * - Trims leading/trailing whitespace
9
+ * - Supports uppercase and lowercase characters for hexadecimal
10
+ *
11
+ * Examples:
12
+ * formatToDecimal('1010', { base: 2 }) → 10
13
+ * formatToDecimal('12', { base: 8 }) → 10
14
+ * formatToDecimal('FF', { base: 16 }) → 255
15
+ * formatToDecimal('0xFF', { base: 16 })→ 255
16
+ *
17
+ * @param {string} value - The input string representing a number in the given base.
18
+ * @param {{ base: 2 | 8 | 16 }} options - Options containing the base of the input string.
19
+ * @returns {number} The decimal (base-10) representation.
20
+ * @throws {TypeError} For non-string inputs, unsupported bases, or malformed values.
21
+ */
22
+ function formatToDecimal(value, options) {
23
+ if (typeof value !== 'string') {
24
+ throw new TypeError('Input must be a string');
25
+ }
26
+ const base = options === null || options === void 0 ? void 0 : options.base;
27
+ if (base !== 2 && base !== 8 && base !== 16) {
28
+ throw new TypeError('Base must be one of 2, 8, or 16');
29
+ }
30
+ let trimmed = value.trim();
31
+ if (trimmed.length === 0) {
32
+ throw new TypeError('Input must be a non-empty string');
33
+ }
34
+ // Optional sign support; not required by spec but harmless and intuitive
35
+ let isNegative = false;
36
+ if (trimmed.startsWith('+') || trimmed.startsWith('-')) {
37
+ isNegative = trimmed[0] === '-';
38
+ trimmed = trimmed.slice(1);
39
+ if (trimmed.length === 0) {
40
+ throw new TypeError('Malformed numeric string');
41
+ }
42
+ }
43
+ // Strip standard prefixes if present and base matches
44
+ const prefix = trimmed.slice(0, 2).toLowerCase();
45
+ if (prefix === '0b' && base === 2) {
46
+ trimmed = trimmed.slice(2);
47
+ }
48
+ else if (prefix === '0o' && base === 8) {
49
+ trimmed = trimmed.slice(2);
50
+ }
51
+ else if (prefix === '0x' && base === 16) {
52
+ trimmed = trimmed.slice(2);
53
+ }
54
+ if (trimmed.length === 0) {
55
+ throw new TypeError('Malformed numeric string');
56
+ }
57
+ // Validate characters for the specified base
58
+ let pattern;
59
+ if (base === 2) {
60
+ pattern = /^[01]+$/;
61
+ }
62
+ else if (base === 8) {
63
+ pattern = /^[0-7]+$/;
64
+ }
65
+ else {
66
+ pattern = /^[0-9a-fA-F]+$/;
67
+ }
68
+ if (!pattern.test(trimmed)) {
69
+ throw new TypeError('Input contains invalid characters for the specified base');
70
+ }
71
+ const parsed = parseInt(trimmed, base);
72
+ return isNegative ? -parsed : parsed;
73
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Converts a duration in seconds or milliseconds into a human-readable string.
3
+ * Intelligently displays hours, minutes, seconds, and optionally milliseconds,
4
+ * while skipping zero-value units unless the entire duration is zero.
5
+ *
6
+ * @param {number} input - The duration in seconds or milliseconds.
7
+ * @param {object} [options] - Configuration options.
8
+ * @param {string} [options.unit='seconds'] - The input unit: 'seconds' or 'milliseconds'.
9
+ * @param {string} [options.format='short'] - Output format: 'short', 'medium', or 'long'.
10
+ * @param {boolean} [options.includeMs=false] - Whether to include milliseconds in the output.
11
+ * @param {string} [options.delimiter=' '] - The delimiter between time units.
12
+ * @returns {string} The formatted duration string.
13
+ * @throws {TypeError} If input is not a number or is negative.
14
+ *
15
+ * @example
16
+ * formatDuration(60); // "1m"
17
+ * formatDuration(61); // "1m 1s"
18
+ * formatDuration(3661); // "1h 1m 1s"
19
+ * formatDuration(1234567, { unit: 'milliseconds', includeMs: true }); // "20m 34s 567ms"
20
+ * formatDuration(3600, { format: 'long' }); // "1 hour"
21
+ */
22
+ export declare function formatDuration(input: number, options?: {
23
+ unit?: 'seconds' | 'milliseconds';
24
+ format?: 'short' | 'medium' | 'long';
25
+ includeMs?: boolean;
26
+ delimiter?: string;
27
+ }): string;
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formatDuration = formatDuration;
4
+ /**
5
+ * Converts a duration in seconds or milliseconds into a human-readable string.
6
+ * Intelligently displays hours, minutes, seconds, and optionally milliseconds,
7
+ * while skipping zero-value units unless the entire duration is zero.
8
+ *
9
+ * @param {number} input - The duration in seconds or milliseconds.
10
+ * @param {object} [options] - Configuration options.
11
+ * @param {string} [options.unit='seconds'] - The input unit: 'seconds' or 'milliseconds'.
12
+ * @param {string} [options.format='short'] - Output format: 'short', 'medium', or 'long'.
13
+ * @param {boolean} [options.includeMs=false] - Whether to include milliseconds in the output.
14
+ * @param {string} [options.delimiter=' '] - The delimiter between time units.
15
+ * @returns {string} The formatted duration string.
16
+ * @throws {TypeError} If input is not a number or is negative.
17
+ *
18
+ * @example
19
+ * formatDuration(60); // "1m"
20
+ * formatDuration(61); // "1m 1s"
21
+ * formatDuration(3661); // "1h 1m 1s"
22
+ * formatDuration(1234567, { unit: 'milliseconds', includeMs: true }); // "20m 34s 567ms"
23
+ * formatDuration(3600, { format: 'long' }); // "1 hour"
24
+ */
25
+ function formatDuration(input, options) {
26
+ // Validate input
27
+ if (typeof input !== 'number' || isNaN(input)) {
28
+ throw new TypeError('Input must be a number');
29
+ }
30
+ if (input < 0) {
31
+ throw new TypeError('Input must be non-negative');
32
+ }
33
+ // Default options
34
+ const opts = {
35
+ unit: (options === null || options === void 0 ? void 0 : options.unit) || 'seconds',
36
+ format: (options === null || options === void 0 ? void 0 : options.format) || 'short',
37
+ includeMs: (options === null || options === void 0 ? void 0 : options.includeMs) || false,
38
+ delimiter: (options === null || options === void 0 ? void 0 : options.delimiter) || ' '
39
+ };
40
+ // Convert to milliseconds
41
+ const totalMs = opts.unit === 'seconds' ? input * 1000 : input;
42
+ // Handle zero case
43
+ if (totalMs === 0) {
44
+ return '0s';
45
+ }
46
+ // Calculate time components
47
+ let remaining = Math.floor(totalMs);
48
+ const ms = remaining % 1000;
49
+ remaining = Math.floor(remaining / 1000);
50
+ const seconds = remaining % 60;
51
+ remaining = Math.floor(remaining / 60);
52
+ const minutes = remaining % 60;
53
+ const hours = Math.floor(remaining / 60);
54
+ // Build the output parts
55
+ const parts = [];
56
+ // Add non-zero units
57
+ if (hours > 0) {
58
+ parts.push(formatTimeUnit(hours, 'h', opts.format));
59
+ }
60
+ if (minutes > 0) {
61
+ parts.push(formatTimeUnit(minutes, 'm', opts.format));
62
+ }
63
+ if (seconds > 0 || (parts.length === 0 && !opts.includeMs)) {
64
+ parts.push(formatTimeUnit(seconds, 's', opts.format));
65
+ }
66
+ if (opts.includeMs && ms > 0) {
67
+ parts.push(formatTimeUnit(ms, 'ms', opts.format));
68
+ }
69
+ return parts.join(opts.delimiter);
70
+ }
71
+ /**
72
+ * Formats a single time unit according to the specified format.
73
+ * @private
74
+ */
75
+ function formatTimeUnit(value, unit, format) {
76
+ switch (format) {
77
+ case 'long':
78
+ const unitNames = {
79
+ 'h': ['hour', 'hours'],
80
+ 'm': ['minute', 'minutes'],
81
+ 's': ['second', 'seconds'],
82
+ 'ms': ['millisecond', 'milliseconds']
83
+ };
84
+ const [singular, plural] = unitNames[unit];
85
+ return `${value} ${value === 1 ? singular : plural}`;
86
+ case 'medium':
87
+ const paddedValue = unit === 'h' ? value : value.toString().padStart(2, '0');
88
+ return `${paddedValue}${unit}`;
89
+ default: // 'short'
90
+ return `${value}${unit}`;
91
+ }
92
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Converts a number of bytes into a human-readable file size string (B, KB, MB, GB, TB).
3
+ *
4
+ * Supports values from bytes up to terabytes, with automatic unit scaling and correct rounding.
5
+ *
6
+ * Examples:
7
+ * 123 → "123 B"
8
+ * 1024 → "1 KB"
9
+ * 1048576 → "1 MB"
10
+ * 1073741824 → "1 GB"
11
+ * 1572864 → "1.5 MB"
12
+ *
13
+ * @param {number} bytes - The number of bytes to convert.
14
+ * @param {number} [precision=2] - The number of decimal places to include for non-integer conversions.
15
+ * @returns {string} The formatted file size string with units.
16
+ * @throws {TypeError} If the input is not a number or precision is not a valid number.
17
+ */
18
+ export declare function formatFileSize(bytes: number, precision?: number): string;
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formatFileSize = formatFileSize;
4
+ /**
5
+ * Converts a number of bytes into a human-readable file size string (B, KB, MB, GB, TB).
6
+ *
7
+ * Supports values from bytes up to terabytes, with automatic unit scaling and correct rounding.
8
+ *
9
+ * Examples:
10
+ * 123 → "123 B"
11
+ * 1024 → "1 KB"
12
+ * 1048576 → "1 MB"
13
+ * 1073741824 → "1 GB"
14
+ * 1572864 → "1.5 MB"
15
+ *
16
+ * @param {number} bytes - The number of bytes to convert.
17
+ * @param {number} [precision=2] - The number of decimal places to include for non-integer conversions.
18
+ * @returns {string} The formatted file size string with units.
19
+ * @throws {TypeError} If the input is not a number or precision is not a valid number.
20
+ */
21
+ function formatFileSize(bytes, precision = 2) {
22
+ if (typeof bytes !== 'number' || Number.isNaN(bytes)) {
23
+ throw new TypeError('Input must be a number');
24
+ }
25
+ if (typeof precision !== 'number' || Number.isNaN(precision) || precision < 0) {
26
+ throw new TypeError('Precision must be a non-negative number');
27
+ }
28
+ if (bytes < 0) {
29
+ throw new RangeError('File size cannot be negative');
30
+ }
31
+ const units = ['B', 'KB', 'MB', 'GB', 'TB'];
32
+ if (bytes === 0)
33
+ return `0 B`;
34
+ const i = Math.floor(Math.log(bytes) / Math.log(1024));
35
+ const value = bytes / Math.pow(1024, i);
36
+ // ✅ Fix: trim trailing zeros by converting to number before string
37
+ const rounded = value % 1 === 0 ? value.toString() : parseFloat(value.toFixed(precision)).toString();
38
+ return `${rounded} ${units[i]}`;
39
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Converts a decimal number to its hexadecimal (base-16) representation.
3
+ *
4
+ * @param {number} num - The decimal number to convert.
5
+ * @param {object} [options] - Optional formatting options.
6
+ * @param {boolean} [options.prefix=false] - Whether to add "0x" before the result.
7
+ * @param {boolean} [options.lowercase=false] - Whether to return hexadecimal in lowercase.
8
+ * @returns {string} The hexadecimal representation of the number.
9
+ * @throws {TypeError} If the input is not a valid number.
10
+ */
11
+ export declare function formatToHexadecimal(num: number, options?: {
12
+ prefix?: boolean;
13
+ lowercase?: boolean;
14
+ }): string;