@scalar/helpers 0.4.1 → 0.4.3

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 (123) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/array/add-to-map-array.js +7 -8
  3. package/dist/array/is-defined.js +12 -5
  4. package/dist/array/sort-by-order.js +60 -18
  5. package/dist/consts/content-types.js +13 -14
  6. package/dist/dom/freeze-element.js +56 -42
  7. package/dist/dom/get-selector.d.ts +7 -0
  8. package/dist/dom/get-selector.d.ts.map +1 -0
  9. package/dist/dom/get-selector.js +31 -0
  10. package/dist/dom/scroll-to-id.js +33 -27
  11. package/dist/file/json2xml.js +79 -61
  12. package/dist/formatters/format-bytes.d.ts +7 -0
  13. package/dist/formatters/format-bytes.d.ts.map +1 -0
  14. package/dist/formatters/format-bytes.js +18 -0
  15. package/dist/formatters/format-milliseconds.d.ts +6 -0
  16. package/dist/formatters/format-milliseconds.d.ts.map +1 -0
  17. package/dist/formatters/format-milliseconds.js +10 -0
  18. package/dist/general/create-limiter.js +47 -31
  19. package/dist/general/debounce.js +86 -66
  20. package/dist/general/extract-config-secrets.js +29 -27
  21. package/dist/general/has-modifier.js +9 -8
  22. package/dist/general/is-mac-os.js +23 -21
  23. package/dist/http/can-method-have-body.js +4 -6
  24. package/dist/http/http-info.js +63 -61
  25. package/dist/http/http-methods.js +4 -7
  26. package/dist/http/http-status-codes.js +316 -320
  27. package/dist/http/is-http-method.js +3 -6
  28. package/dist/http/normalize-http-method.js +19 -19
  29. package/dist/json/escape-json-pointer.js +6 -5
  30. package/dist/json/parse-json-pointer-segments.js +11 -6
  31. package/dist/json/pretty-print-json.d.ts +9 -0
  32. package/dist/json/pretty-print-json.d.ts.map +1 -0
  33. package/dist/json/pretty-print-json.js +42 -0
  34. package/dist/json/unescape-json-pointer.js +7 -5
  35. package/dist/markdown/get-markdown-headings.d.ts +11 -0
  36. package/dist/markdown/get-markdown-headings.d.ts.map +1 -0
  37. package/dist/markdown/get-markdown-headings.js +99 -0
  38. package/dist/node/path.js +168 -138
  39. package/dist/object/get-value-at-path.js +17 -11
  40. package/dist/object/is-object.js +24 -10
  41. package/dist/object/local-storage.js +50 -42
  42. package/dist/object/object-entries.js +2 -5
  43. package/dist/object/object-keys.js +5 -5
  44. package/dist/object/object-replace.js +13 -12
  45. package/dist/object/omit-undefined-values.js +18 -18
  46. package/dist/object/prevent-pollution.js +27 -10
  47. package/dist/object/to-json-compatible.js +71 -62
  48. package/dist/queue/queue.js +103 -84
  49. package/dist/regex/find-variables.js +13 -8
  50. package/dist/regex/regex-helpers.js +17 -17
  51. package/dist/regex/replace-variables.js +21 -19
  52. package/dist/string/camel-to-title.js +10 -5
  53. package/dist/string/capitalize.js +5 -5
  54. package/dist/string/create-hash.js +19 -16
  55. package/dist/string/generate-hash.js +153 -127
  56. package/dist/string/iterate-title.js +13 -11
  57. package/dist/string/truncate.js +16 -9
  58. package/dist/testing/console-spies.js +19 -24
  59. package/dist/testing/measure.js +42 -19
  60. package/dist/testing/measure.test-d.js +12 -9
  61. package/dist/testing/sleep.js +5 -5
  62. package/dist/url/ensure-protocol.js +8 -10
  63. package/dist/url/extract-server-from-path.js +53 -28
  64. package/dist/url/is-local-url.js +24 -18
  65. package/dist/url/is-relative-path.js +15 -13
  66. package/dist/url/is-valid-url.js +17 -10
  67. package/dist/url/make-url-absolute.js +39 -28
  68. package/dist/url/merge-urls.js +74 -52
  69. package/dist/url/redirect-to-proxy.js +68 -39
  70. package/package.json +15 -9
  71. package/dist/array/add-to-map-array.js.map +0 -7
  72. package/dist/array/is-defined.js.map +0 -7
  73. package/dist/array/sort-by-order.js.map +0 -7
  74. package/dist/consts/content-types.js.map +0 -7
  75. package/dist/dom/freeze-element.js.map +0 -7
  76. package/dist/dom/scroll-to-id.js.map +0 -7
  77. package/dist/file/json2xml.js.map +0 -7
  78. package/dist/general/create-limiter.js.map +0 -7
  79. package/dist/general/debounce.js.map +0 -7
  80. package/dist/general/extract-config-secrets.js.map +0 -7
  81. package/dist/general/has-modifier.js.map +0 -7
  82. package/dist/general/is-mac-os.js.map +0 -7
  83. package/dist/http/can-method-have-body.js.map +0 -7
  84. package/dist/http/http-info.js.map +0 -7
  85. package/dist/http/http-methods.js.map +0 -7
  86. package/dist/http/http-status-codes.js.map +0 -7
  87. package/dist/http/is-http-method.js.map +0 -7
  88. package/dist/http/normalize-http-method.js.map +0 -7
  89. package/dist/json/escape-json-pointer.js.map +0 -7
  90. package/dist/json/parse-json-pointer-segments.js.map +0 -7
  91. package/dist/json/unescape-json-pointer.js.map +0 -7
  92. package/dist/node/path.js.map +0 -7
  93. package/dist/object/get-value-at-path.js.map +0 -7
  94. package/dist/object/is-object.js.map +0 -7
  95. package/dist/object/local-storage.js.map +0 -7
  96. package/dist/object/object-entries.js.map +0 -7
  97. package/dist/object/object-keys.js.map +0 -7
  98. package/dist/object/object-replace.js.map +0 -7
  99. package/dist/object/omit-undefined-values.js.map +0 -7
  100. package/dist/object/prevent-pollution.js.map +0 -7
  101. package/dist/object/to-json-compatible.js.map +0 -7
  102. package/dist/queue/queue.js.map +0 -7
  103. package/dist/regex/find-variables.js.map +0 -7
  104. package/dist/regex/regex-helpers.js.map +0 -7
  105. package/dist/regex/replace-variables.js.map +0 -7
  106. package/dist/string/camel-to-title.js.map +0 -7
  107. package/dist/string/capitalize.js.map +0 -7
  108. package/dist/string/create-hash.js.map +0 -7
  109. package/dist/string/generate-hash.js.map +0 -7
  110. package/dist/string/iterate-title.js.map +0 -7
  111. package/dist/string/truncate.js.map +0 -7
  112. package/dist/testing/console-spies.js.map +0 -7
  113. package/dist/testing/measure.js.map +0 -7
  114. package/dist/testing/measure.test-d.js.map +0 -7
  115. package/dist/testing/sleep.js.map +0 -7
  116. package/dist/url/ensure-protocol.js.map +0 -7
  117. package/dist/url/extract-server-from-path.js.map +0 -7
  118. package/dist/url/is-local-url.js.map +0 -7
  119. package/dist/url/is-relative-path.js.map +0 -7
  120. package/dist/url/is-valid-url.js.map +0 -7
  121. package/dist/url/make-url-absolute.js.map +0 -7
  122. package/dist/url/merge-urls.js.map +0 -7
  123. package/dist/url/redirect-to-proxy.js.map +0 -7
