@oazmi/superbuild 0.1.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 (118) hide show
  1. package/esm/_dnt.shims.d.ts +2 -0
  2. package/esm/_dnt.shims.d.ts.map +1 -0
  3. package/esm/_dnt.shims.js +57 -0
  4. package/esm/deps/jsr.io/@oazmi/esbuild-types/0.28.0/src/mod.d.ts +598 -0
  5. package/esm/deps/jsr.io/@oazmi/esbuild-types/0.28.0/src/mod.d.ts.map +1 -0
  6. package/esm/deps/jsr.io/@oazmi/esbuild-types/0.28.0/src/mod.js +1 -0
  7. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/alias.d.ts +617 -0
  8. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/alias.d.ts.map +1 -0
  9. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/alias.js +671 -0
  10. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/array1d.d.ts +487 -0
  11. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/array1d.d.ts.map +1 -0
  12. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/array1d.js +536 -0
  13. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/array2d.d.ts +266 -0
  14. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/array2d.d.ts.map +1 -0
  15. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/array2d.js +318 -0
  16. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/binder.d.ts +368 -0
  17. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/binder.d.ts.map +1 -0
  18. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/binder.js +380 -0
  19. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/crossenv.d.ts +711 -0
  20. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/crossenv.d.ts.map +1 -0
  21. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/crossenv.js +1173 -0
  22. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/cryptoman.d.ts +171 -0
  23. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/cryptoman.d.ts.map +1 -0
  24. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/cryptoman.js +308 -0
  25. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/deps.d.ts +10 -0
  26. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/deps.d.ts.map +1 -0
  27. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/deps.js +10 -0
  28. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/eightpack.d.ts +168 -0
  29. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/eightpack.d.ts.map +1 -0
  30. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/eightpack.js +236 -0
  31. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/eightpack_varint.d.ts +90 -0
  32. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/eightpack_varint.d.ts.map +1 -0
  33. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/eightpack_varint.js +237 -0
  34. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/numericarray.d.ts +213 -0
  35. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/numericarray.d.ts.map +1 -0
  36. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/numericarray.js +363 -0
  37. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/numericmethods.d.ts +233 -0
  38. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/numericmethods.d.ts.map +1 -0
  39. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/numericmethods.js +256 -0
  40. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/pathman.d.ts +1436 -0
  41. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/pathman.d.ts.map +1 -0
  42. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/pathman.js +1730 -0
  43. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/promiseman.d.ts +647 -0
  44. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/promiseman.d.ts.map +1 -0
  45. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/promiseman.js +762 -0
  46. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/stringman.d.ts +538 -0
  47. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/stringman.d.ts.map +1 -0
  48. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/stringman.js +626 -0
  49. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/struct.d.ts +734 -0
  50. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/struct.d.ts.map +1 -0
  51. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/struct.js +764 -0
  52. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/typedbuffer.d.ts +137 -0
  53. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/typedbuffer.d.ts.map +1 -0
  54. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/typedbuffer.js +234 -0
  55. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/typedefs.d.ts +391 -0
  56. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/typedefs.d.ts.map +1 -0
  57. package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/typedefs.js +8 -0
  58. package/esm/deps.d.ts +56 -0
  59. package/esm/deps.d.ts.map +1 -0
  60. package/esm/deps.js +37 -0
  61. package/esm/esbuild/metafile.d.ts +90 -0
  62. package/esm/esbuild/metafile.d.ts.map +1 -0
  63. package/esm/esbuild/metafile.js +275 -0
  64. package/esm/esbuild/native.d.ts +95 -0
  65. package/esm/esbuild/native.d.ts.map +1 -0
  66. package/esm/esbuild/native.js +127 -0
  67. package/esm/esbuild/outputfile.d.ts +86 -0
  68. package/esm/esbuild/outputfile.d.ts.map +1 -0
  69. package/esm/esbuild/outputfile.js +221 -0
  70. package/esm/esbuild/strongtypes.d.ts +90 -0
  71. package/esm/esbuild/strongtypes.d.ts.map +1 -0
  72. package/esm/esbuild/strongtypes.js +8 -0
  73. package/esm/esbuild/typedefs.d.ts +121 -0
  74. package/esm/esbuild/typedefs.d.ts.map +1 -0
  75. package/esm/esbuild/typedefs.js +55 -0
  76. package/esm/esbuild/weaktypes.d.ts +46 -0
  77. package/esm/esbuild/weaktypes.d.ts.map +1 -0
  78. package/esm/esbuild/weaktypes.js +8 -0
  79. package/esm/funcdefs.d.ts +89 -0
  80. package/esm/funcdefs.d.ts.map +1 -0
  81. package/esm/funcdefs.js +145 -0
  82. package/esm/mod.d.ts +4 -0
  83. package/esm/mod.d.ts.map +1 -0
  84. package/esm/mod.js +2 -0
  85. package/esm/package.json +3 -0
  86. package/esm/plugins/emissions_driver.d.ts +33 -0
  87. package/esm/plugins/emissions_driver.d.ts.map +1 -0
  88. package/esm/plugins/emissions_driver.js +260 -0
  89. package/esm/plugins/long_build.d.ts +138 -0
  90. package/esm/plugins/long_build.d.ts.map +1 -0
  91. package/esm/plugins/long_build.js +288 -0
  92. package/esm/plugins/native_replica.d.ts +48 -0
  93. package/esm/plugins/native_replica.d.ts.map +1 -0
  94. package/esm/plugins/native_replica.js +122 -0
  95. package/esm/super/build.d.ts +53 -0
  96. package/esm/super/build.d.ts.map +1 -0
  97. package/esm/super/build.js +39 -0
  98. package/esm/super/build_context.d.ts +83 -0
  99. package/esm/super/build_context.d.ts.map +1 -0
  100. package/esm/super/build_context.js +124 -0
  101. package/esm/super/mod.d.ts +12 -0
  102. package/esm/super/mod.d.ts.map +1 -0
  103. package/esm/super/mod.js +9 -0
  104. package/esm/super/plugin.d.ts +23 -0
  105. package/esm/super/plugin.d.ts.map +1 -0
  106. package/esm/super/plugin.js +31 -0
  107. package/esm/super/plugin_build.d.ts +38 -0
  108. package/esm/super/plugin_build.d.ts.map +1 -0
  109. package/esm/super/plugin_build.js +198 -0
  110. package/esm/super/typedefs.d.ts +323 -0
  111. package/esm/super/typedefs.d.ts.map +1 -0
  112. package/esm/super/typedefs.js +10 -0
  113. package/esm/typedefs.d.ts +21 -0
  114. package/esm/typedefs.d.ts.map +1 -0
  115. package/esm/typedefs.js +5 -0
  116. package/license.md +37 -0
  117. package/package.json +88 -0
  118. package/readme.md +181 -0
