@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.
- package/esm/_dnt.shims.d.ts +2 -0
- package/esm/_dnt.shims.d.ts.map +1 -0
- package/esm/_dnt.shims.js +57 -0
- package/esm/deps/jsr.io/@oazmi/esbuild-types/0.28.0/src/mod.d.ts +598 -0
- package/esm/deps/jsr.io/@oazmi/esbuild-types/0.28.0/src/mod.d.ts.map +1 -0
- package/esm/deps/jsr.io/@oazmi/esbuild-types/0.28.0/src/mod.js +1 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/alias.d.ts +617 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/alias.d.ts.map +1 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/alias.js +671 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/array1d.d.ts +487 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/array1d.d.ts.map +1 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/array1d.js +536 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/array2d.d.ts +266 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/array2d.d.ts.map +1 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/array2d.js +318 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/binder.d.ts +368 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/binder.d.ts.map +1 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/binder.js +380 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/crossenv.d.ts +711 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/crossenv.d.ts.map +1 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/crossenv.js +1173 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/cryptoman.d.ts +171 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/cryptoman.d.ts.map +1 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/cryptoman.js +308 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/deps.d.ts +10 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/deps.d.ts.map +1 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/deps.js +10 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/eightpack.d.ts +168 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/eightpack.d.ts.map +1 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/eightpack.js +236 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/eightpack_varint.d.ts +90 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/eightpack_varint.d.ts.map +1 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/eightpack_varint.js +237 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/numericarray.d.ts +213 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/numericarray.d.ts.map +1 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/numericarray.js +363 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/numericmethods.d.ts +233 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/numericmethods.d.ts.map +1 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/numericmethods.js +256 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/pathman.d.ts +1436 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/pathman.d.ts.map +1 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/pathman.js +1730 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/promiseman.d.ts +647 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/promiseman.d.ts.map +1 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/promiseman.js +762 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/stringman.d.ts +538 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/stringman.d.ts.map +1 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/stringman.js +626 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/struct.d.ts +734 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/struct.d.ts.map +1 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/struct.js +764 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/typedbuffer.d.ts +137 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/typedbuffer.d.ts.map +1 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/typedbuffer.js +234 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/typedefs.d.ts +391 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/typedefs.d.ts.map +1 -0
- package/esm/deps/jsr.io/@oazmi/kitchensink/0.10.0/src/typedefs.js +8 -0
- package/esm/deps.d.ts +56 -0
- package/esm/deps.d.ts.map +1 -0
- package/esm/deps.js +37 -0
- package/esm/esbuild/metafile.d.ts +90 -0
- package/esm/esbuild/metafile.d.ts.map +1 -0
- package/esm/esbuild/metafile.js +275 -0
- package/esm/esbuild/native.d.ts +95 -0
- package/esm/esbuild/native.d.ts.map +1 -0
- package/esm/esbuild/native.js +127 -0
- package/esm/esbuild/outputfile.d.ts +86 -0
- package/esm/esbuild/outputfile.d.ts.map +1 -0
- package/esm/esbuild/outputfile.js +221 -0
- package/esm/esbuild/strongtypes.d.ts +90 -0
- package/esm/esbuild/strongtypes.d.ts.map +1 -0
- package/esm/esbuild/strongtypes.js +8 -0
- package/esm/esbuild/typedefs.d.ts +121 -0
- package/esm/esbuild/typedefs.d.ts.map +1 -0
- package/esm/esbuild/typedefs.js +55 -0
- package/esm/esbuild/weaktypes.d.ts +46 -0
- package/esm/esbuild/weaktypes.d.ts.map +1 -0
- package/esm/esbuild/weaktypes.js +8 -0
- package/esm/funcdefs.d.ts +89 -0
- package/esm/funcdefs.d.ts.map +1 -0
- package/esm/funcdefs.js +145 -0
- package/esm/mod.d.ts +4 -0
- package/esm/mod.d.ts.map +1 -0
- package/esm/mod.js +2 -0
- package/esm/package.json +3 -0
- package/esm/plugins/emissions_driver.d.ts +33 -0
- package/esm/plugins/emissions_driver.d.ts.map +1 -0
- package/esm/plugins/emissions_driver.js +260 -0
- package/esm/plugins/long_build.d.ts +138 -0
- package/esm/plugins/long_build.d.ts.map +1 -0
- package/esm/plugins/long_build.js +288 -0
- package/esm/plugins/native_replica.d.ts +48 -0
- package/esm/plugins/native_replica.d.ts.map +1 -0
- package/esm/plugins/native_replica.js +122 -0
- package/esm/super/build.d.ts +53 -0
- package/esm/super/build.d.ts.map +1 -0
- package/esm/super/build.js +39 -0
- package/esm/super/build_context.d.ts +83 -0
- package/esm/super/build_context.d.ts.map +1 -0
- package/esm/super/build_context.js +124 -0
- package/esm/super/mod.d.ts +12 -0
- package/esm/super/mod.d.ts.map +1 -0
- package/esm/super/mod.js +9 -0
- package/esm/super/plugin.d.ts +23 -0
- package/esm/super/plugin.d.ts.map +1 -0
- package/esm/super/plugin.js +31 -0
- package/esm/super/plugin_build.d.ts +38 -0
- package/esm/super/plugin_build.d.ts.map +1 -0
- package/esm/super/plugin_build.js +198 -0
- package/esm/super/typedefs.d.ts +323 -0
- package/esm/super/typedefs.d.ts.map +1 -0
- package/esm/super/typedefs.js +10 -0
- package/esm/typedefs.d.ts +21 -0
- package/esm/typedefs.d.ts.map +1 -0
- package/esm/typedefs.js +5 -0
- package/license.md +37 -0
- package/package.json +88 -0
- 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
|
+
};
|