@@ -1,18 +1,18 @@
1
- const REGEX = {
2
- /** Checks for a valid scheme */
3
- PROTOCOL: /^(?:https?|ftp|file|mailto|tel|data|wss?)*:\/\//,
4
- /** Finds multiple slashes after the scheme to replace with a single slash */
5
- MULTIPLE_SLASHES: /(?<!:)\/{2,}/g,
6
- /** Finds all variables wrapped in {{double}} */
7
- VARIABLES: /{{((?:[^{}]|{[^{}]*})*)}}/g,
8
- /** Finds all variables wrapped in {single} */
9
- PATH: /(?:{)([^{}]+)}(?!})/g,
10
- /** Finds the name of the schema from the ref path */
11
- REF_NAME: /\/([^\/]+)$/,
12
- /** Finds template variables in multiple formats: {{var}}, {var}, or :var */
13
- TEMPLATE_VARIABLE: /{{\s*([^}\s]+?)\s*}}|{\s*([^}\s]+?)\s*}|:\b[\w.]+\b/g
1
+ /**
2
+ * Collection of regular expressions used throughout the application.
3
+ * These patterns handle URL parsing, variable detection, and reference path extraction.
4
+ */
5
+ export const REGEX = {
6
+ /** Checks for a valid scheme */
7
+ PROTOCOL: /^(?:https?|ftp|file|mailto|tel|data|wss?)*:\/\//,
8
+ /** Finds multiple slashes after the scheme to replace with a single slash */
9
+ MULTIPLE_SLASHES: /(?<!:)\/{2,}/g,
10
+ /** Finds all variables wrapped in {{double}} */
11
+ VARIABLES: /{{((?:[^{}]|{[^{}]*})*)}}/g,
12
+ /** Finds all variables wrapped in {single} */
13
+ PATH: /(?:{)([^{}]+)}(?!})/g,
14
+ /** Finds the name of the schema from the ref path */
15
+ REF_NAME: /\/([^\/]+)$/,
16
+ /** Finds template variables in multiple formats: {{var}}, {var}, or :var */
17
+ TEMPLATE_VARIABLE: /{{\s*([^}\s]+?)\s*}}|{\s*([^}\s]+?)\s*}|:\b[\w.]+\b/g,
14
18
  };