@@ -0,0 +1,626 @@
1
+ /** utility functions for manipulating, generating, or parsing `string`s.
2
+ *
3
+ * @module
4
+ */
5
+ import { array_from, math_min, number_parseInt, string_toLowerCase, string_toUpperCase } from "./alias.js";
6
+ import { bind_array_pop, bind_array_push, bind_string_charCodeAt } from "./binder.js";
7
+ import { sliceContinuous } from "./typedbuffer.js";
8
+ const default_HexStringReprConfig = {
9
+ sep: ", ",
10
+ prefix: "0x",
11
+ postfix: "",
12
+ trailingSep: false,
13
+ bra: "[",
14
+ ket: "]",
15
+ toUpperCase: true,
16
+ radix: 16,
17
+ };
18
+ /** convert an array of integer numbers to hex-string, for the sake of easing representation, or for visual purposes.
19
+ *
20
+ * to customize the appearance of the hex-string, or to use a different radix, use the {@link HexStringReprConfig} interface to change the default `options`.
21
+ *
22
+ * you must make sure that every element of your array `arr` is non-negative, in addition to being less than `options.radix ** 2`.
23
+ * since the default `options.radix === 16`, each of your number must be smaller than `256` on the default config.
24
+ *
25
+ * to invert the operation of this function (i.e. parse an array of integers from a string), use the {@link hexStringToArray} function with the same config `options`.
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * import { assertEquals as assertEq } from "jsr:@std/assert"
30
+ *
31
+ * const
32
+ * my_binary_code = [1, 2, 3, 125, 126, 127, 192, 225, 255],
33
+ * my_custom_config: Partial<HexStringReprConfig> = {
34
+ * sep: ",",
35
+ * trailingSep: true,
36
+ * bra: "<",
37
+ * ket: ">",
38
+ * }
39
+ *
40
+ * const my_binary_code_repr = hexStringOfArray(my_binary_code, my_custom_config)
41
+ * assertEq(my_binary_code_repr, "<0x01,0x02,0x03,0x7D,0x7E,0x7F,0xC0,0xE1,0xFF,>")
42
+ *
43
+ * const my_custom_config2 = { ...my_custom_config, sep: "", trailingSep: false, prefix: "" }
44
+ * const my_binary_code_repr2 = hexStringOfArray(my_binary_code, my_custom_config2)
45
+ * assertEq(my_binary_code_repr2, "<0102037D7E7FC0E1FF>")
46
+ * ```
47
+ */
48
+ export const hexStringOfArray = (arr, options) => {
49
+ const { sep, prefix, postfix, trailingSep, bra, ket, toUpperCase, radix, } = { ...default_HexStringReprConfig, ...options }, num_arr = arr.buffer ? array_from(arr) : arr, str = num_arr.map(v => {
50
+ let s = (v | 0).toString(radix);
51
+ s = s.length === 2 ? s : "0" + s;
52
+ return toUpperCase ? string_toUpperCase(s) : s;
53
+ }).reduce((str, s) => str + prefix + s + postfix + sep, "");
54
+ return bra + str.slice(0, (trailingSep || !sep) ? undefined : -sep.length) + ket;
55
+ };
56
+ /** convert hex-string back to an array of integers,
57
+ * provided that you know the exact {@link HexStringReprConfig} config of your particular hex-string.
58
+ *
59
+ * this function performs the inverse operation of {@link hexStringOfArray}, given that you use the same `options`.
60
+ *
61
+ * @example
62
+ * ```ts
63
+ * import { assertEquals as assertEq } from "jsr:@std/assert"
64
+ *
65
+ * const
66
+ * my_binary_code_repr = "<0x01,0x02,0x03,0x7D,0x7E,0x7F,0xC0,0xE1,0xFF,>",
67
+ * my_custom_config: Partial<HexStringReprConfig> = {
68
+ * sep: ",",
69
+ * trailingSep: true,
70
+ * bra: "<",
71
+ * ket: ">",
72
+ * }
73
+ *
74
+ * const my_binary_code: number[] = hexStringToArray(my_binary_code_repr, my_custom_config)
75
+ *
76
+ * assertEq(my_binary_code, [1, 2, 3, 125, 126, 127, 192, 225, 255])
77
+ * ```
78
+ */
79
+ export const hexStringToArray = (hex_str, options) => {
80
+ const { sep, prefix, postfix, bra, ket, radix, } = { ...default_HexStringReprConfig, ...options }, [sep_len, prefix_len, postfix_len, bra_len, ket_len] = [sep, prefix, postfix, bra, ket].map(s => s.length), hex_str2 = hex_str.slice(bra_len, ket_len > 0 ? -ket_len : undefined), // there are no brackets remaining
81
+ elem_len = prefix_len + 2 + postfix_len + sep_len, int_arr = [];
82
+ for (let i = prefix_len; i < hex_str2.length; i += elem_len) {
83
+ int_arr.push(number_parseInt(hex_str2[i] + hex_str2[i + 1], // these are the two characters representing the current number in hex-string format
84
+ radix));
85
+ }
86
+ return int_arr;
87
+ };
88
+ /** a shorthand function for either getting the upper or lower case of a string `str`, based on the numeric `option`.
89
+ *
90
+ * options:
91
+ * - `option > 0` => input string is turned to uppercase
92
+ * - `option < 0` => input string is turned to lowercase
93
+ * - `option = 0` => input string is unmodified
94
+ */
95
+ export const toUpperOrLowerCase = (str, option) => {
96
+ return option > 0
97
+ ? string_toUpperCase(str)
98
+ : option < 0
99
+ ? string_toLowerCase(str)
100
+ : str;
101
+ };
102
+ /** finds the index of next uppercase character, starting from index `start` and optionally ending at exclusive-index `end`.
103
+ * if an uppercase character is not found, then `undefined` is returned.
104
+ */
105
+ export const findNextUpperCase = (str, start = 0, end = undefined) => {
106
+ end = (end < str.length ? end : str.length) - 1;
107
+ const str_charCodeAt = bind_string_charCodeAt(str);
108
+ let c;
109
+ while (c = str_charCodeAt(start++)) {
110
+ if (c > 64 && c < 91) {
111
+ return start - 1;
112
+ }
113
+ }
114
+ return undefined;
115
+ };
116
+ /** finds the index of next lowercase character, starting from index `start` and optionally ending at exclusive-index `end`.
117
+ * if a lowercase character is not found, then `undefined` is returned.
118
+ */
119
+ export const findNextLowerCase = (str, start = 0, end = undefined) => {
120
+ end = (end < str.length ? end : str.length) - 1;
121
+ const str_charCodeAt = bind_string_charCodeAt(str);
122
+ let c;
123
+ while (c = str_charCodeAt(start++)) {
124
+ if (c > 96 && c < 123) {
125
+ return start - 1;
126
+ }
127
+ }
128
+ return undefined;
129
+ };
130
+ /** find either the next upper or next lower case character index in string `str`, based on the numeric `option`,
131
+ * starting from index `start` and optionally ending at exclusive-index `end`.
132
+ * if your selected uppercase/lowercase option is not found, or if your `option === 0`, then `undefined` is returned.
133
+ *
134
+ * this function is just a composition of the functions {@link findNextUpperCase} and {@link findNextLowerCase}.
135
+ */
136
+ export const findNextUpperOrLowerCase = (str, option, start = 0, end = undefined) => {
137
+ if (option > 0) {
138
+ return findNextUpperCase(str, start, end);
139
+ }
140
+ else if (option < 0) {
141
+ return findNextLowerCase(str, start, end);
142
+ }
143
+ else {
144
+ return undefined;
145
+ }
146
+ };
147
+ /** convert an array of `words` to a single token, based on the configuration provided in `casetype`.
148
+ *
149
+ * to reverse the operation of this function, use the {@link tokenToWords} function with the same `casetype` config that you use here.
150
+ *
151
+ * @example
152
+ * ```ts
153
+ * import { assertEquals as eq } from "jsr:@std/assert"
154
+ *
155
+ * const words = ["convert", "windows", "path", "to", "unix"]
156
+ *
157
+ * const
158
+ * snakeCase: NamingCaseTuple = [-1, -1, -1, "_"],
159
+ * kebabCase: NamingCaseTuple = [-1, -1, -1, "-"],
160
+ * camelCase: NamingCaseTuple = [-1, 1, -1, ""],
161
+ * pascalCase: NamingCaseTuple = [1, 1, -1, ""],
162
+ * screamingSnakeCase: NamingCaseTuple = [1, 1, 1, "_"],
163
+ * screamingKebabCase: NamingCaseTuple = [1, 1, 1, "-"]
164
+ *
165
+ * eq(wordsToToken(snakeCase, words), "convert_windows_path_to_unix")
166
+ * eq(wordsToToken(kebabCase, words), "convert-windows-path-to-unix")
167
+ * eq(wordsToToken(camelCase, words), "convertWindowsPathToUnix")
168
+ * eq(wordsToToken(pascalCase, words), "ConvertWindowsPathToUnix")
169
+ * eq(wordsToToken(screamingSnakeCase, words), "CONVERT_WINDOWS_PATH_TO_UNIX")
170
+ * eq(wordsToToken(screamingKebabCase, words), "CONVERT-WINDOWS-PATH-TO-UNIX")
171
+ * ```
172
+ */
173
+ export const wordsToToken = (casetype, words) => {
174
+ const [first_letter_upper, word_first_letter_upper, rest_word_letters_upper, delimiter = "", prefix = "", suffix = ""] = casetype, last_i = words.length - 1, token = words.map((w, i) => {
175
+ const w_0 = toUpperOrLowerCase(w[0], i > 0 ? word_first_letter_upper : first_letter_upper), w_rest = toUpperOrLowerCase(w.slice(1), rest_word_letters_upper), sep = i < last_i ? delimiter : "";
176
+ return w_0 + w_rest + sep;
177
+ }).reduce((str, word) => str + word, prefix) + suffix;
178
+ return token;
179
+ };
180
+ /** breakdown a single `token` into its constituent words, based on the configuration provided in `casetype`.
181
+ *
182
+ * this function performs the inverse operation of {@link wordsToToken}, provided that you use the same `casetype` config.
183
+ *
184
+ * @example
185
+ * ```ts
186
+ * import { assertEquals as eq } from "jsr:@std/assert"
187
+ *
188
+ * const
189
+ * snakeCase: NamingCaseTuple = [-1, -1, -1, "_"],
190
+ * kebabCase: NamingCaseTuple = [-1, -1, -1, "-"],
191
+ * camelCase: NamingCaseTuple = [-1, 1, -1, ""],
192
+ * pascalCase: NamingCaseTuple = [1, 1, -1, ""],
193
+ * screamingSnakeCase: NamingCaseTuple = [1, 1, 1, "_"],
194
+ * screamingKebabCase: NamingCaseTuple = [1, 1, 1, "-"]
195
+ *
196
+ * // the expected list of words that our tokens should breakdown into
197
+ * const words = ["convert", "windows", "path", "to", "unix"]
198
+ *
199
+ * eq(tokenToWords(snakeCase, "convert_windows_path_to_unix"), words)
200
+ * eq(tokenToWords(kebabCase, "convert-windows-path-to-unix"), words)
201
+ * eq(tokenToWords(camelCase, "convertWindowsPathToUnix"), words)
202
+ * eq(tokenToWords(pascalCase, "ConvertWindowsPathToUnix"), words)
203
+ * eq(tokenToWords(screamingSnakeCase, "CONVERT_WINDOWS_PATH_TO_UNIX"), words)
204
+ * eq(tokenToWords(screamingKebabCase, "CONVERT-WINDOWS-PATH-TO-UNIX"), words)
205
+ * ```
206
+ */
207
+ export const tokenToWords = (casetype, token) => {
208
+ const [, word_first_letter_upper, , delimiter = "", prefix = "", suffix = ""] = casetype;
209
+ token = token.slice(prefix.length, -suffix.length || undefined);
210
+ let words;
211
+ if (delimiter === "") {
212
+ // we must now rely on change-in-character-capitlaization to identify indexes of where to split
213
+ const idxs = [0];
214
+ let i = 0;
215
+ while (i !== undefined) {
216
+ i = findNextUpperOrLowerCase(token, word_first_letter_upper, i + 1);
217
+ idxs.push(i);
218
+ }
219
+ words = sliceContinuous(token, idxs);
220
+ }
221
+ else
222
+ words = token.split(delimiter);
223
+ return words.map(word => string_toLowerCase(word));
224
+ };
225
+ /** converts a string token from one case type to another,
226
+ * by performing a composition operation of {@link tokenToWords} and {@link wordsToToken}.
227
+ *
228
+ * @example
229
+ * ```ts
230
+ * import { assertEquals as eq } from "jsr:@std/assert"
231
+ *
232
+ * const
233
+ * snakeCase: NamingCaseTuple = [-1, -1, -1, "_"],
234
+ * kebabCase: NamingCaseTuple = [-1, -1, -1, "-"],
235
+ * camelCase: NamingCaseTuple = [-1, 1, -1, ""],
236
+ * pascalCase: NamingCaseTuple = [1, 1, -1, ""],
237
+ * screamingSnakeCase: NamingCaseTuple = [1, 1, 1, "_"],
238
+ * screamingKebabCase: NamingCaseTuple = [1, 1, 1, "-"]
239
+ *
240
+ * eq(convertCase(
241
+ * snakeCase, screamingSnakeCase,
242
+ * "convert_windows_path_to_unix",
243
+ * ), "CONVERT_WINDOWS_PATH_TO_UNIX")
244
+ *
245
+ * eq(convertCase(
246
+ * kebabCase, camelCase,
247
+ * "convert-windows-path-to-unix",
248
+ * ), "convertWindowsPathToUnix")
249
+ *
250
+ * eq(convertCase(
251
+ * camelCase, kebabCase,
252
+ * "convertWindowsPathToUnix",
253
+ * ), "convert-windows-path-to-unix")
254
+ *
255
+ * eq(convertCase(
256
+ * kebabCase, kebabCase,
257
+ * "convert-windows-path-to-unix",
258
+ * ), "convert-windows-path-to-unix")
259
+ *
260
+ * eq(convertCase(
261
+ * screamingKebabCase, pascalCase,
262
+ * "CONVERT-WINDOWS-PATH-TO-UNIX",
263
+ * ), "ConvertWindowsPathToUnix")
264
+ * ```
265
+ */
266
+ export const convertCase = (from_casetype, to_casetype, token) => (wordsToToken(to_casetype, tokenToWords(from_casetype, token)));
267
+ /** generate a specific case converter. convenient for continued use.
268
+ *
269
+ * see {@link kebabToCamel} and {@link camelToKebab} as examples that are generated via this function.
270
+ */
271
+ export const convertCase_Factory = (from_casetype, to_casetype) => {
272
+ const bound_words_to_token = wordsToToken.bind(undefined, to_casetype), bound_token_to_words = tokenToWords.bind(undefined, from_casetype);
273
+ return (token) => bound_words_to_token(bound_token_to_words(token));
274
+ };
275
+ /** the token name casing configuration for a "snake_case". */
276
+ export const snakeCase = [-1, -1, -1, "_"];
277
+ /** the token name casing configuration for a "kebab-case". */
278
+ export const kebabCase = [-1, -1, -1, "-"];
279
+ /** the token name casing configuration for a "camelCase". */
280
+ export const camelCase = [-1, 1, -1, ""];
281
+ /** the token name casing configuration for a "PascalCase". */
282
+ export const pascalCase = [1, 1, -1, ""];
283
+ /** the token name casing configuration for a "SCREAMING_SNAKE_CASE". */
284
+ export const screamingSnakeCase = [1, 1, 1, "_"];
285
+ /** the token name casing configuration for a "SCREAMING-SNAKE-CASE". */
286
+ export const screamingKebabCase = [1, 1, 1, "-"];
287
+ /** a function to convert snake case token to a kebab case token. */
288
+ export const snakeToKebab = /*@__PURE__*/ convertCase_Factory(snakeCase, kebabCase);
289
+ /** a function to convert snake case token to a camel case token. */
290
+ export const snakeToCamel = /*@__PURE__*/ convertCase_Factory(snakeCase, camelCase);
291
+ /** a function to convert snake case token to a pascal case token. */
292
+ export const snakeToPascal = /*@__PURE__*/ convertCase_Factory(snakeCase, pascalCase);
293
+ /** a function to convert kebab case token to a snake case token. */
294
+ export const kebabToSnake = /*@__PURE__*/ convertCase_Factory(kebabCase, snakeCase);
295
+ /** a function to convert kebab case token to a camel case token. */
296
+ export const kebabToCamel = /*@__PURE__*/ convertCase_Factory(kebabCase, camelCase);
297
+ /** a function to convert kebab case token to a pascal case token. */
298
+ export const kebabToPascal = /*@__PURE__*/ convertCase_Factory(kebabCase, pascalCase);
299
+ /** a function to convert camel case token to a snake case token. */
300
+ export const camelToSnake = /*@__PURE__*/ convertCase_Factory(camelCase, snakeCase);
301
+ /** a function to convert camel case token to a kebab case token. */
302
+ export const camelToKebab = /*@__PURE__*/ convertCase_Factory(camelCase, kebabCase);
303
+ /** a function to convert camel case token to a pascal case token. */
304
+ export const camelToPascal = /*@__PURE__*/ convertCase_Factory(camelCase, pascalCase);
305
+ /** a function to convert pascal case token to a snake case token. */
306
+ export const PascalToSnake = /*@__PURE__*/ convertCase_Factory(pascalCase, snakeCase);
307
+ /** a function to convert pascal case token to a kebab case token. */
308
+ export const PascalToKebab = /*@__PURE__*/ convertCase_Factory(pascalCase, kebabCase);
309
+ /** a function to convert pascal case token to a camel case token. */
310
+ export const PascalTocamel = /*@__PURE__*/ convertCase_Factory(pascalCase, camelCase);
311
+ /** surround a string with double quotation.
312
+ *
313
+ * someone should nominate this function for 2025 mathematics nobel prize.
314
+ */
315
+ export const quote = (str) => ("\"" + str + "\"");
316
+ /** reversing a string is not natively supported by javascript, and performing it is not so trivial when considering that
317
+ * you can have composite UTF-16 characters (such as emojis and characters with accents).
318
+ *
319
+ * see this excellent solution in stackoverflow for reversing a string: [stackoverflow.com/a/60056845](https://stackoverflow.com/a/60056845).
320
+ * we use the slightly less reliable technique provided by the answer, as it has a better browser support.
321
+ */
322
+ export const reverseString = (input) => {
323
+ return [...input.normalize("NFC")].toReversed().join("");
324
+ };
325
+ /** find the longest common prefix among a list of `inputs`.
326
+ *
327
+ * for efficiency, this function starts off by using the shortest string among `inputs`, then performs a binary search.
328
+ *
329
+ * @example
330
+ * ```ts
331
+ * import { assertEquals as assertEq } from "jsr:@std/assert"
332
+ *
333
+ * assertEq(commonPrefix([
334
+ * "C:/Hello/World/This/Is/An/Example/Bla.cs",
335
+ * "C:/Hello/World/This/Is/Not/An/Example/",
336
+ * "C:/Hello/Earth/Bla/Bla/Bla",
337
+ * ]), "C:/Hello/")
338
+ *
339
+ * assertEq(commonPrefix([
340
+ * "C:/Hello/World/This/Is/An/Example/Bla.cs",
341
+ * "C:/Hello/World/This/is/an/example/bla.cs",
342
+ * "C:/Hello/World/This/Is/Not/An/Example/",
343
+ * ]), "C:/Hello/World/This/")
344
+ *
345
+ * assertEq(commonPrefix([
346
+ * "C:/Hello/World/Users/This/Is/An/Example/Bla.cs",
347
+ * "C:/Hello/World Users/This/Is/An/example/bla.cs",
348
+ * "C:/Hello/World-Users/This/Is/Not/An/Example/",
349
+ * ]), "C:/Hello/World")
350
+ * ```
351
+ */
352
+ export const commonPrefix = (inputs) => {
353
+ const len = inputs.length;
354
+ if (len < 1)
355
+ return "";
356
+ const inputs_lengths = inputs.map((str) => (str.length)), shortest_input_length = math_min(...inputs_lengths), shortest_input = inputs[inputs_lengths.indexOf(shortest_input_length)];
357
+ let left = 0, right = shortest_input_length;
358
+ while (left <= right) {
359
+ const center = ((left + right) / 2) | 0, prefix = shortest_input.substring(0, center);
360
+ if (inputs.every((input) => (input.startsWith(prefix)))) {
361
+ left = center + 1;
362
+ }
363
+ else {
364
+ right = center - 1;
365
+ }
366
+ }
367
+ return shortest_input.substring(0, ((left + right) / 2) | 0);
368
+ };
369
+ /** find the longest common suffix among a list of `inputs`.
370
+ *
371
+ * for efficiency, this function simply reverses the character ordering of each input, and then uses {@link commonPrefix}.
372
+ *
373
+ * @example
374
+ * ```ts
375
+ * import { assertEquals as assertEq } from "jsr:@std/assert"
376
+ *
377
+ * assertEq(commonSuffix([
378
+ * "file:///C:/Hello/World/This/Is/An/Example/Bla.cs",
379
+ * "file:///C:/Hello/Users/This/Is-An/Example/Bla.cs",
380
+ * "file:///C:/Hello/Users/This/Is/YetAnother-An/Example/Bla.cs",
381
+ * "file:///C:/Hello/Earth/This/Is/Not/An/Example/Bla.cs",
382
+ * ]), "An/Example/Bla.cs")
383
+ * ```
384
+ */
385
+ export const commonSuffix = (inputs) => {
386
+ return reverseString(commonPrefix(inputs.map(reverseString)));
387
+ };
388
+ /** this regex contains all characters that need to be escaped in a regex.
389
+ * it is basically defined as `/[.*+?^${}()|[\]\\]/g`.
390
+ */
391
+ export const escapeLiteralCharsRegex = /[.*+?^${}()|[\]\\]/g;
392
+ /** escape a string so that it can be matched exactly in a regex constructor.
393
+ *
394
+ * @example
395
+ * ```ts
396
+ * import { assertEquals as assertEq } from "jsr:@std/assert"
397
+ *
398
+ * const
399
+ * substring = String.raw`(\|[++h.e.\\.o++]|/)`,
400
+ * substring_escaped = escapeLiteralStringForRegex(substring),
401
+ * my_regex = new RegExp(`${substring_escaped}\\(world\\)`),
402
+ * my_string = String.raw`this string consist of (\|[++h.e.\\.o++]|/)(world) positioned somewhere in the middle`
403
+ *
404
+ * assertEq(my_regex.test(my_string), true)
405
+ * ```
406
+ */
407
+ export const escapeLiteralStringForRegex = (str) => (str.replaceAll(escapeLiteralCharsRegex, "\\$&"));
408
+ /** replace the `prefix` of of a given `input` string with the given replace `value`.
409
+ * if a matching prefix is not found, then `undefined` will be returned.
410
+ *
411
+ * @param input the input string to apply the prefix replacement to.
412
+ * @param prefix the prefix string of the input to replace.
413
+ * @param value the optional value to replace the the prefix with. defaults to `""` (empty string).
414
+ * @returns if a matching `prefix` is found in the `input`, then it will be replaced with the given `value`.
415
+ * otherwise, `undefined` will be returned if the `input` does not begin with the `prefix`.
416
+ *
417
+ * @example
418
+ * ```ts
419
+ * import { assertEquals } from "jsr:@std/assert"
420
+ *
421
+ * // aliasing our function for brevity
422
+ * const
423
+ * eq = assertEquals,
424
+ * fn = replacePrefix
425
+ *
426
+ * eq(fn("hello-world/abc-123", "hello-", "goodbye-"), "goodbye-world/abc-123")
427
+ * eq(fn("hello-world/abc-123", "hello-"), "world/abc-123")
428
+ * eq(fn("hello-world/abc-123", "abc"), undefined)
429
+ * eq(fn("hello-world/abc-123", ""), "hello-world/abc-123")
430
+ * eq(fn("hello-world/abc-123", "", "xyz-"), "xyz-hello-world/abc-123")
431
+ * ```
432
+ */
433
+ export const replacePrefix = (input, prefix, value = "") => {
434
+ return input.startsWith(prefix)
435
+ ? value + input.slice(prefix.length)
436
+ : undefined;
437
+ };
438
+ /** replace the `suffix` of of a given `input` string with the given replace `value`.
439
+ * if a matching suffix is not found, then `undefined` will be returned.
440
+ *
441
+ * @param input the input string to apply the suffix replacement to.
442
+ * @param suffix the suffix string of the input to replace.
443
+ * @param value the optional value to replace the the suffix with. defaults to `""` (empty string).
444
+ * @returns if a matching `suffix` is found in the `input`, then it will be replaced with the given `value`.
445
+ * otherwise, `undefined` will be returned if the `input` does not begin with the `suffix`.
446
+ *
447
+ * @example
448
+ * ```ts
449
+ * import { assertEquals } from "jsr:@std/assert"
450
+ *
451
+ * // aliasing our function for brevity
452
+ * const
453
+ * eq = assertEquals,
454
+ * fn = replaceSuffix
455
+ *
456
+ * eq(fn("hello-world/abc-123", "-123", "-xyz"), "hello-world/abc-xyz")
457
+ * eq(fn("hello-world/abc-123", "-123"), "hello-world/abc")
458
+ * eq(fn("hello-world/abc-123", "abc"), undefined)
459
+ * eq(fn("hello-world/abc-123", ""), "hello-world/abc-123")
460
+ * eq(fn("hello-world/abc-123", "", "-xyz"), "hello-world/abc-123-xyz")
461
+ * ```
462
+ */
463
+ export const replaceSuffix = (input, suffix, value = "") => {
464
+ return input.endsWith(suffix)
465
+ ? (suffix === "" ? input : input.slice(0, -suffix.length)) + value
466
+ : undefined;
467
+ };
468
+ const windows_new_line = "\r\n";
469
+ var JSONC_INSIDE;
470
+ (function (JSONC_INSIDE) {
471
+ JSONC_INSIDE[JSONC_INSIDE["NONE"] = 0] = "NONE";
472
+ JSONC_INSIDE[JSONC_INSIDE["STRING"] = 1] = "STRING";
473
+ JSONC_INSIDE[JSONC_INSIDE["INLINE_COMMENT"] = 2] = "INLINE_COMMENT";
474
+ JSONC_INSIDE[JSONC_INSIDE["MULTILINE_COMMENT"] = 3] = "MULTILINE_COMMENT";
475
+ })(JSONC_INSIDE || (JSONC_INSIDE = {}));
476
+ /** remove comments and trailing commas from a "jsonc" (json with comments) string.
477
+ *
478
+ * in a jsonc-string, there three additional features that supersede a regular json-string:
479
+ * - inline comments: anything affer a double forward-slash `//` (that is not part of a string) is a comment, until the end of the line.
480
+ * - multiline comments: anything inside the c-like multiline comment block (`/* ... *\/`) is a comment.
481
+ * - trailing commas: you can add up to one trailing comma (`,`) after the last element of an array, or the last entry of a dictionary.
482
+ *
483
+ * moreover, this function also trims unnecessary whitespaces and newlines outside of string literals.
484
+ *
485
+ * once you have converted your jsonc-string to a json-string, you will probably want to use `JSON.parse` to parse the output.
486
+ *
487
+ * @param jsonc_string - The jsonc string from which comments need to be removed.
488
+ * @returns A string representing the jsonc-equivalent content, without comments and trailing commas.
489
+ *
490
+ * @example
491
+ * ```ts
492
+ * import { assertEquals } from "jsr:@std/assert"
493
+ *
494
+ * const my_jsonc = `
495
+ * {
496
+ * // inline comment
497
+ * "key1": "value1",
498
+ * /* block comment *\/ "key2": 2,
499
+ * /* multiline block comment
500
+ * * hello
501
+ * * world
502
+ * *\/
503
+ * "key3": {
504
+ * "//key4": "value4 //",
505
+ * "jsonInComment": "/* { \\"key\\": \\"value\\" } *\/",
506
+ * "trickyEscapes": "a string with \\\\\\"escaped quotes\\\\\\" and /* fake comment *\/ inside and \\newline",
507
+ * },
508
+ * "array1": [
509
+ * "/* not a comment *\/",
510
+ * "// also not a comment",
511
+ * "has a trailing comma" // trailing comma below \t \t tab characters.
512
+ * , // <-- trailing comma here. and some more \t \t tab characters.
513
+ * ],
514
+ * /* Block comment containing JSON:
515
+ * { "fakeKey": "fakeValue" },
516
+ * *\/
517
+ * "arr//ay2": [
518
+ * true, false, { "1": false, "2": true, },
519
+ * 42,7,
520
+ * // scientific notation
521
+ * 1e10,],
522
+ * }`
523
+ *
524
+ * const expected_value = {
525
+ * key1: "value1",
526
+ * key2: 2,
527
+ * key3: {
528
+ * "//key4": "value4 //",
529
+ * jsonInComment: `/* { "key": "value" } *\/`,
530
+ * trickyEscapes: `a string with \\"escaped quotes\\" and /* fake comment *\/ inside and \newline`,
531
+ * },
532
+ * array1: [
533
+ * "/* not a comment *\/",
534
+ * "// also not a comment",
535
+ * "has a trailing comma",
536
+ * ],
537
+ * "arr//ay2": [ true, false, { "1": false, "2": true }, 42, 7, 10000000000, ]
538
+ * }
539
+ *
540
+ * const
541
+ * my_json = jsoncRemoveComments(my_jsonc),
542
+ * my_parsed_json = JSON.parse(my_json)
543
+ *
544
+ * assertEquals(my_parsed_json, expected_value)
545
+ * ```
546
+ */
547
+ export const jsoncRemoveComments = (jsonc_string) => {
548
+ // we add an additional whitespace character at the start and end to permit a 1-character look-ahead and look-back, without ever going out of bounds.
549
+ jsonc_string = " " + jsonc_string.replaceAll(windows_new_line, "\n") + " ";
550
+ const jsonc_string_length = jsonc_string.length - 1, json_chars = [], json_chars_push = bind_array_push(json_chars), json_chars_pop = bind_array_pop(json_chars);
551
+ let state = JSONC_INSIDE.NONE;
552
+ // string indexing is the fastest way to iterate over the string, character by character,
553
+ // and string concatenation assignment is a little faster than array push, followed by a join at last.
554
+ for (let i = 1; i < jsonc_string_length; i++) {
555
+ const char = jsonc_string[i];
556
+ switch (char) {
557
+ case "/": {
558
+ if (state === JSONC_INSIDE.NONE) {
559
+ const next_char = jsonc_string[i + 1];
560
+ state = (next_char === "/") ? JSONC_INSIDE.INLINE_COMMENT
561
+ : (next_char === "*") ? JSONC_INSIDE.MULTILINE_COMMENT
562
+ : JSONC_INSIDE.NONE;
563
+ if (state !== JSONC_INSIDE.NONE) {
564
+ // skip the look-ahead character `next_char`, since we're now inside a comment.
565
+ i++;
566
+ continue;
567
+ }
568
+ }
569
+ break;
570
+ }
571
+ case "*": {
572
+ if (state === JSONC_INSIDE.MULTILINE_COMMENT) {
573
+ const next_char = jsonc_string[i + 1];
574
+ state = (next_char === "/")
575
+ ? JSONC_INSIDE.NONE
576
+ : state;
577
+ if (state === JSONC_INSIDE.NONE) {
578
+ // skip the look-ahead character `next_char`, if we've existed the multiline comment.
579
+ i++;
580
+ continue;
581
+ }
582
+ }
583
+ break;
584
+ }
585
+ case "\n": {
586
+ state = (state === JSONC_INSIDE.INLINE_COMMENT)
587
+ ? JSONC_INSIDE.NONE
588
+ : state;
589
+ }
590
+ /* falls through */
591
+ case "\t":
592
+ case "\v":
593
+ case " ": {
594
+ if (state === JSONC_INSIDE.NONE) {
595
+ // we don't want to write white spaces and new lines.
596
+ continue;
597
+ }
598
+ break;
599
+ }
600
+ case "\"": {
601
+ state = (state === JSONC_INSIDE.NONE) ? JSONC_INSIDE.STRING
602
+ : (state === JSONC_INSIDE.STRING) ? JSONC_INSIDE.NONE
603
+ : state;
604
+ break;
605
+ }
606
+ case "}":
607
+ case "]": {
608
+ // here we lookback what the previous character was to ensure that any trailing commas are removed that this comma is not a trailing comma.
609
+ if (state === JSONC_INSIDE.NONE) {
610
+ const prev_char = json_chars_pop();
611
+ if (prev_char !== ",") {
612
+ json_chars_push(prev_char);
613
+ }
614
+ }
615
+ break;
616
+ }
617
+ }
618
+ if (state === JSONC_INSIDE.NONE || state === JSONC_INSIDE.STRING) {
619
+ // if this character is a backslash, then forcefully insert the next character.
620
+ json_chars_push(char === "\\"
621
+ ? char + jsonc_string[++i]
622
+ : char);
623
+ }
624
+ }
625
+ return json_chars.join("");
626
+ };