15
- export {
16
- REGEX
17
- };
18
- //# sourceMappingURL=regex-helpers.js.map
@@ -1,20 +1,22 @@
1
- import { REGEX } from "../regex/regex-helpers.js";
2
- function replaceVariables(value, variablesOrCallback) {
3
- const doubleCurlyBrackets = /{{\s*([\w.-]+)\s*}}/g;
4
- const singleCurlyBrackets = /{\s*([\w.-]+)\s*}/g;
5
- const callback = (_, match) => {
6
- if (typeof variablesOrCallback === "function") {
7
- return variablesOrCallback(match);
8
- }
9
- return variablesOrCallback[match]?.toString() || `{${match}}`;
10
- };
11
- return value.replace(doubleCurlyBrackets, callback).replace(singleCurlyBrackets, callback);
1
+ import { REGEX } from '../regex/regex-helpers.js';
2
+ /**
3
+ * This function takes a string and replaces both {single} and {{double}} curly brace variables with given values.
4
+ * Use the replacePathVariables and replaceEnvVariables functions if you only need to replace one type of variable.
5
+ */
6
+ export function replaceVariables(value, variablesOrCallback) {
7
+ // Replace all variables (example: {{ baseurl }} with an HTML tag)
8
+ const doubleCurlyBrackets = /{{\s*([\w.-]+)\s*}}/g;
9
+ const singleCurlyBrackets = /{\s*([\w.-]+)\s*}/g;
10
+ const callback = (_, match) => {
11
+ if (typeof variablesOrCallback === 'function') {
12
+ return variablesOrCallback(match);
13
+ }
14
+ return variablesOrCallback[match]?.toString() || `{${match}}`;
15
+ };
16
+ // Loop through all matches and replace the match with the variable value
17
+ return value.replace(doubleCurlyBrackets, callback).replace(singleCurlyBrackets, callback);
12
18
  }
13
- const replacePathVariables = (path, variables = {}) => path.replace(REGEX.PATH, (match, key) => variables[key] ?? match);
14
- const replaceEnvVariables = (path, variables = {}) => path.replace(REGEX.VARIABLES, (match, key) => variables[key] ?? match);
15
- export {
16
- replaceEnvVariables,
17
- replacePathVariables,
18
- replaceVariables
19
- };
20
- //# sourceMappingURL=replace-variables.js.map
19
+ /** Replace {path} variables with their values */
20
+ export const replacePathVariables = (path, variables = {}) => path.replace(REGEX.PATH, (match, key) => variables[key] ?? match);
21
+ /** Replace {{env}} variables with their values */
22
+ export const replaceEnvVariables = (path, variables = {}) => path.replace(REGEX.VARIABLES, (match, key) => variables[key] ?? match);
@@ -1,5 +1,10 @@
1
- const camelToTitleWords = (camelStr = "") => camelStr.replace(/([A-Z]{2,})/g, " $1").replace(/([A-Z])(?=[a-z])/g, " $1").replace(/^./, (str) => str.toUpperCase()).trim();
2
- export {
3
- camelToTitleWords
4
- };
5
- //# sourceMappingURL=camel-to-title.js.map
1
+ /**
2
+ * Converts a camelCase string to Title Words with spaces
3
+ *
4
+ * @param camelStr - MUST be in camelCase or this might not work
5
+ */
6
+ export const camelToTitleWords = (camelStr = '') => camelStr
7
+ .replace(/([A-Z]{2,})/g, ' $1') // Add space before consecutive capitals
8
+ .replace(/([A-Z])(?=[a-z])/g, ' $1') // Add space before single capital followed by lowercase
9
+ .replace(/^./, (str) => str.toUpperCase()) // Capitalize first letter
10
+ .trim();
@@ -1,5 +1,5 @@
1
- const capitalize = (str = "") => (str[0]?.toUpperCase() ?? "") + str.slice(1);
2
- export {
3
- capitalize
4
- };
5
- //# sourceMappingURL=capitalize.js.map
1
+ /**
2
+ * Capitalize first letter
3
+ * You should normally do this in css, only use this if you have to
4
+ */
5
+ export const capitalize = (str = '') => (str[0]?.toUpperCase() ?? '') + str.slice(1);
@@ -1,18 +1,21 @@
1
- const createHash = (input) => {
2
- let chr = 0;
3
- let hash = 0;
4
- let i = 0;
5
- if (!input?.length) {
1
+ /**
2
+ * Simple 32 bit non-secure hash from a string input
3
+ *
4
+ * @deprecated Please use generateHash from ./generate-hash.ts instead
5
+ *
6
+ * @see https://stackoverflow.com/a/7616484/1624255
7
+ */
8
+ export const createHash = (input) => {
9
+ let chr = 0;
10
+ let hash = 0;
11
+ let i = 0;
12
+ if (!input?.length) {
13
+ return hash;
14
+ }
15
+ for (i = 0; i < input.length; i++) {
16
+ chr = input.charCodeAt(i);
17
+ hash = (hash << 5) - hash + chr;
18
+ hash |= 0; // Convert to 32bit integer
19
+ }
6
20
  return hash;
7
- }
8
- for (i = 0; i < input.length; i++) {
9
- chr = input.charCodeAt(i);
10
- hash = (hash << 5) - hash + chr;
11
- hash |= 0;
12
- }
13
- return hash;
14
21
  };
15
- export {
16
- createHash
17
- };
18
- //# sourceMappingURL=create-hash.js.map
@@ -1,130 +1,156 @@
1
- const generateHash = (input) => {
2
- const seed = 0;
3
- let h1 = seed;
4
- let h2 = seed;
5
- const len = input.length;
6
- const remainder = len & 15;
7
- const bytes = len - remainder;
8
- const c1 = 2277735313;
9
- const c2 = 1291169091;
10
- const c3 = 1390208809;
11
- const c4 = 944331445;
12
- for (let i = 0; i < bytes; i += 16) {
13
- let k1 = input.charCodeAt(i) & 255 | (input.charCodeAt(i + 1) & 255) << 8 | (input.charCodeAt(i + 2) & 255) << 16 | (input.charCodeAt(i + 3) & 255) << 24;
14
- let k2 = input.charCodeAt(i + 4) & 255 | (input.charCodeAt(i + 5) & 255) << 8 | (input.charCodeAt(i + 6) & 255) << 16 | (input.charCodeAt(i + 7) & 255) << 24;
15
- let k3 = input.charCodeAt(i + 8) & 255 | (input.charCodeAt(i + 9) & 255) << 8 | (input.charCodeAt(i + 10) & 255) << 16 | (input.charCodeAt(i + 11) & 255) << 24;
16
- let k4 = input.charCodeAt(i + 12) & 255 | (input.charCodeAt(i + 13) & 255) << 8 | (input.charCodeAt(i + 14) & 255) << 16 | (input.charCodeAt(i + 15) & 255) << 24;
17
- k1 = Math.imul(k1, c1);
18
- k1 = k1 << 15 | k1 >>> 17;
19
- k1 = Math.imul(k1, c2);
20
- h1 ^= k1;
21
- h1 = h1 << 13 | h1 >>> 19;
22
- h1 = Math.imul(h1, 5) + 3864292196;
23
- k2 = Math.imul(k2, c2);
24
- k2 = k2 << 16 | k2 >>> 16;
25
- k2 = Math.imul(k2, c3);
26
- h2 ^= k2;
27
- h2 = h2 << 17 | h2 >>> 15;
28
- h2 = Math.imul(h2, 5) + 461845907;
29
- k3 = Math.imul(k3, c3);
30
- k3 = k3 << 17 | k3 >>> 15;
31
- k3 = Math.imul(k3, c4);
32
- h1 ^= k3;
33
- h1 = h1 << 15 | h1 >>> 17;
34
- h1 = Math.imul(h1, 5) + 1390208809;
35
- k4 = Math.imul(k4, c4);
36
- k4 = k4 << 18 | k4 >>> 14;
37
- k4 = Math.imul(k4, c1);
38
- h2 ^= k4;
39
- h2 = h2 << 13 | h2 >>> 19;
40
- h2 = Math.imul(h2, 5) + 944331445;
41
- }
42
- if (remainder > 0) {
43
- let k1 = 0;
44
- let k2 = 0;
45
- let k3 = 0;
46
- let k4 = 0;
47
- if (remainder >= 15) {
48
- k4 ^= (input.charCodeAt(bytes + 14) & 255) << 16;
1
+ /**
2
+ * MurmurHash3 implementation
3
+ *
4
+ * Generate a hash from a string using the MurmurHash3 algorithm
5
+ * Provides 64-bit hash output with excellent speed and distribution
6
+ *
7
+ * We had to move away from xxhash-wasm since it was causing issues with content security policy (CSP) violations.
8
+ *
9
+ * We cannot use crypto.subtle because it is only available in secure contexts (HTTPS) or on localhost.
10
+ *
11
+ * @param input - The string to hash
12
+ * @returns The 64-bit hash of the input string as a 16-character hex string
13
+ */
14
+ export const generateHash = (input) => {
15
+ const seed = 0;
16
+ // Working with 64-bit values using pairs of 32-bit integers
17
+ let h1 = seed;
18
+ let h2 = seed;
19
+ const len = input.length;
20
+ const remainder = len & 15; // len % 16
21
+ const bytes = len - remainder;
22
+ const c1 = 0x87c37b91;
23
+ const c2 = 0x4cf5ad43;
24
+ const c3 = 0x52dce729;
25
+ const c4 = 0x38495ab5;
26
+ // Process 16-byte chunks
27
+ for (let i = 0; i < bytes; i += 16) {
28
+ let k1 = (input.charCodeAt(i) & 0xff) |
29
+ ((input.charCodeAt(i + 1) & 0xff) << 8) |
30
+ ((input.charCodeAt(i + 2) & 0xff) << 16) |
31
+ ((input.charCodeAt(i + 3) & 0xff) << 24);
32
+ let k2 = (input.charCodeAt(i + 4) & 0xff) |
33
+ ((input.charCodeAt(i + 5) & 0xff) << 8) |
34
+ ((input.charCodeAt(i + 6) & 0xff) << 16) |
35
+ ((input.charCodeAt(i + 7) & 0xff) << 24);
36
+ let k3 = (input.charCodeAt(i + 8) & 0xff) |
37
+ ((input.charCodeAt(i + 9) & 0xff) << 8) |
38
+ ((input.charCodeAt(i + 10) & 0xff) << 16) |
39
+ ((input.charCodeAt(i + 11) & 0xff) << 24);
40
+ let k4 = (input.charCodeAt(i + 12) & 0xff) |
41
+ ((input.charCodeAt(i + 13) & 0xff) << 8) |
42
+ ((input.charCodeAt(i + 14) & 0xff) << 16) |
43
+ ((input.charCodeAt(i + 15) & 0xff) << 24);
44
+ k1 = Math.imul(k1, c1);
45
+ k1 = (k1 << 15) | (k1 >>> 17);
46
+ k1 = Math.imul(k1, c2);
47
+ h1 ^= k1;
48
+ h1 = (h1 << 13) | (h1 >>> 19);
49
+ h1 = Math.imul(h1, 5) + 0xe6546b64;
50
+ k2 = Math.imul(k2, c2);
51
+ k2 = (k2 << 16) | (k2 >>> 16);
52
+ k2 = Math.imul(k2, c3);
53
+ h2 ^= k2;
54
+ h2 = (h2 << 17) | (h2 >>> 15);
55
+ h2 = Math.imul(h2, 5) + 0x1b873593;
56
+ k3 = Math.imul(k3, c3);
57
+ k3 = (k3 << 17) | (k3 >>> 15);
58
+ k3 = Math.imul(k3, c4);
59
+ h1 ^= k3;
60
+ h1 = (h1 << 15) | (h1 >>> 17);
61
+ h1 = Math.imul(h1, 5) + 0x52dce729;
62
+ k4 = Math.imul(k4, c4);
63
+ k4 = (k4 << 18) | (k4 >>> 14);
64
+ k4 = Math.imul(k4, c1);
65
+ h2 ^= k4;
66
+ h2 = (h2 << 13) | (h2 >>> 19);
67
+ h2 = Math.imul(h2, 5) + 0x38495ab5;
49
68
  }
50
- if (remainder >= 14) {
51
- k4 ^= (input.charCodeAt(bytes + 13) & 255) << 8;
69
+ // Process remaining bytes
70
+ if (remainder > 0) {
71
+ let k1 = 0;
72
+ let k2 = 0;
73
+ let k3 = 0;
74
+ let k4 = 0;
75
+ if (remainder >= 15) {
76
+ k4 ^= (input.charCodeAt(bytes + 14) & 0xff) << 16;
77
+ }
78
+ if (remainder >= 14) {
79
+ k4 ^= (input.charCodeAt(bytes + 13) & 0xff) << 8;
80
+ }
81
+ if (remainder >= 13) {
82
+ k4 ^= input.charCodeAt(bytes + 12) & 0xff;
83
+ k4 = Math.imul(k4, c4);
84
+ k4 = (k4 << 18) | (k4 >>> 14);
85
+ k4 = Math.imul(k4, c1);
86
+ h2 ^= k4;
87
+ }
88
+ if (remainder >= 12) {
89
+ k3 ^= (input.charCodeAt(bytes + 11) & 0xff) << 24;
90
+ }
91
+ if (remainder >= 11) {
92
+ k3 ^= (input.charCodeAt(bytes + 10) & 0xff) << 16;
93
+ }
94
+ if (remainder >= 10) {
95
+ k3 ^= (input.charCodeAt(bytes + 9) & 0xff) << 8;
96
+ }
97
+ if (remainder >= 9) {
98
+ k3 ^= input.charCodeAt(bytes + 8) & 0xff;
99
+ k3 = Math.imul(k3, c3);
100
+ k3 = (k3 << 17) | (k3 >>> 15);
101
+ k3 = Math.imul(k3, c4);
102
+ h1 ^= k3;
103
+ }
104
+ if (remainder >= 8) {
105
+ k2 ^= (input.charCodeAt(bytes + 7) & 0xff) << 24;
106
+ }
107
+ if (remainder >= 7) {
108
+ k2 ^= (input.charCodeAt(bytes + 6) & 0xff) << 16;
109
+ }
110
+ if (remainder >= 6) {
111
+ k2 ^= (input.charCodeAt(bytes + 5) & 0xff) << 8;
112
+ }
113
+ if (remainder >= 5) {
114
+ k2 ^= input.charCodeAt(bytes + 4) & 0xff;
115
+ k2 = Math.imul(k2, c2);
116
+ k2 = (k2 << 16) | (k2 >>> 16);
117
+ k2 = Math.imul(k2, c3);
118
+ h2 ^= k2;
119
+ }
120
+ if (remainder >= 4) {
121
+ k1 ^= (input.charCodeAt(bytes + 3) & 0xff) << 24;
122
+ }
123
+ if (remainder >= 3) {
124
+ k1 ^= (input.charCodeAt(bytes + 2) & 0xff) << 16;
125
+ }
126
+ if (remainder >= 2) {
127
+ k1 ^= (input.charCodeAt(bytes + 1) & 0xff) << 8;
128
+ }
129
+ if (remainder >= 1) {
130
+ k1 ^= input.charCodeAt(bytes) & 0xff;
131
+ k1 = Math.imul(k1, c1);
132
+ k1 = (k1 << 15) | (k1 >>> 17);
133
+ k1 = Math.imul(k1, c2);
134
+ h1 ^= k1;
135
+ }
52
136
  }
53
- if (remainder >= 13) {
54
- k4 ^= input.charCodeAt(bytes + 12) & 255;
55
- k4 = Math.imul(k4, c4);
56
- k4 = k4 << 18 | k4 >>> 14;
57
- k4 = Math.imul(k4, c1);
58
- h2 ^= k4;
59
- }
60
- if (remainder >= 12) {
61
- k3 ^= (input.charCodeAt(bytes + 11) & 255) << 24;
62
- }
63
- if (remainder >= 11) {
64
- k3 ^= (input.charCodeAt(bytes + 10) & 255) << 16;
65
- }
66
- if (remainder >= 10) {
67
- k3 ^= (input.charCodeAt(bytes + 9) & 255) << 8;
68
- }
69
- if (remainder >= 9) {
70
- k3 ^= input.charCodeAt(bytes + 8) & 255;
71
- k3 = Math.imul(k3, c3);
72
- k3 = k3 << 17 | k3 >>> 15;
73
- k3 = Math.imul(k3, c4);
74
- h1 ^= k3;
75
- }
76
- if (remainder >= 8) {
77
- k2 ^= (input.charCodeAt(bytes + 7) & 255) << 24;
78
- }
79
- if (remainder >= 7) {
80
- k2 ^= (input.charCodeAt(bytes + 6) & 255) << 16;
81
- }
82
- if (remainder >= 6) {
83
- k2 ^= (input.charCodeAt(bytes + 5) & 255) << 8;
84
- }
85
- if (remainder >= 5) {
86
- k2 ^= input.charCodeAt(bytes + 4) & 255;
87
- k2 = Math.imul(k2, c2);
88
- k2 = k2 << 16 | k2 >>> 16;
89
- k2 = Math.imul(k2, c3);
90
- h2 ^= k2;
91
- }
92
- if (remainder >= 4) {
93
- k1 ^= (input.charCodeAt(bytes + 3) & 255) << 24;
94
- }
95
- if (remainder >= 3) {
96
- k1 ^= (input.charCodeAt(bytes + 2) & 255) << 16;
97
- }
98
- if (remainder >= 2) {
99
- k1 ^= (input.charCodeAt(bytes + 1) & 255) << 8;
100
- }
101
- if (remainder >= 1) {
102
- k1 ^= input.charCodeAt(bytes) & 255;
103
- k1 = Math.imul(k1, c1);
104
- k1 = k1 << 15 | k1 >>> 17;
105
- k1 = Math.imul(k1, c2);
106
- h1 ^= k1;
107
- }
108
- }
109
- h1 ^= len;
110
- h2 ^= len;
111
- h1 += h2;
112
- h2 += h1;
113
- h1 ^= h1 >>> 16;
114
- h1 = Math.imul(h1, 2246822507);
115
- h1 ^= h1 >>> 13;
116
- h1 = Math.imul(h1, 3266489909);
117
- h1 ^= h1 >>> 16;
118
- h2 ^= h2 >>> 16;
119
- h2 = Math.imul(h2, 2246822507);
120
- h2 ^= h2 >>> 13;
121
- h2 = Math.imul(h2, 3266489909);
122
- h2 ^= h2 >>> 16;
123
- h1 += h2;
124
- h2 += h1;
125
- return (h1 >>> 0).toString(16).padStart(8, "0") + (h2 >>> 0).toString(16).padStart(8, "0");
126
- };
127
- export {
128
- generateHash
137
+ // Finalization
138
+ h1 ^= len;
139
+ h2 ^= len;
140
+ h1 += h2;
141
+ h2 += h1;
142
+ h1 ^= h1 >>> 16;
143
+ h1 = Math.imul(h1, 0x85ebca6b);
144
+ h1 ^= h1 >>> 13;
145
+ h1 = Math.imul(h1, 0xc2b2ae35);
146
+ h1 ^= h1 >>> 16;
147
+ h2 ^= h2 >>> 16;
148
+ h2 = Math.imul(h2, 0x85ebca6b);
149
+ h2 ^= h2 >>> 13;
150
+ h2 = Math.imul(h2, 0xc2b2ae35);
151
+ h2 ^= h2 >>> 16;
152
+ h1 += h2;
153
+ h2 += h1;
154
+ // Return 64-bit hash as hex string (two 32-bit values concatenated)
155
+ return (h1 >>> 0).toString(16).padStart(8, '0') + (h2 >>> 0).toString(16).padStart(8, '0');
129
156
  };
130
- //# sourceMappingURL=generate-hash.js.map
@@ -1,12 +1,14 @@
1
- const iterateTitle = (title, checkDuplicates, separator = " #") => {
2
- if (!checkDuplicates(title)) {
3
- return title;
4
- }
5
- const split = title.split(separator);
6
- const newTitle = split.length > 1 ? `${split.slice(0, -1).join()}${separator}${Number(split.at(-1)) + 1}` : `${split.join()}${separator}2`;
7
- return iterateTitle(newTitle, checkDuplicates, separator);
1
+ /**
2
+ * Check for duplicate titles, and iterate title
3
+ */
4
+ export const iterateTitle = (title, checkDuplicates, separator = ' #') => {
5
+ // If the title is not a duplicate return
6
+ if (!checkDuplicates(title)) {
7
+ return title;
8
+ }
9
+ const split = title.split(separator);
10
+ const newTitle = split.length > 1
11
+ ? `${split.slice(0, -1).join()}${separator}${Number(split.at(-1)) + 1}`
12
+ : `${split.join()}${separator}2`;
13
+ return iterateTitle(newTitle, checkDuplicates, separator);
8
14
  };
9
- export {
10
- iterateTitle
11
- };
12
- //# sourceMappingURL=iterate-title.js.map
@@ -1,10 +1,17 @@
1
- const truncate = (str, maxLength = 18) => {
2
- if (str.length <= maxLength) {
3
- return str;
4
- }
5
- return str.slice(0, maxLength) + "\u2026";
1
+ /**
2
+ * Truncates a string to a specified length and adds an ellipsis if it's longer in JS
3
+ *
4
+ * @param str - The string to truncate
5
+ * @param maxLength - The maximum length before truncation (default: 18)
6
+ * @returns The truncated string with ellipsis if needed
7
+ *
8
+ * @example
9
+ * truncate('Very long name that needs truncation') // 'Very long name th…'
10
+ * truncate('Short') // 'Short'
11
+ */
12
+ export const truncate = (str, maxLength = 18) => {
13
+ if (str.length <= maxLength) {
14
+ return str;
15
+ }
16
+ return str.slice(0, maxLength) + '…';
6
17
  };
7
- export {
8
- truncate
9
- };
10
- //# sourceMappingURL=truncate.js.map
@@ -1,25 +1,20 @@
1
- import { vi } from "vitest";
2
- const consoleWarnSpy = vi.spyOn(console, "warn");
3
- let isConsoleWarnEnabled = false;
4
- const consoleErrorSpy = vi.spyOn(console, "error");
5
- let isConsoleErrorEnabled = false;
6
- const resetConsoleSpies = () => {
7
- consoleWarnSpy.mockClear();
8
- consoleErrorSpy.mockClear();
1
+ import { vi } from 'vitest';
2
+ /** Spy on console.warn */
3
+ export const consoleWarnSpy = vi.spyOn(console, 'warn');
4
+ export let isConsoleWarnEnabled = false;
5
+ /** Spy on console.error */
6
+ export const consoleErrorSpy = vi.spyOn(console, 'error');
7
+ export let isConsoleErrorEnabled = false;
8
+ /** Reset the spies */
9
+ export const resetConsoleSpies = () => {
10
+ consoleWarnSpy.mockClear();
11
+ consoleErrorSpy.mockClear();
9
12
  };
10
- const enableConsoleWarn = () => isConsoleWarnEnabled = true;
11
- const disableConsoleWarn = () => isConsoleWarnEnabled = false;
12
- const enableConsoleError = () => isConsoleErrorEnabled = true;
13
- const disableConsoleError = () => isConsoleErrorEnabled = false;
14
- export {
15
- consoleErrorSpy,
16
- consoleWarnSpy,
17
- disableConsoleError,
18
- disableConsoleWarn,
19
- enableConsoleError,
20
- enableConsoleWarn,
21
- isConsoleErrorEnabled,
22
- isConsoleWarnEnabled,
23
- resetConsoleSpies
24
- };
25
- //# sourceMappingURL=console-spies.js.map
13
+ /** Helper to re-enable console warn checks */
14
+ export const enableConsoleWarn = () => (isConsoleWarnEnabled = true);
15
+ /** Helper to disable console warn checks */
16
+ export const disableConsoleWarn = () => (isConsoleWarnEnabled = false);
17
+ /** Helper to enable console error checks */
18
+ export const enableConsoleError = () => (isConsoleErrorEnabled = true);
19
+ /** Helper to disable console error checks */
20
+ export const disableConsoleError = () => (isConsoleErrorEnabled = false);
@@ -1,21 +1,44 @@
1
- const measureSync = (name, fn) => {
2
- const start = performance.now();
3
- const result = fn();
4
- const end = performance.now();
5
- const duration = Math.round(end - start);
6
- console.info(`${name}: ${duration} ms`);
7
- return result;
1
+ /**
2
+ * Measures the execution time of a function and logs it.
3
+ *
4
+ * Works only with sync functions and returns the result of the measured function.
5
+ *
6
+ * @example
7
+ *
8
+ * ```ts
9
+ * // Sync function
10
+ * const result = measureSync('computation', () => {
11
+ * return heavyComputation()
12
+ * })
13
+ * ```
14
+ */
15
+ export const measureSync = (name, fn) => {
16
+ const start = performance.now();
17
+ const result = fn();
18
+ const end = performance.now();
19
+ const duration = Math.round(end - start);
20
+ console.info(`${name}: ${duration} ms`);
21
+ return result;
8
22
  };
9
- const measureAsync = async (name, fn) => {
10
- const start = performance.now();
11
- const result = await fn();
12
- const end = performance.now();
13
- const duration = Math.round(end - start);
14
- console.info(`${name}: ${duration} ms`);
15
- return result;
23
+ /**
24
+ * Measures the execution time of an async function and logs it.
25
+ *
26
+ * Works only with async functions and returns the result of the measured function.
27
+ *
28
+ * @example
29
+ *
30
+ * ```ts
31
+ * // Async function
32
+ * const result = await measure('api-call', async () => {
33
+ * return await fetchData()
34
+ * })
35
+ * ````
36
+ */
37
+ export const measureAsync = async (name, fn) => {
38
+ const start = performance.now();
39
+ const result = await fn();
40
+ const end = performance.now();
41
+ const duration = Math.round(end - start);
42
+ console.info(`${name}: ${duration} ms`);
43
+ return result;
16
44
  };
17
- export {
18
- measureAsync,
19
- measureSync
20
- };
21
- //# sourceMappingURL=measure.js.map
@@ -1,12 +1,15 @@
1
- import { describe, vi } from "vitest";
2
- import { measureAsync, measureSync } from "./measure.js";
1
+ import { describe, vi } from 'vitest';
2
+ import { measureAsync, measureSync } from './measure.js';
3
3
  const asyncFunction = vi.fn();
4
- describe("measureAsync types", async () => {
5
- await measureAsync("test", asyncFunction);
6
- await measureAsync("test", () => 1);
4
+ describe('measureAsync types', async () => {
5
+ // works with async methods
6
+ await measureAsync('test', asyncFunction);
7
+ // @ts-expect-error should error because `fn` doesn't return a Promise
8
+ await measureAsync('test', () => 1);
7
9
  });
8
- describe("measureSync types", () => {
9
- measureSync("test", () => 1);
10
- measureSync("test", asyncFunction);
10
+ describe('measureSync types', () => {
11
+ // works with sync methods
12
+ measureSync('test', () => 1);
13
+ // @ts-expect-error should error because `fn` doesn't return a Promise
14
+ measureSync('test', asyncFunction);
11
15
  });
12
- //# sourceMappingURL=measure.test-d.js.map
@@ -1,5 +1,5 @@
1
- const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
2
- export {
3
- sleep
4
- };
5
- //# sourceMappingURL=sleep.js.map
1
+ /**
2
+ * Little helper for sleeping for x milliseconds
3
+ * an async await friendly setTimeout
4
+ */
5
+ export const sleep = (ms) => new Promise((r) => setTimeout(r, ms));